You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by mc...@apache.org on 2012/07/16 15:43:44 UTC
svn commit: r1362033 [5/10] - in /felix/trunk/bundleplugin/src:
main/java/aQute/bnd/build/ main/java/aQute/bnd/build/model/
main/java/aQute/bnd/build/model/clauses/
main/java/aQute/bnd/build/model/conversions/
main/java/aQute/bnd/compatibility/ main/ja...
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Clazz.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Clazz.java?rev=1362033&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Clazz.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Clazz.java Mon Jul 16 13:43:38 2012
@@ -0,0 +1,1631 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.nio.*;
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.bnd.osgi.Descriptors.Descriptor;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+import aQute.bnd.osgi.Descriptors.TypeRef;
+import aQute.libg.generics.*;
+
+public class Clazz {
+
+ static Pattern METHOD_DESCRIPTOR = Pattern.compile("\\((.*)\\)(.+)");
+
+ public class ClassConstant {
+ int cname;
+
+ public ClassConstant(int class_index) {
+ this.cname = class_index;
+ }
+
+ public String getName() {
+ return (String) pool[cname];
+ }
+ }
+
+ public static enum JAVA {
+ JDK1_1(45, "JRE-1.1"), JDK1_2(46, "J2SE-1.2"), //
+ JDK1_3(47, "J2SE-1.3"), //
+ JDK1_4(48, "J2SE-1.4"), //
+ J2SE5(49, "J2SE-1.5"), //
+ J2SE6(50, "JavaSE-1.6"), //
+ OpenJDK7(51, "JavaSE-1.7"), //
+ UNKNOWN(Integer.MAX_VALUE, "<>")//
+ ;
+
+ final int major;
+ final String ee;
+
+ JAVA(int major, String ee) {
+ this.major = major;
+ this.ee = ee;
+ }
+
+ static JAVA format(int n) {
+ for (JAVA e : JAVA.values())
+ if (e.major == n)
+ return e;
+ return UNKNOWN;
+ }
+
+ public int getMajor() {
+ return major;
+ }
+
+ public boolean hasAnnotations() {
+ return major >= J2SE5.major;
+ }
+
+ public boolean hasGenerics() {
+ return major >= J2SE5.major;
+ }
+
+ public boolean hasEnums() {
+ return major >= J2SE5.major;
+ }
+
+ public static JAVA getJava(int major, @SuppressWarnings("unused") int minor) {
+ for (JAVA j : JAVA.values()) {
+ if (j.major == major)
+ return j;
+ }
+ return UNKNOWN;
+ }
+
+ public String getEE() {
+ return ee;
+ }
+ }
+
+ public static enum QUERY {
+ IMPLEMENTS, EXTENDS, IMPORTS, NAMED, ANY, VERSION, CONCRETE, ABSTRACT, PUBLIC, ANNOTATED, RUNTIMEANNOTATIONS, CLASSANNOTATIONS;
+
+ }
+
+ public final static EnumSet<QUERY> HAS_ARGUMENT = EnumSet.of(QUERY.IMPLEMENTS, QUERY.EXTENDS, QUERY.IMPORTS,
+ QUERY.NAMED, QUERY.VERSION, QUERY.ANNOTATED);
+
+ /**
+ * <pre>
+ * ACC_PUBLIC 0x0001 Declared public; may be accessed from outside its
+ * package.
+ * ACC_FINAL 0x0010 Declared final; no subclasses allowed.
+ * ACC_SUPER 0x0020 Treat superclass methods specially when invoked by the
+ * invokespecial instruction.
+ * ACC_INTERFACE 0x0200 Is an interface, not a
+ * class.
+ * ACC_ABSTRACT 0x0400 Declared abstract; may not be instantiated.
+ * </pre>
+ *
+ * @param mod
+ */
+ final static int ACC_PUBLIC = 0x0001; // Declared
+ // public;
+ // may
+ // be
+ // accessed
+ // from outside its package.
+ final static int ACC_FINAL = 0x0010; // Declared
+ // final;
+ // no
+ // subclasses
+ // allowed.
+ final static int ACC_SUPER = 0x0020; // Treat
+ // superclass
+ // methods
+ // specially when invoked by the
+ // invokespecial instruction.
+ final static int ACC_INTERFACE = 0x0200; // Is
+ // an
+ // interface,
+ // not
+ // a
+ // classs
+ final static int ACC_ABSTRACT = 0x0400; // Declared
+
+ // a thing not in the source code
+ final static int ACC_SYNTHETIC = 0x1000;
+ final static int ACC_ANNOTATION = 0x2000;
+ final static int ACC_ENUM = 0x4000;
+
+ static protected class Assoc {
+ Assoc(byte tag, int a, int b) {
+ this.tag = tag;
+ this.a = a;
+ this.b = b;
+ }
+
+ byte tag;
+ int a;
+ int b;
+ }
+
+ public class Def {
+ final int access;
+ Set<TypeRef> annotations;
+
+ public Def(int access) {
+ this.access = access;
+ }
+
+ public int getAccess() {
+ return access;
+ }
+
+ public boolean isEnum() {
+ return (access & ACC_ENUM) != 0;
+ }
+
+ public boolean isPublic() {
+ return Modifier.isPublic(access);
+ }
+
+ public boolean isAbstract() {
+ return Modifier.isAbstract(access);
+ }
+
+ public boolean isProtected() {
+ return Modifier.isProtected(access);
+ }
+
+ public boolean isFinal() {
+ return Modifier.isFinal(access) || Clazz.this.isFinal();
+ }
+
+ public boolean isStatic() {
+ return Modifier.isStatic(access);
+ }
+
+ public boolean isPrivate() {
+ return Modifier.isPrivate(access);
+ }
+
+ public boolean isNative() {
+ return Modifier.isNative(access);
+ }
+
+ public boolean isTransient() {
+ return Modifier.isTransient(access);
+ }
+
+ public boolean isVolatile() {
+ return Modifier.isVolatile(access);
+ }
+
+ public boolean isInterface() {
+ return Modifier.isInterface(access);
+ }
+
+ public boolean isSynthetic() {
+ return (access & ACC_SYNTHETIC) != 0;
+ }
+
+ void addAnnotation(Annotation a) {
+ if (annotations == null)
+ annotations = Create.set();
+ annotations.add(analyzer.getTypeRef(a.name.getBinary()));
+ }
+
+ public Collection<TypeRef> getAnnotations() {
+ return annotations;
+ }
+ }
+
+ public class FieldDef extends Def {
+ final String name;
+ final Descriptor descriptor;
+ String signature;
+ Object constant;
+ boolean deprecated;
+
+ public boolean isDeprecated() {
+ return deprecated;
+ }
+
+ public void setDeprecated(boolean deprecated) {
+ this.deprecated = deprecated;
+ }
+
+ public FieldDef(int access, String name, String descriptor) {
+ super(access);
+ this.name = name;
+ this.descriptor = analyzer.getDescriptor(descriptor);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String toString() {
+ return getName();
+ }
+
+ public TypeRef getType() {
+ return descriptor.getType();
+ }
+
+ public TypeRef getContainingClass() {
+ return getClassName();
+ }
+
+ public Descriptor getDescriptor() {
+ return descriptor;
+ }
+
+ public void setConstant(Object o) {
+ this.constant = o;
+ }
+
+ public Object getConstant() {
+ return this.constant;
+ }
+
+ // TODO change to use proper generics
+ public String getGenericReturnType() {
+ String use = descriptor.toString();
+ if (signature != null)
+ use = signature;
+
+ Matcher m = METHOD_DESCRIPTOR.matcher(use);
+ if (!m.matches())
+ throw new IllegalArgumentException("Not a valid method descriptor: " + descriptor);
+
+ String returnType = m.group(2);
+ return objectDescriptorToFQN(returnType);
+ }
+
+ public String getSignature() {
+ return signature;
+ }
+
+ }
+
+ public class MethodDef extends FieldDef {
+ public MethodDef(int access, String method, String descriptor) {
+ super(access, method, descriptor);
+ }
+
+ public boolean isConstructor() {
+ return name.equals("<init>") || name.equals("<clinit>");
+ }
+
+ public TypeRef[] getPrototype() {
+ return descriptor.getPrototype();
+ }
+
+ }
+
+ final static byte SkipTable[] = { //
+ 0, // 0 non existent
+ -1, // 1 CONSTANT_utf8 UTF 8, handled in
+ // method
+ -1, // 2
+ 4, // 3 CONSTANT_Integer
+ 4, // 4 CONSTANT_Float
+ 8, // 5 CONSTANT_Long (index +=2!)
+ 8, // 6 CONSTANT_Double (index +=2!)
+ -1, // 7 CONSTANT_Class
+ 2, // 8 CONSTANT_String
+ 4, // 9 CONSTANT_FieldRef
+ 4, // 10 CONSTANT_MethodRef
+ 4, // 11 CONSTANT_InterfaceMethodRef
+ 4, // 12 CONSTANT_NameAndType
+ -1, // 13 Not defined
+ -1, // 14 Not defined
+ 3, // 15 CONSTANT_MethodHandle
+ 2, // 16 CONSTANT_MethodType
+ -1, // 17 Not defined
+ 4, // 18 CONSTANT_InvokeDynamic
+ };
+
+ boolean hasRuntimeAnnotations;
+ boolean hasClassAnnotations;
+
+ TypeRef className;
+ Object pool[];
+ int intPool[];
+ Set<PackageRef> imports = Create.set();
+ String path;
+ int minor = 0;
+ int major = 0;
+ int innerAccess = -1;
+ int accessx = 0;
+ String sourceFile;
+ Set<TypeRef> xref;
+ Set<TypeRef> annotations;
+ int forName = 0;
+ int class$ = 0;
+ TypeRef[] interfaces;
+ TypeRef zuper;
+ ClassDataCollector cd = null;
+ Resource resource;
+ FieldDef last = null;
+ boolean deprecated;
+ Set<PackageRef> api;
+ final Analyzer analyzer;
+
+
+ public Clazz(Analyzer analyzer, String path, Resource resource) {
+ this.path = path;
+ this.resource = resource;
+ this.analyzer = analyzer;
+ }
+
+ public Set<TypeRef> parseClassFile() throws Exception {
+ return parseClassFileWithCollector(null);
+ }
+
+ public Set<TypeRef> parseClassFile(InputStream in) throws Exception {
+ return parseClassFile(in, null);
+ }
+
+ public Set<TypeRef> parseClassFileWithCollector(ClassDataCollector cd) throws Exception {
+ InputStream in = resource.openInputStream();
+ try {
+ return parseClassFile(in, cd);
+ }
+ finally {
+ in.close();
+ }
+ }
+
+ public Set<TypeRef> parseClassFile(InputStream in, ClassDataCollector cd) throws Exception {
+ DataInputStream din = new DataInputStream(in);
+ try {
+ this.cd = cd;
+ return parseClassFile(din);
+ }
+ finally {
+ cd = null;
+ din.close();
+ }
+ }
+
+ Set<TypeRef> parseClassFile(DataInputStream in) throws Exception {
+ xref = new HashSet<TypeRef>();
+
+ boolean crawl = cd != null; // Crawl the byte code if we have a
+ // collector
+ int magic = in.readInt();
+ if (magic != 0xCAFEBABE)
+ throw new IOException("Not a valid class file (no CAFEBABE header)");
+
+ minor = in.readUnsignedShort(); // minor version
+ major = in.readUnsignedShort(); // major version
+ if (cd != null)
+ cd.version(minor, major);
+ int count = in.readUnsignedShort();
+ pool = new Object[count];
+ intPool = new int[count];
+
+ process: for (int poolIndex = 1; poolIndex < count; poolIndex++) {
+ byte tag = in.readByte();
+ switch (tag) {
+ case 0 :
+ break process;
+ case 1 :
+ constantUtf8(in, poolIndex);
+ break;
+
+ case 3 :
+ constantInteger(in, poolIndex);
+ break;
+
+ case 4 :
+ constantFloat(in, poolIndex);
+ break;
+
+ // For some insane optimization reason are
+ // the long and the double two entries in the
+ // constant pool. See 4.4.5
+ case 5 :
+ constantLong(in, poolIndex);
+ poolIndex++;
+ break;
+
+ case 6 :
+ constantDouble(in, poolIndex);
+ poolIndex++;
+ break;
+
+ case 7 :
+ constantClass(in, poolIndex);
+ break;
+
+ case 8 :
+ constantString(in, poolIndex);
+ break;
+
+ case 10 : // Method ref
+ case 11 : // Interface Method ref
+ methodRef(in, poolIndex);
+ break;
+
+ // Name and Type
+ case 12 :
+ nameAndType(in, poolIndex, tag);
+ break;
+
+ // We get the skip count for each record type
+ // from the SkipTable. This will also automatically
+ // abort when
+ default :
+ if (tag == 2)
+ throw new IOException("Invalid tag " + tag);
+ in.skipBytes(SkipTable[tag]);
+ break;
+ }
+ }
+
+ pool(pool, intPool);
+
+ // All name& type and class constant records contain descriptors we must treat
+ // as references, though not API
+
+ for ( Object o : pool ) {
+ if ( o == null)
+ continue;
+
+ if (o instanceof Assoc && ((Assoc)o).tag ==12 ) {
+ referTo( ((Assoc)o).b, 0); // Descriptor
+ } else if ( o instanceof ClassConstant) {
+ String binaryClassName = (String) pool[((ClassConstant)o).cname];
+ TypeRef typeRef = analyzer.getTypeRef(binaryClassName);
+ referTo( typeRef, 0);
+ }
+ }
+
+ /*
+ * Parse after the constant pool, code thanks to Hans Christian
+ * Falkenberg
+ */
+
+ accessx = in.readUnsignedShort(); // access
+ if ( Modifier.isPublic(accessx))
+ api = new HashSet<PackageRef>();
+
+ int this_class = in.readUnsignedShort();
+ className = analyzer.getTypeRef((String) pool[intPool[this_class]]);
+ referTo(className, Modifier.PUBLIC);
+
+ try {
+
+ if (cd != null) {
+ if (!cd.classStart(accessx, className))
+ return null;
+ }
+
+ int super_class = in.readUnsignedShort();
+ String superName = (String) pool[intPool[super_class]];
+ if (superName != null) {
+ zuper = analyzer.getTypeRef(superName);
+ }
+
+ if (zuper != null) {
+ referTo(zuper, accessx);
+ if (cd != null)
+ cd.extendsClass(zuper);
+ }
+
+ int interfacesCount = in.readUnsignedShort();
+ if (interfacesCount > 0) {
+ interfaces = new TypeRef[interfacesCount];
+ for (int i = 0; i < interfacesCount; i++) {
+ interfaces[i] = analyzer.getTypeRef((String) pool[intPool[in.readUnsignedShort()]]);
+ referTo(interfaces[i],accessx);
+ }
+ if (cd != null)
+ cd.implementsInterfaces(interfaces);
+ }
+
+ int fieldsCount = in.readUnsignedShort();
+ for (int i = 0; i < fieldsCount; i++) {
+ int access_flags = in.readUnsignedShort(); // skip access flags
+ int name_index = in.readUnsignedShort();
+ int descriptor_index = in.readUnsignedShort();
+
+ // Java prior to 1.5 used a weird
+ // static variable to hold the com.X.class
+ // result construct. If it did not find it
+ // it would create a variable class$com$X
+ // that would be used to hold the class
+ // object gotten with Class.forName ...
+ // Stupidly, they did not actively use the
+ // class name for the field type, so bnd
+ // would not see a reference. We detect
+ // this case and add an artificial descriptor
+ String name = pool[name_index].toString(); // name_index
+ if (name.startsWith("class$")) {
+ crawl = true;
+ }
+ if (cd != null)
+ cd.field(last = new FieldDef(access_flags, name, pool[descriptor_index].toString()));
+
+ referTo( descriptor_index, access_flags);
+ doAttributes(in, ElementType.FIELD, false, access_flags);
+ }
+
+ //
+ // Check if we have to crawl the code to find
+ // the ldc(_w) <string constant> invokestatic Class.forName
+ // if so, calculate the method ref index so we
+ // can do this efficiently
+ //
+ if (crawl) {
+ forName = findMethodReference("java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;");
+ class$ = findMethodReference(className.getBinary(), "class$", "(Ljava/lang/String;)Ljava/lang/Class;");
+ } else if (major == 48) {
+ forName = findMethodReference("java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;");
+ if (forName > 0) {
+ crawl = true;
+ class$ = findMethodReference(className.getBinary(), "class$",
+ "(Ljava/lang/String;)Ljava/lang/Class;");
+ }
+ }
+
+ // There are some serious changes in the
+ // class file format. So we do not do any crawling
+ // it has also become less important
+ if (major >= JAVA.OpenJDK7.major)
+ crawl = false;
+
+ //
+ // Handle the methods
+ //
+ int methodCount = in.readUnsignedShort();
+ for (int i = 0; i < methodCount; i++) {
+ int access_flags = in.readUnsignedShort();
+ int name_index = in.readUnsignedShort();
+ int descriptor_index = in.readUnsignedShort();
+ referTo(descriptor_index, access_flags);
+ String name = pool[name_index].toString();
+ String descriptor = pool[descriptor_index].toString();
+ if (cd != null) {
+ MethodDef mdef = new MethodDef(access_flags, name, descriptor);
+ last = mdef;
+ cd.method(mdef);
+ }
+
+ if ("<init>".equals(name)) {
+ doAttributes(in, ElementType.CONSTRUCTOR, crawl, access_flags);
+ } else {
+ doAttributes(in, ElementType.METHOD, crawl, access_flags);
+ }
+ }
+ if (cd != null)
+ cd.memberEnd();
+
+ doAttributes(in, ElementType.TYPE, false, accessx);
+
+ //
+ // Parse all the descriptors we found
+ //
+
+ Set<TypeRef> xref = this.xref;
+ reset();
+ return xref;
+ }
+ finally {
+ if (cd != null)
+ cd.classEnd();
+ }
+ }
+
+ private void constantFloat(DataInputStream in, int poolIndex) throws IOException {
+ if (cd != null)
+ pool[poolIndex] = in.readFloat(); // ALU
+ else
+ in.skipBytes(4);
+ }
+
+ private void constantInteger(DataInputStream in, int poolIndex) throws IOException {
+ intPool[poolIndex] = in.readInt();
+ if (cd != null)
+ pool[poolIndex] = intPool[poolIndex];
+ }
+
+ protected void pool(@SuppressWarnings("unused") Object[] pool, @SuppressWarnings("unused") int[] intPool) {}
+
+ /**
+ * @param in
+ * @param poolIndex
+ * @param tag
+ * @throws IOException
+ */
+ protected void nameAndType(DataInputStream in, int poolIndex, byte tag) throws IOException {
+ int name_index = in.readUnsignedShort();
+ int descriptor_index = in.readUnsignedShort();
+ pool[poolIndex] = new Assoc(tag, name_index, descriptor_index);
+ }
+
+ /**
+ * @param in
+ * @param poolIndex
+ * @param tag
+ * @throws IOException
+ */
+ private void methodRef(DataInputStream in, int poolIndex) throws IOException {
+ int class_index = in.readUnsignedShort();
+ int name_and_type_index = in.readUnsignedShort();
+ pool[poolIndex] = new Assoc((byte) 10, class_index, name_and_type_index);
+ }
+
+ /**
+ * @param in
+ * @param poolIndex
+ * @throws IOException
+ */
+ private void constantString(DataInputStream in, int poolIndex) throws IOException {
+ int string_index = in.readUnsignedShort();
+ intPool[poolIndex] = string_index;
+ }
+
+ /**
+ * @param in
+ * @param poolIndex
+ * @throws IOException
+ */
+ protected void constantClass(DataInputStream in, int poolIndex) throws IOException {
+ int class_index = in.readUnsignedShort();
+ intPool[poolIndex] = class_index;
+ ClassConstant c = new ClassConstant(class_index);
+ pool[poolIndex] = c;
+ }
+
+ /**
+ * @param in
+ * @throws IOException
+ */
+ protected void constantDouble(DataInputStream in, int poolIndex) throws IOException {
+ if (cd != null)
+ pool[poolIndex] = in.readDouble();
+ else
+ in.skipBytes(8);
+ }
+
+ /**
+ * @param in
+ * @throws IOException
+ */
+ protected void constantLong(DataInputStream in, int poolIndex) throws IOException {
+ if (cd != null) {
+ pool[poolIndex] = in.readLong();
+ } else
+ in.skipBytes(8);
+ }
+
+ /**
+ * @param in
+ * @param poolIndex
+ * @throws IOException
+ */
+ protected void constantUtf8(DataInputStream in, int poolIndex) throws IOException {
+ // CONSTANT_Utf8
+
+ String name = in.readUTF();
+ pool[poolIndex] = name;
+ }
+
+ /**
+ * Find a method reference in the pool that points to the given class,
+ * methodname and descriptor.
+ *
+ * @param clazz
+ * @param methodname
+ * @param descriptor
+ * @return index in constant pool
+ */
+ private int findMethodReference(String clazz, String methodname, String descriptor) {
+ for (int i = 1; i < pool.length; i++) {
+ if (pool[i] instanceof Assoc) {
+ Assoc methodref = (Assoc) pool[i];
+ if (methodref.tag == 10) {
+ // Method ref
+ int class_index = methodref.a;
+ int class_name_index = intPool[class_index];
+ if (clazz.equals(pool[class_name_index])) {
+ int name_and_type_index = methodref.b;
+ Assoc name_and_type = (Assoc) pool[name_and_type_index];
+ if (name_and_type.tag == 12) {
+ // Name and Type
+ int name_index = name_and_type.a;
+ int type_index = name_and_type.b;
+ if (methodname.equals(pool[name_index])) {
+ if (descriptor.equals(pool[type_index])) {
+ return i;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Called for each attribute in the class, field, or method.
+ *
+ * @param in
+ * The stream
+ * @param access_flags
+ * @throws Exception
+ */
+ private void doAttributes(DataInputStream in, ElementType member, boolean crawl, int access_flags) throws Exception {
+ int attributesCount = in.readUnsignedShort();
+ for (int j = 0; j < attributesCount; j++) {
+ // skip name CONSTANT_Utf8 pointer
+ doAttribute(in, member, crawl, access_flags);
+ }
+ }
+
+ /**
+ * Process a single attribute, if not recognized, skip it.
+ *
+ * @param in
+ * the data stream
+ * @param access_flags
+ * @throws Exception
+ */
+ private void doAttribute(DataInputStream in, ElementType member, boolean crawl, int access_flags) throws Exception {
+ int attribute_name_index = in.readUnsignedShort();
+ String attributeName = (String) pool[attribute_name_index];
+ long attribute_length = in.readInt();
+ attribute_length &= 0xFFFFFFFF;
+ if ("Deprecated".equals(attributeName)) {
+ if (cd != null)
+ cd.deprecated();
+ } else if ("RuntimeVisibleAnnotations".equals(attributeName))
+ doAnnotations(in, member, RetentionPolicy.RUNTIME);
+ else if ("RuntimeVisibleParameterAnnotations".equals(attributeName))
+ doParameterAnnotations(in, member, RetentionPolicy.RUNTIME);
+ else if ("RuntimeInvisibleAnnotations".equals(attributeName))
+ doAnnotations(in, member, RetentionPolicy.CLASS);
+ else if ("RuntimeInvisibleParameterAnnotations".equals(attributeName))
+ doParameterAnnotations(in, member, RetentionPolicy.CLASS);
+ else if ("InnerClasses".equals(attributeName))
+ doInnerClasses(in);
+ else if ("EnclosingMethod".equals(attributeName))
+ doEnclosingMethod(in);
+ else if ("SourceFile".equals(attributeName))
+ doSourceFile(in);
+ else if ("Code".equals(attributeName) && crawl)
+ doCode(in);
+ else if ("Signature".equals(attributeName))
+ doSignature(in, member, access_flags);
+ else if ("ConstantValue".equals(attributeName))
+ doConstantValue(in);
+ else {
+ if (attribute_length > 0x7FFFFFFF) {
+ throw new IllegalArgumentException("Attribute > 2Gb");
+ }
+ in.skipBytes((int) attribute_length);
+ }
+ }
+
+ /**
+ * <pre>
+ * EnclosingMethod_attribute {
+ * u2 attribute_name_index;
+ * u4 attribute_length;
+ * u2 class_index
+ * u2 method_index;
+ * }
+ * </pre>
+ *
+ * @param in
+ * @throws IOException
+ */
+ private void doEnclosingMethod(DataInputStream in) throws IOException {
+ int cIndex = in.readShort();
+ int mIndex = in.readShort();
+
+ if (cd != null) {
+ int nameIndex = intPool[cIndex];
+ TypeRef cName = analyzer.getTypeRef((String) pool[nameIndex]);
+
+ String mName = null;
+ String mDescriptor = null;
+
+ if (mIndex != 0) {
+ Assoc nameAndType = (Assoc) pool[mIndex];
+ mName = (String) pool[nameAndType.a];
+ mDescriptor = (String) pool[nameAndType.b];
+ }
+ cd.enclosingMethod(cName, mName, mDescriptor);
+ }
+ }
+
+ /**
+ * <pre>
+ * InnerClasses_attribute {
+ * u2 attribute_name_index;
+ * u4 attribute_length;
+ * u2 number_of_classes; {
+ * u2 inner_class_info_index;
+ * u2 outer_class_info_index;
+ * u2 inner_name_index;
+ * u2 inner_class_access_flags;
+ * } classes[number_of_classes];
+ * }
+ * </pre>
+ *
+ * @param in
+ * @throws Exception
+ */
+ private void doInnerClasses(DataInputStream in) throws Exception {
+ int number_of_classes = in.readShort();
+ for (int i = 0; i < number_of_classes; i++) {
+ int inner_class_info_index = in.readShort();
+ int outer_class_info_index = in.readShort();
+ int inner_name_index = in.readShort();
+ int inner_class_access_flags = in.readShort() & 0xFFFF;
+
+ if (cd != null) {
+ TypeRef innerClass = null;
+ TypeRef outerClass = null;
+ String innerName = null;
+
+ if (inner_class_info_index != 0) {
+ int nameIndex = intPool[inner_class_info_index];
+ innerClass = analyzer.getTypeRef((String) pool[nameIndex]);
+ }
+
+ if (outer_class_info_index != 0) {
+ int nameIndex = intPool[outer_class_info_index];
+ outerClass = analyzer.getTypeRef((String) pool[nameIndex]);
+ }
+
+ if (inner_name_index != 0)
+ innerName = (String) pool[inner_name_index];
+
+ cd.innerClass(innerClass, outerClass, innerName, inner_class_access_flags);
+ }
+ }
+ }
+
+ /**
+ * Handle a signature
+ *
+ * <pre>
+ * Signature_attribute {
+ * u2 attribute_name_index;
+ * u4 attribute_length;
+ * u2 signature_index;
+ * }
+ * </pre>
+ *
+ * @param member
+ * @param access_flags
+ */
+
+ void doSignature(DataInputStream in, ElementType member, int access_flags) throws IOException {
+ int signature_index = in.readUnsignedShort();
+ String signature = (String) pool[signature_index];
+
+ parseDescriptor(signature, access_flags);
+
+ if (last != null)
+ last.signature = signature;
+
+ if (cd != null)
+ cd.signature(signature);
+ }
+
+ /**
+ * Handle a constant value call the data collector with it
+ */
+ void doConstantValue(DataInputStream in) throws IOException {
+ int constantValue_index = in.readUnsignedShort();
+ if (cd == null)
+ return;
+
+ Object object = pool[constantValue_index];
+ if (object == null)
+ object = pool[intPool[constantValue_index]];
+
+ last.constant = object;
+ cd.constant(object);
+ }
+
+ /**
+ * <pre>
+ * Code_attribute {
+ * u2 attribute_name_index;
+ * u4 attribute_length;
+ * u2 max_stack;
+ * u2 max_locals;
+ * u4 code_length;
+ * u1 code[code_length];
+ * u2 exception_table_length;
+ * { u2 start_pc;
+ * u2 end_pc;
+ * u2 handler_pc;
+ * u2 catch_type;
+ * } exception_table[exception_table_length];
+ * u2 attributes_count;
+ * attribute_info attributes[attributes_count];
+ * }
+ * </pre>
+ *
+ * @param in
+ * @param pool
+ * @throws Exception
+ */
+ private void doCode(DataInputStream in) throws Exception {
+ /* int max_stack = */in.readUnsignedShort();
+ /* int max_locals = */in.readUnsignedShort();
+ int code_length = in.readInt();
+ byte code[] = new byte[code_length];
+ in.readFully(code);
+ crawl(code);
+ int exception_table_length = in.readUnsignedShort();
+ in.skipBytes(exception_table_length * 8);
+ doAttributes(in, ElementType.METHOD, false, 0);
+ }
+
+ /**
+ * We must find Class.forName references ...
+ *
+ * @param code
+ */
+ protected void crawl(byte[] code) {
+ ByteBuffer bb = ByteBuffer.wrap(code);
+ bb.order(ByteOrder.BIG_ENDIAN);
+ int lastReference = -1;
+
+ while (bb.remaining() > 0) {
+ int instruction = 0xFF & bb.get();
+ switch (instruction) {
+ case OpCodes.ldc :
+ lastReference = 0xFF & bb.get();
+ break;
+
+ case OpCodes.ldc_w :
+ lastReference = 0xFFFF & bb.getShort();
+ break;
+
+ case OpCodes.invokespecial : {
+ int mref = 0xFFFF & bb.getShort();
+ if (cd != null)
+ getMethodDef(0, mref);
+ break;
+ }
+
+ case OpCodes.invokevirtual : {
+ int mref = 0xFFFF & bb.getShort();
+ if (cd != null)
+ getMethodDef(0, mref);
+ break;
+ }
+
+ case OpCodes.invokeinterface : {
+ int mref = 0xFFFF & bb.getShort();
+ if (cd != null)
+ getMethodDef(0, mref);
+ break;
+ }
+
+ case OpCodes.invokestatic : {
+ int methodref = 0xFFFF & bb.getShort();
+ if (cd != null)
+ getMethodDef(0, methodref);
+
+ if ((methodref == forName || methodref == class$) && lastReference != -1
+ && pool[intPool[lastReference]] instanceof String) {
+ String fqn = (String) pool[intPool[lastReference]];
+ if (!fqn.equals("class") && fqn.indexOf('.') > 0) {
+ TypeRef clazz = analyzer.getTypeRefFromFQN(fqn);
+ referTo(clazz, 0);
+ }
+ lastReference = -1;
+ }
+ break;
+ }
+
+ case OpCodes.tableswitch :
+ // Skip to place divisible by 4
+ while ((bb.position() & 0x3) != 0)
+ bb.get();
+ /* int deflt = */
+ bb.getInt();
+ int low = bb.getInt();
+ int high = bb.getInt();
+ try {
+ bb.position(bb.position() + (high - low + 1) * 4);
+ }
+ catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ lastReference = -1;
+ break;
+
+ case OpCodes.lookupswitch :
+ // Skip to place divisible by 4
+ while ((bb.position() & 0x3) != 0)
+ bb.get();
+ /* deflt = */
+ bb.getInt();
+ int npairs = bb.getInt();
+ bb.position(bb.position() + npairs * 8);
+ lastReference = -1;
+ break;
+
+ default :
+ lastReference = -1;
+ bb.position(bb.position() + OpCodes.OFFSETS[instruction]);
+ }
+ }
+ }
+
+ private void doSourceFile(DataInputStream in) throws IOException {
+ int sourcefile_index = in.readUnsignedShort();
+ this.sourceFile = pool[sourcefile_index].toString();
+ }
+
+ private void doParameterAnnotations(DataInputStream in, ElementType member, RetentionPolicy policy)
+ throws IOException {
+ int num_parameters = in.readUnsignedByte();
+ for (int p = 0; p < num_parameters; p++) {
+ if (cd != null)
+ cd.parameter(p);
+ doAnnotations(in, member, policy);
+ }
+ }
+
+ private void doAnnotations(DataInputStream in, ElementType member, RetentionPolicy policy) throws IOException {
+ int num_annotations = in.readUnsignedShort(); // # of annotations
+ for (int a = 0; a < num_annotations; a++) {
+ if (cd == null)
+ doAnnotation(in, member, policy, false);
+ else {
+ Annotation annotion = doAnnotation(in, member, policy, true);
+ cd.annotation(annotion);
+ }
+ }
+ }
+
+ private Annotation doAnnotation(DataInputStream in, ElementType member, RetentionPolicy policy, boolean collect)
+ throws IOException {
+ int type_index = in.readUnsignedShort();
+ if (annotations == null)
+ annotations = new HashSet<TypeRef>();
+
+ TypeRef tr = analyzer.getTypeRef(pool[type_index].toString());
+ annotations.add(tr);
+
+ if (policy == RetentionPolicy.RUNTIME) {
+ referTo(type_index,0);
+ hasRuntimeAnnotations = true;
+ } else {
+ hasClassAnnotations = true;
+ }
+ TypeRef name = analyzer.getTypeRef((String) pool[type_index]);
+ int num_element_value_pairs = in.readUnsignedShort();
+ Map<String,Object> elements = null;
+ for (int v = 0; v < num_element_value_pairs; v++) {
+ int element_name_index = in.readUnsignedShort();
+ String element = (String) pool[element_name_index];
+ Object value = doElementValue(in, member, policy, collect);
+ if (collect) {
+ if (elements == null)
+ elements = new LinkedHashMap<String,Object>();
+ elements.put(element, value);
+ }
+ }
+ if (collect)
+ return new Annotation(name, elements, member, policy);
+ return null;
+ }
+
+ private Object doElementValue(DataInputStream in, ElementType member, RetentionPolicy policy, boolean collect)
+ throws IOException {
+ char tag = (char) in.readUnsignedByte();
+ switch (tag) {
+ case 'B' : // Byte
+ case 'C' : // Character
+ case 'I' : // Integer
+ case 'S' : // Short
+ int const_value_index = in.readUnsignedShort();
+ return intPool[const_value_index];
+
+ case 'D' : // Double
+ case 'F' : // Float
+ case 's' : // String
+ case 'J' : // Long
+ const_value_index = in.readUnsignedShort();
+ return pool[const_value_index];
+
+ case 'Z' : // Boolean
+ const_value_index = in.readUnsignedShort();
+ return pool[const_value_index] == null || pool[const_value_index].equals(0) ? false : true;
+
+ case 'e' : // enum constant
+ int type_name_index = in.readUnsignedShort();
+ if (policy == RetentionPolicy.RUNTIME)
+ referTo(type_name_index,0);
+ int const_name_index = in.readUnsignedShort();
+ return pool[const_name_index];
+
+ case 'c' : // Class
+ int class_info_index = in.readUnsignedShort();
+ if (policy == RetentionPolicy.RUNTIME)
+ referTo(class_info_index,0);
+ return pool[class_info_index];
+
+ case '@' : // Annotation type
+ return doAnnotation(in, member, policy, collect);
+
+ case '[' : // Array
+ int num_values = in.readUnsignedShort();
+ Object[] result = new Object[num_values];
+ for (int i = 0; i < num_values; i++) {
+ result[i] = doElementValue(in, member, policy, collect);
+ }
+ return result;
+
+ default :
+ throw new IllegalArgumentException("Invalid value for Annotation ElementValue tag " + tag);
+ }
+ }
+
+ /**
+ * Add a new package reference.
+ *
+ * @param packageRef
+ * A '.' delimited package name
+ */
+ void referTo(TypeRef typeRef, int modifiers) {
+ if (xref != null)
+ xref.add(typeRef);
+ if (typeRef.isPrimitive())
+ return;
+
+ PackageRef packageRef = typeRef.getPackageRef();
+ if (packageRef.isPrimitivePackage())
+ return;
+
+ imports.add(packageRef);
+
+ if ( api != null && (Modifier.isPublic(modifiers)||Modifier.isProtected(modifiers)))
+ api.add(packageRef);
+ }
+
+ void referTo( int index, int modifiers) {
+ String descriptor = (String) pool[index];
+ parseDescriptor(descriptor, modifiers);
+ }
+
+ /**
+ * This method parses a descriptor and adds the package of the descriptor to
+ * the referenced packages. The syntax of the descriptor is:
+ *
+ * <pre>
+ * descriptor ::= ( '(' reference * ')' )? reference
+ * reference ::= 'L' classname ( '<' references '>' )? ';' | 'B' | 'Z' | ... | '+' | '-' | '['
+ * </pre>
+ *
+ * This methods uses heavy recursion to parse the descriptor and a roving
+ * pointer to limit the creation of string objects.
+ *
+ * @param descriptor
+ * The to be parsed descriptor
+ * @param rover
+ * The pointer to start at
+ */
+
+ public void parseDescriptor(String descriptor, int modifiers) {
+ // Some descriptors are weird, they start with a generic
+ // declaration that contains ':', not sure what they mean ...
+ int rover = 0;
+ if (descriptor.charAt(0) == '<') {
+ rover = parseFormalTypeParameters(descriptor, rover, modifiers);
+ }
+
+ if (descriptor.charAt(rover) == '(') {
+ rover = parseReferences(descriptor, rover + 1, ')', modifiers);
+ rover++;
+ }
+ parseReferences(descriptor, rover, (char) 0, modifiers);
+ }
+
+ /**
+ * Parse a sequence of references. A sequence ends with a given character or
+ * when the string ends.
+ *
+ * @param descriptor
+ * The whole descriptor.
+ * @param rover
+ * The index in the descriptor
+ * @param delimiter
+ * The end character or 0
+ * @return the last index processed, one character after the delimeter
+ */
+ int parseReferences(String descriptor, int rover, char delimiter, int modifiers) {
+ int r = rover;
+ while (r < descriptor.length() && descriptor.charAt(r) != delimiter) {
+ r = parseReference(descriptor, r, modifiers);
+ }
+ return r;
+ }
+
+ /**
+ * Parse a single reference. This can be a single character or an object
+ * reference when it starts with 'L'.
+ *
+ * @param descriptor
+ * The descriptor
+ * @param rover
+ * The place to start
+ * @return The return index after the reference
+ */
+ int parseReference(String descriptor, int rover, int modifiers) {
+ int r = rover;
+ char c = descriptor.charAt(r);
+ while (c == '[')
+ c = descriptor.charAt(++r);
+
+ if (c == '<') {
+ r = parseReferences(descriptor, r + 1, '>', modifiers);
+ } else if (c == 'T') {
+ // Type variable name
+ r++;
+ while (descriptor.charAt(r) != ';')
+ r++;
+ } else if (c == 'L') {
+ StringBuilder sb = new StringBuilder();
+ r++;
+ while ((c = descriptor.charAt(r)) != ';') {
+ if (c == '<') {
+ r = parseReferences(descriptor, r + 1, '>', modifiers);
+ } else
+ sb.append(c);
+ r++;
+ }
+ TypeRef ref = analyzer.getTypeRef(sb.toString());
+ if (cd != null)
+ cd.addReference(ref);
+
+ referTo(ref, modifiers);
+ } else {
+ if ("+-*BCDFIJSZV".indexOf(c) < 0)
+ ;// System.err.println("Should not skip: " + c);
+ }
+
+ // this skips a lot of characters
+ // [, *, +, -, B, etc.
+
+ return r + 1;
+ }
+
+ /**
+ * FormalTypeParameters
+ *
+ * @param descriptor
+ * @param index
+ * @return
+ */
+ private int parseFormalTypeParameters(String descriptor, int index, int modifiers) {
+ index++;
+ while (descriptor.charAt(index) != '>') {
+ // Skip IDENTIFIER
+ index = descriptor.indexOf(':', index) + 1;
+ if (index == 0)
+ throw new IllegalArgumentException("Expected IDENTIFIER: " + descriptor);
+
+ // ClassBound? InterfaceBounds
+
+ char c = descriptor.charAt(index);
+
+ // Class Bound?
+ if (c == 'L' || c == 'T') {
+ index = parseReference(descriptor, index, modifiers); // class reference
+ c = descriptor.charAt(index);
+ }
+
+ // Interface Bounds
+ while (c == ':') {
+ index++;
+ index = parseReference(descriptor, index, modifiers);
+ c = descriptor.charAt(index);
+ } // for each interface
+
+ } // for each formal parameter
+ return index + 1; // skip >
+ }
+
+ public Set<PackageRef> getReferred() {
+ return imports;
+ }
+
+ public String getAbsolutePath() {
+ return path;
+ }
+
+ public String getSourceFile() {
+ return sourceFile;
+ }
+
+ /**
+ * .class construct for different compilers sun 1.1 Detect static variable
+ * class$com$acme$MyClass 1.2 " 1.3 " 1.4 " 1.5 ldc_w (class) 1.6 " eclipse
+ * 1.1 class$0, ldc (string), invokestatic Class.forName 1.2 " 1.3 " 1.5 ldc
+ * (class) 1.6 " 1.5 and later is not an issue, sun pre 1.5 is easy to
+ * detect the static variable that decodes the class name. For eclipse, the
+ * class$0 gives away we have a reference encoded in a string.
+ * compilerversions/compilerversions.jar contains test versions of all
+ * versions/compilers.
+ */
+
+ public void reset() {
+ pool = null;
+ intPool = null;
+ xref = null;
+ }
+
+ public boolean is(QUERY query, Instruction instr, Analyzer analyzer) throws Exception {
+ switch (query) {
+ case ANY :
+ return true;
+
+ case NAMED :
+ if (instr.matches(getClassName().getDottedOnly()))
+ return !instr.isNegated();
+ return false;
+
+ case VERSION :
+ String v = major + "." + minor;
+ if (instr.matches(v))
+ return !instr.isNegated();
+ return false;
+
+ case IMPLEMENTS :
+ for (int i = 0; interfaces != null && i < interfaces.length; i++) {
+ if (instr.matches(interfaces[i].getDottedOnly()))
+ return !instr.isNegated();
+ }
+ break;
+
+ case EXTENDS :
+ if (zuper == null)
+ return false;
+
+ if (instr.matches(zuper.getDottedOnly()))
+ return !instr.isNegated();
+ break;
+
+ case PUBLIC :
+ return Modifier.isPublic(accessx);
+
+ case CONCRETE :
+ return !Modifier.isAbstract(accessx);
+
+ case ANNOTATED :
+ if (annotations == null)
+ return false;
+
+ for (TypeRef annotation : annotations) {
+ if (instr.matches(annotation.getFQN()))
+ return !instr.isNegated();
+ }
+
+ return false;
+
+ case RUNTIMEANNOTATIONS :
+ return hasClassAnnotations;
+ case CLASSANNOTATIONS :
+ return hasClassAnnotations;
+
+ case ABSTRACT :
+ return Modifier.isAbstract(accessx);
+
+ case IMPORTS :
+ for (PackageRef imp : imports) {
+ if (instr.matches(imp.getFQN()))
+ return !instr.isNegated();
+ }
+ }
+
+ if (zuper == null)
+ return false;
+
+ Clazz clazz = analyzer.findClass(zuper);
+ if (clazz == null)
+ return false;
+
+ return clazz.is(query, instr, analyzer);
+ }
+
+ public String toString() {
+ return className.getFQN();
+ }
+
+ /**
+ * Called when crawling the byte code and a method reference is found
+ */
+ void getMethodDef(int access, int methodRefPoolIndex) {
+ if (methodRefPoolIndex == 0)
+ return;
+
+ Object o = pool[methodRefPoolIndex];
+ if (o != null && o instanceof Assoc) {
+ Assoc assoc = (Assoc) o;
+ if (assoc.tag == 10) {
+ int string_index = intPool[assoc.a];
+ TypeRef className = analyzer.getTypeRef((String) pool[string_index]);
+ int name_and_type_index = assoc.b;
+ Assoc name_and_type = (Assoc) pool[name_and_type_index];
+ if (name_and_type.tag == 12) {
+ // Name and Type
+ int name_index = name_and_type.a;
+ int type_index = name_and_type.b;
+ String method = (String) pool[name_index];
+ String descriptor = (String) pool[type_index];
+ cd.referenceMethod(access, className, method, descriptor);
+ } else
+ throw new IllegalArgumentException(
+ "Invalid class file (or parsing is wrong), assoc is not type + name (12)");
+ } else
+ throw new IllegalArgumentException(
+ "Invalid class file (or parsing is wrong), Assoc is not method ref! (10)");
+ } else
+ throw new IllegalArgumentException("Invalid class file (or parsing is wrong), Not an assoc at a method ref");
+ }
+
+ public boolean isPublic() {
+ return Modifier.isPublic(accessx);
+ }
+
+ public boolean isProtected() {
+ return Modifier.isProtected(accessx);
+ }
+
+ public boolean isEnum() {
+ return zuper != null && zuper.getBinary().equals("java/lang/Enum");
+ }
+
+ public JAVA getFormat() {
+ return JAVA.format(major);
+
+ }
+
+ public static String objectDescriptorToFQN(String string) {
+ if (string.startsWith("L") && string.endsWith(";"))
+ return string.substring(1, string.length() - 1).replace('/', '.');
+
+ switch (string.charAt(0)) {
+ case 'V' :
+ return "void";
+ case 'B' :
+ return "byte";
+ case 'C' :
+ return "char";
+ case 'I' :
+ return "int";
+ case 'S' :
+ return "short";
+ case 'D' :
+ return "double";
+ case 'F' :
+ return "float";
+ case 'J' :
+ return "long";
+ case 'Z' :
+ return "boolean";
+ case '[' : // Array
+ return objectDescriptorToFQN(string.substring(1)) + "[]";
+ }
+ throw new IllegalArgumentException("Invalid type character in descriptor " + string);
+ }
+
+ public static String unCamel(String id) {
+ StringBuilder out = new StringBuilder();
+ for (int i = 0; i < id.length(); i++) {
+ char c = id.charAt(i);
+ if (c == '_' || c == '$' || c == '.') {
+ if (out.length() > 0 && !Character.isWhitespace(out.charAt(out.length() - 1)))
+ out.append(' ');
+ continue;
+ }
+
+ int n = i;
+ while (n < id.length() && Character.isUpperCase(id.charAt(n))) {
+ n++;
+ }
+ if (n == i)
+ out.append(id.charAt(i));
+ else {
+ boolean tolower = (n - i) == 1;
+ if (i > 0 && !Character.isWhitespace(out.charAt(out.length() - 1)))
+ out.append(' ');
+
+ for (; i < n;) {
+ if (tolower)
+ out.append(Character.toLowerCase(id.charAt(i)));
+ else
+ out.append(id.charAt(i));
+ i++;
+ }
+ i--;
+ }
+ }
+ if (id.startsWith("."))
+ out.append(" *");
+ out.replace(0, 1, Character.toUpperCase(out.charAt(0)) + "");
+ return out.toString();
+ }
+
+ public boolean isInterface() {
+ return Modifier.isInterface(accessx);
+ }
+
+ public boolean isAbstract() {
+ return Modifier.isAbstract(accessx);
+ }
+
+ public int getAccess() {
+ if (innerAccess == -1)
+ return accessx;
+ return innerAccess;
+ }
+
+ public TypeRef getClassName() {
+ return className;
+ }
+
+ /**
+ * To provide an enclosing instance
+ *
+ * @param access
+ * @param name
+ * @param descriptor
+ * @return
+ */
+ public MethodDef getMethodDef(int access, String name, String descriptor) {
+ return new MethodDef(access, name, descriptor);
+ }
+
+ public TypeRef getSuper() {
+ return zuper;
+ }
+
+ public String getFQN() {
+ return className.getFQN();
+ }
+
+ public TypeRef[] getInterfaces() {
+ return interfaces;
+ }
+
+ public void setInnerAccess(int access) {
+ innerAccess = access;
+ }
+
+ public boolean isFinal() {
+ return Modifier.isFinal(accessx);
+ }
+
+ public void setDeprecated(boolean b) {
+ deprecated = b;
+ }
+
+ public boolean isDeprecated() {
+ return deprecated;
+ }
+
+ public boolean isAnnotation() {
+ return (accessx & ACC_ANNOTATION) != 0;
+ }
+
+ public Set<PackageRef> getAPIUses() {
+ if ( api == null)
+ return Collections.emptySet();
+ return api;
+ }
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Clazz.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Clazz.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Clazz.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CombinedResource.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CombinedResource.java?rev=1362033&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CombinedResource.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CombinedResource.java Mon Jul 16 13:43:38 2012
@@ -0,0 +1,33 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.util.*;
+
+public class CombinedResource extends WriteResource {
+ final List<Resource> resources = new ArrayList<Resource>();
+ long lastModified = 0;
+
+ @Override
+ public void write(final OutputStream out) throws IOException, Exception {
+ OutputStream unclosable = new FilterOutputStream(out) {
+ public void close() {
+ // Ignore
+ }
+ };
+ for (Resource r : resources) {
+ r.write(unclosable);
+ unclosable.flush();
+ }
+ }
+
+ @Override
+ public long lastModified() {
+ return lastModified;
+ }
+
+ public void addResource(Resource r) {
+ lastModified = Math.max(lastModified, r.lastModified());
+ resources.add(r);
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CombinedResource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CombinedResource.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CommandResource.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CommandResource.java?rev=1362033&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CommandResource.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CommandResource.java Mon Jul 16 13:43:38 2012
@@ -0,0 +1,53 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+
+import aQute.libg.command.*;
+
+public class CommandResource extends WriteResource {
+ final long lastModified;
+ final Builder domain;
+ final String command;
+
+ public CommandResource(String command, Builder domain, long lastModified) {
+ this.lastModified = lastModified;
+ this.domain = domain;
+ this.command = command;
+ }
+
+ @Override
+ public void write(OutputStream out) throws IOException, Exception {
+ StringBuilder errors = new StringBuilder();
+ StringBuilder stdout = new StringBuilder();
+ try {
+ domain.trace("executing command %s", command);
+ Command cmd = new Command("sh");
+ cmd.inherit();
+ String oldpath = cmd.var("PATH");
+
+ String path = domain.getProperty("-PATH");
+ if (path != null) {
+ path = path.replaceAll("\\s*,\\s*", File.pathSeparator);
+ path = path.replaceAll("\\$\\{@\\}", oldpath);
+ cmd.var("PATH", path);
+ domain.trace("PATH: %s", path);
+ }
+ OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
+ int result = cmd.execute(command, stdout, errors);
+ osw.append(stdout);
+ osw.flush();
+ if (result != 0) {
+ domain.error("executing command failed %s %s", command, stdout + "\n" + errors);
+ }
+ }
+ catch (Exception e) {
+ domain.error("executing command failed %s %s", command, e.getMessage());
+ }
+ }
+
+ @Override
+ public long lastModified() {
+ return lastModified;
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CommandResource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/CommandResource.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Constants.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Constants.java?rev=1362033&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Constants.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Constants.java Mon Jul 16 13:43:38 2012
@@ -0,0 +1,313 @@
+package aQute.bnd.osgi;
+
+import java.nio.charset.*;
+import java.util.*;
+import java.util.regex.*;
+
+public interface Constants {
+ /*
+ * Defined in OSGi
+ */
+ /**
+ * @syntax Bundle-ActivationPolicy ::= policy ( â;â directive )* policy ::=
+ * âlazyâ
+ */
+ String BND_ADDXMLTOTEST = "Bnd-AddXMLToTest";
+ String BUNDLE_ACTIVATIONPOLICY = "Bundle-ActivationPolicy";
+ String BUNDLE_ACTIVATOR = "Bundle-Activator";
+ String BUNDLE_BLUEPRINT = "Bundle-Copyright";
+ String BUNDLE_CATEGORY = "Bundle-Category";
+ String BUNDLE_CLASSPATH = "Bundle-ClassPath";
+ String BUNDLE_CONTACTADDRESS = "Bundle-ContactAddress";
+ String BUNDLE_COPYRIGHT = "Bundle-Copyright";
+ String BUNDLE_DESCRIPTION = "Bundle-Description";
+ String BUNDLE_DOCURL = "Bundle-DocURL";
+ String BUNDLE_ICON = "Bundle-Icon";
+ String BUNDLE_LICENSE = "Bundle-License";
+ String BUNDLE_LOCALIZATION = "Bundle-Localization";
+ String BUNDLE_MANIFESTVERSION = "Bundle-ManifestVersion";
+ String BUNDLE_NAME = "Bundle-Name";
+ String BUNDLE_NATIVECODE = "Bundle-NativeCode";
+ String BUNDLE_REQUIREDEXECUTIONENVIRONMENT = "Bundle-RequiredExecutionEnvironment";
+ String BUNDLE_SYMBOLICNAME = "Bundle-SymbolicName";
+ String BUNDLE_UPDATELOCATION = "Bundle-UpdateLocation";
+ String BUNDLE_VENDOR = "Bundle-Vendor";
+ String BUNDLE_VERSION = "Bundle-Version";
+ String DYNAMICIMPORT_PACKAGE = "DynamicImport-Package";
+ String EXPORT_PACKAGE = "Export-Package";
+ String EXPORT_SERVICE = "Export-Service";
+ String FRAGMENT_HOST = "Fragment-Host";
+ String IMPORT_PACKAGE = "Import-Package";
+ String IMPORT_SERVICE = "Import-Service";
+ String PROVIDE_CAPABILITY = "Provide-Capability";
+ String REQUIRE_BUNDLE = "Require-Bundle";
+ String REQUIRE_CAPABILITY = "Require-Capability";
+ String SERVICE_COMPONENT = "Service-Component";
+
+ String PRIVATE_PACKAGE = "Private-Package";
+ String IGNORE_PACKAGE = "Ignore-Package";
+ String INCLUDE_RESOURCE = "Include-Resource";
+ String CONDITIONAL_PACKAGE = "Conditional-Package";
+ String BND_LASTMODIFIED = "Bnd-LastModified";
+ String CREATED_BY = "Created-By";
+ String TOOL = "Tool";
+ String TESTCASES = "Test-Cases";
+ /**
+ * @deprecated Use {@link Constants#TESTCASES}.
+ */
+ @Deprecated
+ String TESTSUITES = "Test-Suites";
+ String SIGNATURE_TEST = "-signaturetest";
+
+ String headers[] = {
+ BUNDLE_ACTIVATOR, BUNDLE_CONTACTADDRESS, BUNDLE_COPYRIGHT, BUNDLE_DESCRIPTION, BUNDLE_DOCURL,
+ BUNDLE_LOCALIZATION, BUNDLE_NATIVECODE, BUNDLE_VENDOR, BUNDLE_VERSION, BUNDLE_LICENSE, BUNDLE_CLASSPATH,
+ SERVICE_COMPONENT, EXPORT_PACKAGE, IMPORT_PACKAGE, BUNDLE_LOCALIZATION, BUNDLE_MANIFESTVERSION,
+ BUNDLE_NAME, BUNDLE_NATIVECODE, BUNDLE_REQUIREDEXECUTIONENVIRONMENT, BUNDLE_SYMBOLICNAME, BUNDLE_VERSION,
+ FRAGMENT_HOST, PRIVATE_PACKAGE, IGNORE_PACKAGE, INCLUDE_RESOURCE, REQUIRE_BUNDLE, IMPORT_SERVICE,
+ EXPORT_SERVICE, CONDITIONAL_PACKAGE, BND_LASTMODIFIED, TESTCASES, SIGNATURE_TEST, REQUIRE_CAPABILITY,
+ PROVIDE_CAPABILITY, BUNDLE_ICON
+ };
+
+ String BUILDPATH = "-buildpath";
+ String BUILDPACKAGES = "-buildpackages";
+ String BUMPPOLICY = "-bumppolicy";
+ String CONDUIT = "-conduit";
+ String COMPILER_SOURCE = "-source";
+ String COMPILER_TARGET = "-target";
+ String DEPENDSON = "-dependson";
+ String DEPLOY = "-deploy";
+ String DEPLOYREPO = "-deployrepo";
+ String DIGESTS = "-digests";
+ String DSANNOTATIONS = "-dsannotations";
+ String DONOTCOPY = "-donotcopy";
+ String DEBUG = "-debug";
+ String EXPERIMENTS = "-experiments";
+ String EXPORT_CONTENTS = "-exportcontents";
+ String FAIL_OK = "-failok";
+ String INCLUDE = "-include";
+ String INCLUDERESOURCE = "-includeresource";
+ String MAKE = "-make";
+ String METATYPE = "-metatype";
+ String MANIFEST = "-manifest";
+ String SAVEMANIFEST = "-savemanifest";
+ String NAMESECTION = "-namesection";
+ String NODEFAULTVERSION = "-nodefaultversion";
+ String NOEXTRAHEADERS = "-noextraheaders";
+ String NOMANIFEST = "-nomanifest";
+ String NOUSES = "-nouses";
+ String NOBUNDLES = "-nobundles";
+ String PEDANTIC = "-pedantic";
+ String PLUGIN = "-plugin";
+ String PLUGINPATH = "-pluginpath";
+ String POM = "-pom";
+ String RELEASEREPO = "-releaserepo";
+ String REMOVEHEADERS = "-removeheaders";
+ String RESOURCEONLY = "-resourceonly";
+ String SOURCES = "-sources";
+ String SOURCEPATH = "-sourcepath";
+ String SUB = "-sub";
+ String RUNPROPERTIES = "-runproperties";
+ String RUNSYSTEMPACKAGES = "-runsystempackages";
+ String RUNBUNDLES = "-runbundles";
+ String RUNREPOS = "-runrepos";
+
+ /**
+ * @deprecated This is for support of the legacy OBR requirement format, use
+ * {@link #RUNREQUIRES} for new format.
+ */
+ @Deprecated
+ String RUNREQUIRE = "-runrequire";
+
+ String RUNREQUIRES = "-runrequires";
+
+ String RUNEE = "-runee";
+ String RUNPATH = "-runpath";
+ String RUNSTORAGE = "-runstorage";
+ String RUNBUILDS = "-runbuilds";
+ String RUNPATH_MAIN_DIRECTIVE = "main:";
+ String RUNPATH_LAUNCHER_DIRECTIVE = "launcher:";
+ String RUNVM = "-runvm";
+ String RUNTRACE = "-runtrace";
+ String RUNFRAMEWORK = "-runframework";
+ String RUNTIMEOUT = "-runtimeout";
+ String SNAPSHOT = "-snapshot";
+ String RUNFRAMEWORK_SERVICES = "services";
+ String RUNFRAMEWORK_NONE = "none";
+ String REPORTNEWER = "-reportnewer";
+ String SIGN = "-sign";
+ String TESTPACKAGES = "-testpackages";
+ String TESTREPORT = "-testreport";
+ String TESTPATH = "-testpath";
+ String TESTCONTINUOUS = "-testcontinuous";
+ String UNDERTEST = "-undertest";
+ String VERBOSE = "-verbose";
+ String PROVIDER_POLICY = "-provider-policy";
+ String CONSUMER_POLICY = "-consumer-policy";
+ String WAB = "-wab";
+ String WABLIB = "-wablib";
+ String REQUIRE_BND = "-require-bnd";
+
+ // Deprecated
+ String CLASSPATH = "-classpath";
+ String OUTPUT = "-output";
+
+ String options[] = {
+ BUILDPATH, BUMPPOLICY, CONDUIT, CLASSPATH, CONSUMER_POLICY, DEPENDSON, DONOTCOPY, EXPORT_CONTENTS, FAIL_OK,
+ INCLUDE, INCLUDERESOURCE, MAKE, MANIFEST, NOEXTRAHEADERS, NOUSES, NOBUNDLES, PEDANTIC, PLUGIN, POM,
+ PROVIDER_POLICY, REMOVEHEADERS, RESOURCEONLY, SOURCES, SOURCEPATH, SOURCES, SOURCEPATH, SUB, RUNBUNDLES,
+ RUNPATH, RUNSYSTEMPACKAGES, RUNPROPERTIES, REPORTNEWER, UNDERTEST, TESTPATH, TESTPACKAGES, TESTREPORT,
+ VERBOSE, NOMANIFEST, DEPLOYREPO, RELEASEREPO, SAVEMANIFEST, RUNVM, WAB, WABLIB, RUNFRAMEWORK, RUNTRACE,
+ TESTCONTINUOUS, SNAPSHOT, NAMESECTION, DIGESTS, DSANNOTATIONS, EXPERIMENTS
+ };
+
+ // Ignore bundle specific headers. These bundles do not make
+ // a lot of sense to inherit
+ String[] BUNDLE_SPECIFIC_HEADERS = new String[] {
+ INCLUDE_RESOURCE, BUNDLE_ACTIVATOR, BUNDLE_CLASSPATH, BUNDLE_NAME, BUNDLE_NATIVECODE, BUNDLE_SYMBOLICNAME,
+ IMPORT_PACKAGE, EXPORT_PACKAGE, DYNAMICIMPORT_PACKAGE, FRAGMENT_HOST, REQUIRE_BUNDLE, PRIVATE_PACKAGE,
+ EXPORT_CONTENTS, TESTCASES, NOMANIFEST, SIGNATURE_TEST, WAB, WABLIB, REQUIRE_CAPABILITY,
+ PROVIDE_CAPABILITY, DSANNOTATIONS, SERVICE_COMPONENT
+ };
+
+ char DUPLICATE_MARKER = '~';
+ String SPECIFICATION_VERSION = "specification-version";
+ String SPLIT_PACKAGE_DIRECTIVE = "-split-package:";
+ String IMPORT_DIRECTIVE = "-import:";
+ String NO_IMPORT_DIRECTIVE = "-noimport:";
+ String REMOVE_ATTRIBUTE_DIRECTIVE = "-remove-attribute:";
+ String LIB_DIRECTIVE = "lib:";
+ String NOANNOTATIONS = "-noannotations";
+ String COMMAND_DIRECTIVE = "command:";
+ String USES_DIRECTIVE = "uses:";
+ String MANDATORY_DIRECTIVE = "mandatory:";
+ String INCLUDE_DIRECTIVE = "include:";
+ String PROVIDE_DIRECTIVE = "provide:";
+ String EXCLUDE_DIRECTIVE = "exclude:";
+ String PRESENCE_DIRECTIVE = "presence:";
+ String PRIVATE_DIRECTIVE = "private:";
+ String SINGLETON_DIRECTIVE = "singleton:";
+ String EXTENSION_DIRECTIVE = "extension:";
+ String VISIBILITY_DIRECTIVE = "visibility:";
+ String FRAGMENT_ATTACHMENT_DIRECTIVE = "fragment-attachment:";
+ String RESOLUTION_DIRECTIVE = "resolution:";
+ String PATH_DIRECTIVE = "path:";
+ String SIZE_ATTRIBUTE = "size";
+ String LINK_ATTRIBUTE = "link";
+ String NAME_ATTRIBUTE = "name";
+ String DESCRIPTION_ATTRIBUTE = "description";
+ String OSNAME_ATTRIBUTE = "osname";
+ String OSVERSION_ATTRIBUTE = "osversion";
+ String PROCESSOR_ATTRIBUTE = "processor";
+ String LANGUAGE_ATTRIBUTE = "language";
+ String SELECTION_FILTER_ATTRIBUTE = "selection-filter";
+ String BLUEPRINT_WAIT_FOR_DEPENDENCIES_ATTRIBUTE = "blueprint.wait-for-dependencies";
+ String BLUEPRINT_TIMEOUT_ATTRIBUTE = "blueprint.timeout";
+ String VERSION_ATTRIBUTE = "version";
+ String BUNDLE_SYMBOLIC_NAME_ATTRIBUTE = "bundle-symbolic-name";
+ String BUNDLE_VERSION_ATTRIBUTE = "bundle-version";
+ String FROM_DIRECTIVE = "from:";
+
+ String KEYSTORE_LOCATION_DIRECTIVE = "keystore:";
+ String KEYSTORE_PROVIDER_DIRECTIVE = "provider:";
+ String KEYSTORE_PASSWORD_DIRECTIVE = "password:";
+ String SIGN_PASSWORD_DIRECTIVE = "sign-password:";
+
+ String NONE = "none";
+
+ String directives[] = {
+ SPLIT_PACKAGE_DIRECTIVE, NO_IMPORT_DIRECTIVE, IMPORT_DIRECTIVE, RESOLUTION_DIRECTIVE, INCLUDE_DIRECTIVE,
+ USES_DIRECTIVE, EXCLUDE_DIRECTIVE, KEYSTORE_LOCATION_DIRECTIVE, KEYSTORE_PROVIDER_DIRECTIVE,
+ KEYSTORE_PASSWORD_DIRECTIVE, SIGN_PASSWORD_DIRECTIVE, COMMAND_DIRECTIVE, NOANNOTATIONS, LIB_DIRECTIVE,
+ RUNPATH_LAUNCHER_DIRECTIVE, FROM_DIRECTIVE, PRIVATE_DIRECTIVE
+
+ // TODO
+ };
+
+ String USES_USES = "<<USES>>";
+ String CURRENT_USES = "@uses";
+ String IMPORT_REFERENCE = "reference";
+ String IMPORT_PRIVATE = "private";
+ String[] importDirectives = {
+ IMPORT_REFERENCE, IMPORT_PRIVATE
+ };
+
+ static final Pattern VALID_PROPERTY_TYPES = Pattern
+ .compile("(String|Long|Double|Float|Integer|Byte|Character|Boolean|Short)");
+
+ String DEFAULT_BND_EXTENSION = ".bnd";
+ String DEFAULT_JAR_EXTENSION = ".jar";
+ String DEFAULT_BAR_EXTENSION = ".bar";
+ String DEFAULT_BNDRUN_EXTENSION = ".bndrun";
+ String[] METAPACKAGES = {
+ "META-INF", "OSGI-INF", "OSGI-OPT"
+ };
+
+ String CURRENT_VERSION = "@";
+ String CURRENT_PACKAGE = "@package";
+
+ String BUILDFILES = "buildfiles";
+
+ String EMPTY_HEADER = "<<EMPTY>>";
+
+ String EMBEDDED_REPO = "/embedded-repo.jar";
+ String LAUNCHER_PLUGIN = "Launcher-Plugin";
+ String TESTER_PLUGIN = "Tester-Plugin";
+
+ String DEFAULT_LAUNCHER_BSN = "biz.aQute.launcher";
+ String DEFAULT_TESTER_BSN = "biz.aQute.junit";
+
+ String DEFAULT_DO_NOT_COPY = "CVS|\\.svn|\\.git|\\.DS_Store";
+
+ Charset DEFAULT_CHARSET = Charset.forName("UTF8");
+ String VERSION_FILTER = "version";
+ String PROVIDER_TYPE_DIRECTIVE = "x-provider-type:";
+ /**
+ * Component constants
+ */
+ public final static String NAMESPACE_STEM = "http://www.osgi.org/xmlns/scr";
+ public final static String JIDENTIFIER = "<<identifier>>";
+ public final static String COMPONENT_NAME = "name:";
+ public final static String COMPONENT_FACTORY = "factory:";
+ public final static String COMPONENT_SERVICEFACTORY = "servicefactory:";
+ public final static String COMPONENT_IMMEDIATE = "immediate:";
+ public final static String COMPONENT_ENABLED = "enabled:";
+ public final static String COMPONENT_DYNAMIC = "dynamic:";
+ public final static String COMPONENT_MULTIPLE = "multiple:";
+ public final static String COMPONENT_PROVIDE = "provide:";
+ public final static String COMPONENT_OPTIONAL = "optional:";
+ public final static String COMPONENT_PROPERTIES = "properties:";
+ public final static String COMPONENT_IMPLEMENTATION = "implementation:";
+ public final static String COMPONENT_DESIGNATE = "designate:";
+ public final static String COMPONENT_DESIGNATEFACTORY = "designateFactory:";
+ public final static String COMPONENT_DESCRIPTORS = ".descriptors:";
+
+ // v1.1.0
+ public final static String COMPONENT_VERSION = "version:";
+ public final static String COMPONENT_CONFIGURATION_POLICY = "configuration-policy:";
+ public final static String COMPONENT_MODIFIED = "modified:";
+ public final static String COMPONENT_ACTIVATE = "activate:";
+ public final static String COMPONENT_DEACTIVATE = "deactivate:";
+
+ final static Map<String,String> EMPTY = Collections.emptyMap();
+
+ public final static String[] componentDirectives = new String[] {
+ COMPONENT_FACTORY, COMPONENT_IMMEDIATE, COMPONENT_ENABLED, COMPONENT_DYNAMIC, COMPONENT_MULTIPLE,
+ COMPONENT_PROVIDE, COMPONENT_OPTIONAL, COMPONENT_PROPERTIES, COMPONENT_IMPLEMENTATION,
+ COMPONENT_SERVICEFACTORY, COMPONENT_VERSION, COMPONENT_CONFIGURATION_POLICY, COMPONENT_MODIFIED,
+ COMPONENT_ACTIVATE, COMPONENT_DEACTIVATE, COMPONENT_NAME, COMPONENT_DESCRIPTORS, COMPONENT_DESIGNATE,
+ COMPONENT_DESIGNATEFACTORY
+ };
+
+ public final static Set<String> SET_COMPONENT_DIRECTIVES = new HashSet<String>(
+ Arrays.asList(componentDirectives));
+
+ public final static Set<String> SET_COMPONENT_DIRECTIVES_1_1 = //
+ new HashSet<String>(Arrays.asList(
+ COMPONENT_VERSION,
+ COMPONENT_CONFIGURATION_POLICY,
+ COMPONENT_MODIFIED,
+ COMPONENT_ACTIVATE,
+ COMPONENT_DEACTIVATE));
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Constants.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Constants.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Descriptors.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Descriptors.java?rev=1362033&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Descriptors.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Descriptors.java Mon Jul 16 13:43:38 2012
@@ -0,0 +1,557 @@
+package aQute.bnd.osgi;
+
+import java.util.*;
+
+import aQute.libg.generics.*;
+
+public class Descriptors {
+ Map<String,TypeRef> typeRefCache = Create.map();
+ Map<String,Descriptor> descriptorCache = Create.map();
+ Map<String,PackageRef> packageCache = Create.map();
+
+ // MUST BE BEFORE PRIMITIVES, THEY USE THE DEFAULT PACKAGE!!
+ final static PackageRef DEFAULT_PACKAGE = new PackageRef();
+ final static PackageRef PRIMITIVE_PACKAGE = new PackageRef();
+
+ final static TypeRef VOID = new ConcreteRef("V", "void", PRIMITIVE_PACKAGE);
+ final static TypeRef BOOLEAN = new ConcreteRef("Z", "boolean", PRIMITIVE_PACKAGE);
+ final static TypeRef BYTE = new ConcreteRef("B", "byte", PRIMITIVE_PACKAGE);
+ final static TypeRef CHAR = new ConcreteRef("C", "char", PRIMITIVE_PACKAGE);
+ final static TypeRef SHORT = new ConcreteRef("S", "short", PRIMITIVE_PACKAGE);
+ final static TypeRef INTEGER = new ConcreteRef("I", "int", PRIMITIVE_PACKAGE);
+ final static TypeRef LONG = new ConcreteRef("J", "long", PRIMITIVE_PACKAGE);
+ final static TypeRef DOUBLE = new ConcreteRef("D", "double", PRIMITIVE_PACKAGE);
+ final static TypeRef FLOAT = new ConcreteRef("F", "float", PRIMITIVE_PACKAGE);
+
+ {
+ packageCache.put("", DEFAULT_PACKAGE);
+ }
+
+ public interface TypeRef extends Comparable<TypeRef> {
+ String getBinary();
+
+ String getFQN();
+
+ String getPath();
+
+ boolean isPrimitive();
+
+ TypeRef getComponentTypeRef();
+
+ TypeRef getClassRef();
+
+ PackageRef getPackageRef();
+
+ String getShortName();
+
+ boolean isJava();
+
+ boolean isObject();
+
+ String getSourcePath();
+
+ String getDottedOnly();
+
+ }
+
+ public static class PackageRef implements Comparable<PackageRef> {
+ final String binaryName;
+ final String fqn;
+ final boolean java;
+
+ PackageRef(String binaryName) {
+ this.binaryName = fqnToBinary(binaryName);
+ this.fqn = binaryToFQN(binaryName);
+ this.java = this.fqn.startsWith("java."); // &&
+ // !this.fqn.equals("java.sql)"
+
+ // For some reason I excluded java.sql but the classloader will
+ // delegate anyway. So lost the understanding why I did it??
+ }
+
+ PackageRef() {
+ this.binaryName = "";
+ this.fqn = ".";
+ this.java = false;
+ }
+
+ public PackageRef getDuplicate() {
+ return new PackageRef(binaryName + Constants.DUPLICATE_MARKER);
+ }
+
+ public String getFQN() {
+ return fqn;
+ }
+
+ public String getBinary() {
+ return binaryName;
+ }
+
+ public String getPath() {
+ return binaryName;
+ }
+
+ public boolean isJava() {
+ return java;
+ }
+
+ public String toString() {
+ return fqn;
+ }
+
+ boolean isDefaultPackage() {
+ return this.fqn.equals(".");
+ }
+
+ boolean isPrimitivePackage() {
+ return this == PRIMITIVE_PACKAGE;
+ }
+
+ public int compareTo(PackageRef other) {
+ return fqn.compareTo(other.fqn);
+ }
+
+ public boolean equals(Object o) {
+ assert o instanceof PackageRef;
+ return o == this;
+ }
+
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ /**
+ * Decide if the package is a metadata package.
+ *
+ * @param pack
+ * @return
+ */
+ public boolean isMetaData() {
+ if (isDefaultPackage())
+ return true;
+
+ for (int i = 0; i < Constants.METAPACKAGES.length; i++) {
+ if (fqn.startsWith(Constants.METAPACKAGES[i]))
+ return true;
+ }
+ return false;
+ }
+
+ }
+
+ // We "intern" the
+ private static class ConcreteRef implements TypeRef {
+ final String binaryName;
+ final String fqn;
+ final boolean primitive;
+ final PackageRef packageRef;
+
+ ConcreteRef(PackageRef packageRef, String binaryName) {
+ if (packageRef.getFQN().length() < 2)
+ System.err.println("in default pack? " + binaryName);
+ this.binaryName = binaryName;
+ this.fqn = binaryToFQN(binaryName);
+ this.primitive = false;
+ this.packageRef = packageRef;
+ }
+
+ ConcreteRef(String binaryName, String fqn, PackageRef pref) {
+ this.binaryName = binaryName;
+ this.fqn = fqn;
+ this.primitive = true;
+ this.packageRef = pref;
+ }
+
+ public String getBinary() {
+ return binaryName;
+ }
+
+ public String getPath() {
+ return binaryName + ".class";
+ }
+
+ public String getSourcePath() {
+ return binaryName + ".java";
+ }
+
+ public String getFQN() {
+ return fqn;
+ }
+
+ public String getDottedOnly() {
+ return fqn.replace('$', '.');
+ }
+
+ public boolean isPrimitive() {
+ return primitive;
+ }
+
+ public TypeRef getComponentTypeRef() {
+ return null;
+ }
+
+ public TypeRef getClassRef() {
+ return this;
+ }
+
+ public PackageRef getPackageRef() {
+ return packageRef;
+ }
+
+ public String getShortName() {
+ int n = binaryName.lastIndexOf('/');
+ return binaryName.substring(n + 1);
+ }
+
+ public boolean isJava() {
+ return packageRef.isJava();
+ }
+
+ public String toString() {
+ return fqn;
+ }
+
+ public boolean isObject() {
+ return fqn.equals("java.lang.Object");
+ }
+
+ public boolean equals(Object other) {
+ assert other instanceof TypeRef;
+ return this == other;
+ }
+
+ public int compareTo(TypeRef other) {
+ if (this == other)
+ return 0;
+ return fqn.compareTo(other.getFQN());
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ }
+
+ private static class ArrayRef implements TypeRef {
+ final TypeRef component;
+
+ ArrayRef(TypeRef component) {
+ this.component = component;
+ }
+
+ public String getBinary() {
+ return "[" + component.getBinary();
+ }
+
+ public String getFQN() {
+ return component.getFQN() + "[]";
+ }
+
+ public String getPath() {
+ return component.getPath();
+ }
+
+ public String getSourcePath() {
+ return component.getSourcePath();
+ }
+
+ public boolean isPrimitive() {
+ return false;
+ }
+
+ public TypeRef getComponentTypeRef() {
+ return component;
+ }
+
+ public TypeRef getClassRef() {
+ return component.getClassRef();
+ }
+
+ public boolean equals(Object other) {
+ if (other == null || other.getClass() != getClass())
+ return false;
+
+ return component.equals(((ArrayRef) other).component);
+ }
+
+ public PackageRef getPackageRef() {
+ return component.getPackageRef();
+ }
+
+ public String getShortName() {
+ return component.getShortName() + "[]";
+ }
+
+ public boolean isJava() {
+ return component.isJava();
+ }
+
+ public String toString() {
+ return component.toString() + "[]";
+ }
+
+ public boolean isObject() {
+ return false;
+ }
+
+ public String getDottedOnly() {
+ return component.getDottedOnly();
+ }
+
+ public int compareTo(TypeRef other) {
+ if (this == other)
+ return 0;
+
+ return getFQN().compareTo(other.getFQN());
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ }
+
+ public TypeRef getTypeRef(String binaryClassName) {
+ assert !binaryClassName.endsWith(".class");
+
+ TypeRef ref = typeRefCache.get(binaryClassName);
+ if (ref != null)
+ return ref;
+
+ if (binaryClassName.startsWith("[")) {
+ ref = getTypeRef(binaryClassName.substring(1));
+ ref = new ArrayRef(ref);
+ } else {
+ if (binaryClassName.length() >= 1) {
+ switch (binaryClassName.charAt(0)) {
+ case 'V' :
+ return VOID;
+ case 'B' :
+ return BYTE;
+ case 'C' :
+ return CHAR;
+ case 'I' :
+ return INTEGER;
+ case 'S' :
+ return SHORT;
+ case 'D' :
+ return DOUBLE;
+ case 'F' :
+ return FLOAT;
+ case 'J' :
+ return LONG;
+ case 'Z' :
+ return BOOLEAN;
+ case 'L' :
+ binaryClassName = binaryClassName.substring(1, binaryClassName.length() - 1);
+ break;
+ }
+ // falls trough for other 1 letter class names
+ }
+ ref = typeRefCache.get(binaryClassName);
+ if (ref != null)
+ return ref;
+
+ PackageRef pref;
+ int n = binaryClassName.lastIndexOf('/');
+ if (n < 0)
+ pref = DEFAULT_PACKAGE;
+ else
+ pref = getPackageRef(binaryClassName.substring(0, n));
+
+ ref = new ConcreteRef(pref, binaryClassName);
+ }
+
+ typeRefCache.put(binaryClassName, ref);
+ return ref;
+ }
+
+ public PackageRef getPackageRef(String binaryPackName) {
+ if (binaryPackName.indexOf('.') >= 0) {
+ binaryPackName = binaryPackName.replace('.', '/');
+ }
+ PackageRef ref = packageCache.get(binaryPackName);
+ if (ref != null)
+ return ref;
+
+ ref = new PackageRef(binaryPackName);
+ packageCache.put(binaryPackName, ref);
+ return ref;
+ }
+
+ public Descriptor getDescriptor(String descriptor) {
+ Descriptor d = descriptorCache.get(descriptor);
+ if (d != null)
+ return d;
+ d = new Descriptor(descriptor);
+ descriptorCache.put(descriptor, d);
+ return d;
+ }
+
+ public class Descriptor {
+ final TypeRef type;
+ final TypeRef[] prototype;
+ final String descriptor;
+
+ Descriptor(String descriptor) {
+ this.descriptor = descriptor;
+ int index = 0;
+ List<TypeRef> types = Create.list();
+ if (descriptor.charAt(index) == '(') {
+ index++;
+ while (descriptor.charAt(index) != ')') {
+ index = parse(types, descriptor, index);
+ }
+ index++; // skip )
+ prototype = types.toArray(new TypeRef[types.size()]);
+ types.clear();
+ } else
+ prototype = null;
+
+ index = parse(types, descriptor, index);
+ type = types.get(0);
+ }
+
+ int parse(List<TypeRef> types, String descriptor, int index) {
+ char c;
+ StringBuilder sb = new StringBuilder();
+ while ((c = descriptor.charAt(index++)) == '[') {
+ sb.append('[');
+ }
+
+ switch (c) {
+ case 'L' :
+ while ((c = descriptor.charAt(index++)) != ';') {
+ // TODO
+ sb.append(c);
+ }
+ break;
+
+ case 'V' :
+ case 'B' :
+ case 'C' :
+ case 'I' :
+ case 'S' :
+ case 'D' :
+ case 'F' :
+ case 'J' :
+ case 'Z' :
+ sb.append(c);
+ break;
+
+ default :
+ throw new IllegalArgumentException("Invalid type in descriptor: " + c + " from " + descriptor + "["
+ + index + "]");
+ }
+ types.add(getTypeRef(sb.toString()));
+ return index;
+ }
+
+ public TypeRef getType() {
+ return type;
+ }
+
+ public TypeRef[] getPrototype() {
+ return prototype;
+ }
+
+ public boolean equals(Object other) {
+ if (other == null || other.getClass() != getClass())
+ return false;
+
+ return Arrays.equals(prototype, ((Descriptor) other).prototype) && type == ((Descriptor) other).type;
+ }
+
+ public int hashCode() {
+ return prototype == null ? type.hashCode() : type.hashCode() ^ Arrays.hashCode(prototype);
+ }
+
+ public String toString() {
+ return descriptor;
+ }
+ }
+
+ /**
+ * Return the short name of a FQN
+ */
+
+ public static String getShortName(String fqn) {
+ assert fqn.indexOf('/') < 0;
+
+ int n = fqn.lastIndexOf('.');
+ if (n >= 0) {
+ return fqn.substring(n + 1);
+ }
+ return fqn;
+ }
+
+ public static String binaryToFQN(String binary) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0, l = binary.length(); i < l; i++) {
+ char c = binary.charAt(i);
+
+ if (c == '/')
+ sb.append('.');
+ else
+ sb.append(c);
+ }
+ String result = sb.toString();
+ assert result.length() > 0;
+ return result;
+ }
+
+ public static String fqnToBinary(String binary) {
+ return binary.replace('.', '/');
+ }
+
+ public static String getPackage(String binaryNameOrFqn) {
+ int n = binaryNameOrFqn.lastIndexOf('/');
+ if (n >= 0)
+ return binaryNameOrFqn.substring(0, n).replace('/', '.');
+
+ n = binaryNameOrFqn.lastIndexOf(".");
+ if (n >= 0)
+ return binaryNameOrFqn.substring(0, n);
+
+ return ".";
+ }
+
+ public static String fqnToPath(String s) {
+ return fqnToBinary(s) + ".class";
+ }
+
+ public TypeRef getTypeRefFromFQN(String fqn) {
+ if (fqn.equals("boolean"))
+ return BOOLEAN;
+
+ if (fqn.equals("byte"))
+ return BOOLEAN;
+
+ if (fqn.equals("char"))
+ return CHAR;
+
+ if (fqn.equals("short"))
+ return SHORT;
+
+ if (fqn.equals("int"))
+ return INTEGER;
+
+ if (fqn.equals("long"))
+ return LONG;
+
+ if (fqn.equals("float"))
+ return FLOAT;
+
+ if (fqn.equals("double"))
+ return DOUBLE;
+
+ return getTypeRef(fqnToBinary(fqn));
+ }
+
+ public TypeRef getTypeRefFromPath(String path) {
+ assert path.endsWith(".class");
+ return getTypeRef(path.substring(0, path.length() - 6));
+ }
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Descriptors.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Descriptors.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Domain.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Domain.java?rev=1362033&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Domain.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Domain.java Mon Jul 16 13:43:38 2012
@@ -0,0 +1,304 @@
+package aQute.bnd.osgi;
+
+import static aQute.bnd.osgi.Constants.*;
+
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.jar.*;
+
+import aQute.bnd.header.*;
+import aQute.lib.converter.*;
+import aQute.service.reporter.*;
+
+/**
+ * This class abstracts domains that have properties holding OSGi meta data. It
+ * provides access to the keys, the set method and the get method. It then
+ * provides convenient methods to access these properties via semantic methods.
+ */
+public abstract class Domain implements Iterable<String> {
+
+ public abstract String get(String key);
+
+ public String get(String key, String deflt) {
+ String result = get(key);
+ if (result != null)
+ return result;
+ return deflt;
+ }
+
+ public abstract void set(String key, String value);
+
+ public abstract Iterator<String> iterator();
+
+ public static Domain domain(final Manifest manifest) {
+ Attributes attrs = manifest.getMainAttributes();
+ return domain(attrs);
+ }
+
+ public static Domain domain(final Attributes attrs) {
+ return new Domain() {
+
+ @Override
+ public String get(String key) {
+ return attrs.getValue(key);
+ }
+
+ @Override
+ public void set(String key, String value) {
+ attrs.putValue(key, value);
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ final Iterator<Object> it = attrs.keySet().iterator();
+
+ return new Iterator<String>() {
+
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+
+ public String next() {
+ return it.next().toString();
+ }
+
+ public void remove() {
+ it.remove();
+ }
+ };
+ }
+ };
+ }
+
+ public static Domain domain(final Processor processor) {
+ return new Domain() {
+
+ @Override
+ public String get(String key) {
+ return processor.getProperty(key);
+ }
+
+ @Override
+ public String get(String key, String deflt) {
+ return processor.getProperty(key, deflt);
+ }
+
+ @Override
+ public void set(String key, String value) {
+ processor.setProperty(key, value);
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ final Iterator<String> it = processor.getPropertyKeys(true).iterator();
+
+ return new Iterator<String>() {
+ String current;
+
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+
+ public String next() {
+ return current = it.next().toString();
+ }
+
+ public void remove() {
+ processor.getProperties().remove(current);
+ }
+ };
+ }
+ };
+ }
+
+ public static Domain domain(final Map<String,String> map) {
+ return new Domain() {
+
+ @Override
+ public String get(String key) {
+ return map.get(key);
+ }
+
+ @Override
+ public void set(String key, String value) {
+ map.put(key, value);
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ return map.keySet().iterator();
+ }
+ };
+ }
+
+ public Parameters getParameters(String key, Reporter reporter) {
+ return new Parameters(get(key), reporter);
+ }
+
+ public Parameters getParameters(String key) {
+ return new Parameters(get(key));
+ }
+
+ public Parameters getParameters(String key, String deflt) {
+ return new Parameters(get(key, deflt));
+ }
+
+ public Parameters getParameters(String key, String deflt, Reporter reporter) {
+ return new Parameters(get(key, deflt), reporter);
+ }
+
+ public Parameters getImportPackage() {
+ return getParameters(IMPORT_PACKAGE);
+ }
+
+ public Parameters getExportPackage() {
+ return getParameters(EXPORT_PACKAGE);
+ }
+
+ public Parameters getBundleClassPath() {
+ return getParameters(BUNDLE_CLASSPATH);
+ }
+
+ public Parameters getPrivatePackage() {
+ return getParameters(PRIVATE_PACKAGE);
+ }
+
+ public Parameters getIncludeResource() {
+ Parameters ic = getParameters(INCLUDE_RESOURCE);
+ ic.putAll(getParameters(INCLUDERESOURCE));
+ return ic;
+ }
+
+ public Parameters getDynamicImportPackage() {
+ return getParameters(DYNAMICIMPORT_PACKAGE);
+ }
+
+ public Parameters getExportContents() {
+ return getParameters(EXPORT_CONTENTS);
+ }
+
+ public String getBundleActivator() {
+ return get(BUNDLE_ACTIVATOR);
+ }
+
+ public void setPrivatePackage(String s) {
+ if (s != null)
+ set(PRIVATE_PACKAGE, s);
+ }
+
+ public void setIncludeResource(String s) {
+ if (s != null)
+ set(INCLUDE_RESOURCE, s);
+ }
+
+ public void setBundleActivator(String s) {
+ if (s != null)
+ set(BUNDLE_ACTIVATOR, s);
+ }
+
+ public void setExportPackage(String s) {
+ if (s != null)
+ set(EXPORT_PACKAGE, s);
+ }
+
+ public void setImportPackage(String s) {
+ if (s != null)
+ set(IMPORT_PACKAGE, s);
+ }
+
+ public void setBundleClasspath(String s) {
+ if (s != null)
+ set(BUNDLE_CLASSPATH, s);
+ }
+
+ public Parameters getBundleClasspath() {
+ return getParameters(BUNDLE_CLASSPATH);
+ }
+
+ public void setBundleRequiredExecutionEnvironment(String s) {
+ if (s != null)
+ set(BUNDLE_REQUIREDEXECUTIONENVIRONMENT, s);
+ }
+
+ public Parameters getBundleRequiredExecutionEnvironment() {
+ return getParameters(BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
+ }
+
+ public void setSources(boolean b) {
+ if (b)
+ set(SOURCES, "true");
+ else
+ set(SOURCES, "false");
+ }
+
+ public boolean isSources() {
+ return Processor.isTrue(get(SOURCES));
+ }
+
+ public Map.Entry<String,Attrs> getBundleSymbolicName() {
+ Parameters p = getParameters(BUNDLE_SYMBOLICNAME);
+ if (p.isEmpty())
+ return null;
+ return p.entrySet().iterator().next();
+ }
+
+ public void setBundleSymbolicName(String s) {
+ set(BUNDLE_SYMBOLICNAME, s);
+ }
+
+ public String getBundleVersion() {
+ return get(BUNDLE_VERSION);
+ }
+
+ public void setBundleVersion(String version) {
+ Version v = new Version(version);
+ set(BUNDLE_VERSION, v.toString());
+ }
+
+ public void setBundleVersion(Version version) {
+ set(BUNDLE_VERSION, version.toString());
+ }
+
+ public void setFailOk(boolean b) {
+ set(FAIL_OK, b + "");
+ }
+
+ public boolean isFailOk() {
+ return Processor.isTrue(get(FAIL_OK));
+ }
+
+ /**
+ * Find an icon with the requested size in the list of icons.
+ *
+ * @param requestedSize
+ * the number of pixels desired
+ * @return null or a the selected URI (which may be relative)
+ */
+ public String getIcon(int requestedSize) throws Exception {
+ String spec = get(Constants.BUNDLE_ICON);
+ if (spec == null)
+ return null;
+
+ Parameters p = OSGiHeader.parseHeader(spec);
+ int dist = Integer.MAX_VALUE;
+ String selected = null;
+
+ for (Entry<String,Attrs> e : p.entrySet()) {
+ String url = e.getKey();
+ if (selected == null)
+ selected = url;
+
+ int size = Converter.cnv(Integer.class, e.getValue().get("size"));
+ if (size != 0 && Math.abs(requestedSize - size) < dist) {
+ dist = Math.abs(requestedSize - size);
+ selected = url;
+ }
+ }
+ return selected;
+ }
+
+ public void setConditionalPackage(String string) {
+ set(CONDITIONAL_PACKAGE, string);
+
+ }
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Domain.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/Domain.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/EmbeddedResource.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/EmbeddedResource.java?rev=1362033&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/EmbeddedResource.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/EmbeddedResource.java Mon Jul 16 13:43:38 2012
@@ -0,0 +1,99 @@
+package aQute.bnd.osgi;
+
+import java.io.*;
+import java.util.zip.*;
+
+import aQute.lib.io.*;
+
+public class EmbeddedResource implements Resource {
+ byte data[];
+ long lastModified;
+ String extra;
+
+ public EmbeddedResource(byte data[], long lastModified) {
+ this.data = data;
+ this.lastModified = lastModified;
+ }
+
+ public InputStream openInputStream() throws FileNotFoundException {
+ return new ByteArrayInputStream(data);
+ }
+
+ public void write(OutputStream out) throws IOException {
+ out.write(data);
+ }
+
+ public String toString() {
+ return ":" + data.length + ":";
+ }
+
+ public static void build(Jar jar, InputStream in, long lastModified) throws IOException {
+ ZipInputStream jin = new ZipInputStream(in);
+ ZipEntry entry = jin.getNextEntry();
+ while (entry != null) {
+ if (!entry.isDirectory()) {
+ byte data[] = collect(jin);
+ jar.putResource(entry.getName(), new EmbeddedResource(data, lastModified), true);
+ }
+ entry = jin.getNextEntry();
+ }
+ IO.drain(in);
+ jin.close();
+ }
+
+ /**
+ * Convenience method to turn an inputstream into a byte array. The method
+ * uses a recursive algorithm to minimize memory usage.
+ *
+ * @param in
+ * stream with data
+ * @param offset
+ * where we are in the stream
+ * @returns byte array filled with data
+ */
+ static byte[] collect(InputStream in) throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ copy(in, out);
+ return out.toByteArray();
+ }
+
+ static void copy(InputStream in, OutputStream out) throws IOException {
+ int available = in.available();
+ if (available <= 10000)
+ available = 64000;
+ byte[] buffer = new byte[available];
+ int size;
+ while ((size = in.read(buffer)) > 0)
+ out.write(buffer, 0, size);
+ }
+
+ public long lastModified() {
+ return lastModified;
+ }
+
+ public static void build(Jar sub, Resource resource) throws Exception {
+ InputStream in = resource.openInputStream();
+ try {
+ build(sub, in, resource.lastModified());
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ finally {
+ in.close();
+ }
+ }
+
+ public String getExtra() {
+ return extra;
+ }
+
+ public void setExtra(String extra) {
+ this.extra = extra;
+ }
+
+ public long size() {
+ return data.length;
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/EmbeddedResource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/EmbeddedResource.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/bnd/osgi/EmbeddedResource.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision