Initial commit from SVN.

This commit is contained in:
wcrisman
2014-05-30 10:31:51 -07:00
commit b45e56b890
1968 changed files with 370949 additions and 0 deletions

26
.gitignore vendored Normal file
View File

@@ -0,0 +1,26 @@
#Projects current not under version control.
/Archives/
/Amaranthine Deific Alogrithm/
#App Browser & Foundation are currently convienence projects and should be removed entirely at some point (bad build structure).
/Application Browser/
/Application Foundation/
/Common Alt/
/Document Test/
/Foundation ASF Server/
#Don't include class files, archives, or temporary word files.
*.class
*.zip
*.jar
~$*.doc
#Don't include Eclipse temp files, Ivy temp files, Binary output, Build files, or compiled Resource files.
# xres files are uncompiled and should be included.
.settings
/
bin/
.ivy/
build/
*.res
archives/
/*/controls/

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="/Common"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Class File Services</name>
<comment></comment>
<projects>
<project>Common</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,123 @@
package com.de22.javabytecode;
import com.de22.javabytecode.attribute.*;
import com.de22.javabytecode.constant.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* Defines an attribute in any of the attribute collections.
* See the JVM specification 4.7.
* Subclasses of this type will provided additional functionality.
*/
public abstract class CodeAttribute extends Component {
/** The index of the attribute's name in the constant collection. */
private short nameIndex = -1;
/**
* CodeAttribute constructor.
*/
public CodeAttribute(Type type) {
super(type);
}//CodeAttribute()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public abstract String getDefaultName();
/**
* Gets the index of the attribute's name in the type's constant pool.
* @return The index of the attribute name.
*/
public short getNameIndex() {
return nameIndex;
}//getNameIndex()//
/* (non-Javadoc)
* @see com.de22.javabytecode.ITypeComponent#getSize()
*/
public abstract int getSize();
/**
* Reads an attribute from the given stream.
* @param type The type object that the attribute will belong to.
* @param in The input stream to read the attribute from.
*/
protected static CodeAttribute readAttribute(Type type, java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
CodeAttribute attribute = null;
short nameIndex = in.readShort();
Constant constant = type.getConstant(nameIndex);
ConstantUtf8 constantUtf8 = constant instanceof ConstantUtf8 ? (ConstantUtf8) constant : constant instanceof ConstantString ? (ConstantUtf8) type.getConstant(((ConstantString) constant).getStringIndex()) : null;
//This should never occur, but seems to for some compiled java code (probably due to a bad compiler). We will simply replace the missing string with an empty string.//
if(constantUtf8 == null) {
// System.out.println("Null constant found (index = " + nameIndex + ") while reading an unidentified attribute.");
attribute = new Unidentified(type, "");
attribute.nameIndex = nameIndex;
attribute.readExternal(in);
}//if//
else {
String name = constantUtf8.getValue();
if(name.equalsIgnoreCase("SourceFile")) {
attribute = new SourceFile(type);
}//if//
else if(name.equalsIgnoreCase("Code")) {
attribute = new Code(type);
}//else if//
else if(name.equalsIgnoreCase("Exceptions")) {
attribute = new ExceptionIndexes(type);
}//else if//
else if(name.equalsIgnoreCase("LineNumberTable")) {
attribute = new LineNumberTable(type);
}//else if//
else if(name.equalsIgnoreCase("LocalVariableTable")) {
attribute = new LocalVariableTable(type);
}//else if//
else if(name.equalsIgnoreCase("InnerClasses")) {
attribute = new InnerClasses(type);
}//else if//
else if(name.equalsIgnoreCase("ConstantValue")) {
attribute = new ConstantValue(type);
}//else if//
else if(name.equalsIgnoreCase("Synthetic")) {
attribute = new Synthetic(type);
}//else if//
else {
attribute = new Unidentified(type, name);
}//else//
attribute.nameIndex = nameIndex;
attribute.readExternal(in);
}//else//
return attribute;
}//readAttribute()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
if(this.nameIndex == -1) {
//There is usually no need to read the name index since it is read in the readAttribute(Type, ObjectInput) method.//
nameIndex = in.readShort();
}//if//
//Note: We leave it to the attribute to read the length of the attribute because some will require this info and most will ignore it.//
}//readExternal()//
/**
* Sets the index of the attribute's name in the type's constant pool.
* @param nameIndex The index of the attribute name.
*/
public void setNameIndex(short nameIndex) {
this.nameIndex = nameIndex;
}//setNameIndex()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
short nameIndex = getType().getConstantIndex(new ConstantUtf8(getType(), getDefaultName()));
//Write the constant index referenceing the attribute name.//
out.writeShort(nameIndex);
//Write size in bytes of the attribute.//
out.writeInt(getSize());
}//writeExternal()//
}//CodeAttribute//

View File

@@ -0,0 +1,122 @@
package com.de22.javabytecode;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public abstract class Component implements ITypeComponent {
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private Type type = null;
/**
* Converts a class name in the java class file format to class name in the java source format.
* @param type The class to convert to a java format (which except for native non-array types (such as int), can be sent to a class loader).
* @return The java source formatted class name.
*/
public static String classFileFormatToJavaFormat(String type) {
String result = null;
if(type.charAt(0) == '[') {
result = type.replace('/', '.');
}//if//
else if(type.charAt(0) == 'L') {
result = type.substring(1, type.length() - 1).replace('/', '.');
}//else if//
else {
switch(type.charAt(0)) {
case 'V': {
result = Void.TYPE.getName();
break;
}//case//
case 'I': {
result = Integer.TYPE.getName();
break;
}//case//
case 'B': {
result = Byte.TYPE.getName();
break;
}//case//
case 'C': {
result = Character.TYPE.getName();
break;
}//case//
case 'S': {
result = Short.TYPE.getName();
break;
}//case//
case 'Z': {
result = Boolean.TYPE.getName();
break;
}//case//
case 'D': {
result = Double.TYPE.getName();
break;
}//case//
case 'F': {
result = Float.TYPE.getName();
break;
}//case//
case 'J': {
result = Long.TYPE.getName();
break;
}//case//
}//switch//
}//else//
return result;
}//classFileFormatToJavaFormat()//
/**
* Converts class names in the java class file format to class names in the java source format.
* @param types The classes to convert to a java format.
* @return The java source formatted class names.
*/
public static String[] classFileFormatToJavaFormat(String[] types) {
String[] result = new String[types.length];
for(int typeIndex = 0; typeIndex < types.length; typeIndex++) {
result[typeIndex] = classFileFormatToJavaFormat(types[typeIndex]);
}//for//
return result;
}//classFileFormatToJavaFormat()//
/**
* Component constructor.
*/
public Component(Type type) {
super();
this.type = type;
}//Component()//
/**
* Appends a the end of line characters to the buffer.
* <p>This is a utility method to assist the toString(StringBuffer, int) implementations.
* @param buffer The buffer to write an end of line to.
*/
protected static void appendEndOfLine(StringBuffer buffer) {
buffer.append('\r');
buffer.append('\n');
}//appendEndOfLine()//
/**
* Appends tab characters to the buffer.
* <p>This is a utility method to assist the toString(StringBuffer, int) implementations.
* @param buffer The buffer to write a tabs to.
* @param tabCount The number of tabs to append.
*/
protected static void appendTabs(StringBuffer buffer, int tabCount) {
while(tabCount-- != 0) {
buffer.append('\t');
}//while//
}//appendTabs()//
/**
* Gets the class associated with this component.
* @return The class information that this component is a member of.
*/
protected Type getType() {
return type;
}//getType()//
/**
* Displays the component and all subcomponents in human readable string form.
* @param buffer The buffer to display to.
* @param tabCount The number of tabs to prepend to each line.
*/
public abstract void toString(StringBuffer buffer, int tabCount);
}//Component//

View File

@@ -0,0 +1,111 @@
package com.de22.javabytecode;
import java.io.IOException;
import com.common.debug.*;
import com.de22.javabytecode.constant.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public abstract class Constant extends Component {
public static final byte CONSTANT_UTF8 = 0x01;
public static final byte CONSTANT_INTEGER = 0x03;
public static final byte CONSTANT_FLOAT = 0x04;
public static final byte CONSTANT_LONG = 0x05;
public static final byte CONSTANT_DOUBLE = 0x06;
public static final byte CONSTANT_CLASS = 0x07;
public static final byte CONSTANT_STRING = 0x08;
public static final byte CONSTANT_FIELD_REF = 0x09;
public static final byte CONSTANT_METHOD_REF = 0x0A;
public static final byte CONSTANT_INTERFACE_METHOD_REF = 0x0B;
public static final byte CONSTANT_NAME_AND_TYPE = 0x0C;
/**
* Constant constructor.
*/
public Constant(Type type) {
super(type);
}//Constant()//
/**
* Gets this constant's identifying constant.
* @return The constant value that identifies this constant object type.
*/
public abstract byte getTag();
/**
* Gets a display string that shows the resulting value of the constant in a viewer friendly way.
* @return The viewer friendly constant result.
*/
public abstract String getPrettyValue();
/**
* Determines whether the constant takes double the constant entries in the class bytes.
* @return Whether the constant is a double size constant.
*/
public boolean isDoubleSize() {
return false;
}//isDoubleSize()//
/**
* Reads a constant from the given stream.
* @param type The type object that the constant will belong to.
* @param in The input stream to read the constant from.
*/
protected static Constant readConstant(Type type, java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
Constant constant = null;
short tag = in.readByte();
switch(tag) {
case CONSTANT_CLASS:
constant = new ConstantType(type);
break;
case CONSTANT_DOUBLE:
constant = new ConstantDouble(type);
break;
case CONSTANT_FIELD_REF:
constant = new ConstantFieldRef(type);
break;
case CONSTANT_FLOAT:
constant = new ConstantFloat(type);
break;
case CONSTANT_INTEGER:
constant = new ConstantInteger(type);
break;
case CONSTANT_INTERFACE_METHOD_REF:
constant = new ConstantInterfaceMethodRef(type);
break;
case CONSTANT_LONG:
constant = new ConstantLong(type);
break;
case CONSTANT_METHOD_REF:
constant = new ConstantMethodRef(type);
break;
case CONSTANT_NAME_AND_TYPE:
constant = new ConstantNameAndType(type);
break;
case CONSTANT_STRING:
constant = new ConstantString(type);
break;
case CONSTANT_UTF8:
constant = new ConstantUtf8(type);
break;
default:
Debug.halt();
break;
}//switch//
constant.readExternal(in);
return constant;
}//readConstant()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
//The tag will be read by the readConstant(Type, ObjectInput) method.//
}//readExternal()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
out.writeByte(getTag());
}//writeExternal()//
}//Constant//

View File

@@ -0,0 +1,223 @@
package com.de22.javabytecode;
import java.io.IOException;
import com.common.util.*;
import com.de22.javabytecode.constant.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class Field extends Component {
private short accessFlags = 0; //The visibility of the field and the field modifiers.//
private short fieldNameIndex = 0; //The index in the constant collection of the name of this field.//
private short descriptorIndex = 0; //The index in the constant collection of the descriptor for this field.//
private IList attributes = new LiteList(10, 30); //The attributes associated with this field.//
/**
* Field constructor.
*/
protected Field(Type type) {
super(type);
}//Field()//
/**
* Field constructor.
*/
public Field(Type type, short accessFlags, short descriptorIndex, short fieldNameIndex) {
super(type);
this.accessFlags = accessFlags;
this.descriptorIndex = descriptorIndex;
this.fieldNameIndex = fieldNameIndex;
}//Field()//
/**
* Adds an attribute to the method.
* An attribute describes some property of the method.
* @param attribute The attribute to add to the method. The attribute's name will automatically be added to the constant pool.
* @return The index of the attribute in the attribute pool.
*/
public short addAttribute(CodeAttribute attribute) {
short nameIndex = getType().addConstant(new ConstantUtf8(getType(), attribute.getDefaultName()), false);
attribute.setNameIndex(nameIndex);
attributes.add(attribute);
return (short) (attributes.getSize() - 1);
}//addAttribute()//
/**
* Removes the attribute referenced by the index.
* @param index The zero based index of the attribute to remove.
* @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index.
*/
public CodeAttribute removeAttribute(short index) {
int constant = index - 1;
return (CodeAttribute) attributes.remove(constant);
}//getAttribute()//
/**
* Gets the attributes referenced by the index.
* @param index The zero based index of the attribute to retrieve.
* @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index.
*/
public CodeAttribute getAttribute(short index) {
int constant = index - 1;
return (CodeAttribute) attributes.get(constant);
}//getAttribute()//
/**
* Gets the count of attributes associated with the type.
* @return The number of attributes for this type.
*/
public int getAttributeCount() {
return attributes.getSize();
}//getAttributeCount()//
/**
* Gets the field's access flags.
* @return The field's access flags.
* @see #ACC_PUBLIC
* @see #ACC_PRIVATE
* @see #ACC_PROTECTED
* @see #ACC_STATIC
* @see #ACC_VOLITILE
* @see #ACC_FINAL
* @see #ACC_TRANSIENT
*/
public short getAccessFlags() {
return accessFlags;
}//getAccessFlags()//
/**
* Gets the index of constant in the classes constant pool for the field descriptor.
* @return The field descriptor's constant pool index.
*/
public short getDescriptorIndex() {
return descriptorIndex;
}//getDescriptorIndex()//
/**
* Gets the constant pool index identifying the field name.
* @return The field name's index in the constant pool.
*/
public short getFieldNameIndex() {
return fieldNameIndex;
}//getFieldNameIndex()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 0;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
short count = 0;
accessFlags = in.readShort();
fieldNameIndex = in.readShort();
descriptorIndex = in.readShort();
count = in.readShort();
while(count-- != 0) {
addAttribute(CodeAttribute.readAttribute(getType(), in));
}//while//
}//readExternal()//
/**
* Reads a field from the given stream.
* @param type The type object that the field will belong to.
* @param in The input stream to read the field from.
*/
protected static Field readField(Type type, java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
Field field = new Field(type);
field.readExternal(in);
return field;
}//readField()//
/**
* Sets the field's access flags.
* @param accessFlags The field's access flags.
* @see #ACC_PUBLIC
* @see #ACC_PRIVATE
* @see #ACC_PROTECTED
* @see #ACC_STATIC
* @see #ACC_VOLITILE
* @see #ACC_FINAL
* @see #ACC_TRANSIENT
*/
public void setAccessFlags(short accessFlags) {
this.accessFlags = accessFlags;
}//setAccessFlags()//
/**
* Sets the index of constant in the classes constant pool for the field descriptor.
* @param descriptorIndex The field descriptor's constant pool index.
*/
public void setDescriptorIndex(short descriptorIndex) {
this.descriptorIndex = descriptorIndex;
}//setDescriptorIndex()//
/**
* Sets the constant pool index identifying the field name.
* @param nameIndex The field name's index in the constant pool.
*/
public void setFieldNameIndex(short fieldNameIndex) {
this.fieldNameIndex = fieldNameIndex;
}//setFieldNameIndex()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIterator iterator = null;
appendTabs(buffer, tabCount);
buffer.append("Field (nameIndex=");
buffer.append(fieldNameIndex);
buffer.append(" descriptorIndex=");
buffer.append(descriptorIndex);
buffer.append(" accessFlags=");
buffer.append(accessFlags);
buffer.append(" descriptor='");
buffer.append(getType().getConstant(descriptorIndex));
buffer.append("' name='");
buffer.append(getType().getConstant(fieldNameIndex));
buffer.append("')");
if(attributes.getSize() > 0) {
buffer.append(' ');
buffer.append('{');
appendEndOfLine(buffer);
iterator = attributes.iterator();
while(iterator.hasNext()) {
CodeAttribute attribute = (CodeAttribute) iterator.next();
attribute.toString(buffer, tabCount + 1);
}//while//
appendTabs(buffer, tabCount);
buffer.append('}');
}//if//
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
IIterator iterator = null;
out.writeShort(accessFlags);
out.writeShort(fieldNameIndex);
out.writeShort(descriptorIndex);
if(attributes != null) {
out.writeShort((short) attributes.getSize());
iterator = attributes.iterator();
while(iterator.hasNext()) {
((CodeAttribute) iterator.next()).writeExternal(out);
}//while//
}//if//
else {
out.writeShort((short) 0);
}//else//
}//writeExternal()//
}//Field//

View File

@@ -0,0 +1,26 @@
package com.de22.javabytecode;
import java.io.Externalizable;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public interface ITypeComponent extends Externalizable {
public static final short ACC_PUBLIC = 0x0001;
public static final short ACC_PRIVATE = 0x0002;
public static final short ACC_PROTECTED = 0x0004;
public static final short ACC_STATIC = 0x0008;
public static final short ACC_FINAL = 0x0010;
public static final short ACC_SUPER = 0x0020;
public static final short ACC_SYNCHRONIZED = 0x0020;
public static final short ACC_VOLITILE = 0x0040;
public static final short ACC_TRANSIENT = 0x0080;
public static final short ACC_NATIVE = 0x0100;
public static final short ACC_INTERFACE = 0x0200;
public static final short ACC_ABSTRACT = 0x0400;
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize();
}//ITypeComponent//

View File

@@ -0,0 +1,83 @@
package com.de22.javabytecode;
import java.io.IOException;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class Interface extends Component {
private short interfaceIndex = 0; //The index in the constant table of the interface constant.//
/**
* Interface constructor.
*/
protected Interface(Type type) {
super(type);
}//Interface()//
/**
* Interface constructor.
*/
public Interface(Type type, short interfaceIndex) {
super(type);
this.interfaceIndex = interfaceIndex;
}//Interface()//
/**
* Gets the index of the interface class reference in the constant pool.
* @return The constant pool index of the interface class.
*/
public short getClassIndex() {
return interfaceIndex;
}//getClassIndex()//
/**
* Sets the index of the interface class reference in the constant pool.
* @param classIndex The constant pool index of the interface class.
*/
public void setClassIndex(short classIndex) {
this.interfaceIndex = classIndex;
}//setClassIndex()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 0;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
interfaceIndex = in.readShort();
}//readExternal()//
/**
* Reads a interface from the given stream.
* @param type The type object that the interface will belong to.
* @param in The input stream to read the interface from.
*/
protected static Interface readInterface(Type type, java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
Interface interfaze = new Interface(type);
interfaze.readExternal(in);
return interfaze;
}//readInterface()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Interface (interfaceIndex=");
buffer.append(interfaceIndex);
buffer.append(" name='");
buffer.append(getType().getConstant(interfaceIndex));
buffer.append("')");
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
out.writeShort(interfaceIndex);
}//writeExternal()//
}//Interface//

View File

@@ -0,0 +1,264 @@
package com.de22.javabytecode;
import java.io.IOException;
import com.common.util.*;
import com.de22.javabytecode.constant.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class Method extends Component {
private short accessFlags = 0; //The modifiers and visibility for the method.//
private short nameIndex = 0; //The index within the constant collection of the name constant for this method.//
private short descriptorIndex = 0; //The index within the constant collection of the descriptor for this method.//
private IList attributes = new LiteList(10, 30); //The attributes associated with this method.//
/**
* Gets the return type in class file format (ie: [I for int[] and Ljava.lang.Object; for java.lang.Object).
* @param descriptor The descriptor in class file format.
* @return The return type in class file format.
*/
public static String getReturnType(String descriptor) {
return descriptor.substring(descriptor.lastIndexOf(')') + 1);
}//getReturnType()//
/**
* Gets the method parameters in class file format (ie: [I for int[] and Ljava.lang.Object; for java.lang.Object).
* @param descriptor The descriptor in class file format.
* @return The collection of parameters in order and in class file format.
*/
public static String[] getParamterTypes(String descriptor) {
int descriptorIndex = 1;
int parameterIndex = 0;
String[] result = null;
int startIndex = 1;
//First count the parameters.//
while(descriptor.charAt(descriptorIndex) != ')') {
if(descriptor.charAt(descriptorIndex) == 'L') {
descriptorIndex = descriptor.indexOf(';', descriptorIndex);
parameterIndex++;
}//if//
else if(descriptor.charAt(descriptorIndex) != '[') {
parameterIndex++;
}//else if//
descriptorIndex++;
}//while//
result = new String[parameterIndex];
parameterIndex = 0;
descriptorIndex = 1;
//Next load the parameter class names.//
while(descriptor.charAt(descriptorIndex) != ')') {
if(descriptor.charAt(descriptorIndex) == 'L') {
descriptorIndex = descriptor.indexOf(';', descriptorIndex);
result[parameterIndex++] = descriptor.substring(startIndex, descriptorIndex + 1);
startIndex = descriptorIndex + 1;
}//if//
else if(descriptor.charAt(descriptorIndex) != '[') {
result[parameterIndex++] = descriptor.substring(startIndex, descriptorIndex + 1);
startIndex = descriptorIndex + 1;
}//else if//
descriptorIndex++;
}//while//
return result;
}//getParamterTypes()//
/**
* Method constructor.
*/
protected Method(Type type) {
super(type);
}//Method()//
/**
* Adds an attribute to the method.
* An attribute describes some property of the method.
* @param attribute The attribute to add to the method. The attribute's name will automatically be added to the constant pool.
* @return The index of the attribute in the attribute pool.
*/
public short addAttribute(CodeAttribute attribute) {
short nameIndex = getType().addConstant(new ConstantUtf8(getType(), attribute.getDefaultName()), false);
attribute.setNameIndex(nameIndex);
attributes.add(attribute);
return (short) (attributes.getSize() - 1);
}//addAttribute()//
/**
* Gets the attribute referenced by the index.
* <p>Warning: This is a one based index, but the method to get the count will return the actual number of values.</p>
* @param index The one based index of the attribute to retrieve.
* @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index.
*/
public CodeAttribute getAttribute(short index) {
int constant = index - 1;
return (CodeAttribute) attributes.get(constant);
}//getAttribute()//
/**
* Removes the attribute referenced by the index.
* <p>Warning: This is a one based index, but the method to get the count will return the actual number of values.</p>
* @param index The one based index of the attribute to remove.
* @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index.
*/
public CodeAttribute removeAttribute(short index) {
int constant = index - 1;
return (CodeAttribute) attributes.remove(constant);
}//getAttribute()//
/**
* Gets the count of attributes associated with the type.
* @return The number of attributes for this type.
*/
public int getAttributeCount() {
return attributes.getSize();
}//getAttributeCount()//
/**
* Gets the method's access flags.
* @return The method's access flags.
* @see #ACC_PUBLIC
* @see #ACC_PRIVATE
* @see #ACC_PROTECTED
* @see #ACC_STATIC
* @see #ACC_ABSTRACT
* @see #ACC_SYNCHRONIZED
* @see #ACC_NATIVE
* @see #ACC_FINAL
*/
public short getAccessFlags() {
return accessFlags;
}//getAccessFlags()//
/**
* Gets the index of constant in the classes constant pool for the method descriptor.
* @return The method descriptor's constant pool index.
*/
public short getDescriptorIndex() {
return descriptorIndex;
}//getDescriptorIndex()//
/**
* Gets the index of constant in the classes constant pool for the method name.
* @return The methods name's constant pool index.
*/
public short getNameIndex() {
return nameIndex;
}//getNameIndex()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 0;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
short length;
accessFlags = in.readShort();
nameIndex = in.readShort();
descriptorIndex = in.readShort();
length = in.readShort();
attributes = length > 0 ? new LiteList((int) length, 10) : LiteList.EMPTY_LIST;
while(length-- > 0) {
addAttribute(CodeAttribute.readAttribute(getType(), in));
}//while//
}//readExternal()//
/**
* Reads a method from the given stream.
* @param type The type object that the method will belong to.
* @param in The input stream to read the method from.
*/
protected static Method readMethod(Type type, java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
Method method = new Method(type);
method.readExternal(in);
return method;
}//readMethod()//
/**
* Sets the method's access flags.
* @param accessFlags The method's access flags.
* @see #ACC_PUBLIC
* @see #ACC_PRIVATE
* @see #ACC_PROTECTED
* @see #ACC_STATIC
* @see #ACC_ABSTRACT
* @see #ACC_SYNCHRONIZED
* @see #ACC_NATIVE
* @see #ACC_FINAL
*/
public void setAccessFlags(short accessFlags) {
this.accessFlags = accessFlags;
}//setAccessFlags()//
/**
* Sets the index of constant in the classes constant pool for the method descriptor.
* @param descriptorIndex The method descriptor's constant pool index.
*/
public void setDescriptorIndex(short descriptorIndex) {
this.descriptorIndex = descriptorIndex;
}//setDescriptorIndex()//
/**
* Sets the index of constant in the classes constant pool for the method name.
* @param nameIndex The methods name's constant pool index.
*/
public void setNameIndex(short nameIndex) {
this.nameIndex = nameIndex;
}//setNameIndex()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIterator iterator = null;
appendTabs(buffer, tabCount);
buffer.append("Method (accessFlags=");
buffer.append(accessFlags);
buffer.append(" nameIndex=");
buffer.append(nameIndex);
buffer.append(" descriptorIndex=");
buffer.append(descriptorIndex);
buffer.append(" Name='");
buffer.append(getType().getConstant(nameIndex));
buffer.append("' Signature='");
buffer.append(getType().getConstant(descriptorIndex));
buffer.append("')");
if(attributes.getSize() > 0) {
buffer.append(' ');
buffer.append('{');
appendEndOfLine(buffer);
iterator = attributes.iterator();
while(iterator.hasNext()) {
CodeAttribute attribute = (CodeAttribute) iterator.next();
attribute.toString(buffer, tabCount + 1);
}//while//
appendTabs(buffer, tabCount);
buffer.append('}');
}//if//
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
short length = (short) (attributes != null ? attributes.getSize() : 0);
out.writeShort(accessFlags);
out.writeShort(nameIndex);
out.writeShort(descriptorIndex);
out.writeShort(length);
for(int index = 0; index < length; index++) {
((CodeAttribute) attributes.get(index)).writeExternal(out);
}//for//
}//writeExternal()//
}//Method//

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,276 @@
package com.de22.javabytecode.attribute;
import com.common.io.StreamSupport;
import com.common.util.*;
import com.de22.javabytecode.*;
import com.de22.javabytecode.constant.ConstantUtf8;
/**
* Copyright Declarative Engineering LLC 1999,2006<p>
*/
public class Code extends CodeAttribute {
private short maxStack = 0;
private short maxLocals = 0;
private byte[] code = null;
private IList exceptions = null;
private IList attributes = null;
public static final String DEFAULT_NAME = "Code";
/**
* Copyright Declarative Engineering LLC 1999<p>
*/
public static class CodeException {
public short startPc = 0;
public short endPc = 0;
public short handlerPc = 0;
/** A reference into the constant pool to a ClassConstant. */
public short catchType = 0;
public CodeException() {
}//CodeException()//
public CodeException(short startPc, short endPc, short handlerPc, short catchType) {
this.startPc = startPc;
this.endPc = endPc;
this.handlerPc = handlerPc;
this.catchType = catchType;
}//CodeException()//
}//CodeException//
/**
* Code constructor.
* @param type The class this constant is a member of.
*/
public Code(Type type) {
super(type);
}//Code()//
/**
* Code constructor.
* @param type The class this constant is a member of.
*/
public Code(Type type, byte[] codeBytes, short maxStack, short maxLocals) {
super(type);
this.maxLocals = maxLocals;
this.maxStack = maxStack;
this.code = codeBytes;
}//Code()//
/**
* Gets the number of defined exception handlers.
* @return The count of exception handler metadata for the code.
*/
public int getExceptionCount() {
return exceptions == null ? 0 : exceptions.getSize();
}//getExceptionCount()//
/**
* Gets the exception metadata at the given zero based index.
* @param index The zero based index of the exception to be retrieved.
* @return The code exception metadata.
*/
public CodeException getException(int index) {
return (CodeException) exceptions.get(index);
}//getException()//
/**
* Adds an attribute to the method.
* An attribute describes some property of the method.
* @param attribute The attribute to add to the method. The attribute's name will automatically be added to the constant pool.
* @return The index of the attribute in the attribute pool.
*/
public short addAttribute(CodeAttribute attribute) {
short nameIndex = getType().addConstant(new ConstantUtf8(getType(), attribute.getDefaultName()), false);
attribute.setNameIndex(nameIndex);
attributes.add(attribute);
return (short) (attributes.getSize() - 1);
}//addAttribute()//
/**
* Gets the attribute referenced by the index.
* <p>Warning: This is a one based index, but the method to get the count will return the actual number of values.</p>
* @param index The one based index of the field to retrieve.
* @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index.
*/
public CodeAttribute getAttribute(short index) {
int constant = index - 1;
return (CodeAttribute) attributes.get(constant);
}//getAttribute()//
/**
* Removes the attribute referenced by the index.
* <p>Warning: This is a one based index, but the method to get the count will return the actual number of values.</p>
* @param index The one based index of the field to remove.
* @return The attribute at the index. An array index out of bounds exception will be thrown if there is not an attribute at that index.
*/
public CodeAttribute removeAttribute(short index) {
int constant = index - 1;
return (CodeAttribute) attributes.remove(constant);
}//getAttribute()//
/**
* Gets the count of attributes associated with the type.
* @return The number of attributes for this type.
*/
public int getAttributeCount() {
return attributes == null ? 0 : attributes.getSize();
}//getAttributeCount()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
int length = 12 + (code != null ? code.length : 0) + (exceptions != null ? exceptions.getSize() * 8 : 0);
if(attributes != null) {
for(int index = 0; index < attributes.getSize(); index++) {
CodeAttribute next = (CodeAttribute) attributes.get(index);
length += next.getSize() + 6; //Add 6 because each attribute is preceeded by a 2b name index, and a 4b total length which are not included in the size reported by the attribute.//
}//while//
}//if//
return length;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
int exceptionCount;
int attributeCount;
super.readExternal(in);
int size = in.readInt(); //Read the size of the attribute (totalLength).//
maxStack = in.readShort();
maxLocals = in.readShort();
code = new byte[in.readInt()];
if(StreamSupport.readBytes(in, code) != code.length) {
new RuntimeException("Error: Bad code size.");
}//if//
//in.read(code);
exceptionCount = in.readShort();
if(exceptionCount != 0) {
exceptions = new LiteList(exceptionCount, 10);
//while(exceptionCount-- != 0) {
for(int index = 0; index < exceptionCount; index++) {
exceptions.add(new CodeException(in.readShort(), in.readShort(), in.readShort(), in.readShort()));
}//while//
}//if//
attributeCount = in.readShort();
if(attributeCount > 0) {
attributes = new LiteList(attributeCount, 10);
//while(attributeCount-- != 0) {
for(int index = 0; index < attributeCount; index++) {
attributes.add(CodeAttribute.readAttribute(getType(), in));
}//while//
}//if//
//Test the getSize() method.//
if(size != getSize()) {
new RuntimeException("Error: Bad size: " + getSize()).printStackTrace();
}//if//
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIterator iterator = null;
appendTabs(buffer, tabCount);
buffer.append("Code CodeAttribute (MaxStack=");
buffer.append(maxStack);
buffer.append(" MaxLocals=");
buffer.append(maxLocals);
buffer.append(')');
buffer.append(' ');
buffer.append('{');
appendEndOfLine(buffer);
if(attributes != null) {
iterator = attributes.iterator();
while(iterator.hasNext()) {
CodeAttribute attribute = (CodeAttribute) iterator.next();
attribute.toString(buffer, tabCount + 1);
}//while//
}//if//
if(exceptions != null) {
iterator = exceptions.iterator();
while(iterator.hasNext()) {
CodeException exception = (CodeException) iterator.next();
appendTabs(buffer, tabCount + 1);
buffer.append("Exception (startPc=");
buffer.append(exception.startPc);
buffer.append(" endPc=");
buffer.append(exception.endPc);
buffer.append(" handlerPc=");
buffer.append(exception.handlerPc);
buffer.append(" catchType=");
buffer.append(exception.catchType);
buffer.append(')');
appendEndOfLine(buffer);
}//while//
}//if//
if(code != null) {
appendTabs(buffer, tabCount);
buffer.append("Code\t[");
appendEndOfLine(buffer);
buffer.append(com.de22.javabytecode.code.FormatSupport.formatCode(getType(), code, tabCount + 1));
appendTabs(buffer, tabCount + 1);
buffer.append("]");
appendEndOfLine(buffer);
}//if//
appendTabs(buffer, tabCount);
buffer.append('}');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
int exceptionsLength = exceptions != null ? exceptions.getSize() : 0;
int attributesLength = attributes != null ? attributes.getSize() : 0;
super.writeExternal(out);
out.writeShort(maxStack);
out.writeShort(maxLocals);
out.writeInt(code.length);
out.write(code);
out.writeShort((short) exceptionsLength);
for(int index = 0; index < exceptionsLength; index++) {
CodeException codeException = (CodeException) exceptions.get(index);
out.writeShort(codeException.startPc);
out.writeShort(codeException.endPc);
out.writeShort(codeException.handlerPc);
out.writeShort(codeException.catchType);
}//for//
out.writeShort((short) attributesLength);
for(int index = 0; index < attributesLength; index++) {
((CodeAttribute) attributes.get(index)).writeExternal(out);
}//for//
}//writeExternal()//
}//Code//

View File

@@ -0,0 +1,78 @@
package com.de22.javabytecode.attribute;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* Used by fields to represent a constant that the field will be initialized to.
*/
public class ConstantValue extends CodeAttribute {
private short constantIndex = 0;
public static final String DEFAULT_NAME = "ConstantValue";
/**
* ConstantValue constructor.
* @param type The class this constant is a member of.
*/
public ConstantValue(Type type) {
super(type);
}//ConstantValue()//
/**
* Gets the index of the constant being referenced.
* @return The constant referenced by this code attribue.
*/
public short getConstantIndex() {
return constantIndex;
}//getConstantIndex()//
/**
* Sets the index of the constant being referenced.
* @param constantIndex The constant referenced by this code attribue.
*/
public void setConstantIndex(short constantIndex) {
this.constantIndex = constantIndex;
}//setConstantIndex()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
super.readExternal(in);
in.readInt(); //Read the size of the attribute.//
constantIndex = in.readShort();
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Constant CodeAttribute (ConstantIndex=");
buffer.append(constantIndex);
buffer.append(" Value=[ ");
buffer.append(getType().getConstant(constantIndex));
buffer.append(" ])");
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
super.writeExternal(out);
out.writeShort(constantIndex);
}//writeExternal()//
}//ConstantValue//

View File

@@ -0,0 +1,92 @@
package com.de22.javabytecode.attribute;
import com.common.util.optimized.*;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* Maintains the exceptions thrown by a method?
*/
public class ExceptionIndexes extends CodeAttribute {
private IntArray indexes = new IntArray(10, 40);
public static final String DEFAULT_NAME = "Exceptions";
/**
* ExceptionIndexes constructor.
* @param type The class this constant is a member of.
*/
public ExceptionIndexes(Type type) {
super(type);
}//ExceptionIndexes()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2 + (indexes != null ? indexes.getSize() * 2 : 0);
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
short indexCount = 0;
super.readExternal(in);
in.readInt(); //Read the size of the attribute.//
indexCount = in.readShort();
while(indexCount-- != 0) {
indexes.add((int) in.readShort());
}//while//
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIntIterator iterator = indexes.iterator();
appendTabs(buffer, tabCount);
buffer.append("Exception Indexes (");
while(iterator.hasNext()) {
int index = iterator.next();
buffer.append(index);
if(iterator.hasNext()) {
buffer.append(',');
buffer.append(' ');
}//if//
}//while//
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
super.writeExternal(out);
if(indexes != null) {
int length = indexes.getSize();
out.writeShort((short) length);
for(int index = 0; index < length; index++) {
out.writeShort((short) indexes.get(index));
}//for//
}//if//
else {
out.writeShort((short) 0);
}//else//
}//writeExternal()//
}//ExceptionIndexes//

View File

@@ -0,0 +1,143 @@
package com.de22.javabytecode.attribute;
import com.common.util.IIterator;
import com.common.util.IList;
import com.common.util.LiteList;
import com.de22.javabytecode.CodeAttribute;
import com.de22.javabytecode.Type;
/**
* Copyright Declarative Engineering LLC 2007<p>
*/
public class InnerClasses extends CodeAttribute {
public static final String DEFAULT_NAME = "InnerClasses";
private IList innerClasses = null;
/**
* Identifies a single line number.
*/
public static class InnerClass {
/** References the class constant in the constant pool for the inner class. */
public short innerClassInfo = 0;
/** References the class constant in the constant pool for the outer class. */
public short outerClassInfo = 0;
/** References the name of the inner class in the constant pool. */
public short innerNameIndex = 0;
/** The modifiers for the inner class. */
public short innerClassAccessFlags = 0;
public InnerClass() {
}//InnerClass()//
public InnerClass(short innerClassInfo, short outerClassInfo, short innerNameIndex, short innerClassAccessFlags) {
this.innerClassInfo = innerClassInfo;
this.outerClassInfo = outerClassInfo;
this.innerNameIndex = innerNameIndex;
this.innerClassAccessFlags = innerClassAccessFlags;
}//InnerClass()//
}//InnerClass//
/**
* InnerClasses constructor.
* @param type
*/
public InnerClasses(Type type) {
super(type);
}//InnerClasses()//
/**
* Gets the count of inner classes.
* @return The number of inner classes defined in this code attribute.
*/
public int getInnerClassesCount() {
return innerClasses.getSize();
}//getInnerClassesCount()//
/**
* Gets the inner class data at the given zero based index.
* @param index The zero based index of the inner class.
* @return The inner class data.
*/
public InnerClass getInnerClass(int index) {
return (InnerClass) innerClasses.get(index);
}//getInnerClass()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2 + (innerClasses != null ? innerClasses.getSize() * 8 : 0);
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
int innerClassCount;
super.readExternal(in);
in.readInt(); //Read the size of the attribute.//
innerClassCount = in.readShort();
innerClasses = new LiteList(innerClassCount == 0 ? 1 : innerClassCount, 10);
while(innerClassCount-- > 0) {
innerClasses.add(new InnerClass(in.readShort(), in.readShort(), in.readShort(), in.readShort()));
}//while//
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIterator iterator = null;
if(innerClasses != null) {
iterator = innerClasses.iterator();
appendTabs(buffer, tabCount);
buffer.append("InnerClasses {");
appendEndOfLine(buffer);
while(iterator.hasNext()) {
InnerClass innerClass = (InnerClass) iterator.next();
appendTabs(buffer, tabCount + 1);
buffer.append("LocalVariable (innerClassInfo=");
buffer.append(innerClass.innerClassInfo);
buffer.append(" outerClassInfo=");
buffer.append(innerClass.outerClassInfo);
buffer.append(" innerNameIndex=");
buffer.append(innerClass.innerNameIndex);
buffer.append(" innerClassAccessFlags=");
buffer.append(innerClass.innerClassAccessFlags);
buffer.append(")");
appendEndOfLine(buffer);
}//while//
appendTabs(buffer, tabCount);
buffer.append('}');
appendEndOfLine(buffer);
}//if//
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
short length = (short) (innerClasses != null ? innerClasses.getSize() : 0);
super.writeExternal(out);
out.writeShort(length);
for(int index = 0; index < length; index++) {
InnerClass innerClass = (InnerClass) innerClasses.get(index);
out.writeShort(innerClass.innerClassInfo);
out.writeShort(innerClass.outerClassInfo);
out.writeShort(innerClass.innerNameIndex);
out.writeShort(innerClass.innerClassAccessFlags);
}//for//
}//writeExternal()//
}//InnerClasses//

View File

@@ -0,0 +1,115 @@
package com.de22.javabytecode.attribute;
import com.common.util.*;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* References a constant in the constant pool?
*/
public class LineNumberTable extends CodeAttribute {
public static final String DEFAULT_NAME = "LineNumberTable";
private IList lineNumbers = null;
/**
* Identifies a single line number.
*/
private static class LineNumber {
public short startPc = 0;
public short lineNumber = 0;
public LineNumber() {
}//LineNumber()//
public LineNumber(short startPc, short lineNumber) {
this.startPc = startPc;
this.lineNumber = lineNumber;
}//LineNumber()//
}//LineNumber//
/**
* ConstantValue constructor.
* @param type The class this constant is a member of.
*/
public LineNumberTable(Type type) {
super(type);
}//ConstantValue()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2 + (lineNumbers != null ? lineNumbers.getSize() * 4 : 0);
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
short length = 0;
super.readExternal(in);
in.readInt(); //Read the size of the attribute.//
length = in.readShort();
if(length > 0) {
lineNumbers = new LiteList(length, 10);
}//if//
while(length-- != 0) {
lineNumbers.add(new LineNumber(in.readShort(), in.readShort()));
}//while//
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIterator iterator = null;
if(lineNumbers != null) {
iterator = lineNumbers.iterator();
appendTabs(buffer, tabCount);
buffer.append("LineNumbers {");
appendEndOfLine(buffer);
while(iterator.hasNext()) {
LineNumber lineNumber = (LineNumber) iterator.next();
appendTabs(buffer, tabCount + 1);
buffer.append("LineNumber (startPc=");
buffer.append(lineNumber.startPc);
buffer.append(" lineNumber=");
buffer.append(lineNumber.lineNumber);
buffer.append(")");
appendEndOfLine(buffer);
}//while//
appendTabs(buffer, tabCount);
buffer.append('}');
appendEndOfLine(buffer);
}//if//
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
short length = (short) (lineNumbers != null ? lineNumbers.getSize() : 0);
super.writeExternal(out);
out.writeShort(length);
for(int index = 0; index < length; index++) {
LineNumber lineNumber = (LineNumber) lineNumbers.get(index);
out.writeShort(lineNumber.startPc);
out.writeShort(lineNumber.lineNumber);
}//for//
}//writeExternal()//
}//ConstantValue//

View File

@@ -0,0 +1,148 @@
package com.de22.javabytecode.attribute;
import com.common.util.*;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* References a constant in the constant pool?
*/
public class LocalVariableTable extends CodeAttribute {
private IList localVariables = null;
public static final String DEFAULT_NAME = "LocalVariableTable";
/**
* Identifies a single local variable.
*/
public static class LocalVariable {
public short startPc = 0;
public short variableLength = 0;
public short nameIndex = 0;
public short descriptorIndex = 0;
public short index = 0;
public LocalVariable() {
}//LocalVariable()//
public LocalVariable(short startPc, short variableLength, short nameIndex, short descriptorIndex, short index) {
this.startPc = startPc;
this.variableLength = variableLength;
this.nameIndex = nameIndex;
this.descriptorIndex = descriptorIndex;
this.index = index;
}//LocalVariable()//
}//LocalVariable//
/**
* ConstantValue constructor.
* @param type The class this constant is a member of.
*/
public LocalVariableTable(Type type) {
super(type);
}//ConstantValue()//
/**
* Gets the number of local variables in the table.
* @return The number of local variables.
*/
public int getLocalVariableCount() {
return localVariables != null ? localVariables.getSize() : 0;
}//getLocalVariableCount()//
/**
* Gets the desired local variable metadata.
* @param index The zero based index of the desired local variable.
* @return The local variable.
*/
public LocalVariable getLocalVariable(int index) {
return (LocalVariable) localVariables.get(index);
}//getLocalVariable()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2 + (localVariables != null ? localVariables.getSize() * 10 : 0);
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
short length = 0;
super.readExternal(in);
in.readInt(); //Read the size of the attribute.//
length = in.readShort();
if(length > 0) {
localVariables = new LiteList(length, 10);
}//if//
while(length-- != 0) {
localVariables.add(new LocalVariable(in.readShort(), in.readShort(), in.readShort(), in.readShort(), in.readShort()));
}//while//
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
IIterator iterator = null;
if(localVariables != null) {
iterator = localVariables.iterator();
appendTabs(buffer, tabCount);
buffer.append("Local Variables {");
appendEndOfLine(buffer);
while(iterator.hasNext()) {
LocalVariable localVariable = (LocalVariable) iterator.next();
appendTabs(buffer, tabCount + 1);
buffer.append("LocalVariable (startPc=");
buffer.append(localVariable.startPc);
buffer.append(" variableLength=");
buffer.append(localVariable.variableLength);
buffer.append(" nameIndex=");
buffer.append(localVariable.nameIndex);
buffer.append(" descriptorIndex=");
buffer.append(localVariable.descriptorIndex);
buffer.append(" name='");
buffer.append(getType().getConstant(localVariable.nameIndex));
buffer.append("' type='");
buffer.append(getType().getConstant(localVariable.descriptorIndex));
buffer.append("' ?index?=");
buffer.append(localVariable.index);
buffer.append(")");
appendEndOfLine(buffer);
}//while//
appendTabs(buffer, tabCount);
buffer.append('}');
appendEndOfLine(buffer);
}//if//
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
short length = (short) (localVariables != null ? localVariables.getSize() : 0);
super.writeExternal(out);
out.writeShort(length);
for(int index = 0; index < length; index++) {
LocalVariable localVariable = (LocalVariable) localVariables.get(index);
out.writeShort(localVariable.startPc);
out.writeShort(localVariable.variableLength);
out.writeShort(localVariable.nameIndex);
out.writeShort(localVariable.descriptorIndex);
out.writeShort(localVariable.index);
}//for//
}//writeExternal()//
}//ConstantValue//

View File

@@ -0,0 +1,78 @@
package com.de22.javabytecode.attribute;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* A reference to the source file name associated with the class file.
*/
public class SourceFile extends CodeAttribute {
private short sourceFileIndex = 0;
public static final String DEFAULT_NAME = "SourceFile";
/**
* SourceFile constructor.
* @param type The class this constant is a member of.
*/
public SourceFile(Type type) {
super(type);
}//SourceFile()//
/**
* Gets the index in the constant pool of the source file's name.
* @return The index to the source file name constant (UTF8) in the constant pool.
*/
public short getSourceFileIndex() {
return sourceFileIndex;
}//getSourceFileIndex()//
/**
* Sets the index in the constant pool of the source file's name.
* @param sourceFileIndex The index to the source file name constant (UTF8) in the constant pool.
*/
public void setSourceFileIndex(short sourceFileIndex) {
this.sourceFileIndex = sourceFileIndex;
}//setSourceFileIndex()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
super.readExternal(in);
in.readInt(); //Read the size of the attribute.//
sourceFileIndex = in.readShort();
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Source File Reference CodeAttribute (sourceFileIndex=");
buffer.append(sourceFileIndex);
buffer.append(" fileName='");
buffer.append(getType().getConstant(sourceFileIndex));
buffer.append("')");
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
super.writeExternal(out);
out.writeShort(sourceFileIndex);
}//writeExternal()//
}//SourceFile//

View File

@@ -0,0 +1,58 @@
package com.de22.javabytecode.attribute;
import com.de22.javabytecode.CodeAttribute;
import com.de22.javabytecode.Type;
/**
* Copyright Declarative Engineering LLC 2007<p>
*/
public class Synthetic extends CodeAttribute {
public static final String DEFAULT_NAME = "Synthetic";
/**
* Synthetic constructor.
* @param type The class this constant is a member of.
*/
public Synthetic(Type type) {
super(type);
}//Synthetic()//
/* (non-Javadoc)
* @see com.de22.javabytecode.CodeAttribute#getDefaultName()
*/
public String getDefaultName() {
return DEFAULT_NAME;
}//getDefaultName()//
/* (non-Javadoc)
* @see com.de22.javabytecode.CodeAttribute#getSize()
*/
public int getSize() {
return 0;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
int length = -1;
super.readExternal(in);
//Should always be zero.//
length = in.readInt();
in.skip(length);
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Constant Synthetic");
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
super.writeExternal(out);
}//writeExternal()//
}//Synthetic//

View File

@@ -0,0 +1,83 @@
package com.de22.javabytecode.attribute;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class Unidentified extends CodeAttribute {
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private String attributeName = null;
/** The unidentified data. This may never be null. */
private byte[] data = EMPTY_BYTE_ARRAY;
/**
* Unidentified constructor.
* @param type The class this constant is a member of.
* @param attributeName The name of the unidentified attribute (normally the name would select a different class).
*/
public Unidentified(Type type, String attributeName) {
super(type);
this.attributeName = attributeName;
}//Unidentified()//
/**
* Gets the name of the unidentified attribute.
* @return The attribute's name which identifies what the attribute data means.
*/
public String getAttributeName() {
return attributeName;
}//getAttributeName()//
/**
* Gets the attribute's default name as it is stored in the class bytes.
* @return The default name identifying the attribute's type.
*/
public String getDefaultName() {
return attributeName;
}//getDefaultName()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return data.length;
}//getSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
int length = -1;
int readCount = 0;
super.readExternal(in);
length = in.readInt(); //Read the size of the attribute.//
data = new byte[length]; //Create the data array.//
//Read the data.//
while(readCount != data.length) {
readCount += in.read(data, readCount, data.length - readCount);
}//while//
}//readExternal()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Unidentified CodeAttribute (name=");
buffer.append(attributeName);
buffer.append(" Size=");
buffer.append(data.length);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
super.writeExternal(out);
out.write(data);
}//writeExternal()//
}//Unidentified//

View File

@@ -0,0 +1,646 @@
package com.de22.javabytecode.code;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import com.common.io.*;
import com.common.util.*;
import com.common.util.optimized.IntArray;
import com.common.debug.*;
import com.de22.javabytecode.*;
import com.de22.javabytecode.Type.TypeMetadata;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class FormatSupport {
private static final int LINE_SPACING = 12;
private static final int SHORT_LINE_DESCRIPTION_SPACING = 32;
private static final int LINE_DESCRIPTION_SPACING = 36;
private static final boolean DISPLAY_PARAMETER_BYTES = false;
private static final char FILE_SEPARATOR = System.getProperty("file.separator").charAt(0);
private static final char[] hexCharacters = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/**
* FormatSupport constructor.
*/
public FormatSupport() {
super();
}//FormatSupport()//
/**
* Appends the byte to the buffer as a hex string.
* @param value The byte value to append.
* @param buffer The string buffer append to.
*/
public static void appendByteAsHex(byte value, StringBuffer buffer) {
byte highBits = (byte) ((value >> 4) & 0x0F);
byte lowBits = (byte) (value & 0x0F);
buffer.append(hexCharacters[highBits]);
buffer.append(hexCharacters[lowBits]);
}//appendByteAsHex()//
/**
* Adds the specified number of tabs to the buffer.
* @param tabCount The number of tabs to append.
* @param buffer The string buffer to add the tabs to.
*/
public static void appendTabs(int tabCount, StringBuffer buffer) {
while(tabCount-- != 0) {
buffer.append('\t');
}//while//
}//appendTabs()//
/**
* Formats the hex codes of a class file so that they may be easily read by humans.
* @param type The type metadata used to access the constant pool.
* @param codes The array of all class bytes. If the byte codes are not properly formatted then this method may not be able to format everything and will return what was formatted.
* @param tabLevel How many tabs to add to the beginning of every line. Any non-negative value may be used.
* @return The formatted code as a simple string.
*/
public static String formatCode(Type type, byte[] codes, int tabLevel) {
StringBuffer buffer = new StringBuffer(10000);
IList opCodes = OpCode.getOpCodes();
try {
for(int index = 0; index < codes.length; index++) {
int code = codes[index] & 0xFF;
String indexString = Integer.toString(index);
OpCode opCode = (OpCode) opCodes.get(code);
if(codes[index] == -86) { //switch statement//
int startingNumber;
int endingNumber;
int jumpOffset;
appendTabs(tabLevel, buffer);
buffer.append(" line " + indexString);
for(int t = indexString.length(); t < LINE_SPACING; t++) {buffer.append(' ');} //Space evenly//
buffer.append("0x");
appendByteAsHex(codes[index], buffer);
buffer.append(' ');
buffer.append(opCode.toString());
buffer.append('\r');
buffer.append('\n');
//Spaces//
while((++index) % 4 != 0) {
formatLine(codes[index], index, "Spacing", tabLevel, buffer);
}//while//
jumpOffset = StreamSupport.readInt(codes, index); //The default jump offset.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Default Jump Offset = " + jumpOffset, tabLevel, buffer);
startingNumber = StreamSupport.readInt(codes, index); //The first number in the switch statement.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Starting Value = " + startingNumber, tabLevel, buffer);
endingNumber = StreamSupport.readInt(codes, index); //The last number in the switch statement.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Ending Value = " + endingNumber, tabLevel, buffer);
for(int entryIndex = startingNumber; entryIndex <= endingNumber; entryIndex++) {
jumpOffset = StreamSupport.readInt(codes, index); //The default jump offset.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Jump Offset #" + entryIndex + " = " + jumpOffset, tabLevel, buffer);
}//for//
index--;
}//if//
else if(codes[index] == -85) { //lookup switch statement//
int numberOfCases;
int caseValue;
int caseOffset;
int defaultCaseOffset;
appendTabs(tabLevel, buffer);
buffer.append(" line ");
buffer.append(indexString);
for(int t = indexString.length(); t < LINE_SPACING; t++) {buffer.append(' ');} //Space evenly//
buffer.append("0x");
appendByteAsHex(codes[index], buffer);
buffer.append(' ');
buffer.append(opCode.toString());
buffer.append('\r');
buffer.append('\n');
//Spaces//
while((++index) % 4 != 0) {
formatLine(codes[index], index, "Spacing", tabLevel, buffer);
}//while//
defaultCaseOffset = StreamSupport.readInt(codes, index); //The default jump offset.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Default Jump Offset = " + defaultCaseOffset, tabLevel, buffer);
numberOfCases = StreamSupport.readInt(codes, index); //The first number in the switch statement.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Number of cases = " + numberOfCases, tabLevel, buffer);
for(int caseIndex = 0; caseIndex < numberOfCases; caseIndex++) {
caseValue = StreamSupport.readInt(codes, index); //The last number in the switch statement.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Case" + caseIndex + " value = " + caseValue, tabLevel, buffer);
caseOffset = StreamSupport.readInt(codes, index); //The last number in the switch statement.//
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "", tabLevel, buffer);
formatLine(codes[index], index++, "Case" + caseIndex + " offset = " + caseOffset, tabLevel, buffer);
}//for//
index--;
}//else if//
else {
int lineDataCharacterCount;
appendTabs(tabLevel, buffer);
lineDataCharacterCount = buffer.length();
buffer.append(" line ");
buffer.append(indexString);
for(int t = indexString.length(); t < LINE_SPACING; t++) {buffer.append(' ');} //Space evenly//
if(DISPLAY_PARAMETER_BYTES) {
buffer.append("0x");
appendByteAsHex(codes[index], buffer);
buffer.append(' ');
}//if//
buffer.append(opCode.getName());
lineDataCharacterCount = buffer.length() - lineDataCharacterCount + 1;
for(int t = lineDataCharacterCount; t < LINE_DESCRIPTION_SPACING; t++) {buffer.append(' ');} //Space evenly//
buffer.append(opCode.getDescription());
buffer.append('\r');
buffer.append('\n');
if(DISPLAY_PARAMETER_BYTES) {
for(int param = 0; param < opCode.getParameterByteDescriptions().getSize(); param++) {
indexString = new Integer(index + param + 1).toString();
code = (codes[index + param + 1] < 0 ? ((int) codes[index + param + 1]) + 256 : (int) codes[index + param + 1]);
appendTabs(tabLevel, buffer);
buffer.append(" line ");
buffer.append(indexString);
for(int t = indexString.length(); t < LINE_SPACING; t++) {buffer.append(' ');} //Space evenly//
buffer.append("0x");
appendByteAsHex(codes[index + param + 1], buffer);
buffer.append(" ");
buffer.append(opCode.getParameterByteDescriptions().get(param));
buffer.append('\r');
buffer.append('\n');
}//for//
}//if//
else {
int codeIndex = index + 1;
for(int param = 0; param < opCode.getParameterDescriptions().getSize(); param++) {
int paramType = opCode.getParameterTypes()[param];
long value = 0;
int paramByteCount;
int lineDisplayCharacterCount = 0;
boolean isConstantRef = false;
appendTabs(tabLevel, buffer);
lineDataCharacterCount = buffer.length();
switch(paramType) {
case OpCode.SHORT_CONSTANT_REF: {
value = (long) (codes[codeIndex] & 0xFF);
//if(((short) value) < 0) {
// buffer.append(type.getConstant((short) value));
//}
paramByteCount = 1;
isConstantRef = true;
break;
}//case//
case OpCode.CONSTANT_REF: {
value = (long) ((((codes[codeIndex] & 0xFF) << 8) | (codes[codeIndex + 1] & 0xFF)) & 0xFFFF);
//if(((short) value) < 0) {
// buffer.append(type.getConstant((short) value));
//}
paramByteCount = 2;
isConstantRef = true;
break;
}//case//
case OpCode.SIGNED_BYTE: {
value = (long) codes[codeIndex];
paramByteCount = 1;
break;
}//case//
case OpCode.UNSIGNED_BYTE: {
value = (long) (codes[codeIndex] & 0xFF);
paramByteCount = 1;
break;
}//case//
case OpCode.SIGNED_SHORT: {
value = (long) (((codes[codeIndex] & 0xFF) << 8) | (codes[codeIndex + 1] & 0xFF));
paramByteCount = 2;
break;
}//case//
case OpCode.UNSIGNED_SHORT: {
value = (long) ((((codes[codeIndex] & 0xFF) << 8) | (codes[codeIndex + 1] & 0xFF)) & 0xFFFF);
paramByteCount = 2;
break;
}//case//
case OpCode.SIGNED_INT: {
value = (long) (((codes[codeIndex] & 0xFF) << 24) | ((codes[codeIndex + 1] & 0xFF) << 16) | ((codes[codeIndex + 2] & 0xFF) << 8) | (codes[codeIndex + 3] & 0xFF));
paramByteCount = 4;
break;
}//case//
case OpCode.UNSIGNED_INT: {
value = (long) ((((codes[codeIndex] & 0xFF) << 24) | ((codes[codeIndex + 1] & 0xFF) << 16) | ((codes[codeIndex + 2] & 0xFF) << 8) | (codes[codeIndex + 3] & 0xFF)) & 0xFFFF);
paramByteCount = 4;
break;
}//case//
default:
throw new RuntimeException("Unexpected opcode parameter type.");
}//switch//
if(paramByteCount == 1) {
buffer.append(" line ");
lineDisplayCharacterCount = buffer.length();
buffer.append(codeIndex);
lineDisplayCharacterCount = buffer.length() - lineDisplayCharacterCount;
}//if//
else {
buffer.append(" lines ");
lineDisplayCharacterCount = buffer.length();
buffer.append(codeIndex);
buffer.append("-");
buffer.append(codeIndex + paramByteCount - 1);
lineDisplayCharacterCount = buffer.length() - lineDisplayCharacterCount + 1;
}//else//
for(int t = lineDisplayCharacterCount; t < LINE_SPACING; t++) {buffer.append(' ');} //Space evenly//
buffer.append(value);
lineDataCharacterCount = buffer.length() - lineDataCharacterCount + 1;
if(isConstantRef) {
for(int t = lineDataCharacterCount; t < SHORT_LINE_DESCRIPTION_SPACING; t++) {buffer.append(' ');} //Space evenly//
buffer.append('{');
buffer.append(type.getConstant((short) value).getPrettyValue());
buffer.append('}');
buffer.append(' ');
}//if//
else {
for(int t = lineDataCharacterCount; t < LINE_DESCRIPTION_SPACING; t++) {buffer.append(' ');} //Space evenly//
}//else//
buffer.append(opCode.getParameterDescriptions().get(param));
buffer.append('\r');
buffer.append('\n');
codeIndex += paramByteCount;
}//for//
}//else//
index += opCode.getParameterByteDescriptions().getSize();
}//else//
}//for//
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
return buffer.toString();
}//formatCode()//
/**
* Will format a descriptor string using the parameters and return type of the method.
* This is used to create method descriptors for a class file.
* <p>Example: void methodName(double[] a, String b) -> ([DLjava/lang/String;)V;
* @param returnType The descriptor's return type.
* @param parameterTypes The descriptor's parameter types (in order of parameter).
* @param buffer The buffer to write the output to.
*/
public static void formatDescriptor(Class returnType, Class[] parameterTypes, StringBuffer buffer) {
buffer.append('(');
if(parameterTypes != null) {
for(int index = 0; index < parameterTypes.length; index++) {
formatType(parameterTypes[index], buffer);
}//for//
}//if//
buffer.append(')');
formatType(returnType, buffer);
}//formatDescriptor()//
/**
* Used to format a line when outputing the interperated class file's hex codes.
*/
public static void formatLine(byte code, int index, String message, int tabLevel, StringBuffer buffer) {
String indexString = new Integer(index).toString();
appendTabs(tabLevel, buffer);
buffer.append(" line ");
buffer.append(indexString);
for(int t = indexString.length(); t < 4; t++) {buffer.append(' ');} //Space evenly//
appendByteAsHex(code, buffer);
buffer.append(' ');
buffer.append(message);
buffer.append('\r');
buffer.append('\n');
}//formatLine()//
/**
* Formats a non-primitive class to a class file compatible string.
* <p>NOTE: This method will not place an "L" at the beginning or a ";" at the end of the formatted string.
* @param type Class The non-primitive class to convert to a string.
* @param buffer The buffer to write the string to.
*/
public static void formatNonPrimitiveType(Class type, StringBuffer buffer) {
formatNonPrimitiveType(type.getName(), buffer);
}//formatNonPrimitiveType()//
/**
* Formats a non-primitive class to a class file compatible string.
* <p>NOTE: This method will not place an "L" at the beginning or a ";" at the end of the formatted string.
* @param type The non-primitive class to convert to a string.
* @param buffer The buffer to write the string to.
*/
public static void formatNonPrimitiveType(String qualifiedTypeName, StringBuffer buffer) {
StringTokenizer tokenizer = new StringTokenizer(qualifiedTypeName, ".");
boolean isFirst = true;
while(tokenizer.hasMoreTokens()) {
if(!isFirst) {
buffer.append('/');
}//if//
else {
isFirst = false;
}//else//
buffer.append(tokenizer.nextToken());
}//while//
}//formatNonPrimitiveType()//
/**
* Formats a class to a class file compatible string.
* @param type The class to convert to a string.
* @param buffer The buffer to write the output to.
*/
public static void formatType(Class type, StringBuffer buffer) {
if(type != null) {
while(type.isArray()) {
buffer.append('[');
type = type.getComponentType();
}//while//
}//if//
if((type == null) || (type.equals(Void.TYPE))) {
buffer.append('V');
}//if//
else if(type.isPrimitive()) {
if(type.equals(Integer.TYPE)) {
buffer.append('I');
}//if//
else if(type.equals(Byte.TYPE)) {
buffer.append('B');
}//else if//
else if(type.equals(Character.TYPE)) {
buffer.append('C');
}//else if//
else if(type.equals(Short.TYPE)) {
buffer.append('S');
}//else if//
else if(type.equals(Boolean.TYPE)) {
buffer.append('Z');
}//else if//
else if(type.equals(Double.TYPE)) {
buffer.append('D');
}//else if//
else if(type.equals(Float.TYPE)) {
buffer.append('F');
}//else if//
else if(type.equals(Long.TYPE)) {
buffer.append('J');
}//else if//
}//else if//
else {
buffer.append('L');
formatNonPrimitiveType(type.getName(), buffer);
buffer.append(';');
}//else//
}//formatType()//
/**
* Reverse engineers a class file and prints the output to the console.
* @param args The array of initialization parameters.
* args[0] = The path and file name of the class or jar or path to a class file directory to reverse engineer.
* args[1] = The optional path (must exist) where the output will be stored. If the files exist they will be over written. If not specified the output will go to the console.
*/
public static void main(String[] args) {
String debugText = null;
long t = System.currentTimeMillis();
try {
File file = new File(args[0]);
File path = args.length > 1 ? new File(args[1]) : null;
if(path != null && (path.isFile() || (!path.exists() && !path.mkdirs()))) {
path = null;
}//if//
if(file.isDirectory()) {
LiteList directoryStack = new LiteList(10, 20);
LiteList listingStack = new LiteList(10, 20);
IntArray listingIndexStack = new IntArray(10, 20);
File directory = file;
File[] files = directory.listFiles();
for(int index = 0; index < files.length; index++) {
if(files[index].isDirectory()) {
File[] subfiles = files[index].listFiles();
if(subfiles.length > 0) {
directoryStack.add(directory);
listingStack.add(files);
listingIndexStack.add(index);
directory = files[index];
files = subfiles;
index = 0;
}//if//
}//if//
else if(files[index].getName().endsWith(".class")) {
debugText = files[index].getPath();
processClassFile(new FileInputStream(files[index]), path);
}//else if//
if((index == files.length - 1) && (directoryStack.getSize() > 0)) {
directory = (File) directoryStack.remove(directoryStack.getSize() - 1);
files = (File[]) listingStack.remove(listingStack.getSize() - 1);
index = listingIndexStack.remove(listingIndexStack.getSize() - 1);
}//if//
}//for//
}//if//
else if(file.getName().endsWith(".class")) {
debugText = file.getPath();
byte[] bytes = StreamSupport.readBytes(new FileInputStream(file));
processClassFile(new ByteArrayInputStream(bytes), path);
}//else if//
else if(file.getName().endsWith(".jar") || file.getName().endsWith(".zip")) {
ZipFile zip = null;
Enumeration enumeration = null;
if(file.getName().endsWith("jar")) {
zip = new JarFile(file, false, JarFile.OPEN_READ);
}//if//
else {
zip = new ZipFile(file, ZipFile.OPEN_READ);
}//else//
try {
enumeration = zip.entries();
while(enumeration.hasMoreElements()) {
ZipEntry entry = (ZipEntry) enumeration.nextElement();
if(!entry.isDirectory()) {
if(entry.getName().endsWith(".class")) {
InputStream in = zip.getInputStream(entry);
byte[] bytes = new byte[in.available()];
ByteArrayInputStream bin;
int readCount = 0;
debugText = entry.getName();
while(readCount < bytes.length) {
readCount += in.read(bytes, readCount, bytes.length - readCount);
}//while//
//Convert the zip input stream to a byte array stream.//
bin = new ByteArrayInputStream(bytes);
processClassFile(bin, path);
in.close();
}//if//
}//if//
}//while//
}//try//
finally {
zip.close();
}//finally//
}//else if//
}//try//
catch(Throwable e) {
Debug.log(e, "Caught while processing the class file: " + debugText);
}//catch//
Debug.log("Total time (milliseconds): " + (System.currentTimeMillis() - t));
System.exit(0);
}//main()//
/**
* Processes a class file and writes out the byte codes in a semi-readable form.
* @param bytesIn The input stream containing the bytes codes. This stream will always be closed by this method.
* @param outputPath The optional path where the class output should be written to (under its packaging of course). The console will be used otherwise.
*/
private static void processClassFile(InputStream bytesIn, File outputPath) throws Throwable {
StringBuffer buffer = null;
ObjectInputStream in = null;
Type type = null;
try {
File outputFile = null;
TypeMetadata metadata = null;
in = new ObjectInputStream(bytesIn, null, null);
buffer = new StringBuffer(5000);
type = new Type();
type.readExternal(in);
type.toString(buffer, 0);
metadata = type.collectMetadata();
if(outputPath != null) {
String fileName = metadata.getTypeName().replace('.', FILE_SEPARATOR) + ".txt";
String directoryName = fileName.lastIndexOf(FILE_SEPARATOR) != -1 ? fileName.substring(0, fileName.lastIndexOf(FILE_SEPARATOR)) : "";
File outputDirectory = new File(outputPath, directoryName);
outputFile = new File(outputPath, fileName);
if(!outputDirectory.exists()) {
outputDirectory.mkdirs();
}//if//
if(!outputFile.exists()) {
outputFile.createNewFile();
}//if//
}//if//
if(outputFile == null) {
Debug.log(buffer.toString());
}//if//
else {
FileOutputStream fout = null;
try {
fout = new FileOutputStream(outputFile.getAbsolutePath(), false);
fout.write(buffer.toString().getBytes());
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
finally {
if(fout != null) {
try {
fout.close();
}//try//
catch(Throwable e) {
//Ignored.//
}//catch//
}//if//
}//finally//
}//else//
}//try//
catch(Throwable e) {
//Fill in as much of the buffer as we can so we can have some kind of output.//
if((type != null) && (buffer.length() == 0)) {
try {
type.toString(buffer, 0);
}//try//
catch(Throwable e2) {
//Ignore//
}//catch//
}//if//
System.out.println(buffer);
throw e;
}//catch//
finally {
if(in != null) {
try {
in.close();
}//try//
catch(Throwable e) {
}//catch//
}//if//
if(bytesIn != null) {
try {
bytesIn.close();
}//try//
catch(Throwable e) {
}//catch//
}//if//
}//finally//
}//processClassFile()//
}//FormatSupport//

View File

@@ -0,0 +1,672 @@
package com.de22.javabytecode.code;
import java.io.IOException;
import com.common.debug.*;
import com.common.io.StandardOutputStream;
import com.de22.javabytecode.*;
import com.de22.javabytecode.util.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* Supports method building.
*/
public class MethodSupport {
public static final int I = 0; //Integer
public static final int L = 1; //Long
public static final int F = 2; //Float
public static final int D = 3; //Double
public static final int A = 4; //Object
public static final byte INVOKE_INTERFACE = 1;
public static final byte INVOKE_VIRTUAL = 2;
public static final byte INVOKE_SPECIAL = 3;
public static final byte INVOKE_STATIC = 4;
private Type type = null;
/**
* MethodSupport constructor.
*/
private MethodSupport() {
super();
}//MethodSupport()//
/**
* MethodSupport constructor.
*/
public MethodSupport(Type type) {
super();
this.type = type;
}//MethodSupport()//
/**
* Casts the item on the top of the stack to the desired type.
* The stack size is unaffected.
* @param typeIndex The index of the cast type in the ConstantPool.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void cast(short typeIndex, StandardOutputStream out, StackTracker stack) throws IOException {
if(typeIndex != 0) {
out.writeByte((byte) 192); //checkcast
out.writeShort(typeIndex);
}//if//
}//cast()//
/**
* Pops two long values from the stack and compares them, and pushes the result on the stack.
* The stack is decremented by 4 and incremented by 1. The result is pushed on the stack as 1 where long1>long2, -1 where long1<long2, and 0 where long1==long2.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void compareLongs(StandardOutputStream out, StackTracker stack) throws IOException {
out.writeByte((byte) 148); //lcmp
stack.decrement(3);
}//compareLongs()//
/**
* Creates an array and pushes it on the stack.
* The array size is pushed on the stack and then popped off and the new array is pushed on the stack.
* @param arraySize The size of the array.
* @param arrayType The array's type which must be one of the TYPE_* identifiers defined in this class.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
* @see #TYPE_BOOLEAN
* @see #TYPE_BYTE
* @see #TYPE_CHAR
* @see #TYPE_SHORT
* @see #TYPE_INT
* @see #TYPE_FLOAT
* @see #TYPE_LONG
* @see #TYPE_DOUBLE
*/
public void createArray(int arraySize, byte arrayType, StandardOutputStream out, StackTracker stack) throws IOException {
push(arraySize, out, stack);
out.writeByte((byte) 188);
out.writeByte((byte) arrayType);
stack.increment();
}//createArray()//
/**
* Pops two int values from the stack and computes the remainder of dividing the first by the second i1 % i2 them, and pushes the result on the stack.
* The stack is decremented by 2 and incremented by 1.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void imod(StandardOutputStream out, StackTracker stack) throws IOException {
out.writeByte((byte) 112); //irem - Gets the remainder using: value1 % value2//
stack.decrement();
}//imod()//
/**
* Invokes the specified method using the object reference and arguments on the stack.
* <p>The caller should already have placed the object reference (except if this is a static method call) and parameters on the stack.<p>
* @param type The type object representing the compiling class.
* @param method The method being called.
* @param out The output stream for the class byte codes.
* @param stack The stack tracker that is keeping track of the current stack size.
* @return The number of of method return value words placed on the stack.
*/
public int invoke(java.lang.reflect.Method method, StandardOutputStream out, StackTracker stack) throws IOException {
Class[] parameters = method.getParameterTypes();
short methodIndex = type.addConstantMethod(method.getDeclaringClass(), method.getReturnType(), method.getName(), parameters);
int retVal = 0;
int argumentSize = 0;
for(int index = 0; index < parameters.length; index++) {
argumentSize += ((parameters[index].equals(Long.TYPE)) || (parameters[index].equals(Double.TYPE))) ? 2 : 1;
}//for//
if(method.getDeclaringClass().isInterface()) {
//Interface//
out.writeByte((byte) 185); //(-argumentSize -1 +returnValueSize) invokeinterface.//
out.writeShort((short) methodIndex);
out.writeByte((byte) (argumentSize + 1)); //The number of words to pull off the stack.//
out.writeByte((byte) 0); //Required to be 0.//
stack.decrement(argumentSize + 1);
}//if//
else if((method.getName().equals("<init>")) || (method.getName().equals("<cinit>")) || (java.lang.reflect.Modifier.isPrivate(method.getModifiers())) || (method.getClass().equals(type.getClass().getSuperclass()))) {
//Special//
out.writeByte((byte) 183); //(-argumentSize -1 +returnValueSize) invokevirtual.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize + 1);
}//else if//
else if(java.lang.reflect.Modifier.isStatic(method.getModifiers())) {
//Static//
out.writeByte((byte) 184); //(-argumentSize +returnValueSize) invokestatic.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize);
}//else if//
else {
//Virtual//
out.writeByte((byte) 182); //(-argumentSize -1 +returnValueSize) invokevirtual.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize + 1);
}//else//
//Increment the stack to reflect the methods return value.//
if((method.getReturnType().equals(Long.TYPE)) || (method.getReturnType().equals(Double.TYPE))) {
stack.increment(2);
retVal = 2;
}//if//
else if(!method.getReturnType().equals(Void.TYPE)) {
stack.increment();
retVal = 1;
}//else if//
return retVal;
}//invoke()//
/**
* Invokes the specified method on the class being built using the object reference and arguments on the stack.
* <p>The caller should already have placed the object reference (except if this is a static method call) and parameters on the stack.<p>
* @param methodName The name of the method being called.
* @param parameters The parameter types that the method defines.
* @param returnType The method's return type.
* @param out The output stream for the class byte codes.
* @param stack The stack tracker that is keeping track of the current stack size.
* @return The number of of method return value words placed on the stack.
*/
public int invokeSuper(String methodName, Class[] parameters, Class returnType, boolean isStatic, StandardOutputStream out, StackTracker stack) throws IOException {
short methodIndex = type.addConstantMethod(null, returnType, methodName, parameters);
int retVal = 0;
int argumentSize = 0;
for(int index = 0; index < parameters.length; index++) {
argumentSize += ((parameters[index].equals(Long.TYPE)) || (parameters[index].equals(Double.TYPE))) ? 2 : 1;
}//for//
if((methodName.equals("<init>")) || (methodName.equals("<cinit>")) || (!isStatic)) {
//Special//
out.writeByte((byte) 183); //(-argumentSize -1 +returnValueSize) invokespecial.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize + 1);
}//if//
else {
//Static//
out.writeByte((byte) 184); //(-argumentSize +returnValueSize) invokestatic.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize);
}//else//
//Increment the stack to reflect the methods return value.//
if((returnType.equals(Long.TYPE)) || (returnType.equals(Double.TYPE))) {
stack.increment(2);
retVal = 2;
}//if//
else if(!returnType.equals(Void.TYPE)) {
stack.increment();
retVal = 1;
}//else if//
return retVal;
}//invokeSuper()//
/**
* Invokes the specified method on the class being built using the object reference and arguments on the stack.
* <p>The caller should already have placed the object reference (except if this is a static method call) and parameters on the stack.<p>
* @param methodName The name of the method being called.
* @param parameters The parameter types that the method defines.
* @param returnType The method's return type.
* @param out The output stream for the class byte codes.
* @param stack The stack tracker that is keeping track of the current stack size.
* @return The number of of method return value words placed on the stack.
*/
public int invokeThis(String methodName, Class[] parameters, Class returnType, boolean isStatic, StandardOutputStream out, StackTracker stack) throws IOException {
short methodIndex = type.addConstantMethod(null, returnType, methodName, parameters);
int retVal = 0;
int argumentSize = 0;
for(int index = 0; index < parameters.length; index++) {
argumentSize += ((parameters[index].equals(Long.TYPE)) || (parameters[index].equals(Double.TYPE))) ? 2 : 1;
}//for//
if((methodName.equals("<init>")) || (methodName.equals("<cinit>"))) {
//Special//
out.writeByte((byte) 183); //(-argumentSize -1 +returnValueSize) invokespecial.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize + 1);
}//if//
else if(isStatic) {
//Static//
out.writeByte((byte) 184); //(-argumentSize +returnValueSize) invokestatic.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize);
}//else if//
else {
//Virtual//
out.writeByte((byte) 182); //(-argumentSize -1 +returnValueSize) invokevirtual.//
out.writeShort((short) methodIndex);
stack.decrement(argumentSize + 1);
}//else//
//Increment the stack to reflect the methods return value.//
if((returnType.equals(Long.TYPE)) || (returnType.equals(Double.TYPE))) {
stack.increment(2);
retVal = 2;
}//if//
else if(!returnType.equals(Void.TYPE)) {
stack.increment();
retVal = 1;
}//else if//
return retVal;
}//invokeThis()//
/**
* Jumps the code pointer by <code>offset</code> amount.
* The stack is unaffected.
* <p>Warning: The jump offset will be adjusted to take into account the bytes of code that perform the jump. The caller should not need to take this into account.
* @param offset The amount to jump where a negative value would jump backward in the code, and a positive value jumps forward.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void jump(int offset, StandardOutputStream out, StackTracker stack) throws IOException {
//Adjust the offset to account for the added code of performing the jump.//
if(offset >= 0) {
offset += 3;
if(offset > 32767) {
offset += 2;
}//if//
}//if//
//Used the short jump when possible.//
if((offset < 32768) && (offset > -32769)) {
out.writeByte((byte) 167); //goto//
out.writeShort((short) offset);
}//if//
else {
out.writeByte((byte) 200); //goto_w//
out.writeInt(offset);
}//else//
}//jump()//
/**
* Pops two long values from the stack and computes the remainder of dividing the first by the second l1 % l2 them, and pushes the result on the stack.
* The stack is decremented by 4 and incremented by 2.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void lmod(StandardOutputStream out, StackTracker stack) throws IOException {
out.writeByte((byte) 113); //lrem - Gets the remainder using: value1 % value2//
stack.decrement(2);
}//lmod()//
/**
* Pops the value of a local variable onto the stack.
* The stack is incremented by one or two depending on the local variable's type.
* @param local The number identifying the local variable.
* @param type The local variable's type. All valid types are defined by this class as identifiers and are listed below.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
* @see #I
* @see #L
* @see #F
* @see #D
* @see #A
*/
public void load(byte local, int type, StandardOutputStream out, StackTracker stack) throws IOException {
switch(type) {
case I: {
switch(local) {
case 0: {
out.writeByte((byte) 26); //iload_0//
break;
}//case//
case 1: {
out.writeByte((byte) 27); //iload_1//
break;
}//case//
case 2: {
out.writeByte((byte) 28); //iload_2//
break;
}//case//
case 3: {
out.writeByte((byte) 29); //iload_3//
break;
}//case//
default: {
out.writeByte((byte) 21); //iload//
out.writeByte((byte) local);
break;
}//default//
}//switch//
stack.increment();
break;
}//case//
case L: {
switch(local) {
case 0: {
out.writeByte((byte) 30); //lload_0//
break;
}//case//
case 1: {
out.writeByte((byte) 31); //lload_1//
break;
}//case//
case 2: {
out.writeByte((byte) 32); //lload_2//
break;
}//case//
case 3: {
out.writeByte((byte) 33); //lload_3//
break;
}//case//
default: {
out.writeByte((byte) 22); //lload//
out.writeByte((byte) local);
break;
}//default//
}//switch//
stack.increment(2);
break;
}//case//
case F: {
switch(local) {
case 0: {
out.writeByte((byte) 34); //fload_0//
break;
}//case//
case 1: {
out.writeByte((byte) 35); //fload_1//
break;
}//case//
case 2: {
out.writeByte((byte) 36); //fload_2//
break;
}//case//
case 3: {
out.writeByte((byte) 37); //fload_3//
break;
}//case//
default: {
out.writeByte((byte) 23); //fload//
out.writeByte((byte) local);
break;
}//default//
}//switch//
stack.increment();
break;
}//case//
case D: {
switch(local) {
case 0: {
out.writeByte((byte) 38); //dload_0//
break;
}//case//
case 1: {
out.writeByte((byte) 39); //dload_1//
break;
}//case//
case 2: {
out.writeByte((byte) 40); //dload_2//
break;
}//case//
case 3: {
out.writeByte((byte) 41); //dload_3//
break;
}//case//
default: {
out.writeByte((byte) 24); //dload//
out.writeByte((byte) local);
break;
}//default//
}//switch//
stack.increment(2);
break;
}//case//
case A: {
switch(local) {
case 0: {
out.writeByte((byte) 42); //aload_0//
break;
}//case//
case 1: {
out.writeByte((byte) 43); //aload_1//
break;
}//case//
case 2: {
out.writeByte((byte) 44); //aload_2//
break;
}//case//
case 3: {
out.writeByte((byte) 45); //aload_3//
break;
}//case//
default: {
out.writeByte((byte) 25); //aload//
out.writeByte((byte) local);
break;
}//default//
}//switch//
stack.increment();
break;
}//case//
default: {
//Must be I, L, F, D, or A//
Debug.halt();
throw new RuntimeException("Error: Unable to continue processing the class due to an internal error.");
}//default//
}//switch//
}//load()//
/**
* @see load(byte, Class, StandardOutputStream, StackTracker)
*/
public void load(byte local, Class type, StandardOutputStream out, StackTracker stack) throws IOException {
int typeCode;
if(type.isPrimitive()) {
if((type.equals(Integer.TYPE)) || (type.equals(Character.TYPE)) || (type.equals(Short.TYPE)) || (type.equals(Boolean.TYPE)) || (type.equals(Byte.TYPE))) {
typeCode = I;
}//if//
else if(type.equals(Long.TYPE)) {
typeCode = L;
}//else if//
else if(type.equals(Float.TYPE)) {
typeCode = F;
}//else if//
else if(type.equals(Double.TYPE)) {
typeCode = D;
}//else if//
else {
Debug.halt();
typeCode = A;
}//else//
}//if//
else {
typeCode = A;
}//else//
load(local, typeCode, out, stack);
}//load()//
/**
* Converts a long value on the stack to an int value.
* Pops a long value from the stack and pushes an int value which decrements the stack size by one.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void long2int(StandardOutputStream out, StackTracker stack) throws IOException {
out.writeByte((byte) 136); //l2i//
stack.decrement(1);
}//long2int()//
/**
* Adds a return statement to the type to return the method's return value from the stack.
* The return value will be popped from the stack. The stack will be incremented by one or two (for a long our double return value).
* @param type The method's return type.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void methodReturn(Class type, StandardOutputStream out, StackTracker stack) throws IOException {
boolean decrement = true;
if(type.isPrimitive()) {
if(type.equals(Integer.TYPE)) {
out.writeByte((byte) 172); //(-1) ireturn -> Return integer//
}//if//
else if(type.equals(Boolean.TYPE)) {
out.writeByte((byte) 172); //(-1) ireturn -> Return integer//
}//else if//
else if(type.equals(Long.TYPE)) {
out.writeByte((byte) 173); //(-1) lreturn -> Return long//
stack.decrement(); //Account for double size value
}//else if//
else if(type.equals(Short.TYPE)) {
out.writeByte((byte) 172); //(-1) ireturn -> Return integer//
}//else if//
else if(type.equals(Float.TYPE)) {
out.writeByte((byte) 174); //(-1) freturn -> Return float//
}//else if//
else if(type.equals(Double.TYPE)) {
out.writeByte((byte) 175); //(-1) dreturn -> Return double//
stack.decrement(); //Account for double size value//
}//else if//
else if(type.equals(Character.TYPE)) {
out.writeByte((byte) 172); //(-1) ireturn -> Return integer//
}//else if//
else if(type.equals(Byte.TYPE)) {
out.writeByte((byte) 172); //(-1) ireturn -> Return integer//
}//else if//
else {
//Must be VOID.//
if(stack.getStackSize() == 1) {
out.writeByte((byte) 87); //(0) pop -> Remove the remaining item on the local stack//
}//if//
else if(stack.getStackSize() > 1) {
Debug.log("Error: The stack size should be one or zero when appending a method return.");
}//else if//
else {
decrement = false;
}//else//
out.writeByte((byte) 177); //(0) return -> Return nothing//
}//else//
}//if//
else {
//An object type of return.//
out.writeByte((byte) 192); //(0) checkcast -> cast the local object to it's proper type//
out.writeShort((short) this.type.addConstantType(type)); //The index of the class to cast to//
out.writeByte((byte) 176); //(-1) areturn -> Return object reference//
}//else//
if(decrement) {
stack.decrement();
}//if//
}//methodReturn()//
/**
* Pushes a constant value onto the stack.
* The constant value or a reference to the constant value in the constant pool will be pushed on the stack. The stack will be incremented by one.
* @param value The value to place on the stack.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void push(int value, StandardOutputStream out, StackTracker stack) throws IOException {
switch(value) {
case -1: {
out.writeByte((byte) 2); //iconst_m1
stack.increment();
break;
}//case//
case 0: {
out.writeByte((byte) 3); //iconst_0
stack.increment();
break;
}//case//
case 1: {
out.writeByte((byte) 4); //iconst_1
stack.increment();
break;
}//case//
case 2: {
out.writeByte((byte) 5); //iconst_2
stack.increment();
break;
}//case//
case 3: {
out.writeByte((byte) 6); //iconst_3
stack.increment();
break;
}//case//
case 4: {
out.writeByte((byte) 7); //iconst_4
stack.increment();
break;
}//case//
case 5: {
out.writeByte((byte) 8); //iconst_5
stack.increment();
break;
}//case//
default: {
if((value < 128) && (value > -129)) {
out.writeByte((byte) 16); //bipush//
out.writeByte((byte) value);
stack.increment();
}//if//
else if((value < 32768) && (value > -32769)) {
out.writeByte((byte) 17); //sipush//
out.writeShort((short) value);
stack.increment();
}//else if//
else {
short index = type.addConstantInt(value);
pushConstant(index, out, stack);
}//else//
break;
}//default//
}//switch//
}//push()//
/**
* Pushes a constant long (wide) value onto the stack.
* The constant value or a reference to the constant value in the constant pool will be pushed on the stack. The stack will be incremented by two.
* @param value The value to place on the stack.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void push(long value, StandardOutputStream out, StackTracker stack) throws IOException {
if(value == 0) {
out.writeByte((byte) 9); //lconst_0//
stack.increment(2);
}//if//
else if(value == 1) {
out.writeByte((byte) 10); //lconst_1//
stack.increment(2);
}//else if//
else {
short index = type.addConstantLong(value);
pushWideConstant(index, out, stack);
}//else//
}//push()//
/**
* Pushes a constant value onto the stack using a constant value in the constant pool.
* A reference to the constant will be used to push the value on the stack. The stack will be incremented by one.
* @param index The value's index in the constant pool.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void pushConstant(short index, StandardOutputStream out, StackTracker stack) throws IOException {
if((index < 128) && (index > -129)) {
out.writeByte((byte) 18); //ldc//
out.writeByte((byte) index);
}//if//
else {
out.writeByte((byte) 19); //ldc_w//
out.writeShort(index);
}//else//
stack.increment();
}//pushConstant()//
/**
* Pushes a wide constant value onto the stack using a constant value in the constant pool.
* A reference to the constant will be used to push the wide (8 byte) value on the stack. The stack will be incremented by two.
* @param index The value's index in the constant pool.
* @param out The output stream to write to.
* @param stack The stack tracker that will track the stack size.
*/
public void pushWideConstant(short index, StandardOutputStream out, StackTracker stack) throws IOException {
out.writeByte((byte) 20); //ldc2_w//
out.writeShort(index);
stack.increment(2);
}//pushWideConstant()//
}//MethodSupport//

View File

@@ -0,0 +1,397 @@
package com.de22.javabytecode.code;
import com.common.util.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* Defines an operation code.
*/
public class OpCode {
public static final int SIGNED_INT = 0;
public static final int UNSIGNED_INT = 1;
public static final int SIGNED_SHORT = 2;
public static final int UNSIGNED_SHORT = 3;
public static final int SIGNED_BYTE = 4;
public static final int UNSIGNED_BYTE = 5;
public static final int SHORT_CONSTANT_REF = 6; //Same as an UNSIGNED_BYTE, but identifies the param as being an index into the constant pool.//
public static final int CONSTANT_REF = 7; //Same as an UNSIGNED_SHORT, but identifies the param as being an index into the constant pool.//
private static final int[] EMPTY_INT_ARRAY = new int[0];
/** The opcode's name. */
private String name = null;
/** The opcode's general description. */
private String description = null;
/** The collection of parameter types, one for each parameter in the opcode. */
private int[] parameterTypes = null;
/** The collection of parameter descriptions, one for each parameter in the opcode. */
private IList parameterDescriptions = null;
/** The collection of parameter byte descriptions, one for each byte that follows the opcode. */
private IList parameterByteDescriptions = null;
private static IList opCodes = null;
/**
* Defines the array of all operation codes in Java.
*/
private static final OpCode[] opCodeArray = new OpCode[] {
new OpCode("nop", "Do nothing.", -9999), //00
new OpCode("aconst_null", "Push a null object reference onto the operand stack.", -9999), //01
new OpCode("iconst_m1", "Push the int constant -1 onto the operand stack.", -9999), //02
new OpCode("iconst_0", "Push the int constant 0 onto the operand stack.", -9999), //03
new OpCode("iconst_1", "Push the int constant 1 onto the operand stack.", -9999), //04
new OpCode("iconst_2", "Push the int constant 2 onto the operand stack.", -9999), //05
new OpCode("iconst_3", "Push the int constant 3 onto the operand stack.", -9999), //06
new OpCode("iconst_4", "Push the int constant 4 onto the operand stack.", -9999), //07
new OpCode("iconst_5", "Push the int constant 5 onto the operand stack.", -9999), //08
new OpCode("lconst_0", "Push the long constant 0 onto the operand stack.", -9999), //09
new OpCode("lconst_1", "Push the long constant 1 onto the operand stack.", -9999), //0A
new OpCode("fconst_0", "Push the float constant 0 onto the operand stack.", -9999), //0B
new OpCode("fconst_1", "Push the float constant 1 onto the operand stack.", -9999), //0C
new OpCode("fconst_2", "Push the float constant 2 onto the operand stack.", -9999), //0D
new OpCode("dconst_0", "Push the double constant 0 onto the operand stack.", -9999), //0E
new OpCode("dconst_1", "Push the double constant 1 onto the operand stack.", -9999), //0F
new OpCode("bipush", "Pushes a specified byte onto the operand stack as a signed int.", new int[] {SIGNED_BYTE}, new String[] {"The signed byte value."}, new String[] {"A signed byte."}, -9999), //10
new OpCode("sipush", "Pushes a specified short onto the operand stack as a signed int.", new int[] {SIGNED_SHORT}, new String[] {"The signed short value."}, new String[] {"The high byte.", "The low byte. ((byte1<<8)|byte2 = short)"}, -9999), //11
new OpCode("ldc", "Pushes a constant onto the operand stack (may be int, float, or string reference).", new int[] {SHORT_CONSTANT_REF}, new String[] {"The index in the ClassFile's constantPool."}, new String[] {"An index in the ClassFile's constantPool."}, -9999), //12
new OpCode("ldc_w", "Pushes a constant onto the operand stack (may be int, float, or string reference).", new int[] {CONSTANT_REF}, new String[] {"The index in the ClassFile's constantPool."}, new String[] {"The high byte of the index in the ClassFile's constantPool.", "The low byte ((highByte<<8)|lowByte = index)."}, -9999), //13
new OpCode("ldc2_w", "Pushes a constant onto the operand stack (may be long, or double).", new int[] {CONSTANT_REF}, new String[] {"The index in the ClassFile's constantPool."}, new String[] {"The high byte of the index in the ClassFile's constantPool.", "The low byte ((highByte<<8)|lowByte = index)."}, -9999), //14
new OpCode("iload", "Load an int from a local variable onto the operand stack.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable."}, new String[] {"The index of the local variable."}, -9999), //15
new OpCode("lload", "Load a long from a local variable onto the operand stack.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable."}, new String[] {"The index of the local variable."}, -9999), //16
new OpCode("fload", "Load a float from a local variable onto the operand stack.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable."}, new String[] {"The index of the local variable."}, -9999), //17
new OpCode("dload", "Load a double from a local variable onto the operand stack.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable."}, new String[] {"The index of the local variable."}, -9999), //18
new OpCode("aload", "Load an object reference from a local variable onto the operand stack.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable."}, new String[] {"The index of the local variable."}, -9999), //19
new OpCode("iload_0", "Load an int from the local variable 0 onto the operand stack.", -9999), //1A
new OpCode("iload_1", "Load an int from the local variable 1 onto the operand stack.", -9999), //1B
new OpCode("iload_2", "Load an int from the local variable 2 onto the operand stack.", -9999), //1C
new OpCode("iload_3", "Load an int from the local variable 3 onto the operand stack.", -9999), //1D
new OpCode("lload_0", "Load a long from the local variable 0 onto the operand stack.", -9999), //1E
new OpCode("lload_1", "Load a long from the local variable 1 onto the operand stack.", -9999), //1F
new OpCode("lload_2", "Load a long from the local variable 2 onto the operand stack.", -9999), //20
new OpCode("lload_3", "Load a long from the local variable 3 onto the operand stack.", -9999), //21
new OpCode("fload_0", "Load a float from the local variable 0 onto the operand stack.", -9999), //22
new OpCode("fload_1", "Load a float from the local variable 1 onto the operand stack.", -9999), //23
new OpCode("fload_2", "Load a float from the local variable 2 onto the operand stack.", -9999), //24
new OpCode("fload_3", "Load a float from the local variable 3 onto the operand stack.", -9999), //25
new OpCode("dload_0", "Load a double from the local variable 0 onto the operand stack.", -9999), //26
new OpCode("dload_1", "Load a double from the local variable 1 onto the operand stack.", -9999), //27
new OpCode("dload_2", "Load a double from the local variable 2 onto the operand stack.", -9999), //28
new OpCode("dload_3", "Load a double from the local variable 3 onto the operand stack.", -9999), //29
new OpCode("aload_0", "Load an object reference from the local variable 0 onto the operand stack.", -9999), //2A
new OpCode("aload_1", "Load an object reference from the local variable 1 onto the operand stack.", -9999), //2B
new OpCode("aload_2", "Load an object reference from the local variable 2 onto the operand stack.", -9999), //2C
new OpCode("aload_3", "Load an object reference from the local variable 3 onto the operand stack.", -9999), //2D
new OpCode("iaload", "", -9999), //2E
new OpCode("laload", "", -9999), //2F
new OpCode("faload", "", -9999), //30
new OpCode("daload", "", -9999), //31
new OpCode("aaload", "", -9999), //32
new OpCode("baload", "", -9999), //33
new OpCode("caload", "", -9999), //34
new OpCode("saload", "", -9999), //35
new OpCode("istore", "Pops an int off the operand stack & stores it at the specified local variable index.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable to be used."}, new String[] {"The index of the local variable to be used."}, -9999), //36
new OpCode("lstore", "Pops a long off the operand stack & stores it at the specified local variable index.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable to be used."}, new String[] {"The index of the local variable to be used."}, -9999), //37
new OpCode("fstore", "Pops a float off the operand stack & stores it at the specified local variable index.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable to be used."}, new String[] {"The index of the local variable to be used."}, -9999), //38
new OpCode("dstore", "Pops a double off the operand stack & stores it at the specified local variable index.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable to be used."}, new String[] {"The index of the local variable to be used."}, -9999), //39
new OpCode("astore", "Pops an object reference off the operand stack & stores it at the specified local variable index.", new int[] {UNSIGNED_BYTE}, new String[] {"The index of the local variable to be used."}, new String[] {"The index of the local variable to be used."}, -9999), //3A
new OpCode("istore_0", "Pops an int off the operand stack & stores it in the local variable 0.", -9999), //3B
new OpCode("istore_1", "Pops an int off the operand stack & stores it in the local variable 1.", -9999), //3C
new OpCode("istore_2", "Pops an int off the operand stack & stores it in the local variable 2.", -9999), //3D
new OpCode("istore_3", "Pops an int off the operand stack & stores it in the local variable 3.", -9999), //3E
new OpCode("lstore_0", "Pops an int off the operand stack & stores it in the local variable 0.", -9999), //3F
new OpCode("lstore_1", "Pops a long off the operand stack & stores it in the local variable 1.", -9999), //40
new OpCode("lstore_2", "Pops a long off the operand stack & stores it in the local variable 2.", -9999), //41
new OpCode("lstore_3", "Pops a long off the operand stack & stores it in the local variable 3.", -9999), //42
new OpCode("fstore_0", "Pops a float off the operand stack & stores it in the local variable 0.", -9999), //43
new OpCode("fstore_1", "Pops a float off the operand stack & stores it in the local variable 1.", -9999), //44
new OpCode("fstore_2", "Pops a float off the operand stack & stores it in the local variable 2.", -9999), //45
new OpCode("fstore_3", "Pops a float off the operand stack & stores it in the local variable 3.", -9999), //46
new OpCode("dstore_0", "Pops a double off the operand stack & stores it in the local variable 0.", -9999), //47
new OpCode("dstore_1", "Pops a double off the operand stack & stores it in the local variable 1.", -9999), //48
new OpCode("dstore_2", "Pops a double off the operand stack & stores it in the local variable 2.", -9999), //49
new OpCode("dstore_3", "Pops a double off the operand stack & stores it in the local variable 3.", -9999), //4A
new OpCode("astore_0", "Pops an object reference off the operand stack & stores it in the local variable 0.", -9999), //4B
new OpCode("astore_1", "Pops an object reference off the operand stack & stores it in the local variable 1.", -9999), //4C
new OpCode("astore_2", "Pops an object reference off the operand stack & stores it in the local variable 2.", -9999), //4D
new OpCode("astore_3", "Pops an object reference off the operand stack & stores it in the local variable 3.", -9999), //4E
new OpCode("iastore", "Stores a value into an int array at an index (...,arrayref,index,value -> ...).", -9999), //4F
new OpCode("lastore", "Stores a value into a long array at an index (...,arrayref,index,value -> ...).", -9999), //50
new OpCode("fastore", "Stores a value into a float array at an index (...,arrayref,index,value -> ...).", -9999), //51
new OpCode("dastore", "Stores a value into a double array at an index (...,arrayref,index,value -> ...).", -9999), //52
new OpCode("aastore", "Stores a value into an object array at an index (...,arrayref,index,value -> ...).", -9999), //53
new OpCode("bastore", "Stores a value into a byte/boolean array at an index (...,arrayref,index,value -> ...).", -9999), //54
new OpCode("castore", "Stores a value into a char array at an index (...,arrayref,index,value -> ...).", -9999), //55
new OpCode("sastore", "Stores a value into a short array at an index (...,arrayref,index,value -> ...).", -9999), //56
new OpCode("pop", "Pops the top word off the operand stack.", -9999), //57
new OpCode("pop2", "Pops the top 2 words off the operand stack.", -9999), //58
new OpCode("dup", "Duplicates the top word on the operand stack.", -9999), //59
new OpCode("dup_x1", "Duplicates the top word on the operand stack & puts the duplicate one down.", -9999), //5A
new OpCode("dup_x2", "Duplicates the top word on the operand stack & puts the duplicate two down.", -9999), //5B
new OpCode("dup2", "Duplicates the top 2 words on the operand stack.", -9999), //5C
new OpCode("dup2_x1", "Duplicates the top 2 words on the operand stack & puts the duplicates one down.", -9999), //5D
new OpCode("dup2_x2", "Duplicates the top 2 words on the operand stack & puts the duplicates two down.", -9999), //5E
new OpCode("swap", "Swaps the top two words on the operand stack.", -9999), //5F
new OpCode("iadd", "Pops two int values off the operand stack and pushes back (value1+value2).", -9999), //60
new OpCode("ladd", "Pops two long values off the operand stack and pushes back (value1+value2).", -9999), //61
new OpCode("fadd", "Pops two float values off the operand stack and pushes back (value1+value2).", -9999), //62
new OpCode("dadd", "Pops two double values off the operand stack and pushes back (value1+value2).", -9999), //63
new OpCode("isub", "Pops two int values off the operand stack and pushes back (value1-value2).", -9999), //64
new OpCode("lsub", "Pops two long values off the operand stack and pushes back (value1-value2).", -9999), //65
new OpCode("fsub", "Pops two float values off the operand stack and pushes back (value1-value2).", -9999), //66
new OpCode("dsub", "Pops two double values off the operand stack and pushes back (value1-value2).", -9999), //67
new OpCode("imul", "Pops two int values off the operand stack and pushes back (value1*value2).", -9999), //68
new OpCode("lmul", "Pops two long values off the operand stack and pushes back (value1*value2).", -9999), //69
new OpCode("fmul", "Pops two float values off the operand stack and pushes back (value1*value2).", -9999), //6A
new OpCode("dmul", "Pops two double values off the operand stack and pushes back (value1*value2).", -9999), //6B
new OpCode("idiv", "Pops two int values off the operand stack and pushes back (value1/value2).", -9999), //6C
new OpCode("ldiv", "Pops two long values off the operand stack and pushes back (value1/value2).", -9999), //6D
new OpCode("fdiv", "Pops two float values off the operand stack and pushes back (value1/value2).", -9999), //6E
new OpCode("ddiv", "Pops two double values off the operand stack and pushes back (value1/value2).", -9999), //6F
new OpCode("irem", "Pops two int values off the operand stack and pushes back (value1%value2).", -9999), //70
new OpCode("lrem", "Pops two long values off the operand stack and pushes back (value1%value2).", -9999), //71
new OpCode("frem", "Pops two float values off the operand stack and pushes back (value1%value2).", -9999), //72
new OpCode("drem", "Pops two double values off the operand stack and pushes back (value1%value2).", -9999), //73
new OpCode("ineg", "Pops an int value off the operand stack and pushes back (0 - value).", -9999), //74
new OpCode("lneg", "Pops a long value off the operand stack and pushes back (0 - value).", -9999), //75
new OpCode("fneg", "Pops a float value off the operand stack and pushes back (0 - value).", -9999), //76
new OpCode("dneg", "Pops a double value off the operand stack and pushes back (0 - value).", -9999), //77
new OpCode("ishl", "", -9999), //78
new OpCode("lshl", "", -9999), //79
new OpCode("ishr", "", -9999), //7A
new OpCode("lshr", "", -9999), //7B
new OpCode("iushr", "", -9999), //7C
new OpCode("lushr", "", -9999), //7D
new OpCode("iand", "", -9999), //7E
new OpCode("land", "", -9999), //7F
new OpCode("ior", "", -9999), //80
new OpCode("lor", "", -9999), //81
new OpCode("ixor", "", -9999), //82
new OpCode("lxor", "", -9999), //83
new OpCode("iinc", "Increments a local variable by a given constant.", new int[] {UNSIGNED_BYTE, SIGNED_BYTE}, new String[] {"The index to an integer local variable in the current frame.", "The signed byte (converted to a sign extended integer) used to modify the local variable referenced by the first parameter."}, new String[] {"The local variable index (int).", "The signed constant value (int)"}, -9999), //84
new OpCode("i2l", "", -9999), //85
new OpCode("i2f", "", -9999), //86
new OpCode("i2d", "", -9999), //87
new OpCode("l2i", "", -9999), //88
new OpCode("l2f", "", -9999), //89
new OpCode("l2d", "", -9999), //8A
new OpCode("f2i", "", -9999), //8B
new OpCode("f2l", "", -9999), //8C
new OpCode("f2d", "", -9999), //8D
new OpCode("d2i", "", -9999), //8E
new OpCode("d2l", "", -9999), //8F
new OpCode("d2f", "", -9999), //90
new OpCode("i2b", "", -9999), //91
new OpCode("i2c", "", -9999), //92
new OpCode("i2s", "", -9999), //93
new OpCode("lcmp", "", -9999), //94
new OpCode("fcmpl", "", -9999), //95
new OpCode("fcmpg", "", -9999), //96
new OpCode("dcmpl", "", -9999), //97
new OpCode("dcmpg", "", -9999), //98
new OpCode("ifeq", "Pops an int value off the operand stack and checks for (value == 0).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //99
new OpCode("ifne", "Pops an int value off the operand stack and checks for (value != 0).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //9A
new OpCode("iflt", "Pops an int value off the operand stack and checks for (value < 0).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //9B
new OpCode("ifge", "Pops an int value off the operand stack and checks for (value >= 0).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //9C
new OpCode("ifgt", "Pops an int value off the operand stack and checks for (value > 0).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //9D
new OpCode("ifle", "Pops an int value off the operand stack and checks for (value <= 0).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //9E
new OpCode("if_icmpeq", "Pops two int values off the operand stack and checks for (value1 == value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //9F
new OpCode("if_icmpne", "Pops two int values off the operand stack and checks for (value1 != value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A0
new OpCode("if_icmplt", "Pops two int values off the operand stack and checks for (value1 < value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A1
new OpCode("if_icmpge", "Pops two int values off the operand stack and checks for (value1 >= value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A2
new OpCode("if_icmpgt", "Pops two int values off the operand stack and checks for (value1 > value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A3
new OpCode("if_icmple", "Pops two int values off the operand stack and checks for (value1 <= value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A4
new OpCode("if_acmpeq", "Pops two object references off the operand stack and checks for (value1 == value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A5
new OpCode("if_acmpne", "Pops two object references off the operand stack and checks for (value1 != value2).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A6
new OpCode("goto", "Performs a branch operation.", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset."}, new String[] {"The high byte of the signed 16bit jump offset.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //A7
new OpCode("jsr", "", -9999), //A8
new OpCode("ret", "", -9999), //A9
new OpCode("tableswitch", "", -9999), //AA
new OpCode("lookupswitch", "", -9999), //AB
new OpCode("ireturn", "Return an int (off the operand stack).", -9999), //AC
new OpCode("lreturn", "Return a long (off the operand stack).", -9999), //AD
new OpCode("freturn", "Return a float (off the operand stack).", -9999), //AE
new OpCode("dreturn", "Return a double (off the operand stack).", -9999), //AF
new OpCode("areturn", "Return a reference (off the operand stack).", -9999), //B0
new OpCode("return", "Return from this method.", -9999), //B1
new OpCode("getstatic", "Pops an object reference off the operand stack and pushes the value (1 or 2 words) of that object's static attribute (CodeAttribute determined by the ConstantFieldReference indexed in the ClassFile's constantPool)", new int[] {CONSTANT_REF}, new String[] {"The index into the ClassFile's constantPool (Should index a ConstantFieldReference)."}, new String[] {"The high byte of an index into the ClassFile's constantPool (Should index a ConstantFieldReference).", "The low byte of the offset. ((highbyte<<8)|lowbyte = index)"}, -9999), //B2
new OpCode("putstatic", "Pops an object reference and the value (1 or 2 words) off the operand stack and sets the value of that object's static attribute (CodeAttribute determined by the ConstantFieldReference indexed in the ClassFile's constantPool)", new int[] {CONSTANT_REF}, new String[] {"The index into the ClassFile's constantPool (Should index a ConstantFieldReference)."}, new String[] {"The high byte of an index into the ClassFile's constantPool (Should index a ConstantFieldReference).", "The low byte of the offset. ((highbyte<<8)|lowbyte = index)"}, -9999), //B3
new OpCode("getfield", "Pops an object reference off the operand stack and pushes the value (1 or 2 words) of that object's attribute (CodeAttribute determined by the ConstantFieldReference indexed in the ClassFile's constantPool)", new int[] {CONSTANT_REF}, new String[] {"The index into the ClassFile's constantPool (Should index a ConstantFieldReference)."}, new String[] {"The high byte of an index into the ClassFile's constantPool (Should index a ConstantFieldReference).", "The low byte of the offset. ((highbyte<<8)|lowbyte = index)"}, -9999), //B4
new OpCode("putfield", "Pops an object reference and the value (1 or 2 words) off the operand stack and sets the value of that object's attribute (CodeAttribute determined by the ConstantFieldReference indexed in the ClassFile's constantPool)", new int[] {CONSTANT_REF}, new String[] {"The index into the ClassFile's constantPool (Should index a ConstantFieldReference)."}, new String[] {"The high byte of an index into the ClassFile's constantPool (Should index a ConstantFieldReference).", "The low byte of the offset. ((highbyte<<8)|lowbyte = index)"}, -9999), //B5
new OpCode("invokevirtual", "Pops an object reference, all method parameters and invokes the indexed method.", new int[] {CONSTANT_REF}, new String[] {"The index of a ConstantMethodReference in the ClassFile's constantPool."}, new String[] {"The highbyte of an index of a ConstantMethodReference in the ClassFile's constantPool.", "The lowbyte ((highbyte<<8)|lowbyte = index)."}, -9999), //B6
new OpCode("invokespecial", "Pops an object reference, all method parameters and invokes the indexed method.", new int[] {CONSTANT_REF}, new String[] {"The index of a ConstantMethodReference in the ClassFile's constantPool."}, new String[] {"The highbyte of an index of a ConstantMethodReference in the ClassFile's constantPool.", "The lowbyte ((highbyte<<8)|lowbyte = index)."}, -9999), //B7
new OpCode("invokestatic", "Pops all method parameters and invokes the indexed method.", new int[] {CONSTANT_REF}, new String[] {"The index of a ConstantMethodReference in the ClassFile's constantPool."}, new String[] {"The highbyte of an index of a ConstantMethodReference in the ClassFile's constantPool.", "The lowbyte ((highbyte<<8)|lowbyte = index)."}, -9999), //B8
new OpCode("invokeinterface", "Pops an object reference, all method parameters and invokes the indexed method.", new int[] {CONSTANT_REF, UNSIGNED_BYTE, UNSIGNED_BYTE}, new String[] {"The index of a ConstantInterfaceMethodReference in the ClassFile's constantPool.", "The number of words (plus one) that should be popped off the operand stack (to be used as parameter(s)).", "Reserved; Must be 0."}, new String[] {"The highbyte of an index of a ConstantInterfaceMethodReference in the ClassFile's constantPool.", "The lowbyte ((highbyte<<8)|lowbyte = index).", "The number of words (plus one) that should be popped off the operand stack (to be used as parameter(s)).", "Reserved; Must be 0."}, -9999), //B9
new OpCode("xxxunusedxxx", "", -9999), //BA
new OpCode("new", "Creates a new object of the given type.", new int[] {CONSTANT_REF}, new String[] {"The constant reference to the object type."}, new String[] {"", ""}, -9999), //BB
new OpCode("newarray", "Creates a new array whose size is an int popped off the stack.", new int[] {UNSIGNED_BYTE}, new String[] {"The array type code."}, new String[] {"The array type code."}, -9999), //BC
new OpCode("anewarray", "Pops an int (count) off the stack & creates a new array of size count.", new int[] {CONSTANT_REF}, new String[] {"The index of a ConstantClass in the ClassFile's constantPool (The type of the array)."}, new String[] {"The highbyte of an index of a ConstantClass in the ClassFile's constantPool (The type of the array).", "The lowbyte ((highbyte<<8)|lowbyte = index)."}, -9999), //BD
new OpCode("arraylength", "", -9999), //BE
new OpCode("athrow", "", -9999), //BF
new OpCode("checkcast", "Checks the object reference on the operand stack is castable to the given ConstantClass", new int[] {CONSTANT_REF}, new String[] {"The index of a ConstantClass in the ClassFile's constantPool."}, new String[] {"The highbyte of an index of a ConstantClass in the ClassFile's constantPool.", "The lowbyte ((highbyte<<8)|lowbyte = index)."}, -9999), //C0
new OpCode("instanceof", "", new int[] {CONSTANT_REF}, new String[] {"The index in the ClassFile's constantPool."}, new String[] {"The high byte of the index in the ClassFile's constantPool.", "The low byte ((highByte<<8)|lowByte = index)."}, -9999), //C1
new OpCode("monitorenter", "", -9999), //C2
new OpCode("monitorexit", "", -9999), //C3
new OpCode("wide", "", -9999), //C4
new OpCode("multianewarray", "", -9999), //C5
new OpCode("ifnull", "Pops an object reference value off the operand stack and checks for (value == null).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //C6
new OpCode("ifnonnull", "Pops an object reference value off the operand stack and checks for (value != null).", new int[] {SIGNED_SHORT}, new String[] {"The signed 16bit jump offset used when the statement resolves to true."}, new String[] {"The high byte of the signed 16bit jump offset used when the statement resolves to true.", "The low byte of the offset. ((highbyte<<8)|lowbyte = offset)"}, -9999), //C7
new OpCode("goto_w", "", new int[] {SIGNED_INT}, new String[] {"The signed 32bit jump offset."}, new String[] {"The first (high) byte of the signed 32bit jump offset.", "The second byte of the offset.", "The third byte of the offset.", "The fourth (low) byte of the offset. ((byte1<<24)|(byte2<<24)|(byte3<<24)|(byte4) = offset)"}, -9999), //C8
new OpCode("jsr_w", "", -9999), //C9
new OpCode("breakpoint", "Reserved", -9999), //CA
new OpCode("ldc_quick", "", -9999), //CB
new OpCode("ldc_w_quick", "", -9999), //CC
new OpCode("ldc2_w_quick", "", -9999), //CD
new OpCode("getfield_quick", "", -9999), //CE
new OpCode("putfield_quick", "", -9999), //CF
new OpCode("getfield2_quick", "", -9999), //D0
new OpCode("putfield2_quick", "", -9999), //D1
new OpCode("getstatic_quick", "", -9999), //D2
new OpCode("putstatic_quick", "", -9999), //D3
new OpCode("getstatic2_quick", "", -9999), //D4
new OpCode("putstatic2_quick", "", -9999), //D5
new OpCode("invokevirtual_quick", "", -9999), //D6
new OpCode("invokenonvirtual_quick", "", -9999), //D7
new OpCode("invokesuper_quick", "", -9999), //D8
new OpCode("invokestatic_quick", "", -9999), //D9
new OpCode("invokeinterface_quick", "", -9999), //DA
new OpCode("invokevirtualobject_quick", "", -9999), //DB
new OpCode("xxx", "", -9999), //DC
new OpCode("new_quick", "", -9999), //DD
new OpCode("anewarray_quick", "", -9999), //DE
new OpCode("multianewarray_quick", "", -9999), //DF
new OpCode("checkcast_quick", "", -9999), //E0
new OpCode("instanceof_quick", "", -9999), //E1
new OpCode("invokevirtual_quick_w", "", -9999), //E2
new OpCode("getfield_quick_w", "", -9999), //E3
new OpCode("putfield_quick_w", "", -9999), //E4
new OpCode("xxx", "", -9999), //E5
new OpCode("xxx", "", -9999), //E6
new OpCode("xxx", "", -9999), //E7
new OpCode("xxx", "", -9999), //E8
new OpCode("xxx", "", -9999), //E9
new OpCode("xxx", "", -9999), //EA
new OpCode("xxx", "", -9999), //EB
new OpCode("xxx", "", -9999), //EC
new OpCode("xxx", "", -9999), //ED
new OpCode("xxx", "", -9999), //EE
new OpCode("xxx", "", -9999), //EF
new OpCode("xxx", "", -9999), //F0
new OpCode("xxx", "", -9999), //F1
new OpCode("xxx", "", -9999), //F2
new OpCode("xxx", "", -9999), //F3
new OpCode("xxx", "", -9999), //F4
new OpCode("xxx", "", -9999), //F5
new OpCode("xxx", "", -9999), //F6
new OpCode("xxx", "", -9999), //F7
new OpCode("xxx", "", -9999), //F8
new OpCode("xxx", "", -9999), //F9
new OpCode("xxx", "", -9999), //FA
new OpCode("xxx", "", -9999), //FB
new OpCode("xxx", "", -9999), //FC
new OpCode("xxx", "", -9999), //FD
new OpCode("impdep1", "Reserved", -9999), //FE
new OpCode("impdep2", "Reserved", -9999) //FF
};//opCodes//
/**
* OpCode constructor.
*/
private OpCode() {
super();
}//OpCode()//
/**
* OpCode constructor.
* @param name The operational code name.
* @param description The useful description of this op code.
* @param extra The number of extra bytes following the op code.
*/
private OpCode(String name, String description, int extra) {
this.name = name;
this.description = description;
this.parameterTypes = EMPTY_INT_ARRAY;
this.parameterDescriptions = LiteList.EMPTY_LIST;
this.parameterByteDescriptions = LiteList.EMPTY_LIST;
}//OpCode()//
/**
* OpCode constructor.
* @param name The operational code name.
* @param description The useful description of this op code.
* @param parameterTypes
* @param parameterDescriptions
* @param parameterByteDescriptions
* @param extra The number of extra bytes following the op code.
*/
private OpCode(String name, String description, int[] parameterTypes, String[] parameterDescriptions, String[] parameterByteDescriptions, int extra) {
this.name = name;
this.description = description;
this.parameterTypes = parameterTypes;
this.parameterDescriptions = parameterDescriptions != null ? new LiteList(parameterDescriptions) : LiteList.EMPTY_LIST;
this.parameterDescriptions.isChangeable(false);
this.parameterByteDescriptions = parameterByteDescriptions != null ? new LiteList(parameterByteDescriptions) : LiteList.EMPTY_LIST;
this.parameterByteDescriptions.isChangeable(false);
}//OpCode()//
/**
* Gets the operational code's description.
* @return The description of the OpCode.
*/
public String getDescription() {
return description;
}//getDescription()//
/**
* Gets the operational code's name.
* @return The name of the OpCode.
*/
public String getName() {
return name;
}//getName()//
/**
* Gets the OpCode objects that represent all valid java operational codes.
* @return The ordered array of all OpCodes.
*/
public static IList getOpCodes() {
if(opCodes == null) {
synchronized(OpCode.class) {
if(opCodes == null) {
opCodes = new LiteList(opCodeArray);
opCodes.isChangeable(false);
}//if//
}//synchronized//
}//if//
return opCodes;
}//getOpCodes()//
/**
* Gets the parameter type codes (see OpCode identifiers), one for each parameter to the opcode.
* @return The collection of parameter types.
*/
public int[] getParameterTypes() {
return parameterTypes;
}//getParameterTypes()//
/**
* Gets the descriptions for each parameter in order that they occur.
* @return The ordered collection of parameter descriptions.
*/
public IList getParameterDescriptions() {
return parameterDescriptions;
}//getParameterDescriptions()//
/**
* Gets the descriptions for each parameter byte in order that they occur.
* @return The ordered collection of descriptions for each byte that follows the opcode.
*/
public IList getParameterByteDescriptions() {
return parameterByteDescriptions;
}//getParameterByteDescriptions()//
/**
* Provides a human readable representation of the OpCode.
* @return A string representation.
*/
public String toString() {
String retVal = "";
retVal += name;
for(int t = name.length(); t < 12; t++) {
retVal += " ";
}//for//
retVal += " " + description;
return retVal;
}//toString()//
}//OpCode//

View File

@@ -0,0 +1,170 @@
package com.de22.javabytecode.code;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import com.common.debug.Debug;
import com.common.io.ByteArrayInputStream;
import com.common.io.ByteArrayOutputStream;
import com.common.io.ObjectInputStream;
import com.common.io.ObjectOutputStream;
import com.de22.javabytecode.Type;
/**
* Copyright Declarative Engineering LLC 2007<p>
* A simple test class that reads in a class file and then writes it out without any modifications.
* This class tests the ability to read and write a class file without introducing errors.
*/
public class Test {
/**
* Reverse engineers a class file and writes it back out to 'output.class'.
* @param args The array of initialization parameters.
* args[0] = The path and file name of the class to reverse engineer.
* args[1] = The path (must exist) where the output.class file will be stored. If the file exists it will be over written.
*/
public static void main(String[] args) {
String debugText = null;
long t = System.currentTimeMillis();
try {
File file = new File(args[0]);
File path = args.length > 1 ? new File(args[1]) : null;
if(path != null && (path.isFile() || (!path.exists() && !path.mkdirs()))) {
path = null;
}//if//
if(file.getName().endsWith(".class")) {
debugText = file.getPath();
processClassFile(file, new File(path, "output.class"));
compareClassFiles(file, new File(path, "output.class"));
}//if//
}//try//
catch(Throwable e) {
Debug.log(e, "Caught while processing the class file: " + debugText);
}//catch//
Debug.log("Total time (milliseconds): " + (System.currentTimeMillis() - t));
System.exit(0);
}//main()//
/**
* Writes a file.
* @param file The file to write.
* @param bytes The bytes to place in the file.
*/
public static void writeFile(File file, byte[] bytes) {
FileOutputStream fout = null;
try {
fout = new FileOutputStream(file);
fout.write(bytes);
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
finally {
if(fout != null) {
try {
fout.close();
}//try//
catch(Throwable e) {
}//catch//
}//if//
}//finally//
}//writeFile()//
/**
* Reads a file and returns the bytes contained there in.
* @param file The file to read.
* @return The bytes contained in the file.
*/
public static byte[] readFile(File file) {
FileInputStream fin = null;
byte[] bytes = null;
int counter = 0;
try {
fin = new FileInputStream(file);
bytes = new byte[fin.available()];
while(counter < bytes.length) {
counter += fin.read(bytes, counter, bytes.length - counter);
}//while//
fin.close();
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
finally {
if(fin != null) {
try {
fin.close();
}//try//
catch(Throwable e) {
}//catch//
}//if//
}//finally//
return bytes;
}//readFile()//
/**
* Processes a class file and writes out the byte codes in a semi-readable form.
* @param bytesIn The input stream containing the bytes codes. This stream will always be closed by this method.
* @param outputPath The optional path where the class output should be written to (under its packaging of course). The console will be used otherwise.
*/
private static void processClassFile(File inputFile, File outputFile) throws Throwable {
ByteArrayInputStream bin = null;
ObjectInputStream in = null;
Type type = null;
ByteArrayOutputStream bout = null;
ObjectOutputStream out = null;
try {
bin = new ByteArrayInputStream(readFile(inputFile));
in = new ObjectInputStream(bin, null, null);
type = new Type();
type.readExternal(in);
bout = new ByteArrayOutputStream(100000, false);
out = new ObjectOutputStream(bout, null);
type.writeExternal(out);
out.flush();
writeFile(outputFile, bout.toByteArray());
}//try//
catch(Throwable e) {
e.printStackTrace();
throw e;
}//catch//
}//processClassFile()//
/**
* Processes a class file and writes out the byte codes in a semi-readable form.
* @param bytesIn The input stream containing the bytes codes. This stream will always be closed by this method.
* @param outputPath The optional path where the class output should be written to (under its packaging of course). The console will be used otherwise.
*/
private static void compareClassFiles(File inputFile, File outputFile) throws Throwable {
byte[] originalBytes;
byte[] modifiedBytes;
int byteLength;
originalBytes = readFile(inputFile);
modifiedBytes = readFile(outputFile);
byteLength = Math.min(originalBytes.length, modifiedBytes.length);
for(int index = 0; index < byteLength; index++) {
if(originalBytes[index] != modifiedBytes[index]) {
Debug.log("Files diverge at index " + index);
return;
}//if//
}//for//
if(originalBytes.length != modifiedBytes.length) {
Debug.log("One file has more bytes than the other.");
}//if//
else {
Debug.log("Files are exactly the same.");
}//else//
}//processClassFile()//
}//Test//

View File

@@ -0,0 +1,112 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ConstantDouble extends Constant {
private double value = 0;
/**
* ConstantDouble constructor.
* @param type The class this constant is a member of.
*/
public ConstantDouble(Type type) {
super(type);
}//ConstantDouble()//
/**
* ConstantDouble constructor.
* @param type The class this constant is a member of.
* @param value The value of the constant.
*/
public ConstantDouble(Type type, double value) {
super(type);
this.value = value;
}//ConstantDouble()//
/**
* Gets the value for this associated with this constant.
* @return The double value.
*/
public double getValue() {
return value;
}//getValue()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantDouble) && (value == ((ConstantDouble) object).value);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 8;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_DOUBLE;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return (int) Double.doubleToLongBits(value);
}//hashCode()//
/**
* Determines whether the constant takes double the constant entries in the class bytes.
* @return Whether the constant is a double size constant.
*/
public boolean isDoubleSize() {
return true;
}//isDoubleSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
value = in.readDouble();
}//readExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
return Double.toString(value) + " (Double)";
}//getPrettyValue()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "Double: " + Double.toString(value);
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Double Constant (");
buffer.append(value);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeDouble(value);
}//writeExternal()//
}//ConstantDouble//

View File

@@ -0,0 +1,154 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ConstantFieldRef extends Constant {
/** The reference to the class that defines the field. */
private short classIndex = 0;
/** The reference to the name and signature of the method. */
private short nameAndTypeIndex = 0;
/**
* ConstantFieldRef constructor.
* @param type The class this constant is a member of.
*/
public ConstantFieldRef(Type type) {
super(type);
}//ConstantFieldRef()//
/**
* ConstantFieldRef constructor.
* @param type The class this constant is a member of.
* @param classIndex The index of the class constant.
* @param nameAndTypeIndex The index of the name and type descriptor constant.
*/
public ConstantFieldRef(Type type, short classIndex, short nameAndTypeIndex) {
super(type);
this.classIndex = classIndex;
this.nameAndTypeIndex = nameAndTypeIndex;
}//ConstantFieldRef()//
/**
* Gets the constant pool index for the class that defines the field (a ConstantType instance).
* @return The pool index of the class constant.
*/
public short getClassIndex() {
return classIndex;
}//getClassIndex()//
/**
* Gets the constant pool index for the name and type for the field (a ConstantNameAndType instance).
* @return The pool index of the name and type constant.
*/
public short getNameAndTypeIndex() {
return nameAndTypeIndex;
}//getNameAndTypeIndex()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantFieldRef) && (((ConstantFieldRef) object).classIndex == classIndex) && (((ConstantFieldRef) object).nameAndTypeIndex == nameAndTypeIndex);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 4;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_FIELD_REF;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return (classIndex << 4) | nameAndTypeIndex;
}//hashCode()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
classIndex = in.readShort();
nameAndTypeIndex = in.readShort();
}//readExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
Constant definingTypeConstant = getType().getConstant(classIndex);
Constant nameAndTypeConstant = getType().getConstant(nameAndTypeIndex);
Constant fieldTypeConstant = null;
Constant fieldNameConstant = null;
if(definingTypeConstant instanceof ConstantType) {
definingTypeConstant = getType().getConstant(((ConstantType) definingTypeConstant).getNameIndex());
}//if//
if(definingTypeConstant instanceof ConstantString) {
definingTypeConstant = getType().getConstant(((ConstantString) definingTypeConstant).getStringIndex());
}//if//
if(nameAndTypeConstant instanceof ConstantNameAndType) {
fieldNameConstant = getType().getConstant(((ConstantNameAndType) nameAndTypeConstant).getNameIndex());
fieldTypeConstant = getType().getConstant(((ConstantNameAndType) nameAndTypeConstant).getDescriptorIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(fieldTypeConstant instanceof ConstantType) {
fieldTypeConstant = getType().getConstant(((ConstantType) fieldTypeConstant).getNameIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(fieldTypeConstant instanceof ConstantString) {
fieldTypeConstant = getType().getConstant(((ConstantString) fieldTypeConstant).getStringIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(fieldNameConstant instanceof ConstantString) {
fieldNameConstant = getType().getConstant(((ConstantString) fieldNameConstant).getStringIndex());
}//if//
return definingTypeConstant instanceof ConstantUtf8 && fieldTypeConstant instanceof ConstantUtf8 && fieldNameConstant instanceof ConstantUtf8 ? ((ConstantUtf8) definingTypeConstant).getValue() + "." + ((ConstantUtf8) fieldNameConstant).getValue() + " (Field Name)" : "Error: Unexpected Constant Reference";
}//getPrettyValue()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "Field Reference (classIndex: " + classIndex + " nameAndTypeIndex: " + nameAndTypeIndex;
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Field Reference Constant (classIndex=");
buffer.append(classIndex);
buffer.append(" nameAndTypeIndex=");
buffer.append(nameAndTypeIndex);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort(classIndex);
out.writeShort(nameAndTypeIndex);
}//writeExternal()//
}//ConstantFieldRef//

View File

@@ -0,0 +1,105 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ConstantFloat extends Constant {
private float value = 0;
/**
* ConstantType constructor.
* @param type The class this constant is a member of.
*/
public ConstantFloat(Type type) {
super(type);
}//ConstantFloat()//
/**
* ConstantType constructor.
* @param type The class this constant is a member of.
* @param value The value of the constant.
*/
public ConstantFloat(Type type, float value) {
super(type);
this.value = value;
}//ConstantFloat()//
/**
* Gets the value for this associated with this constant.
* @return The float value.
*/
public float getValue() {
return value;
}//getValue()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantFloat) && (value == ((ConstantFloat) object).value);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 4;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_FLOAT;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return Float.floatToIntBits(value);
}//hashCode()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
value = in.readFloat();
}//readExternal()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "Float: " + Float.toString(value);
}//toString()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
return Float.toString(value) + " (Float)";
}//getPrettyValue()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Float Constant (");
buffer.append(value);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeFloat(value);
}//writeExternal()//
}//ConstantFloat//

View File

@@ -0,0 +1,105 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ConstantInteger extends Constant {
private int value = 0;
/**
* ConstantInteger constructor.
* @param type The class this constant is a member of.
*/
public ConstantInteger(Type type) {
super(type);
}//ConstantInteger()//
/**
* ConstantInteger constructor.
* @param type The class this constant is a member of.
* @param value The value of the constant.
*/
public ConstantInteger(Type type, int value) {
super(type);
this.value = value;
}//ConstantInteger()//
/**
* Gets the value for this associated with this constant.
* @return The integer value.
*/
public int getValue() {
return value;
}//getValue()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantInteger) && (value == ((ConstantInteger) object).value);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 4;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_INTEGER;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return value;
}//hashCode()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
value = in.readInt();
}//readExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
return Integer.toString(value) + " (Integer)";
}//getPrettyValue()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "Integer: " + Integer.toString(value);
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Integer Constant (");
buffer.append(value);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeInt(value);
}//writeExternal()//
}//ConstantInteger//

View File

@@ -0,0 +1,149 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* A reference to a method that is defined by an interface.
*/
public class ConstantInterfaceMethodRef extends Constant {
/** The reference to the interface that defines the method. */
private short classIndex = 0;
/** The reference to the name and signature of the method. */
private short nameAndTypeIndex = 0;
/**
* ConstantInterfaceMethodRef constructor.
* @param type The class this constant is a member of.
*/
public ConstantInterfaceMethodRef(Type type) {
super(type);
}//ConstantInterfaceMethodRef()//
/**
* ConstantInterfaceMethodRef constructor.
* @param type The class this constant is a member of.
* @param classIndex The index of the class constant.
* @param nameAndTypeIndex The index of the name and type descriptor constant.
*/
public ConstantInterfaceMethodRef(Type type, short classIndex, short nameAndTypeIndex) {
super(type);
this.classIndex = classIndex;
this.nameAndTypeIndex = nameAndTypeIndex;
}//ConstantInterfaceMethodRef()//
/**
* Gets the constant pool index for the interface that defines the method (a ConstantType instance).
* @return The pool index of the class constant.
*/
public short getClassIndex() {
return classIndex;
}//getClassIndex()//
/**
* Gets the constant pool index for the name and type for the method (a ConstantNameAndType instance).
* @return The pool index of the name and type constant.
*/
public short getNameAndTypeIndex() {
return nameAndTypeIndex;
}//getNameAndTypeIndex()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantInterfaceMethodRef) && (((ConstantInterfaceMethodRef) object).classIndex == classIndex) && (((ConstantInterfaceMethodRef) object).nameAndTypeIndex == nameAndTypeIndex);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 4;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_INTERFACE_METHOD_REF;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return (classIndex << 4) | nameAndTypeIndex;
}//hashCode()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
classIndex = in.readShort();
nameAndTypeIndex = in.readShort();
}//readExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
Constant definingTypeConstant = getType().getConstant(classIndex);
Constant nameAndTypeConstant = getType().getConstant(nameAndTypeIndex);
Constant methodSignatureConstant = null;
Constant methodNameConstant = null;
if(definingTypeConstant instanceof ConstantType) {
definingTypeConstant = getType().getConstant(((ConstantType) definingTypeConstant).getNameIndex());
}//if//
if(definingTypeConstant instanceof ConstantString) {
definingTypeConstant = getType().getConstant(((ConstantString) definingTypeConstant).getStringIndex());
}//if//
if(nameAndTypeConstant instanceof ConstantNameAndType) {
methodNameConstant = getType().getConstant(((ConstantNameAndType) nameAndTypeConstant).getNameIndex());
methodSignatureConstant = getType().getConstant(((ConstantNameAndType) nameAndTypeConstant).getDescriptorIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(methodSignatureConstant instanceof ConstantString) {
methodSignatureConstant = getType().getConstant(((ConstantString) methodSignatureConstant).getStringIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(methodNameConstant instanceof ConstantString) {
methodNameConstant = getType().getConstant(((ConstantString) methodNameConstant).getStringIndex());
}//if//
return definingTypeConstant instanceof ConstantUtf8 && methodNameConstant instanceof ConstantUtf8 && methodSignatureConstant instanceof ConstantUtf8 ? ((ConstantUtf8) definingTypeConstant).getValue() + "." + ((ConstantUtf8) methodNameConstant).getValue() + ((ConstantUtf8) methodSignatureConstant).getValue() + " (Interface Method Name)" : "Error: Unexpected Constant Reference";
}//getPrettyValue()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "Interface Method Reference (classIndex: " + classIndex + " nameAndTypeIndex: " + nameAndTypeIndex;
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Interface Method Reference Constant (classIndex=");
buffer.append(classIndex);
buffer.append(" nameAndTypeIndex=");
buffer.append(nameAndTypeIndex);
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort(classIndex);
out.writeShort(nameAndTypeIndex);
}//writeExternal()//
}//ConstantInterfaceMethodRef//

View File

@@ -0,0 +1,112 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ConstantLong extends Constant {
private long value = 0;
/**
* ConstantLong constructor.
* @param type The class this constant is a member of.
*/
public ConstantLong(Type type) {
super(type);
}//ConstantLong()//
/**
* ConstantLong constructor.
* @param type The class this constant is a member of.
* @param value The value of the constant.
*/
public ConstantLong(Type type, long value) {
super(type);
this.value = value;
}//ConstantLong()//
/**
* Gets the value for this associated with this constant.
* @return The long value.
*/
public long getValue() {
return value;
}//getValue()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantLong) && (value == ((ConstantLong) object).value);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 8;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_LONG;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return (int) value;
}//hashCode()//
/**
* Determines whether the constant takes double the constant entries in the class bytes.
* @return Whether the constant is a double size constant.
*/
public boolean isDoubleSize() {
return true;
}//isDoubleSize()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
value = in.readLong();
}//readExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
return Long.toString(value) + " (Long)";
}//getPrettyValue()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "Long: " + Long.toString(value);
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Long Constant (");
buffer.append(value);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeLong(value);
}//writeExternal()//
}//ConstantLong//

View File

@@ -0,0 +1,142 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* A reference to a method that is part of another class.
*/
public class ConstantMethodRef extends Constant {
/** The reference to the class that defines the method. */
private short classIndex = 0;
/** The reference to the name and signature of the method. */
private short nameAndTypeIndex = 0;
/**
* ConstantMethodRef constructor.
* @param type The class this constant is a member of.
*/
public ConstantMethodRef(Type type) {
super(type);
}//ConstantMethodRef()//
/**
* ConstantMethodRef constructor.
* @param type The class this constant is a member of.
* @param classIndex The index of the class constant.
* @param nameAndTypeIndex The index of the name and type descriptor constant.
*/
public ConstantMethodRef(Type type, short classIndex, short nameAndTypeIndex) {
super(type);
this.classIndex = classIndex;
this.nameAndTypeIndex = nameAndTypeIndex;
}//ConstantMethodRef()//
/**
* Gets the constant pool index for the class that defines the method (a ConstantType instance).
* @return The pool index of the class constant.
*/
public short getClassIndex() {
return classIndex;
}//getClassIndex()//
/**
* Gets the constant pool index for the name and type for the method (a ConstantNameAndType instance).
* @return The pool index of the name and type constant.
*/
public short getNameAndTypeIndex() {
return nameAndTypeIndex;
}//getNameAndTypeIndex()//
/* (non-Javadoc)
* @see com.de22.javabytecode.ITypeComponent#getSize()
*/
public int getSize() {
return 4;
}//getSize()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getTag()
*/
public byte getTag() {
return CONSTANT_METHOD_REF;
}//getTag()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return (classIndex << 4) | nameAndTypeIndex;
}//hashCode()//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return (object instanceof ConstantMethodRef) && (((ConstantMethodRef) object).classIndex == classIndex) && (((ConstantMethodRef) object).nameAndTypeIndex == nameAndTypeIndex);
}//equals()//
/* (non-Javadoc)
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
classIndex = in.readShort();
nameAndTypeIndex = in.readShort();
}//readExternal()//
/* (non-Javadoc)
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort(classIndex);
out.writeShort(nameAndTypeIndex);
}//writeExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
Constant definingTypeConstant = getType().getConstant(classIndex);
Constant nameAndTypeConstant = getType().getConstant(nameAndTypeIndex);
Constant methodSignatureConstant = null;
Constant methodNameConstant = null;
if(definingTypeConstant instanceof ConstantType) {
definingTypeConstant = getType().getConstant(((ConstantType) definingTypeConstant).getNameIndex());
}//if//
if(definingTypeConstant instanceof ConstantString) {
definingTypeConstant = getType().getConstant(((ConstantString) definingTypeConstant).getStringIndex());
}//if//
if(nameAndTypeConstant instanceof ConstantNameAndType) {
methodNameConstant = getType().getConstant(((ConstantNameAndType) nameAndTypeConstant).getNameIndex());
methodSignatureConstant = getType().getConstant(((ConstantNameAndType) nameAndTypeConstant).getDescriptorIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(methodSignatureConstant instanceof ConstantString) {
methodSignatureConstant = getType().getConstant(((ConstantString) methodSignatureConstant).getStringIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(methodNameConstant instanceof ConstantString) {
methodNameConstant = getType().getConstant(((ConstantString) methodNameConstant).getStringIndex());
}//if//
return definingTypeConstant instanceof ConstantUtf8 && methodNameConstant instanceof ConstantUtf8 && methodSignatureConstant instanceof ConstantUtf8 ? ((ConstantUtf8) definingTypeConstant).getValue() + "." + ((ConstantUtf8) methodNameConstant).getValue() + ((ConstantUtf8) methodSignatureConstant).getValue() + " (Method Name)" : "Error: Unexpected Constant Reference";
}//getPrettyValue()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return "Method Reference (classIndex: " + classIndex + " nameAndTypeIndex: " + nameAndTypeIndex;
}//toString()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Component#toString(java.lang.StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Method Reference Constant (classIndex=");
buffer.append(classIndex);
buffer.append(" nameAndTypeIndex=");
buffer.append(nameAndTypeIndex);
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
}//ConstantMethodRef//

View File

@@ -0,0 +1,138 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* A reference to a method or field name and signature (descriptor).
*/
public class ConstantNameAndType extends Constant {
/** The index of the name of the method (ie: 'parseInt'). */
private short nameIndex = 0;
/** The index of the method or field descriptor (ie: '(Ljava/lang/String;)I' or for a field: 'Ljava/lang/String;' without quotes of course). */
private short descriptorIndex = 0;
/**
* ConstantNameAndType constructor.
* @param type The class this constant is a member of.
*/
public ConstantNameAndType(Type type) {
super(type);
}//ConstantNameAndType()//
/**
* ConstantNameAndType constructor.
* @param type The class this constant is a member of.
* @param nameIndex The index of the name constant.
* @param descriptorIndex The descriptor constant index.
*/
public ConstantNameAndType(Type type, short nameIndex, short descriptorIndex) {
super(type);
this.nameIndex = nameIndex;
this.descriptorIndex = descriptorIndex;
}//ConstantNameAndType()//
/**
* Gets the constant pool index for the name.
* @return The index in the type's constant pool for the name which should be a ConstantUtf8.
*/
public short getNameIndex() {
return nameIndex;
}//getNameIndex()//
/**
* Gets the constant pool index for the descriptor.
* @return The index in the type's constant pool for the descriptor.
*/
public short getDescriptorIndex() {
return descriptorIndex;
}//getDescriptorIndex()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return (nameIndex << 4) | descriptorIndex;
}//hashCode()//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return (object instanceof ConstantNameAndType) && (((ConstantNameAndType) object).nameIndex == nameIndex) && (((ConstantNameAndType) object).descriptorIndex == descriptorIndex);
}//equals()//
/* (non-Javadoc)
* @see com.de22.javabytecode.ITypeComponent#getSize()
*/
public int getSize() {
return 4;
}//getSize()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getTag()
*/
public byte getTag() {
return CONSTANT_NAME_AND_TYPE;
}//getTag()//
/* (non-Javadoc)
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
nameIndex = in.readShort();
descriptorIndex = in.readShort();
}//readExternal()//
/* (non-Javadoc)
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort(nameIndex);
out.writeShort(descriptorIndex);
}//writeExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
Constant fieldTypeConstant = getType().getConstant(getDescriptorIndex());
Constant fieldNameConstant = getType().getConstant(getNameIndex());
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(fieldTypeConstant instanceof ConstantType) {
fieldTypeConstant = getType().getConstant(((ConstantType) fieldTypeConstant).getNameIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(fieldTypeConstant instanceof ConstantString) {
fieldTypeConstant = getType().getConstant(((ConstantString) fieldTypeConstant).getStringIndex());
}//if//
//Shouldn't ever be this type of constant.. but we will add it just in case.//
if(fieldNameConstant instanceof ConstantString) {
fieldNameConstant = getType().getConstant(((ConstantString) fieldNameConstant).getStringIndex());
}//if//
return fieldTypeConstant instanceof ConstantUtf8 && fieldNameConstant instanceof ConstantUtf8 ? ((ConstantUtf8) fieldTypeConstant).getValue() + " " + ((ConstantUtf8) fieldNameConstant).getValue() + " (Name & Type)" : "Error: Unexpected Constant Reference";
}//getPrettyValue()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
Constant descriptorConstant = getType().getConstant(descriptorIndex);
Constant nameConstant = getType().getConstant(nameIndex);
return "Descriptor: " + (descriptorConstant instanceof ConstantNameAndType ? (" DescriptorIndex: " + descriptorIndex + "<--ERROR") : descriptorConstant.toString()) + (nameConstant instanceof ConstantNameAndType ? (" NameIndex: " + nameIndex + "<--ERROR") : (" Name: " + getType().getConstant(nameIndex)));
}//toString()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Component#toString(java.lang.StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Name & Type Constant (nameIndex=");
buffer.append(nameIndex);
buffer.append(" descriptorIndex=");
buffer.append(descriptorIndex);
buffer.append(" value='");
buffer.append(toString());
buffer.append('\'');
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
}//ConstantNameAndType//

View File

@@ -0,0 +1,110 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* References a string in the constant pool.
*/
public class ConstantString extends Constant {
private short stringIndex = 0;
/**
* ConstantString constructor.
* @param type The class this constant is a member of.
*/
public ConstantString(Type type) {
super(type);
}//ConstantString()//
/**
* ConstantString constructor.
* @param type The class this constant is a member of.
*/
public ConstantString(Type type, short stringIndex) {
super(type);
this.stringIndex = stringIndex;
}//ConstantString()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantString) && (((ConstantString) object).stringIndex == stringIndex);
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return 2;
}//getSize()//
/**
* Gets the constant pool index of the string which should be a ConstantUtf8 object.
* @return The index in the constant pool of the actual string.
*/
public short getStringIndex() {
return stringIndex;
}//getStringIndex()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_STRING;
}//getTag()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return stringIndex;
}//hashCode()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
stringIndex = in.readShort();
}//readExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
Constant constant = getType().getConstant(stringIndex);
return constant instanceof ConstantUtf8 ? "\"" + ((ConstantUtf8) constant).getValue().replaceAll("\n", "\\\\n").replaceAll("\r", "\\\\r").replace("\t", "\\\\t") + "\" (String w/o Quotes)" : "Error: Unexpected Constant Reference";
}//getPrettyValue()//
/**
* Gets a string representation of this object.
* @return A string that represents this object.
*/
public String toString() {
return "String" + (getType().getConstant(stringIndex) instanceof ConstantString ? " Index: " + stringIndex + " <--ERROR" : ": " + getType().getConstant(stringIndex));
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("String Constant (index=");
buffer.append(stringIndex);
buffer.append(" value='");
buffer.append(getType().getConstant(stringIndex).toString());
buffer.append('\'');
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort(stringIndex);
}//writeExternal()//
}//ConstantString//

View File

@@ -0,0 +1,106 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* A reference to a class name constant.
*/
public class ConstantType extends Constant {
/** The index of the class name (ie: 'com/common/util/LiteList'). */
private short nameIndex = 0;
/**
* ConstantType constructor.
*/
public ConstantType(Type type) {
super(type);
}//ConstantType()//
/**
* ConstantType constructor.
* @param type The class this constant is a member of. <b>Warning: This type must be in the class file format for class names.</b>
*/
public ConstantType(Type type, short nameIndex) {
super(type);
this.nameIndex = nameIndex;
}//ConstantType()//
/**
* Gets the class name's index within the type's constant pool.
* @return The constant pool index of the class name.
*/
public short getNameIndex() {
return nameIndex;
}//getNameIndex()//
/* (non-Javadoc)
* @see com.de22.javabytecode.ITypeComponent#getSize()
*/
public int getSize() {
return 2;
}//getSize()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getTag()
*/
public byte getTag() {
return CONSTANT_CLASS;
}//getTag()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return nameIndex;
}//hashCode()//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return (object instanceof ConstantType) && (((ConstantType) object).nameIndex == nameIndex);
}//equals()//
/* (non-Javadoc)
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
nameIndex = in.readShort();
}//readExternal()//
/* (non-Javadoc)
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort(nameIndex);
}//writeExternal()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
Constant constant = getType().getConstant(nameIndex);
if(constant instanceof ConstantString) {
constant = getType().getConstant(((ConstantString) constant).getStringIndex());
}//if//
return constant instanceof ConstantUtf8 ? "\"" + ((ConstantUtf8) constant).getValue() + "\" (Type w/o Quotes)" : "Error: Unexpected Constant Reference";
}//getPrettyValue()//
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return getType().getConstant(nameIndex) instanceof ConstantType ? "NameIndex: " + nameIndex + " <--ERROR" : "Name: " + getType().getConstant(nameIndex);
}//toString()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Component#toString(java.lang.StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("Class Constant (index=");
buffer.append(nameIndex);
buffer.append(" value='");
buffer.append(getType().getConstant(nameIndex).toString());
buffer.append('\'');
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
}//ConstantType//

View File

@@ -0,0 +1,154 @@
package com.de22.javabytecode.constant;
import java.io.IOException;
import com.common.debug.*;
import com.de22.javabytecode.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ConstantUtf8 extends Constant {
private static final String UTF8_ENCODING = "UTF8";
private byte[] bytes = null;
private String value = null;
/**
* ConstantUtf8 constructor.
* @param type The class this constant is a member of.
*/
public ConstantUtf8(Type type) {
super(type);
}//ConstantUtf8()//
/**
* ConstantUtf8 constructor.
* @param type The class this constant is a member of.
* @param value The value of the constant.
*/
public ConstantUtf8(Type type, String value) {
super(type);
setValue(value);
}//ConstantUtf8()//
/**
* Determines whether the two objects are logically equal.
* @param object The object to compare with this object.
* @return Whether they are logically equal.
*/
public boolean equals(Object object) {
return (object instanceof ConstantUtf8) && (((((ConstantUtf8) object).getValue() == null) && (getValue() == null)) || ((((ConstantUtf8) object).getValue() != null) && ((ConstantUtf8) object).getValue().equals(getValue())));
}//equals()//
/**
* Gets the size in number of bytes of the component and all subcomponents.
* @return The number of bytes required to represent the component and all subcomponents.
*/
public int getSize() {
return getValueBytes().length + 2;
}//getSize()//
/**
* Gets this class' identifying constant.
* @return The constant value that identifies this constant object type.
*/
public byte getTag() {
return CONSTANT_UTF8;
}//getTag()//
/**
* Gets the value for this associated with this constant.
* @return The string value.
*/
public String getValue() {
return value;
}//getValue()//
/**
* Gets the byte array value for the string. The bytes will be created if they have not yet.
* @return The string value as a byte array.
*/
public byte[] getValueBytes() {
if(bytes == null) {
try {
bytes = value.getBytes(UTF8_ENCODING);
}//try//
catch(java.io.UnsupportedEncodingException e) {
Debug.log(e);
Debug.halt();
}//catch//
}//if//
return bytes;
}//getValueBytes()//
/**
* Gets the hash code for the constant.
* @return The constant hash code.
*/
public int hashCode() {
return value != null ? value.hashCode() : 0;
}//hashCode()//
/**
* Reads this object from the given stream.
* @param in The input stream to read this object from.
*/
public void readExternal(java.io.ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
int readCount = 0;
int size = (((int) (((byte) in.read()) & 0xFF) << 8) + ((int) (((byte) in.read()) & 0xFF)));
bytes = new byte[size];
while(readCount != bytes.length) {
readCount += in.read(bytes, readCount, bytes.length - readCount);
}//while//
convertToString(bytes);
}//readExternal()//
/**
* Converts the bytes into a UTF8 string.
* <p>Note: This method was created to house this one line of code due to a VM error or compiler error in JDK 1.5_08. For some strange reason separating the line allows the app to not crash and a correct value to be returned.</p>
* @param bytes
* @throws IOException
* @throws ClassNotFoundException
*/
private void convertToString(byte[] bytes) throws IOException, ClassNotFoundException {
value = new String(bytes, UTF8_ENCODING);
}//convertToString()//
/**
* Sets the value for this associated with this constant.
* @param value The string value.
*/
public void setValue(String value) {
this.value = value;
this.bytes = null;
}//getValue()//
/* (non-Javadoc)
* @see com.de22.javabytecode.Constant#getPrettyValue()
*/
public String getPrettyValue() {
return "\"" + value.replaceAll("\n", "\\\\n").replaceAll("\r", "\\\\r").replaceAll("\t", "\\\\t") + "\" (UTF8 w/o Quotes)";
}//getPrettyValue()//
/**
* Provides a debug output string representing this object.
* @return A debug string representing this object.
*/
public String toString() {
return value.replaceAll("\n", "\\\\n").replaceAll("\r", "\\\\r").replaceAll("\t", "\\\\t");
}//toString()//
/**
* @see Component.toString(StringBuffer, int)
*/
public void toString(StringBuffer buffer, int tabCount) {
appendTabs(buffer, tabCount);
buffer.append("UTF8 Constant (");
buffer.append(value.replaceAll("\n", "\\\\n").replaceAll("\r", "\\\\r").replaceAll("\t", "\\\\t"));
buffer.append(')');
appendEndOfLine(buffer);
}//toString()//
/**
* Writes this object to the given stream.
* @param out The output stream to write this object to.
*/
public void writeExternal(java.io.ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeShort((short) getValueBytes().length);
out.write(getValueBytes());
}//writeExternal()//
}//ConstantUtf8//

View File

@@ -0,0 +1,205 @@
package com.de22.javabytecode.generator;
import java.io.IOException;
import java.lang.reflect.Modifier;
import com.common.io.*;
import com.common.debug.*;
import com.de22.javabytecode.*;
import com.de22.javabytecode.code.*;
/**
* Copyright Declarative Engineering LLC 1999<p>
* Provides some assistance methods for generating a class.
*/
public abstract class ClassGenerator {
public static final String INIT_METHOD_NAME = "<init>";
//private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
protected StringBuffer sharedBuffer = new StringBuffer(500); //A shared string buffer that can be used by the class generator and subclasses to temporarily buffer data within the method. Warning: This is reused by many methods so make sure you don't store anything important before calling another method.//
private Type type = null;
/**
* ClassGenerator constructor.
*/
private ClassGenerator() {
super();
}//ClassGenerator()//
/**
* ClassGenerator constructor.
*/
public ClassGenerator(String qualifiedClassName) {
super();
createClass(qualifiedClassName);
}//ClassGenerator()//
/**
* Creates a new type. All subsequent operations are against this type.
* <p>TODO: Provide more input to this method to allow different access flags and such.
* @param qualifiedClassName The fully qualified class name of this new class. Must use '/' instead of '.' & do not use a '.class' or '.java' extention.
*/
protected void createClass(String qualifiedClassName) {
try {
Type type = new Type(qualifiedClassName);
type.setAccessFlags((short) (Type.ACC_PUBLIC | Type.ACC_SUPER));
type.setMajorVersion((short) 45);
type.setMinorVersion((short) 3);
setType(type);
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
}//createClass()//
/**
* Creates the one and only init method which should at the very least call the super classes' init method.
* <p>TODO: Stop ignoring the passed byte codes and instead add them in the mix.
* @param superClass The class that this class will inherit from.
* @param code This parameter is currently ignored.
*/
public void createInitMethod(Class superClass, byte[] code) {
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream(20, false);
StandardOutputStream out = new StandardOutputStream(bout);
short superInitIndex = getType().addConstantMethod(superClass, null, INIT_METHOD_NAME, new Class[0]);
out.writeByte((byte) 42); //aload_0
out.writeByte((byte) 183); //invokespecial -> invoke super class' <init> method.
out.writeShort((short) superInitIndex);
out.writeByte((byte) 177); //return
//Add the method to the type.//
getType().addMethod(Modifier.PUBLIC, null, INIT_METHOD_NAME, new Class[0], bout.toByteArray(), 1, 1);
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
}//createInitMethod()//
/**
* Formats a descriptor string using the parameters and return type of the method.
* This is used to create method descriptors for a class file.
* <p>Example: void methodName(double[] a, String b) -> ([DLjava/lang/String;)V;
* @param returnType The descriptor's return type.
* @param parameterTypes The descriptor's parameter types (in order of parameter).
* @return The formatted type string.
*/
protected String formatDescriptor(Class returnType, Class[] parameterTypes) {
sharedBuffer.setLength(0);
FormatSupport.formatDescriptor(returnType, parameterTypes, sharedBuffer);
return sharedBuffer.toString();
}//formatDescriptor()//
/**
* Formats a non-primitive class to a class file compatible string.
* <p>NOTE: This method will not place an "L" at the beginning or a ";" at the end of the formatted string.
* @param type The non-primitive class to convert to a string.
* @return The string representation of the type.
*/
protected String formatNonPrimitiveType(String qualifiedTypeName) {
sharedBuffer.setLength(0);
FormatSupport.formatNonPrimitiveType(qualifiedTypeName, sharedBuffer);
return sharedBuffer.toString();
}//formatNonPrimitiveType()//
/**
* Formats a class to a class file compatible string.
* @param type The class to convert to a string.
* @return The formatted type string.
*/
protected String formatType(Class type) {
sharedBuffer.setLength(0);
FormatSupport.formatType(type, sharedBuffer);
return sharedBuffer.toString();
}//formatType()//
/**
* Generates a method signature string from the method.
* @param method The method whose signature should be generated.
*/
protected static String generateMethodSignature(java.lang.reflect.Method method) {
try {
StringBuffer signature = new StringBuffer(100);
Class[] parameterTypes = method.getParameterTypes();
for(int index = 0; index < parameterTypes.length; index++) {
if(signature == null) {
signature = new StringBuffer(100);
}//if//
else {
signature.append(',');
signature.append(' ');
}//else//
signature.append(parameterTypes[index].getName());
}//for//
signature.append('(');
if(signature != null) {
signature.append(signature);
}//if//
signature.append(')');
return signature.toString();
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
return "";
}//catch//
}//generateMethodSignature()//
/**
* Gets the classes' byte codes.
* @return The array of byte codes for the class.
*/
public byte[] getClassByteCodes() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(1000, false);
getType().writeExternal(new ObjectOutputStream(out, null));
return out.toByteArray();
}//getClassByteCodes()//
/**
* Gets the classes' type object.
* @return The type object describing the class byte codes.
*/
public Type getType() {
return type;
}//getType()//
/**
* Sets the classes' source file reference.
* <p>TODO: Implement this properly by adding an addAttributeSourceFile method to the Type class.
* @param path The path to the source file that created this class.
*/
public void setSourceFile(String path) {
try {
//Type type = getType();
//SourceFile sourceFile = new SourceFile(type, path);
//Add the attribute to the class.//
//type.addAttribute(sourceFile);
}//try//
catch(Throwable e) {
Debug.log(e);
Debug.halt();
}//catch//
}//setSuperClass()//
/**
* Sets the super class for this class.
* @param qualifiedSuperClassName The qualified class name of the super class. This string will be reformatted for use in the class byte codes.
*/
public void setSuperClass(String qualifiedSuperClassName) {
Type type = getType();
type.setSuperClass(formatNonPrimitiveType(qualifiedSuperClassName));
}//setSuperClass()//
/**
* Sets the classes' type object.
* @param type The type object describing the class byte codes.
*/
private void setType(Type type) {
this.type = type;
}//setType()//
}//ClassGenerator//

View File

@@ -0,0 +1,54 @@
package com.de22.javabytecode.io;
import java.io.IOException;
import com.common.io.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
*/
public class ByteCodeOutputStream extends StandardOutputStream {
/**
* ByteCodeOutputStream constructor.
* The size of the initial buffer in bytes.
*/
public ByteCodeOutputStream(int bufferSize) {
super(new BufferedOutputStream(new ByteArrayOutputStream(bufferSize, false)));
}//ByteCodeOutputStream()//
/**
* ByteCodeOutputStream constructor.
* @param outputStream The buffered output stream to wrapper.
*/
protected ByteCodeOutputStream(BufferedOutputStream outputStream) {
super(outputStream);
}//ByteCodeOutputStream()//
/**
* @see BufferedOutputStream.getByteIndex()
*/
public int getByteIndex() {
return ((BufferedOutputStream) getOutputStream()).getByteIndex();
}//getByteIndex()//
/**
* @see BufferedOutputStream.getInsertOutputStream(int)
*/
public ByteCodeOutputStream getInsertOutputStream(int reservedByteCount) throws IOException {
return new ByteCodeOutputStream(((BufferedOutputStream) getOutputStream()).getInsertOutputStream(reservedByteCount));
}//getInsertOutputStream()//
/**
* @see BufferedOutputStream.getInsertOutputStream(int, int)
*/
public ByteCodeOutputStream getInsertOutputStream(int bufferSize, int incrementSize) throws IOException {
return new ByteCodeOutputStream(((BufferedOutputStream) getOutputStream()).getInsertOutputStream(bufferSize, incrementSize));
}//getInsertOutputStream()//
/**
* @see BufferedOutputStream.getOutputStreamLocation()
*/
public IOutputStreamLocation getOutputStreamLocation() throws IOException {
return ((BufferedOutputStream) getOutputStream()).getOutputStreamLocation();
}//getOutputStreamLocation()//
/**
* @see ByteArrayOutputStream.toByteArray()
*/
public byte[] toByteArray() throws IOException {
return ((BufferedOutputStream) getOutputStream()).toByteArray();
}//toByteArray()//
}//ByteCodeOutputStream//

View File

@@ -0,0 +1,115 @@
package com.de22.javabytecode.util;
import com.common.debug.*;
/**
* Copyright Wynne Crisman 1999,2006<p>
* Assists the code in tracking the stack size at any given time, and the total stack size of a segment of code.
*/
public class StackTracker {
private int stackSize = 0; //The current stack size of the code segment.//
private int maxStackSize = 0; //The maximum stack size of the code segment.//
/**
* StackTracker constructor.
*/
public StackTracker() {
super();
}//StackTracker()//
/**
* StackTracker constructor.
*/
protected StackTracker(int stackSize, int maxStackSize) {
super();
this.stackSize = stackSize;
this.maxStackSize = maxStackSize;
}//StackTracker()//
/**
* Derements the stack size by one.
*/
public void decrement() {
stackSize--;
}//decrement()//
/**
* Derements the stack size by <code>count</code>.
* @param count The count by which the stack should be decremented.
*/
public void decrement(int count) {
stackSize -= count;
}//decrement()//
/**
* Gets the maximum size of the stack at any point in the code segment.
* @return The maximum size the stack took durring its life.
*/
public int getMaxStackSize() {
return maxStackSize;
}//getMaxStackSize()//
/**
* Gets the current stack size.
* @return The size of the stack at the current point in the code.
*/
public int getStackSize() {
return stackSize;
}//getStackSize()//
/**
* Increments the stack size by one.
*/
public void increment() {
stackSize++;
if(maxStackSize < stackSize) {
maxStackSize = stackSize;
}//if//
}//increment()//
/**
* Increments the stack size by <code>count</code>.
* @param count The count by which the stack should be incremented.
*/
public void increment(int count) {
stackSize += count;
if(maxStackSize < stackSize) {
maxStackSize = stackSize;
}//if//
}//increment()//
/**
* Merges the stack trackers into one.
* This is useful when the code branches at it is necessary to merge two separate branches of the code.
* <p>Important: The stack trackers must have the same stack size in order to be merged! A runtime exception will ensue if they are not equal.
* @param stackTracker The stack tracker to merge with this stack tracker. The passed stack tracker will not be affected.
*/
public void merge(StackTracker stackTracker) {
//Ensure that both stacks have the same size.//
if(stackTracker.stackSize != stackSize) {
Debug.halt();
throw new RuntimeException("Critical Error: Unable to merge the stack data.");
}//if//
//Set the greater of the two maximum stack size values.//
if(stackTracker.maxStackSize > maxStackSize) {
maxStackSize = stackTracker.maxStackSize;
}//if//
}//merge()//
/**
* Resets the tracker counts.
*/
public void reset() {
stackSize = 0;
maxStackSize = 0;
}//reset()//
/**
* Splits the stack tracker into two.
* This is useful when the code branches at it is necessary to track two separate branches of the code.
* @return A duplicate stack tracker.
*/
public StackTracker split() {
return new StackTracker(stackSize, maxStackSize);
}//split()//
/**
* Gets a debug string for the stack tracker.
* @return A string representing the current state of the stack tracker.
*/
public String toString() {
return "StackTracker[stackSize = " + stackSize + ", maxStackSize = " + maxStackSize + "]";
}//toString()//
}//StackTracker//

9
Common Test/.classpath Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry combineaccessrules="false" kind="src" path="/Class File Services"/>
<classpathentry combineaccessrules="false" kind="src" path="/Common"/>
<classpathentry combineaccessrules="false" kind="src" path="/Orb"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>

17
Common Test/.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Common Test</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,47 @@
package com.softwarezealot.common.io.test;
import com.common.debug.*;
import com.common.util.*;
import com.common.io.*;
/**
* Copyright Wynne Crisman 1999-2002<p>
*/
public class BufferedOutputStreamTest {
/**
* Starts the application.
* @param args An array of command-line arguments.
*/
public static void main(java.lang.String[] args) {
byte[] bytes = null;
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream(50, false);
BufferedOutputStream bufOut = new BufferedOutputStream(bout, 100);
BufferedOutputStream bufOut2 = null;
StandardOutputStream sout = new StandardOutputStream(bufOut);
StandardOutputStream sout2 = null;
sout.writeByte(0);
sout.writeByte(1);
sout.writeByte(2);
bufOut2 = bufOut.getInsertOutputStream(10, 10);
sout2 = new StandardOutputStream(bufOut2);
sout.writeByte(5);
sout.writeByte(6);
sout.writeByte(7);
sout2.writeByte(3);
sout2.writeByte(4);
sout2.close();
sout.flush();
bytes = bout.toByteArray();
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
System.out.println("Done");
System.exit(0);
}//main()//
}

View File

@@ -0,0 +1,591 @@
package com.softwarezealot.common.io.test;
import com.common.debug.*;
import com.common.util.*;
import com.common.io.*;
import com.common.security.*;
/**
* Copyright Wynne Crisman 1999,2003<p>
*/
public class SecurityStreamTests {
/**
* SecurityStreamTests constructor comment.
*/
public SecurityStreamTests() {
super();
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void main(java.lang.String[] args) {
//testHash();
testSymmetricEncryption();
//testSignatureEncryption();
//testAsymmetricEncryption();
//testWritePrivateKey();
//testWriteCompressedData();
//testWriteCompressedEncryptedData();
//testReadKey();
//testWriteCompressedHashedData();
//testDeflation();
System.out.println("Done");
System.exit(0);
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void testAsymmetricEncryption() {
System.out.println("Testing Asymmetric");
long t = System.currentTimeMillis();
try {
IAsymmetricAlgorithm privateAlgorithm = new RsaAlgorithm(1024);
IAsymmetricAlgorithm publicAlgorithm = privateAlgorithm.getPublicAsymmetricAlgorithm();
ByteArrayOutputStream bout = new ByteArrayOutputStream(1000, false);
AsymmetricOutputStream out = new AsymmetricOutputStream(bout, publicAlgorithm);
byte[] source = new byte[500];
Random random = new Random();
random.nextBytes(source);
out.encrypt(true);
out.write(source);
out.encrypt(false);
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
AsymmetricInputStream in = new AsymmetricInputStream(bin, privateAlgorithm);
byte[] received = new byte[500];
in.decrypt(true);
in.read(received);
in.decrypt(false);
for(int i = 0; i < received.length; i++) {
if(source[i] != received[i]) {
System.out.println("Failed Asymmetric Test");
break;
}//if//
}//for//
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
t = System.currentTimeMillis() - t;
System.out.println("Finished Testing Asymmetric; Time: " + t + "ms");
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void testDeflation() {
System.out.println("Testing deflation");
long t = System.currentTimeMillis();
try {
int size = 100;
byte[] data = new byte[size << 1];
Random random = new Random();
java.util.zip.Deflater deflater = new java.util.zip.Deflater(5, true);
java.util.zip.Inflater inflater = new java.util.zip.Inflater(true);
byte[] deflated = new byte[size << 2];
byte[] inflated = new byte[size << 1];
int inflatedCount = 0;
int deflatedCount = 0;
random.nextBytes(data);
deflater.setInput(data, 0, size);
deflatedCount += deflater.deflate(deflated, deflatedCount, deflated.length - deflatedCount);
deflater.finish();
deflatedCount += deflater.deflate(deflated, deflatedCount, deflated.length - deflatedCount);
deflater.reset();
deflater.setInput(data, size, size);
deflatedCount += deflater.deflate(deflated, deflatedCount, deflated.length - deflatedCount);
deflater.finish();
deflatedCount += deflater.deflate(deflated, deflatedCount, deflated.length - deflatedCount);
System.out.println("Deflated " + deflatedCount + " bytes.");
/*
for(int i = 0, incrementSize = 105; i < deflatedCount; i += incrementSize) {
int count = 0;
inflater.setInput(deflated, i, incrementSize);
do {
count = inflater.inflate(inflated, inflatedCount, 1);
inflatedCount += count;
} while(count > 0);
}//for//
*/
int count = 0;
int deflatedIndex = 0;
//Read the first 100 data elements.//
while(inflatedCount < 100) {
if((count = inflater.inflate(inflated, inflatedCount, 100 - inflatedCount)) == 0) {
if((inflater.finished()) || (inflater.needsDictionary())) {
//What to do?//
break;
}//if//
if(inflater.needsInput()) {
inflater.setInput(deflated, deflatedIndex, 1);
deflatedIndex += 1;
}//if//
}//if//
else {
inflatedCount += count;
}//else//
}//while//
//Read the second 100 data elements.//
while(inflatedCount < 200) {
if((count = inflater.inflate(inflated, inflatedCount, 200 - inflatedCount)) == 0) {
if((inflater.finished()) || (inflater.needsDictionary())) {
//What to do?//
inflater.reset();
}//if//
if(inflater.needsInput()) {
inflater.setInput(deflated, deflatedIndex, 1);
deflatedIndex += 1;
}//if//
}//if//
else {
inflatedCount += count;
}//else//
}//while//
//Test the received data.//
if(inflatedCount == data.length) {
boolean isOk = true;
for(int i = 0; (isOk) && (i < data.length); i++) {
if(inflated[i] != data[i]) {
isOk = false;
System.out.println("Error: Data validation failed on index " + i);
}//if//
}//for//
if(isOk) {
System.out.println("Data validated sucessfully.");
}//if//
}//if//
else {
System.out.println("Error: Only inflated " + inflatedCount + " bytes.");
}//else//
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
t = System.currentTimeMillis() - t;
System.out.println("Finished Testing Deflation; Time: " + t + "ms");
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void testHash() {
System.out.println("Testing Hash");
long t = System.currentTimeMillis();
try {
IHashAlgorithm algorithm = new Sha1();
ByteArrayOutputStream bout = new ByteArrayOutputStream(1000, false);
HashedOutputStream out = new HashedOutputStream(bout, algorithm);
byte[] source = new byte[500];
Random random = new Random();
random.nextBytes(source);
out.hash(true);
out.write(source);
out.writeHash();
out.hash(false);
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
HashedInputStream in = new HashedInputStream(bin, algorithm);
byte[] received = new byte[500];
byte[] remoteHash = new byte[algorithm.getHashSize()];
byte[] localHash = null;
in.hash(true);
in.read(received);
localHash = in.getHash();
in.read(remoteHash);
in.hash(false);
for(int i = 0; i < received.length; i++) {
if(source[i] != received[i]) {
System.out.println("Hashed Stream Failed");
break;
}//if//
}//for//
for(int i = 0; i < localHash.length; i++) {
if(remoteHash[i] != localHash[i]) {
System.out.println("Hash Failed");
break;
}//if//
}//for//
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
t = System.currentTimeMillis() - t;
System.out.println("Finished Testing Hash; Time: " + t + "ms");
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void testReadKey() {
System.out.println("Testing reading a private key from file: c:\\temp\\temp.prk");
long t = System.currentTimeMillis();
try {
int size = 20;
ISymmetricAlgorithm algorithm = new Rijndael("bane");
java.io.FileInputStream fin = new java.io.FileInputStream("c:\\temp\\test.prk");
SymmetricInputStream sin = new SymmetricInputStream(fin, algorithm);
ObjectInputStream in = new ObjectInputStream(sin, null, null);
ISignatureAlgorithm receivedSignature = null;
in.decrypt(true);
receivedSignature = (ISignatureAlgorithm) in.readObject();
in.decrypt(false);
fin.close();
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
t = System.currentTimeMillis() - t;
System.out.println("Finished Testing Key File Reading; Time: " + t + "ms");
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void testSignatureEncryption() {
System.out.println("Testing Signature");
long t = System.currentTimeMillis();
try {
ISignatureAlgorithm privateAlgorithm = new RsaAlgorithm(1024);
ISignatureAlgorithm publicAlgorithm = privateAlgorithm.getPublicSignatureAlgorithm();
ByteArrayOutputStream bout = new ByteArrayOutputStream(1000, false);
SignatureOutputStream out = new SignatureOutputStream(bout, privateAlgorithm);
byte[] source = new byte[500];
Random random = new Random();
random.nextBytes(source);
out.encrypt(true);
out.write(source);
out.encrypt(false);
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
SignatureInputStream in = new SignatureInputStream(bin, publicAlgorithm);
byte[] received = new byte[500];
in.decrypt(true);
in.read(received);
in.decrypt(false);
for(int i = 0; i < received.length; i++) {
if(source[i] != received[i]) {
System.out.println("Failed Signature");
break;
}//if//
}//for//
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
t = System.currentTimeMillis() - t;
System.out.println("Finished Testing Signature; Time: " + t + "ms");
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void testSymmetricEncryption() {
System.out.println("Testing Symmetric");
long t = System.currentTimeMillis();
try {
int size = 1400;
ISymmetricAlgorithm algorithm = new Rijndael("test");
ByteArrayOutputStream bout = new ByteArrayOutputStream(1000, false);
SymmetricOutputStream out = new SymmetricOutputStream(bout, algorithm);
byte[] source = new byte[size];
Random random = new Random();
random.nextBytes(source);
out.encrypt(true);
out.write(source);
out.encrypt(false);
out.flush();
algorithm = new Rijndael("test");
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
SymmetricInputStream in = new SymmetricInputStream(bin, algorithm);
byte[] received = new byte[size];
in.decrypt(true);
in.read(received);
in.decrypt(false);
for(int i = 0; i < received.length; i++) {
if(source[i] != received[i]) {
System.out.println("Failed Symmetric Test");
break;
}//if//
}//for//
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
t = System.currentTimeMillis() - t;
System.out.println("Finished Testing Symmetric; Time: " + t + "ms");
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void testWriteCompressedData() {
System.out.println("Testing writing a random data to file in c:\\temp");
long t = System.currentTimeMillis();
try {
int size = 3050;
byte[] data = new byte[size];
java.io.FileOutputStream fout = new java.io.FileOutputStream("c:\\temp\\test.tmp", false);
CompressionOutputStream cout = new CompressionOutputStream(fout);
ObjectOutputStream out = new ObjectOutputStream(cout, null);
Random random = new Random();
random.nextBytes(data);
out.write(data);
out.flush();
out.close();
java.io.FileInputStream fin = new java.io.FileInputStream("c:\\temp\\test.tmp");
CompressionInputStream cin = new CompressionInputStream(fin);
ObjectInputStream in = new ObjectInputStream(cin, null, null);
ISignatureAlgorithm receivedSignature = null;
byte[] received = new byte[size];
in.read(received);
in.close();
for(int i = 0; i < received.length; i++) {
if(data[i] != received[i]) {
System.out.println("Failed Test");
break;
}//if//
}//for//
new java.io.File("c:\\temp\\test.tmp").delete();
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
t = System.currentTimeMillis() - t;
System.out.println("Finished Testing File Writing; Time: " + t + "ms");
}
/**
*
*/
public static void testWriteCompressedEncryptedData() {
System.out.println("Testing writing a random data to file in c:\\temp");
long t = System.currentTimeMillis();
try {
int size = 3050;
byte[] data = new byte[size];
ISymmetricAlgorithm algorithm = new Rijndael("test");
java.io.FileOutputStream fout = new java.io.FileOutputStream("c:\\temp\\test.tmp", false);
SymmetricOutputStream sout = new SymmetricOutputStream(fout, algorithm);
CompressionOutputStream cout = new CompressionOutputStream(sout);
ObjectOutputStream out = new ObjectOutputStream(cout, null);
Random random = new Random();
random.nextBytes(data);
out.encrypt(true);
out.write(data);
out.encrypt(false);
out.flush();
out.close();
algorithm = new Rijndael("test");
java.io.FileInputStream fin = new java.io.FileInputStream("c:\\temp\\test.tmp");
SymmetricInputStream sin = new SymmetricInputStream(fin, algorithm);
CompressionInputStream cin = new CompressionInputStream(sin);
ObjectInputStream in = new ObjectInputStream(cin, null, null);
ISignatureAlgorithm receivedSignature = null;
byte[] received = new byte[size];
in.decrypt(true);
in.read(received);
in.decrypt(false);
in.close();
for(int i = 0; i < received.length; i++) {
if(data[i] != received[i]) {
System.out.println("Failed Test");
break;
}//if//
}//for//
new java.io.File("c:\\temp\\test.tmp").delete();
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
t = System.currentTimeMillis() - t;
System.out.println("Finished Testing File Writing; Time: " + t + "ms");
}
/**
*
*/
public static void testWriteCompressedHashedData() {
System.out.println("Preparing test...");
ISignatureAlgorithm privateKey = new RsaAlgorithm(2048);
System.out.println("Testing writing a hashed stream where the hash is signed.");
long t = System.currentTimeMillis();
int streamSize = 0;
try {
boolean isValid = false;
int size = 10;
byte[] data = new byte[] {1, 30, 20, -10, 100, 80, 90, -11, 55, 11}; //new byte[size];
ISignatureAlgorithm publicKey = privateKey.getPublicSignatureAlgorithm();
ByteArrayOutputStream bout = new ByteArrayOutputStream(1000, false);
SignatureOutputStream sout = new SignatureOutputStream(bout, privateKey);
HashedOutputStream hout = new HashedOutputStream(sout, new Sha1());
CompressionOutputStream cout = new CompressionOutputStream(hout);
ObjectOutputStream out = new ObjectOutputStream(cout, null);
out.writeObject(data);
out.encrypt(true);
hout.writeHash();
out.encrypt(false);
out.flush();
out.close();
streamSize = bout.getSize();
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
SignatureInputStream sin = new SignatureInputStream(bin, publicKey);
HashedInputStream hin = new HashedInputStream(sin, new Sha1());
CompressionInputStream cin = new CompressionInputStream(hin);
ObjectInputStream in = new ObjectInputStream(cin, null, null);
byte[] received = null;
received = (byte[]) in.readObject();
in.decrypt(true);
isValid = hin.validateHash();
in.decrypt(false);
in.close();
if(!isValid) {
System.out.println("Failed Validation");
}//if//
else if(data.length == received.length) {
for(int i = 0; i < received.length; i++) {
if(data[i] != received[i]) {
System.out.println("Failed Comparison");
break;
}//if//
}//for//
}//else if//
else {
System.out.println("Failed Read");
}//else//
new java.io.File("c:\\temp\\test.tmp").delete();
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
t = System.currentTimeMillis() - t;
System.out.println("Finished Testing hashed stream; Time: " + t + "ms");
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void testWritePrivateKey() {
System.out.println("Testing writing a private key to file in c:\\temp");
long t = System.currentTimeMillis();
try {
int size = 20;
ISignatureAlgorithm privateSignature = new RsaAlgorithm(1024);
ISignatureAlgorithm publicSignature = privateSignature.getPublicSignatureAlgorithm();
ISymmetricAlgorithm algorithm = new Rijndael("test");
java.io.FileOutputStream fout = new java.io.FileOutputStream("c:\\temp\\test.tmp", false);
SymmetricOutputStream sout = new SymmetricOutputStream(fout, algorithm);
CompressionOutputStream cout = new CompressionOutputStream(sout);
ObjectOutputStream out = new ObjectOutputStream(cout, null);
out.encrypt(true);
out.writeObject(privateSignature);
out.encrypt(false);
out.flush();
out.close();
algorithm = new Rijndael("test");
java.io.FileInputStream fin = new java.io.FileInputStream("c:\\temp\\test.tmp");
SymmetricInputStream sin = new SymmetricInputStream(fin, algorithm);
CompressionInputStream cin = new CompressionInputStream(sin);
ObjectInputStream in = new ObjectInputStream(cin, null, null);
ISignatureAlgorithm receivedSignature = null;
in.decrypt(true);
receivedSignature = (ISignatureAlgorithm) in.readObject();
in.decrypt(false);
in.close();
byte[] source = new byte[size];
Random random = new Random();
byte[] signed = new byte[receivedSignature.getSignedSize(size)];
byte[] unsigned = new byte[size];
random.nextBytes(source);
receivedSignature.sign(source, 0, source.length, signed, 0);
publicSignature.verify(signed, 0, signed.length, unsigned, 0);
for(int i = 0; i < unsigned.length; i++) {
if(source[i] != unsigned[i]) {
System.out.println("Failed Test");
break;
}//if//
}//for//
new java.io.File("c:\\temp\\test.tmp").delete();
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
t = System.currentTimeMillis() - t;
System.out.println("Finished Testing File Writing; Time: " + t + "ms");
}
}

View File

@@ -0,0 +1,185 @@
package com.softwarezealot.common.io.test;
import com.common.system.SystemManager;
import com.common.io.*;
/**
* Copyright Wynne Crisman 1999<p>
*/
public class Test {
/**
* Test constructor comment.
*/
public Test() {
super();
}
public static void main(String[] args) {
try {
//char t = '\uAAAA';
//System.out.println("\\uAAAA\t" + ((int)t) + "\t" + 0xAAAA);
printUnicode16ToUTF8HexCodes();
//System.out.println("" + (0xFFFF));
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
System.exit(0);
}//main()//
/**
* see JDK documentation (JNI section) types.doc.html.
*/
public static void printUnicode16ToUTF8HexCodes() {
try {
byte[] character = new byte[2];
char[] characters = new char[1];
int max = 0xFFFF;
String UTF8 = "UTF8";
String Unicode = "Unicode";
int count = 0;
StringBuffer buffer = new StringBuffer(10000);
byte[] oldUtf8 = null;
int loopNumber = 0;
for(characters[0] = '\u0000'; characters[0] < max; characters[0]++, loopNumber++) {
String str = new String(characters);
byte[] utf8 = str.getBytes(UTF8);
byte[] unicode16 = str.getBytes(Unicode);
int intValue = (int) characters[0];
boolean isSequential = false;
if((oldUtf8 != null) && (oldUtf8.length == utf8.length)) {
int diffCount = 0;
boolean isMoreThanOne = false;
boolean nextByteMustIncrement = false;
for(int index = oldUtf8.length - 1; (!isMoreThanOne) && (index >= 0); index--) {
if((nextByteMustIncrement) && ((oldUtf8[index] + 1) != utf8[index])) {
isMoreThanOne = true;
nextByteMustIncrement = false;
}//if//
else if(oldUtf8[index] != utf8[index]) {
diffCount++;
if((oldUtf8[index] + 1) != utf8[index]) {
if((oldUtf8[index] == 0xFF) && (utf8[index] == 0x00)) {
nextByteMustIncrement = true;
}//if//
else {
isMoreThanOne = true;
}//else//
}//if//
}//else if//
}//for//
if((!isMoreThanOne) && (diffCount == 1)) {
isSequential = true;
}//if//
}//if//
if(!isSequential) {
buffer.append(intValue);
buffer.append('\t');
buffer.append(StreamSupport.getHexString(unicode16));
buffer.append('\t');
buffer.append(StreamSupport.getHexString(utf8));
buffer.append('\r');
buffer.append('\n');
if(count++ > 1000) {
System.out.print(buffer);
buffer.setLength(0);
//com.common.debug.DebugSupport.halt();
count = 0;
}//if//
}//if//
oldUtf8 = utf8;
}//for//
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
}//printUnicode16ToUTF8HexCodes()//
public static void test() {
byte[] bytes = null;
String str = "abcd\u0aaa\u8488\u0799\uffff";
//Test the java conversion.//
try {
long t = System.currentTimeMillis();
for(int index = 0; index < 10000; index++) {
bytes = str.getBytes("UTF8");
}//for//
System.out.println("Time: " + (System.currentTimeMillis() - t));
System.out.println("Before: " + str);
System.out.println("After: " + (new String(bytes, "UTF8")));
System.out.println("Length: " + bytes.length);
System.out.println("Bytes: " + StreamSupport.getHexString(bytes));
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
//Test the software zealot conversion.//
try {
SystemManager.setupSystem(new com.common.system.WindowsSystem(), null, null);
int length = SystemManager.getUtf8StringLength(str);
bytes = new byte[length];
long t = System.currentTimeMillis();
for(int index = 0; index < 10000; index++) {
com.common.system.SystemManager.convertUtf8StringToBytes(str, bytes, 0);
}//for//
System.out.println("Time: " + (System.currentTimeMillis() - t));
System.out.println("Before: " + str);
System.out.println("After: " + (new String(bytes, "UTF8")));
System.out.println("Length: " + length);
System.out.println("Bytes: " + StreamSupport.getHexString(bytes));
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
//Test the software zealot conversion.//
try {
//SystemManager.setupSystem(new com.common.system.WindowsSystem(), null, null);
int length = SystemManager.getUtf8StringLength(str);
bytes = new byte[length];
long t = System.currentTimeMillis();
for(int index = 0; index < 10000; index++) {
int strLength = str.length();
for(int characterIndex = 0; characterIndex < strLength; characterIndex++) {
char ch = str.charAt(characterIndex);
//byte upper = ch >> 8;
//byte lower = ch && 0xFF;
if(ch == 0) {
}//if//
else if(ch < 0x7F) {
}//else if//
else if(ch < 0xFFFF) {
}//else if//
else {
}//else//
}//for//
}//for//
System.out.println("Time: " + (System.currentTimeMillis() - t));
System.out.println("Before: " + str);
System.out.println("After: " + (new String(bytes, "UTF8")));
System.out.println("Length: " + length);
System.out.println("Bytes: " + StreamSupport.getHexString(bytes));
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
System.exit(0);
}//main()//
}

View File

@@ -0,0 +1,40 @@
package com.softwarezealot.common.security.test;
import com.common.debug.*;
import com.common.security.*;
/**
* Copyright Wynne Crisman 1999,2003<p>
*/
public class ElGamalTest {
/**
* ElGamalTest constructor comment.
*/
public ElGamalTest() {
super();
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void main(java.lang.String[] args) {
try {
/*
ElGamal2 a = new ElGamal2(1024, new Random(100L));
String t = "Hello world! Hello world!";
byte[] m = t.getBytes("UTF8");
byte[] c = null;
c = a.encrypt(m);
System.out.println(m.length + " " + c.length);
m = a.decrypt(c);
System.out.println(new String(m, "UTF8"));
*/
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
System.exit(0);
}
}

View File

@@ -0,0 +1,52 @@
package com.softwarezealot.common.security.test;
import com.common.debug.*;
import com.common.security.*;
/**
* Copyright Wynne Crisman 1999,2003<p>
*/
public class RijndaelTest {
/**
* RijndaelTest constructor comment.
*/
public RijndaelTest() {
super();
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void main(String[] args) {
System.out.println("Starting Rijdael Test");
try {
int size = 236;
Rijndael a = new Rijndael("test");
byte[] source = new byte[size];
byte[] encrypted = new byte[a.getEncryptedSize(size)];
a.getUnencryptedSize(encrypted.length);
a.getOptimalEncryptionBlockSize();
a.getOptimalDecryptionBlockSize();
byte[] decrypted = new byte[size];
Random random = new Random();
random.nextBytes(source);
a.encrypt(source, 0, source.length, encrypted, 0);
a.decrypt(encrypted, 0, encrypted.length, decrypted, 0);
for(int i = 0; i < decrypted.length; i++) {
if(source[i] != decrypted[i]) {
System.out.println("Failed Rijdael Test");
break;
}//if//
}//for//
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
System.out.println("Finished Rijdael Test");
System.exit(0);
}
}

View File

@@ -0,0 +1,51 @@
package com.softwarezealot.common.security.test;
import com.common.debug.*;
import com.common.security.*;
/**
* Copyright Wynne Crisman 1999,2003<p>
*/
public class RsaTest {
/**
* RsaTest constructor comment.
*/
public RsaTest() {
super();
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void main(java.lang.String[] args) {
long t = System.currentTimeMillis();
IAsymmetricAlgorithm pri = new RsaAlgorithm();
System.out.println("RSA Startup Time: " + (System.currentTimeMillis() - t));
IAsymmetricAlgorithm pub = null;
Random r = new Random();
byte[] u = new byte[1000];
byte[] d = null;
byte[] e = null;
pri.getPublicKeyBytes();
pub = pri.getPublicAsymmetricAlgorithm();
r.nextBytes(u);
e = pub.encrypt(u);
d = pri.decrypt(e);
if(d.length == u.length) {
for(int index = 0; index < d.length; index++) {
if(d[index] != u[index]) {
Debug.log("Failed");
break;
}//if//
}//for//
}//if//
else {
Debug.log("Incorrect Size");
}//else//
Debug.log("Finished");
System.exit(0);
}
}

View File

@@ -0,0 +1,84 @@
package com.softwarezealot.common.security.test;
import com.common.debug.*;
/**
* Copyright Wynne Crisman 1999-2002<p>
* This class supports and tests the com.common.security.Sha1 algorithm.
*/
public class Sha1Test {
//
// Only two known sets of data!
// Using Hex format 0xAB results in needing casts.
//
private static String[] texts = { "abc", // t 1
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", // t 2
"", // empty, added
};
private static byte[][] bytes = { { -87, -103, 62, 54, 71, 6, -127, 106, -70, 62, 37, 113, 120, 80, -62, 108, -100, -48, -40, -99, }, {
-124, -104, 62, 68, 28, 59, -46, 110, -70, -82, 74, -95, -7, 81, 41, -27, -27, 70, 112, -15, }, {
-38, 57, -93, -18, 94, 107, 75, 13, 50, 85, -65, -17, -107, 96, 24, -112, -81, -40, 7, 9, }, };
/**
* Sha1 constructor.
*/
public Sha1Test() {
super();
}//Sha1()//
/**
* Starts the self test.
*/
public static final void main(String argv[]) {
try {
selfTest();
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
Debug.log("Done.");
System.exit(0);
}//main()//
private static final boolean notEquals(byte[] a, byte[] b) {
for(int i = 0; i < a.length; i++) {
if(a[i] != b[i]) {
return true;
}//if//
}//for//
return false;
}//notEquals()//
public static void selfTest() throws Throwable {
/* Compared the old SHA algorithm with the new one to ensure compatability.
com.common.security.Sha1Old algorithmOld = new com.common.security.Sha1Old();
com.common.security.Sha1 algorithm = new com.common.security.Sha1();
String fullSource = "This is a long long test of a lot of text and has many characters so that we can test the hash algorithm with quite a few frames of data. This way the test doesn't just include one frame which would make the test invalid. So if this test works then we can say the hash works very well!";
String partialSource = null;
byte[] hashOld = null;
byte[] hash = null;
for(int index = 1; index < fullSource.length(); index++) {
partialSource = fullSource.substring(0, index);
algorithm.add(partialSource);
hash = algorithm.hash();
algorithmOld.includeSource(partialSource);
hashOld = algorithmOld.generateDigest();
if(notEquals(hash, hashOld)) {
com.ibm.uvm.tools.DebugSupport.halt();
}
}
*/
int length = bytes[0].length;
for(int i = 0; i < texts.length; i++) {
com.common.security.Sha1 algorithm = new com.common.security.Sha1();
byte[] text = texts[i].getBytes();
algorithm.add(texts[i]);
if(notEquals(algorithm.hash(), bytes[i])) {
throw new Exception("hash #" + i + " failed");
}//if//
}//for//
}//selfTest()//
}//Sha1//

View File

@@ -0,0 +1,45 @@
package com.softwarezealot.common.thread.test;
/**
* Copyright Wynne Crisman 1999,2003<p>
*/
public class ThreadServiceTest {
/**
* ThreadServiceTest constructor comment.
*/
public ThreadServiceTest() {
super();
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void main(java.lang.String[] args) {
new ThreadServiceTest().run();
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public synchronized void run() {
com.common.thread.ThreadService.run(new Runnable() {
public void run() {
System.out.println("Testing 123");
synchronized(ThreadServiceTest.this) {
ThreadServiceTest.this.notify();
}//synchronized//
}//run()//
});
try {
wait();
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
System.out.println("Test complete");
System.exit(0);
}
}

View File

@@ -0,0 +1,61 @@
package com.softwarezealot.common.util.test;
import java.io.*;
import com.common.util.*;
import com.common.debug.*;
/**
* Copyright Wynne Crisman 1999,2005<p>
*/
public class AdvancedTextParserTest {
/**
* AdvancedStringParserTest constructor comment.
*/
public AdvancedTextParserTest() {
super();
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void main(java.lang.String[] args) {
//AdvancedStringParser parser = new AdvancedStringParser("This is a test of the AdvancedStringParser class. \r\nThis test will:\r\n\t-check that all parts are working properly\r\n\t-show the programmer what is broken");
try {
AdvancedTextParser.DelimiterSet delimiterSetA = null;
File file = new File(args[0]);
FileInputStream fin = new FileInputStream(file);
byte[] bytes = new byte[fin.available()];
String source = null;
String[] delimiters = new String[args.length - 1];
fin.read(bytes);
source = new String(bytes, "UTF8");
System.arraycopy(args, 1, delimiters, 0, delimiters.length);
for(int index = 0; index < delimiters.length; index++) {
delimiterSetA = AdvancedTextParser.addDelimiter(delimiterSetA, delimiters[index], true, false, null);
}//for//
//parser.setDelimiterSet(delimiterSetA);
long t = System.currentTimeMillis();
for(int count = 0; count < 50000; count++) {
AdvancedTextParser parser = new AdvancedTextParser(source, delimiterSetA);
while(parser.hasNext()) {
String segment = parser.next();
//Debug.log(segment);
}//while//
}//for//
t = System.currentTimeMillis() - t;
Debug.log("total time: " + t + "ms");
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}
}

View File

@@ -0,0 +1,39 @@
package com.softwarezealot.common.util.test;
import com.common.debug.*;
import com.common.util.*;
/**
* Copyright Wynne Crisman 1999,2005<p>
*/
public class HashMapTest {
/**
* HashMapTest constructor comment.
*/
public HashMapTest() {
super();
}
/**
*
*/
public static void main(String[] args) {
String prefix = "I02000";
int keyCount = 150;
LiteHashMap map = new LiteHashMap(10);
IList keys = new LiteList(keyCount, 50);
for(int i = 0; i < keyCount; i++) {
keys.add(prefix + i);
}//for//
for(int i = 0; i < keys.getSize(); i++) {
map.put(keys.get(i), new Integer(i));
}//for//
for(int i = 0; i < keys.getSize(); i++) {
Debug.log(map.get(keys.get(i)).toString());
}//for//
System.exit(0);
}//main()//
}//HashMapTest//

View File

@@ -0,0 +1,28 @@
package com.softwarezealot.common.util.test;
import com.common.util.*;
import com.common.debug.*;
import com.common.event.*;
import com.common.thread.*;
/**
* Copyright Wynne Crisman 1999-2002<p>
*/
public class JobQueueTest {
/**
* Starts the application.
* @param args An array of command-line arguments.
*/
public static void main(String[] args) {
//Test the job queue.//
JobQueue queue = new JobQueue(new Object[] {new Integer(1), new Integer(2)});
LiteList jobs = new LiteList(1000, 10);
for(int index = 0; index < 1000; index++) {
queue.addJob(new SampleJob(index), 0);
}//for//
queue.close();
ThreadService.shutdown();
}//main()//
}//JobQueue//

View File

@@ -0,0 +1,63 @@
package com.softwarezealot.common.util.test;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import com.common.comparison.Comparator;
import com.common.comparison.IComparator;
import com.common.util.LiteList;
public class ListTest {
private static class Combo {
public String text;
public Integer value;
public Combo(String text, Integer value) {
this.text = text;
this.value = value;
}
public String toString() {
return value + " : " + text;
}
}
/**
* @param args
*/
public static void main(String[] args) {
LiteList list = new LiteList(10, 20);
list.setOrderComparator(new Comparator() {
public int hash(Object value) {
return 0;
}
public int compare(Object value1, Object value2) {
return ((Combo) value1).value.intValue() <= ((Combo) value2).value.intValue() ? Comparator.LESS_THAN : Comparator.GREATER_THAN;
}
});
list.add(new Combo("First", new Integer(10)));
list.add(new Combo("Second", new Integer(5)));
list.add(new Combo("Third", new Integer(15)));
list.add(new Combo("Fourth", new Integer(20)));
list.add(new Combo("Fifth", new Integer(0)));
list.add(new Combo("Sixth", new Integer(5)));
list.add(new Combo("Seventh", new Integer(0)));
list.add(new Combo("Eight", new Integer(5)));
list.add(new Combo("Nineth", new Integer(5)));
list.add(new Combo("Tenth", new Integer(5)));
list.add(new Combo("Eleventh", new Integer(5)));
list.add(new Combo("Twelvth", new Integer(5)));
list.add(new Combo("Thirteenth", new Integer(5)));
list.add(new Combo("Fourteenth", new Integer(5)));
list.add(new Combo("Fifteenth", new Integer(5)));
for(int index = 0; index < list.getSize(); index++) {
System.out.println(list.get(index));
}
System.exit(0);
}
}

View File

@@ -0,0 +1,39 @@
package com.softwarezealot.common.util.test;
import com.common.debug.*;
import com.common.event.*;
/**
* Copyright Wynne Crisman 1999-2002<p>
*/
public class SampleJob extends com.common.event.VoidHandler1 {
private int jobNumber = 0;
/**
* SampleJob constructor.
*/
public SampleJob(int jobNumber) {
super();
this.jobNumber = jobNumber;
}//SampleJob()//
/**
* Processes the job by printing the job number to the debug log.
* @param resource The resource passed by the invoker (in this case the job queue).
*/
public void evaluate(Object resource) {
//Simualate some work.//
if((resource == null) || (resource.equals(new Integer(2)))) {
synchronized(this) {
try {
wait(10);
}//try//
catch(InterruptedException e) {
Debug.handle(e);
}//catch//
}//synchronized//
}//if//
//Spit out the details to the logs.//
Debug.log(jobNumber + " completed" + (resource != null ? (" on job processor: " + resource + ".") : "."));
}//evaluate()//
}//SampleJob//

View File

@@ -0,0 +1,55 @@
package com.softwarezealot.common.util.test;
import java.io.*;
import com.common.util.*;
import com.common.debug.*;
/**
* Copyright Wynne Crisman 1999,2005<p>
*/
public class TextParserTest {
/**
* AdvancedStringParserTest constructor comment.
*/
public TextParserTest() {
super();
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void main(java.lang.String[] args) {
long t = System.currentTimeMillis();
try {
File file = new File(args[0]);
FileInputStream fin = new FileInputStream(file);
byte[] bytes = new byte[fin.available()];
String source = null;
String[] delimiters = new String[args.length - 1];
fin.read(bytes);
source = new String(bytes, "UTF8");
System.arraycopy(args, 1, delimiters, 0, delimiters.length);
for(int count = 0; count < 50000; count++) {
TextParser parser = new TextParser(source, delimiters, true);
parser.addDelimiter(" ", false);
while(parser.hasNext()) {
String segment = parser.next();
//Debug.log(segment);
}//while//
}//for//
t = System.currentTimeMillis() - t;
Debug.log("total time: " + t + "ms");
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}
}

View File

@@ -0,0 +1,98 @@
package com.softwarezealot.common.util.test;
import com.common.util.*;
import com.common.debug.*;
//import com.foundation.util.Tree;
/**
* Copyright Wynne Crisman 1999,2005<p>
*/
public class TreeTest {
/**
* TreeTest constructor comment.
*/
public TreeTest() {
super();
}
/**
* Starts the application.
* @param args an array of command-line arguments
*/
public static void main(java.lang.String[] args) {
/*
Tree tree = new Tree();
String root1 = "root1";
String root1child1 = "root1child1";
String root2 = "root2";
String root2child1 = "root2child1";
String root2child2 = "root2child2";
String root2child2child1 = "root2child2child1";
String root2child2child1child1 = "root2child2child1child1";
String root2child2child1child2 = "root2child2child1child2";
String root2child2child2 = "root2child2child2";
String root2child2child3 = "root2child2child3";
String root2child3 = "root2child3";
String root3 = "root3";
String root4 = "root4";
String root4child1 = "root4child1";
String root4child1child1 = "root4child1child1";
String root4child2 = "root4child2";
tree.add(root1);
tree.add(root1, root1child1);
tree.add(root2);
tree.add(root3);
tree.add(root2, root2child1);
tree.add(root2, root2child2);
tree.add(root2, root2child3);
tree.add(root2child2, root2child2child1);
tree.add(root2child2child1, root2child2child1child1);
tree.add(root2child2, root2child2child2);
tree.add(root2child2, root2child2child3);
tree.add(root2child2child1, root2child2child1child2);
Debug.log("");
Debug.log("Top Down:");
IIterator iterator = tree.iterator();
while(iterator.hasNext()) {
Debug.log("" + iterator.next());
}//while//
Debug.log("");
Debug.log("Depth First:");
iterator = tree.iteratorDepthFirst();
while(iterator.hasNext()) {
Debug.log("" + iterator.next());
}//while//
Debug.log("");
Debug.log("Top Down from root2child2:");
iterator = tree.iterator(root2child2);
while(iterator.hasNext()) {
Debug.log("" + iterator.next());
}//while//
tree.remove(root2child2);
Debug.log("");
Debug.log("Top Down after removing root2child2:");
iterator = tree.iterator(root2child2);
while(iterator.hasNext()) {
Debug.log("" + iterator.next());
}//while//
Tree subtree = new Tree();
subtree.add(root4);
subtree.add(root4, root4child1);
subtree.add(root4child1, root4child1child1);
subtree.add(root4, root4child2);
tree.addAll((ICollection) subtree);
Debug.log("");
Debug.log("Top Down after adding root4:");
iterator = tree.iterator();
while(iterator.hasNext()) {
Debug.log("" + iterator.next());
}//while//
*/
}
}

View File

@@ -0,0 +1,39 @@
package com.softwarezealot.orb.test;
import com.common.orb.Orb;
import com.common.thread.ThreadService;
import com.de22.orb.Address;
import com.de22.orb.optional.ServerSocketOptions;
import com.de22.orb.optional.SocketOptions;
/**
* Copyright Declarative Engineering LLC 2009<p>
*/
public class OrbServerSocketTest {
/**
* @param args
*/
public static void main(String[] args) {
Orb.setOrbWrapper(new com.de22.orb.optional.CommonOrbWrapper(new com.de22.orb.development.OrbClassLoader(), null, null, null, null));
try {
Object serverSocketId = Orb.openServerSocket("TestServerSocket", new ServerSocketOptions(new Address("4000"), null, new SocketOptions()));
if(serverSocketId != null) {
System.out.println("Test sucessful.");
Orb.closeServerSocket(serverSocketId);
}//if//
else {
System.out.println("Test failed.");
}//else//
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
Orb.shutdown();
ThreadService.shutdown();
}
}

6
Common/.classpath Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>

17
Common/.project Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Common</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

122
Common/build.xml Normal file
View File

@@ -0,0 +1,122 @@
<!--
Builds the common project.
-->
<project xmlns:ivy="antlib:org.apache.ivy.ant" name="Common Project" default="build-common" basedir=".">
<property name="compress" value="true"/>
<property name="build" value="./build"/>
<!-- BEGIN: ivy library -->
<property name="ivy" value="${build}/Ivy"/>
<property name="ivy.version" value="2.3.0"/>
<target name="check-ivy">
<available file="${ivy.jar.file}" property="skip.download.ivy"/>
</target>
<target name="download-ivy" depends="check-ivy" unless="skip.download.ivy">
<mkdir dir="${ivy}"/>
<echo message="installing ivy..."/>
<get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.version}/ivy-${ivy.version}.jar" dest="${ivy}/ivy-${ivy.version}.jar" usetimestamp="true"/>
</target>
<target name="load-ivy" depends="download-ivy">
<path id="ivy.classpath">
<fileset dir="${ivy}">
<include name="*.jar"/>
</fileset>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.classpath"/>
</target>
<!-- END: ivy library -->
<!-- BEGIN: svnant library -->
<property name="svnant" value="${build}/SvnAnt"/>
<property name="svnant-version" value='1.4dev-5544'/>
<property name="svnant-folder-version" value='1.4dev'/>
<target name="check-svnant">
<available file="${svnant}/svnant-${svnant-version}.zip" property="skip-download-svnant"/>
</target>
<target name="download-svnant" depends="check-svnant" unless="skip-download-svnant">
<delete dir="${svnant}" quiet="true" failonerror="false"/>
<mkdir dir="${svnant}"/>
<echo message="Installing SvnAnt..."/>
<get src="http://media:8081/artifactory/simple/libs-release-local/svnant-${svnant-version}.zip" dest="${svnant}" usetimestamp="true"/>
<unzip src="${svnant}/svnant-${svnant-version}.zip" dest="${build}/SvnAnt">
</unzip>
</target>
<target name="load-svnant" depends="download-svnant">
<path id="svnant.classpath">
<fileset dir="${build}/SvnAnt/"> <!--${build}/SvnAnt/svnant-${svnant-folder-version}/lib-->
<include name="**/*.jar"/>
</fileset>
</path>
<typedef resource="org/tigris/subversion/svnant/svnantlib.xml" classpathref="svnant.classpath"/>
</target>
<!-- END: svnant library -->
<target name="ivy-setup" depends="load-ivy">
<property name="ivy.default.ivy.user.dir" location="./.ivy/"/>
<ivy:configure id="ivy.settings" file="ivysettings.xml" username="jenkins" passwd="1qaz2wsx"/>
<ivy:resolve file="ivy.xml"/>
</target>
<target name="download-dependancies" depends="ivy-setup" description="Downloads the dependancies defined by the ivy.xml file from Artifactory.">
<ivy:retrieve />
</target>
<target name="upload-artifacts" depends="ivy-setup" description="Uploads artifacts defined by the ivy.xml file to Artifactory.">
<ivy:publish revision="${build-version}" status="incremental" resolver="libs-release-resolver" overwrite="true">
<artifacts pattern="[artifact]-[revision].[type].[ext]"/>
</ivy:publish>
</target>
<target name="load-svn-version">
<svn>
<wcVersion path="."/>
</svn>
<tstamp>
<format property="build-time" pattern="yyyyMMddkkmm" timezone="PST"/>
</tstamp>
</target>
<target name="get-dateversion" if="modified">
<property name="build-version" value="SNAPSHOT-${committed.max}-${build-time}"/>
</target>
<target name="get-svnversion" unless="modified">
<property name="build-version" value="SNAPSHOT-${committed.max}"/>
</target>
<target name="get-version" depends="load-svnant, load-svn-version, get-dateversion, get-svnversion">
<echo message="Project's SVN version: ${committed.max}; is modified source: ${modified}"/>
<echo message="Version used: ${build-version}"/>
</target>
<target name="init">
<mkdir dir="${build}/lib"/>
</target>
<target name="build-common" depends="build-common-src, build-common-bin" description="Builds the source zip and binary jar and places them in the ./build/lib directory.">
</target>
<target name="build-common-src" depends="init, get-version">
<zip destfile="${build}/lib/DE Common-${build-version}.src.zip" basedir="./src" compress="${compress}" includes="**/*.java, **/*.properties"/>
</target>
<target name="build-common-bin" depends="init, get-version">
<!-- Debug Build -->
<mkdir dir="${build}/bin"/>
<javac destdir="${build}/bin" target="1.4" source="1.4" encoding="utf-8" nowarn="true" verbose="no" fork="true" classpath="" debug="true" debuglevel="source" includeantruntime="false">
<compilerarg value="-XDignore.symbol.file"/>
<src path="./src"/>
</javac>
<jar destfile="${build}/lib/DE Common-${build-version}.bin.jar" basedir="./bin" compress="${compress}" includes="**/*.class, **/*.properties"/>
<delete dir="${build}/bin"/>
<!-- Release Build
<mkdir dir="${build}/bin"/>
<javac destdir="${build}/bin" target="1.4" source="1.4" encoding="utf-8" nowarn="true" verbose="no" fork="true" classpath="" debug="off" includeantruntime="false">
<compilerarg value="-XDignore.symbol.file"/>
<src path="./src"/>
</javac>
<jar destfile="${build}/lib/DE Common-${build-version}.jar" basedir="./bin" compress="${compress}" includes="**/*.class, **/*.properties"/>
<delete dir="${build}/bin"/>-->
</target>
<target name="clean" description="Cleans the old build files from disk.">
<delete dir="${build}"/>
</target>
</project>

16
Common/ivy.xml Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
<!-- status is one of "release", "milestone", or "integration" -->
<info organisation="com.declarativeengineering" module="Common" status="integration">
<repository name="ibiblio" url="http://media:8081/artifactory/libs-release" pattern="[organization]/[module]/[revision]/[module]-[revision](-[classifier]).[ext]" artifacts="true"/>
</info>
<!--
<dependancies>
<dependancy org="org.tigris.subversion" name="svnant" rev="latest.release"/>
</dependancies>
-->
<publications>
<artifact name="DE Common" type="bin" ext="jar"/>
<artifact name="DE Common" type="src" ext="zip"/>
</publications>
</ivy-module>

14
Common/ivysettings.xml Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<ivy-settings>
<settings defaultResolver="main"/>
<!--<caches defaultCacheDir="./cache/" checkUpToDate="false"/>-->
<resolvers>
<chain name="main">
<ibiblio name="remote-repos-resolver" m2compatible="true" root="http://media:8081/artifactory/remote-repos"/>
<url name="libs-release-resolver" m2compatible="true">
<artifact pattern="http://media:8081/artifactory/libs-release/[organization]/[module]/[revision]/[module]-[revision](-[classifier]).[ext]"/>
<ivy pattern="http://media:8081/artifactory/libs-release/[organization]/[module]/[revision]/[module]-[revision](-[classifier]).pom"/>
</url>
</chain>
</resolvers>
</ivy-settings>

View File

@@ -0,0 +1,416 @@
/*
* Copyright (c) 1999,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.comparison;
import java.math.BigDecimal;
import java.text.Collator;
/**
* Defines utility methods and the basic structure of a comparator which compares two objects for equality and/or ordering.
*/
public abstract class Comparator implements IComparator {
private static final IComparator identityComparator = new IdentityComparator();
private static final IComparator logicalComparator = new LogicalComparator();
private static final IComparator stringComparator = new StringComparator();
private static final IComparator numericStringComparator = new NumericStringComparator();
/**
* A simple identity comparitor which uses the equals operator for comparison. The results will only reflect equality.
*/
public static class IdentityComparator extends Comparator {
/**
* IdentityComparator constructor.
*/
public IdentityComparator() {
}//IdentityComparator()//
/* (non-Javadoc)
* @see com.common.comparison.IComparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(Object value1, Object value2) {
if(value1 instanceof IComparable) {
return ((IComparable) value1).equalsEquals(value2) ? EQUAL : NOT_EQUAL;
}//if//
else {
return value1 == value2 ? EQUAL : NOT_EQUAL;
}//else//
}//compare//
/* (non-Javadoc)
* @see com.common.comparison.Comparator#hash(java.lang.Object)
*/
public int hash(Object value) {
return System.identityHashCode(value);
}//hash()//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return object instanceof IdentityComparator;
}//equals()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return IdentityComparator.class.hashCode();
}//hashCode()//
}//IdentityComparator//
/**
* A simple logical comparator using the built in equals method for comparison. The results will only reflect equality.
*/
public static class LogicalComparator extends Comparator {
/**
* LogicalComparator constructor.
*/
public LogicalComparator() {
}//LogicalComparator()//
/* (non-Javadoc)
* @see com.common.comparison.IComparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(Object value1, Object value2) {
return (value1 == null ? (value2 == null ? EQUAL : NOT_EQUAL) : (value1.equals(value2) ? EQUAL : NOT_EQUAL));
}//compare//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return object instanceof LogicalComparator;
}//equals()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return LogicalComparator.class.hashCode();
}//hashCode()//
}//LogicalComparator//
/**
* A basic string logical comparator.
*/
public static class StringComparator extends Comparator {
/** Whether the comparator only needs to test for equality and can ignore which is greater or less. This optimizes the string comparison since equals(..) is far faster than compare(..) for text. This is ignored if a collator is specified since a collator takes fancy text conversions into account, rendering a length test useless. */
private boolean checkEqualityOnly = false;
/** Whether to check case. This is ignored if a collator is used. */
private boolean caseSensitive = true;
/** The collator used when searching. */
private Collator collator = null;
/**
* StringComparator constructor.
*/
public StringComparator() {
}//StringComparator()//
/**
* StringComparator constructor.
* @param caseSensitive Whether the strings are case sensitive.
*/
public StringComparator(boolean caseSensitive) {
this.caseSensitive = caseSensitive;
}//StringComparator()//
/**
* StringComparator constructor.
* @param caseSensitive Whether the strings are case sensitive.
* @param checkEqualityOnly Optimizes the comparator since testing a string for equality is far faster (10x) than testing to see which is greater or less than the other.
*/
public StringComparator(boolean caseSensitive, boolean checkEqualityOnly) {
this.caseSensitive = caseSensitive;
this.checkEqualityOnly = checkEqualityOnly;
}//StringComparator()//
/**
* StringComparator constructor.
* @param collator The custom collator to use for comparing strings. This provides maximum multi-ligual capabilities.
*/
public StringComparator(Collator collator) {
this.collator = collator;
}//StringComparator()//
/* (non-Javadoc)
* @see com.common.comparison.IComparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(Object value1, Object value2) {
if(value1 == null) {
return value2 == null ? EQUAL : LESS_THAN;
}//if//
else if(value2 == null) {
return GREATER_THAN;
}//else if//
else {
if(collator != null) {
return collator.compare((String) value1, (String) value2);
}//if//
else if(checkEqualityOnly) {
return (caseSensitive ? ((String) value1).equals((String) value2) : ((String) value1).equalsIgnoreCase((String) value2)) ? EQUAL : NOT_EQUAL;
}//else if//
else {
int value = caseSensitive ? ((String) value1).compareTo((String) value2) : ((String) value1).compareToIgnoreCase((String) value2);
return (value < 0 ? LESS_THAN : (value > 0 ? GREATER_THAN : EQUAL));
}//else//
}//else//
}//compare//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return object instanceof StringComparator;
}//equals()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return StringComparator.class.hashCode();
}//hashCode()//
/* (non-Javadoc)
* @see com.common.comparison.Comparator#hash(java.lang.Object)
*/
public int hash(Object value) {
return ((String) value).toLowerCase().hashCode();
}//hash()//
}//StringComparator//
/**
* A more complex string comparator which recognizes numbers embedded in the string and compares them as numbers, not as characters.
*/
public static class NumericStringComparator extends Comparator {
private boolean placeNumbersBeforeText = true;
/**
* NumericStringComparator constructor.
*/
public NumericStringComparator() {
}//NumericStringComparator()//
/**
* NumericStringComparator constructor.
* @param placeNumbersBeforeText Whether numbers should preceed text in ordering.
*/
public NumericStringComparator(boolean placeNumbersBeforeText) {
this.placeNumbersBeforeText = placeNumbersBeforeText;
}//NumericStringComparator()//
/* (non-Javadoc)
* @see com.common.comparison.IComparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(Object value1, Object value2) {
int result = EQUAL;
if(value1 == null) {
result = value2 == null ? EQUAL : LESS_THAN;
}//if//
else if(value2 == null) {
result = GREATER_THAN;
}//else if//
else if((value1 instanceof String) && (value2 instanceof String)) {
String text1 = (String) value1;
String text2 = (String) value2;
for(int index1 = 0, index2 = 0; result == 0; index1++, index2++) {
char ch1 = 0;
char ch2 = 0;
if(index1 >= text1.length() && index2 >= text2.length()) {
break;
}//if//
else if(index1 >= text1.length()) {
result = LESS_THAN;
}//else if//
else if(index2 >= text2.length()) {
result = GREATER_THAN;
}//else if//
if(result == 0) {
boolean ch1IsDigit = false;
boolean ch2IsDigit = false;
ch1 = text1.charAt(index1);
ch2 = text2.charAt(index2);
//Allow a number to begin with a decimal point.//
if(ch1 == '.') {
ch1IsDigit = (text1.length() > index1 + 1) && (Character.isDigit(text1.charAt(index1 + 1)));
}//if//
else {
ch1IsDigit = Character.isDigit(ch1);
}//else//
if(ch2 == '.') {
ch2IsDigit = (text2.length() > index2 + 1) && (Character.isDigit(text2.charAt(index2 + 1)));
}//if//
else {
ch2IsDigit = Character.isDigit(ch2);
}//else//
//If they are both numbers then compare them.//
if(ch1IsDigit && ch2IsDigit) {
int endIndex1 = getLastDigitIndex(text1, index1);
int endIndex2 = getLastDigitIndex(text2, index2);
//int number1 = Integer.parseInt(text1.substring(index1, endIndex1 + 1));
//int number2 = Integer.parseInt(text2.substring(index2, endIndex2 + 1));
BigDecimal number1 = new BigDecimal(text1.substring(index1, endIndex1 + 1));
BigDecimal number2 = new BigDecimal(text2.substring(index2, endIndex2 + 1));
//if(number1 != number2) {
// result = number1 < number2 ? LESS_THAN : GREATER_THAN;
//}//if//
if(!number1.equals(number2)) {
result = number1.compareTo(number2) < 0 ? LESS_THAN : GREATER_THAN;
}//if//
index1 = endIndex1;
index2 = endIndex2;
}//if//
else if(ch1IsDigit) {
result = placeNumbersBeforeText ? LESS_THAN : GREATER_THAN;
}//else if//
else if(ch2IsDigit) {
result = placeNumbersBeforeText ? GREATER_THAN : LESS_THAN;
}//else if//
else {
if(ch1 != ch2) {
result = ch1 < ch2 ? LESS_THAN : GREATER_THAN;
}//if//
}//else//
}//if//
}//for//
}//else if//
else if(value1 instanceof String) {
result = LESS_THAN;
}//else if//
else if(value2 instanceof String) {
result = GREATER_THAN;
}//else if//
else {
result = EQUAL;
}//else//
return result;
}//compare//
/**
* Gets the last index that is a digit.
* @param text The text to search.
* @param startIndex The index to start from.
* @return The last index that is a digit (inclusive).
*/
private int getLastDigitIndex(String text, int startIndex) {
int result = startIndex + 1;
while((result < text.length()) && (Character.isDigit(text.charAt(result)))) {
result++;
}//while//
return result - 1;
}//getLastDigitIndex()//
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object object) {
return object instanceof StringComparator;
}//equals()//
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return NumericStringComparator.class.hashCode();
}//hashCode()//
}//NumericStringComparator//
/**
* Comparator constructor.
*/
public Comparator() {
super();
}//Comparator()//
/* (non-Javadoc)
* @see com.common.comparison.IComparator#compare(java.lang.Object, java.lang.Object)
*/
public abstract int compare(Object value1, Object value2);
/* (non-Javadoc)
* @see com.common.comparison.IComparator#hash(java.lang.Object)
*/
public int hash(Object value) {
return value.hashCode();
}//hash()//
/**
* Gets the common identity comparator which can be used to check for two identical objects.
* @return A commonly used comparator used to check for exact equality.
*/
public static IComparator getIdentityComparator() {
return identityComparator;
}//getIdentityComparator()//
/**
* Gets the common identity comparator which can be used to check for two identical objects.
* @return A commonly used comparator used to check for aproximate equality.
*/
public static IComparator getLogicalComparator() {
return logicalComparator;
}//getLogicalComparator()//
/**
* Gets the common string comparator which can be used to check for two logically equal strings.
* @return A commonly used comparator used to check for aproximate equality of two strings.
*/
public static IComparator getStringComparator() {
return stringComparator;
}//getStringComparator()//
/**
* Gets the common string comparator which can be used to check for two logically equal strings.
* @return A commonly used comparator used to check for aproximate equality of two strings.
*/
public static IComparator getNumericStringComparator() {
return numericStringComparator;
}//getStringComparator()//
/**
* Checks a value returned by the compare method to see if it represents equality.
* @param comparisonValue The value returned by the compare method.
* @return Will be true if the comparison value indicates equality.
*/
public static boolean isEqual(int comparisonValue) {
return comparisonValue == EQUAL;
}//isEqual()//
/**
* Checks a value returned by the compare method to see if the method indicated that value1 was less than value2.
* @param comparisonValue The value returned by the compare method.
* @return Will be true if the comparison value indicates value1 is greater than value2.
*/
public static boolean isGreaterThan(int comparisonValue) {
return comparisonValue > EQUAL;
}//isGreaterThan()//
/**
* Checks a value returned by the compare method to see if the method indicated that value1 was less than value2.
* @param comparisonValue The value returned by the compare method.
* @return Will be true if the comparison value indicates value1 is less than value2.
*/
public static boolean isLessThan(int comparisonValue) {
return comparisonValue < EQUAL;
}//isLessThan()//
/**
* Determines whether the two objects are logically equal by using the java.lang.Object.equals(java.lang.Object) method.
* This method is useful because it accepts null parameters.
* @param object1 The first object to compare. This value may be null.
* @param object2 The second object to compare. This value may be null.
* @return Whether the two objects are logically equal (not necessarily the exact same object).
*/
public static boolean equals(Object object1, Object object2) {
boolean result = false;
if(object1 != null) {
if((object2 instanceof Comparable) && (object2.getClass().equals(object1.getClass()))) {
result = ((Comparable) object2).compareTo(object1) == 0;
}//if//
else {
result = object1.equals(object2);
}//else//
}//else if//
else {
result = object2 == null;
}//else//
return result;
}//equals()//
/**
* Allows the serialization of this type.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
}//readExternal()//
/**
* Allows the serialization of this type.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
}//writeExternal()//
}//Comparator//

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.comparison;
public interface IComparable extends Comparable {
public static final int EQUAL = IComparator.EQUAL;
public static final int NOT_EQUAL = IComparator.NOT_EQUAL;
public static final int LESS_THAN = IComparator.LESS_THAN;
public static final int GREATER_THAN = IComparator.GREATER_THAN;
/**
* Compares the object with another object for the purpose of determining order.
* @param object The object to compare this object with.
* @return A number greater than zero if this object is greater than the passed object, or less than zero if it is less than, or zero if they are equal.
*/
public int compareTo(Object object);
/**
* Checks to see if the two objects are similar enough to be considered equal.
* @param object The object to compare this object with.
* @return Will be true if the objects are logically equivalent.
*/
public boolean equals(Object object);
/**
* Checks to see if the two objects are exactly equal, that is to say that they occupy the same memory space.
* @param object The object to compare this object with.
* @return Will be true if the objects are identical, otherwise false.
*/
public boolean equalsEquals(Object object);
}//IComparable//

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 1999,2008 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.comparison;
public interface IComparator extends java.io.Externalizable, java.util.Comparator {
public static final int EQUAL = 0;
public static final int NOT_EQUAL = -1;
public static final int LESS_THAN = -1;
public static final int GREATER_THAN = 1;
/**
* Gets a relative comparison of the two values.
* <p>If value1 < value2 then a negative integer will be returned.
* <p>If value1 = value2 then zero will be returned.
* <p>If value1 > value2 then a positive integer will be returned.
* @param value1 The first value to compare. This value is to the left of the operator.
* @param value2 The second value to compare. This value is to the right of the operator.
* @return A number representing the operator that accuratly compares the two values. The value will be greater than zero if value1 > value2; less than zero if value1 < value2; and zero if the values are equal.
* @see Comparator.isEqaul(int)
* @see Comparator.isLessThan(int)
* @see Comparator.isGreaterThan(int)
*/
public int compare(Object value1, Object value2);
/**
* Hashes the value using the comparator's hash mechanism.
* @param value The value to be hashed.
* @return The resulting hash.
*/
public int hash(Object value);
}//IComparator//

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 1999,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.debug;
/**
* This should be the base class for application specific logs.
*/
public class ConsoleLog implements ILog {
private String lineSeparator = System.getProperty("line.separator");
/**
* DefaultLog constructor.
*/
public ConsoleLog() {
super();
}//ConsoleLog()//
/**
* Allows for common application specific handling of some exceptions.
* The default log's behavior is to rethrow ThreadDeath exceptions and InterruptedExceptions so that threads can properly terminate.
*/
public void handle(Throwable exception) {
if(exception instanceof ThreadDeath) {
throw (ThreadDeath) exception;
}//if//
else if(exception instanceof InterruptedException) {
Thread.currentThread().interrupt();
}//else if//
}//handle()//
/**
* The default is to print the stack trace to the standard output stream.
*/
public synchronized void log(String note, Throwable exception, int type, boolean display) {
if(note != null && note.trim().length() > 0 && !note.equals("null")) {
System.out.print(note + lineSeparator);
}//if//
if(exception != null) {
printException(exception);
}//if//
}//log()//
/**
* Recursively prints the exceptions in order of occurance.
* @param exception The exception to print.
*/
private void printException(Throwable exception) {
if(exception.getCause() != null) {
printException(exception.getCause());
}//if//
// if(exception.getMessage() != null && exception.getMessage().trim().length() > 0) {
// System.out.println(exception.getMessage());
// }//if//
exception.printStackTrace();
}//printException()//
}//DefaultLog//

View File

@@ -0,0 +1,144 @@
/*
* Copyright (c) 2009,2007 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt */
package com.common.debug;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
/**
* This is where all the orb debug information gets sent to.
* A custom log can be specified by overriding DefaultDebugLog or implementing IDebugLog & calling OrbDebugLog.getSingleton().setDebugLog(myDebugLog);
*/
public final class Debug {
public static final int TYPE_ERROR = ILog.TYPE_ERROR;
public static final int TYPE_WARNING = ILog.TYPE_WARNING;
public static final int TYPE_INFORMATION = ILog.TYPE_INFORMATION;
private static ILog log = null;
/**
* OrbDebugLog constructor.
*/
private Debug() {
super();
}//OrbDebugLog()//
/**
* Creates a string containing the full stack for the exception.
* @param e The exception.
* @return The stack text.
*/
public static String getExceptionStack(Throwable e) {
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
return stringWriter.toString();
}//getExceptionStack()//
/**
* Gets the current debug log.
*/
public static ILog getLog() {
if(log == null) {
//setLog(new FrameLog());
//((com.common.debug.FrameLog) getLog()).setVisible(true);
setLog(new DefaultLog());
}//if//
return log;
}//getLog()//
public static void halt() {
try {
Class debugSupportClass = Class.forName("com.ibm.uvm.tools.DebugSupport");
Method haltMethod = debugSupportClass.getMethod("halt", new Class[0]);
haltMethod.invoke(null, new Object[0]);
}//try//
catch(Throwable e) {
}//catch//
}//halt()//
/**
* Allows for common application specific handling of some exceptions.
* The default log's behavior is to rethrow ThreadDeath exceptions and InterruptedExceptions so that threads can properly terminate.
*/
public static void handle(Throwable exception) {
getLog().handle(exception);
}//handle()//
/**
* Determines if a log has been set yet.
*/
public static boolean hasLog() {
return log != null;
}//hasLog()//
public static void log(String note) {
getLog().log(note, null, ILog.TYPE_INFORMATION, false);
}//log()//
public static void log(String note, boolean forceDisplay) {
getLog().log(note, null, ILog.TYPE_INFORMATION, forceDisplay);
}//log()//
public static void log(Throwable exception) {
getLog().log(null, exception, ILog.TYPE_ERROR, true);
}//log()//
public static void log(String note, Throwable exception) {
getLog().log(note, exception, exception == null ? ILog.TYPE_INFORMATION : ILog.TYPE_ERROR, true);
}//log()//
/**
* @deprecated
*/
public static void log(Throwable exception, String note) {
getLog().log(note, exception, exception == null ? ILog.TYPE_INFORMATION : ILog.TYPE_ERROR, true);
}//log()//
/**
* @deprecated
*/
public static void log(Throwable exception, String note, boolean forceDisplay) {
getLog().log(note, exception, exception == null ? ILog.TYPE_INFORMATION : ILog.TYPE_ERROR, forceDisplay);
}//log()//
public static void log(String note, Throwable exception, boolean forceDisplay) {
getLog().log(note, exception, exception == null ? ILog.TYPE_INFORMATION : ILog.TYPE_ERROR, forceDisplay);
}//log()//
public static void log(Throwable exception, boolean forceDisplay) {
getLog().log(null, exception, ILog.TYPE_ERROR, forceDisplay);
}//log()//
public static void log(Object location, String note) {
log(ILog.TYPE_INFORMATION, location, note);
}//log()//
public static void log(int type, String note) {
getLog().log(note, null, type, false);
}//log()//
public static void log(int type, String note, boolean forceDisplay) {
getLog().log(note, null, type, forceDisplay);
}//log()//
public static void log(int type, Throwable exception) {
getLog().log(null, exception, type, true);
}//log()//
public static void log(int type, Throwable exception, boolean forceDisplay) {
getLog().log(null, exception, type, forceDisplay);
}//log()//
public static void log(int type, String note, Throwable exception) {
getLog().log(note, exception, type, true);
}//log()//
public static void log(int type, String note, Throwable exception, boolean forceDisplay) {
getLog().log(note, exception, type, forceDisplay);
}//log()//
public static void log(int type, Object location, String note) {
if(location != null) {
String completeNote = "\r\n" + location.toString() + "\r\n" + note;
getLog().log(completeNote, null, type, true);
}//if//
else {
log(note);
}//else//
}//log()//
/**
* Sets an application defined debug log object.
* @param log ILog A log object that handles debug logging for the application.
*/
public static void setLog(ILog _log) {
log = _log;
}//setLog()//
}//DebugSupport//

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 1999,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.debug;
/**
* This should be the base class for application specific logs.
*/
public class DefaultLog extends ConsoleLog {
/**
* DefaultLog constructor.
*/
public DefaultLog() {
super();
}//DefaultLog()//
}//DefaultLog//

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2003,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.debug;
import java.io.*;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
/**
* Logs all output to a single log file.
*/
public class FileLog extends ConsoleLog {
private DateFormat dateFormat = new SimpleDateFormat("MM/dd hh:mm:ss:SSS a");
private File file = null;
private File path = null;
private String lineSeparator = System.getProperty("line.separator");
/**
* DefaultLog constructor.
*/
public FileLog() {
this(new File('.' + System.getProperty("path.separator") + "log.txt"));
}//FileLog()//
/**
* DefaultLog constructor.
*/
public FileLog(File file) {
super();
this.path = new File(file.getParent());
this.file = file;
//Clear previous log data.//
if(file.exists()) {
try {
file.delete();
}//try//
catch(Throwable e) {
//Ignore.//
}//catch//
}//if//
}//FileLog()//
/**
* The default is to print the stack trace to the standard output stream.
* @param note The note to be logged.
* @param exception The exception to be logged.
* @param display Whether to force the log output. This is currently ignored.
*/
public synchronized void log(String note, Throwable exception, int type, boolean display) {
try {
PrintWriter writer = null;
if(!path.exists()) {
if(!path.mkdirs()) {
System.out.println("Unable to create the required log directory.");
}//if//
}//if//
if(path.exists()) {
writer = new PrintWriter(new FileWriter(file.toString(), file.exists()));
}//if//
writer.write(dateFormat.format(new Date()));
writer.write('\t');
//Write the note if there is one.//
if(note != null && note.trim().length() > 0) {
writer.write(note);
}//if//
//Write the exception if there is one.//
if(exception != null) {
if(note != null) {
writer.write(lineSeparator);
}//if//
printException(writer, exception);
}//if//
writer.write(lineSeparator);
writer.close();
}//try//
catch(IOException e) {
e.printStackTrace();
}//catch//
}//log()//
/**
* Recursively prints the exceptions in order of occurance.
* @param writer The writer to use for printing.
* @param exception The exception to print.
*/
private void printException(PrintWriter writer, Throwable exception) {
if(exception.getCause() != null) {
printException(writer, exception.getCause());
}//if//
if(exception.getMessage() != null && exception.getMessage().trim().length() > 0) {
writer.write(exception.getMessage());
writer.write(lineSeparator);
}//if//
exception.printStackTrace(writer);
writer.write(lineSeparator);
}//printException()//
}//FileLog//

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.debug;
/**
* The ILog interface defines the basic structure of an application specific logging class.
* This class will handle exceptions and debug notes for the application in an application specific way.
*/
public interface ILog {
public static final int TYPE_ERROR = 0;
public static final int TYPE_WARNING = 1;
public static final int TYPE_INFORMATION = 2;
/**
* Allows for common application specific handling of some exceptions.
* The default log's behavior is to rethrow ThreadDeath exceptions and InterruptedExceptions so that threads can properly terminate.
*/
public void handle(Throwable exception);
/**
* Handles logging a note and/or exception.
* @param note String An optional note to be logged. If an exception is also specified, then the note should be bundled with the exception in the log output.
* @param exception Throwable An optional exception to be logged.
* @param type The type of log entry this is. One of the type codes.
* @param forceDisplay boolean A flag indicating whether the note/exception should be displayed. The log may treat this how ever it desires.
*/
public void log(String note, Throwable exception, int type, boolean forceDisplay);
}//ILog//

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 1999,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.debug;
import java.io.*;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import com.common.util.IReversableIterator;
import com.common.util.CircularQueue;
/**
* Queues log entries and writes log files containing the queued entries when a display is requested.
*/
public class QueuedLog extends ConsoleLog {
private DateFormat dateFormat = new SimpleDateFormat("MM/dd hh:mm:ss:SSS a");
private File path = null;
private String logFileNamePrefix = null;
private String countFileName = null;
private String lineSeparator = System.getProperty("line.separator");
private CircularQueue queue = null;
private boolean useTimestamps = false;
private int fileIndex = 0;
/** Whether to display the log content in order of descending time (newest to oldest log entry). */
private boolean descendingTimeOrder = true;
/**
* QueuedLog constructor.
*/
public QueuedLog() {
this(new File("."), 100, true);
}//QueuedLog()//
/**
* QueuedLog constructor.
* @param path The path where log files will be located.
* @param queueSize The size of the circular queue.
*/
public QueuedLog(File path, int queueSize) {
this(path, queueSize, true);
}//QueuedLog()//
/**
* QueuedLog constructor.
* @param path The path where log files will be located.
* @param queueSize The size of the circular queue.
* @param descendingTimeOrder Whether to display the log content in order of descending time (newest to oldest log entry).
*/
public QueuedLog(File path, int queueSize, boolean descendingTimeOrder) {
super();
this.queue = new CircularQueue(queueSize);
this.path = path == null ? new File(".") : path;
this.countFileName = "count.txt";
this.logFileNamePrefix = "log";
this.descendingTimeOrder = descendingTimeOrder;
}//QueuedLog()//
/**
* The default is to print the stack trace to the standard output stream.
*/
public synchronized void log(String note, Throwable exception, int type, boolean display) {
StringWriter writer = new StringWriter((useTimestamps ? 9 : 0) + (note != null ? note.length() : 0) + (exception != null ? 400 : 0));
if(useTimestamps) {
writer.write(dateFormat.format(new Date()));
writer.write('\t');
}//if//
if(note != null && note.trim().length() > 0) {
writer.write(note);
}//if//
if(exception != null) {
PrintWriter printWriter = new PrintWriter(writer, true);
printException(printWriter, exception);
}//if//
queue.enqueue(writer.getBuffer().toString());
if(display) {
writeLogFile();
}//if//
}//log()//
/**
* Writes the a log file.
*/
public synchronized void writeLogFile() {
try {
PrintWriter writer = null;
if(!path.exists()) {
if(!path.mkdirs()) {
System.out.println("Unable to create the required log directory.");
}//if//
}//if//
if(path.exists()) {
StringBuffer buffer = new StringBuffer(logFileNamePrefix.length() + 4);
IReversableIterator iterator = null;
//Create the log file name.//
buffer.append(logFileNamePrefix);
//Prefix the number with zero padding.//
for(int count = Integer.toString(fileIndex).length(); count < 4; count++) {
buffer.append('0');
}//for//
buffer.append(fileIndex);
buffer.append(".txt");
//Write the log file.//
writer = new PrintWriter(new FileWriter(new File(path, buffer.toString()), false));
writer.write("Below are the queued log entries beginning with the " + (descendingTimeOrder ? "most recent log and ending with the least recent" : "least recent log and ending with the most recent") + "...");
writer.write(lineSeparator);
writer.write("_______________________________________________________________________________________________________");
writer.write(lineSeparator);
iterator = queue.iterator();
if(descendingTimeOrder) {
iterator.resetToBack();
//Write the log entries.//
while(iterator.hasPrevious()) {
writer.write(iterator.previous().toString());
writer.write(lineSeparator);
}//while//
}//if//
else {
iterator.resetToFront();
//Write the log entries.//
while(iterator.hasNext()) {
writer.write(iterator.next().toString());
writer.write(lineSeparator);
}//while//
}//else//
writer.close();
//Write the count file.//
writer = new PrintWriter(new FileWriter(new File(path, countFileName), false));
writer.write("" + ++fileIndex);
writer.close();
}//if//
}//try//
catch(IOException e) {
e.printStackTrace();
}//catch//
}//writeLogFile()//
/**
* Recursively prints the exceptions in order of occurance.
* @param writer The writer to use for printing.
* @param exception The exception to print.
*/
private void printException(PrintWriter writer, Throwable exception) {
if(exception.getCause() != null) {
printException(writer, exception.getCause());
}//if//
if(exception.getMessage() != null && exception.getMessage().trim().length() > 0) {
writer.write(exception.getMessage());
writer.write(lineSeparator);
}//if//
exception.printStackTrace(writer);
writer.write(lineSeparator);
}//printException()//
}//QueuedLog//

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
/*
* TODO: Determine original source.
*/
package com.common.development.security;
import java.math.BigInteger;
import com.common.debug.*;
import com.common.security.Random;
/**
* This class contains the ElGamel Asymmetric algorithm's development time code.
* This includes constant generation and testing algorithms.
*/
public class ElGamal {
/** Use probable-primes with no more than a 2^-80 chance of being composite. */
private static final int CONFIDENCE = 80;
/** A reusable buffer to optimize memory useage. */
private static final BigInteger ONE = BigInteger.valueOf(1L);
/**
* ElGamel constructor.
*/
public ElGamal() {
super();
}//ElGamel()//
/**
* Gets a generator mod <i>p</i>.
* <i>q</i> is an array containing all the prime factors of <i>p-1</i>.
* <p> This algorithm is based on Schneier page 254.
* @param p
* @param q
* @param random The random number generator to use in the algorithm.
* @return The g that fits the p and q parameters.
*/
private BigInteger findG(BigInteger p, BigInteger[] q, Random random) {
BigInteger p_minus_1 = p.subtract(ONE);
BigInteger[] z = new BigInteger[q.length];
BigInteger g;
int length = p.bitLength() - 1;
//z_i = (p-1)/q_i for each factor q_i//
for(int i = 0; i < q.length; i++) {
z[i] = p_minus_1.divide(q[i]);
}//for//
while(true) {
g = new BigInteger(length, random).setBit(length);
if(PrimeNumberGenerator.isGeneratorModP(g, p, z)) {
return g;
}//if//
}//while//
}//findG()//
/**
* Generates a prime number for use by ElGamal.
* @param primeLength Must be greater than 256. Common values are: 512, 768, 1024, 2048, 4096.
* @param random Any good random number generator.
* @param primeType The type of prime number to use. Valid values are: Prime.NORMAL, Prime.STRONG, Prime.GERMAIN.
*/
public BigInteger[] generatePrime(int primeLength, Random random, int primeType) {
Object[] result = PrimeNumberGenerator.getElGamal(primeLength, CONFIDENCE, random, primeType);
BigInteger newP = (BigInteger) result[0];
BigInteger[] q = (BigInteger[]) result[1];
BigInteger newG = findG(newP, q, random);
return new BigInteger[] {newP, newG};
}//generatePrime()//
/**
* Generates a prime length pair (elgamal constants)
*/
public static void main(String[] args) {
try {
int primeLength = 1024;
BigInteger[] pg = new ElGamal().generatePrime(primeLength, new com.common.security.Random(), PrimeNumberGenerator.STRONG);
testPrime(primeLength, pg[0], pg[1]);
Debug.log("p=");
Debug.log(pg[0].toString(16));
Debug.log("g=");
Debug.log(pg[1].toString(16));
}//try//
catch(Throwable e) {
e.printStackTrace();
}//catch//
System.exit(0);
}//main()//
/**
* Tests the prime number values to ensure they are correct.
* @param primeLength The number of bits in the prime number.
* @param p The P prime number.
* @param g The G prime number.
*/
public static void testPrime(int primeLength, BigInteger p, BigInteger g) {
if(p.bitLength() < primeLength) {
throw new SecurityException(p + " has incorrect bit length");
}//if//
if(!p.isProbablePrime(80)) {
throw new SecurityException(p + " is not prime");
}//if//
if(g.compareTo(p) >= 0) {
throw new SecurityException("g >= p");
}//if//
}//testPrime()//
}//ElGamel//

View File

@@ -0,0 +1,903 @@
/*
* Copyright (c) 1999,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
/*
* TODO: Determine original source.
*/
package com.common.development.security;
import java.math.BigInteger;
import com.common.util.LiteList;
import com.common.security.Random;
/**
* This class houses a number of methods for generating prime numbers using different algorithms.
*/
public class PrimeNumberGenerator {
private static final BigInteger ZERO = BigInteger.valueOf(0L);
private static final BigInteger ONE = BigInteger.valueOf(1L);
private static final BigInteger TWO = BigInteger.valueOf(2L);
/**
* Identifies a plain prime number.
*/
public static final int PLAIN = 0;
/**
* Identifies a cryptographically strong prime number.
*/
public static final int STRONG = 1;
/**
* Identifies a Germain prime number.
*/
public static final int GERMAIN = 2;
/**
* Maintains a collection of small prime numbers so as to optmize things.
*/
private static BigInteger[] SMALL_PRIMES;
private static byte[] PRIME_BITMAP;
private static final int PRIME_BITMAP_SIZE = 30030; // 2*3*5*7*11*13 //
private static final BigInteger PRIME_BITMAP_MOD = BigInteger.valueOf(PRIME_BITMAP_SIZE);
private static final int SMALL_PRIME_THRESHOLD = 100;
private static BigInteger SMALL_PRIME_MOD;
static {
//This array was generated by "java cryptix.examples.math.ListPrimes 50000".//
int[] sp = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213,
2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287,
2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531,
2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617,
2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819,
2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181,
3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257,
3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511,
3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571,
3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821,
3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139,
4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231,
4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493,
4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583,
4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831,
4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003,
5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179,
5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279,
5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387,
5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521,
5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639,
5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693,
5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939,
5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053,
6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221,
6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301,
6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367,
6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571,
6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673,
6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761,
6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917,
6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297,
7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411,
7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499,
7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643,
7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017,
8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111,
8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219,
8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291,
8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387,
8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501,
8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597,
8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677,
8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741,
8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831,
8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929,
8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011,
9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109,
9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199,
9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283,
9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377,
9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439,
9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533,
9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631,
9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733,
9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811,
9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887,
9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007,
10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099,
10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177,
10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271,
10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343,
10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459,
10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567,
10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657,
10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739,
10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859,
10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949,
10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059,
11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149,
11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251,
11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329,
11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443,
11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527,
11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657,
11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777,
11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833,
11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933,
11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011,
12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109,
12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211,
12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289,
12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401,
12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487,
12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553,
12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641,
12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739,
12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829,
12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923,
12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007,
13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109,
13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187,
13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309,
13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411,
13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499,
13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619,
13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697,
13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781,
13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879,
13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967,
13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081,
14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197,
14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323,
14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419,
14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519,
14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593,
14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699,
14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767,
14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851,
14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947,
14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073,
15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149,
15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259,
15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319,
15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401,
15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497,
15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607,
15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679,
15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773,
15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881,
15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971,
15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069,
16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183,
16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267,
16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381,
16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481,
16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603,
16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691,
16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811,
16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903,
16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993,
17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093,
17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191,
17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317,
17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389,
17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477,
17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573,
17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669,
17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783,
17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891,
17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971,
17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059,
18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143,
18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233,
18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313,
18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427,
18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517,
18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637,
18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749,
18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899,
18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009,
19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121,
19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219,
19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319,
19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423,
19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477,
19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571,
19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699,
19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793,
19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891,
19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991,
19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071,
20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149,
20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261,
20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357,
20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443,
20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551,
20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693,
20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771,
20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897,
20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983,
21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067,
21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169,
21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277,
21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383,
21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491,
21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563,
21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647,
21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751,
21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841,
21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943,
21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039,
22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123,
22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229,
22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307,
22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441,
22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543,
22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643,
22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727,
22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817,
22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943,
22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029,
23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099,
23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203,
23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321,
23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447,
23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561,
23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629,
23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743,
23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827,
23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909,
23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007,
24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091,
24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169,
24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281,
24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413,
24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517,
24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659,
24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767,
24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877,
24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977,
24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097,
25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183,
25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303,
25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391,
25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471,
25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603,
25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693,
25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799,
25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913,
25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999,
26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111,
26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203,
26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297,
26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399,
26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497,
26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633,
26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711,
26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801,
26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891,
26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987,
26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077,
27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211,
27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329,
27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449,
27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551,
27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691,
27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767,
27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827,
27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947,
27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051,
28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151,
28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283,
28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403,
28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499,
28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579,
28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649,
28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729,
28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837,
28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933,
28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059,
29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167,
29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251,
29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363,
29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443,
29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573,
29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671,
29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819,
29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921,
29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059,
30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137,
30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241,
30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341,
30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469,
30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559,
30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689,
30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803,
30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871,
30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983,
31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091,
31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183,
31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259,
31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357,
31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511,
31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601,
31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721,
31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817,
31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973,
31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063,
32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159,
32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257,
32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353,
32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423,
32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531,
32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609,
32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717,
32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831,
32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939,
32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023,
33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113,
33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211,
33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343,
33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427,
33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533,
33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613,
33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713,
33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797,
33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893,
33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031,
34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157,
34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261,
34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337,
34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457,
34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537,
34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649,
34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739,
34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847,
34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961,
34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083,
35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159,
35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291,
35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401,
35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509,
35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593,
35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759,
35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863,
35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969,
35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061,
36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161,
36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277,
36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383,
36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497,
36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587,
36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691,
36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781,
36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877,
36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947,
36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057,
37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189,
37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309,
37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397,
37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507,
37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573,
37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663,
37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813,
37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951,
37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047,
38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183,
38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281,
38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371,
38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543,
38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639,
38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713,
38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821,
38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921,
38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041,
39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133,
39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227,
39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323,
39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419,
39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541,
39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667,
39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769,
39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857,
39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971,
39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087,
40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169,
40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283,
40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433,
40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531,
40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639,
40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787,
40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867,
40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973,
40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081,
41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183,
41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257,
41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387,
41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507,
41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603,
41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669,
41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801,
41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897,
41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981,
41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073,
42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187,
42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283,
42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379,
42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457,
42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557,
42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677,
42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743,
42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841,
42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953,
42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051,
43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189,
43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319,
43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451,
43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579,
43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661,
43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783,
43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933,
43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017,
44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101,
44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201,
44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279,
44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449,
44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537,
44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641,
44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741,
44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843,
44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953,
44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077,
45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181,
45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307,
45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403,
45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533,
45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641,
45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757,
45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853,
45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979,
45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099,
46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199,
46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309,
46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447,
46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549,
46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643,
46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747,
46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831,
46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993,
46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119,
47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221,
47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317,
47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419,
47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527,
47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629,
47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717,
47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819,
47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939,
47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049,
48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179,
48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299,
48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409,
48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497,
48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611,
48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733,
48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817,
48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907,
48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033,
49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123,
49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211,
49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339,
49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433,
49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537,
49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663,
49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757,
49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853,
49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957,
49991, 49993, 49999,
};
try {
SMALL_PRIMES = new BigInteger[sp.length];
for(int i = 0; i < sp.length; i++) {
SMALL_PRIMES[i] = BigInteger.valueOf(sp[i]);
}//for//
PRIME_BITMAP = new byte[(PRIME_BITMAP_SIZE+15)/16];
for(int i = 1; i <= 5; i++) {
int p = sp[i]; // 3, 5, 7, 11 or 13
for(int j = p; j < PRIME_BITMAP_SIZE; j += p+p) {
int x = j >> 1;
PRIME_BITMAP[x >> 3] |= (1 << (x & 0x07));
}//for//
}//for//
BigInteger x = ONE;
for(int i = 0; i < SMALL_PRIME_THRESHOLD; i++) {
x = x.multiply(SMALL_PRIMES[i]);
}//for//
SMALL_PRIME_MOD = x;
}//try//
catch(RuntimeException e) {
e.printStackTrace();
throw e;
}//catch//
}//static//
/**
* PrimeNumberGenerator constructor.
*/
private PrimeNumberGenerator() {
super();
}//PrimeNumberGenerator()//
/**
* Generates a random probable-prime, <i>p</i>, of the given length, such that all the factors of <i>p</i> - 1 are known.
* @param bitlength An approximate number of bits that the returned prime integer must have.
* @param certainty A measure of the probability that the returned integer <i>p</i>, and the largest factor of <i>p</i> - 1 are primes. The Miller-Rabin test used ensures that these values are prime with a probability that exceeds 1 - (1/2)<sup><i>certainty</i></sup>.
* @param random A source of randomness for the bits to use in building the prime.
* @param prime_type What type of prime to build: PLAIN, STRONG or GERMAIN.
* @return An array of two Objects: the first being the found prime itself, say <i>p</i>, and the second Object is an array of the known distinct prime factors of the value (<i>p</i> - 1).
*/
public static Object[] getElGamal(int bitlength, int certainty, Random random, int prime_type) {
BigInteger p = null;
BigInteger[] q = null;
switch(prime_type) {
case PLAIN:
//Alternative-1: replicate what we had before.//
while(q == null) {
p = new BigInteger(bitlength, certainty, random);
q = getSmallFactors(p.subtract(ONE), certainty);
//If input has only small factors it is insecure (see Pohlig and Hellman reference). Make sure that the last prime factor; i.e. the largest, is at least half the length of the input.//
if(q != null && q[q.length - 1].bitLength() <= p.bitLength() / 2) {
q = null;
}//if//
}//while//
break;
case STRONG:
//Alternative-2: use GORDON-built strong primes.//
BigInteger[] result;
BigInteger r;
while(q == null) {
result = getGordon(bitlength, certainty, random);
p = result[0];
r = result[1];
q = PrimeNumberGenerator.getSmallFactors(p.subtract(ONE), certainty, r);
}//while//
break;
case GERMAIN:
//Alternative-3: use GERMAIN primes.//
p = getGermain(bitlength, certainty, random);
q = new BigInteger[] {TWO, p.subtract(ONE).divide(TWO)};
break;
}//switch//
Object[] result = {p, q};
return result;
}//getElGamal()//
/**
* Gets a Germain (Sophie) probable-prime with an approximate specified <i>bitlength</i>, that is prime with a probability exceeding 1 - (1/2)<sup><i>certainty</i></sup>.
* <p> An integer <i>p</i> is a GERMAIN prime iff it is a prime, and <i>p</i> = 2<i>q</i> + 1 where <i>q</i> is also a prime.
* @param bitlength An approximate number of bits that the returned prime integer must have.
* @param certainty A measure of the probability that the returned integer is a prime. The Miller-Rabin test used ensures that the returned value is a prime with a probability that exceeds 1 - (1/2)<sup><i>certainty</i></sup>.
* @param random A source of randomness for the bits to use in building the prime.
* @return A Germain prime: a prime of the form 2q + 1 where q is also a prime.
*/
public static BigInteger getGermain(int bitlength, int certainty, Random random) {
BigInteger q, p;
//Generating a GERMAIN prime.//
while(true) {
q = new BigInteger(bitlength, certainty, random);
p = TWO.multiply(q).add(ONE);
if(isProbablePrimeFast(p, certainty)) {
break;
}//if//
}//while//
return p;
}//getGermain()//
/**
* Gets a Gordon <b>strong</b> probable-prime with an approximate specified <i>bitlength</i>, that is prime with a probability exceeding 1 - (1/2)<sup><i>certainty</i></sup>.
* <p> A prime is said to be <b>strong</b> iff integers <i>r</i>, <i>s</i>, and <i>t</i> exist such that the following three conditions are satisfied:
* <ol>
* <li> <i>p</i> - 1 has a large prime factor, denoted <i>r</i>,
* <li> <i>p</i> + 1 has a large prime factor, denoted <i>s</i>, and
* <li> <i>r</i> - 1 has a large prime factor, denoted <i>t</i>.
* </ol>
* <p>
* GORDON's algorithm is described in [HAC] p.150 as follows:
* <ol>
* <li> generate 2 random primes <i>s</i> and <i>t</i> of roughly
* equal bit-length.
* <li> select an integer i0. Find the first prime in the
* sequence <i>2it + 1</i>, for <i>i = i0, i0+1, i0+2,...</i>
* Denote this prime by <i>r = 2it + 1</i>.
* <li> compute <i>p0 = 2(s<sup>(r-2)</sup> mod r)s - 1</i> --See errata
* on [HAC] web site.
* <li> select an integer j0. Find the first prime in the sequence
* <i>p0 + 2jrs</i>, for <i>j = j0, j0 + 1, j0 + 2, ...</i>
* Denote this prime by <i>p = p0 + 2jrs</i>.
* <li> return <i>p</i>.
* </ol>
* @param bitlength An approximate number of bits that the returned prime integer must have.
* @param certainty A measure of the probability that the returned integer is a prime. The Miller-Rabin test used ensures that the returned value is a prime with a probability that exceeds 1 - (1/2)<sup><i>certainty</i></sup>.
* @param random A source of randomness for the bits to use in building the prime.
* @return An array whose elements are respectively p, r, s and t.
*/
public static BigInteger[] getGordon(int bitLength, int certainty, Random random) {
//1. generate 2 random primes s and t of roughly equal bitlength
BigInteger s = new BigInteger(bitLength / 2, certainty, random);
BigInteger t = new BigInteger(bitLength / 2, certainty, random);
//2. select an integer i0. Find the first prime in the sequence
// 2it + 1, for i = i0, i0+1, i0+2,... Denote this prime by
// r = 2it + 1
BigInteger t2 = t.multiply(TWO);
BigInteger r = t2.add(ONE);
//Generating a strong prime (GORDON algorithm)...//
while(!isProbablePrimeFast(r, certainty)) {
r = r.add(t2);
}//while//
//3. compute p0 = 2(s**(r-2) mod r)s - 1.
// See errata on [HAC] web site.
BigInteger p0 = s.modPow(r.subtract(TWO), r).multiply(s).multiply(TWO).subtract(ONE);
//4. select an integer j0. Find the first prime in the sequence
// p0 + 2jrs, for j = j0, j0+1, j0+2,... Denote this prime by
// p = p0 + 2jrs
BigInteger rs2 = r.multiply(s).multiply(TWO);
BigInteger p = p0.add(rs2);
//if(DEBUG && debuglevel >= 4) progress("<p>");
while(!isProbablePrimeFast(p, certainty)) {
p = p.add(rs2);
//if(DEBUG && debuglevel >= 5) progress(".");
}//while//
return new BigInteger[] {p, r, s, t};
}//getGordon()//
/**
* Gets a BigInteger array whose elements are the prime factors of a designated BigInteger value, or null if the value could not easily be factorised.
* @param r A BigInteger to factor.
* @param certainty A measure of the probability that the largest returned factor is a prime. The Miller-Rabin test used ensures that this factor is a prime with a probability that exceeds 1 - (1/2)<sup><i>certainty</i></sup>.
* @return A BigInteger array whose elements are the distinct prime factors of <i>p</i> when the latter can be written as: <pre> S_1 * S_2 * ... * S_n * L </pre>
* Where S_i are small prime factors found in SMALL_PRIMES and L is a large prime factor. Return null otherwise.
*/
public static BigInteger[] getSmallFactors (BigInteger r, int certainty) {
BigInteger[] result;
BigInteger s;
LiteList factors = new LiteList(100, 100);
for(int i = 0; i < SMALL_PRIMES.length; i++) {
s = SMALL_PRIMES[i];
result = r.divideAndRemainder(s);
if(result[1].equals(ZERO)) {
factors.add(s); //SMALL_PRIMES[i] is a factor.//
r = result[0]; //The quotient.//
//It may be a factor more than once; divide out from r.//
while(true) {
result = r.divideAndRemainder(s);
if(!result[1].equals(ZERO)) {
break;
}//if//
r = result[0]; // the quotient
}//while//
}//if//
}//for//
if(!r.equals(ONE)) {
//if(DEBUG && debuglevel >= 5) progress("(" + r.bitLength() + "-bit ");
if(!r.isProbablePrime(certainty)) { // check that r is prime.
//if(DEBUG && debuglevel >= 5) err.println("composite)");
return null;
}//if//
//if(DEBUG && debuglevel >= 5) err.println("prime)");
factors.add(r);
}//if//
else {
//if(DEBUG && debuglevel >= 5) err.println("1");
}//else//
BigInteger[] z = new BigInteger[factors.getSize()];
factors.toArray(z);
return z;
}//getSmallFactors()//
/**
* Gets a BigInteger array whose elements are the prime factors of a designated BigInteger value, for which we already have one large prime factor.<p>
* The returned array conatins all the distinct factors including the one we gave on input. The returned array is not guaranteed to be in any specific order.
* @param r A BigInteger to factor.
* @param certainty A measure of the probability that the returned integers are primes. The Miller-Rabin test used ensures that each array element is a prime with a probability that exceeds 1 - (1/2)<sup><i>certainty</i></sup>.
* @param q A known prime factor of r.
* @return If all the prime factors, except two (one of which is <i>q</i>), can be found in the list of pre-computed small primes the method returns an
* array whose elements are the distinct prime factors of <i>r</i>. On the other hand if not all the prime factors, except two, can be found in the
* list of pre-computed small primes the method returns null.
*/
public static BigInteger[] getSmallFactors(BigInteger r, int certainty, BigInteger q) {
BigInteger[] result = r.divideAndRemainder(q);
if(!result[1].equals(ZERO)) {
throw new ArithmeticException("q is not a factor of r");
}//if//
BigInteger t = result[0]; //The quotient.//
while(true) {
result = t.divideAndRemainder(q);
if(!result[1].equals(ZERO)) {
break;
}//if//
t = result[0]; //The quotient.//
}//while//
BigInteger s;
LiteList factors = new LiteList(100, 100);
for(int i = 0; i < SMALL_PRIMES.length; i++) {
s = SMALL_PRIMES[i];
result = t.divideAndRemainder(s);
if(result[1].equals(ZERO)) {
factors.add(s); //SMALL_PRIMES[i] is a factor.//
t = result[0]; //The quotient.//
//It may be a factor more than once; reduce t.//
while (true) {
result = t.divideAndRemainder(s);
if(!result[1].equals(ZERO)) {
break;
}//if//
t = result[0]; //The quotient.//
}//while//
}//if//
}//for//
if(!t.equals(ONE)) {
if(!t.isProbablePrime(certainty)) { // check that t is prime.
//if(DEBUG && debuglevel >= 5) err.println("composite)");
return null;
}//if//
//if(DEBUG && debuglevel >= 5) err.println("prime)");
factors.add(t);
}//if//
else {
//if(DEBUG && debuglevel >= 5) err.println("1");
}//else//
factors.add(q); //The one we started with.//
BigInteger[] z = new BigInteger[factors.getSize()];
factors.toArray(z);
return z;
}//getSmallFactors()//
/**
* ?
* @param g
* @param p
* @param z An array containing (p-1)/q for each unique prime factor q of p-1.
* @return Will be true if <i>g</i> is a generator mod <i>p</i>.
*/
public static boolean isGeneratorModP(BigInteger g, BigInteger p, BigInteger[] z) {
for(int i = 0; i < z.length; i++) {
if(g.modPow(z[i], p).equals(ONE)) {
return false;
}//if//
}//for//
return true;
}//isGeneratorModP()//
/**
* Implements a faster (on average) primality check than <code>BigInteger.isProbablePrime(r, certainty)</code>.
* @param r The number to check.
* @param certainty The level of certainty required.
* @return Whether the integer is a probable prime number.
*/
public static boolean isProbablePrimeFast(BigInteger r, int certainty) {
int x = r.mod(PRIME_BITMAP_MOD).intValue() >> 1;
if((PRIME_BITMAP[x >> 3] & (1 << (x & 0x07))) != 0) {
return false;
}//if//
BigInteger q = r.mod(SMALL_PRIME_MOD);
for(int i = 0; i < SMALL_PRIME_THRESHOLD; i++) {
if (q.mod(SMALL_PRIMES[i]).equals(ZERO)) return false;
}//for//
return r.isProbablePrime(certainty);
}//isProbablePrimeFast()//
}//PrimeNumberGenerator()//

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.event;
/**
* Performs some task using the passed parameters and returns a value of Boolean type.
*/
public abstract class BooleanHandler implements java.io.Externalizable {
/**
* BooleanHandler constructor.
*/
public BooleanHandler() {
super();
}//BooleanHandler()//
/**
* Performs what ever the handler is coded to do when called.
* @param parameters Object[] The parameters passed to the handler when it is invoked.
* @return The return value of the handler which must either be a Boolean.TRUE or Boolean.FALSE value and should not be null.
*/
public abstract Boolean evaluate(Object[] parameters);
/**
* Will handle reading the handler from an input stream.
* @param in java.io.ObjectInput The input stream to read the data from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
}//readExternal()//
/**
* Will handle writing the handler to an output stream.
* @param out java.io.ObjectOutput The output stream to write the data to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
}//writeExternal()//
}//BooleanHandler//

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.event;
/**
* Performs some task using the passed parameters and returns a value of Boolean type.
*/
public abstract class BooleanHandler1 extends BooleanHandler {
/**
* BooleanHandler1 constructor.
*/
public BooleanHandler1() {
super();
}//BooleanHandler1()//
/**
* Calls the evaluate method that takes one parameter.
* @param parameters Object[] The parameters passed to the handler when it is invoked.
* @return The return value of the handler which must either be a Boolean.TRUE or Boolean.FALSE value and should not be null.
*/
public final Boolean evaluate(Object[] parameters) {
return evaluate(((parameters != null) && (parameters.length > 0)) ? parameters[0] : null);
}//evaluate()//
/**
* Performs what ever the handler is coded to do when called.
* @param param1 The parameter passed to the handler when it is invoked.
* @return The return value of the handler which must either be a Boolean.TRUE or Boolean.FALSE value and should not be null.
*/
public abstract Boolean evaluate(Object param1);
}//BooleanHandler1//

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.event;
/**
* Performs some task using the passed parameters and returns a value of Boolean type.
*/
public abstract class BooleanHandler2 extends BooleanHandler {
/**
* BooleanHandler2 constructor.
*/
public BooleanHandler2() {
super();
}//BooleanHandler2()//
/**
* Calls the evaluate method that takes two parameters.
* @param parameters The parameters passed to the handler when it is invoked.
* @return The return value of the handler which must either be a Boolean.TRUE or Boolean.FALSE value and should not be null.
*/
public final Boolean evaluate(Object[] parameters) {
return evaluate(((parameters != null) && (parameters.length > 0)) ? parameters[0] : null, ((parameters != null) && (parameters.length > 1)) ? parameters[1] : null);
}//evaluate()//
/**
* Performs what ever the handler is coded to do when called.
* @param param1 The first parameter passed to the handler when it is invoked.
* @param param2 The second parameter passed to the handler when it is invoked.
* @return The return value of the handler which must either be a Boolean.TRUE or Boolean.FALSE value and should not be null.
*/
public abstract Boolean evaluate(Object param1, Object param2);
}//BooleanHandler2//

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.event;
/**
* Performs some task using the passed parameters and returns a value of Object type.
*/
public abstract class ObjectHandler implements java.io.Externalizable {
/**
* BooleanHandler constructor.
*/
public ObjectHandler() {
super();
}//BooleanHandler()//
/**
* Performs some action when the handler is invoked.
* @param parameters The parameters passed to the handler when it is invoked.
* @return The object value that is the result of the task handling.
*/
public abstract Object evaluate(Object[] parameters);
/**
* Will handle reading the handler from an input stream.
* @param in java.io.ObjectInput The input stream to read the data from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
}//readExternal()//
/**
* Will handle writing the handler to an output stream.
* @param out java.io.ObjectOutput The output stream to write the data to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
}//writeExternal()//
}//ObjectHandler//

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.event;
/**
* Performs some task using the passed parameters and returns a value of Object type.
*/
public abstract class ObjectHandler1 extends ObjectHandler {
/**
* ObjectHandler1 constructor.
*/
public ObjectHandler1() {
super();
}//ObjectHandler1()//
/**
* Calls the evaluate method that takes one parameter.
* @param parameters The parameters passed to the handler when it is invoked.
* @return The object value that is the result of the task handling.
*/
public final Object evaluate(Object[] parameters) {
return evaluate(((parameters != null) && (parameters.length > 0)) ? parameters[0] : null);
}//evaluate()//
/**
* Performs some action when the handler is invoked.
* @param param1 The parameter passed to the handler when it is invoked.
* @return The object value that is the result of the task handling.
*/
public abstract Object evaluate(Object param1);
}//ObjectHandler1//

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.event;
/**
* Performs some task using the passed parameters and returns a value of Object type.
*/
public abstract class ObjectHandler2 extends ObjectHandler {
/**
* ObjectHandler2 constructor.
*/
public ObjectHandler2() {
super();
}//ObjectHandler2()//
/**
* Calls the evaluate method that takes two parameters.
* @param parameters The parameters passed to the handler when it is invoked.
* @return The object value that is the result of the task handling.
*/
public final Object evaluate(Object[] parameters) {
return evaluate(((parameters != null) && (parameters.length > 0)) ? parameters[0] : null, ((parameters != null) && (parameters.length > 1)) ? parameters[1] : null);
}//evaluate()//
/**
* Performs some action when the handler is invoked.
* @param param1 The first parameter passed to the handler when it is invoked.
* @param param2 The second parameter passed to the handler when it is invoked.
* @return The object value that is the result of the task handling.
*/
public abstract Object evaluate(Object param1, Object param2);
}//ObjectHandler2//

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.event;
/**
* Performs some task using the passed array of parameters.
* <p>NOTE: If you want a handler that takes three or less parameters then use on of the HandlerN classes where N is the number of parameters the handler takes.
*/
public abstract class VoidHandler implements java.io.Externalizable {
/**
* Handler constructor.
*/
public VoidHandler() {
super();
}//Handler()//
/**
* Performs what ever the handler is coded to do when called.
* @param parameters The parameters passed to the handler when it is invoked.
*/
public abstract void evaluate(Object[] parameters);
/**
* Handles reading the handler from an input stream.
* @param in The input stream to read the data from.
*/
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
}//readExternal()//
/**
* Handles writing the handler to an output stream.
* @param out The output stream to write the data to.
*/
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
}//writeExternal()//
}//Handler//

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.event;
/**
* Performs some task.
*/
public abstract class VoidHandler0 extends VoidHandler {
/**
* Handler0 constructor.
*/
public VoidHandler0() {
super();
}//Handler0()//
/**
* Performs what ever the handler is coded to do when called.
*/
public abstract void evaluate();
/**
* Calls the evaluate method that takes no parameters.
* @param parameters The parameters passed to the handler when it is invoked.
*/
public void evaluate(Object[] parameters) {
evaluate();
}//evaluate()//
}//Handler0//

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.event;
/**
* Performs some task using the passed parameter.
*/
public abstract class VoidHandler1 extends VoidHandler {
/**
* Handler1 constructor.
*/
public VoidHandler1() {
super();
}//Handler1()//
/**
* Calls the evaluate method that takes one parameter.
* @param parameters The parameters passed to the handler when it is invoked.
*/
public final void evaluate(Object[] parameters) {
evaluate(((parameters != null) && (parameters.length > 0)) ? parameters[0] : null);
}//evaluate()//
/**
* Performs what ever the handler is coded to do when called.
* @param param1 The parameter passed to the handler when it is invoked.
*/
public abstract void evaluate(Object param1);
}//Handler1//

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.event;
/**
* Performs some task using the passed parameters.
*/
public abstract class VoidHandler2 extends VoidHandler {
/**
* Handler2 constructor.
*/
public VoidHandler2() {
super();
}//Handler2()//
/**
* Calls the evaluate method that takes two parameters.
* @param parameters The parameters passed to the handler when it is invoked.
*/
public final void evaluate(Object[] parameters) {
evaluate(((parameters != null) && (parameters.length > 0)) ? parameters[0] : null, ((parameters != null) && (parameters.length > 1)) ? parameters[1] : null);
}//evaluate()//
/**
* Performs what ever the handler is coded to do when called.
* @param param1 The first parameter passed to the handler when it is invoked.
* @param param2 The second parameter passed to the handler when it is invoked.
*/
public abstract void evaluate(Object param1, Object param2);
}//Handler2//

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.exception;
public class CommonRuntimeException extends RuntimeException {
/**
* CommonRuntimeException constructor.
*/
public CommonRuntimeException() {
super();
}//CommonRuntimeException()//
/**
* CommonRuntimeException constructor.
* @param description String The exception description.
*/
public CommonRuntimeException(String description) {
super(description);
}//CommonRuntimeException()//
}//CommonRuntimeException//

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.exception;
public class EventException extends CommonRuntimeException {
/**
* EventException constructor.
*/
public EventException() {
super();
}//EventException()//
/**
* EventException constructor.
* @param description String The exception description.
*/
public EventException(String description) {
super(description);
}//EventException()//
}//EventException//

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.exception;
public class IOSecurityException extends java.io.IOException {
/**
* IOSecurityException constructor.
*/
public IOSecurityException() {
super();
}//IOSecurityException()//
/**
* IOSecurityException constructor.
* @param description The exception's description.
*/
public IOSecurityException(String description) {
super(description);
}//IOSecurityException()//
}//IOSecurityException//

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.exception;
public class IllegalOperationException extends CommonRuntimeException {
/**
* IllegalOperationException constructor.
*/
public IllegalOperationException() {
super();
}//IllegalOperationException()//
/**
* IllegalOperationException constructor.
* @param description String The exception description.
*/
public IllegalOperationException(String description) {
super(description);
}//IllegalOperationException()//
}//IllegalOperationException//

View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.exception;
/**
* Thrown when a method has determined that one of its' arguments has an invalid or unexpected value.
*/
public class InvalidArgumentException extends CommonRuntimeException {
/**
* InvalidArgumentException constructor.
*/
public InvalidArgumentException() {
super();
}//InvalidArgumentException()//
/**
* InvalidArgumentException constructor.
* @param description String The exception description.
*/
public InvalidArgumentException(String description) {
super(description);
}//InvalidArgumentException()//
}//InvalidArgumentException//

View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.exception;
/**
* Thrown when a method that the user called is not being supported at all or under some circumstances.
*/
public class MethodNotSupportedException extends CommonRuntimeException {
/**
* MethodNotSupportedException constructor.
*/
public MethodNotSupportedException() {
super();
}//MethodNotSupportedException()//
/**
* MethodNotSupportedException constructor.
* @param description The exception description.
*/
public MethodNotSupportedException(String description) {
super(description);
}//MethodNotSupportedException()//
}//MethodNotSupportedException//

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.exception;
public class ThreadException extends CommonRuntimeException {
/**
* ThreadException constructor.
*/
public ThreadException() {
super();
}//ThreadException()//
/**
* ThreadException constructor.
* @param description String The exception description.
*/
public ThreadException(String description) {
super(description);
}//ThreadException()//
}//ThreadException//

View File

@@ -0,0 +1,929 @@
/*
* Copyright (c) 1999,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.io;
import java.io.IOException;
import java.io.Externalizable;
import java.lang.reflect.Array;
import com.common.orb.Orb;
import com.common.util.*;
import com.common.debug.*;
import com.common.exception.*;
/**
* Defines a basic object input stream which can be subclassed as needed.
*/
public abstract class AbstractObjectInputStream extends AbstractStandardInputStream implements IObjectStream, java.io.ObjectInput, IObjectInputStream {
/** A factory that will produce an instance of the given class. If provided, this will be used instead of calling Class.newInstance(). */
private IInstanceFactory instanceFactory = null;
/** The class tracker is notified every time a class is referenced by the stream. It allows the application to track what classes are utilized by the streams. */
private IClassTracker classTracker = null;
/** The list of classes that were serialized indexed by the number the stream will use to reference them in the future. */
private IList classList = null;
/** The optional class loader which is used if provided to lookup the class names. */
private ClassLoader loader = null;
/** The collection of objects deserialized in order of deserialization. Used to reference previously deserialized values by number in the stream to prevent recursive references from bloating the stream. */
private IList deserializedValues = null;
/** Called prior to looking up the deserialized class name - allows replacement of the class name. */
private IClassReplacementHandler classReplacementHandler = null;
/** Allows the input stream to replace one class with another <b>if the original class cannot be found</b>. */
private IStreamManager streamManager = null;
/**
* Provides customized deserialization of streamed application objects.
* <p><b>WARNING: Circular reference to this serialized object may not occur within its deserialization.</b>
* <p>The deserialize method will receive the object's class object and the stream reference. It should determine whether it can deserialize that type and either pass the request to the encapsulated handler, or return null indicating that the default action should occur within the stream.</p>
* <p>The encapsulated handler allows the handlers to be chained together such that the stream calls the first handler in the chain and it will call the next handler until a handler deserializes the object, or all handlers return null.</p>
* <p>TODO: Allow for circular references in the deserialized object.
*/
public static class CustomDeserializationHandler {
private CustomDeserializationHandler encapsulatedHandler = null;
public CustomDeserializationHandler() {
}//CustomDeserializationHandler()//
public CustomDeserializationHandler(CustomDeserializationHandler encapsulatedHandler) {
this.encapsulatedHandler = encapsulatedHandler;
}//CustomDeserializationHandler()//
/**
* Gets the encapsulated handler providing deserialization services.
* @return The handler that will be called if this handler cannot deserialize the object.
*/
public CustomDeserializationHandler getEncapsulatedHandler() {
return encapsulatedHandler;
}//getEncapsulatedHandler()//
/**
* Sets the encapsulated handler providing deserialization services.
* @param encapsulatedHandler The handler that will be called if this handler cannot deserialize the object.
*/
public void setEncapsulatedHandler(CustomDeserializationHandler encapsulatedHandler) {
this.encapsulatedHandler = encapsulatedHandler;
}//setEncapsulatedHandler()//
/**
* Receives the object's class object and the stream reference and determines whether it can deserialize that type, either passing the request to the encapsulated handler, or returning null indicating that the default action should occur within the stream.
* <p><b>WARNING: Circular reference to this serialized object may not occur within its deserialization.</b>
* @param type The class for the object needing deserialization.
* @param in The input stream containing the serialized object's bytes.
* @return The object deserialized or null indicating that the stream should deserialize the object using the default deserialization algorithms.
*/
public Object deserialize(Class type, AbstractObjectInputStream in) {
return encapsulatedHandler == null ? null : encapsulatedHandler.deserialize(type, in);
}//deserialize()//
}//CustomDeserializationHandler//
/**
* Adds a custom serialization handler to the mapping for use by the object input and output streams.
* @param type The class the handler will be used to serialize and deserialize.
* @param handler The handler used to serialize and deserialize instances of the given class.
*/
public static final void addCustomSerializationHandler(Class type, ISerializationHandler handler) {
ObjectStream.serializationHandlersMap.put(type, handler);
}//addCustomSerializationHandler()//
/**
* AbstractObjectInputStream constructor.
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
*/
public AbstractObjectInputStream(ClassLoader loader, IList classList) throws IOException {
this(loader, null, classList, null, null, null);
}//AbstractObjectInputStream()//
/**
* AbstractObjectInputStream constructor.
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
*/
public AbstractObjectInputStream(ClassLoader loader, IList classList, IInstanceFactory instanceFactory) throws IOException {
this(loader, null, classList, instanceFactory, null, null);
}//AbstractObjectInputStream()//
/**
* AbstractObjectInputStream constructor.
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
* @param classReplacementHandler The optional handler called when the stream loads a class. Allows the stream to replace one class name with another.
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
* @param classTracker This optional handler is notified if a class is instantiated, allowing applications to track which classes are being streamed and instantiated.
*/
public AbstractObjectInputStream(ClassLoader loader, IClassReplacementHandler classReplacementHandler, IList classList, IInstanceFactory instanceFactory, IClassTracker classTracker) throws IOException {
this(loader, classReplacementHandler, classList, instanceFactory, classTracker, null);
}//AbstractObjectInputStream()//
/**
* AbstractObjectInputStream constructor.
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
* @param classReplacementHandler The optional handler called when the stream loads a class. Allows the stream to replace one class name with another.
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
* @param classTracker This optional handler is notified if a class is instantiated, allowing applications to track which classes are being streamed and instantiated.
* @param deserializedValues The previously deserialized values.
*/
protected AbstractObjectInputStream(ClassLoader loader, IClassReplacementHandler classReplacementHandler, IList classList, IInstanceFactory instanceFactory, IClassTracker classTracker, IList deserializedValues) throws IOException {
super();
this.classReplacementHandler = classReplacementHandler;
this.classTracker = classTracker;
this.loader = loader;
this.classList = classList;
this.deserializedValues = deserializedValues == null ? new LiteList(30, 10) : deserializedValues;
this.instanceFactory = instanceFactory;
}//AbstractObjectInputStream()//
/**
* AbstractObjectInputStream constructor.
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
*/
public AbstractObjectInputStream(ClassLoader loader, IList classList, int defaultNumberStyle) throws IOException {
this(loader, null, classList, null, null, null, defaultNumberStyle);
}//AbstractObjectInputStream()//
/**
* AbstractObjectInputStream constructor.
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
*/
public AbstractObjectInputStream(ClassLoader loader, IList classList, IInstanceFactory instanceFactory, int defaultNumberStyle) throws IOException {
this(loader, null, classList, instanceFactory, null, null, defaultNumberStyle);
}//AbstractObjectInputStream()//
/**
* AbstractObjectInputStream constructor.
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
* @param classReplacementHandler The optional handler called when the stream loads a class. Allows the stream to replace one class name with another.
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
* @param classTracker This optional handler is notified if a class is instantiated, allowing applications to track which classes are being streamed and instantiated.
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
*/
public AbstractObjectInputStream(ClassLoader loader, IClassReplacementHandler classReplacementHandler, IList classList, IInstanceFactory instanceFactory, IClassTracker classTracker, int defaultNumberStyle) throws IOException {
this(loader, classReplacementHandler, classList, instanceFactory, classTracker, null, defaultNumberStyle);
}//AbstractObjectInputStream()//
/**
* AbstractObjectInputStream constructor.
* @param loader The class loader to use when it is necessary to load classes when creating objects read from the stream.
* @param classReplacementHandler The optional handler called when the stream loads a class. Allows the stream to replace one class name with another.
* @param classList An optional list used to maintain the order classes were recognized by the stream. This allows class indexes to be streamed in place of the class name. This list is passed so that it may be reused if multiple streams from the same source are read.
* @param instanceFactory The instance factory to be used to generate instances of classes read from the stream.
* @param classTracker This optional handler is notified if a class is instantiated, allowing applications to track which classes are being streamed and instantiated.
* @param deserializedValues The previously deserialized values.
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
*/
protected AbstractObjectInputStream(ClassLoader loader, IClassReplacementHandler classReplacementHandler, IList classList, IInstanceFactory instanceFactory, IClassTracker classTracker, IList deserializedValues, int defaultNumberStyle) throws IOException {
super(defaultNumberStyle);
this.classReplacementHandler = classReplacementHandler;
this.classTracker = classTracker;
this.loader = loader;
this.classList = classList;
this.deserializedValues = deserializedValues == null ? new LiteList(30, 10) : deserializedValues;
this.instanceFactory = instanceFactory;
}//AbstractObjectInputStream()//
/* (non-Javadoc)
* @see com.common.io.IObjectInputStream#getInstanceFactory()
*/
public IInstanceFactory getInstanceFactory() {
return instanceFactory;
}//()//
/* (non-Javadoc)
* @see com.common.io.IObjectInputStream#getClassTracker()
*/
public IClassTracker getClassTracker() {
return classTracker;
}//getClassTracker()//
/* (non-Javadoc)
* @see com.common.io.IObjectInputStream#getClassList()
*/
public IList getClassList() {
return classList;
}//getClassList()//
/* (non-Javadoc)
* @see com.common.io.IObjectInputStream#getLoader()
*/
public ClassLoader getLoader() {
return loader;
}//getLoader()//
/* (non-Javadoc)
* @see com.common.io.IObjectInputStream#getDeserializedValues()
*/
public IList getDeserializedValues() {
return deserializedValues;
}//getDeserializedValues()//
/* (non-Javadoc)
* @see com.common.io.IObjectInputStream#getClassReplacementHandler()
*/
public IClassReplacementHandler getClassReplacementHandler() {
return classReplacementHandler;
}//getClassReplacementHandler()//
/* (non-Javadoc)
* @see com.common.io.IObjectInputStream#getStreamManager()
*/
public IStreamManager getStreamManager() {
return streamManager;
}//getStreamManager()//
/**
* Allocates memory for a new object of the given type.
* <p>WARNING: At this time, proper initialization of the object may not occur.
* @param type The class to create a new object for.
* @return The new initialized object.
*/
private Object allocateNewObject(Class type) throws InstantiationException, IllegalAccessException {
Object result = null;
if(type == null) {
throw new InstantiationException("Received a null class reference in ObjectInputStream.allocateNewObject(Class).");
}//if//
if(classTracker != null) {
classTracker.add(type.getName());
}//if//
//First try to use the instance factory.//
if(instanceFactory != null) {
result = instanceFactory.createInstance(type);
}//if/
//Second try using a default constructor.//
if(result == null) {
try {
result = type.newInstance();
}//try//
catch(Throwable e) {
//Ignore.//
}//catch//
}//if//
//Last try the native system call.//
if(result == null) {
//TODO: Should make sure that this fails gracefully if the library is not available.//
result = com.common.system.SystemManager.instantiateObject(type);
}//if//
return result;
}//allocateNewObject()//
/**
* Closes this input stream. Will also close the wrappered stream.
*/
public void close() throws IOException {
if(deserializedValues != null) {
deserializedValues.removeAll();
deserializedValues = null;
}//if//
}//close()//
/**
* Deserailizes an object from this stream.
* @return The object that was deserialized.
*/
protected Object deserialize(Class type) throws IOException, ClassNotFoundException {
Object result = null;
ISerializationHandler handler = null;
if((ObjectStream.serializationHandlersMap != null) && ((handler = (ISerializationHandler) ObjectStream.serializationHandlersMap.get(type)) != null)) {
result = handler.deserialize(this);
}//if//
else if(Throwable.class.isAssignableFrom(type)) {
//Allow the exceptions to be deserialized, although we will be unable to set the message of stack.//
}//else if//
else {
throw new IOException("Unable to deserialize the object of type: " + type.getName());
}//else//
return result;
}//deserialize()//
/**
* Deserializes an object from this stream.
* @param object The object to deserialize.
* @return The deserialized object. May differ from the passed object.
*/
protected Object deserialize(Object object) throws ClassNotFoundException, IOException {
//Note: The proxy class can't implement IExternalizable, but the proxied class can. To avoid trying to make a remote call to the IExternalizable readExternal method, we need to ensure this isn't a proxy.//
if(object instanceof IExternalizable/* && !Orb.isProxy(object)*/) {
Object result = ((IExternalizable) object).readExternal(this);
if(result != null) {
if(result == IExternalizable.NULL_VALUE) {
object = null;
}//if//
else {
object = result;
}//else//
}//if//
}//if//
else if(object instanceof Externalizable) {
((Externalizable) object).readExternal(this);
}//else if//
else if(object instanceof Throwable) {
//Allow the exceptions to be deserialized, although we will be unable to set the message of stack.//
}//else if//
else {
throw new IOException("Unable to deserialize the object of type: " + object.getClass().getName());
}//else//
return object;
}//deserialize()//
/**
* Loads a class using what ever class loader has been specified.
* @param className The name of the class to load.
* @return The loaded class.
*/
private Class loadClass(String className) throws ClassNotFoundException {
try {
if(classReplacementHandler != null) {
className = classReplacementHandler.getReplacementClassName(className);
}//if//
return Class.forName(className, true, loader == null ? getClass().getClassLoader() : loader);
}//try//
catch(IncompatibleClassChangeError e) {
Debug.log(e);
throw new ClassNotFoundException("The class " + className + " was not loadable.");
}//catch//
catch(NoClassDefFoundError e) {
Debug.log(e);
throw new ClassNotFoundException("The class " + className + " definition was not found.");
}//catch//
}//loadClass()//
/**
* Will allow the user of the stream to peek at a byte in the stream.
* @param offset The offset from the current location in the stream.
* @return Will return the byte at that offset.
*/
public byte peekByte(int offset) throws IOException {
/* if((position + offset < count) && (position + offset >= 0)) {
return buffer[position + offset];
}//if//
throw new IOException("Invalid offset.");
*/
throw new IOException("ObjectInputStream.peakByte(int) not yet implemented.");
}//peekByte()//
/**
* Reads an array from the stream.
* @param isPrimitive Whether the array is of a primitive type.
* @return The array object.
*/
private Object readArray() throws IOException, ClassNotFoundException {
int deserializedValueIndex = deserializedValues.getSize();
Object array = null;
String typeName;
Class type;
int typeNumber;
int dimensionCount;
int dimensionSize;
boolean isNative = readBoolean();
deserializedValues.add(null);
if(isNative) {
switch(readByte()) {
case BOOLEAN: {
type = Boolean.TYPE;
break;
}//case//
case BYTE: {
type = Byte.TYPE;
break;
}//case//
case SHORT: {
type = Short.TYPE;
break;
}//case//
case INTEGER: {
type = Integer.TYPE;
break;
}//case//
case FLOAT: {
type = Float.TYPE;
break;
}//case//
case LONG: {
type = Long.TYPE;
break;
}//case//
case DOUBLE: {
type = Double.TYPE;
break;
}//case//
case CHARACTER: {
type = Character.TYPE;
break;
}//case//
default: {
Debug.log("Error: Unidentified primitive type.");
type = null;
break;
}//default//
}//switch//
typeName = type.getName();
}//if//
else {
typeName = readString();
type = loadClass(typeName);
}//else//
typeNumber = readByte();
dimensionCount = readInt();
//Read the first dimension's size so that we can create the array.//
dimensionSize = readInt();
if(dimensionSize != -1) {
//Create the array with a size for only the first dimension.//
try {
array = Array.newInstance(type, dimensionSize);
}//try//
catch(Throwable e) {
Debug.log(e, "Caught while trying to instantiate an instance of [" + typeName);
throw new IOException("Error instantiating array.");
}//catch//
deserializedValues.replace(deserializedValueIndex, array);
readArray(array, typeName, typeNumber, 0, dimensionCount, dimensionSize);
if(classTracker != null) {
classTracker.add(array.getClass().getName());
}//if//
}//if//
return array;
}//readArray()//
/**
* A recusive method which will iterate over each item in the array and output it to the stream.
* The arrayType should be Stream.OBJECT or one of the primitives (ie Stream.INTEGER or Stream.BYTE..etc).
* @param array The array housing the data to be read. This array is already correctly sized for the data.
* @param typeNumber The array type indicating what type of data is being read.
* @param dimension The current dimension being read.
* @param dimensionCount The number of dimensions to be read.
* @param dimensionSize The count of elements in the given array to be read.
*/
private void readArray(Object array, String typeName, int typeNumber, int dimension, int dimensionCount, int dimensionSize) throws IOException, ClassNotFoundException {
if(dimension + 1 == dimensionCount) {
switch(typeNumber) {
case OBJECT: {
for(int index = 0; index < dimensionSize; index++) {
Object obj = readObject();
if(obj != null) { //Temp fix for gcj.//
Array.set(array, index, obj);
}//if//
}//for//
break;
}//case//
case INTEGER: {
int[] typedArray = (int[]) array;
for(int index = 0; index < dimensionSize; index++) {
typedArray[index] = readInt();
}//for//
break;
}//case//
case LONG: {
long[] typedArray = (long[]) array;
for(int index = 0; index < dimensionSize; index++) {
typedArray[index] = readLong();
}//for//
break;
}//case//
case SHORT: {
short[] typedArray = (short[]) array;
for(int index = 0; index < dimensionSize; index++) {
typedArray[index] = readShort();
}//for//
break;
}//case//
case BYTE: {
byte[] typedArray = (byte[]) array;
read(typedArray);
break;
}//case//
case CHARACTER: {
char[] typedArray = (char[]) array;
for(int index = 0; index < dimensionSize; index++) {
typedArray[index] = readChar();
}//for//
break;
}//case//
case BOOLEAN: {
boolean[] typedArray = (boolean[]) array;
for(int index = 0; index < dimensionSize; index++) {
typedArray[index] = readBoolean();
}//for//
break;
}//case//
case FLOAT: {
float[] typedArray = (float[]) array;
for(int index = 0; index < dimensionSize; index++) {
typedArray[index] = readFloat();
}//for//
break;
}//case//
case DOUBLE: {
double[] typedArray = (double[]) array;
for(int index = 0; index < dimensionSize; index++) {
typedArray[index] = readDouble();
}//for//
break;
}//case//
default: {
throw new IOException("Invalid arrayType found.");
}//default//
}//switch//
}//if//
else {
String nextTypeName;
Class nextType;
if(dimension + 2 == dimensionCount) {
if(typeNumber == OBJECT) {
nextTypeName = typeName.substring(2, typeName.length() - 1);
nextType = loadClass(nextTypeName);
}//if//
else {
switch(typeNumber) {
case BOOLEAN: {
nextType = Boolean.TYPE;
break;
}//case//
case BYTE: {
nextType = Byte.TYPE;
break;
}//case//
case SHORT: {
nextType = Short.TYPE;
break;
}//case//
case INTEGER: {
nextType = Integer.TYPE;
break;
}//case//
case FLOAT: {
nextType = Float.TYPE;
break;
}//case//
case LONG: {
nextType = Long.TYPE;
break;
}//case//
case DOUBLE: {
nextType = Double.TYPE;
break;
}//case//
case CHARACTER: {
nextType = Character.TYPE;
break;
}//case//
default: {
Debug.log("Error: Unidentified primitive type.");
nextType = null;
break;
}//default//
}//switch//
nextTypeName = nextType.getName();
}//else//
}//if//
else {
nextTypeName = typeName.substring(1);
nextType = loadClass(nextTypeName);
}//else//
//Read the next dimension of the array.//
for(int index = 0; index < dimensionSize; index++) {
int nextDimensionSize = readInt();
//If the dimension is not null (as indicated by -1) then create it and read it.//
if(nextDimensionSize != -1) {
Object nextArray = Array.newInstance(nextType, nextDimensionSize);
Array.set(array, index, nextArray);
readArray(nextArray, nextTypeName, typeNumber, dimension + 1, dimensionCount, nextDimensionSize);
}//if//
else {
Array.set(array, index, null);
}//else//
}//for//
}//else//
}//readArray()//
/**
* Reads an object from the stream.
* @return The object read from the stream.
*/
public Object readObject() throws ClassNotFoundException, IOException {
return readObject(false);
}//readObject()//
/**
* Reads an object from the stream.
* @param loopDetect
* @return The object read from the stream.
*/
protected Object readObject(boolean loopDetect) throws ClassNotFoundException, IOException {
int objectType = readByte();
Object result = null;
boolean alreadyAddedToDeserializedValues = false; //Arrays and Object which may have internal recusive references must add to the list as soon as the object/array has been allocated.//
switch(objectType) {
case ARRAY: {
result = readArray();
alreadyAddedToDeserializedValues = true;
break;
}//case//
case NULL: {
break;
}//case//
case RECURSIVE_OBJECT: {
int number = readInt();
return deserializedValues.get(number);
}//case//
case CUSTOM_OBJECT: {
if(loopDetect) {
throw new IOException("Invalid stream detected due to unexpected looping.");
}//if//
try {
Class type;
int deserializedValueIndex = deserializedValues.getSize();
//Add a place holder to the deserialized object list.//
deserializedValues.add(null);
type = (Class) readObject();
result = deserialize(type);
deserializedValues.replace(deserializedValueIndex, result); //Replace the placeholder with the object.//
alreadyAddedToDeserializedValues = true;
}//try//
catch(IOException e) {
throw e;
}//catch//
catch(Throwable e) {
Debug.log(e);
throw new IOException("Stream corruption error or Stream setup error found while trying to read an Object.");
}//catch//
break;
}//case//
case OBJECT: {
if(loopDetect) {
throw new IOException("Invalid stream detected due to unexpected looping.");
}//if//
try {
Class type;
int deserializedValueIndex = deserializedValues.getSize();
//Add a place holder to the deserialized object list.//
deserializedValues.add(null);
type = (Class) readObject();
//Create a new instance using the default constructor.//
try {
result = type.newInstance();
}//try//
catch(Throwable e) {
//Ignore.//
}//catch//
//Try to create a new instance using native code.//
if(result == null) {
try {
result = allocateNewObject(type);
}//try//
catch(Throwable e) {
throw new IOException("Error allocating type: " + type.getName().toString() + " Cannot finish reading stream due to finding unknown object type: " + type.getName() + "\r\n\tCausing exception: " + e.toString());
}//catch//
}//if//
if(result != null) {
deserializedValues.replace(deserializedValueIndex, result); //Replace the placeholder with the object.//
alreadyAddedToDeserializedValues = true;
result = deserialize(result);
}//if//
}//try//
catch(IOException e) {
throw e;
}//catch//
catch(Throwable e) {
Debug.log(e);
throw new IOException("Stream corruption error or Stream setup error found while trying to read an Object.");
}//catch//
break;
}//case//
case BOOLEAN: {
result = new Boolean(readBoolean());
break;
}//case//
case BYTE: {
result = new Byte(readByte());
break;
}//case//
case CHARACTER: {
result = new Character(readChar());
break;
}//case//
case SHORT: {
result = new Short(readShort());
break;
}//case//
case INTEGER: {
result = new Integer(readInt());
break;
}//case//
case LONG: {
result = new Long(readLong());
break;
}//case//
case FLOAT: {
result = new Float(readFloat());
break;
}//case//
case DOUBLE: {
result = new Double(readDouble());
break;
}//case//
case STRING: {
/*
result = StringSupport.fromBytes(buffer, position, -1);
pos += StringSupport.getStringLength((String) result) + 4;
*/
result = readUTF16();
break;
}//case//
case UTF8: {
/*
result = StringSupport.fromUtfBytes(buffer, position, -1);
pos += StringSupport.getUtfStringLength((String) result) + 4;
*/
result = readUTF8();
break;
}//case//
case CLASS: {
int deserializedValueIndex = deserializedValues.getSize();
//Add a place holder to the deserialized object list.//
deserializedValues.add(null);
//Read the type.//
result = readType();
//Replace the placeholder.//
deserializedValues.replace(deserializedValueIndex, result);
//Set the flag so we don't add the deserialized value twice.//
alreadyAddedToDeserializedValues = true;
break;
}//case//
case SHARED_BOOLEAN: {
result = (readBoolean() == true ? Boolean.TRUE : Boolean.FALSE);
break;
}//case//
default: {
if(isDecrypting()) {
throw new IOSecurityException("Stream corruption detected. Most likely cause was a failure to properly decrypt the stream.");
}//if//
else {
throw new IOException("Stream corruption detected. Unknown object type.");
}//else//
}//default//
}//switch//
if((result != null) && (!alreadyAddedToDeserializedValues)) {
//Cache the return value in case the object is referenced again in this stream.//
deserializedValues.add(result);
}//if//
return result;
}//readObject()//
/**
* Reads a string from the stream as an object. This is wholly different from using the readUTF() readUTF8() and readUTF16() methods.
* @return The value read from the stream.
*/
public String readString() throws IOException {
try {
return (String) readObject(false);
}//try//
catch(ClassCastException e) {
throw new IOException("Stream corruption: Unable to cast Object to String in readString().");
}//catch//
catch(ClassNotFoundException e) {
throw new IOException("Stream corruption: Unable to find a class while reading a string: " + e.getMessage());
}//catch//
}//readString()//
/**
* Reads a class name or ID off of the stream.
* If optimized class streaming is enabled on the remote process, then the classList will be used to cache the mapping of class objects to ID's.
* @return The class object read from the stream.
*/
protected Class readType() throws IOException, ClassNotFoundException {
Object object = readObject();
Integer index = (Integer) readObject();
Class result = null;
if(object != null) {
try {
if(object instanceof String) {
result = loadClass((String) object);
}//if//
else {
switch(((Byte) object).intValue()) {
case BOOLEAN: {
result = Boolean.TYPE;
break;
}//case//
case BYTE: {
result = Byte.TYPE;
break;
}//case//
case SHORT: {
result = Short.TYPE;
break;
}//case//
case INTEGER: {
result = Integer.TYPE;
break;
}//case//
case FLOAT: {
result = Float.TYPE;
break;
}//case//
case LONG: {
result = Long.TYPE;
break;
}//case//
case DOUBLE: {
result = Double.TYPE;
break;
}//case//
case CHARACTER: {
result = Character.TYPE;
break;
}//case//
default: {
Debug.log("Error: Unidentified primitive type.");
break;
}//default//
}//switch//
}//else//
}//try//
catch(ClassNotFoundException e) {
if(streamManager != null) {
result = streamManager.replaceType((String) object);
if(result == null) {
throw e;
}//if//
}//if//
else {
throw e;
}//else//
}//catch//
//Save the class reference if the index is non null.//
if(index != null) {
synchronized(classList) {
//Only place the type in the classList when it will be the last item in the class list.//
while(classList.getSize() != index.intValue()) {
try {
classList.wait();
}//try//
catch(InterruptedException e) {
Thread.interrupted();
}//catch//
}//while//
classList.add(result);
classList.notifyAll();
}//synchronized//
}//if//
}//if//
else {
synchronized(classList) {
if(classList.getSize() <= index.intValue()) {
throw new IOException("Unable to find the class due to an invalid index being received.");
}//if//
result = (Class) classList.get(index.intValue());
}//synchronized//
}//else//
return result;
}//readType()//
/**
* Resets this stream so that it may be re-read.
*/
public void reset() throws java.io.IOException {
if(deserializedValues != null) {
deserializedValues.removeAll();
}//if//
}//reset()//
}//AbstractObjectInputStream//

View File

@@ -0,0 +1,697 @@
/*
* Copyright (c) 2005,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.io;
import java.io.IOException;
import java.io.Externalizable;
import java.lang.reflect.Array;
import com.common.orb.Orb;
import com.common.util.*;
import com.common.debug.*;
import com.common.util.optimized.*;
/**
* Defines a basic object output stream which can be subclassed as needed.
*/
public abstract class AbstractObjectOutputStream extends AbstractStandardOutputStream implements IObjectStream, java.io.ObjectOutput, IObjectOutputStream {
/** The mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming. */
private IHashMap classMap;
/** A collection of objects which have already been serialized, used to prevent recusive serialization. */
private ObjectIntHashMap serializedObjectMap;
/** The handler called when writing a class name to the stream. This allows the application to swap the name for another name. */
private IClassReplacementHandler classReplacementHandler = null;
/**
* Adds a custom serialization handler to the mapping for use by the object input and output streams.
* @param type The class the handler will be used to serialize and deserialize.
* @param handler The handler used to serialize and deserialize instances of the given class.
*/
public static final void addCustomSerializationHandler(Class type, ISerializationHandler handler) {
AbstractObjectInputStream.addCustomSerializationHandler(type, handler);
}//addCustomSerializationHandler()//
/**
* AbstractObjectOutputStream constructor.
* <p>WARNING: If a classMap is provided (optimized type streaming is used), then the user must be careful to reuse the same maps while streaming under the same context. In addition, the receiver of the stream must be careful to reuse thier maps so that the indexes match up properly.
* <p></b>IMPORTANT: The supplied map MUST use an IDENTITY comparator <code>Comparator.getIdentityComparator()</code> for key comparison.</b>
* @param classMap The mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming.
* @param classReplacementHandler The handler called when writing a class name to the stream. This allows the application to swap the name for another name.
*/
public AbstractObjectOutputStream(IHashMap classMap, IClassReplacementHandler classReplacementHandler) throws IOException {
this(classMap, classReplacementHandler, null);
}//AbstractObjectOutputStream()//
/**
* AbstractObjectOutputStream constructor.
* <p>WARNING: If a classMap is provided (optimized type streaming is used), then the user must be careful to reuse the same maps while streaming under the same context. In addition, the receiver of the stream must be careful to reuse thier maps so that the indexes match up properly.
* <p></b>IMPORTANT: The supplied map MUST use an IDENTITY comparator <code>Comparator.getIdentityComparator()</code> for key comparison.</b>
* @param classMap The optional mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming.
* @param classReplacementHandler The optional handler called when writing a class name to the stream. This allows the application to swap the name for another name.
* @param serializedObjectMap The optional map of indices by class name - used in conjunction with the classMap to serialize class names.
*/
protected AbstractObjectOutputStream(IHashMap classMap, IClassReplacementHandler classReplacementHandler, ObjectIntHashMap serializedObjectMap) throws IOException {
super();
this.classReplacementHandler = classReplacementHandler;
//Save the class mapping for later use. This will be used to substitute class identifiers for class names in the stream.//
this.classMap = classMap;
//Setup the mapping of serialized objects so that recursion can be detected.//
this.serializedObjectMap = serializedObjectMap != null ? serializedObjectMap : new ObjectIntHashMap(30, com.common.comparison.Comparator.getIdentityComparator());
}//AbstractObjectOutputStream()//
/**
* AbstractObjectOutputStream constructor.
* <p>WARNING: If a classMap is provided (optimized type streaming is used), then the user must be careful to reuse the same maps while streaming under the same context. In addition, the receiver of the stream must be careful to reuse thier maps so that the indexes match up properly.
* <p></b>IMPORTANT: The supplied map MUST use an IDENTITY comparator <code>Comparator.getIdentityComparator()</code> for key comparison.</b>
* @param classMap The mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming.
* @param classReplacementHandler The handler called when writing a class name to the stream. This allows the application to swap the name for another name.
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
*/
public AbstractObjectOutputStream(IHashMap classMap, IClassReplacementHandler classReplacementHandler, int defaultNumberStyle) throws IOException {
this(classMap, classReplacementHandler, null, defaultNumberStyle);
}//AbstractObjectOutputStream()//
/**
* AbstractObjectOutputStream constructor.
* <p>WARNING: If a classMap is provided (optimized type streaming is used), then the user must be careful to reuse the same maps while streaming under the same context. In addition, the receiver of the stream must be careful to reuse thier maps so that the indexes match up properly.
* <p></b>IMPORTANT: The supplied map MUST use an IDENTITY comparator <code>Comparator.getIdentityComparator()</code> for key comparison.</b>
* @param classMap The optional mapping class names to numbers allowing the stream to optimize the serialization of classes. The hash map keys should be compared using an identity comparator. This value may be <code>null</code> which will turn off optimized type streaming.
* @param classReplacementHandler The optional handler called when writing a class name to the stream. This allows the application to swap the name for another name.
* @param serializedObjectMap The optional map of indices by class name - used in conjunction with the classMap to serialize class names.
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
*/
protected AbstractObjectOutputStream(IHashMap classMap, IClassReplacementHandler classReplacementHandler, ObjectIntHashMap serializedObjectMap, int defaultNumberStyle) throws IOException {
super(defaultNumberStyle);
this.classReplacementHandler = classReplacementHandler;
//Save the class mapping for later use. This will be used to substitute class identifiers for class names in the stream.//
this.classMap = classMap;
//Setup the mapping of serialized objects so that recursion can be detected.//
this.serializedObjectMap = serializedObjectMap != null ? serializedObjectMap : new ObjectIntHashMap(30, com.common.comparison.Comparator.getIdentityComparator());
}//AbstractObjectOutputStream()//
/* (non-Javadoc)
* @see com.common.io.IObjectOutputStream#getSerializedObjectMap()
*/
public ObjectIntHashMap getSerializedObjectMap() {
return serializedObjectMap;
}//getSerializedObjectMap()//
/* (non-Javadoc)
* @see com.common.io.IObjectOutputStream#getClassMap()
*/
public IHashMap getClassMap() {
return classMap;
}//getClassMap()//
/* (non-Javadoc)
* @see com.common.io.IObjectOutputStream#getClassReplacementHandler()
*/
public IClassReplacementHandler getClassReplacementHandler() {
return classReplacementHandler;
}//getClassReplacementHandler()//
/**
* Closes this output stream and releases any system resources associated with this stream.
*/
public void close() throws IOException {
//Clear out the serialized object map to help GC.//
if(serializedObjectMap != null) {
serializedObjectMap.removeAll();
}//if//
}//close()//
/**
* Flushes any buffered bytes to their destination.
*/
public abstract void flush() throws IOException;
/**
* Resets the stream so it may be reused.
* It is the caller's reponsibility to ensure that other chained streams are also reset.
*/
protected void internalReset() {
if(serializedObjectMap != null) {
serializedObjectMap.removeAll();
}//if//
}//internalReset()//
/**
* Serializes the given object to this stream.
* <p>NOTE: The OBJECT identifier and the object's type have already been serialized to the stream.
* @param object The object to serialize.
*/
protected void serializeObject(Object object) throws IOException {
//Note: The proxy class can't implement IExternalizable, but the proxied class can. To avoid trying to make a remote call to the IExternalizable writeExternal method, we need to ensure this isn't a proxy.//
if(object instanceof IExternalizable/* && !Orb.isProxy(object)*/) {
//Use the serialize handler.//
write(OBJECT);
//Write the object's class.//
writeObject(object.getClass());
//Call object to write its' self out.//
((IExternalizable) object).writeExternal(this);
}//if//
else if(object instanceof Externalizable) {
//Use the serialize handler.//
write(OBJECT);
//Write the object's class.//
writeObject(object.getClass());
//Call object to write its' self out.//
((Externalizable) object).writeExternal(this);
}//else if//
else {
ISerializationHandler serializeHandler = (ISerializationHandler) ObjectStream.serializationHandlersMap.get(object.getClass());
//Use the serialize handler.//
write(CUSTOM_OBJECT);
//Write the object's class.//
writeObject(object.getClass());
if(serializeHandler != null) {
serializeHandler.serialize(object, this);
}//if//
else if(object instanceof Throwable) {
//Allow exceptions to be serialized, although the exception stack and message data will not be serialized because it cannot be reassembled on the other side.//
}//else if//
else {
throw new IOException(object.getClass().getName() + " does not support serialization.");
}//else//
}//else//
}//serialize()//
/**
* Will recusively write out the contents of the array. Will also optimize for primitive types.
* @param array The array to write to the stream.
*/
private void writeArray(Object array) throws IOException, ClassNotFoundException {
String className = array.getClass().getName();
int dimensionCount = 0;
char arrayTypeCharacter;
int typeNumber;
//Class arrayClass = null;
//Count the number of array dimensions.//
while(className.charAt(dimensionCount) == '[') {
dimensionCount++;
}//while//
//Identify the array type (Object, int, byte, float, etc...).//
arrayTypeCharacter = className.charAt(dimensionCount);
switch(arrayTypeCharacter) {
case 'L': {
typeNumber = OBJECT;
break;
}//case//
case 'B': {
typeNumber = BYTE;
break;
}//case//
case 'D': {
typeNumber = DOUBLE;
break;
}//case//
case 'F': {
typeNumber = FLOAT;
break;
}//case//
case 'I': {
typeNumber = INTEGER;
break;
}//case//
case 'J': {
typeNumber = LONG;
break;
}//case//
case 'S': {
typeNumber = SHORT;
break;
}//case//
case 'V': {
typeNumber = BOOLEAN;
break;
}//case//
case 'C': {
typeNumber = CHARACTER;
break;
}//case//
default: {
Debug.log("Error: Unable to determine the array type.");
typeNumber = OBJECT;
break;
}//default//
}//switch//
//Write the array header to the stream.//
write(ARRAY);
if(dimensionCount == 1) {
if(typeNumber == OBJECT) {
writeBoolean(false);
//Remove the preceeding '[L' and ending ';'.//
writeString(className.substring(2, className.length() - 1));
}//if//
else {
writeBoolean(true);
writeByte(typeNumber);
}//else//
}//if//
else {
writeBoolean(false);
//Remove the preceeding '['.//
writeString(className.substring(1));
}//else//
writeByte((byte) typeNumber);
writeInt(dimensionCount);
writeArray(array, typeNumber, dimensionCount, 0);
}//writeObject()//
/**
* A recusive method which will iterate over each item in the array and output it to the stream.
* The arrayType should be Stream.OBJECT or one of the primitives (ie Stream.INTEGER or Stream.BYTE..etc).
* <p>NOTE: The length of the dimensionSizeList may not be the same as the numberOfDimensions.
* @param array The array to write to the stream.
* @param arrayType The type of the array we are writing.
* @param numberOfDimensions The number of dimensions for this array.
* @param dimensionIndex The index of the dimension we are currently writing.
* @param dimensionSizeList ?
*/
private void writeArray(Object array, int typeNumber, int dimensionCount, int dimensionIndex) throws IOException {
int dimensionSize = array != null ? Array.getLength(array) : -1;
//Write the dimension size or -1 if the array is null.//
writeInt(dimensionSize);
//If the array is not null then write it out.//
if(array != null) {
if(dimensionCount == dimensionIndex + 1) {
switch(typeNumber) {
case OBJECT: {
Object[] objects = (Object[]) array;
for(int index = 0; index < dimensionSize; index++) {
writeObject(objects[index]);
}//for//
break;
}//case//
case INTEGER: {
int[] ints = (int[]) array;
for(int index = 0; index < dimensionSize; index++) {
writeInt(ints[index]);
}//for//
break;
}//case//
case LONG: {
long[] longs = (long[]) array;
for(int index = 0; index < dimensionSize; index++) {
writeLong(longs[index]);
}//for//
break;
}//case//
case SHORT: {
short[] shorts = (short[]) array;
for(int index = 0; index < dimensionSize; index++) {
writeShort(shorts[index]);
}//for//
break;
}//case//
case BYTE: {
write((byte[]) array);
break;
}//case//
case CHARACTER: {
char[] chars = (char[]) array;
for(int index = 0; index < dimensionSize; index++) {
writeChar(chars[index]);
}//for//
break;
}//case//
case BOOLEAN: {
boolean[] booleans = (boolean[]) array;
for(int index = 0; index < dimensionSize; index++) {
writeBoolean(booleans[index]);
}//for//
break;
}//case//
case FLOAT: {
float[] floats = (float[]) array;
for(int index = 0; index < dimensionSize; index++) {
writeFloat(floats[index]);
}//for//
break;
}//case//
case DOUBLE: {
double[] doubles = (double[]) array;
for(int index = 0; index < dimensionSize; index++) {
writeDouble(doubles[index]);
}//for//
break;
}//case//
default: {
throw new IOException("Invalid arrayType found while streaming the array.");
}//default//
}//switch//
}//if//
else {
for(int index = 0; index < dimensionSize; index++) {
writeArray(Array.get(array, index), typeNumber, dimensionCount, dimensionIndex + 1);
}//for//
}//else//
}//if//
}//writeArray()//
/**
* Writes a string in double byte format (two byte Unicode).
* @param string The string to write.
*/
public void writeDoubleByte(String string) throws IOException {
writeObject(string, STRING);
}//writeDoubleByte()//
/**
* Writes a Boolean object to the stream.
* @param object The boolean to write.
*/
public void writeObject(Boolean object) throws IOException {
writeObject(object, (object == Boolean.TRUE || object == Boolean.FALSE) ? SHARED_BOOLEAN : BOOLEAN);
}//writeObject()//
/**
* Writes a Byte object to the stream.
* @param object The byte to write.
*/
public void writeObject(Byte object) throws IOException {
writeObject(object, BYTE);
}//writeObject()//
/**
* Writes a Character object to the stream.
* @param object The character to write.
*/
public void writeObject(Character object) throws IOException {
writeObject(object, CHARACTER);
}//writeObject()//
/**
* Writes a Double object to the stream.
* @param object The double to write.
*/
public void writeObject(Double object) throws IOException {
writeObject(object, DOUBLE);
}//writeObject()//
/**
* Writes a Float object to the stream.
* @param object The float to write.
*/
public void writeObject(Float object) throws IOException {
writeObject(object, FLOAT);
}//writeObject()//
/**
* Writes an Integer object to the stream.
* @param object The integer to write.
*/
public void writeObject(Integer object) throws IOException {
writeObject(object, INTEGER);
}//writeObject()//
/**
* Writes a Long object to the stream.
* @param object The long to write.
*/
public void writeObject(Long object) throws IOException {
writeObject(object, LONG);
}//writeObject()//
/**
* Writes an object to the stream.
* @param object The object to write to this stream.
*/
public void writeObject(Object object) throws IOException {
writeObject(object, UNKNOWN_OBJECT);
}//writeObject()//
/**
* TODO: Update this documentation!<p>
* Writes any object to the stream. The object must either be one of the optimized types, or it must implement Externalizable, IExternalizable, or it must have registered special serialization handlers.
* @param object The object to serialize to this stream.
* @param objectType The type code for the object. This should be UNKNOWN_OBJECT if the type code is not yet known.
*/
protected void writeObject(Object object, byte objectType) throws IOException {
try {
int objectNumber;
if(object == null) {
//Write the null value to the stream.//
write(NULL);
}//if//
else if((objectNumber = serializedObjectMap.get(object)) != IObjectIntHashMap.NULL_VALUE) { //Check to see if this object has already been serialized.//
//Place the object number on the stream because the object has already been streamed.//
write(RECURSIVE_OBJECT);
writeInt(objectNumber);
}//if//
else {
//Add the object to the collection of already sent objects.//
objectNumber = serializedObjectMap.getSize();
serializedObjectMap.put(object, objectNumber);
//Serialize the object.//
if(object instanceof Class) {
writeByte(CLASS);
writeType((Class) object);
}//if//
else if(object.getClass().isArray()) {
writeArray(object);
}//else if//
else {
//Setup the type identifier so that some optimizations can occur.//
if(objectType == UNKNOWN_OBJECT) {
if(object instanceof java.lang.Number) {
if(object instanceof java.lang.Integer) {
objectType = INTEGER;
}//if//
else if(object instanceof java.lang.Long) {
objectType = LONG;
}//else if//
else if(object instanceof java.lang.Byte) {
objectType = BYTE;
}//else if//
else if(object instanceof java.lang.Short) {
objectType = SHORT;
}//else if//
else if(object instanceof java.lang.Float) {
objectType = FLOAT;
}//else if//
else if(object instanceof java.lang.Double) {
objectType = DOUBLE;
}//else if//
}//if//
else if(object instanceof java.lang.Character) {
objectType = CHARACTER;
}//else if//
else if(object instanceof java.lang.String) {
objectType = UTF8;
}//else if//
else if(object instanceof java.lang.Boolean) {
if(object == Boolean.TRUE || object == Boolean.FALSE) {
objectType = SHARED_BOOLEAN;
}//if//
else {
objectType = BOOLEAN;
}//else//
}//else if//
}//if//
//Write the object using either the optimized code, or the standard object serialization code.//
if(objectType != UNKNOWN_OBJECT) {
//Write the type code.//
write(objectType);
//Determine which optimized type it is.//
switch(objectType) {
case BOOLEAN: {
writeBoolean(((Boolean) object).booleanValue());
break;
}//case//
case BYTE: {
writeByte(((Byte) object).byteValue());
break;
}//case//
case CHARACTER: {
writeChar(((Character) object).charValue());
break;
}//case//
case SHORT: {
writeShort(((Short) object).shortValue());
break;
}//case//
case INTEGER: {
writeInt(((Integer) object).intValue());
break;
}//case//
case LONG: {
writeLong(((Long) object).longValue());
break;
}//case//
case FLOAT: {
writeFloat(((Float) object).floatValue());
break;
}//case//
case DOUBLE: {
writeDouble(((Double) object).doubleValue());
break;
}//case//
case STRING: {
/*
String str = ((String) outObject);
int length = str.length();
char[] chars = str.toCharArray();
writeInt(length);
for(int i = 0; i < length; i++) {
write((int) chars[i]);
}//for//
*/
/*
writeInt(((String) outObject).length());
StringSupport.writeString((String) outObject, this);
*/
/*
int numBytes;
//Calculate the number of bytes the string will write out.//
numBytes = StringSupport.getUnicode16Length((String) object) + 4;
//Write the string bytes.//
outputStream.ensureSpace(numBytes);
StringSupport.toBytes((String) object, outputStream.getBuffer(), outputStream.index);
outputStream.index += numBytes;
*/
writeUTF16((String) object);
break;
}//case//
case UTF8: {
/*
int numBytes;
//Calculate the number of bytes the string will write out.//
numBytes = StringSupport.getUtf8Length((String) object) + 4;
//Write the string bytes.//
outputStream.ensureSpace(numBytes);
StringSupport.toUtf8Bytes((String) object, outputStream.getBuffer(), outputStream.index);
outputStream.index += numBytes;
*/
writeUTF8((String) object);
break;
}//case//
case SHARED_BOOLEAN: {
writeBoolean(((Boolean) object).booleanValue());
break;
}//case//
default: {
throw new IOException("Unknown optimized type.");
}//default//
}//switch//
}//if//
else {
//Write the object's attributes.//
serializeObject(object);
}//else//
}//else//
}//else//
}//try//
catch(IOException e) {
throw e; //Rethrow//
}//catch//
catch(Throwable e) {
Debug.log(e);
throw new IOException("Caught a " + e.getClass().getName() + " exception while serializing an object of the class " + object.getClass());
}//catch//
}//writeObject()//
/**
* Writes a Short object to the stream.
* @param object The short to write.
*/
public void writeObject(Short object) throws IOException {
writeObject(object, SHORT);
}//writeObject()//
/**
* Writes a String object to the stream.
* @param object The string to write.
*/
public void writeObject(String object) throws IOException {
writeObject(object, UTF8);
}//writeObject()//
/**
* Writes a string using the default format (UTF8 or multi-byte Unicode).
* @param string The string to stream.
*/
public void writeString(String string) throws IOException {
writeObject(string, UTF8);
}//writeString()//
/**
* Manages the type collections so that the stream may be optimized such that a class name only has to be written to the stream once.
* @param type The class to write to the stream.
*/
protected void writeType(Class type) throws IOException {
//Check to see if we are using optimized type streaming.//
Object typeData = null;
Integer typeNumber = null;
if((classMap != null) && (classMap.containsKey(type))) {
typeNumber = (Integer) classMap.get(type);
}//if//
else {
if(classMap != null) {
//We can use the size of the class map as an index because values will never be removed from the map.//
classMap.put(type, (typeNumber = new Integer(classMap.getSize())));
}//if//
if(type.isPrimitive()) {
String name = type.getName();
switch(Character.toLowerCase(name.charAt(0))) {
case 'i': {
typeData = new Byte(INTEGER);
break;
}//case//
case 'b': {
if(type.equals(Byte.TYPE)) {
typeData = new Byte(BYTE);
}//if//
else {
typeData = new Byte(BOOLEAN);
}//else//
break;
}//case//
case 's': {
typeData = new Byte(SHORT);
break;
}//case//
case 'l': {
typeData = new Byte(LONG);
break;
}//case//
case 'f': {
typeData = new Byte(FLOAT);
break;
}//case//
case 'd': {
typeData = new Byte(DOUBLE);
break;
}//case//
case 'c': {
typeData = new Byte(CHARACTER);
break;
}//case//
default: {
Debug.log("Error: Unidentified primitive type name.");
break;
}//case//
}//switch//
}//if//
else {
//Write the type name this one time so that the remote process knows what the index will map to.//
typeData = type.getName();
if(classReplacementHandler != null) {
typeData = classReplacementHandler.getReplacementClassName((String) typeData);
}//if//
}//else//
}//else//
writeObject(typeData);
writeObject(typeNumber);
}//writeType()//
}//AbstractObjectOutputStream//

View File

@@ -0,0 +1,314 @@
/*
* Copyright (c) 1999,2008 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.io;
import java.io.InputStream;
import java.io.IOException;
import java.io.EOFException;
/**
* Provides basic functionality for a standard stream that can deserialize basic java data types.
*/
public abstract class AbstractStandardInputStream extends InputStream implements IStandardInputStream {
public static final int STYLE_LSF = StreamSupport.NUMBER_LSF;
public static final int STYLE_MSF = StreamSupport.NUMBER_MSF;
public static final int STYLE_VLSF = StreamSupport.NUMBER_VLSF;
public static final int STYLE_VMSF = StreamSupport.NUMBER_VMSF;
public static final int STYLE_DEFAULT = STYLE_MSF;
protected static final String READ_EOF_MESSAGE = "There are not enough bytes in the stream to read the requested value.";
private int defaultNumberStyle = STYLE_DEFAULT;
/**
* AbstractStandardInputStream constructor.
*/
protected AbstractStandardInputStream() {
super();
}//AbstractStandardInputStream()//
/**
* AbstractStandardInputStream constructor.
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
*/
protected AbstractStandardInputStream(int defaultNumberStyle) {
super();
this.defaultNumberStyle = defaultNumberStyle;
}//AbstractStandardInputStream()//
/**
* Gets the number style used by default when serializing numbers.
* @return The number style identifier used by default.
*/
public int getDefaultNumberStyle() {
return defaultNumberStyle;
}//getDefaultNumberStyle()//
/**
* Gets the number of available bytes in this input stream.
* @return The count of bytes that may be immediatly read from the stream.
*/
public abstract int available() throws IOException;
/* (non-Javadoc)
* @see com.common.io.IInputStream#canDecrypt()
*/
public boolean canDecrypt() {
return false;
}//canDecrypt()//
/* (non-Javadoc)
* @see java.io.InputStream#close()
*/
public abstract void close() throws IOException;
/* (non-Javadoc)
* @see com.common.io.IInputStream#decrypt(boolean)
*/
public void decrypt(boolean decrypt) throws IOException {
throw new IOException(ERROR_DECRYPTION_NOT_SUPPORTED);
}//decrypt()//
/* (non-Javadoc)
* @see com.common.io.IInputStream#isDecrypting()
*/
public boolean isDecrypting() {
return false;
}//isDecrypting()//
/**
* Marks the stream so that the reader can reset to the current position.
* @param readLimit The number of bytes that may be read before the mark becomes invalid.
*/
public abstract void mark(int readLimit);
/**
* Determines whether the stream supports using the mark method.
* @return Whether the mark method is supported.
*/
public abstract boolean markSupported();
/**
* Reads an unsigned byte from the stream.
* @return The unsigned byte read from the stream.
*/
public abstract int read() throws IOException;
/**
* Reads bytes from the stream until the buffer is full or there are no more bytes in the stream.
* @param buffer The buffer where the read bytes will be placed.
* @return The number of bytes read into the buffer.
*/
public abstract int read(byte[] buffer) throws IOException;
/**
* Reads bytes from the stream until the buffer is full or there are no more bytes in the stream.
* @param buffer The buffer where the read bytes will be placed.
* @param offset The offset where the first read byte should be placed in the buffer.
* @param length The number of bytes that should be read into the buffer.
* @return The number of bytes read into the buffer.
*/
public abstract int read(byte[] buffer, int offset, int length) throws IOException;
/**
* @see IInputStream.read(java.io.OutputStream, int)
*/
public abstract int read(java.io.OutputStream out, int length) throws IOException;
/**
* Reads a boolean from the stream.
* @return The value read from the stream.
*/
public boolean readBoolean() throws IOException {
int value = read();
if(value == -1) {
throw new EOFException(READ_EOF_MESSAGE);
}//if//
return value > 0;
}//readBoolean()//
/**
* Reads a byte from the stream.
* @return The value read from the stream.
*/
public byte readByte() throws IOException {
return (byte) read();
}//readByte()//
/**
* Reads a (2 byte) character from the stream.
* @return The value read from the stream.
*/
public char readChar() throws IOException {
return StreamSupport.readCharacter(this);
}//readChar()//
/**
* Reads a (8 byte) double from the stream.
* @return The value read from the stream.
*/
public double readDouble() throws IOException {
return StreamSupport.readDouble(this);
}//readDouble()//
/**
* Reads a fixed length string from file removes the unnecessary padding.
* @param length The fixed number of bytes in the string.
* @return The read string minus all space at the beginning or end of the string.
* @exception IOException If an I/O error occurs. In particular, an <code>IOException</code> may be thrown if the input stream has been closed.
*/
public String readFixedLengthString(int length) throws java.io.IOException {
byte[] bytes = new byte[length];
if(read(bytes) != length) {
throw new IOException("Unable to finish reading the fixed length string.");
}//if//
while((length > 0) && (bytes[length - 1] == 32)) {
length--;
}//while//
return new String(bytes, 0, length, STRING_FORMAT_UTF8);
}//writeFixedLengthString()//
/**
* Reads a (4 byte) float from the stream.
* @return The value read from the stream.
*/
public float readFloat() throws IOException {
return StreamSupport.readFloat(this);
}//readFloat()//
/**
* Don't know why this method exists?
* @param bytes
*/
public void readFully(byte[] bytes) throws IOException {
read(bytes);
}//readFully()//
/**
* Don't know why this method exists?
* @param bytes
* @param offset
* @param length
*/
public void readFully(byte[] bytes, int offset, int length) throws IOException {
read(bytes, offset, length);
}//readFully()//
/**
* Reads a (4 byte) int from the stream.
* @return The value read from the stream.
*/
public int readInt() throws IOException {
return StreamSupport.readInt(this, defaultNumberStyle);
}//readInt()//
/**
* Reads a (4 byte) int from the stream.
* @return The value read from the stream.
*/
public int readInt(int style) throws IOException {
return StreamSupport.readInt(this, style);
}//readInt()//
/**
* Reads a (8 byte) long from the stream.
* @return The value read from the stream.
*/
public long readLong() throws IOException {
return StreamSupport.readLong(this, defaultNumberStyle);
}//readLong()//
/**
* Reads a (8 byte) long from the stream.
* @return The value read from the stream.
*/
public long readLong(int style) throws IOException {
return StreamSupport.readLong(this, style);
}//readLong()//
/**
* Reads a string value from this stream.
* <p>WARNING: This method is for backward compatibility only! It will not read a single line of a string, but will rather read the entire string prefixed by the string length.
* @return The string value read.
*/
public String readLine() throws IOException {
return readUTF();
}//readLine()//
/**
* Reads a (2 byte) short from the stream.
* @return The value read from the stream.
*/
public short readShort() throws IOException {
return StreamSupport.readShort(this);
}//readShort()//
public int readUnsignedByte() throws IOException {
int retVal = read();
return (int) (retVal < 0 ? retVal + 256 : retVal);
}//readUnsignedByte()//
public int readUnsignedShort() throws IOException {
short retVal = readShort();
return (int) (retVal < 0 ? retVal + 65536 : retVal);
}//readUnsignedShort()//
/**
* Reads a UTF8 string from the stream.
* @see #readUTF8()
* @return The string read from the stream.
*/
public String readUTF() throws IOException {
return readUTF8();
}//readUTF()//
/**
* Reads a UTF16 string from the stream.
* A UTF16 string is a fixed character size string using 2 bytes for each character.
* <p>WARNING: The user must call writeUTF16(String) in the output stream for this method to work properly. The user cannot mix and match string serialization methods.
* @return The string read from the stream.
*/
public String readUTF16() throws IOException {
int size = readInt();
String result = null;
if(size != -1) {
byte[] bytes = new byte[size];
read(bytes);
result = new String(bytes, STRING_FORMAT_UNICODE);
}//if//
return result;
}//readUTF()//
/**
* Reads a UTF8 string from the stream.
* A UTF8 string is a variable character size string using 1..N bytes for each character. All ASCII characters will use 1 byte, but most european characters will use 2 and some oriental characters will use 3 bytes.
* <p>WARNING: The user must call writeUTF8(String) in the output stream for this method to work properly. The user cannot mix and match string serialization methods.
* @return The string read from the stream.
*/
public String readUTF8() throws IOException {
int size = readInt();
String result = null;
if(size != -1) {
byte[] bytes = null;
//TODO: Remove this - seems like old code - it flagged my big-data test that used a string with 100k characters in it.
//if(size > 16767) {
// throw new IOException("Corruption detected while reading a UTF8 string from a stream. Please check to make sure that you are reading in the same order you wrote to the stream.");
//}//if//
bytes = new byte[size];
read(bytes);
result = new String(bytes, STRING_FORMAT_UTF8);
}//if//
return result;
}//readUTF8()//
/**
* Resets the stream by telling the encapsulated stream to reset.
*/
public abstract void reset() throws IOException;
/**
* Skips the next <code>count</code> bytes on the stream.
* @param count The number of bytes to skip.
* @return The number of bytes that were skipped.
*/
public abstract long skip(long count) throws IOException;
/**
* Skips the specified number of bytes so that they are never read.
* @param byteCount The number of bytes to skip.
* @return The number of bytes skipped.
*/
public int skipBytes(int byteCount) throws IOException {
return (int) skip((long) byteCount);
}//skipBytes()//
/**
* Skips the specified number of bytes so that they are never read.
* @param byteCount The number of bytes to skip.
* @return The number of bytes skipped.
*/
public long skipBytes(long byteCount) throws IOException {
return skip(byteCount);
}//skipBytes()//
}//AbstractStandardInputStream//

View File

@@ -0,0 +1,275 @@
/*
* Copyright (c) 1999,2007 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.io;
import java.io.OutputStream;
import java.io.IOException;
/**
* Provides basic functionality for a standard stream that can serialize basic java data types.
*/
public abstract class AbstractStandardOutputStream extends OutputStream implements IStandardOutputStream {
public static final int STYLE_LSF = StreamSupport.NUMBER_LSF;
public static final int STYLE_MSF = StreamSupport.NUMBER_MSF;
public static final int STYLE_VLSF = StreamSupport.NUMBER_VLSF;
public static final int STYLE_VMSF = StreamSupport.NUMBER_VMSF;
public static final int STYLE_DEFAULT = STYLE_MSF;
private boolean containsEncryptedSegments = false;
private int defaultNumberStyle = STYLE_DEFAULT;
/**
* AbstractStandardOutputStream constructor.
*/
protected AbstractStandardOutputStream() {
super();
}//AbstractStandardOutputStream()//
/**
* AbstractStandardOutputStream constructor.
* @param defaultNumberStyle One of the STYLE_xx identifiers. This defaults to most significant byte first.
*/
protected AbstractStandardOutputStream(int defaultNumberStyle) {
super();
this.defaultNumberStyle = defaultNumberStyle;
}//AbstractStandardOutputStream()//
/**
* Gets the number style used by default when serializing numbers.
* @return The number style identifier used by default.
*/
public int getDefaultNumberStyle() {
return defaultNumberStyle;
}//getDefaultNumberStyle()//
/**
* @see IObjectOutputStream.canEncrypt()
*/
public boolean canEncrypt() {
return false;
}//canEncrypt()//
/**
* Closes this output stream and the encapsulated output stream.
*/
public abstract void close() throws IOException;
/**
* Determines whether encryption was used for some or all of the stream.
* @return Whether the stream utilized encryption.
*/
public boolean containsEncryptedSegments() {
return containsEncryptedSegments;
}//containsEncryptedSegments()//
/**
* Determines whether encryption was used for some or all of the stream.
* @param containsEncryptedSegments Whether the stream utilized encryption.
*/
protected void containsEncryptedSegments(boolean containsEncryptedSegments) {
this.containsEncryptedSegments = containsEncryptedSegments;
}//containsEncryptedSegments()//
/**
* @see IObjectOutputStream.encrypt(boolean)
*/
public void encrypt(boolean encrypt) throws IOException {
throw new IOException(ERROR_ENCRYPTION_NOT_SUPPORTED);
}//encrypt()//
/**
* Flushes this output stream and the encapsulated output stream.
*/
public abstract void flush() throws IOException;
/**
* @see IObjectOutputStream.isEncrypting()
*/
public boolean isEncrypting() {
return false;
}//isEncrypting()//
/**
* Writes the bytes to the stream.
* @param bytes The bytes to write to the stream.
*/
public abstract void write(byte[] bytes) throws IOException;
/**
* Writes the bytes to the stream.
* @param bytes The bytes to write to the stream.
* @param offset The offset of the first byte to write.
* @param length the number of bytes to write.
*/
public abstract void write(byte[] bytes, int offset, int length) throws IOException;
/**
* Writes the unsigned byte to the stream.
* @param b The unsigned byte to write to the stream.
*/
public abstract void write(int b) throws IOException;
/**
* Writes a boolean to the stream.
* @param value The value to write to the stream.
*/
public void writeBoolean(boolean value) throws IOException {
write(value ? 1 : 0);
}//writeBoolean()//
/**
* Writes a byte to the stream.
* @param value The value to write to the stream.
*/
public void writeByte(byte value) throws IOException {
write(value);
}//writeByte()//
/**
* Writes an unsigned byte to the stream.
* @param value The unsigned value to write to the stream.
*/
public void writeByte(int value) throws IOException {
write(value);
}//writeByte()//
/**
* Writes a string in the default UTF8 (multi-byte Unicode) format.
* @param string The string to stream.
* @deprecated Use writeUTF16(String).
*/
public void writeBytes(String string) throws IOException {
writeUTF16(string);
}//writeBytes()//
/**
* Writes a character to the stream.
* @param value The value to write to the stream.
*/
public void writeChar(char value) throws IOException {
StreamSupport.writeCharacter(value, this);
}//writeChar()//
/**
* Writes a character to the stream.
* @param value The value to write to the stream.
*/
public void writeChar(int value) throws IOException {
StreamSupport.writeCharacter((char) value, this);
}//writeChar()//
/**
* Writes a string in the default UTF8 (multi-byte Unicode) format.
* @param string The string to stream.
* @deprecated Use writeUTF8(String).
*/
public void writeChars(String string) throws IOException {
writeUTF8(string);
}//writeChars()//
/**
* Writes a double to the stream.
* @param value The value to write to the stream.
*/
public void writeDouble(double value) throws IOException {
StreamSupport.writeDouble(value, this);
}//writeDouble()//
/**
* Writes a fixed length string to file and pads it with spaces where necessary.
* @param string The string to write. This string must be under the byte size limit and an IOException will result from an improperly sized string.
* @param length The fixed number of bytes in the string.
* @exception IOException If an I/O error occurs. In particular, an <code>IOException</code> may be thrown if the output stream has been closed.
*/
public void writeFixedLengthString(String string, int length) throws java.io.IOException {
byte[] bytes = string.getBytes(STRING_FORMAT_UTF8);
int underflow;
if(bytes.length > length) {
throw new IOException("Fixed string length exceeds expected length.");
}//if//
write(bytes);
underflow = length - bytes.length;
while(underflow-- > 0) {
write(32);
}//while//
}//writeFixedLengthString()//
/**
* Writes a float to the stream.
* @param value The value to write to the stream.
*/
public void writeFloat(float value) throws IOException {
StreamSupport.writeFloat(value, this);
}//writeFloat()//
/**
* Writes a int to the stream.
* @param value The value to write to the stream.
*/
public void writeInt(int value) throws IOException {
StreamSupport.writeInt(value, this, defaultNumberStyle);
}//writeInt()//
/**
* Writes a int to the stream.
* @param value The value to write to the stream.
* @param style One of the style identifiers defined by this output stream.
*/
public void writeInt(int value, int style) throws IOException {
StreamSupport.writeInt(value, this, style);
}//writeInt()//
/**
* Writes a long to the stream.
* @param value The value to write to the stream.
*/
public void writeLong(long value) throws IOException {
StreamSupport.writeLong(value, this, defaultNumberStyle);
}//writeLong()//
/**
* Writes a long to the stream.
* @param value The value to write to the stream.
* @param style One of the style identifiers defined by this output stream.
*/
public void writeLong(long value, int style) throws IOException {
StreamSupport.writeLong(value, this, style);
}//writeLong()//
/**
* Writes an unsigned short to the stream.
* @param value The unsigned value to write to the stream.
*/
public void writeShort(int value) throws IOException {
StreamSupport.writeShort((short) (value & 0xFFFF), this);
}//writeShort()//
/**
* Writes a short to the stream.
* @param value The value to write to the stream.
*/
public void writeShort(short value) throws IOException {
StreamSupport.writeShort(value, this);
}//writeShort()//
/**
* Writes a UTF8 string to the stream.
* @see #writeUTF8()
* @param string The string to write to the stream.
*/
public void writeUTF(String string) throws IOException {
writeUTF8(string);
}//writeUTF()//
/**
* Writes a UTF16 string to the stream.
* A UTF16 string is a fixed character size string using 2 bytes for each character.
* <p>WARNING: The user must call readUTF16(String) in the input stream for this method to work properly. The user cannot mix and match string serialization methods.
* @param string The string to write to the stream.
*/
public void writeUTF16(String string) throws IOException {
if(string != null) {
byte[] bytes = string.getBytes(STRING_FORMAT_UNICODE);
writeInt(bytes.length);
write(bytes);
}//if//
else {
writeInt(-1);
}//else//
}//writeUTF16()//
/**
* Writes a UTF8 string to the stream.
* A UTF8 string is a variable character size string using 1..N bytes for each character. All ASCII characters will use 1 byte, but most european characters will use 2 and some oriental characters will use 3 bytes.
* <p>WARNING: The user must call readUTF8(String) in the input stream for this method to work properly. The user cannot mix and match string serialization methods.
* @param string The string to write to the stream.
*/
public void writeUTF8(String string) throws IOException {
if(string != null) {
byte[] bytes = string.getBytes(STRING_FORMAT_UTF8);
writeInt(bytes.length);
write(bytes);
}//if//
else {
writeInt(-1);
}//else//
}//writeUTF8()//
}//StandardOutputStream//

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.io;
import java.io.InputStream;
import com.common.security.*;
/*
* This class allows an asymmetricly encrypted stream to be plugged into an input stream so that read bytes are decrypted using the private key.
*/
public class AsymmetricInputStream extends CryptoInputStream implements IInputStream {
private IAsymmetricAlgorithm algorithm = null;
/**
* AsymmetricInputStream constructor.
*/
public AsymmetricInputStream(InputStream stream, IAsymmetricAlgorithm algorithm) {
super(stream, algorithm);
this.algorithm = algorithm;
this.encryptedBuffer = new byte[algorithm.getOptimalDecryptionBlockSize()];
this.decryptedBuffer = new byte[algorithm.getOptimalEncryptionBlockSize()];
}//AsymmetricInputStream()//
/* (non-Javadoc)
* @see com.common.io.CryptoOutputStream#decrypt(byte[], int, int, byte[], int)
*/
protected int decrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset) {
return algorithm.decrypt(data, dataOffset, dataLength, output, outputOffset);
}//decrypt()//
}//AsymmetricInputStream//

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 1999,2005 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.io;
import java.io.OutputStream;
import com.common.security.*;
/*
* This class allows an asymmetric stream to be plugged into an output stream so that written bytes are encrypted using the public key.
*/
public class AsymmetricOutputStream extends CryptoOutputStream implements IOutputStream {
private IAsymmetricAlgorithm algorithm = null;
/**
* AsymmetricOutputStream constructor.
*/
public AsymmetricOutputStream(OutputStream stream, IAsymmetricAlgorithm algorithm) {
super(stream, algorithm);
this.algorithm = algorithm;
this.encryptedBuffer = new byte[algorithm.getOptimalDecryptionBlockSize()];
this.decryptedBuffer = new byte[algorithm.getOptimalEncryptionBlockSize()];
}//AsymmetricOutputStream()//
/* (non-Javadoc)
* @see com.common.io.CryptoOutputStream#encrypt(byte[], int, int, byte[], int)
*/
protected int encrypt(byte[] data, int dataOffset, int dataLength, byte[] output, int outputOffset) {
return algorithm.encrypt(data, dataOffset, dataLength, output, outputOffset);
}//encrypt()//
}//AsymmetricOutputStream//

View File

@@ -0,0 +1,272 @@
/*
* Copyright (c) 1999,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.io;
import java.io.InputStream;
import java.io.IOException;
/**
* The buffered input stream is used for two reasons. The first reason is to allow the user to peek
* at future values in the stream. The second reason is to all more efficient read operations when
* dealing with streams where reading one byte at a time is inefficient.
* <p>TODO: Should add a close method which will close the underlying stream.</p>
*/
public class BufferedInputStream extends InputStream {
public static final int DEFAULT_BLOCK_BUFFER_SIZE = 10;
private InputStream inputStream = null; //The input stream that source will be read from.//
private byte[] buffer = null; //The buffer that will hold unread values.//
private int bufferedSize = 0; //The number of bytes currently in the buffer.//
private int firstByteOffset = 0; //The offset of the first byte in the buffer. This is necessary because we are using a rotating scheme where the first byte in the buffer is not always at index zero and the last byte may be at a smaller index than the first byte.//
/**
* BufferedInputStream constructor.
* @param inputStream The stream containing the source data.
*/
public BufferedInputStream(InputStream inputStream) {
this(inputStream, DEFAULT_BLOCK_BUFFER_SIZE);
}//BufferedInputStream()//
/**
* BufferedInputStream constructor.
* @param inputStream The stream containing the source data.
* @param bufferSize The number of bytes to buffer at one time. This value must be greater than zero and it will determine how far the user can peek in the stream.
*/
public BufferedInputStream(InputStream inputStream, int bufferSize) {
super();
if(bufferSize < 1) {
throw new RuntimeException("The BufferedInputStream requires a buffer size > 0.");
}//if//
this.inputStream = inputStream;
this.buffer = new byte[bufferSize];
}//BufferedInputStream()//
/**
* Determines how many more bytes of source data are available to be read.
* @return The number of source bytes that are readable.
*/
public int available() throws IOException {
return inputStream.available();
}//available()//
/**
* Fills the buffer with source bytes until either the buffer is full or there are no more source bytes.
*/
protected void fillBuffer() throws IOException {
if(bufferedSize == 0) {
firstByteOffset = 0;
bufferedSize = inputStream.read(buffer);
}//if//
else {
int offset = firstByteOffset + bufferedSize;
int length;
if(offset < buffer.length) {
bufferedSize += inputStream.read(buffer, offset, buffer.length - offset);
}//if//
//Calculate the number of bytes remaining to be read (so that the buffer is full).//
length = buffer.length - bufferedSize;
if(length > 0) {
bufferedSize += inputStream.read(buffer, 0, length);
}//if//
}//else//
}//fillBuffer()//
/**
* Gets the encapsulated input stream.
* @return Gets the input stream that this object wrappers.
*/
public InputStream getInputStream() {
return inputStream;
}//getInputStream()//
/**
* Peeks at a single unsigned byte value in the stream of future values.
* This method does NOT consume the value and the value will eventually be returned durring a read operation.
* @param offset The offset in the stream for the byte that should be returned. A value of zero will return the byte that will next be returned by the read() operation. This value must be greater than or equal to zero and less than the buffer size used when creating this stream.
* @return The byte at the given offset from the current position in the stream.
*/
public int peek(int offset) throws IOException {
int retVal;
if((offset > buffer.length) || (offset < 0)) {
throw new RuntimeException("Unable to peek at a byte that cannot be buffered. Please make sure you specify a large enough buffer size when constructing the BufferedInputStream object. You also may not peek at bytes already read from the stream.");
}//if//
else {
int bufferOffset = offset + firstByteOffset;
if(bufferedSize < offset + 1) {
fillBuffer();
if(bufferedSize < offset + 1) {
throw new RuntimeException("Unable to peek at a byte that does not exist in the stream. Please make sure you verify there are enough bytes in the stream by calling inputStream.available().");
}//if//
}//if//
if(bufferOffset > buffer.length) {
bufferOffset -= buffer.length;
}//if//
retVal = buffer[bufferOffset];
}//else//
return retVal;
}//peek()//
/**
* Peeks at a group of bytes in the stream's future.
* This method does NOT consume the values and the values will eventually be returned durring a read operation.
* @param streamOffset The offset in the stream for the first byte that should be returned. A value of zero will return the byte that will next be returned by the read() operation. This value must be greater than or equal to zero and less than the buffer size (used when creating this stream) minus the requested length.
* @param outputBuffer The buffer that should be filled with the output bytes.
* @param offset The offset in the output buffer where the first output byte will be placed.
* @param length The number of output bytes requested for this operation. All requested bytes will be supplied or an exception will be raised because the stream either does not have enough bytes to fulfill the request, or because the buffer being used is smaller than the length + stream offset.
* @return The byte at the given offset from the current position in the stream.
*/
public void peek(int streamOffset, byte[] outputBuffer, int offset, int length) throws IOException {
if((streamOffset + length > buffer.length) || (streamOffset < 0)) {
throw new RuntimeException("Unable to peek at a byte that cannot be buffered. Please make sure you specify a large enough buffer size when constructing the BufferedInputStream object. You also may not peek at bytes already read from the stream.");
}//if//
else {
int bufferOffset = streamOffset + firstByteOffset;
if(bufferedSize < streamOffset + length) {
fillBuffer();
if(bufferedSize < offset + length) {
throw new RuntimeException("Unable to peek at a byte that does not exist in the stream. Please make sure you verify there are enough bytes in the stream by calling inputStream.available().");
}//if//
}//if//
while(length < 0) {
//Adjust the starting point within the buffer.//
if(bufferOffset > buffer.length) {
bufferOffset -= buffer.length;
}//if//
outputBuffer[offset++] = buffer[bufferOffset++];
}//while//
}//else//
}//peek()//
/**
* Reads a single unsigned byte value from the stream.
* @return The next unsigned byte value in the stream.
*/
public int read() throws IOException {
int retVal;
if(bufferedSize == 0) {
fillBuffer();
if(bufferedSize > 0) {
retVal = buffer[firstByteOffset++];
bufferedSize--;
if(firstByteOffset == buffer.length) {
firstByteOffset = 0;
}//if//
}//if//
else {
throw new IOException("No more source data.");
}//else//
}//if//
else {
retVal = buffer[firstByteOffset++];
bufferedSize--;
if(firstByteOffset == buffer.length) {
firstByteOffset = 0;
}//if//
}//else//
return retVal;
}//read()//
/**
* Reads a bytes off the source stream and places them in the bytes buffer.
* @param bytes The buffer that will contain the source bytes read from the stream.
* @return The number of bytes read.
*/
public int read(byte[] bytes) throws IOException {
return read(bytes, 0, bytes.length);
}//read()//
/**
* Reads a bytes off the source stream and places them in the bytes buffer.
* @param bytes The buffer that will contain the source bytes read from the stream.
* @param offset The offset in the bytes buffer where the first source byte will be placed.
* @param length The number of source bytes that will be placed in the bytes buffer. Note that <code>bytes.length - offset >= length</code> - this is not checked and non-compliance will result in a ArrayIndexOutOfBounds exception.
* @return The number of bytes read.
*/
public int read(byte[] bytes, int offset, int length) throws IOException {
int retVal = 0;
//If we have buffered bytes then first add them.//
if(bufferedSize > 0) {
int endLength = length > bufferedSize ? bufferedSize : length;
int beginLength = 0;
//Save the number of bytes being copied.//
retVal = endLength;
//Adjust the end length if it will over run the buffer size.//
if(endLength + firstByteOffset > buffer.length) {
beginLength = endLength - (buffer.length - firstByteOffset);
endLength -= beginLength;
}//if//
//Copy the bytes at the end of the buffer.//
System.arraycopy(buffer, firstByteOffset, bytes, offset, endLength);
//Copy the bytes at the beginning of the buffer.//
if(beginLength > 0) {
System.arraycopy(buffer, 0, bytes, offset + endLength, beginLength);
}//if//
//Adjust the buffer indexes.//
bufferedSize = length > bufferedSize ? 0 : bufferedSize - length;
firstByteOffset = bufferedSize == 0 ? 0 : firstByteOffset + length;
if(firstByteOffset >= buffer.length) {
firstByteOffset = firstByteOffset - buffer.length;
}//if//
}//if//
//If we did not have enough buffered bytes to fill the array then we will need to send the array to the source stream.//
if(retVal < length) {
retVal += inputStream.read(bytes, offset + retVal, length - retVal);
}//if//
return retVal;
}//read()//
/**
* Skips <code>count</code> bytes in the stream.
* @param count The number to skip.
* @return The number of bytes skipped.
*/
public long skip(long count) throws IOException {
int skipCount = 0;
//Skip the buffered values as necessary.//
if(bufferedSize != 0) {
//If the count is greater than the buffer size then clear the buffer, otherwise clear part of the buffer.//
if(count > bufferedSize) {
skipCount = bufferedSize;
bufferedSize = 0;
firstByteOffset = 0;
}//if//
else {
skipCount = (int) count;
bufferedSize -= count;
firstByteOffset += count;
//Adjust the first byte offset so it is in the correct range.//
if(firstByteOffset >= buffer.length) {
firstByteOffset -= buffer.length;
}//if//
}//else//
}//if//
//Skip any unbuffered values as necessary.//
return skipCount < count ? inputStream.skip(count - skipCount) + skipCount : skipCount;
}//skip()//
}//BufferedInputStream//

View File

@@ -0,0 +1,603 @@
/*
* Copyright (c) 1999,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.io;
import java.io.OutputStream;
import java.io.IOException;
import com.common.util.*;
import com.common.debug.*;
/**
* Implements a buffer around another output stream such that the user can insert values into the stream at a later time, and can track the byte location of a specific point in the stream so that it is updated when the stream is modified.
* <p><b>WARNING: This class is not the least bit thread safe and is not designed to ever be thread safe.</b></p>
* <p>TODO: It would be nice to be able to have a buffered output stream wrapper a byte array stream such that the buffered stream writes directly to the byte stream except when necessary (because of insert streams for example).</p>
*/
public class BufferedOutputStream extends OutputStream implements IOutputStreamLocation {
public static final int DEFAULT_BUFFER_INCREMENT_SIZE = 1000;
public static final int DEFAULT_INSERT_BUFFER_INCREMENT_SIZE = 100;
public static final int DEFAULT_BUFFER_SIZE = 2000;
public static final int DEFAULT_INSERT_BUFFER_SIZE = 200;
private int streamLocation = 0; //The location that the current stream is inserting into its parent output stream. If this stream is not inserting then it is the number of bytes already flushed to the encapuslated stream.//
private boolean isFixedSize = false; //TODO: May determine by checking whether the buffer attribute is null.//
private boolean isInsertStream = false; //Whether the stream is inserting into another buffer stream.//
private int reservedByteCount = 0; //Only applies to fixed size insert streams. The number of bytes reserved in the encapsulated buffered output stream. This value goes down as bytes are written.//
private OutputStream outputStream = null; //The stream being buffered.//
private int bufferIncrementSize = DEFAULT_BUFFER_INCREMENT_SIZE; //The number of bytes to increment the buffer by (when it is necessary).//
private LiteList locations = new LiteList(10, 20); //The ordered collection of stream location objects.//
private byte[] buffer = null; //The collection of bytes currently buffered.//
private int bufferSize = 0; //The number of bytes currently buffered.// //TODO:Rename this to bufferIndex or bufferCount. BufferSize is very confusing.//
/**
* BufferedOutputStream constructor.
* This constructor creates a simple location marker within a parent buffered output stream. The location will be updated as bytes are inserted earlier in the stream, and the updated location is accessable by the user.
* @param streamLocation The location within the parent buffered output stream. This location will be updated by the parent stream as necessary.
*/
protected BufferedOutputStream(int streamLocation) {
super();
this.streamLocation = streamLocation;
this.isInsertStream = false;
}//BufferedOutputStream()//
/**
* BufferedOutputStream constructor.
* @param outputStream The destination for written data.
* @param streamLocation The location of this output stream in the context of the parent buffered output stream. This location will be the index of the last reserved byte, or if there are no reserved bytes then it will be the location at which bytes will be inserted into the parent stream.
* @param reservedByteCount The initial size of the buffer used for buffering the data when necessary, or if this is a fixed size stream then it will be the number of bytes reserved in the parent stream.
*/
protected BufferedOutputStream(BufferedOutputStream outputStream, int streamLocation, int reservedByteCount) {
super();
this.outputStream = outputStream;
this.streamLocation = streamLocation;
this.buffer = null;
this.reservedByteCount = reservedByteCount;
this.isFixedSize = true;
this.isInsertStream = true;
}//BufferedOutputStream()//
/**
* BufferedOutputStream constructor.
* @param outputStream The destination for written data.
* @param streamLocation The location of this output stream in the context of the parent buffered output stream. This location will be the index of the last reserved byte, or if there are no reserved bytes then it will be the location at which bytes will be inserted into the parent stream.
* @param byteCount The initial size of the buffer used for buffering the data when necessary, or if this is a fixed size stream then it will be the number of bytes reserved in the parent stream.
* @param isFixedSize Whether the parent stream has reserved a fixed number of bytes allocated to this stream. If it is not fixed size then the user can write as many bytes as desired before closing the stream.
*/
protected BufferedOutputStream(BufferedOutputStream outputStream, int streamLocation, int bufferSize, int incrementSize) {
super();
this.outputStream = outputStream;
this.streamLocation = streamLocation;
this.buffer = new byte[bufferSize <= 0 ? DEFAULT_BUFFER_SIZE : bufferSize];
this.bufferIncrementSize = incrementSize <= 0 ? DEFAULT_BUFFER_INCREMENT_SIZE : incrementSize;
this.isFixedSize = false;
this.isInsertStream = true;
}//BufferedOutputStream()//
/**
* BufferedOutputStream constructor.
*/
public BufferedOutputStream(OutputStream outputStream) {
this(outputStream, DEFAULT_BUFFER_SIZE);
}//BufferedOutputStream()//
/**
* BufferedOutputStream constructor.
* @param outputStream The destination for written data.
* @param bufferSize The initial size of the buffer used for buffering the data when necessary.
*/
public BufferedOutputStream(OutputStream outputStream, int bufferSize) {
super();
this.outputStream = outputStream;
this.buffer = new byte[bufferSize];
this.streamLocation = 0;
this.isFixedSize = false;
this.isInsertStream = false;
}//BufferedOutputStream()//
/**
* Closes the stream and flushes any remaining buffered data.
* <p>If this stream is an insertion stream then it will not close the encapsulated (parent) stream because the close only means no more bytes will be inserted.
* <p>If this stream is not an insertion stream then the encapsulated stream will be told to close. If for example, this is a buffered output stream encapsulating a FileOutputStream, then the file output stream will receive all buffered data, and then will be told to close.
*/
public void close() throws IOException {
flush();
if(bufferSize > 0) {
throw new IOException("Unable to close the buffered output stream because there are open insertion buffer output streams in existance preventing the stream data from flushing to the encapsulated output stream. Please close all related insertion streams before closing this stream.");
}//if//
if(isInsertStream) {
if((isFixedSize) && (reservedByteCount != 0)) {
throw new IOException("Unable to close the insertion stream because the reserved bytes have not all been filled. Either don't reserve bytes, or you must fill exactly that number of bytes.");
}//if//
isInsertStream = false;
}//if//
else {
//Close the encapsulated output stream.//
//TODO: Modify to not set the isInsertStream = false when the stream can no longer insert. Then this can be turned back on.//
//TODO: Why is this commented out? We need to notify the underlying stream that it should close.//
// outputStream.close();
}//else//
}//close()//
/**
* Flushes all or some of the buffer to the stream.
* <p>Note: The flush method may only flush bytes that occur earlier than the first insert stream's location because the insert opertion will add or modify bytes and those bytes must stay buffered to allow this.
*/
public void flush() throws IOException {
if((!isFixedSize) && (buffer != null) && (bufferSize > 0)) {
//Remove locations such that the first location in the collection is an insertable BufferedOutputStream object.//
while((locations.getSize() > 0) && (!((BufferedOutputStream) locations.getFirst()).isInsertStream())) {
locations.remove(0);
}//while//
//Flush the buffer up to the first active BufferedOutputStream's location.//
if(locations.getSize() == 0) {
if(bufferSize > 0) {
if(isInsertStream) {
//Insert the bytes into the encapsulated buffered output stream.//
((BufferedOutputStream) outputStream).insert(streamLocation, buffer, 0, bufferSize, false);
}//if//
else {
//Append the bytes to the encapsulated output stream.//
outputStream.write(buffer, 0, bufferSize);
}//else//
//Update the overall stream location.//
//streamLocation += bufferSize; //This is automatically done by the underlying buffered output stream.//
//Update the buffer size.//
bufferSize = 0;
}//if//
}//if//
else {
BufferedOutputStream location = (BufferedOutputStream) locations.getFirst();
int flushableByteCount = location.getByteIndex() - streamLocation;
//Adjust the number of flushable bytes if the first location has unused reserved bytes.//
if(location.getReservedByteCount() > 0) {
flushableByteCount -= location.getReservedByteCount();
}//if//
//Flush those bytes that we can.//
if(flushableByteCount > 0) {
if(isInsertStream) {
//Insert the bytes into the encapsulated buffered output stream.//
((BufferedOutputStream) outputStream).insert(streamLocation, buffer, 0, flushableByteCount, false);
}//if//
else {
//Append the bytes to the encapsulated output stream.//
outputStream.write(buffer, 0, flushableByteCount);
}//else//
//Update the overall stream location.//
streamLocation += flushableByteCount;
//Update the buffer size.//
bufferSize -= flushableByteCount;
//Shift remaining buffered bytes so that they begin at the first index in the buffer.//
System.arraycopy(buffer, flushableByteCount, buffer, 0, bufferSize);
}//if//
}//else//
}//if//
}//flush()//
/**
* Gets the stream index of the location in the stream when this object was created.
* This value will change if there is an update location object that the users writes data to (unless it has reserved space), or if this location is an update location and did not reserve space and writes data.
* The location will be the last byte index in the set of values written to the stream, or the index of the stream at the time the location was created (updated if any new bytes were written to the stream at an earlier index).
* @return The index within the stream of this location object (or the ending index if the location allows updating).
*/
public int getByteIndex() {
return streamLocation + bufferSize;
}//getByteIndex()//
/**
* Gets an output stream object that allows the user to write a fixed amount of data to the stream at some future time at the current location.
* @param reservedByteCount The number of bytes to reserve in the stream. The user must write exactly this many bytes before the stream can be successfully flushed.
* @return An IStreamUpdateLocation object that can provide the index within the stream and allows the user to write data to the stream at the current position at some future time.
*/
public BufferedOutputStream getInsertOutputStream(int reservedByteCount) throws IOException {
BufferedOutputStream stream = null;
if(reservedByteCount > 0) {
//Add the reserved bytes to the buffer.//
if(bufferSize + reservedByteCount > buffer.length) {
resizeBuffer(reservedByteCount);
}//if//
bufferSize += reservedByteCount;
}//if//
//Create an update location.//
stream = new BufferedOutputStream(this, streamLocation + bufferSize, reservedByteCount);
locations.add(stream);
return stream;
}//getInsertOutputStream()//
/**
* Gets an output stream object that allows the user to write data to the stream at some future time at the current location.
* @param initialBufferSize The size of the initial buffer. This value should be large enough to provide efficient writes to the buffered stream, but small enough not to be wasteful.
* @param incrementSize The number of bytes to increment the buffer by if it is necessary. The buffer will first try to flush to the buffered stream, and will only increase in size if necessary.
* @return An IStreamUpdateLocation object that can provide the index within the stream and allows the user to write data to the stream at the current position at some future time.
*/
public BufferedOutputStream getInsertOutputStream(int initialBufferSize, int incrementSize) throws IOException {
BufferedOutputStream stream = new BufferedOutputStream(this, streamLocation + bufferSize, initialBufferSize, incrementSize);
locations.add(stream);
return stream;
}//getInsertOutputStream()//
/**
* Gets the encapsulated output stream.
* @return Gets the output stream that this object wrappers.
*/
public OutputStream getOutputStream() {
return outputStream;
}//getOutputStream()//
/**
* Gets a location object associated with the current location in the stream.
* This location object can be used to access the current stream position at the location.
* This is useful for the user because the user could also get a dynamic update location which allows the stream to be dynamically modified at some future time.
* A location after the dynamic update location would tell the user what the byte index is after the dynamic update location was completed (all bytes written).
* @return An IStreamLocation object that can provide the index within the stream. It will be updated automatically if a dynamic update location is used to insert byte earlier in the stream.
*/
public IOutputStreamLocation getOutputStreamLocation() throws IOException {
BufferedOutputStream location = new BufferedOutputStream(streamLocation + bufferSize);
if(locations.getSize() > 0) {
locations.add(location);
}//if//
return location;
}//getOutputStreamLocation()//
/**
* Gets the number of bytes reserved in the encapsulated buffered output stream.
* <p>Note: This value is only valid if this stream encapsulates a buffered output stream and is an insert buffer with a fixed number of insertable bytes.
* <p>Note: If this value is non-zero then the parent stream may not flush bytes (beyond the reserved bytes in the stream) to its encapsulated output stream. Thus the user must use ALL reserved bytes, no more, no less.
* @return The number of reserved bytes. This value goes down as bytes are written, until the value reaches zero. If this value is zero then no more bytes may be written.
*/
public int getReservedByteCount() {
return reservedByteCount;
}//getReservedByteCount()//
/**
* Inserts the specified byte values to the stream.
* @param streamIndex The index of the first array byte within the stream (where index zero is the very first byte written to the stream).
* @param bytes The array of values to write to the stream.
* @param offset The offset of the first value to write to the stream.
* @param length The number of values to write to the stream.
* @param isReserved Whether the byte is being written to a reserved space. If this is true then an insert buffer will not be used because space in the buffer is already allocated.
*/
protected void insert(int streamIndex, byte[] bytes, int offset, int length, boolean isReserved) throws IOException {
//If this value is going into a reserved space in the buffer then simply write to the buffer, otherwise we will add it to the insert buffer.//
if(isReserved) {
System.arraycopy(bytes, offset, buffer, streamIndex - streamLocation, length);
}//if//
else {
int availableSpace = buffer.length - bufferSize;
int remainingBytes = length;
int bufferInsertLocation = streamIndex - streamLocation;
//Determine whether we can perform a simple write, or whether we need to perform a write & flush loop or resize the buffer.//
if(availableSpace < remainingBytes) {
//Keep writing and flushing as long as there is data and buffer space.//
while((availableSpace > 0) && (remainingBytes > 0)) {
int copyLength = availableSpace > remainingBytes ? remainingBytes : availableSpace;
//Shift the buffered bytes so that there is space for the inserted bytes.//
if(bufferSize > bufferInsertLocation) {
System.arraycopy(buffer, bufferInsertLocation, buffer, copyLength + bufferInsertLocation, bufferSize - bufferInsertLocation);
}//if//
//Copy the data into the correct place in the buffer.//
System.arraycopy(bytes, offset, buffer, bufferInsertLocation, copyLength);
bufferSize += copyLength;
remainingBytes -= copyLength;
offset += copyLength;
if(remainingBytes > 0) {
flush();
//Recompute the location to insert the remaining bytes.//
bufferInsertLocation = streamIndex - streamLocation + offset;
//Recompute the amount of available space in the buffer.//
availableSpace = buffer.length - bufferSize;
//Make sure we are not being grossly inefficient by ensuring that we at least flush some substantial number of bytes each round.//
if(availableSpace < bufferIncrementSize) {
resizeBuffer(bufferIncrementSize);
availableSpace = buffer.length - bufferSize;
}//if//
}//if//
}//while//
//If we must, then resize the buffer to accomidate the data.//
if((availableSpace == 0) && (remainingBytes > 0)) {
//Resize the buffer so it can contain the new data.//
resizeBuffer(remainingBytes);
//Shift the buffered bytes so that there is space for the inserted bytes.//
if(bufferSize > bufferInsertLocation) {
System.arraycopy(buffer, bufferInsertLocation, buffer, remainingBytes + bufferInsertLocation, bufferSize - bufferInsertLocation);
}//if//
//Copy the bytes into the buffer.//
System.arraycopy(bytes, offset, buffer, bufferInsertLocation, remainingBytes);
//Update the buffer size.//
bufferSize += remainingBytes;
}//if//
}//if//
else {
//Shift the buffered bytes so that there is space for the inserted bytes.//
if(bufferSize > bufferInsertLocation) {
System.arraycopy(buffer, bufferInsertLocation, buffer, bufferInsertLocation + length, bufferSize - bufferInsertLocation);
}//if//
//Copy the bytes into the buffer.//
System.arraycopy(bytes, offset, buffer, bufferInsertLocation, length);
//Update the buffer size.//
bufferSize += length;
}//else//
/* The code above replaces this code - it provides better buffer usage.
int bufferInsertLocation = streamIndex - streamLocation;
//Resize the buffer if necessary.//
if(length + bufferSize > buffer.length) {
resizeBuffer(length);
}//if//
//Shift the buffered bytes so that there is space for the inserted bytes.//
if(bufferSize > bufferInsertLocation) {
System.arraycopy(buffer, bufferInsertLocation, buffer, length + bufferInsertLocation, bufferSize - bufferInsertLocation);
}//if//
//Copy the inserted bytes.//
System.arraycopy(bytes, offset, buffer, bufferInsertLocation, length);
*/
//Notify the location objects that their positions may have changed.//
updateLocations(streamIndex, length);
}//else//
}//insert()//
/**
* Inserts the specified byte values to the stream.
* @param streamIndex The index of the first array byte within the stream (where index zero is the very first byte written to the stream).
* @param bytes The array of values to write to the stream.
* @param isReserved Whether the byte is being written to a reserved space. If this is true then an insert buffer will not be used because space in the buffer is already allocated.
*/
protected void insert(int streamIndex, byte[] bytes, boolean isReserved) throws IOException {
insert(streamIndex, bytes, 0, bytes.length, isReserved);
}//insert()//
/**
* Inserts the specified unsigned byte value to the stream.
* @param streamIndex The index of the byte within the stream (where index zero is the very first byte written to the stream).
* @param b The unsigned byte value to write to the stream.
* @param isReserved Whether the byte is being written to a reserved space. If this is true then an insert buffer will not be used because space in the buffer is already allocated.
*/
protected void insert(int streamIndex, int b, boolean isReserved) throws IOException {
//If this value is going into a reserved space in the buffer then simply write to the buffer, otherwise we will add it to the insert buffer.//
if(isReserved) {
buffer[streamIndex - streamLocation] = (byte) b;
}//if//
else {
Debug.halt(); //Should not occur.//
}//else//
}//insert()//
/**
* Determines whether this stream is performing an insert of bytes into another BufferedOutputStream object.
* @return Whether this stream is inserting into another stream.
*/
protected boolean isInsertStream() {
return isInsertStream;
}//isInsertStream()//
/**
* Shifts the location of the buffered output stream.
* <p>This will occur if this stream is either a simple marker, or an insertable stream into the encapsulated buffered output stream.
* The encapsulated buffered output stream will call this method if another insertable stream inserts some data into the stream at an earlier stream location.
* @param offset The number of bytes to move the location forward (higher or later in the stream).
*/
protected void moveLocation(int offset) {
streamLocation += offset;
}//moveLocation()//
/**
* Resizes the buffer so that it can contain <code>count</code> more bytes (at a minimum).
* @param count The number of bytes the user expects to add immediatly.
*/
protected void resizeBuffer(int count) throws IOException {
byte[] tempBuffer = new byte[buffer.length + (count > bufferIncrementSize ? count + bufferIncrementSize : bufferIncrementSize)];
System.arraycopy(buffer, 0, tempBuffer, 0, buffer.length);
buffer = tempBuffer;
}//resizeBuffer()//
/**
* Copies the contents of the stream's buffer into a new byte array.
* @return A byte array containing all of the bytes written to this stream.
*/
public byte[] toByteArray() throws IOException {
byte[] bytes = null;
flush();
if(outputStream instanceof java.io.ByteArrayOutputStream) {
bytes = ((java.io.ByteArrayOutputStream) outputStream).toByteArray();
}//if//
else if(outputStream instanceof ByteArrayOutputStream) {
bytes = ((ByteArrayOutputStream) outputStream).toByteArray();
}//else if//
else if(outputStream instanceof BufferedOutputStream) {
bytes = ((BufferedOutputStream) outputStream).toByteArray();
}//else if//
else {
throw new com.common.exception.MethodNotSupportedException("toByteArray() not supported except for java.io.ByteArrayOutputStream and com.common.io.ByteArrayOutputStream");
}//else//
return bytes;
}//toByteArray()//
/**
* Updates the location objects after bytes were inserted into the stream.
* @param byteIndex The stream byte index that the bytes were inserted at.
* @param insertedByteCount The number of bytes inserted.
*/
protected void updateLocations(int byteIndex, int insertedByteCount) {
IIterator iterator = locations.iterator();
while(iterator.hasNext()) {
BufferedOutputStream location = (BufferedOutputStream) iterator.next();
if(((location.isFixedSize) && ((location.getByteIndex() - location.reservedByteCount) >= byteIndex)) || ((!location.isFixedSize) && (location.getByteIndex() >= byteIndex))) {
location.moveLocation(insertedByteCount);
}//if//
}//while//
}//updateLocations()//
/**
* Writes the specified byte values to the stream.
* @param bytes The array of values to write to the stream.
*/
public void write(byte[] bytes) throws IOException {
if((isInsertStream) && (isFixedSize)) {
if(bytes.length > reservedByteCount) {
throw new IOException("Cannot write more bytes than were reserved when the insert output stream was created.");
}//if//
//Send the data to the encapsulated stream at the location of the earliest unused reserved byte.//
((BufferedOutputStream) outputStream).insert(streamLocation - reservedByteCount, bytes, isFixedSize);
//Update the count of reserved bytes.//
reservedByteCount -= bytes.length;
if(reservedByteCount == 0) {
close();
}//if//
}//if//
else {
int offset = 0;
int availableSpace = buffer.length - bufferSize;
int remainingBytes = bytes.length;
//Determine whether we can perform a simple write, or whether we need to perform a write & flush loop or resize the buffer.//
if(availableSpace < remainingBytes) {
//Keep writing and flushing as long as there is data and buffer space.//
while((availableSpace > 0) && (remainingBytes > 0)) {
int copyLength = availableSpace > remainingBytes ? remainingBytes : availableSpace;
System.arraycopy(bytes, offset, buffer, bufferSize, copyLength);
bufferSize += copyLength;
remainingBytes -= copyLength;
offset += copyLength;
if(remainingBytes > 0) {
flush();
availableSpace = buffer.length - bufferSize;
}//if//
}//while//
//If we must, then resize the buffer to accomidate the data.//
if((availableSpace == 0) && (remainingBytes > 0)) {
//Resize the buffer so it can contain the new data.//
resizeBuffer(remainingBytes);
//Copy the bytes into the buffer.//
System.arraycopy(bytes, offset, buffer, bufferSize, remainingBytes);
//Update the buffer size.//
bufferSize += remainingBytes;
}//if//
}//if//
else {
//Copy the bytes into the buffer.//
System.arraycopy(bytes, 0, buffer, bufferSize, bytes.length);
//Update the buffer size.//
bufferSize += bytes.length;
}//else//
}//else//
}//write()//
/**
* Writes the specified byte values to the stream.
* @param bytes The array of values to write to the stream.
* @param offset The offset of the first value to write to the stream.
* @param length The number of values to write to the stream.
*/
public void write(byte[] bytes, int offset, int length) throws IOException {
if((isInsertStream) && (isFixedSize)) {
if(length > reservedByteCount) {
throw new IOException("Cannot write more bytes than were reserved when the insert output stream was created.");
}//if//
//Send the data to the encapsulated stream at the location of the earliest unused reserved byte.//
((BufferedOutputStream) outputStream).insert(streamLocation - reservedByteCount, bytes, offset, length, isFixedSize);
//Update the count of reserved bytes.//
reservedByteCount -= length;
if(reservedByteCount == 0) {
close();
}//if//
}//if//
else {
int availableSpace = buffer.length - bufferSize;
int remainingBytes = length;
//Determine whether we can perform a simple write, or whether we need to perform a write & flush loop or resize the buffer.//
if(availableSpace < remainingBytes) {
//Keep writing and flushing as long as there is data and buffer space.//
while((availableSpace > 0) && (remainingBytes > 0)) {
int copyLength = availableSpace > remainingBytes ? remainingBytes : availableSpace;
System.arraycopy(bytes, offset, buffer, bufferSize, copyLength);
bufferSize += copyLength;
remainingBytes -= copyLength;
offset += copyLength;
if(remainingBytes > 0) {
flush();
availableSpace = buffer.length - bufferSize;
}//if//
}//while//
//If we must, then resize the buffer to accomidate the data.//
if((availableSpace == 0) && (remainingBytes > 0)) {
//Resize the buffer so it can contain the new data.//
resizeBuffer(remainingBytes);
//Copy the bytes into the buffer.//
System.arraycopy(bytes, offset, buffer, bufferSize, remainingBytes);
//Update the buffer size.//
bufferSize += remainingBytes;
}//if//
}//if//
else {
//Copy the bytes into the buffer.//
System.arraycopy(bytes, offset, buffer, bufferSize, length);
//Update the buffer size.//
bufferSize += length;
}//else//
}//else//
}//write()//
/**
* Writes the specified unsigned byte value to the stream.
* @param b The unsigned byte value to write to the stream.
*/
public void write(int b) throws IOException {
if((isInsertStream) && (isFixedSize)) {
if(reservedByteCount == 0) {
throw new IOException("Cannot write more bytes than were reserved when the insert output stream was created.");
}//if//
//Send the data to the encapsulated stream at the location of the earliest unused reserved byte.//
((BufferedOutputStream) outputStream).insert(streamLocation - reservedByteCount, b, isFixedSize);
//Update the count of reserved bytes.//
reservedByteCount--;
if(reservedByteCount == 0) {
close();
}//if//
}//if//
else {
//If there is not enough room in the buffer then try to flush it, and if still no room then resize it.//
if(bufferSize == buffer.length) {
flush();
if(bufferSize == buffer.length) {
resizeBuffer(1);
}//if//
}//if//
//Write the byte to the buffer.//
buffer[bufferSize++] = (byte) b;
}//else//
}//write()//
}//BufferedOutputStream//

View File

@@ -0,0 +1,328 @@
/*
* Copyright (c) 1999,2008 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.io;
import java.io.*;
/**
* A simple stream that reads bytes from a byte array.
* This stream is capable of decrypting the bytes as they are read.
*/
public class ByteArrayInputStream extends java.io.InputStream implements IInputStream {
/** The default initial size of the buffer. */
private static final int DEFAULT_SIZE = 1001;
private byte[] buffer;
private int position;
private int count;
private int expectedSize;
//private boolean reuseBuffer;
private int originalPosition = 0;
private int originalCount = 0;
/**
* Creates the byte array input stream with a buffer containing source data.
* @param buffer A buffer containing the source data for this stream.
*/
public ByteArrayInputStream(byte[] buffer) {
this(buffer, 0, (buffer != null ? buffer.length : 0));
}//ByteArrayInputStream()//
/**
* Creates the byte array input stream with a buffer containing source data.
* @param buffer A buffer containing the source data for this stream.
* @param offset The offset of the first byte of source data in the buffer.
* @param length The number of bytes of source data in the buffer.
*/
public ByteArrayInputStream(byte[] buffer, int offset, int length) {
//this.reuseBuffer = false;
this.expectedSize = DEFAULT_SIZE;
internalSetBuffer(buffer, offset, length);
}//ByteArrayInputStream()//
/**
* Creates the byte array input stream with the estimated number of source bytes to be put in the stream.
* @param expectedSize The number of bytes the user expects will be in this stream.
*/
public ByteArrayInputStream(int expectedSize) {
//this.reuseBuffer = true;
this.expectedSize = expectedSize;
this.buffer = null;
this.position = 0;
this.count = 0;
}//ByteArrayInputStream()//
/**
* Gets the current position in the stream.
* @return The current position.
*/
public int getPosition() {
return position;
}//getPosition()//
/**
* Sets the current position in the stream.
* @param position The current position.
*/
public void setPosition(int position) {
this.position = position;
}//setPosition()//
/**
* Gets the number of available bytes in the input stream.
* @return The number of bytes that have not yet been read from the input stream.
*/
public int available() throws IOException {
return count - position;
}//available()//
/**
* @see IInputStream.canDecrypt()
*/
public boolean canDecrypt() {
return false;
}//canDecrypt()//
/**
* @see IInputStream.canReadFrom()
*/
public boolean canReadFrom() {
return true;
}//canReadFrom()//
/**
* Closes the stream and releases all held resources.
*/
public void close() throws IOException {
internalRelease();
}//close()//
/**
* Switches decryption of the stream off and on.
* Nothing will occur if no symmetric algorithm was provided to the stream.
* The stream does maintain a decryption count which is incremented when decryption is turned on and only stops the decrypting when this count reaches zero.
* Since data written to the ByteArrayOutputStream is never double encrypted, the data read will also not be double decrypted.
* @param decrypt Whether to turn decryption on (<code>true</code>) or off (<code>false</code>).
* @see IInputStream.decrypt(boolean)
*/
public void decrypt(boolean decrypt) throws java.io.IOException {
}//encrypt()//
/**
* Makes sure the buffer is large enough to hold <code>size</code> bytes in addition to any bytes already held.
* @param size The number of new bytes the buffer must be able to hold.
*/
protected void ensureSpace(int size) {
byte[] oldBuffer = buffer;
if(oldBuffer == null) {
buffer = new byte[expectedSize < size ? size + 50 : expectedSize];
}//if//
else if(oldBuffer.length - count < size) {
byte[] newBuffer = new byte[oldBuffer.length + size + 50];
System.arraycopy(oldBuffer, 0, newBuffer, 0, count);
buffer = newBuffer;
}//else if//
}//ensureSpace()//
/**
* Will release any held resources.
*/
public void finalize() {
//Release the stream resources.//
internalRelease();
}//finalize()//
/**
* Initializes the stream with the given source material.
* @param buffer The new byte array buffer to use for source bytes.
*/
public void initialize(byte[] buffer) {
if(buffer != null) {
internalInitialize(buffer, 0, buffer.length);
}//if//
else {
throw new com.common.exception.InvalidArgumentException("Must supply a valid buffer.");
}//else//
}//initialize()//
/**
* Initializes the stream with the given source material.
* @param buffer The new byte array buffer to use for source bytes.
* @param offset The offset in the buffer where the first source byte can be found.
* @param length The number of source bytes available in the supplied buffer.
*/
public void initialize(byte[] buffer, int offset, int length) {
internalInitialize(buffer, offset, length);
}//initialize()//
/**
* Initializes the stream with the given source material.
* @param buffer The new byte array buffer to use for source bytes.
* @param offset The offset in the buffer where the first source byte can be found.
* @param length The number of source bytes available in the supplied buffer.
*/
private void internalInitialize(byte[] buffer, int offset, int length) {
//Cleanup in case this stream is being reused.//
internalRelease();
//The buffer is not reusable.//
//reuseBuffer = false;
//Initialize the stream with the new source material.//
internalSetBuffer(buffer, offset, length);
}//internalInitialize()//
/**
* Releases the held resources and resets the stream indexes.
* This is useful if the stream will be reused, if the buffers are reuseable, or to assist GC.
*/
private void internalRelease() {
//Clean the stream.//
buffer = null;
originalPosition = 0;
originalCount = 0;
position = 0;
count = 0;
}//internalRelease()//
/**
* Resets the stream so that it may be re-read.
*/
private void internalReset() {
//Reset the position and count to the original values.//
position = originalPosition;
count = originalCount;
}//internalReset()//
/**
* Sets the buffer to be used by this stream as a source of bytes.
* @param buffer The new byte array buffer to use for source bytes.
* @param offset The offset in the buffer where the first source byte can be found.
* @param length The number of source bytes available in the supplied buffer.
*/
protected void internalSetBuffer(byte[] buffer, int offset, int length) {
//Set the position variables.//
this.originalPosition = offset;
this.originalCount = length + offset;
this.buffer = buffer;
this.position = offset;
this.count = length + offset;
}//internalSetBuffer()//
/**
* Gets the underlying buffer used by the input stream.
* @return The underlying buffer.
*/
public byte[] getBuffer() {
return buffer;
}//getBuffer()//
/**
* @see IInputStream.isDecrypting()
*/
public boolean isDecrypting() {
return false;
}//isDecrypting()//
/**
* Gets the next byte from the stream without actually incrementing the stream.
* @return The next byte in the stream.
*/
public byte peek() throws IOException {
return peek(1);
}//peek()//
/**
* Gets the byte from the stream at the requested offset without actually incrementing the stream.
* @param offset The offset from the current location in the stream. This value must be positive and should not exceed the number of bytes left in the stream.
* @return The byte found at the specified offset.
*/
public byte peek(int offset) throws IOException {
if((position + offset < count) && (position + offset >= 0)) {
return buffer[position + offset];
}//if//
throw new IOException("Invalid offset.");
}//peek()//
/* (non-Javadoc)
* @see java.io.InputStream#read()
*/
public int read() throws IOException {
return position < count ? buffer[position++] & 0xFF : -1;
}//read()//
/* (non-Javadoc)
* @see java.io.InputStream#read(byte[], int, int)
*/
public int read(byte[] bytes, int offset, int length) throws IOException {
int newPosition = position + length;
//Check to see if there are any bytes available.//
if(position < count) {
//Update the number of requested bytes if there are not enough available.//
if(newPosition > count) {
length = count - position;
newPosition = position + length;
}//if//
//Copy the bytes from this stream to the buffer.//
System.arraycopy(buffer, position, bytes, offset, length);
//Update the stream position.//
position = newPosition;
}//if//
else {
//Note: I changed this to -1 to comply with the java.io.InputStream#read(byte[], int, int) commenting. This may cause problems with existing code that uses this class.//
length = -1;
}//else//
//Return the number of bytes pulled off the stream.//
return length;
}//read()//
/* (non-Javadoc)
* @see com.common.io.IInputStream#read(java.io.OutputStream, int)
*/
public int read(java.io.OutputStream out, int length) throws IOException {
int newPosition = position + length;
//Check to see if there are any bytes available.//
if(position < count) {
//Update the number of requested bytes if there are not enough available.//
if(newPosition > count) {
length = count - position;
newPosition = position + length;
}//if//
//Copy the bytes from this stream to the output stream.//
out.write(buffer, position, length);
//Update the stream position.//
position = newPosition;
}//if//
else {
length = 0;
}//else//
//Return the number of bytes pulled off the stream.//
return length;
}//read()//
/**
* Replaces the buffered data in this input stream with the bytes from the given input stream.
* @param in The input stream containing the data to be buffered by this input stream.
* @param numberOfBytes The number of bytes to be read.
* @throws IOException If there are not enough bytes on the given input stream.
*/
public void readFrom(InputStream in, int numberOfBytes) throws IOException {
int totalNumberOfBytes = numberOfBytes + count;
int bytesRead;
//Ensure the length of the buffer.//
ensureSpace(numberOfBytes);
//Read the bytes off the stream.//
while(count != totalNumberOfBytes) {
bytesRead = in.read(buffer, count, totalNumberOfBytes - count);
if(bytesRead == -1) {
throw new IOException();
}//if//
count += bytesRead;
originalCount += bytesRead;
}//while//
}//readFrom()//
/**
* Releases the stream resources and resets the stream so that the object may be GC'd or reused.
* This stream will no longer be re-readable.
*/
public void release() {
internalRelease();
}//release()//
/**
* Resets the stream so that it may be re-read.
*/
public void reset() throws IOException {
internalReset();
}//reset()//
}//ByteArrayInputStream//

View File

@@ -0,0 +1,307 @@
/*
* Copyright (c) 1999,2008 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.io;
import java.io.*;
import java.nio.ByteBuffer;
import com.common.security.*;
/**
* A simple stream that writes bytes to a byte array.
* This stream is capable of encrypting the bytes as they are written.
*/
public class ByteArrayOutputStream extends OutputStream implements IOutputStream {
private byte[] buffer;
protected int index;
private int optimalSize = 0;
//private boolean reuseBuffer;
/**
* ByteArrayOutputStream constructor.
* @param optimalSize The estimated number of bytes that will be written to the stream.
* @param reuseBuffer Whether the resources should be reused.
*/
public ByteArrayOutputStream(int optimalSize, boolean reuseBuffer) {
//this.reuseBuffer = reuseBuffer;
this.optimalSize = optimalSize;
this.buffer = null;
this.index = 0;
}//ByteArrayOutputStream()//
/**
* @see IOutputStream.canEncrypt()
*/
public boolean canEncrypt() {
return true;
}//canEncrypt()//
/**
* @see IOutputStream.canEncrypt()
*/
public boolean canGetSize() {
return true;
}//canGetSize()//
/**
* @see IOutputStream.canReset()
*/
public boolean canReset() {
return true;
}//canReset()//
/**
* @see IOutputStream.canWriteTo()
*/
public boolean canWriteTo() {
return true;
}//canWriteTo()//
/**
* Closes the stream and releases all held resources.
*/
public void close() throws IOException {
internalRelease();
}//close()//
/**
* Switches encryption of the stream off and on.
* Nothing will occur if no symmetric algorithm was provided to the stream.
* The stream does maintain an encryption count which is incremented when encryption is turned on and only stops the encrypting when this count reaches zero.
* Since data written to the ByteArrayOutputStream is never double encrypted, the data read will also not be double decrypted.
* @param encrypt Whether to turn encryption on (<code>true</code>) or off (<code>false</code>).
*/
public void encrypt(boolean encrypt) throws java.io.IOException {
}//encrypt()//
/**
* Makes sure there is enough space available to write <code>size</code> bytes to the stream.
* @param size The number of bytes of space that should be available.
*/
protected void ensureSpace(int size) {
byte[] oldBuffer = buffer;
if(oldBuffer == null) {
buffer = new byte[optimalSize < size ? size + 100 : optimalSize];
}//if//
else if(oldBuffer.length - index < size) {
byte[] newBuffer = new byte[oldBuffer.length + size + 100];
System.arraycopy(oldBuffer, 0, newBuffer, 0, index);
buffer = newBuffer;
}//else if//
}//ensureSpace()//
/**
* Will release any held resources.
*/
public void finalize() throws Throwable {
internalRelease();
}//finalize()//
/**
* Gets the buffer used by this stream.
* @return The buffer used by the stream for storing bytes written.
*/
public byte[] getBuffer() {
return buffer;
}//getBuffer()//
/**
* Sets the buffer used by this stream.
* @param buffer The buffer used by the stream for storing bytes written.
*/
protected void setBuffer(byte[] buffer) {
this.buffer = buffer;
}//setBuffer()//
/**
* Gets the number of bytes in the stream (including reserved or inset bytes if there are any).
* @return The number of bytes in the stream.
*/
public int getSize() {
return index;
}//getSize()//
/**
* Initializes the stream with a new buffer.
*/
public void initialize(int insetSize, ISymmetricAlgorithm symmetricAlgorithm) {
internalInitialize(insetSize, symmetricAlgorithm);
}//initialize()//
/**
* Initializes the stream with a new buffer.
*/
protected void internalInitialize(int insetSize, ISymmetricAlgorithm symmetricAlgorithm) {
//Make sure we are clean.//
internalRelease();
//Get a new buffer.//
internalSetBuffer(new byte[optimalSize]);
//Set the current index.//
this.index = insetSize;
}//internalInitialize()//
/**
* Resets the stream and releases any held resources.
*/
private void internalRelease() {
buffer = null;
index = 0;
}//internalRelease()//
/**
* Resets the stream so it may be reused.
*/
private void internalReset() {
index = 0;
}//internalReset()//
/**
* Sets the stream's buffer.
* @param buffer The byte array buffer to be used by this stream.
*/
private void internalSetBuffer(byte[] buffer) {
this.buffer = buffer;
}//internalSetBuffer()//
/**
* @see IOutputStream.isEncrypting()
*/
public boolean isEncrypting() {
return false;
}//isEncrypting()//
/**
* Will add padding to the stream up to the given index within the stream.
* <p>NOTE: The purpose of this method is to get around timing problems in win95/98 where streams of a size less than 255 bytes causes 150ms delays in reading from the stream.
* @param index The index (position) within the stream to pad to.
*/
public void padTo(int index) throws IOException {
int paddingSize = index - this.index;
//Write zeros to the stream for padding.//
if(paddingSize > 0) {
while(paddingSize != 0) {
write(0);
paddingSize--;
}//while//
}//if//
}//padTo()//
/**
* Adds padding to the stream.
* @param size The number of padding bytes to be written to the stream.
*/
public void pad(int size) throws IOException {
//Write zeros to the stream for padding.//
if(size > 0) {
while(size != 0) {
write(0);
size--;
}//while//
}//if//
}//pad()//
/**
* Resets the stream so that it may be reused.
*/
public void reset() throws IOException {
internalReset();
}//reset()//
/**
* Gets the current position in the output stream.
* @return The current stream position. Same as calling getSize().
*/
public int getPosition() {
return index;
}//getPosition()//
/**
* Sets the stream position for writing.
* @param position The position of the stream. This will change the size of the stream.
*/
public void setPosition(int position) {
if(position > buffer.length) {
ensureSpace(position - index);
}//if//
index = position;
}//setPosition()//
/**
* Copies the contents of the stream's buffer into a new byte array.
* @return A byte array containing all of the bytes written to this stream.
*/
public byte[] toByteArray() {
byte[] newbuffer = new byte[index];
if(buffer != null) {
System.arraycopy(buffer, 0, newbuffer, 0, index);
}//if//
return newbuffer;
}//toByteArray()//
/**
* Writes the bytes to this stream.
* @param bytes The data to be written to this stream.
*/
public void write(ByteBuffer bytes) throws java.io.IOException {
int count = bytes.remaining();
//Make sure there is enough space.//
ensureSpace(count);
//Copy the bytes to the stream buffer.//
bytes.get(buffer, index, count);
//Update the index.//
index += count;
}//write()//
/**
* Writes the bytes to this stream.
* @param bytes The data to be written to this stream.
* @param length The number of bytes to write to this stream.
*/
public void write(ByteBuffer bytes, int count) throws java.io.IOException {
//Make sure there is enough space.//
ensureSpace(count);
//Copy the bytes to the stream buffer.//
bytes.get(buffer, index, count);
//Update the index.//
index += count;
}//write()//
/**
* Writes the bytes to this stream.
* @param bytes The data to be written to this stream.
*/
public void write(byte[] bytes) throws java.io.IOException {
//Make sure there is enough space.//
ensureSpace(bytes.length);
//Copy the bytes to the stream buffer.//
System.arraycopy(bytes, 0, buffer, index, bytes.length);
//Update the index.//
index += bytes.length;
}//write()//
/**
* Writes the bytes to this stream.
* @param bytes The data to be written to this stream.
* @param offset The offset of the first byte to write.
* @param length The number of bytes to write to this stream.
*/
public void write(byte[] bytes, int offset, int length) throws java.io.IOException {
//Make sure there is enough space.//
ensureSpace(length);
//Copy the bytes to the stream buffer.//
System.arraycopy(bytes, offset, buffer, index, length);
//Update the index.//
index += length;
}//write()//
/**
* Writes the specified byte to this stream.
* @param b The byte to append to this stream.
*/
public void write(int b) throws IOException {
//Make sure there is enough space.//
ensureSpace(1);
//Append the new byte to the end of the buffer.//
buffer[index] = (byte) b;
//Adjust the count of bytes in the buffer.//
index++;
}//write()//
/**
* Writes the contents of the stream buffer to the given output stream.
* @param out The output stream to write the data to.
*/
public void writeTo(OutputStream out) throws IOException {
out.write(buffer, 0, index);
}//writeTo()//
/**
* Writes the contents of the stream buffer to the given byte buffer.
* @param out The output stream to write the data to.
*/
public void writeTo(ByteBuffer buffer) throws IOException {
buffer.put(this.buffer, 0, index);
}//writeTo()//
}//ByteArrayOutputStream//

View File

@@ -0,0 +1,204 @@
/*
* Copyright (c) 1999,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.common.io;
import java.io.InputStream;
import java.io.IOException;
import java.util.zip.*;
import com.common.debug.*;
public class CompressionInputStream extends InputStream implements IInputStream {
public static final int DEFAULT_BUFFER_SIZE = 301;
protected InputStream stream = null;
protected Inflater inflater = null;
protected byte[] internalBuffer = null;
protected byte[] bufferOfOne = new byte[1];
/**
* CompressionInputStream constructor.
* @param stream The stream that will provide input to this compression stream.
*/
public CompressionInputStream(InputStream stream) {
this(stream, new Inflater(true), DEFAULT_BUFFER_SIZE);
}//CompressionInputStream()//
/**
* CompressionInputStream constructor.
* @param stream The stream that will provide input to this compression stream.
* @param inflater The inflater to be used to inflate the input data.
*/
public CompressionInputStream(InputStream stream, Inflater inflater) {
this(stream, inflater, DEFAULT_BUFFER_SIZE);
}//CompressionInputStream()//
/**
* CompressionInputStream constructor.
* @param stream The stream that will provide input to this compression stream.
* @param inflater The inflater to be used to inflate the input data.
* @param bufferSize The size of the internal buffer used to shuttle data from the underlying stream through the inflater.
*/
public CompressionInputStream(InputStream stream, Inflater inflater, int bufferSize) {
//Validate the inputs.//
if(bufferSize < 1) {
throw new IllegalArgumentException("Buffer size must be greater than zero.");
}//if//
else if(stream == null) {
throw new IllegalArgumentException("A non-null input stream must be provided.");
}//else if//
else if(inflater == null) {
inflater = new Inflater(true);
}//else if//
this.stream = stream;
this.inflater = inflater;
this.internalBuffer = new byte[bufferSize];
}//CompressionInputStream()//
/* (non-Javadoc)
* @see IInputStream#canDecrypt()
*/
public boolean canDecrypt() {
return (stream instanceof IInputStream) && (((IInputStream) stream).canDecrypt());
}//canDecrypt()//
/* (non-Javadoc)
* @see IInputStream#decrypt(boolean)
*/
public void decrypt(boolean decrypt) throws IOException {
if(stream instanceof IInputStream) {
if(((IInputStream) stream).canDecrypt()) {
((IInputStream) stream).decrypt(decrypt);
}//if//
else {
throw new IOException(ERROR_DECRYPTION_NOT_SUPPORTED);
}//else//
}//if//
else {
throw new IOException(ERROR_DECRYPTION_NOT_SUPPORTED);
}//else//
}//decrypt()//
/**
* Inflates the next section of compressed data.
* @return Whether there was a next section to be decompressed.
*/
private boolean inflate() throws IOException {
int readSize = (int) (StreamSupport.readShort(stream) & 0xFFFF);
boolean result = false;
if((readSize = stream.read(internalBuffer, 0, readSize)) > 0) {
inflater.setInput(internalBuffer, 0, readSize);
result = true;
}//if//
return result;
}//inflate()//
/* (non-Javadoc)
* @see IInputStream#isDecrypting()
*/
public boolean isDecrypting() {
return (stream instanceof IInputStream) && (((IInputStream) stream).isDecrypting());
}//isDecrypting()//
/* (non-Javadoc)
* @see java.io.InputStream#read()
*/
public int read() throws IOException {
int result = -2;
try {
while(result == -2) {
if(inflater.inflate(bufferOfOne, 0, 1) == 0) {
if(inflater.needsDictionary()) {
//TODO: Do we need to do anything special if a dictionary is needed?
Debug.log(new RuntimeException("Needs dictionary."));
result = -1;
}//if//
else if(inflater.finished()) {
result = -1;
}//else if//
else if(inflater.needsInput()) {
//int readSize = length > internalBuffer.length ? internalBuffer.length : length;
//int readSize = internalBuffer.length;
if(!inflate()) {
break;
}//if//
}//else if//
}//if//
else {
result = bufferOfOne[0] & 0xFF;
}//else//
}//while//
}//try//
catch(DataFormatException e) {
Debug.log(e);
throw new IOException("Stream corruption error in decompressing.");
}//catch//
return result;
}//read()//
/* (non-Javadoc)
* @see java.io.InputStream#read(byte[])
*/
public int read(byte[] buffer) throws IOException {
return read(buffer, 0, buffer.length);
}//read()//
/* (non-Javadoc)
* @see java.io.InputStream#read(byte[], int, int)
*/
public int read(byte[] buffer, int offset, int length) throws IOException {
int result = 0;
try {
int count = 0;
while(count != -1 && length > 0) {
if((count = inflater.inflate(buffer, offset, length)) == 0) {
if(inflater.needsDictionary()) {
//TODO: Do we need to do anything special if a dictionary is needed?
Debug.log(new RuntimeException("Needs dictionary."));
count = -1;
}//if//
else if(inflater.finished()) {
count = -1;
}//else if//
else if(inflater.needsInput()) {
//int readSize = length > internalBuffer.length ? internalBuffer.length : length;
//int readSize = internalBuffer.length;
if(!inflate()) {
break;
}//if//
}//else if//
}//if//
else {
offset += count;
length -= count;
result += count;
}//else//
}//while//
}//try//
catch(DataFormatException e) {
Debug.log(e);
throw new IOException("Stream corruption error in decompressing.");
}//catch//
return result == 0 ? -1 : result;
}//read()//
/* (non-Javadoc)
* @see IInputStream#read(java.io.OutputStream, int)
*/
public int read(java.io.OutputStream out, int length) throws IOException {
int result;
if(stream instanceof IInputStream) {
result = ((IInputStream) stream).read(out, length);
}//if//
else {
byte[] bytes = new byte[length];
result = stream.read(bytes, 0, bytes.length);
out.write(bytes, 0, result);
}//else//
return result;
}//read()//
}//CompressionInputStream//

Some files were not shown because too many files have changed in this diff Show More