mirror of https://github.com/apache/jclouds.git
Merge pull request #338 from andreaturli/development
issue 384: refactor sendScancode
This commit is contained in:
commit
93a5bae746
|
@ -18,31 +18,35 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.virtualbox.functions;
|
package org.jclouds.virtualbox.functions;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import com.google.common.base.Predicate;
|
import static com.google.common.collect.Iterables.transform;
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
import com.google.inject.Inject;
|
import java.net.URI;
|
||||||
import org.jclouds.compute.callables.RunScriptOnNode.Factory;
|
import java.util.List;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.scriptbuilder.domain.Statements;
|
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
import org.jclouds.virtualbox.domain.ExecutionType;
|
import org.jclouds.virtualbox.domain.ExecutionType;
|
||||||
import org.jclouds.virtualbox.domain.IMachineSpec;
|
import org.jclouds.virtualbox.domain.IMachineSpec;
|
||||||
import org.jclouds.virtualbox.domain.IsoSpec;
|
import org.jclouds.virtualbox.domain.IsoSpec;
|
||||||
import org.jclouds.virtualbox.domain.VmSpec;
|
import org.jclouds.virtualbox.domain.VmSpec;
|
||||||
import org.jclouds.virtualbox.settings.KeyboardScancodes;
|
|
||||||
import org.jclouds.virtualbox.util.MachineUtils;
|
import org.jclouds.virtualbox.util.MachineUtils;
|
||||||
import org.virtualbox_4_1.*;
|
import org.virtualbox_4_1.IMachine;
|
||||||
|
import org.virtualbox_4_1.IProgress;
|
||||||
|
import org.virtualbox_4_1.ISession;
|
||||||
|
import org.virtualbox_4_1.LockType;
|
||||||
|
import org.virtualbox_4_1.VirtualBoxManager;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import com.google.common.base.Function;
|
||||||
import javax.inject.Named;
|
import com.google.common.base.Predicate;
|
||||||
import javax.inject.Singleton;
|
import com.google.common.base.Splitter;
|
||||||
import java.net.URI;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.inject.Inject;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
|
||||||
import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class CreateAndInstallVm implements Function<IMachineSpec, IMachine> {
|
public class CreateAndInstallVm implements Function<IMachineSpec, IMachine> {
|
||||||
|
@ -56,28 +60,19 @@ public class CreateAndInstallVm implements Function<IMachineSpec, IMachine> {
|
||||||
|
|
||||||
private final Predicate<SshClient> sshResponds;
|
private final Predicate<SshClient> sshResponds;
|
||||||
private final ExecutionType executionType;
|
private final ExecutionType executionType;
|
||||||
|
|
||||||
private final Factory scriptRunner;
|
|
||||||
private final Supplier<NodeMetadata> host;
|
|
||||||
|
|
||||||
private final Function<IMachine, SshClient> sshClientForIMachine;
|
private final Function<IMachine, SshClient> sshClientForIMachine;
|
||||||
|
|
||||||
private final MachineUtils machineUtils;
|
private final MachineUtils machineUtils;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CreateAndInstallVm(
|
public CreateAndInstallVm(Supplier<VirtualBoxManager> manager,
|
||||||
Supplier<VirtualBoxManager> manager,
|
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
|
||||||
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
|
Predicate<SshClient> sshResponds, Function<IMachine, SshClient> sshClientForIMachine,
|
||||||
Predicate<SshClient> sshResponds,
|
ExecutionType executionType, MachineUtils machineUtils) {
|
||||||
Function<IMachine, SshClient> sshClientForIMachine,
|
|
||||||
Supplier<NodeMetadata> host, Factory scriptRunner,
|
|
||||||
ExecutionType executionType, MachineUtils machineUtils) {
|
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists;
|
this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists;
|
||||||
this.sshResponds = sshResponds;
|
this.sshResponds = sshResponds;
|
||||||
this.sshClientForIMachine = sshClientForIMachine;
|
this.sshClientForIMachine = sshClientForIMachine;
|
||||||
this.scriptRunner = scriptRunner;
|
|
||||||
this.host = host;
|
|
||||||
this.executionType = executionType;
|
this.executionType = executionType;
|
||||||
this.machineUtils = machineUtils;
|
this.machineUtils = machineUtils;
|
||||||
}
|
}
|
||||||
|
@ -90,99 +85,48 @@ public class CreateAndInstallVm implements Function<IMachineSpec, IMachine> {
|
||||||
|
|
||||||
String vmName = vmSpec.getVmName();
|
String vmName = vmSpec.getVmName();
|
||||||
|
|
||||||
final IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists
|
final IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(machineSpec);
|
||||||
.apply(machineSpec);
|
|
||||||
|
|
||||||
// Launch machine and wait for it to come online
|
// Launch machine and wait for it to come online
|
||||||
ensureMachineIsLaunched(vmName);
|
ensureMachineIsLaunched(vmName);
|
||||||
|
|
||||||
URI uri = isoSpec.getPreConfigurationUri().get();
|
URI uri = isoSpec.getPreConfigurationUri().get();
|
||||||
String installationKeySequence = isoSpec.getInstallationKeySequence()
|
String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL",
|
||||||
.replace("PRECONFIGURATION_URL", uri.toASCIIString());
|
uri.toASCIIString());
|
||||||
sendKeyboardSequence(installationKeySequence, vmName);
|
|
||||||
|
|
||||||
|
configureOsInstallationWithKeyboardSequence(vmName, installationKeySequence);
|
||||||
SshClient client = sshClientForIMachine.apply(vm);
|
SshClient client = sshClientForIMachine.apply(vm);
|
||||||
|
|
||||||
logger.debug(">> awaiting installation to finish node(%s)", vmName);
|
logger.debug(">> awaiting installation to finish node(%s)", vmName);
|
||||||
|
|
||||||
checkState(sshResponds.apply(client),
|
checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", vmName);
|
||||||
"timed out waiting for guest %s to be accessible via ssh", vmName);
|
|
||||||
|
|
||||||
logger.debug("<< installation of image complete. Powering down node(%s)",
|
logger.debug("<< installation of image complete. Powering down node(%s)", vmName);
|
||||||
vmName);
|
|
||||||
ensureMachineHasPowerDown(vmName);
|
ensureMachineHasPowerDown(vmName);
|
||||||
return vm;
|
return vm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void configureOsInstallationWithKeyboardSequence(String vmName, String installationKeySequence) {
|
||||||
|
Iterable<List<Integer>> scancodelist =
|
||||||
|
transform(Splitter.on(" ").split(installationKeySequence), new StringToKeyCode());
|
||||||
|
|
||||||
|
for (List<Integer> scancodes : scancodelist) {
|
||||||
|
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new SendScancode(scancodes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ensureMachineHasPowerDown(String vmName) {
|
private void ensureMachineHasPowerDown(String vmName) {
|
||||||
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared,
|
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
|
||||||
new Function<ISession, Void>() {
|
@Override
|
||||||
@Override
|
public Void apply(ISession session) {
|
||||||
public Void apply(ISession session) {
|
IProgress powerDownProgress = session.getConsole().powerDown();
|
||||||
IProgress powerDownProgress = session.getConsole()
|
powerDownProgress.waitForCompletion(-1);
|
||||||
.powerDown();
|
return null;
|
||||||
powerDownProgress.waitForCompletion(-1);
|
}
|
||||||
return null;
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureMachineIsLaunched(String vmName) {
|
private void ensureMachineIsLaunched(String vmName) {
|
||||||
machineUtils.applyForMachine(vmName,
|
machineUtils.applyForMachine(vmName, new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType, ""));
|
||||||
new LaunchMachineIfNotAlreadyRunning(manager.get(), executionType,
|
|
||||||
""));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendKeyboardSequence(String keyboardSequence, String vmName) {
|
}
|
||||||
String[] splitSequence = keyboardSequence.split(" ");
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (String line : splitSequence) {
|
|
||||||
String converted = stringToKeycode(line);
|
|
||||||
for (String word : converted.split(" ")) {
|
|
||||||
sb.append("VBoxManage controlvm ").append(vmName)
|
|
||||||
.append(" keyboardputscancode ").append(word).append("; ");
|
|
||||||
runScriptIfWordEndsWith(sb, word, "<Enter>");
|
|
||||||
runScriptIfWordEndsWith(sb, word, "<Return>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runScriptIfWordEndsWith(StringBuilder sb, String word,
|
|
||||||
String key) {
|
|
||||||
if (word.endsWith(KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP.get(key))) {
|
|
||||||
scriptRunner
|
|
||||||
.create(host.get(), Statements.exec(sb.toString()),
|
|
||||||
runAsRoot(false).wrapInInitScript(false)).init().call();
|
|
||||||
sb.delete(0, sb.length() - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String stringToKeycode(String s) {
|
|
||||||
StringBuilder keycodes = new StringBuilder();
|
|
||||||
if (s.startsWith("<")) {
|
|
||||||
String[] specials = s.split("<");
|
|
||||||
for (int i = 1; i < specials.length; i++) {
|
|
||||||
keycodes.append(
|
|
||||||
KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP.get("<"
|
|
||||||
+ specials[i])).append(" ");
|
|
||||||
}
|
|
||||||
return keycodes.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
while (i < s.length()) {
|
|
||||||
String digit = s.substring(i, i + 1);
|
|
||||||
String hex = KeyboardScancodes.NORMAL_KEYBOARD_BUTTON_MAP.get(digit);
|
|
||||||
keycodes.append(hex).append(" ");
|
|
||||||
if (i != 0 && i % 14 == 0)
|
|
||||||
keycodes.append(" ");
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
keycodes.append(
|
|
||||||
KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP.get("<Spacebar>"))
|
|
||||||
.append(" ");
|
|
||||||
|
|
||||||
return keycodes.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.virtualbox.functions;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.virtualbox_4_1.ISession;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
class SendScancode implements Function<ISession, Void> {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private static final int MAX_SIZE = 30;
|
||||||
|
private final List<Integer> scancodes;
|
||||||
|
|
||||||
|
public SendScancode(List<Integer> scancodes) {
|
||||||
|
this.scancodes = scancodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void apply(ISession iSession) {
|
||||||
|
for (List<Integer> maxOrLess : Lists.partition(scancodes, MAX_SIZE)) {
|
||||||
|
long codeStores = iSession.getConsole().getKeyboard().putScancodes(maxOrLess);
|
||||||
|
logger.debug("List of scancodes sent: ", maxOrLess);
|
||||||
|
assert (codeStores == maxOrLess.size());
|
||||||
|
// TODO @Adrian if maxOrLess contains SPECIAL CHAR sleep should be higher than NORMAL CHAR (300 ms - 50 ms)
|
||||||
|
// if (Iterables.any(maxOrLess, Predicates.in(SPECIAL_KEYBOARD_BUTTON_MAP_LIST.values()))) {
|
||||||
|
// try {
|
||||||
|
// Thread.sleep(300);
|
||||||
|
// } catch (InterruptedException e) {
|
||||||
|
// logger.debug("There was a problem in sleeping this thread", e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// TODO without extra check the extra time needed is more or less 250 ms
|
||||||
|
try {
|
||||||
|
Thread.sleep(250);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.debug("There was a problem in sleeping this thread", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.virtualbox.functions;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jclouds.virtualbox.settings.KeyboardScancodes;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
|
||||||
|
public class StringToKeyCode implements Function<String, List<Integer>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Integer> apply(String subsequence) {
|
||||||
|
return stringToKeycode(subsequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> stringToKeycode(String s) {
|
||||||
|
if (containsSpecialCharacter(s)) {
|
||||||
|
return transforSpecialCharIntoKeycodes(s);
|
||||||
|
} else {
|
||||||
|
return transformStandardCharacterIntoKeycodes(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> transformStandardCharacterIntoKeycodes(String s) {
|
||||||
|
List<Integer> values = new ArrayList<Integer>();
|
||||||
|
for (String digit : Splitter.fixedLength(1).split(s)) {
|
||||||
|
List<Integer> hex = KeyboardScancodes.NORMAL_KEYBOARD_BUTTON_MAP_LIST.get(digit);
|
||||||
|
if (hex != null)
|
||||||
|
values.addAll(hex);
|
||||||
|
}
|
||||||
|
values.addAll(KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP_LIST.get("<Spacebar>"));
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> transforSpecialCharIntoKeycodes(String s) {
|
||||||
|
List<Integer> values = new ArrayList<Integer>();
|
||||||
|
for (String special : s.split("<")) {
|
||||||
|
List<Integer> value = KeyboardScancodes.SPECIAL_KEYBOARD_BUTTON_MAP_LIST.get("<" + special);
|
||||||
|
if (value != null)
|
||||||
|
values.addAll(value);
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsSpecialCharacter(String s) {
|
||||||
|
return s.startsWith("<");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,145 +19,174 @@
|
||||||
|
|
||||||
package org.jclouds.virtualbox.settings;
|
package org.jclouds.virtualbox.settings;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class KeyboardScancodes {
|
public class KeyboardScancodes {
|
||||||
|
|
||||||
// http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
|
// http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
|
||||||
|
public static final Map<String, List<Integer>> SPECIAL_KEYBOARD_BUTTON_MAP_LIST = createSpecialCodeMap();
|
||||||
|
public static final Map<String, List<Integer>> NORMAL_KEYBOARD_BUTTON_MAP_LIST = createNormalCodeMap();
|
||||||
|
|
||||||
public static final Map<String, String> NORMAL_KEYBOARD_BUTTON_MAP = createMap();
|
public static CharToIntegersMapBuilder builder() {
|
||||||
public static final Map<String, String> SPECIAL_KEYBOARD_BUTTON_MAP = createSpecialMap();
|
return new CharToIntegersMapBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, List<Integer>> createNormalCodeMap() {
|
||||||
|
Map<String, List<Integer>> alphaToHex = KeyboardScancodes.builder()
|
||||||
|
.put("1", 0x02, 0x82)
|
||||||
|
.put("2", 0x03, 0x83)
|
||||||
|
.put("3", 0x04, 0x84)
|
||||||
|
.put("4", 0x05, 0x85)
|
||||||
|
.put("5", 0x06, 0x86)
|
||||||
|
.put("6", 0x07, 0x87)
|
||||||
|
.put("7", 0x08, 0x88)
|
||||||
|
.put("8", 0x09, 0x89)
|
||||||
|
.put("9", 0x0a, 0x8a)
|
||||||
|
.put("0", 0x0b, 0x8b)
|
||||||
|
|
||||||
private static Map<String, String> createMap() {
|
.put("-", 0x0c, 0x8c)
|
||||||
Map<String, String> alphaToHex = new HashMap<String, String>();
|
.put("=", 0x0d, 0x8d)
|
||||||
alphaToHex.put("1", "02 82");
|
.put("Tab", 0x0f, 0x8f)
|
||||||
alphaToHex.put("2", "03 83");
|
.put("q", 0x10, 0x90)
|
||||||
alphaToHex.put("3", "04 84");
|
.put("w", 0x11, 0x91)
|
||||||
alphaToHex.put("4", "05 85");
|
.put("e", 0x12, 0x92)
|
||||||
alphaToHex.put("5", "06 86");
|
.put("r", 0x13, 0x93)
|
||||||
alphaToHex.put("6", "07 87");
|
.put("t", 0x14, 0x94)
|
||||||
alphaToHex.put("7", "08 88");
|
.put("y", 0x15, 0x95)
|
||||||
alphaToHex.put("8", "09 89");
|
.put("u", 0x16, 0x96)
|
||||||
alphaToHex.put("9", "0a 8a");
|
.put("i", 0x17, 0x97)
|
||||||
alphaToHex.put("0", "0b 8b");
|
.put("o", 0x18, 0x98)
|
||||||
alphaToHex.put("-", "0c 8c");
|
.put("p", 0x19, 0x99)
|
||||||
alphaToHex.put("=", "0d 8d");
|
|
||||||
alphaToHex.put("Tab", "0f 8f");
|
|
||||||
alphaToHex.put("q", "10 90");
|
|
||||||
alphaToHex.put("w", "11 91");
|
|
||||||
alphaToHex.put("e", "12 92");
|
|
||||||
alphaToHex.put("r", "13 93");
|
|
||||||
alphaToHex.put("t", "14 94");
|
|
||||||
alphaToHex.put("y", "15 95");
|
|
||||||
alphaToHex.put("u", "16 96");
|
|
||||||
alphaToHex.put("i", "17 97");
|
|
||||||
alphaToHex.put("o", "18 98");
|
|
||||||
alphaToHex.put("p", "19 99");
|
|
||||||
|
|
||||||
alphaToHex.put("Q", "2a 10 aa");
|
.put("Q", 0x2a, 0x10, 0xaa)
|
||||||
alphaToHex.put("W", "2a 11 aa");
|
.put("W", 0x2a, 0x11, 0xaa)
|
||||||
alphaToHex.put("E", "2a 12 aa");
|
.put("E", 0x2a, 0x12, 0xaa)
|
||||||
alphaToHex.put("R", "2a 13 aa");
|
.put("R", 0x2a, 0x13, 0xaa)
|
||||||
alphaToHex.put("T", "2a 14 aa");
|
.put("T", 0x2a, 0x14, 0xaa)
|
||||||
alphaToHex.put("Y", "2a 15 aa");
|
.put("Y", 0x2a, 0x15, 0xaa)
|
||||||
alphaToHex.put("U", "2a 16 aa");
|
.put("U", 0x2a, 0x16, 0xaa)
|
||||||
alphaToHex.put("I", "2a 17 aa");
|
.put("I", 0x2a, 0x17, 0xaa)
|
||||||
alphaToHex.put("O", "2a 18 aa");
|
.put("O", 0x2a, 0x18, 0xaa)
|
||||||
alphaToHex.put("P", "2a 19 aa");
|
.put("P", 0x2a, 0x19, 0xaa)
|
||||||
|
|
||||||
alphaToHex.put("a", "1e 9e");
|
.put("a", 0x1e, 0x9e)
|
||||||
alphaToHex.put("s", "1f 9f");
|
.put("s", 0x1f, 0x9f)
|
||||||
alphaToHex.put("d", "20 a0");
|
.put("d", 0x20, 0xa0)
|
||||||
alphaToHex.put("f", "21 a1");
|
.put("f", 0x21, 0xa1)
|
||||||
alphaToHex.put("g", "22 a2");
|
.put("g", 0x22, 0xa2)
|
||||||
alphaToHex.put("h", "23 a3");
|
.put("h", 0x23, 0xa3)
|
||||||
alphaToHex.put("j", "24 a4");
|
.put("j", 0x24, 0xa4)
|
||||||
alphaToHex.put("k", "25 a5");
|
.put("k", 0x25, 0xa5)
|
||||||
alphaToHex.put("l", "26 a6");
|
.put("l", 0x26, 0xa6)
|
||||||
|
|
||||||
alphaToHex.put("A", "2a 1e aa 9e");
|
.put("A", 0x2a, 0x1e, 0xaa, 0x9e)
|
||||||
alphaToHex.put("S", "2a 1f aa 9f");
|
.put("S", 0x2a, 0x1f, 0xaa, 0x9f)
|
||||||
alphaToHex.put("D", "2a 20 aa a0");
|
.put("D", 0x2a, 0x20, 0xaa, 0xa0)
|
||||||
alphaToHex.put("F", "2a 21 aa a1");
|
.put("F", 0x2a, 0x21, 0xaa, 0xa1)
|
||||||
alphaToHex.put("G", "2a 22 aa a2");
|
.put("G", 0x2a, 0x22, 0xaa, 0xa2)
|
||||||
alphaToHex.put("H", "2a 23 aa a3");
|
.put("H", 0x2a, 0x23, 0xaa, 0xa3)
|
||||||
alphaToHex.put("J", "2a 24 aa a4");
|
.put("J", 0x2a, 0x24, 0xaa, 0xa4)
|
||||||
alphaToHex.put("K", "2a 25 aa a5");
|
.put("K", 0x2a, 0x25, 0xaa, 0xa5)
|
||||||
alphaToHex.put("L", "2a 26 aa a6");
|
.put("L", 0x2a, 0x26, 0xaa, 0xa6)
|
||||||
|
|
||||||
alphaToHex.put(");", "27 a7");
|
.put(") ", 0x27, 0xa7)
|
||||||
alphaToHex.put("\"", "2a 28 aa a8");
|
.put("\"", 0x2a, 0x28, 0xaa, 0xa8)
|
||||||
alphaToHex.put("\"", "28 a8");
|
.put("\"", 0x28, 0xa8)
|
||||||
alphaToHex.put("\\", "2b ab");
|
.put("\\", 0x2b, 0xab)
|
||||||
alphaToHex.put("|", "2a 2b aa 8b");
|
.put("|", 0x2a, 0x2b, 0xaa, 0x8b)
|
||||||
alphaToHex.put("[", "1a 9a");
|
.put("[", 0x1a, 0x9a)
|
||||||
alphaToHex.put("", "1b 9b");
|
.put("", 0x1b, 0x9b)
|
||||||
alphaToHex.put("<", "2a 33 aa b3");
|
.put("<", 0x2a, 0x33, 0xaa, 0xb3)
|
||||||
alphaToHex.put(">", "2a 34 aa b4");
|
.put(">", 0x2a, 0x34, 0xaa, 0xb4)
|
||||||
alphaToHex.put("$", "2a 05 aa 85");
|
.put("$", 0x2a, 0x05, 0xaa, 0x85)
|
||||||
alphaToHex.put("+", "2a 0d aa 8d");
|
.put("+", 0x2a, 0x0d, 0xaa, 0x8d)
|
||||||
|
|
||||||
|
.put("z", 0x2c, 0xac)
|
||||||
|
.put("x", 0x2d, 0xad)
|
||||||
|
.put("c", 0x2e, 0xae)
|
||||||
|
.put("v", 0x2f, 0xaf)
|
||||||
|
.put("b", 0x30, 0xb0)
|
||||||
|
.put("n", 0x31, 0xb1)
|
||||||
|
.put("m", 0x32, 0xb2)
|
||||||
|
.put("Z", 0x2a, 0x2c, 0xaa, 0xac)
|
||||||
|
.put("X", 0x2a, 0x2d, 0xaa, 0xad)
|
||||||
|
.put("C", 0x2a, 0x2e, 0xaa, 0xae)
|
||||||
|
.put("V", 0x2a, 0x2f, 0xaa, 0xaf)
|
||||||
|
.put("B", 0x2a, 0x30, 0xaa, 0xb0)
|
||||||
|
.put("N", 0x2a, 0x31, 0xaa, 0xb1)
|
||||||
|
.put("M", 0x2a, 0x32, 0xaa, 0xb2)
|
||||||
|
|
||||||
alphaToHex.put("z", "2c ac");
|
.put(",", 0x33, 0xb3)
|
||||||
alphaToHex.put("x", "2d ad");
|
.put(".", 0x34, 0xb4)
|
||||||
alphaToHex.put("c", "2e ae");
|
.put("/", 0x35, 0xb5)
|
||||||
alphaToHex.put("v", "2f af");
|
.put(":", 0x2a, 0x27, 0xaa, 0xa7)
|
||||||
alphaToHex.put("b", "30 b0");
|
.put("%", 0x2a, 0x06, 0xaa, 0x86)
|
||||||
alphaToHex.put("n", "31 b1");
|
.put("_", 0x2a, 0x0c, 0xaa, 0x8c)
|
||||||
alphaToHex.put("m", "32 b2");
|
.put("&", 0x2a, 0x08, 0xaa, 0x88)
|
||||||
alphaToHex.put("Z", "2a 2c aa ac");
|
.put("(", 0x2a, 0x0a, 0xaa, 0x8a)
|
||||||
alphaToHex.put("X", "2a 2d aa ad");
|
.put(")", 0x2a, 0x0b, 0xaa, 0x8b)
|
||||||
alphaToHex.put("C", "2a 2e aa ae");
|
|
||||||
alphaToHex.put("V", "2a 2f aa af");
|
.build();
|
||||||
alphaToHex.put("B", "2a 30 aa b0");
|
|
||||||
alphaToHex.put("N", "2a 31 aa b1");
|
|
||||||
alphaToHex.put("M", "2a 32 aa b2");
|
|
||||||
|
|
||||||
alphaToHex.put(",", "33 b3");
|
|
||||||
alphaToHex.put(".", "34 b4");
|
|
||||||
alphaToHex.put("/", "35 b5");
|
|
||||||
alphaToHex.put(":", "2a 27 aa a7");
|
|
||||||
alphaToHex.put("%", "2a 06 aa 86");
|
|
||||||
alphaToHex.put("_", "2a 0c aa 8c");
|
|
||||||
alphaToHex.put("&", "2a 08 aa 88");
|
|
||||||
alphaToHex.put("(", "2a 0a aa 8a");
|
|
||||||
alphaToHex.put(")", "2a 0b aa 8b");
|
|
||||||
return Collections.unmodifiableMap(alphaToHex);
|
return Collections.unmodifiableMap(alphaToHex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, String> createSpecialMap() {
|
private static Map<String, List<Integer>> createSpecialCodeMap() {
|
||||||
Map<String, String> special = new HashMap<String, String>();
|
Map<String, List<Integer>> special = KeyboardScancodes
|
||||||
special.put("<Enter>", "1c 9c");
|
.builder()
|
||||||
special.put("<Backspace>", "0e 8e");
|
.put("<Enter>", 0x1c, 0x9c)
|
||||||
special.put("<Spacebar>", "39 b9");
|
.put("<Backspace>", 0x0e, 0x8e)
|
||||||
special.put("<Return>", "1c 9c");
|
.put("<Spacebar>", 0x39, 0xb9)
|
||||||
special.put("<Esc>", "01 81");
|
.put("<Return>", 0x1c, 0x9c)
|
||||||
special.put("<Tab>", "0f 8f");
|
.put("<Esc>", 0x01, 0x81)
|
||||||
special.put("<KillX>", "1d 38 0e");
|
.put("<Tab>", 0x0f, 0x8f)
|
||||||
special.put("<Wait>", "wait");
|
.put("<KillX>", 0x1d, 0x38, 0x0e)
|
||||||
|
|
||||||
special.put("<Up>", "48 c8");
|
.put("<Up>", 0x48, 0xc8)
|
||||||
special.put("<Down>", "50 d0");
|
.put("<Down>", 0x50, 0xd0)
|
||||||
special.put("<PageUp>", "49 c9");
|
.put("<PageUp>", 0x49, 0xc9)
|
||||||
special.put("<PageDown>", "51 d1");
|
.put("<PageDown>", 0x51, 0xd1)
|
||||||
special.put("<End>", "4f cf");
|
.put("<End>", 0x4f, 0xcf)
|
||||||
special.put("<Insert>", "52 d2");
|
.put("<Insert>", 0x52, 0xd2)
|
||||||
special.put("<Delete>", "53 d3");
|
.put("<Delete>", 0x53, 0xd3)
|
||||||
special.put("<Left>", "4b cb");
|
.put("<Left>", 0x4b, 0xcb)
|
||||||
special.put("<Right>", "4d cd");
|
.put("<Right>", 0x4d, 0xcd)
|
||||||
special.put("<Home>", "47 c7");
|
.put("<Home>", 0x47, 0xc7)
|
||||||
|
|
||||||
special.put("<F1>", "3b");
|
.put("<F1>", 0x3b)
|
||||||
special.put("<F2>", "3c");
|
.put("<F2>", 0x3c)
|
||||||
special.put("<F3>", "3d");
|
.put("<F3>", 0x3d)
|
||||||
special.put("<F4>", "3e");
|
.put("<F4>", 0x3e)
|
||||||
special.put("<F5>", "3f");
|
.put("<F5>", 0x3f)
|
||||||
special.put("<F6>", "40");
|
.put("<F6>", 0x40)
|
||||||
special.put("<F7>", "41");
|
.put("<F7>", 0x41)
|
||||||
special.put("<F8>", "42");
|
.put("<F8>", 0x42)
|
||||||
special.put("<F9>", "43");
|
.put("<F9>", 0x43)
|
||||||
special.put("<F10>", "44");
|
.put("<F10>", 0x44)
|
||||||
|
.build();
|
||||||
return Collections.unmodifiableMap(special);
|
return Collections.unmodifiableMap(special);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static class CharToIntegersMapBuilder {
|
||||||
|
|
||||||
|
private Map<String, List<Integer>> mappings = new HashMap<String, List<Integer>>();
|
||||||
|
|
||||||
|
public CharToIntegersMapBuilder put(String str, int... mapping) {
|
||||||
|
List<Integer> arrayList = new ArrayList<Integer>();
|
||||||
|
for (int i : mapping) {
|
||||||
|
arrayList.add(i);
|
||||||
|
}
|
||||||
|
mappings.put(str, arrayList);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, List<Integer>> build() {
|
||||||
|
return mappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue