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 ( '&lt;' references '&gt;' )? ';' | '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