You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by hu...@apache.org on 2014/01/03 11:18:03 UTC
[30/50] [abbrv] CLOUDSTACK-5344: Updated to allow rdp console to
access hyper-v vm virtual framebuffer.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/ObjectID.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/ObjectID.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/ObjectID.java
new file mode 100755
index 0000000..c112cd0
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/ObjectID.java
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.asn1;
+
+import streamer.ByteBuffer;
+
+public class ObjectID extends Tag {
+
+ /**
+ * Raw bytes of encoded OID.
+ */
+ public ByteBuffer value;
+
+ public ObjectID(String name) {
+ super(name);
+ tagType = OBJECT_ID;
+ }
+
+ @Override
+ public boolean isValueSet() {
+ return value != null;
+ }
+
+ @Override
+ public long calculateLengthOfValuePayload() {
+ return value.length;
+ }
+
+ @Override
+ public void writeTagValuePayload(ByteBuffer buf) {
+ buf.writeBytes(value);
+ }
+
+ @Override
+ public void readTagValue(ByteBuffer buf, BerType typeAndFlags) {
+ long length = buf.readBerLength();
+
+ value = buf.readBytes((int)length);
+ }
+
+ @Override
+ public Tag deepCopy(String suffix) {
+ return new ObjectID(name + suffix).copyFrom(this);
+ }
+
+ @Override
+ public Tag copyFrom(Tag tag) {
+ super.copyFrom(tag);
+ value = new ByteBuffer(((ObjectID)tag).value.toByteArray());
+ return this;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/OctetString.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/OctetString.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/OctetString.java
new file mode 100755
index 0000000..3da9c84
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/OctetString.java
@@ -0,0 +1,80 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.asn1;
+
+import streamer.ByteBuffer;
+
+public class OctetString extends Tag {
+
+ public ByteBuffer value = null;
+
+ public OctetString(String name) {
+ super(name);
+ tagType = OCTET_STRING;
+ }
+
+ @Override
+ public void readTagValue(ByteBuffer buf, BerType typeAndFlags) {
+ // Type is already read by parent parser
+
+ long length = buf.readBerLength();
+
+ if (length > buf.length)
+ throw new RuntimeException("BER octet string is too long: " + length + " bytes. Data: " + buf + ".");
+
+ value = buf.readBytes((int)length);
+ }
+
+ @Override
+ public Tag deepCopy(String suffix) {
+ return new OctetString(name + suffix).copyFrom(this);
+ }
+
+ @Override
+ public Tag copyFrom(Tag tag) {
+ super.copyFrom(tag);
+ value = ((OctetString)tag).value;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "= " + value;
+ }
+
+ @Override
+ public long calculateLengthOfValuePayload() {
+ if (value != null)
+ return value.length;
+ else
+ return 0;
+ }
+
+ @Override
+ public void writeTagValuePayload(ByteBuffer buf) {
+ if (value != null)
+ buf.writeBytes(value);
+ else
+ return;
+ }
+
+ @Override
+ public boolean isValueSet() {
+ return value != null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/Sequence.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/Sequence.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/Sequence.java
new file mode 100755
index 0000000..6fa23f8
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/Sequence.java
@@ -0,0 +1,143 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.asn1;
+
+import java.util.Arrays;
+
+import streamer.ByteBuffer;
+
+/**
+ * One or more elements of different types.
+ *
+ * Only prefixed tags are supported.
+ */
+public class Sequence extends Tag {
+
+ public Tag[] tags;
+
+ public Sequence(String name) {
+ super(name);
+ tagType = SEQUENCE;
+ // Sequence and SequenceOf are always encoded as constructed
+ constructed = true;
+ }
+
+ @Override
+ public long calculateLengthOfValuePayload() {
+ long sum = 0;
+
+ for (Tag tag : tags) {
+ long tagLength = tag.calculateFullLength();
+ sum += tagLength;
+ }
+
+ return sum;
+ }
+
+ @Override
+ public void writeTagValuePayload(ByteBuffer buf) {
+ // Write tags
+ for (Tag tag : tags) {
+ tag.writeTag(buf);
+ }
+ }
+
+ @Override
+ public void readTagValue(ByteBuffer buf, BerType typeAndFlags) {
+ // Type is already read by parent parser
+
+ long length = buf.readBerLength();
+ if (length > buf.remainderLength())
+ throw new RuntimeException("BER sequence is too long: " + length + " bytes, while buffer remainder length is " + buf.remainderLength() + ". Data: " + buf
+ + ".");
+
+ ByteBuffer value = buf.readBytes((int)length);
+ parseContent(value);
+
+ value.unref();
+ }
+
+ protected void parseContent(ByteBuffer buf) {
+ for (int i = 0; buf.remainderLength() > 0 && i < tags.length; i++) {
+ BerType typeAndFlags = readBerType(buf);
+
+ // If current tag does not match data in buffer
+ if (!tags[i].isTypeValid(typeAndFlags)) {
+
+ // If tag is required, then throw exception
+ if (!tags[i].optional) {
+ throw new RuntimeException("[" + this + "] ERROR: Required tag is missed: " + tags[i] + ". Unexected tag type: " + typeAndFlags + ". Data: " + buf
+ + ".");
+ } else {
+ // One or more tags are omitted, so skip them
+ for (; i < tags.length; i++) {
+ if (tags[i].isTypeValid(typeAndFlags)) {
+ break;
+ }
+ }
+
+ if (i >= tags.length || !tags[i].isTypeValid(typeAndFlags)) {
+ throw new RuntimeException("[" + this + "] ERROR: No more tags to read or skip, but some data still left in buffer. Unexected tag type: "
+ + typeAndFlags + ". Data: " + buf + ".");
+ }
+ }
+ }
+
+ tags[i].readTag(buf, typeAndFlags);
+ }
+
+ }
+
+ @Override
+ public boolean isTypeValid(BerType typeAndFlags, boolean explicit) {
+ if (explicit)
+ return typeAndFlags.tagClass == tagClass && typeAndFlags.constructed && typeAndFlags.typeOrTagNumber == tagNumber;
+ else
+ // Sequences are always encoded as "constructed" in BER.
+ return typeAndFlags.tagClass == UNIVERSAL_CLASS && typeAndFlags.constructed && typeAndFlags.typeOrTagNumber == SEQUENCE;
+ }
+
+ @Override
+ public Tag deepCopy(String suffix) {
+ return new Sequence(name + suffix).copyFrom(this);
+ }
+
+ @Override
+ public Tag copyFrom(Tag tag) {
+ super.copyFrom(tag);
+
+ if (tags.length != ((Sequence)tag).tags.length)
+ throw new RuntimeException("Incompatible sequences. This: " + this + ", another: " + tag + ".");
+
+ for (int i = 0; i < tags.length; i++) {
+ tags[i].copyFrom(((Sequence)tag).tags[i]);
+ }
+
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "{" + Arrays.toString(tags) + " }";
+ }
+
+ @Override
+ public boolean isValueSet() {
+ return tags != null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/SequenceOf.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/SequenceOf.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/SequenceOf.java
new file mode 100755
index 0000000..f288991
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/SequenceOf.java
@@ -0,0 +1,82 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.asn1;
+
+import java.util.ArrayList;
+
+import streamer.ByteBuffer;
+
+/**
+ * Zero or more elements of same type (array).
+ */
+public class SequenceOf extends Sequence {
+
+ /**
+ * Type of this array.
+ */
+ public Tag type;
+
+ /* Values are stored in tags[] variable inherited from Sequence. */
+
+ public SequenceOf(String name) {
+ super(name);
+ }
+
+ @Override
+ protected void parseContent(ByteBuffer buf) {
+ ArrayList<Tag> tagList = new ArrayList<Tag>();
+
+ for (int index = 0; buf.remainderLength() > 0; index++) {
+ // End of array is marked with two zero bytes (0x00 0x00)
+ if (buf.peekUnsignedByte(0) == 0x00 && buf.peekUnsignedByte(1) == 0x00) {
+ break;
+ }
+
+ Tag tag = type.deepCopy(index);
+
+ tag.readTag(buf);
+ tagList.add(tag);
+ }
+
+ tags = tagList.toArray(new Tag[tagList.size()]);
+ }
+
+ @Override
+ public Tag deepCopy(String suffix) {
+ return new SequenceOf(name + suffix).copyFrom(this);
+ }
+
+ @Override
+ public Tag copyFrom(Tag tag) {
+ super.copyFrom(tag);
+ // We can create shallow copy of type, because it will not be modified
+ type = ((SequenceOf)tag).type;
+
+ tags = new Tag[((Sequence)tag).tags.length];
+ for (int i = 0; i < tags.length; i++) {
+ tags[i] = ((Sequence)tag).tags[i].deepCopy("");
+ }
+
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + ": " + type;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/Tag.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/Tag.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/Tag.java
new file mode 100755
index 0000000..80ece43
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/asn1/Tag.java
@@ -0,0 +1,462 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.asn1;
+
+import streamer.ByteBuffer;
+
+public abstract class Tag implements Asn1Constants {
+
+ /**
+ * Name of this tag, for debugging purposes.
+ */
+ public String name = "";
+
+ /**
+ * Is this tag required or optional, for explicit tags only.
+ */
+ public boolean optional = false;
+
+ /**
+ * Tag primitive (e.g. implicit boolean), or constructed (e.g. sequence, or
+ * explicit boolean).
+ */
+ public boolean constructed = false;
+
+ /**
+ * Class of tag, when it is explicit.
+ */
+ public int tagClass = UNIVERSAL_CLASS;
+
+ /**
+ * Tag number (e.g. index in sequence), when tag is explicit.
+ */
+ public int tagNumber = -1;
+
+ /**
+ * Tag type (e.g. INDER), when tag is implicit.
+ */
+ public int tagType = -1;
+
+ /**
+ * If tag is explicit, then it is prefixed with tag number, so it can be
+ * optional or used in unordered set.
+ */
+ public boolean explicit = false;
+
+ public Tag(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Write tag value, with or without prefix.
+ */
+ public void writeTag(ByteBuffer buf) {
+
+ if (!isMustBeWritten())
+ return;
+
+ // Write prefix, when necessary
+ if (explicit) {
+
+ // Write tag prefix, always constructed
+ BerType berTagPrefix = new BerType(tagClass, true, tagNumber);
+ writeBerType(buf, berTagPrefix);
+
+ // Write tag prefix length
+ buf.writeBerLength(calculateLength());
+
+ // Write tag value
+ writeTagValue(buf);
+ } else {
+ // If implicit, just write tag value
+ writeTagValue(buf);
+ }
+ }
+
+ /**
+ * Must return true when value of this tag is set or tag is required, so it
+ * can be written, false otherwise.
+ */
+ public boolean isMustBeWritten() {
+ return !optional || isValueSet();
+ }
+
+ /**
+ * Must return true when value of this tag is set or tag is required, so it
+ * can be written, false otherwise.
+ */
+ public abstract boolean isValueSet();
+
+ /**
+ * Calculate full length of tag, including type (or prefix, when explicit).
+ */
+ public long calculateFullLength() {
+ if (!isMustBeWritten())
+ return 0;
+
+ // Length of value, including type
+ long length = calculateLength();
+
+ if (!explicit) {
+ // Length of tag type and it length
+ length += calculateLengthOfTagTypeOrTagNumber(tagType) + calculateLengthOfLength(length);
+ } else {
+ // Length of tag prefix and it length
+ length += calculateLengthOfTagTypeOrTagNumber(tagNumber) + calculateLengthOfLength(length);
+ }
+
+ return length;
+ }
+
+ /**
+ * Calculate length of tag, including type when explicit, but without length
+ * of prefix (or type, when implicit).
+ */
+ public long calculateLength() {
+ if (!isMustBeWritten())
+ return 0;
+
+ // Length of value
+ long length = calculateLengthOfValuePayload();
+
+ if (explicit) {
+ // Length of tag type and it length
+ length += calculateLengthOfTagTypeOrTagNumber(tagType) + calculateLengthOfLength(length);
+ }
+
+ return length;
+ }
+
+ /**
+ * Calculate length of BER length.
+ */
+ public int calculateLengthOfLength(long length) {
+ if (length < 0)
+ throw new RuntimeException("[" + this + "] ERROR: Length of tag cannot be less than zero: " + length + ".");
+
+ if (length <= 0x7f)
+ return 1;
+ if (length <= 0xff)
+ return 2;
+ if (length <= 0xffFF)
+ return 3;
+ if (length <= 0xffFFff)
+ return 4;
+ if (length <= 0xffFFffFFL)
+ return 5;
+ if (length <= 0xffFFffFFffL)
+ return 6;
+ if (length <= 0xffFFffFFffFFL)
+ return 7;
+ if (length <= 0xffFFffFFffFFffL)
+ return 8;
+
+ return 9;
+ }
+
+ /**
+ * Calculate length of type to tag number. Values less than 31 are encoded
+ * using lower 5 bits of first byte of tag. Values larger than 31 are
+ * indicated by lower 5 bits set to 1 (0x1F, 31), and next bytes are contain
+ * value in network order, where topmost bit of byte (0x80) indicates is value
+ * contains more bytes, i.e. last byte of sequence has this bit set to 0.
+ */
+ public int calculateLengthOfTagTypeOrTagNumber(int tagType) {
+ if (tagType >= EXTENDED_TYPE)
+ throw new RuntimeException("Multibyte tag types are not supported yet.");
+
+ return 1;
+ }
+
+ /**
+ * Calculate length of payload only, without tag prefix, tag type, and
+ * lengths.
+ *
+ * @return
+ */
+ public abstract long calculateLengthOfValuePayload();
+
+ /**
+ * Write tag value only, without prefix.
+ */
+ public void writeTagValue(ByteBuffer buf) {
+
+ // Write type
+ BerType valueType = new BerType(UNIVERSAL_CLASS, constructed, tagType);
+ writeBerType(buf, valueType);
+
+ // Write length
+ long lengthOfPayload = calculateLengthOfValuePayload();
+ buf.writeBerLength(lengthOfPayload);
+
+ // Store cursor to check is calculated length matches length of actual bytes
+ // written
+ int storedCursor = buf.cursor;
+
+ // Write value
+ writeTagValuePayload(buf);
+
+ // Check is calculated length matches length of actual bytes written, to catch errors early
+ int actualLength = buf.cursor - storedCursor;
+ if (actualLength != lengthOfPayload)
+ throw new RuntimeException("[" + this + "] ERROR: Unexpected length of data in buffer. Expected " + lengthOfPayload + " of bytes of payload, but "
+ + actualLength + " bytes are written instead. Data: " + buf + ".");
+ }
+
+ /**
+ * Write tag value only, without prefix, tag type, and length.
+ */
+ public abstract void writeTagValuePayload(ByteBuffer buf);
+
+ /**
+ * Read required tag, i.e. we are 100% sure that byte buffer will contain this
+ * tag, or exception will be thrown otherwise.
+ *
+ * @param buf
+ * buffer with tag data
+ */
+ public void readTag(ByteBuffer buf) {
+ BerType typeAndFlags = readBerType(buf);
+
+ // * DEBUG */System.out.println("Tag, read " + typeAndFlags);
+
+ if (!isTypeValid(typeAndFlags))
+ throw new RuntimeException("[" + this + "] Unexpected type: " + typeAndFlags + ".");
+
+ readTag(buf, typeAndFlags);
+ }
+
+ /**
+ * Read tag when it type is already read.
+ */
+ public void readTag(ByteBuffer buf, BerType typeAndFlags) {
+
+ if (explicit) {
+ long length = buf.readBerLength();
+
+ if (length > buf.length)
+ throw new RuntimeException("BER value is too long: " + length + " bytes. Data: " + buf + ".");
+
+ ByteBuffer value = buf.readBytes((int)length);
+
+ readTagValue(value);
+
+ value.unref();
+ } else {
+
+ readTagValue(buf, typeAndFlags);
+ }
+ }
+
+ /**
+ * Read tag value only, i.e. it prefix is already read.
+ */
+ public void readTagValue(ByteBuffer value) {
+ BerType typeAndFlags = readBerType(value);
+
+ // * DEBUG */System.out.println("Tag, read value " + typeAndFlags);
+
+ if (!isTypeValid(typeAndFlags, false))
+ throw new RuntimeException("[" + this + "] Unexpected type: " + typeAndFlags + ".");
+
+ readTagValue(value, typeAndFlags);
+ }
+
+ /**
+ * Check are tag type and flags valid for this tag.
+ */
+ public final boolean isTypeValid(BerType typeAndFlags) {
+ return isTypeValid(typeAndFlags, explicit);
+ }
+
+ /**
+ * Check are tag type and flags valid for this tag with or without tag prefix.
+ *
+ * @param explicit
+ * if true, then value is wrapped in tag prefix
+ */
+ public boolean isTypeValid(BerType typeAndFlags, boolean explicit) {
+ if (explicit)
+ return typeAndFlags.tagClass == tagClass && typeAndFlags.constructed && typeAndFlags.typeOrTagNumber == tagNumber;
+ else
+ return typeAndFlags.tagClass == UNIVERSAL_CLASS && !typeAndFlags.constructed && typeAndFlags.typeOrTagNumber == tagType;
+ }
+
+ @Override
+ public String toString() {
+ return " \nTag [name="
+ + name
+
+ + ((constructed) ? ", constructed=" + constructed : "")
+
+ + (", tagType=" + tagTypeOrNumberToString(UNIVERSAL_CLASS, tagType))
+
+ + ((explicit) ? ", explicit=" + explicit + ", optional=" + optional + ", tagClass=" + tagClassToString(tagClass) + ", tagNumber="
+ + tagTypeOrNumberToString(tagClass, tagNumber) : "") + "]";
+ }
+
+ public static final String tagTypeOrNumberToString(int tagClass, int tagTypeOrNumber) {
+ switch (tagClass) {
+ case UNIVERSAL_CLASS:
+ switch (tagTypeOrNumber) {
+ case EOF:
+ return "EOF";
+ case BOOLEAN:
+ return "BOOLEAN";
+ case INTEGER:
+ return "INTEGER";
+ case BIT_STRING:
+ return "BIT_STRING";
+ case OCTET_STRING:
+ return "OCTET_STRING";
+ case NULL:
+ return "NULL";
+ case OBJECT_ID:
+ return "OBJECT_ID";
+ case REAL:
+ return "REAL";
+ case ENUMERATED:
+ return "ENUMERATED";
+ case SEQUENCE:
+ return "SEQUENCE";
+ case SET:
+ return "SET";
+ case NUMERIC_STRING:
+ return "NUMERIC_STRING";
+ case PRINTABLE_STRING:
+ return "PRINTABLE_STRING";
+ case TELETEX_STRING:
+ return "TELETEX_STRING";
+ case VIDEOTEXT_STRING:
+ return "VIDEOTEXT_STRING";
+ case IA5_STRING:
+ return "IA5_STRING";
+ case UTCTIME:
+ return "UTCTIME";
+ case GENERAL_TIME:
+ return "GENERAL_TIME";
+ case GRAPHIC_STRING:
+ return "GRAPHIC_STRING";
+ case VISIBLE_STRING:
+ return "VISIBLE_STRING";
+ case GENERAL_STRING:
+ return "GENERAL_STRING";
+ case EXTENDED_TYPE:
+ return "EXTENDED_TYPE (multibyte)";
+ default:
+ return "UNKNOWN(" + tagTypeOrNumber + ")";
+
+ }
+
+ default:
+ return "[" + tagTypeOrNumber + "]";
+ }
+ }
+
+ public static final String tagClassToString(int tagClass) {
+ switch (tagClass) {
+ case UNIVERSAL_CLASS:
+ return "UNIVERSAL";
+ case CONTEXT_CLASS:
+ return "CONTEXT";
+ case APPLICATION_CLASS:
+ return "APPLICATION";
+ case PRIVATE_CLASS:
+ return "PRIVATE";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ /**
+ * Read BER tag type.
+ */
+ public BerType readBerType(ByteBuffer buf) {
+ int typeAndFlags = buf.readUnsignedByte();
+
+ int tagClass = typeAndFlags & CLASS_MASK;
+
+ boolean constructed = (typeAndFlags & CONSTRUCTED) != 0;
+
+ int type = typeAndFlags & TYPE_MASK;
+ if (type == EXTENDED_TYPE)
+ throw new RuntimeException("Extended tag types/numbers (31+) are not supported yet.");
+
+ return new BerType(tagClass, constructed, type);
+ }
+
+ /**
+ * Write BER tag type.
+ */
+ public void writeBerType(ByteBuffer buf, BerType berType) {
+
+ if (berType.typeOrTagNumber >= EXTENDED_TYPE || berType.typeOrTagNumber < 0)
+ throw new RuntimeException("Extended tag types/numbers (31+) are not supported yet: " + berType + ".");
+
+ if ((berType.tagClass & CLASS_MASK) != berType.tagClass)
+ throw new RuntimeException("Value of BER tag class is out of range: " + berType.tagClass + ". Expected values: " + UNIVERSAL_CLASS + ", " + CONTEXT_CLASS
+ + ", " + APPLICATION_CLASS + ", " + PRIVATE_CLASS + ".");
+
+ int typeAndFlags = berType.tagClass | ((berType.constructed) ? CONSTRUCTED : 0) | berType.typeOrTagNumber;
+
+ buf.writeByte(typeAndFlags);
+ }
+
+ /**
+ * Read tag value only, i.e. it prefix is already read, when value type is
+ * already read.
+ *
+ * @param buf
+ * buffer with tag data
+ */
+ public abstract void readTagValue(ByteBuffer buf, BerType typeAndFlags);
+
+ /**
+ * Create deep copy of this tag with given suffix appended to name.
+ *
+ * @param suffix
+ * suffix to add to tag name, or empty string
+ * @return deep copy of this tag
+ */
+ public abstract Tag deepCopy(String suffix);
+
+ /**
+ * Create deep copy of this tag for array or set.
+ *
+ * @param index
+ * index of element in array or set
+ * @return deep copy of this tag
+ */
+ public Tag deepCopy(int index) {
+ return deepCopy("[" + index + "]");
+ }
+
+ /**
+ * Copy tag values from an other tag, except name.
+ *
+ * @return this
+ */
+ public Tag copyFrom(Tag tag) {
+ constructed = tag.constructed;
+ explicit = tag.explicit;
+ optional = tag.optional;
+ tagClass = tag.tagClass;
+ tagNumber = tag.tagNumber;
+ return this;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/IncrementalOption.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/IncrementalOption.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/IncrementalOption.java
new file mode 100755
index 0000000..eb24d11
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/IncrementalOption.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.opt;
+
+public class IncrementalOption extends Option {
+ int value = 0;
+
+ @Override
+ public int parse(int position, String[] args) {
+ value++;
+ return super.parse(position, args);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/IntOption.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/IntOption.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/IntOption.java
new file mode 100755
index 0000000..87e732a
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/IntOption.java
@@ -0,0 +1,41 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.opt;
+
+public class IntOption extends Option {
+ public int value = 0;
+
+ @Override
+ public int parse(int position, String[] args) {
+ if (position + 1 >= args.length)
+ throw new NoArgumentForOptionException("Cannot find required argument for option \"" + args[position] + "\".");
+
+ value = Integer.parseInt(args[position + 1]);
+ return super.parse(position, args) + 1;
+ }
+
+ @Override
+ public String help() {
+ StringBuilder help = new StringBuilder();
+ help.append(join("|", name, alias, aliases)).append(" VALUE\t").append(description);
+ if (required)
+ help.append(" Required.");
+ else if (value != 0)
+ help.append(" Default value is \"").append("" + value).append("\".");
+ return help.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/NoArgumentForOptionException.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/NoArgumentForOptionException.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/NoArgumentForOptionException.java
new file mode 100755
index 0000000..a074672
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/NoArgumentForOptionException.java
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.opt;
+
+public class NoArgumentForOptionException extends RuntimeException {
+ public NoArgumentForOptionException(String message) {
+ super(message);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/Option.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/Option.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/Option.java
new file mode 100755
index 0000000..e69d3f3
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/Option.java
@@ -0,0 +1,102 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.opt;
+
+public class Option {
+
+ public String name = "";
+ public String alias = null;
+ public String aliases[] = null;
+
+ public String description = "";
+ public boolean used = false;
+ public boolean required = false;
+
+ /**
+ * Parse option value, if any.
+ *
+ * @param position
+ * position of this option in list of arguments
+ * @param args
+ * command line arguments
+ * @return how many arguments are consumed, at least 1
+ */
+ public int parse(int position, String args[]) {
+ used = true;
+ return 1;
+ }
+
+ @Override
+ public String toString() {
+ return help();
+ }
+
+ /**
+ * Return help string for this option. Example:
+ *
+ * <pre>
+ * --foo|-f Foo option.
+ * </pre>
+ */
+ public String help() {
+ return join("|", name, alias, aliases) + "\t" + description + ((required) ? " Required." : "");
+ }
+
+ /**
+ * Return string like "--foo|-f|--another-foo-alias".
+ */
+ protected String join(String delim, String name, String alias, String aliases[]) {
+
+ // Option name is mandatory
+ StringBuilder sb = new StringBuilder(name.length());
+ sb.append(name);
+
+ // Alias is optional
+ if (alias != null && alias.length() > 0) {
+ sb.append(delim).append(alias);
+ }
+
+ // Other aliases are optional too
+ if (aliases != null) {
+ for (String s : aliases) {
+ if (s != null && s.length() > 0) {
+ sb.append(delim).append(s);
+ }
+ }
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Return description of options in format suitable for help and usage text.
+ *
+ * @param header
+ * header string to print before list of options
+ * @param options
+ * list of options to print
+ */
+ public static String toHelp(String header, Option[] options) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(header).append(":\n");
+ for (Option option : options) {
+ sb.append(" ").append(option.help()).append('\n');
+ }
+ return sb.toString();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/OptionParser.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/OptionParser.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/OptionParser.java
new file mode 100755
index 0000000..11c42fe
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/OptionParser.java
@@ -0,0 +1,147 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.opt;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Simple parser of GNU-like options.
+ */
+public class OptionParser {
+
+ public static Option helpOption() {
+ return new Option() {
+ {
+ name = "--help";
+ alias = "-h";
+ }
+ };
+ }
+
+ /**
+ * Parse options, capture values and return rest of arguments.
+ *
+ * @param args
+ * command line arguments to parse
+ * @param startFrom
+ * number of first argument to start parsing from
+ * @param options
+ * options to fill with values
+ * @return rest of command line after first non-option or "--" separator
+ */
+ public static String[] parseOptions(String args[], int startFrom, Option options[]) {
+ // Convert array of options into map, where key is option name or alias
+ Map<String, Option> optionMap = new HashMap<String, Option>(options.length);
+ for (Option option : options) {
+ optionMap.put(option.name, option);
+
+ if (option.alias != null)
+ optionMap.put(option.alias, option);
+
+ if (option.aliases != null) {
+ for (String alias : option.aliases)
+ optionMap.put(alias, option);
+ }
+ }
+
+ // Parse arguments
+ int position = startFrom;
+ while (position < args.length) {
+ // Double dash means end of options
+ String optionName = args[position];
+ if (optionName.equals("--")) {
+ position++;
+ break;
+ }
+
+ Option option = optionMap.get(optionName);
+
+ // If option is not found, then this is argument, unless is starts with
+ // dash
+ if (option == null)
+ if (!optionName.startsWith("-"))
+ break;
+ else
+ throw new UnknownOptionException("Option \"" + optionName
+ + "\" is unknown. If this is not an option, then use \"--\" to separate options and arguments. Known options: " + optionMap.keySet().toString());
+
+ position += option.parse(position, args);
+ }
+
+ // Check is required options are used on command line
+ for (Option option : options) {
+ if (option.required && !option.used)
+ throw new OptionRequiredException("Option \"" + option.name + "\" is required.");
+ }
+
+ // Return rest of arguments, which are left after options
+ return (position < args.length) ? Arrays.copyOfRange(args, position, args.length) : new String[] {};
+ }
+
+ /* Example. */
+ public static void main(String args[]) {
+ if (args.length == 0)
+ args = new String[] {"--help", "--foo", "fooval", "--bar", "123", "-v", "--verbose", "-v", "-a", "a1", "-aa", "a2", "-aaa", "a3", "rest", "of",
+ "arguments"};
+
+ StringOption foo = new StringOption() {
+ {
+ name = "--foo";
+ alias = "-f";
+ value = "fooDefault";
+ }
+ };
+
+ IntOption bar = new IntOption() {
+ {
+ name = "--bar";
+ alias = "-b";
+ value = 123;
+ }
+ };
+
+ IncrementalOption verbose = new IncrementalOption() {
+ {
+ name = "--verbose";
+ alias = "-v";
+ }
+ };
+
+ StringArrayOption array = new StringArrayOption() {
+ {
+ name = "--array";
+ alias = "-a";
+ aliases = new String[] {"-aa", "-aaa"};
+ }
+ };
+
+ String arguments[] = OptionParser.parseOptions(args, 0, new Option[] {helpOption(), foo, bar, verbose, array});
+
+ assertTrue(foo.value.equals("fooval"));
+ assertTrue(bar.value == 123);
+ assertTrue(verbose.value == 3);
+ assertTrue(Arrays.equals(array.value, new String[] {"a1", "a2", "a3"}));
+ assertTrue(Arrays.equals(arguments, new String[] {"rest", "of", "arguments"}));
+ }
+
+ public static void assertTrue(boolean result) {
+ if (!result)
+ throw new AssertionError();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/OptionRequiredException.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/OptionRequiredException.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/OptionRequiredException.java
new file mode 100755
index 0000000..b397627
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/OptionRequiredException.java
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.opt;
+
+public class OptionRequiredException extends RuntimeException {
+ public OptionRequiredException(String message) {
+ super(message);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/StringArrayOption.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/StringArrayOption.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/StringArrayOption.java
new file mode 100755
index 0000000..b2f3c30
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/StringArrayOption.java
@@ -0,0 +1,38 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.opt;
+
+import java.util.Arrays;
+
+public class StringArrayOption extends Option {
+ public String value[] = null;
+
+ @Override
+ public int parse(int position, String[] args) {
+ if (position + 1 >= args.length)
+ throw new NoArgumentForOptionException("Cannot find required argument for option \"" + args[position] + "\".");
+
+ // Append value to end of array of values
+ if (value == null) {
+ value = new String[] {args[position + 1]};
+ } else {
+ value = Arrays.copyOf(value, value.length + 1);
+ value[value.length - 1] = args[position + 1];
+ }
+ return super.parse(position, args) + 1;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/StringEnumerationOption.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/StringEnumerationOption.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/StringEnumerationOption.java
new file mode 100755
index 0000000..f59952e
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/StringEnumerationOption.java
@@ -0,0 +1,72 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.opt;
+
+public class StringEnumerationOption extends Option {
+ public String value = "";
+ public String choices[] = new String[] {};
+
+ @Override
+ public int parse(int position, String[] args) {
+ if (position + 1 >= args.length)
+ throw new NoArgumentForOptionException("Cannot find required argument for option \"" + args[position] + "\".");
+
+ value = args[position + 1];
+
+ for (String s : choices) {
+ if (value.equals(s))
+ return super.parse(position, args) + 1;
+ }
+
+ throw new NoArgumentForOptionException("Unexpected argument for option \"" + args[position] + "\": \"" + value + "\". Expected argument: "
+ + join("|", choices) + ".");
+ }
+
+ @Override
+ public String help() {
+ StringBuilder help = new StringBuilder();
+ help.append(join("|", name, alias, aliases)).append(" ").append(join("|", choices)).append("\t").append(description);
+ if (required)
+ help.append(" Required.");
+ else if (value != null && value.length() > 0)
+ help.append(" Default value is \"").append(value).append("\".");
+ return help.toString();
+ }
+
+ /**
+ * Join strings in array into one large string.
+ */
+ protected String join(String delim, String values[]) {
+ StringBuilder sb = new StringBuilder();
+ if (values != null) {
+ boolean first = true;
+ for (String s : values) {
+ if (s != null && s.length() > 0) {
+ if (first)
+ first = false;
+ else
+ sb.append(delim);
+
+ sb.append(s);
+ }
+ }
+ }
+
+ return sb.toString();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/StringOption.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/StringOption.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/StringOption.java
new file mode 100755
index 0000000..ec9c82c
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/StringOption.java
@@ -0,0 +1,41 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.opt;
+
+public class StringOption extends Option {
+ public String value = "";
+
+ @Override
+ public int parse(int position, String[] args) {
+ if (position + 1 >= args.length)
+ throw new NoArgumentForOptionException("Cannot find required argument for option \"" + args[position] + "\".");
+
+ value = args[position + 1];
+ return super.parse(position, args) + 1;
+ }
+
+ @Override
+ public String help() {
+ StringBuilder help = new StringBuilder();
+ help.append(join("|", name, alias, aliases)).append(" VALUE\t").append(description);
+ if (required)
+ help.append(" Required.");
+ else if (value != null && value.length() > 0)
+ help.append(" Default value is \"").append(value).append("\".");
+ return help.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/UnknownOptionException.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/UnknownOptionException.java b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/UnknownOptionException.java
new file mode 100755
index 0000000..58cce73
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/common/opt/UnknownOptionException.java
@@ -0,0 +1,27 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 common.opt;
+
+public class UnknownOptionException extends RuntimeException {
+
+ public UnknownOptionException(String message) {
+ super(message);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/AwtRdpKeyboardAdapter.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/AwtRdpKeyboardAdapter.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/AwtRdpKeyboardAdapter.java
deleted file mode 100644
index 06449f6..0000000
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/AwtRdpKeyboardAdapter.java
+++ /dev/null
@@ -1,350 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF 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 rdpclient;
-
-import java.awt.event.KeyEvent;
-
-import streamer.BaseElement;
-import streamer.ByteBuffer;
-import streamer.Link;
-import common.KeyOrder;
-
-public class AwtRdpKeyboardAdapter extends BaseElement {
-
- /**
- * Absence of this flag indicates a key-down event, while its presence
- * indicates a key-release event.
- */
- public static final int FASTPATH_INPUT_KBDFLAGS_RELEASE = 0x01;
-
- /**
- * Keystroke message contains an extended scancode. For enhanced 101-key and
- * 102-key keyboards, extended keys include the right ALT and right CTRL keys
- * on the main section of the keyboard; the INS, DEL, HOME, END, PAGE UP, PAGE
- * DOWN and ARROW keys in the clusters to the left of the numeric keypad; and
- * the Divide ("/") and ENTER keys in the numeric keypad.
- */
- public static final int FASTPATH_INPUT_KBDFLAGS_EXTENDED = 0x02;
-
- public static final int FASTPATH_INPUT_EVENT_SCANCODE = 0;
-
- public AwtRdpKeyboardAdapter(String id) {
- super(id);
- }
-
- @Override
- public void handleData(ByteBuffer buf, Link link) {
- if (verbose)
- System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
-
- KeyOrder order = (KeyOrder)buf.getOrder();
- buf.unref();
-
- ByteBuffer outBuf = new ByteBuffer(2, true);
-
- int scanCode = map_en_us(order.event);
-
- // eventHeader (1 byte): An 8-bit, unsigned integer. The format of this
- // field is the same as the eventHeader byte field described in section
- // 2.2.8.1.2.2. The eventCode bitfield (3 bits in size) MUST be set to
- // FASTPATH_INPUT_EVENT_SCANCODE (0). The eventFlags bitfield (5 bits in
- // size) contains flags describing the keyboard event.
- outBuf.writeByte((scanCode >> 8) | (FASTPATH_INPUT_EVENT_SCANCODE << 5) | ((order.pressed) ? 0 : FASTPATH_INPUT_KBDFLAGS_RELEASE));
-
- // keyCode (1 byte): An 8-bit, unsigned integer. The scancode of the key
- // which triggered the event.
- outBuf.writeByte(scanCode);
-
- // Push buffer to one pad only, so it can be modified without copying of
- // data
- pushDataToPad(STDOUT, outBuf);
- }
-
- /**
- * Return key scan code (in lower byte) and extended flags (in second byte).
- */
- private int map_en_us(KeyEvent event) {
- // Also set extended key flag when necessary.
- // For enhanced 101-key and 102-key keyboards, extended keys include the
- // right ALT and right CTRL keys on the main section of the keyboard; the
- // INS, DEL, HOME, END, PAGE UP, PAGE DOWN and ARROW keys in the clusters to
- // the left of the numeric keypad; and the Divide ("/") and ENTER keys in
- // the numeric keypad.
-
- switch (event.getKeyCode()) {
- // Functional keys
- case KeyEvent.VK_ESCAPE:
- return 1;
- case KeyEvent.VK_F1:
- return 59;
- case KeyEvent.VK_F2:
- return 60;
- case KeyEvent.VK_F3:
- return 61;
- case KeyEvent.VK_F4:
- return 62;
- case KeyEvent.VK_F5:
- return 63;
- case KeyEvent.VK_F6:
- return 64;
- case KeyEvent.VK_F7:
- return 65;
- case KeyEvent.VK_F8:
- return 66;
- case KeyEvent.VK_F9:
- return 67;
- case KeyEvent.VK_F10:
- return 68;
- case KeyEvent.VK_F11:
- return 87;
- case KeyEvent.VK_F12:
- return 88;
-
- // Row #1
- case KeyEvent.VK_BACK_QUOTE:
- return 41;
- case KeyEvent.VK_1:
- return 2;
- case KeyEvent.VK_2:
- return 3;
- case KeyEvent.VK_3:
- return 4;
- case KeyEvent.VK_4:
- return 5;
- case KeyEvent.VK_5:
- return 6;
- case KeyEvent.VK_6:
- return 7;
- case KeyEvent.VK_7:
- return 8;
- case KeyEvent.VK_8:
- return 9;
- case KeyEvent.VK_9:
- return 10;
- case KeyEvent.VK_0:
- return 11;
- case KeyEvent.VK_MINUS:
- return 12;
- case KeyEvent.VK_EQUALS:
- return 13;
- case KeyEvent.VK_BACK_SPACE:
- return 14;
-
- // Row #2
- case KeyEvent.VK_TAB:
- return 15;
- case KeyEvent.VK_Q:
- return 16;
- case KeyEvent.VK_W:
- return 17;
- case KeyEvent.VK_E:
- return 18;
- case KeyEvent.VK_R:
- return 19;
- case KeyEvent.VK_T:
- return 20;
- case KeyEvent.VK_Y:
- return 21;
- case KeyEvent.VK_U:
- return 22;
- case KeyEvent.VK_I:
- return 23;
- case KeyEvent.VK_O:
- return 24;
- case KeyEvent.VK_P:
- return 25;
- case KeyEvent.VK_OPEN_BRACKET:
- return 26;
- case KeyEvent.VK_CLOSE_BRACKET:
- return 27;
- case KeyEvent.VK_ENTER:
- switch (event.getKeyLocation()) {
- default:
- case KeyEvent.KEY_LOCATION_STANDARD:
- return 28;
- case KeyEvent.KEY_LOCATION_NUMPAD:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 28;
- }
-
- // Row #3
- case KeyEvent.VK_CAPS_LOCK:
- return 58;
- case KeyEvent.VK_A:
- return 30;
- case KeyEvent.VK_S:
- return 31;
- case KeyEvent.VK_D:
- return 32;
- case KeyEvent.VK_F:
- return 33;
- case KeyEvent.VK_G:
- return 34;
- case KeyEvent.VK_H:
- return 35;
- case KeyEvent.VK_J:
- return 36;
- case KeyEvent.VK_K:
- return 37;
- case KeyEvent.VK_L:
- return 38;
- case KeyEvent.VK_SEMICOLON:
- return 39;
- case KeyEvent.VK_QUOTE:
- return 40;
-
- // Row #4
- case KeyEvent.VK_SHIFT:
- switch (event.getKeyLocation()) {
- default:
- case KeyEvent.KEY_LOCATION_LEFT:
- return 42;
- case KeyEvent.KEY_LOCATION_RIGHT:
- return 54;
- }
- case KeyEvent.VK_BACK_SLASH:
- return 43;
- case KeyEvent.VK_Z:
- return 44;
- case KeyEvent.VK_X:
- return 45;
- case KeyEvent.VK_C:
- return 46;
- case KeyEvent.VK_V:
- return 47;
- case KeyEvent.VK_B:
- return 48;
- case KeyEvent.VK_N:
- return 49;
- case KeyEvent.VK_M:
- return 50;
- case KeyEvent.VK_COMMA:
- return 51;
- case KeyEvent.VK_PERIOD:
- return 52;
- case KeyEvent.VK_SLASH:
- return 53;
-
- //
- // Bottom row
- case KeyEvent.VK_CONTROL:
- switch (event.getKeyLocation()) {
- default:
- case KeyEvent.KEY_LOCATION_LEFT:
- return 29;
- case KeyEvent.KEY_LOCATION_RIGHT:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 29;
- }
- case KeyEvent.VK_WINDOWS:
- switch (event.getKeyLocation()) {
- default:
- case KeyEvent.KEY_LOCATION_LEFT:
- return 91;
- case KeyEvent.KEY_LOCATION_RIGHT:
- return 92;
- }
- case KeyEvent.VK_ALT:
- switch (event.getKeyLocation()) {
- default:
- case KeyEvent.KEY_LOCATION_LEFT:
- return 56;
- case KeyEvent.KEY_LOCATION_RIGHT:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 56;
- }
- case KeyEvent.VK_ALT_GRAPH:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 56;
-
- case KeyEvent.VK_SPACE:
- return 57;
-
- case KeyEvent.VK_CONTEXT_MENU:
- return 93;
-
- //
- // Special keys
- case KeyEvent.VK_PRINTSCREEN:
- return 55;
- case KeyEvent.VK_SCROLL_LOCK:
- return 70;
- case KeyEvent.VK_PAUSE:
- return 29;
-
- // Text navigation keys
- case KeyEvent.VK_INSERT:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 82;
- case KeyEvent.VK_HOME:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 71;
- case KeyEvent.VK_PAGE_UP:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 73;
- case KeyEvent.VK_DELETE:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 83;
- case KeyEvent.VK_END:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 79;
- case KeyEvent.VK_PAGE_DOWN:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 81;
-
- // Cursor keys
- case KeyEvent.VK_UP:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 72;
- case KeyEvent.VK_LEFT:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 75;
- case KeyEvent.VK_DOWN:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 80;
- case KeyEvent.VK_RIGHT:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 77;
-
- // Keypad
- case KeyEvent.VK_NUM_LOCK:
- return 69;
- case KeyEvent.VK_DIVIDE:
- return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 53;
- case KeyEvent.VK_MULTIPLY:
- return 55;
- case KeyEvent.VK_SUBTRACT:
- return 74;
- case KeyEvent.VK_ADD:
- return 78;
-
- case KeyEvent.VK_NUMPAD7:
- return 71;
- case KeyEvent.VK_NUMPAD8:
- return 72;
- case KeyEvent.VK_NUMPAD9:
- return 73;
- case KeyEvent.VK_NUMPAD4:
- return 75;
- case KeyEvent.VK_NUMPAD5:
- return 76;
- case KeyEvent.VK_NUMPAD6:
- return 77;
- case KeyEvent.VK_NUMPAD1:
- return 79;
- case KeyEvent.VK_NUMPAD2:
- return 80;
- case KeyEvent.VK_NUMPAD3:
- return 81;
- case KeyEvent.VK_NUMPAD0:
- return 82;
- case KeyEvent.VK_DECIMAL:
- return 83;
-
- default:
- System.err.println("Key is not mapped: " + event + ".");
- return 57; // Space
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/48c47101/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/AwtRdpMouseAdapter.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/AwtRdpMouseAdapter.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/AwtRdpMouseAdapter.java
deleted file mode 100644
index f533906..0000000
--- a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/AwtRdpMouseAdapter.java
+++ /dev/null
@@ -1,179 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF 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 rdpclient;
-
-import java.awt.event.InputEvent;
-
-import streamer.BaseElement;
-import streamer.ByteBuffer;
-import streamer.Link;
-import common.MouseOrder;
-
-/**
- * @see http://msdn.microsoft.com/en-us/library/cc240594.aspx
- */
-public class AwtRdpMouseAdapter extends BaseElement {
- public static final int FASTPATH_INPUT_EVENT_MOUSE = 0x01;
-
- /**
- * Event is a mouse wheel rotation. The only valid flags in a wheel rotation
- * event are PTRFLAGS_WHEEL_NEGATIVE and the WheelRotationMask; all other
- * pointer flags are ignored.
- */
- public static final int PTRFLAGS_WHEEL = 0x0200;
-
- /**
- * Wheel rotation value (contained in the WheelRotationMask bit field) is
- * negative and MUST be sign-extended before injection at the server.
- */
- public static final int PTRFLAGS_WHEEL_NEGATIVE = 0x0100;
-
- /**
- * Bit field describing the number of rotation units the mouse wheel was
- * rotated. The value is negative if the PTRFLAGS_WHEEL_NEGATIVE flag is set.
- */
- public static final int WHEEL_ROTATION_MASK = 0x01FF;
-
- /**
- * Indicates that the mouse position MUST be updated to the location specified
- * by the xPos and yPos fields.
- */
- public static final int PTRFLAGS_MOVE = 0x0800;
-
- /**
- * Indicates that a click event has occurred at the position specified by the
- * xPos and yPos fields. The button flags indicate which button has been
- * clicked and at least one of these flags MUST be set.
- */
- public static final int PTRFLAGS_DOWN = 0x8000;
-
- /**
- * Mouse button 1 (left button) was clicked or released. If the PTRFLAGS_DOWN
- * flag is set, then the button was clicked, otherwise it was released.
- */
- public static final int PTRFLAGS_BUTTON1 = 0x1000;
-
- /**
- * Mouse button 2 (right button) was clicked or released. If the PTRFLAGS_DOWN
- * flag is set, then the button was clicked, otherwise it was released.
- */
- public static final int PTRFLAGS_BUTTON2 = 0x2000;
-
- /**
- * Mouse button 3 (middle button or wheel) was clicked or released. If the
- * PTRFLAGS_DOWN flag is set, then the button was clicked, otherwise it was
- * released.
- */
- public static final int PTRFLAGS_BUTTON3 = 0x4000;
-
- public AwtRdpMouseAdapter(String id) {
- super(id);
- }
-
- @Override
- public void handleData(ByteBuffer buf, Link link) {
- if (verbose)
- System.out.println("[" + this + "] INFO: Data received: " + buf + ".");
-
- // Get mouse event
- MouseOrder order = (MouseOrder)buf.getOrder();
-
- ByteBuffer outBuf = new ByteBuffer(7, true);
-
- // eventHeader (1 byte): An 8-bit, unsigned integer. EventCode bitfield (top
- // 3 bits) MUST be set to FASTPATH_INPUT_EVENT_MOUSE (1). The
- // eventFlags bitfield (low 5 bits) MUST be zeroed out.
- outBuf.writeByte(FASTPATH_INPUT_EVENT_MOUSE << 5);
-
- // pointerFlags (2 bytes): A 16-bit, unsigned integer.
- outBuf.writeShortLE(getPointerFlags(order));
-
- // xPos (2 bytes): A 16-bit, unsigned integer. The x-coordinate of the
- // pointer.
- outBuf.writeShortLE(order.event.getX());
-
- // yPos (2 bytes): A 16-bit, unsigned integer. The y-coordinate of the
- // pointer.
- outBuf.writeShortLE(order.event.getY());
-
- // Push buffer to one pad only, so it can be modified without copying of
- // data
- pushDataToPad(STDOUT, outBuf);
- }
-
- // Remember mouse buttons
- protected boolean button1, button2, button3;
-
- protected int getPointerFlags(MouseOrder order) {
- int flags = 0;
-
- int modifiers = order.event.getModifiersEx();
-
- if (order.pressed) {
- // Mouse pressed
- flags |= PTRFLAGS_DOWN;
-
- // Check, which one of buttons is released
- boolean b1 = ((modifiers & InputEvent.BUTTON1_DOWN_MASK) > 0) && !button1;
- boolean b2 = ((modifiers & InputEvent.BUTTON2_DOWN_MASK) > 0) && !button2;
- boolean b3 = ((modifiers & InputEvent.BUTTON3_DOWN_MASK) > 0) && !button3;
-
- if (b1) {
- flags |= PTRFLAGS_BUTTON1;
- button1 = true;
- }
-
- if (b2) {
- flags |= PTRFLAGS_BUTTON3;
- button2 = true;
- }
-
- if (b3) {
- flags |= PTRFLAGS_BUTTON2;
- button3 = true;
- }
- } else if (order.released) {
- // Mouse released
-
- // Check, which one of buttons is released
- boolean b1 = !((modifiers & InputEvent.BUTTON1_DOWN_MASK) > 0) && button1;
- boolean b2 = !((modifiers & InputEvent.BUTTON2_DOWN_MASK) > 0) && button2;
- boolean b3 = !((modifiers & InputEvent.BUTTON3_DOWN_MASK) > 0) && button3;
-
- if (b1) {
- flags |= PTRFLAGS_BUTTON1;
- button1 = false;
- }
-
- if (b2) {
- flags |= PTRFLAGS_BUTTON3;
- button2 = false;
- }
-
- if (b3) {
- flags |= PTRFLAGS_BUTTON2;
- button3 = false;
- }
- } else {
- // Mouse moved
- flags |= PTRFLAGS_MOVE;
- }
-
- return flags;
- }
-
-}