Initial source commit.


git-svn-id: https://svn.apache.org/repos/asf/incubator/oscar/trunk@233031 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/org/osgi/framework/AdminPermission.java b/src/org/osgi/framework/AdminPermission.java
new file mode 100644
index 0000000..05a0966
--- /dev/null
+++ b/src/org/osgi/framework/AdminPermission.java
@@ -0,0 +1,932 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/AdminPermission.java,v 1.12 2005/05/13 20:32:54 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.*;
+import java.util.*;
+import org.apache.osgi.framework.FilterImpl;
+
+/**
+ * Indicates the caller's authority to perform specific privileged administrative 
+ * operations on or to get sensitive information about a bundle.
+ * 
+ * <ul>
+ *   <li>The <code>{@link AdminPermission#METADATA}</code> action allows calls to
+ *   	<ul>
+ *         <li>{@link Bundle#getHeaders()}
+ *         <li>{@link Bundle#getHeaders(String)}
+ *         <li>{@link Bundle#getLocation()}
+ *         </ul>
+ *   <li>The <code>{@link AdminPermission#RESOURCE}</code> action allows calls to
+ *   	<ul>
+ *   		<li>{@link Bundle#getResource(String)}
+ *   		<li>{@link Bundle#getEntry(String)}
+ *   		<li>{@link Bundle#getEntryPaths(String)}
+ *   		<li>Bundle resource/entry URL creation
+ *   	</ul>
+ *   <li>The <code>{@link AdminPermission#METADATA}</code> action allows calls to
+ *   	<ul>
+ *   		<li>{@link Bundle#loadClass(String)}
+ *   	</ul>
+ *   <li>The <code>{@link AdminPermission#LIFECYCLE}</code> action allows calls to
+ *   	<ul>
+ *   		<li>{@link BundleContext#installBundle(String)}
+ *   		<li>{@link BundleContext#installBundle(String, InputStream)}
+ *   		<li>{@link Bundle#update()}
+ *   		<li>{@link Bundle#update(InputStream)}
+ *   		<li>{@link Bundle#uninstall()}
+ *   	</ul>
+ *   <li>The <code>{@link AdminPermission#EXECUTE}</code> action allows calls to
+ *   	<ul>
+ *   		<li>{@link Bundle#start()}
+ *   		<li>{@link Bundle#stop()}
+ *   		<li>{@link org.osgi.service.startlevel.StartLevel#setBundleStartLevel(Bundle, int)}
+ *   	</ul>
+ *   <li>The <code>{@link AdminPermission#LISTENER}</code> action allows calls to
+ *   	<ul>
+ *   		<li>{@link BundleContext#addBundleListener(BundleListener)} for 
+ *   				<code>SynchronousBundleListener</code>
+ *   		<li>{@link BundleContext#removeBundleListener(BundleListener)} for 
+ *   				<code>SynchronousBundleListener</code>
+ *   	</ul>
+ *   <li>The <code>{@link AdminPermission#PERMISSION}</code> action allows calls to
+ *   	<ul>
+ *   		<li>{@link org.osgi.service.permissionadmin.PermissionAdmin#setPermissions(String, PermissionInfo[])}
+ *   		<li>{@link org.osgi.service.permissionadmin.PermissionAdmin#setDefaultPermissions(PermissionInfo[])}
+ *   	</ul>
+ *   <li>The <code>{@link AdminPermission#RESOLVE}</code> action allows calls to
+ *   	<ul>
+ *   		<li>{@link org.osgi.service.packageadmin.PackageAdmin#refreshPackages(Bundle[])}</code>
+ *   		<li>{@link org.osgi.service.packageadmin.PackageAdmin#resolveBundles(Bundle[])}</code>
+ *   	</ul>
+ *   <li>The <code>{@link AdminPermission#STARTLEVEL}</code> action allows calls to
+ *   	<ul>
+ *   		<li>{@link org.osgi.service.startlevel.StartLevel#setStartLevel(int)}
+ *   		<li>{@link org.osgi.service.startlevel.StartLevel#setInitialBundleStartLevel(int)}
+ *   	</ul>
+ * </ul>
+ * 
+ * The special action "*" will represent all actions.
+ * 
+ * @version $Revision: 1.12 $
+ */
+
+public final class AdminPermission extends Permission
+{
+	static final long	serialVersionUID	= 207051004521261705L;
+
+    /**
+     * The action string <code>class</code> (Value is "class").
+     */
+    public final static String CLASS = "class"; //$NON-NLS-1$
+
+    /**
+     * The action string <code>execute</code> (Value is "execute").
+     */
+    public final static String EXECUTE = "execute"; //$NON-NLS-1$
+    
+    /**
+     * The action string <code>lifecycle</code> (Value is "lifecycle").
+     */
+    public final static String LIFECYCLE = "lifecycle"; //$NON-NLS-1$
+    
+    /**
+     * The action string <code>listener</code> (Value is "listener").
+     */
+    public final static String LISTENER = "listener"; //$NON-NLS-1$
+    
+    /**
+     * The action string <code>metadata</code> (Value is "metadata").
+     */
+    public final static String METADATA = "metadata"; //$NON-NLS-1$
+
+    /**
+     * The action string <code>permission</code> (Value is "permission").
+     */
+    public final static String PERMISSION = "permission"; //$NON-NLS-1$
+	
+    /**
+     * The action string <code>resolve</code> (Value is "resolve").
+     */
+    public final static String RESOLVE = "resolve"; //$NON-NLS-1$
+
+    /**
+     * The action string <code>resource</code> (Value is "resource").
+     */
+    public final static String RESOURCE = "resource"; //$NON-NLS-1$
+    
+    /**
+     * The action string <code>startlevel</code> (Value is "startlevel").
+     */
+    public final static String STARTLEVEL = "startlevel"; //$NON-NLS-1$
+
+    /**
+     * The action string <code>extensionLifecycle</code> (Value is "extensionLifecycle").
+     */
+    public final static String EXTENSIONLIFECYCLE = "extensionLifecycle"; //$NON-NLS-1$
+
+    private final static int ACTION_CLASS				= 0x00000001;
+    private final static int ACTION_EXECUTE				= 0x00000002;
+    private final static int ACTION_LIFECYCLE			= 0x00000004;
+    private final static int ACTION_LISTENER			= 0x00000008;
+    private final static int ACTION_METADATA			= 0x00000010;
+    private final static int ACTION_PERMISSION			= 0x00000020;
+    private final static int ACTION_RESOLVE				= 0x00000040;
+    private final static int ACTION_RESOURCE			= 0x00000080;
+    private final static int ACTION_STARTLEVEL			= 0x00000100;
+	private final static int ACTION_EXTENSIONLIFECYCLE	= 0x00000200;
+    private final static int ACTION_ALL = 
+		ACTION_CLASS 				|
+		ACTION_EXECUTE 				|
+		ACTION_LIFECYCLE 			|
+		ACTION_LISTENER 			|
+    	ACTION_METADATA 			|
+		ACTION_PERMISSION			|
+		ACTION_RESOLVE 				|
+		ACTION_RESOURCE 			|
+		ACTION_STARTLEVEL			|
+		ACTION_EXTENSIONLIFECYCLE;
+    private final static int ACTION_NONE = 0;
+	
+	/**
+	 * Indicates that this AdminPermission refers to all bundles
+	 * @serial
+	 */
+	private boolean wildcard;
+	
+	/**
+	 * An x.500 distinguished name used to match a bundle's signature - only used if
+	 * wildcard is false and bundle = null
+	 * @serial
+	 */
+	private String filter;
+
+    /**
+     * The actions in canonical form.
+     *
+     * @serial
+     */
+    private String actions = null;
+
+    /**
+     * The actions mask.
+     */
+	private transient int action_mask = ACTION_NONE;
+
+	/**
+	 * The bundle governed by this AdminPermission - only used if 
+	 * wildcard is false and filter == null
+	 */
+	private transient Bundle bundle;
+
+    /**
+     * If this AdminPermission was constructed with a bundle, this dictionary holds
+     * the properties of that bundle, used to match a filter in implies.
+     * This is not initialized until necessary, and then cached in this object.
+     */
+    private transient Dictionary bundleProperties;
+    
+    /**
+     * If this AdminPermission was constructed with a filter, this dictionary holds
+     * a Filter matching object used to evaluate the filter in implies.
+     * This is not initialized until necessary, and then cached in this object
+     */
+    private transient Filter filterImpl;
+    
+	/**
+     * Creates a new <code>AdminPermission</code> object that matches 
+     * all bundles and has all actions.  Equivalent to 
+     * AdminPermission("*","*");
+     */
+    public AdminPermission()
+    {
+    	this("*",AdminPermission.ACTION_ALL); //$NON-NLS-1$
+    }
+    
+    /**
+     * Creates a new <code>AdminPermission</code> object for use by the <code>Policy</code>
+     * object to instantiate new <code>Permission</code> objects.
+     * 
+     * Null arguments are equivalent to "*"
+     *
+     * @param filter an X.500 Distinguished Name suffix or "*" to match all bundles
+     * @param actions <code>class</code>, <code>execute</code>, <code>lifecycle</code>, 
+     * <code>listener</code>, <code>metadata</code>, <code>permission</code>, <code>resolve</code>, 
+     * <code>resource</code>, <code>startlevel</code>, or "*" to indicate all actions
+     */
+    public AdminPermission(String filter, String actions)
+    {
+    	//arguments will be null if called from a PermissionInfo defined with
+    	//no args
+    	this(
+    			(filter == null ? "*" : filter), //$NON-NLS-1$
+				getMask((actions == null ? "*" : actions)) //$NON-NLS-1$
+				);
+    }
+
+    /**
+     * Creates a new <code>AdminPermission</code> object for use by the <code>Policy</code>
+     * object to instantiate new <code>Permission</code> objects.
+     * 
+     * @param bundle A bundle
+     * @param actions <code>class</code>, <code>execute</code>, <code>lifecycle</code>, 
+     * <code>listener</code>, <code>metadata</code>, <code>permission</code>, <code>resolve</code>, 
+     * <code>resource</code>, <code>startlevel</code>, or "*" to indicate all actions
+     */
+    public AdminPermission(Bundle bundle, String actions) {
+    	super(bundle.toString());
+    	this.bundle = bundle;
+    	this.wildcard = false;
+    	this.filter = null;
+    	this.action_mask = getMask(actions);
+    }
+ 
+    /**
+     * Package private constructor used by AdminPermissionCollection.
+     *
+     * @param filter name filter
+     * @param action_mask mask
+     */
+    AdminPermission(String filter, int action_mask) {
+    	super(filter);
+    	
+    	//name must be either * or a filter
+    	if (filter.equals("*")) { //$NON-NLS-1$
+    		this.wildcard = true;
+    		this.filter = null;
+    	} else {
+			this.wildcard = false;
+			this.filter = filter;
+    	}
+    	this.bundle = null;
+    	this.action_mask = action_mask;
+    }
+
+    /**
+     * Parse action string into action mask.
+     *
+     * @param actions Action string.
+     * @return action mask.
+     */
+    private static int getMask(String actions) {
+    
+    	boolean seencomma = false;
+
+    	int mask = ACTION_NONE;
+
+    	if (actions == null) {
+    		return mask;
+    	}
+
+    	char[] a = actions.toCharArray();
+
+    	int i = a.length - 1;
+    	if (i < 0)
+    		return mask;
+
+    	while (i != -1) {
+    		char c;
+
+    		// skip whitespace
+    		while ((i!=-1) && ((c = a[i]) == ' ' ||
+    				c == '\r' ||
+					c == '\n' ||
+					c == '\f' ||
+					c == '\t'))
+    			i--;
+
+    		// check for the known strings
+    		int matchlen;
+
+    		if (i >= 4 && 
+					(a[i-4] == 'c' || a[i-4] == 'C') &&
+					(a[i-3] == 'l' || a[i-3] == 'L') &&
+					(a[i-2] == 'a' || a[i-2] == 'A') &&
+					(a[i-1] == 's' || a[i-1] == 'S') &&
+					  (a[i] == 's' ||   a[i] == 'S'))
+			{
+				matchlen = 5;
+				mask |= ACTION_CLASS;
+	
+    		} else if (i >= 6 && 
+					(a[i-6] == 'e' || a[i-6] == 'E') &&
+					(a[i-5] == 'x' || a[i-5] == 'X') &&
+					(a[i-4] == 'e' || a[i-4] == 'E') &&
+					(a[i-3] == 'c' || a[i-3] == 'C') &&
+					(a[i-2] == 'u' || a[i-2] == 'U') &&
+					(a[i-1] == 't' || a[i-1] == 'T') &&
+					  (a[i] == 'e' ||   a[i] == 'E'))
+			{
+				matchlen = 7;
+				mask |= ACTION_EXECUTE;
+				
+			} else if (i >= 17 && 
+					(a[i-17] == 'e' || a[i-17] == 'E') &&
+					(a[i-16] == 'x' || a[i-16] == 'X') &&
+					(a[i-15] == 't' || a[i-15] == 'T') &&
+					(a[i-14] == 'e' || a[i-14] == 'E') &&
+					(a[i-13] == 'n' || a[i-13] == 'N') &&
+					(a[i-12] == 's' || a[i-12] == 'S') &&
+					(a[i-11] == 'i' || a[i-11] == 'I') &&
+					(a[i-10] == 'o' || a[i-10] == 'O') &&
+					(a[i-9] == 'n' || a[i-9] == 'N') &&
+					(a[i-8] == 'l' || a[i-8] == 'L') &&
+					(a[i-7] == 'i' || a[i-7] == 'I') &&
+					(a[i-6] == 'f' || a[i-6] == 'F') &&
+					(a[i-5] == 'e' || a[i-5] == 'E') &&
+					(a[i-4] == 'c' || a[i-4] == 'C') &&
+					(a[i-3] == 'y' || a[i-3] == 'Y') &&
+					(a[i-2] == 'c' || a[i-2] == 'C') &&
+					(a[i-1] == 'l' || a[i-1] == 'L') &&
+					  (a[i] == 'e' ||   a[i] == 'E'))
+    		{
+    			matchlen = 18;
+    			mask |= ACTION_EXTENSIONLIFECYCLE;
+
+    		} else if (i >= 8 && 
+					(a[i-8] == 'l' || a[i-8] == 'L') &&
+					(a[i-7] == 'i' || a[i-7] == 'I') &&
+					(a[i-6] == 'f' || a[i-6] == 'F') &&
+					(a[i-5] == 'e' || a[i-5] == 'E') &&
+					(a[i-4] == 'c' || a[i-4] == 'C') &&
+					(a[i-3] == 'y' || a[i-3] == 'Y') &&
+					(a[i-2] == 'c' || a[i-2] == 'C') &&
+					(a[i-1] == 'l' || a[i-1] == 'L') &&
+					  (a[i] == 'e' ||   a[i] == 'E'))
+			{
+				matchlen = 9;
+				mask |= ACTION_LIFECYCLE;
+				
+			} else if (i >= 7 && 
+					(a[i-7] == 'l' || a[i-7] == 'L') &&
+					(a[i-6] == 'i' || a[i-6] == 'I') &&
+					(a[i-5] == 's' || a[i-5] == 'S') &&
+					(a[i-4] == 't' || a[i-4] == 'T') &&
+					(a[i-3] == 'e' || a[i-3] == 'E') &&
+					(a[i-2] == 'n' || a[i-2] == 'N') &&
+					(a[i-1] == 'e' || a[i-1] == 'E') &&
+					  (a[i] == 'r' ||   a[i] == 'R'))
+			{
+				matchlen = 8;
+				mask |= ACTION_LISTENER;
+			
+			} else if (i >= 7 && 
+    				(a[i-7] == 'm' || a[i-7] == 'M') &&
+    	            (a[i-6] == 'e' || a[i-6] == 'E') &&
+    	            (a[i-5] == 't' || a[i-5] == 'T') &&
+    	            (a[i-4] == 'a' || a[i-4] == 'A') &&
+    	            (a[i-3] == 'd' || a[i-3] == 'D') &&
+    	            (a[i-2] == 'a' || a[i-2] == 'A') &&
+					(a[i-1] == 't' || a[i-1] == 'T') &&
+					  (a[i] == 'a' ||   a[i] == 'A'))
+    		{
+    			matchlen = 8;
+    			mask |= ACTION_METADATA;
+
+    		} else if (i >= 9 && 
+					(a[i-9] == 'p' || a[i-9] == 'P') &&
+					(a[i-8] == 'e' || a[i-8] == 'E') &&
+					(a[i-7] == 'r' || a[i-7] == 'R') &&
+					(a[i-6] == 'm' || a[i-6] == 'M') &&
+					(a[i-5] == 'i' || a[i-5] == 'I') &&
+					(a[i-4] == 's' || a[i-4] == 'S') &&
+					(a[i-3] == 's' || a[i-3] == 'S') &&
+					(a[i-2] == 'i' || a[i-2] == 'I') &&
+					(a[i-1] == 'o' || a[i-1] == 'O') &&
+					  (a[i] == 'n' ||   a[i] == 'N'))
+    		{
+    			matchlen = 10;
+    			mask |= ACTION_PERMISSION;
+			
+    		} else if (i >= 6 && 
+					(a[i-6] == 'r' || a[i-6] == 'R') &&
+					(a[i-5] == 'e' || a[i-5] == 'E') &&
+					(a[i-4] == 's' || a[i-4] == 'S') &&
+					(a[i-3] == 'o' || a[i-3] == 'O') &&
+					(a[i-2] == 'l' || a[i-2] == 'L') &&
+					(a[i-1] == 'v' || a[i-1] == 'V') &&
+					  (a[i] == 'e' ||   a[i] == 'E'))
+    		{
+    			matchlen = 7;
+    			mask |= ACTION_RESOLVE;
+    			
+    		} else if (i >= 7 && 
+    					(a[i-7] == 'r' || a[i-7] == 'R') &&
+						(a[i-6] == 'e' || a[i-6] == 'E') &&
+						(a[i-5] == 's' || a[i-5] == 'S') &&
+						(a[i-4] == 'o' || a[i-4] == 'O') &&
+						(a[i-3] == 'u' || a[i-3] == 'U') &&
+						(a[i-2] == 'r' || a[i-2] == 'R') &&
+						(a[i-1] == 'c' || a[i-1] == 'C') &&
+						  (a[i] == 'e' ||   a[i] == 'E'))
+			{
+    			matchlen = 8;
+    			mask |= ACTION_RESOURCE;
+
+    		} else if (i >= 9 && 
+					(a[i-9] == 's' || a[i-9] == 'S') &&
+					(a[i-8] == 't' || a[i-8] == 'T') &&
+					(a[i-7] == 'a' || a[i-7] == 'A') &&
+					(a[i-6] == 'r' || a[i-6] == 'R') &&
+					(a[i-5] == 't' || a[i-5] == 'T') &&
+					(a[i-4] == 'l' || a[i-4] == 'L') &&
+					(a[i-3] == 'e' || a[i-3] == 'E') &&
+					(a[i-2] == 'v' || a[i-2] == 'V') &&
+					(a[i-1] == 'e' || a[i-1] == 'E') &&
+					  (a[i] == 'l' ||   a[i] == 'L'))
+    		{
+    			matchlen = 10;
+    			mask |= ACTION_STARTLEVEL;
+
+    		} else if (i >= 0 && 
+					(a[i] == '*'))
+    		{
+    			matchlen = 1;
+    			mask |= ACTION_ALL;
+
+			} else {
+				// parse error
+				throw new IllegalArgumentException(
+						"invalid permission: " + actions);
+        }
+
+        // make sure we didn't just match the tail of a word
+        // like "ackbarfstartlevel".  Also, skip to the comma.
+        seencomma = false;
+        while (i >= matchlen && !seencomma) {
+        	switch(a[i-matchlen]) {
+        		case ',':
+        			seencomma = true;
+        			/*FALLTHROUGH*/
+        		case ' ': case '\r': case '\n':
+        		case '\f': case '\t':
+        			break;
+        		default:
+        			throw new IllegalArgumentException(
+        					"invalid permission: " + actions);
+        	}
+        	i--;
+        }
+
+        // point i at the location of the comma minus one (or -1).
+        i -= matchlen;
+    }
+
+    if (seencomma) {
+        throw new IllegalArgumentException("invalid permission: " +
+                        actions);
+    }
+
+    return mask;
+    }
+     
+    /**
+     * Called by <code><@link AdminPermission#implies(Permission)></code> on an AdminPermission
+     * which was constructed with a Bundle.  This method loads a dictionary with the
+     * filter-matchable properties of this bundle.  The dictionary is cached so this lookup
+     * only happens once.
+     * 
+     * This method should only be called on an AdminPermission which was constructed with a 
+     * bundle
+     * 
+     * @return a dictionary of properties for this bundle
+     */
+    private Dictionary getProperties() {
+    	if (bundleProperties == null) {
+    		bundleProperties = new Hashtable();
+
+    		AccessController.doPrivileged(new PrivilegedAction() {
+				public Object run() {
+		    		//set Id
+		    		bundleProperties.put("id",new Long(bundle.getBundleId())); //$NON-NLS-1$
+		    		
+		    		//set location
+		    		bundleProperties.put("location",bundle.getLocation()); //$NON-NLS-1$
+		    		
+		    		//set name
+		    		if (bundle.getSymbolicName() != null)
+		    			bundleProperties.put("name",bundle.getSymbolicName()); //$NON-NLS-1$
+		    		
+		    		//set signers
+//		    		bundleProperties.put("signer",new SignerWrapper(bundle)); //$NON-NLS-1$
+		    		
+		    		return null;
+				}
+			});
+    	}     		
+    	return bundleProperties;
+    }
+/*
+    private static class SignerWrapper extends Object {
+    	private Bundle bundle;
+    	private String pattern;
+    	public SignerWrapper(String pattern) {
+    		this.pattern = pattern;    			
+    	}
+    	SignerWrapper(Bundle bundle) {
+    		this.bundle = bundle;
+    	}
+    	
+		public boolean equals(Object o) {
+			if (!(o instanceof SignerWrapper))
+				return false;
+			SignerWrapper other = (SignerWrapper) o;
+			AbstractBundle matchBundle = (AbstractBundle) (bundle != null ? bundle : other.bundle);
+			String matchPattern = bundle != null ? other.pattern : pattern;
+			return matchBundle.getBundleData().matchDNChain(matchPattern);
+		}
+    }
+*/    
+
+    /**
+     * Called by <tt><@link AdminPermission#implies(Permission)></tt> on an AdminPermission
+     * which was constructed with a filter.  This method loads a FilterImpl with the
+     * filter specification of this AdminPermission.  The filter is cached so this work
+     * only happens once.
+     * 
+     * This method should only be called on an AdminPermission which was constructed with a 
+     * filter
+     * 
+     * @return a filterImpl for this bundle
+     */
+    private Filter getFilterImpl() {
+        if (filterImpl == null) {
+            try {
+                int pos = filter.indexOf("signer"); //$NON-NLS-1$
+                if (pos != -1){ 
+                
+                    //there may be a signer attribute 
+                    StringBuffer filterBuf = new StringBuffer(filter);
+                    int numAsteriskFound = 0; //use as offset to replace in buffer
+                    
+                    int walkbackPos; //temp pos
+
+                    //find occurences of (signer= and escape out *'s
+                    while (pos != -1) {
+
+                        //walk back and look for '(' to see if this is an attr
+                        walkbackPos = pos-1; 
+                        
+                        //consume whitespace
+                        while(walkbackPos >= 0 && Character.isWhitespace(filter.charAt(walkbackPos))) {
+                            walkbackPos--;
+                        }
+                        if (walkbackPos <0) {
+                            //filter is invalid - FilterImpl will throw error
+                            break;
+                        }
+                        
+                        //check to see if we have unescaped '('
+                        if (filter.charAt(walkbackPos) != '(' || (walkbackPos > 0 && filter.charAt(walkbackPos-1) == '\\')) {
+                            //'(' was escaped or not there
+                            pos = filter.indexOf("signer",pos+6); //$NON-NLS-1$
+                            continue;
+                        }                   
+                        pos+=6; //skip over 'signer'
+
+                        //found signer - consume whitespace before '='
+                        while (Character.isWhitespace(filter.charAt(pos))) {
+                            pos++;
+                        }
+
+                        //look for '='
+                        if (filter.charAt(pos) != '=') {
+                            //attr was signerx - keep looking
+                            pos = filter.indexOf("signer",pos); //$NON-NLS-1$
+                            continue;
+                        }
+                        pos++; //skip over '='
+                        
+                        //found signer value - escape '*'s
+                        while (!(filter.charAt(pos) == ')' && filter.charAt(pos-1) != '\\')) {
+                            if (filter.charAt(pos) == '*') {
+                                filterBuf.insert(pos+numAsteriskFound,'\\');
+                                numAsteriskFound++;
+                            }
+                            pos++;
+                        }
+
+                        //end of signer value - look for more?
+                        pos = filter.indexOf("signer",pos); //$NON-NLS-1$
+                    } //end while (pos != -1)
+                    filter = filterBuf.toString();
+                } //end if (pos != -1)
+
+                filterImpl = new FilterImpl(filter);
+            } catch (InvalidSyntaxException e) {
+                //we will return null
+            }
+        }           
+        return filterImpl;
+    }
+
+    /**
+     * Determines if the specified permission is implied by this object.
+     * This method throws an exception if the specified permission was not
+     * constructed with a bundle.
+     * 
+     * <p>This method returns <code>true</code> if
+     * The specified permission is an AdminPermission AND
+     * <ul>
+     * 	<li>this object's filter is an X.500 Distinguished name suffix that 
+     * matches the specified permission's bundle OR
+     * 	<li>this object's filter is "*" OR
+     * 	<li>this object's bundle is a equal to the specified permission's
+     * bundle
+     * </ul>
+     * AND this object's actions include all of the specified permission's actions 	 
+     *
+     * Special case: if the specified permission was constructed with "*", then this method
+     * returns <code>true</code> if this object's filter is "*" and this object's actions include
+     * all of the specified permission's actions
+     * 
+     * @param p The permission to interrogate.
+     *
+     * @return <code>true</code> if the specified permission is implied by
+     * this object; <code>false</code> otherwise.
+     * @throws RuntimeException if specified permission was not constructed with
+     * a bundle or "*"
+     */
+    public boolean implies(Permission p)
+    {
+    	if (!(p instanceof AdminPermission))
+    		return false;
+    	AdminPermission target = (AdminPermission)p;
+    	//check actions first - much faster
+    	if ((action_mask & target.action_mask)!=target.action_mask)
+    		return false;
+    	//if passed in a filter, puke
+    	if (target.filter != null)
+    		throw new RuntimeException("Cannot imply a filter");
+    	//special case - only wildcard implies wildcard
+    	if (target.wildcard)
+    		return wildcard;
+
+    	//check our name 
+    	if (filter != null) {
+    		//it's a filter
+    		Filter filterImpl = getFilterImpl();
+			return filterImpl != null && filterImpl.match(target.getProperties());
+    	} else if (wildcard) {
+    		//it's "*"
+    		return true;
+    	} else {
+    		//it's a bundle id
+    		return bundle.equals(target.bundle);
+    	}
+    	    	
+    }
+    
+    /**
+     * Returns the canonical string representation of the <code>AdminPermission</code> actions.
+     *
+     * <p>Always returns present <code>AdminPermission</code> actions in the following order:
+     * <code>CLASS</code>, <code>EXECUTE</code>, <code>LIFECYCLE</code>, <code>LISTENER</code>, 
+     * <code>METADATA</code>, <code>PERMISSION</code>, <code>RESOLVE</code>, <code>RESOURCE</code>, 
+     * <code>STARTLEVEL</code>.
+     * @return Canonical string representation of the <code>AdminPermission</code> actions.
+     */
+	public String getActions() {
+		if (actions == null) {
+			if (action_mask == ACTION_ALL) {
+				actions = "*"; //$NON-NLS-1$
+			} else {
+				StringBuffer sb = new StringBuffer();
+				
+				if ((action_mask & ACTION_CLASS) == ACTION_CLASS) {
+					sb.append(CLASS);
+					sb.append(',');
+				}
+
+				if ((action_mask & ACTION_EXECUTE) == ACTION_EXECUTE) {
+					sb.append(EXECUTE);
+					sb.append(',');
+				}
+	
+				if ((action_mask & ACTION_LIFECYCLE) == ACTION_LIFECYCLE) {
+					sb.append(LIFECYCLE);
+					sb.append(',');
+				}
+	
+				if ((action_mask & ACTION_LISTENER) == ACTION_LISTENER) {
+					sb.append(LISTENER);
+					sb.append(',');
+				}
+				
+				if ((action_mask & ACTION_METADATA) == ACTION_METADATA) {
+					sb.append(METADATA);
+					sb.append(',');
+				}
+	
+				if ((action_mask & ACTION_PERMISSION) == ACTION_PERMISSION) {
+					sb.append(PERMISSION);
+					sb.append(',');
+				}
+	
+				if ((action_mask & ACTION_RESOLVE) == ACTION_RESOLVE) {
+					sb.append(RESOLVE);
+					sb.append(',');
+				}
+	
+				if ((action_mask & ACTION_RESOURCE) == ACTION_RESOURCE) {
+					sb.append(RESOURCE);
+					sb.append(',');
+				}
+	
+				if ((action_mask & ACTION_STARTLEVEL) == ACTION_STARTLEVEL) {
+					sb.append(STARTLEVEL);
+					sb.append(',');
+				}
+
+				if ((action_mask & ACTION_EXTENSIONLIFECYCLE) == ACTION_EXTENSIONLIFECYCLE) {
+					sb.append(EXTENSIONLIFECYCLE);
+					sb.append(',');
+				}
+
+				//remove trailing comma
+				if (sb.length() > 0) {
+					sb.deleteCharAt(sb.length()-1);
+				}
+				
+				actions = sb.toString();
+			}
+		}
+		return actions;
+	}
+	
+    /**
+     * Determines the equality of two <code>AdminPermission</code> objects. <p>Two 
+     * <code>AdminPermission</code> objects are equal.
+     *
+     * @param obj The object being compared for equality with this object.
+     * @return <code>true</code> if <code>obj</code> is equivalent to this 
+     * <code>AdminPermission</code>; <code>false</code> otherwise.
+     */
+    public boolean equals(Object obj)
+    {
+        if (obj == this) {
+        	return true;
+        }
+        
+        if (!(obj instanceof AdminPermission))
+        {
+            return false;
+        }
+        
+        AdminPermission a = (AdminPermission) obj;
+
+        return (action_mask == a.action_mask) &&
+        		(wildcard == a.wildcard) &&
+        		(bundle == null ? a.bundle == null : (a.bundle == null ? false : bundle.getBundleId() == a.bundle.getBundleId())) &&
+				(filter == null ? a.filter == null : filter.equals(a.filter));
+    }
+
+    /**
+     * Returns the hash code value for this object.
+     *
+     * @return Hash code value for this object.
+     */
+	public int hashCode() {
+		return getName().hashCode() ^ getActions().hashCode();
+	}
+
+	private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException {
+		// Write out the actions. The superclass takes care of the name
+		// call getActions to make sure actions field is initialized
+		if (actions == null)
+			getActions();
+		if (filter == null && !wildcard)
+			throw new UnsupportedOperationException("cannot serialize");
+		s.defaultWriteObject();
+	}
+
+	/**
+	 * readObject is called to restore the state of this permission from a
+	 * stream.
+	 */
+	private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
+		// Read in the action, then initialize the rest
+		s.defaultReadObject();
+		action_mask = getMask(actions);
+	}
+
+    /**
+     * Returns a new <code>PermissionCollection</code> object suitable for storing
+     * <code>AdminPermission</code>s.
+     * 
+     * @return A new <code>PermissionCollection</code> object.
+     */
+    public PermissionCollection newPermissionCollection()
+    {
+        return(new AdminPermissionCollection());
+    }
+
+	/**
+	 * Stores a collection of <code>AdminPermission</code>s.
+	 */
+	private final class AdminPermissionCollection extends PermissionCollection
+	{
+		private static final long serialVersionUID = 3906372644575328048L;
+		/**
+	     * Collection of permissions.
+	     *
+	     * @serial
+	     */
+		private Hashtable permissions;
+	
+	    /**
+	     * Create an empty AdminPermissions object.
+	     *
+	     */
+	
+	    public AdminPermissionCollection()
+	    {
+	        permissions = new Hashtable();        
+	    }
+
+	    /**
+	     * Adds a permission to the <code>AdminPermission</code> objects. The key for 
+	     * the hashtable is the name
+	     *
+	     * @param permission The <code>AdminPermission</code> object to add.
+	     *
+	     * @exception IllegalArgumentException If the permission is not an
+	     * <code>AdminPermission</code> instance.
+	     *
+	     * @exception SecurityException If this <code>AdminPermissionCollection</code>
+	     * object has been marked read-only.
+	     */
+	    public void add(Permission permission)
+	    {
+	        if (! (permission instanceof AdminPermission))
+	            throw new IllegalArgumentException("invalid permission: "+
+	                                               permission);
+	        if (isReadOnly())
+	            throw new SecurityException("attempt to add a Permission to a " +
+	                                        "readonly AdminCollection");
+	        AdminPermission ap = (AdminPermission) permission;
+	    	AdminPermission existing = (AdminPermission) permissions.get(ap.getName());
+	    	if (existing != null){
+	    		int oldMask = existing.action_mask;
+	    		int newMask = ap.action_mask;
+	        
+	    		if (oldMask != newMask) {
+	    			permissions.put(existing.getName(),
+	    					new AdminPermission(existing.getName(), oldMask | newMask));
+	    		}
+	    	} else {
+	    		permissions.put(ap.getName(), ap);
+	    	}
+	    }
+	
+	
+	    /**
+	     * Determines if the specified permissions implies the permissions
+	     * expressed in <code>permission</code>.
+	     *
+	     * @param permission The Permission object to compare with the <code>AdminPermission</code>
+	     *  objects in this collection.
+	     *
+	     * @return <code>true</code> if <code>permission</code> is implied by an 
+	     * <code>AdminPermission</code> in this collection, <code>false</code> otherwise.
+	     */
+	    public boolean implies(Permission permission)
+	    {
+	        if (!(permission instanceof AdminPermission))
+	            return(false);
+	
+	        AdminPermission target = (AdminPermission) permission;
+	        
+	        //just iterate one by one
+	        Iterator permItr = permissions.values().iterator();
+	        
+	        while(permItr.hasNext())
+	        	if (((AdminPermission)permItr.next()).implies(target))
+	        		return true;
+	        return false;
+	    }
+	 
+	
+	    /**
+	     * Returns an enumeration of all <code>AdminPermission</code> objects in the
+	     * container.
+	     *
+	     * @return Enumeration of all <code>AdminPermission</code> objects.
+	     */
+	
+	    public Enumeration elements()
+	    {
+	        return(Collections.enumeration(permissions.values()));
+	    }
+	}
+}
\ No newline at end of file
diff --git a/src/org/osgi/framework/AllServiceListener.java b/src/org/osgi/framework/AllServiceListener.java
new file mode 100644
index 0000000..6de64bc
--- /dev/null
+++ b/src/org/osgi/framework/AllServiceListener.java
@@ -0,0 +1,48 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/AllServiceListener.java,v 1.5 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+/**
+ * A <code>ServiceEvent</code> listener.
+ *
+ * <p><code>AllServiceListener</code> is a listener interface that may be implemented by a bundle
+ * developer.
+ * <p>An <code>AllServiceListener</code> object is registered with the Framework using the
+ * <code>BundleContext.addServiceListener</code> method.
+ * <code>AllServiceListener</code> objects are called with a <code>ServiceEvent</code> object when
+ * a service is registered, modified, or is in the process of unregistering.
+ *
+ * <p><code>ServiceEvent</code> object delivery to <code>AllServiceListener</code> objects is filtered by the
+ * filter specified when the listener was registered. If the Java Runtime Environment
+ * supports permissions, then additional filtering is done.
+ * <code>ServiceEvent</code> objects are only delivered to the listener if the bundle which defines
+ * the listener object's class has the appropriate <code>ServicePermission</code> to get the service
+ * using at least one of the named classes the service was registered under.
+ * 
+ * <p>
+ * Unlike normal <code>ServiceListener</code> objects,
+ * <code>AllServiceListener</code> objects receive all ServiceEvent objects regardless of the
+ * whether the package source of the listening bundle is equal to the package source of
+ * the bundle that registered the service. This means that the listener may not be able to
+ * cast the service object to any of its corresponding service interfaces if the service
+ * object is retrieved.
+ * 
+ * @version $Revision: 1.5 $
+ * @see ServiceEvent
+ * @see ServicePermission
+ */
+
+public abstract interface AllServiceListener extends ServiceListener
+{
+	//This is a marker interface
+}
+
+
diff --git a/src/org/osgi/framework/Bundle.java b/src/org/osgi/framework/Bundle.java
new file mode 100644
index 0000000..de19d9f
--- /dev/null
+++ b/src/org/osgi/framework/Bundle.java
@@ -0,0 +1,932 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/Bundle.java,v 1.27 2005/06/21 16:37:35 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+/**
+ * An installed bundle in the Framework.
+ * 
+ * <p>
+ * A <code>Bundle</code> object is the access point to define the lifecycle of
+ * an installed bundle. Each bundle installed in the OSGi environment must have
+ * an associated <code>Bundle</code> object.
+ * 
+ * <p>
+ * A bundle must have a unique identity, a <code>long</code>, chosen by the
+ * Framework. This identity must not change during the lifecycle of a bundle,
+ * even when the bundle is updated. Uninstalling and then reinstalling the
+ * bundle must create a new unique identity.
+ * 
+ * <p>
+ * A bundle can be in one of six states:
+ * <ul>
+ * <li>{@link #UNINSTALLED}
+ * <li>{@link #INSTALLED}
+ * <li>{@link #RESOLVED}
+ * <li>{@link #STARTING}
+ * <li>{@link #STOPPING}
+ * <li>{@link #ACTIVE}
+ * </ul>
+ * <p>
+ * Values assigned to these states have no specified ordering; they represent
+ * bit values that may be ORed together to determine if a bundle is in one of
+ * the valid states.
+ * 
+ * <p>
+ * A bundle should only execute code when its state is one of
+ * <code>STARTING</code>,<code>ACTIVE</code>, or <code>STOPPING</code>.
+ * An <code>UNINSTALLED</code> bundle can not be set to another state; it is a
+ * zombie and can only be reached because references are kept somewhere.
+ * 
+ * <p>
+ * The Framework is the only entity that is allowed to create
+ * <code>Bundle</code> objects, and these objects are only valid within the
+ * Framework that created them.
+ * 
+ * @version $Revision: 1.27 $
+ */
+public abstract interface Bundle {
+	/**
+	 * This bundle is uninstalled and may not be used.
+	 * 
+	 * <p>
+	 * The <code>UNINSTALLED</code> state is only visible after a bundle is
+	 * uninstalled; the bundle is in an unusable state but references to the
+	 * <code>Bundle</code> object may still be available and used for
+	 * introspection.
+	 * <p>
+	 * The value of <code>UNINSTALLED</code> is 0x00000001.
+	 */
+	public static final int	UNINSTALLED	= 0x00000001;
+
+	/**
+	 * This bundle is installed but not yet resolved.
+	 * 
+	 * <p>
+	 * A bundle is in the <code>INSTALLED</code> state when it has been
+	 * installed in the Framework but cannot run.
+	 * <p>
+	 * This state is visible if the bundle's code dependencies are not resolved.
+	 * The Framework may attempt to resolve an <code>INSTALLED</code> bundle's
+	 * code dependencies and move the bundle to the <code>RESOLVED</code>
+	 * state.
+	 * <p>
+	 * The value of <code>INSTALLED</code> is 0x00000002.
+	 */
+	public static final int	INSTALLED	= 0x00000002;
+
+	/**
+	 * This bundle is resolved and is able to be started.
+	 * 
+	 * <p>
+	 * A bundle is in the <code>RESOLVED</code> state when the Framework has
+	 * successfully resolved the bundle's dependencies. These dependencies
+	 * include:
+	 * <ul>
+	 * <li>The bundle's class path from its {@link Constants#BUNDLE_CLASSPATH}
+	 * Manifest header.
+	 * <li>The bundle's package dependencies from its
+	 * {@link Constants#EXPORT_PACKAGE}and {@link Constants#IMPORT_PACKAGE}
+	 * Manifest headers.
+	 * <li>The bundle's required bundle dependencies from its
+	 * {@link Constants#REQUIRE_BUNDLE}Manifest header.
+	 * <li>A fragment bundle's host dependency from its
+	 * {@link Constants#FRAGMENT_HOST}Manifest header.
+	 * </ul>
+	 * <p>
+	 * Note that the bundle is not active yet. A bundle must be put in the
+	 * <code>RESOLVED</code> state before it can be started. The Framework may
+	 * attempt to resolve a bundle at any time. 
+	 * <p>
+	 * The value of <code>RESOLVED</code> is 0x00000004.
+	 */
+	public static final int	RESOLVED	= 0x00000004;
+
+	/**
+	 * This bundle is in the process of starting.
+	 * 
+	 * <p>
+	 * A bundle is in the <code>STARTING</code> state when the {@link #start}
+	 * method is active. A bundle must be in this state when the bundle's
+	 * {@link BundleActivator#start}is called. If this method completes without
+	 * exception, then the bundle has successfully started and must move to the
+	 * <code>ACTIVE</code> state.
+	 * <p>
+	 * The value of <code>STARTING</code> is 0x00000008.
+	 */
+	public static final int	STARTING	= 0x00000008;
+
+	/**
+	 * This bundle is in the process of stopping.
+	 * 
+	 * <p>
+	 * A bundle is in the <code>STOPPING</code> state when the {@link #stop}
+	 * method is active. A bundle must be in this state when the bundle's
+	 * {@link BundleActivator#stop}method is called. When this method completes
+	 * the bundle is stopped and must move to the <code>RESOLVED</code> state.
+	 * <p>
+	 * The value of <code>STOPPING</code> is 0x00000010.
+	 */
+	public static final int	STOPPING	= 0x00000010;
+
+	/**
+	 * This bundle is now running.
+	 * 
+	 * <p>
+	 * A bundle is in the <code>ACTIVE</code> state when it has been
+	 * successfully started.
+	 * <p>
+	 * The value of <code>ACTIVE</code> is 0x00000020.
+	 */
+	public static final int	ACTIVE		= 0x00000020;
+
+	/**
+	 * Returns this bundle's current state.
+	 * 
+	 * <p>
+	 * A bundle can be in only one state at any time.
+	 * 
+	 * @return An element of <code>UNINSTALLED</code>,<code>INSTALLED</code>,
+	 *         <code>RESOLVED</code>,<code>STARTING</code>,
+	 *         <code>STOPPING</code>,<code>ACTIVE</code>.
+	 */
+	public abstract int getState();
+
+	/**
+	 * Starts this bundle.
+	 * 
+	 * <p>
+	 * If the Framework implements the optional Start Level service and the
+	 * current start level is less than this bundle's start level, then the
+	 * Framework must persistently mark this bundle as started and delay the
+	 * starting of this bundle until the Framework's current start level becomes
+	 * equal or more than the bundle's start level.
+	 * <p>
+	 * Otherwise, the following steps are required to start a bundle:
+	 * <ol>
+	 * <li>If this bundle's state is <code>UNINSTALLED</code> then an
+	 * <code>IllegalStateException</code> is thrown.
+	 * 
+	 * <li>If this bundle's state is <code>STARTING</code> or
+	 * <code>STOPPING</code> then this method must wait for this bundle to
+	 * change state before continuing. If this does not occur in a reasonable
+	 * time, a <code>BundleException</code> is thrown to indicate this bundle
+	 * was unable to be started.
+	 * 
+	 * <li>If this bundle's state is <code>ACTIVE</code> then this method
+	 * returns immediately.
+	 * 
+	 * <li>Persistently record that this bundle has been started. When the
+	 * Framework is restarted, this bundle must be automatically started.
+	 * 
+	 * <li>If this bundle's state is not <code>RESOLVED</code>, an attempt
+	 * is made to resolve this bundle's package dependencies. If the Framework
+	 * cannot resolve this bundle, a <code>BundleException</code> is thrown.
+	 * 
+	 * <li>This bundle's state is set to <code>STARTING</code>.
+	 * 
+	 * <li>The {@link BundleActivator#start}method of this bundle's
+	 * <code>BundleActivator</code>, if one is specified, is called. If the
+	 * <code>BundleActivator</code> is invalid or throws an exception, this
+	 * bundle's state is set back to <code>RESOLVED</code>.<br>
+	 * Any services registered by the bundle must be unregistered. <br>
+	 * Any services used by the bundle must be released. <br>
+	 * Any listeners registered by the bundle must be removed. <br>
+	 * A <code>BundleException</code> is then thrown.
+	 * 
+	 * <li>If this bundle's state is <code>UNINSTALLED</code>, because the
+	 * bundle was uninstalled while the <code>BundleActivator.start</code>
+	 * method was running, a <code>BundleException</code> is thrown.
+	 * 
+	 * <li>This bundle's state is set to <code>ACTIVE</code>.
+	 * 
+	 * <li>A bundle event of type {@link BundleEvent#STARTED}is broadcast.
+	 * </ol>
+	 * 
+	 * <b>Preconditions </b>
+	 * <ul>
+	 * <li><code>getState()</code> in {<code>INSTALLED</code>}, {
+	 * <code>RESOLVED</code>}.
+	 * </ul>
+	 * <b>Postconditions, no exceptions thrown </b>
+	 * <ul>
+	 * <li>Bundle persistent state is marked as active.
+	 * <li><code>getState()</code> in {<code>ACTIVE</code>}.
+	 * <li><code>BundleActivator.start()</code> has been called and did not
+	 * throw an exception.
+	 * </ul>
+	 * <b>Postconditions, when an exception is thrown </b>
+	 * <ul>
+	 * <li>Depending on when the exception occurred, bundle persistent state is
+	 * marked as active.
+	 * <li><code>getState()</code> not in {<code>STARTING</code>}, {
+	 * <code>ACTIVE</code>}.
+	 * </ul>
+	 * 
+	 * @exception BundleException If this bundle could not be started. This
+	 *            could be because a code dependency could not be resolved or
+	 *            the specified <code>BundleActivator</code> could not be
+	 *            loaded or threw an exception.
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled or this bundle tries to change its own state.
+	 * @exception java.lang.SecurityException If the caller does not have the
+	 *            appropriate <code>AdminPermission[bundle, EXECUTE]</code>,
+	 *            and the Java Runtime Environment supports permissions.
+	 */
+	public abstract void start() throws BundleException;
+
+	/**
+	 * Stops this bundle.
+	 * 
+	 * <p>
+	 * The following steps are required to stop a bundle:
+	 * <ol>
+	 * <li>If this bundle's state is <code>UNINSTALLED</code> then an
+	 * <code>IllegalStateException</code> is thrown.
+	 * 
+	 * <li>If this bundle's state is <code>STARTING</code> or
+	 * <code>STOPPING</code> then this method must wait for this bundle to
+	 * change state before continuing. If this does not occur in a reasonable
+	 * time, a <code>BundleException</code> is thrown to indicate this bundle
+	 * was unable to be stopped.
+	 * 
+	 * <li>Persistently record that this bundle has been stopped. When the
+	 * Framework is restarted, this bundle must not be automatically started.
+	 * 
+	 * <li>If this bundle's state is not <code>ACTIVE</code> then this method
+	 * returns immediately.
+	 * 
+	 * <li>This bundle's state is set to <code>STOPPING</code>.
+	 * 
+	 * <li>The {@link BundleActivator#stop}method of this bundle's
+	 * <code>BundleActivator</code>, if one is specified, is called. If that
+	 * method throws an exception, this method must continue to stop this
+	 * bundle. A <code>BundleException</code> must be thrown after completion
+	 * of the remaining steps.
+	 * 
+	 * <li>Any services registered by this bundle must be unregistered.
+	 * <li>Any services used by this bundle must be released.
+	 * <li>Any listeners registered by this bundle must be removed.
+	 * 
+	 * <li>If this bundle's state is <code>UNINSTALLED</code>, because the
+	 * bundle was uninstalled while the <code>BundleActivator.stop</code>
+	 * method was running, a <code>BundleException</code> must be thrown.
+	 * 
+	 * <li>This bundle's state is set to <code>RESOLVED</code>.
+	 * 
+	 * <li>A bundle event of type {@link BundleEvent#STOPPED}is broadcast.
+	 * </ol>
+	 * 
+	 * <b>Preconditions </b>
+	 * <ul>
+	 * <li><code>getState()</code> in {<code>ACTIVE</code>}.
+	 * </ul>
+	 * <b>Postconditions, no exceptions thrown </b>
+	 * <ul>
+	 * <li>Bundle persistent state is marked as stopped.
+	 * <li><code>getState()</code> not in {<code>ACTIVE</code>,
+	 * <code>STOPPING</code>}.
+	 * <li><code>BundleActivator.stop</code> has been called and did not
+	 * throw an exception.
+	 * </ul>
+	 * <b>Postconditions, when an exception is thrown </b>
+	 * <ul>
+	 * <li>Bundle persistent state is marked as stopped.
+	 * </ul>
+	 * 
+	 * @exception BundleException If this bundle's <code>BundleActivator</code>
+	 *            could not be loaded or threw an exception.
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled or this bundle tries to change its own state.
+	 * @exception java.lang.SecurityException If the caller does not have the
+	 *            appropriate <code>AdminPermission[bundle, EXECUTE]</code>,
+	 *            and the Java Runtime Environment supports permissions.
+	 */
+	public abstract void stop() throws BundleException;
+
+	/**
+	 * Updates this bundle.
+	 * 
+	 * <p>
+	 * If this bundle's state is <code>ACTIVE</code>, it must be stopped
+	 * before the update and started after the update successfully completes.
+	 * 
+	 * <p>
+	 * If the bundle being updated has exported any packages, these packages
+	 * must not be updated. Instead, the previous package version must remain
+	 * exported until the <code>PackageAdmin.refreshPackages</code> method has
+	 * been has been called or the Framework is relaunched.
+	 * 
+	 * <p>
+	 * The following steps are required to update a bundle:
+	 * <ol>
+	 * <li>If this bundle's state is <code>UNINSTALLED</code> then an
+	 * <code>IllegalStateException</code> is thrown.
+	 * 
+	 * <li>If this bundle's state is <code>ACTIVE</code>,
+	 * <code>STARTING</code> or <code>STOPPING</code>, the bundle is
+	 * stopped as described in the <code>Bundle.stop</code> method. If
+	 * <code>Bundle.stop</code> throws an exception, the exception is rethrown
+	 * terminating the update.
+	 * 
+	 * <li>The download location of the new version of this bundle is
+	 * determined from either the bundle's
+	 * {@link Constants#BUNDLE_UPDATELOCATION}Manifest header (if available) or
+	 * the bundle's original location.
+	 * 
+	 * <li>The location is interpreted in an implementation dependent manner,
+	 * typically as a URL, and the new version of this bundle is obtained from
+	 * this location.
+	 * 
+	 * <li>The new version of this bundle is installed. If the Framework is
+	 * unable to install the new version of this bundle, the original version of
+	 * this bundle must be restored and a <code>BundleException</code> must be
+	 * thrown after completion of the remaining steps.
+	 * 
+	 * <li>If the bundle has declared an Bundle-RequiredExecutionEnvironment
+	 * header, then the listed execution environments must be verified against
+	 * the installed execution environments. If they do not all match, the
+	 * original version of this bundle must be restored and a
+	 * <code>BundleException</code> must be thrown after completion of the
+	 * remaining steps.
+	 * 
+	 * <li>This bundle's state is set to <code>INSTALLED</code>.
+	 * 
+	 * <li>If the new version of this bundle was successfully installed, a
+	 * bundle event of type {@link BundleEvent#UPDATED}is broadcast.
+	 * 
+	 * <li>If this bundle's state was originally <code>ACTIVE</code>, the
+	 * updated bundle is started as described in the <code>Bundle.start</code>
+	 * method. If <code>Bundle.start</code> throws an exception, a Framework
+	 * event of type {@link FrameworkEvent#ERROR}is broadcast containing the
+	 * exception.
+	 * </ol>
+	 * 
+	 * <b>Preconditions </b>
+	 * <ul>
+	 * <li><code>getState()</code> not in {<code>UNINSTALLED</code>}.
+	 * </ul>
+	 * <b>Postconditions, no exceptions thrown </b>
+	 * <ul>
+	 * <li><code>getState()</code> in {<code>INSTALLED</code>,
+	 * <code>RESOLVED</code>,<code>ACTIVE</code>}.
+	 * <li>This bundle has been updated.
+	 * </ul>
+	 * <b>Postconditions, when an exception is thrown </b>
+	 * <ul>
+	 * <li><code>getState()</code> in {<code>INSTALLED</code>,
+	 * <code>RESOLVED</code>,<code>ACTIVE</code>}.
+	 * <li>Original bundle is still used; no update occurred.
+	 * </ul>
+	 * 
+	 * @exception BundleException If the update fails.
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled or this bundle tries to change its own state.
+	 * @exception java.lang.SecurityException If the caller does not have the
+	 *            appropriate <code>AdminPermission[bundle, LIFECYCLE]</code> for both
+	 *            the current bundle and the updated bundle,
+	 *            and the Java Runtime Environment supports permissions.
+	 * @see #stop()
+	 * @see #start()
+	 */
+	public abstract void update() throws BundleException;
+
+	/**
+	 * Updates this bundle from an <code>InputStream</code>.
+	 * 
+	 * <p>
+	 * This method performs all the steps listed in <code>Bundle.update()</code>,
+	 * except the bundle must be read from the supplied <code>InputStream</code>,
+	 * rather than a <code>URL</code>.
+	 * <p>
+	 * This method must always close the <code>InputStream</code> when it is
+	 * done, even if an exception is thrown.
+	 * 
+	 * @param in The <code>InputStream</code> from which to read the new
+	 *        bundle.
+	 * @exception BundleException If the provided stream cannot be read or the
+	 *            update fails.
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled or this bundle tries to change its own state.
+	 * @exception java.lang.SecurityException If the caller does not have the
+	 *            appropriate <code>AdminPermission[bundle, LIFECYCLE]</code> for both
+	 *            the current bundle and the updated bundle,
+	 *            and the Java Runtime Environment supports permissions.
+	 * @see #update()
+	 */
+	public abstract void update(InputStream in) throws BundleException;
+
+	/**
+	 * Uninstalls this bundle.
+	 * 
+	 * <p>
+	 * This method causes the Framework to notify other bundles that this bundle
+	 * is being uninstalled, and then puts this bundle into the
+	 * <code>UNINSTALLED</code> state. The Framework must remove any resources
+	 * related to this bundle that it is able to remove.
+	 * 
+	 * <p>
+	 * If this bundle has exported any packages, the Framework must continue to
+	 * make these packages available to their importing bundles until the
+	 * <code>PackageAdmin.refreshPackages</code> method has been called or the
+	 * Framework is relaunched.
+	 * 
+	 * <p>
+	 * The following steps are required to uninstall a bundle:
+	 * <ol>
+	 * <li>If this bundle's state is <code>UNINSTALLED</code> then an
+	 * <code>IllegalStateException</code> is thrown.
+	 * 
+	 * <li>If this bundle's state is <code>ACTIVE</code>,
+	 * <code>STARTING</code> or <code>STOPPING</code>, this bundle is
+	 * stopped as described in the <code>Bundle.stop</code> method. If
+	 * <code>Bundle.stop</code> throws an exception, a Framework event of type
+	 * {@link FrameworkEvent#ERROR}is broadcast containing the exception.
+	 * 
+	 * <li>This bundle's state is set to <code>UNINSTALLED</code>.
+	 * 
+	 * <li>A bundle event of type {@link BundleEvent#UNINSTALLED}is broadcast.
+	 * 
+	 * <li>This bundle and any persistent storage area provided for this bundle
+	 * by the Framework are removed.
+	 * </ol>
+	 * 
+	 * <b>Preconditions </b>
+	 * <ul>
+	 * <li><code>getState()</code> not in {<code>UNINSTALLED</code>}.
+	 * </ul>
+	 * <b>Postconditions, no exceptions thrown </b>
+	 * <ul>
+	 * <li><code>getState()</code> in {<code>UNINSTALLED</code>}.
+	 * <li>This bundle has been uninstalled.
+	 * </ul>
+	 * <b>Postconditions, when an exception is thrown </b>
+	 * <ul>
+	 * <li><code>getState()</code> not in {<code>UNINSTALLED</code>}.
+	 * <li>This Bundle has not been uninstalled.
+	 * </ul>
+	 * 
+	 * @exception BundleException If the uninstall failed. This can occur if
+	 *            another thread is attempting to change the bundle's state and
+	 *            does not complete in a timely manner.
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled or this bundle tries to change its own state.
+	 * @exception java.lang.SecurityException If the caller does not have the
+	 *            appropriate <code>AdminPermission[bundle, LIFECYCLE]</code>,
+	 *            and the Java Runtime Environment supports permissions.
+	 * @see #stop()
+	 */
+	public abstract void uninstall() throws BundleException;
+
+	/**
+	 * Returns this bundle's Manifest headers and values. This method returns
+	 * all the Manifest headers and values from the main section of the bundle's
+	 * Manifest file; that is, all lines prior to the first blank line.
+	 * 
+	 * <p>
+	 * Manifest header names are case-insensitive. The methods of the returned
+	 * <code>Dictionary</code> object must operate on header names in a
+	 * case-insensitive manner.
+	 * 
+	 * If a Manifest header value starts with &quot;%&quot;, it must be
+	 * localized according to the default locale.
+	 * 
+	 * <p>
+	 * For example, the following Manifest headers and values are included if
+	 * they are present in the Manifest file:
+	 * 
+	 * <pre>
+	 *        Bundle-Name
+	 *        Bundle-Vendor
+	 *        Bundle-Version
+	 *        Bundle-Description
+	 *        Bundle-DocURL
+	 *        Bundle-ContactAddress
+	 * </pre>
+	 * 
+	 * <p>
+	 * This method must continue to return Manifest header information while
+	 * this bundle is in the <code>UNINSTALLED</code> state.
+	 * 
+	 * @return A <code>Dictionary</code> object containing this bundle's
+	 *         Manifest headers and values.
+	 * 
+	 * @exception java.lang.SecurityException If the caller does not have the appropriate
+	 *            <code>AdminPermission[bundle, METADATA]</code>, and the
+	 *            Java Runtime Environment supports permissions.
+	 * 
+	 * @see Constants#BUNDLE_LOCALIZATION
+	 */
+	public abstract Dictionary getHeaders();
+
+	/**
+	 * Returns this bundle's identifier. The bundle is assigned a unique
+	 * identifier by the Framework when it is installed in the OSGi environment.
+	 * 
+	 * <p>
+	 * A bundle's unique identifier has the following attributes:
+	 * <ul>
+	 * <li>Is unique and persistent.
+	 * <li>Is a <code>long</code>.
+	 * <li>Its value is not reused for another bundle, even after the bundle is
+	 * uninstalled.
+	 * <li>Does not change while the bundle remains installed.
+	 * <li>Does not change when the bundle is updated.
+	 * </ul>
+	 * 
+	 * <p>
+	 * This method must continue to return this bundle's unique identifier while
+	 * this bundle is in the <code>UNINSTALLED</code> state.
+	 * 
+	 * @return The unique identifier of this bundle.
+	 */
+	public abstract long getBundleId();
+
+	/**
+	 * Returns this bundle's location identifier.
+	 * 
+	 * <p>
+	 * The bundle location identifier is the location passed to
+	 * <code>BundleContext.installBundle</code> when a bundle is installed.
+	 * The bundle location identifier does not change while the bundle remains
+	 * installed, even if the bundle is updated.
+	 * 
+	 * <p>
+	 * This method must continue to return this bundle's location identifier
+	 * while this bundle is in the <code>UNINSTALLED</code> state.
+	 * 
+	 * @return The string representation of this bundle's location identifier.
+	 * @exception java.lang.SecurityException If the caller does not have the
+	 *            appropriate <code>AdminPermission[bundle, METADATA]</code>,
+	 *            and the Java Runtime Environment supports permissions.
+	 */
+	public abstract String getLocation();
+
+	/**
+	 * Returns this bundle's <code>ServiceReference</code> list for all
+	 * services it has registered or <code>null</code> if this bundle has no
+	 * registered services.
+	 * 
+	 * <p>
+	 * If the Java runtime supports permissions, a <code>ServiceReference</code>
+	 * object to a service is included in the returned list only if the caller
+	 * has the <code>ServicePermission</code> to get the service using at
+	 * least one of the named classes the service was registered under.
+	 * 
+	 * <p>
+	 * The list is valid at the time of the call to this method, however, as the
+	 * Framework is a very dynamic environment, services can be modified or
+	 * unregistered at anytime.
+	 * 
+	 * @return An array of <code>ServiceReference</code> objects or
+	 *         <code>null</code>.
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled.
+	 * @see ServiceRegistration
+	 * @see ServiceReference
+	 * @see ServicePermission
+	 */
+	public abstract ServiceReference[] getRegisteredServices();
+
+	/**
+	 * Returns this bundle's <code>ServiceReference</code> list for all
+	 * services it is using or returns <code>null</code> if this bundle is not
+	 * using any services. A bundle is considered to be using a service if its
+	 * use count for that service is greater than zero.
+	 * 
+	 * <p>
+	 * If the Java Runtime Environment supports permissions, a
+	 * <code>ServiceReference</code> object to a service is included in the
+	 * returned list only if the caller has the <code>ServicePermission</code>
+	 * to get the service using at least one of the named classes the service
+	 * was registered under.
+	 * <p>
+	 * The list is valid at the time of the call to this method, however, as the
+	 * Framework is a very dynamic environment, services can be modified or
+	 * unregistered at anytime.
+	 * 
+	 * @return An array of <code>ServiceReference</code> objects or
+	 *         <code>null</code>.
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled.
+	 * @see ServiceReference
+	 * @see ServicePermission
+	 */
+	public abstract ServiceReference[] getServicesInUse();
+
+	/**
+	 * Determines if this bundle has the specified permissions.
+	 * 
+	 * <p>
+	 * If the Java Runtime Environment does not support permissions, this method
+	 * always returns <code>true</code>.
+	 * <p>
+	 * <code>permission</code> is of type <code>Object</code> to avoid
+	 * referencing the <code>java.security.Permission</code> class directly.
+	 * This is to allow the Framework to be implemented in Java environments
+	 * which do not support permissions.
+	 * 
+	 * <p>
+	 * If the Java Runtime Environment does support permissions, this bundle and
+	 * all its resources including embedded JAR files, belong to the same
+	 * <code>java.security.ProtectionDomain</code>; that is, they must share
+	 * the same set of permissions.
+	 * 
+	 * @param permission The permission to verify.
+	 * 
+	 * @return <code>true</code> if this bundle has the specified permission
+	 *         or the permissions possessed by this bundle imply the specified
+	 *         permission; <code>false</code> if this bundle does not have the
+	 *         specified permission or <code>permission</code> is not an
+	 *         <code>instanceof</code> <code>java.security.Permission</code>.
+	 * 
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled.
+	 */
+	public abstract boolean hasPermission(Object permission);
+
+	/**
+	 * Find the specified resource from this bundle.
+	 * 
+	 * This bundle's class loader is called to search for the named resource. If
+	 * this bundle's state is <code>INSTALLED</code>, then only this bundle
+	 * must be searched for the specified resource. Imported packages cannot be
+	 * searched when a bundle has not been resolved. If this bundle is a
+	 * fragment bundle then <code>null</code> is returned.
+	 * 
+	 * @param name The name of the resource. See
+	 *        <code>java.lang.ClassLoader.getResource</code> for a description
+	 *        of the format of a resource name.
+	 * @return a URL to the named resource, or <code>null</code> if the
+	 *         resource could not be found or if this bundle is a fragment
+	 *         bundle or if the caller does not have the appropriate
+	 *         <code>AdminPermission[bundle, RESOURCE]</code>, and the Java
+	 *         Runtime Environment supports permissions.
+	 * 
+	 * @since 1.1
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled.
+	 */
+	public abstract URL getResource(String name);
+
+	/**
+	 * Returns this bundle's Manifest headers and values localized to the
+	 * specifed locale.
+	 * 
+	 * <p>
+	 * This method performs the same function as
+	 * <code>Bundle.getHeaders()</code> except the manifest header values are
+	 * localized to the specified locale.
+	 * 
+	 * If a Manifest header value starts with &quot;%&quot;, it must be
+	 * localized according to the specified locale. If the specified locale
+	 * cannot be found, then the header values must be returned using the
+	 * default locale.
+	 * 
+	 * If <code>null</code> is specified as the locale string, the header
+	 * values must be localized using the default locale. If the empty string
+	 * (&quot;&quot;) is specified as the locale string, the header values must
+	 * not be localized and the raw (unlocalized) header values, including any
+	 * leading &quot;%&quot;, must be returned.
+	 * 
+	 * <p>
+	 * This method must continue to return Manifest header information while
+	 * this bundle is in the <code>UNINSTALLED</code> state, however the
+	 * header values must only be available in the raw and default locale
+	 * values.
+	 * 
+	 * @param locale The locale name into which the header values are to be
+	 *        localized. If the specified locale is <code>null</code> then the
+	 *        locale returned by <code>java.util.Locale.getDefault</code> is
+	 *        used. If the specified locale is the empty string, this method
+	 *        will return the raw (unlocalized) manifest headers including any
+	 *        leading &quot;%&quot;.
+	 * @return A <code>Dictionary</code> object containing this bundle's
+	 *         Manifest headers and values.
+	 * 
+	 * @exception java.lang.SecurityException If the caller does not have the appropriate
+	 *            <code>AdminPermission[bundle, METADATA]</code>, and the
+	 *            Java Runtime Environment supports permissions.
+	 * 
+	 * @see #getHeaders()
+	 * @see Constants#BUNDLE_LOCALIZATION
+	 * @since 1.3
+	 */
+	public Dictionary getHeaders(String locale);
+
+	/**
+	 * Returns the symbolic name of this bundle as specified by its
+	 * <code>Bundle-SymbolicName</code> manifest header. The name must be
+	 * unique, it is recommended to use a reverse domain name naming convention
+	 * like that used for java packages. If the bundle does not have a specified
+	 * symbolic name then <code>null</code> is returned.
+	 * 
+	 * <p>
+	 * This method must continue to return this bundle's symbolic name while
+	 * this bundle is in the <code>UNINSTALLED</code> state.
+	 * 
+	 * @return The symbolic name of this bundle.
+	 * @since 1.3
+	 */
+	public String getSymbolicName();
+
+	/**
+	 * 
+	 * Loads the specified class using this bundle's classloader.
+	 * 
+	 * <p>
+	 * If the bundle is a fragment bundle then this method must throw a
+	 * <code>ClassNotFoundException</code>.
+	 * 
+	 * <p>
+	 * If this bundle's state is <code>INSTALLED</code>, this method must
+	 * attempt to resolve the bundle before attempting to load the class.
+	 * 
+	 * <p>
+	 * If the bundle cannot be resolved, a Framework event of type
+	 * {@link FrameworkEvent#ERROR}is broadcast containing a
+	 * <code>BundleException</code> with details of the reason the bundle
+	 * could not be resolved. This method must then throw a
+	 * <code>ClassNotFoundException</code>.
+	 * 
+	 * <p>
+	 * If this bundle's state is <code>UNINSTALLED</code>, then an
+	 * <code>IllegalStateException</code> is thrown.
+	 * 
+	 * @param name The name of the class to load.
+	 * @return The Class object for the requested class.
+	 * @exception java.lang.ClassNotFoundException If no such class can be found
+	 *            or if this bundle is a fragment bundle or if the caller does
+	 *            not have the appropriate <code>AdminPermission[bundle, CLASS]</code>,
+	 *            and the Java Runtime Environment supports permissions.
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled.
+	 * @since 1.3
+	 */
+	public Class loadClass(String name) throws ClassNotFoundException;
+
+	/**
+	 * Find the specified resources from this bundle.
+	 * 
+	 * This bundle's class loader is called to search for the named resource. If
+	 * this bundle's state is <code>INSTALLED</code>, then only this bundle
+	 * must be searched for the specified resource. Imported packages cannot be
+	 * searched when a bundle has not been resolved. If this bundle is a
+	 * fragment bundle then <code>null</code> is returned.
+	 * 
+	 * @param name The name of the resource. See
+	 *        <code>java.lang.ClassLoader.getResources</code> for a
+	 *        description of the format of a resource name.
+	 * @return an Enumeration of URLs to the named resources, or
+	 *         <code>null</code> if the resource could not be found or if this
+	 *         bundle is a fragment bundle or if the caller does not have the appropriate
+	 *         <code>AdminPermission[bundle, RESOURCE]</code>, and the Java
+	 *         Runtime Environment supports permissions.
+	 * 
+	 * @since 1.3
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled.
+	 * @throws java.io.IOException If there is an I/O error.
+	 */
+	public Enumeration getResources(String name) throws IOException;
+
+	/**
+	 * Returns an Enumeration of all the paths (<code>String</code>) objects) to 
+	 * entries within the bundle whose longest sub-path matches the supplied path 
+	 * argument. The bundle's classloader is not used to search for entries. Only 
+	 * the contents of the bundle is searched.  A specified path of &quot;/&quot; 
+	 * indicates the root of the bundle.
+	 * 
+	 * <p>
+	 * Returned paths indicating subdirectory paths end with a &quot;/&quot;.
+	 * The returned paths are all relative to the root of the bundle.
+	 * 
+	 * <p>
+	 * This method returns <code>null</code> if no entries could be found that
+	 * match the specified path or if the caller does not have the appropriate
+	 * <code>AdminPermission[bundle, RESOURCE]</code> and the Java 
+	 * Runtime Environment supports permissions.
+	 * 
+	 * @param path the path name to get the entry path for.
+	 * @return An Enumeration of the entry paths (<code>String</code> objects) 
+	 *         or <code>null</code> if an entry could not be found or if the 
+	 *         caller does not have the appropriate <code>AdminPermission[bundle, RESOURCE]</code> 
+	 *         and the Java Runtime Environment supports permissions.
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled.
+	 * @since 1.3
+	 */
+	public Enumeration getEntryPaths(String path);
+
+	/**
+	 * Returns a URL to the specified entry in this bundle. The bundle's
+	 * classloader is not used to search for the specified entry. Only the
+	 * contents of the bundle is searched for the specified entry. A specified
+	 * path of &quot;/&quot; indicates the root of the bundle.
+	 * 
+	 * <p>
+	 * This method returns a URL to the specified entry, or <code>null</code>
+	 * if the entry could not be found or if the caller does not have the appropriate
+	 * <code>AdminPermission[bundle, RESOURCE]</code> and the Java Runtime
+	 * Environment supports permissions.
+	 * 
+	 * @param name The name of the entry. See
+	 *        <code>java.lang.ClassLoader.getResource</code> for a description
+	 *        of the format of a resource name.
+	 * @return A URL to the specified entry, or <code>null</code> if the entry
+	 *         could not be found or if the caller does not have the appropriate
+	 *         <code>AdminPermission[bundle, RESOURCE]</code> and the Java
+	 *         Runtime Environment supports permissions.
+	 * 
+	 * @exception java.lang.IllegalStateException If this bundle has been
+	 *            uninstalled.
+	 * @since 1.3
+	 */
+	public URL getEntry(String name);
+
+	/**
+	 * Returns the time when this bundle was last modified. A bundle is
+	 * considered to be modified when it is installed, updated or uninstalled.
+	 * 
+	 * <p>
+	 * The time value is the number of milliseconds since January 1, 1970,
+	 * 00:00:00 GMT.
+	 * 
+	 * @return The time when this bundle was last modified.
+	 * @since 1.3
+	 */
+	public long getLastModified();
+
+	/**
+	 * Returns entries in this bundle and its attached fragments. The bundle's
+	 * classloader is not used to search for entries. Only the contents of the
+	 * bundle and its attached fragments are searched for the specified
+	 * entries.
+	 * 
+	 * If this bundle's state is <code>INSTALLED</code>, this method must
+	 * attempt to resolve the bundle before attempting to find entries.<p>
+	 * 
+	 * This method is intended to be used to obtain configuration, setup,
+	 * localization and other information from this bundle. This method takes
+	 * into account that the &quot;contents&quot; of this bundle can be extended
+	 * with fragments. This &quot;bundle space&quot; is not a namespace with
+	 * unique members; the same entry name can be present multiple times. This
+	 * method therefore returns an enumeration of URL objects. These URLs can
+	 * come from different JARs but have the same path name. This method can
+	 * either return only entries in the specified path or recurse into
+	 * subdirectories returning entries in the directory tree beginning at the
+	 * specified path. Fragments can be attached after this bundle is resolved,
+	 * possibly changing the set of URLs returned by this method. If this bundle
+	 * is not resolved, only the entries in the JAR file of this bundle are
+	 * returned.
+	 * <p>
+	 * Examples:
+	 * <pre>
+	 * // List all XML files in the OSGI-INF directory and below
+	 * Enumeration	e	= b.findEntries(&quot;OSGI-INF&quot;, &quot;*.xml&quot;, true);
+	 * 
+	 * // Find a specific localization file
+	 * Enumeration e = b.findEntries(&quot;OSGI-INF/l10n&quot;, 
+	 *    &quot;bundle_nl_DU.properties&quot;, false);
+	 * if (e.hasMoreElements())
+	 * 	return (URL) e.nextElement();
+	 * </pre>
+	 * 
+	 * @param path The path name in which to look. A specified path of
+	 *        &quot;/&quot; indicates the root of the bundle. Path is relative
+	 *        to the root of the bundle and must not be null.
+	 * @param filePattern The file name pattern for selecting entries in the
+	 *        specified path. The pattern is only matched against the last
+	 *        element of the entry path and it supports substring matching, as
+	 *        specified in the Filter specification, using the wildcard
+	 *        character (&quot;*&quot;). If null is specified, this is
+	 *        equivalent to &quot;*&quot; and matches all files.
+	 * @param recurse If <code>true</code>, recurse into subdirectories.
+	 *        Otherwise only return entries from the given directory.
+	 * @return An enumeration of URL objects for each matching entry, or
+	 *         <code>null</code> if an entry could not be found or if the
+	 *         caller does not have the appropriate
+	 *         <code>AdminPermission[bundle, RESOURCE]</code>, and the Java
+	 *         Runtime Environment supports permissions. The URLs are sorted
+	 *         such that entries from this bundle are returned first followed by
+	 *         the entries from attached fragments in ascending bundle id order.
+	 *         If this bundle is a fragment, then only matching entries in this
+	 *         fragment are returned.
+	 * @since 1.3
+	 */
+	public Enumeration findEntries(String path, String filePattern,
+			boolean recurse);
+}
\ No newline at end of file
diff --git a/src/org/osgi/framework/BundleActivator.java b/src/org/osgi/framework/BundleActivator.java
new file mode 100644
index 0000000..8be4194
--- /dev/null
+++ b/src/org/osgi/framework/BundleActivator.java
@@ -0,0 +1,82 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/BundleActivator.java,v 1.8 2005/06/21 16:22:12 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+/**
+ * Customizes the starting and stopping of a bundle.
+ * <p>
+ * <code>BundleActivator</code> is an interface that may be implemented when a
+ * bundle is started or stopped. The Framework can create instances of a
+ * bundle's <code>BundleActivator</code> as required. If an instance's
+ * <code>BundleActivator.start</code> method executes successfully, it is
+ * guaranteed that the same instance's <code>BundleActivator.stop</code> method
+ * will be called when the bundle is to be stopped.
+ * 
+ * <p>
+ * <code>BundleActivator</code> is specified through the <code>Bundle-Activator</code>
+ * Manifest header. A bundle can only specify a single <code>BundleActivator</code>
+ * in the Manifest file. Fragment bundles must not have a <code>BundleActivator</code>.
+ * The form of the Manifest header is:
+ * 
+ * <pre>
+ *  Bundle-Activator: &lt;i&gt;class-name&lt;/i&gt;
+ * </pre>
+ * 
+ * where <code>class-name</code> is a fully qualified Java classname.
+ * <p>
+ * The specified <code>BundleActivator</code> class must have a public constructor
+ * that takes no parameters so that a <code>BundleActivator</code> object can be
+ * created by <code>Class.newInstance()</code>.
+ * 
+ * @version $Revision: 1.8 $
+ */
+
+public abstract interface BundleActivator {
+	/**
+	 * Called when this bundle is started so the Framework can perform the
+	 * bundle-specific activities necessary to start this bundle. This method
+	 * can be used to register services or to allocate any resources that this
+	 * bundle needs.
+	 * 
+	 * <p>
+	 * This method must complete and return to its caller in a timely manner.
+	 * 
+	 * @param context The execution context of the bundle being started.
+	 * @exception java.lang.Exception If this method throws an exception, this
+	 *            bundle is marked as stopped and the Framework will remove this
+	 *            bundle's listeners, unregister all services registered by this
+	 *            bundle, and release all services used by this bundle.
+	 * @see Bundle#start
+	 */
+	public abstract void start(BundleContext context) throws Exception;
+
+	/**
+	 * Called when this bundle is stopped so the Framework can perform the
+	 * bundle-specific activities necessary to stop the bundle. In general, this
+	 * method should undo the work that the <code>BundleActivator.start</code>
+	 * method started. There should be no active threads that were started by
+	 * this bundle when this bundle returns. A stopped bundle must
+	 * not call any Framework objects.
+	 * 
+	 * <p>
+	 * This method must complete and return to its caller in a timely manner.
+	 * 
+	 * @param context The execution context of the bundle being stopped.
+	 * @exception java.lang.Exception If this method throws an exception, the
+	 *            bundle is still marked as stopped, and the Framework will
+	 *            remove the bundle's listeners, unregister all services
+	 *            registered by the bundle, and release all services used by the
+	 *            bundle.
+	 * @see Bundle#stop
+	 */
+	public abstract void stop(BundleContext context) throws Exception;
+}
+
diff --git a/src/org/osgi/framework/BundleContext.java b/src/org/osgi/framework/BundleContext.java
new file mode 100644
index 0000000..91fa559
--- /dev/null
+++ b/src/org/osgi/framework/BundleContext.java
@@ -0,0 +1,790 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/BundleContext.java,v 1.13 2005/06/21 16:22:12 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.Dictionary;
+
+/**
+ * A bundle's execution context within the Framework. The context is used to
+ * grant access to other methods so that this bundle can interact with the
+ * Framework.
+ * 
+ * <p>
+ * <code>BundleContext</code> methods allow a bundle to:
+ * <ul>
+ * <li>Subscribe to events published by the Framework.
+ * <li>Register service objects with the Framework service registry.
+ * <li>Retrieve <code>ServiceReferences</code> from the Framework service
+ * registry.
+ * <li>Get and release service objects for a referenced service.
+ * <li>Install new bundles in the Framework.
+ * <li>Get the list of bundles installed in the Framework.
+ * <li>Get the {@link Bundle} object for a bundle.
+ * <li>Create <code>File</code> objects for files in a persistent storage area
+ * provided for the bundle by the Framework.
+ * </ul>
+ * 
+ * <p>
+ * A <code>BundleContext</code> object will be created and provided to the bundle
+ * associated with this context when it is started using the
+ * {@link BundleActivator#start} method. The same <code>BundleContext</code>
+ * object will be passed to the bundle associated with this context when it is
+ * stopped using the {@link BundleActivator#stop} method. A <code>BundleContext</code>
+ * object is generally for the private use of its associated bundle and is not
+ * meant to be shared with other bundles in the OSGi environment.
+ * 
+ * <p>
+ * The <code>Bundle</code> object associated with a <code>BundleContext</code> object
+ * is called the <em>context bundle</em>.
+ *
+ * <p>
+ * The <code>BundleContext</code> object is only valid during the execution
+ * of its context bundle; that is, during the period from when the context
+ * bundle is in the <code>STARTING</code>, <code>STOPPING</code>, and
+ * <code>ACTIVE</code> bundle states. If the <code>BundleContext</code> object
+ * is used subsequently, an <code>IllegalStateException</code> must be thrown.
+ * The <code>BundleContext</code> object must never be reused after its
+ * context bundle is stopped.
+ * 
+ * <p>
+ * The Framework is the only entity that can create <code>BundleContext</code>
+ * objects and they are only valid within the Framework that created them.
+ * 
+ * @version $Revision: 1.13 $
+ */
+
+public abstract interface BundleContext {
+	/**
+	 * Returns the value of the specified property. If the key is not found in
+	 * the Framework properties, the system properties are then searched. The
+	 * method returns <code>null</code> if the property is not found.
+	 * 
+	 * <p>
+	 * The Framework defines the following standard property keys:
+	 * </p>
+	 * <ul>
+	 * <li>{@link Constants#FRAMEWORK_VERSION}- The OSGi Framework version.
+	 * </li>
+	 * <li>{@link Constants#FRAMEWORK_VENDOR}- The Framework implementation
+	 * vendor.</li>
+	 * <li>{@link Constants#FRAMEWORK_LANGUAGE}- The language being used. See
+	 * ISO 639 for possible values.</li>
+	 * <li>{@link Constants#FRAMEWORK_OS_NAME}- The host computer operating
+	 * system.</li>
+	 * <li>{@link Constants#FRAMEWORK_OS_VERSION}- The host computer operating
+	 * system version number.</li>
+	 * <li>{@link Constants#FRAMEWORK_PROCESSOR}- The host computer processor
+	 * name.</li>
+	 * </ul>
+	 * <p>
+	 * All bundles must have permission to read these properties.
+	 * 
+	 * <p>
+	 * Note: The last four standard properties are used by the
+	 * {@link Constants#BUNDLE_NATIVECODE} <code>Manifest</code> header's matching
+	 * algorithm for selecting native language code.
+	 * 
+	 * @param key The name of the requested property.
+	 * @return The value of the requested property, or <code>null</code> if the
+	 *         property is undefined.
+	 * @exception java.lang.SecurityException If the caller does not have the
+	 *            appropriate <code>PropertyPermission</code> to read the
+	 *            property, and the Java Runtime Environment supports
+	 *            permissions.
+	 */
+	public abstract String getProperty(String key);
+
+	/**
+	 * Returns the <code>Bundle</code> object associated with this
+	 * <code>BundleContext</code>. This bundle is called the context bundle.
+	 * 
+	 * @return The <code>Bundle</code> object associated with this
+	 * 		   <code>BundleContext</code>.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 */
+	public abstract Bundle getBundle();
+
+	/**
+	 * Installs a bundle from the specified location string. A bundle is
+	 * obtained from <code>location</code> as interpreted by the Framework in an
+	 * implementation dependent manner.
+	 * <p>
+	 * Every installed bundle is uniquely identified by its location string,
+	 * typically in the form of a URL.
+	 * 
+	 * <p>
+	 * The following steps are required to install a bundle:
+	 * <ol>
+	 * <li>If a bundle containing the same location string is already
+	 * installed, the <code>Bundle</code> object for that bundle is returned.
+	 * 
+	 * <li>The bundle's content is read from the location string. If this
+	 * fails, a {@link BundleException} is thrown.
+	 * 
+	 * <li>The bundle's <code>Bundle-NativeCode</code> dependencies are resolved.
+	 * If this fails, a <code>BundleException</code> is thrown.
+	 * 
+	 * <li>The bundle's associated resources are allocated. The associated
+	 * resources minimally consist of a unique identifier and a persistent
+	 * storage area if the platform has file system support. If this step fails,
+	 * a <code>BundleException</code> is thrown.
+	 * 
+	 * <li>If the bundle has declared an Bundle-RequiredExecutionEnvironment
+	 * header, then the listed execution environments must be verified against
+	 * the installed execution environments. If they are not all present, a
+	 * <code>BundleException</code> must be thrown.
+	 * 
+	 * <li>The bundle's state is set to <code>INSTALLED</code>.
+	 * 
+	 * <li>A bundle event of type {@link BundleEvent#INSTALLED} is broadcast.
+	 * 
+	 * <li>The <code>Bundle</code> object for the newly or previously installed
+	 * bundle is returned.
+	 * </ol>
+	 * 
+	 * <b>Postconditions, no exceptions thrown </b>
+	 * <ul>
+	 * <li><code>getState()</code> in {<code>INSTALLED</code>,<code>RESOLVED</code>}.
+	 * <li>Bundle has a unique ID.
+	 * </ul>
+	 * <b>Postconditions, when an exception is thrown </b>
+	 * <ul>
+	 * <li>Bundle is not installed and no trace of the bundle exists.
+	 * </ul>
+	 * 
+	 * @param location The location identifier of the bundle to install.
+	 * @return The <code>Bundle</code> object of the installed bundle.
+	 * @exception BundleException If the installation failed.
+	 * @exception java.lang.SecurityException If the caller does not have the
+	 *            appropriate <code>AdminPermission</code>, and the Java Runtime
+	 *            Environment supports permissions.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 */
+	public abstract Bundle installBundle(String location)
+			throws BundleException;
+
+	/**
+	 * Installs a bundle from the specified <code>InputStream</code> object.
+	 * 
+	 * <p>
+	 * This method performs all of the steps listed in
+	 * <code>BundleContext.installBundle(String location)</code>, except that the
+	 * bundle's content will be read from the <code>InputStream</code> object. The
+	 * location identifier string specified will be used as the identity of the
+	 * bundle.
+	 * 
+	 * <p>
+	 * This method must always close the <code>InputStream</code> object, even if
+	 * an exception is thrown.
+	 * 
+	 * @param location The location identifier of the bundle to install.
+	 * @param input The <code>InputStream</code> object from which this bundle
+	 *        will be read.
+	 * @return The <code>Bundle</code> object of the installed bundle.
+	 * @exception BundleException If the provided stream cannot be read or the
+	 *            installation failed.
+	 * @exception java.lang.SecurityException If the caller does not have the
+	 *            appropriate <code>AdminPermission</code>, and the Java Runtime
+	 *            Environment supports permissions.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 * @see #installBundle(java.lang.String)
+	 */
+	public abstract Bundle installBundle(String location, InputStream input)
+			throws BundleException;
+
+	/**
+	 * Returns the bundle with the specified identifier.
+	 * 
+	 * @param id The identifier of the bundle to retrieve.
+	 * @return A <code>Bundle</code> object or <code>null</code> if the identifier
+	 *         does not match any installed bundle.
+	 */
+	public abstract Bundle getBundle(long id);
+
+	/**
+	 * Returns a list of all installed bundles.
+	 * <p>
+	 * This method returns a list of all bundles installed in the OSGi
+	 * environment at the time of the call to this method. However, since the
+	 * Framework is a very dynamic environment, bundles can be installed or
+	 * uninstalled at anytime.
+	 * 
+	 * @return An array of <code>Bundle</code> objects, one object per installed
+	 *         bundle.
+	 */
+	public abstract Bundle[] getBundles();
+
+	/**
+	 * Adds the specified <code>ServiceListener</code> object with the specified
+	 * <code>filter</code> to the context bundle's list of listeners.
+	 * See {@link Filter} for a description of the filter syntax.
+	 * <code>ServiceListener</code> objects are notified when a service has a
+	 * lifecycle state change.
+	 * 
+	 * <p>
+	 * If the context bundle's list of listeners already contains a listener
+	 * <code>l</code> such that <code>(l==listener)</code>, then this method replaces
+	 * that listener's filter (which may be <code>null</code>) with the specified
+	 * one (which may be <code>null</code>).
+	 * 
+	 * <p>
+	 * The listener is called if the filter criteria is met. To filter based
+	 * upon the class of the service, the filter should reference the
+	 * {@link Constants#OBJECTCLASS} property. If <code>filter</code> is
+	 * <code>null</code>, all services are considered to match the filter.
+	 * 
+	 * <p>
+	 * When using a <code>filter</code>, it is possible that the
+	 * <code>ServiceEvent</code>s for the complete lifecycle of a service will
+	 * not be delivered to the listener. For example, if the <code>filter</code>
+	 * only matches when the property <code>x</code> has the value <code>1</code>,
+	 * the listener will not be called if the service is registered with the
+	 * property <code>x</code> not set to the value <code>1</code>. Subsequently,
+	 * when the service is modified setting property <code>x</code> to the value
+	 * <code>1</code>, the filter will match and the listener will be called with
+	 * a <code>ServiceEvent</code> of type <code>MODIFIED</code>. Thus, the
+	 * listener will not be called with a <code>ServiceEvent</code> of type
+	 * <code>REGISTERED</code>.
+	 * 
+	 * <p>
+	 * If the Java Runtime Environment supports permissions, the
+	 * <code>ServiceListener</code> object will be notified of a service event
+	 * only if the bundle that is registering it has the
+	 * <code>ServicePermission</code> to get the service using at least one of the
+	 * named classes the service was registered under.
+	 * 
+	 * @param listener The <code>ServiceListener</code> object to be added.
+	 * @param filter The filter criteria.
+	 * 
+	 * @exception InvalidSyntaxException If <code>filter</code> contains an
+	 *            invalid filter string that cannot be parsed.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 * 
+	 * @see ServiceEvent
+	 * @see ServiceListener
+	 * @see ServicePermission
+	 */
+	public abstract void addServiceListener(ServiceListener listener,
+			String filter) throws InvalidSyntaxException;
+
+	/**
+	 * Adds the specified <code>ServiceListener</code> object to the context
+	 * bundle's list of listeners.
+	 * 
+	 * <p>
+	 * This method is the same as calling
+	 * <code>BundleContext.addServiceListener(ServiceListener listener,
+	 * String filter)</code>
+	 * with <code>filter</code> set to <code>null</code>.
+	 * 
+	 * @param listener The <code>ServiceListener</code> object to be added.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 * 
+	 * @see #addServiceListener(ServiceListener, String)
+	 */
+	public abstract void addServiceListener(ServiceListener listener);
+
+	/**
+	 * Removes the specified <code>ServiceListener</code> object from the context
+	 * bundle's list of listeners.
+	 * 
+	 * <p>
+	 * If <code>listener</code> is not contained in this context bundle's list of
+	 * listeners, this method does nothing.
+	 * 
+	 * @param listener The <code>ServiceListener</code> to be removed.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 */
+	public abstract void removeServiceListener(ServiceListener listener);
+
+	/**
+	 * Adds the specified <code>BundleListener</code> object to the context
+	 * bundle's list of listeners if not already present. BundleListener
+	 * objects are notified when a bundle has a lifecycle state change.
+	 * 
+	 * <p>
+	 * If the context bundle's list of listeners already contains a listener
+	 * <code>l</code> such that <code>(l==listener)</code>, this method does
+	 * nothing.
+	 * 
+	 * @param listener The <code>BundleListener</code> to be added.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 * 
+	 * @see BundleEvent
+	 * @see BundleListener
+	 */
+	public abstract void addBundleListener(BundleListener listener);
+
+	/**
+	 * Removes the specified <code>BundleListener</code> object from the context
+	 * bundle's list of listeners.
+	 * 
+	 * <p>
+	 * If <code>listener</code> is not contained in the context bundle's list of
+	 * listeners, this method does nothing.
+	 * 
+	 * @param listener The <code>BundleListener</code> object to be removed.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 */
+	public abstract void removeBundleListener(BundleListener listener);
+
+	/**
+	 * Adds the specified <code>FrameworkListener</code> object to the context
+	 * bundle's list of listeners if not already present.
+	 * FrameworkListeners are notified of general Framework events.
+	 * 
+	 * <p>
+	 * If the context bundle's list of listeners already contains a listener
+	 * <code>l</code> such that <code>(l==listener)</code>, this method does
+	 * nothing.
+	 * 
+	 * @param listener The <code>FrameworkListener</code> object to be added.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 * 
+	 * @see FrameworkEvent
+	 * @see FrameworkListener
+	 */
+	public abstract void addFrameworkListener(FrameworkListener listener);
+
+	/**
+	 * Removes the specified <code>FrameworkListener</code> object from the
+	 * context bundle's list of listeners.
+	 * 
+	 * <p>
+	 * If <code>listener</code> is not contained in the context bundle's list of
+	 * listeners, this method does nothing.
+	 * 
+	 * @param listener The <code>FrameworkListener</code> object to be removed.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 */
+	public abstract void removeFrameworkListener(FrameworkListener listener);
+
+	/**
+	 * Registers the specified service object with the specified properties
+	 * under the specified class names into the Framework. A
+	 * <code>ServiceRegistration</code> object is returned. The
+	 * <code>ServiceRegistration</code> object is for the private use of the
+	 * bundle registering the service and should not be shared with other
+	 * bundles. The registering bundle is defined to be the context bundle.
+	 * Other bundles can locate the service by using either the
+	 * {@link #getServiceReferences} or {@link #getServiceReference} method.
+	 * 
+	 * <p>
+	 * A bundle can register a service object that implements the
+	 * {@link ServiceFactory} interface to have more flexibility in providing
+	 * service objects to other bundles.
+	 * 
+	 * <p>
+	 * The following steps are required to register a service:
+	 * <ol>
+	 * <li>If <code>service</code> is not a <code>ServiceFactory</code>, an
+	 * <code>IllegalArgumentException</code> is thrown if <code>service</code> is
+	 * not an <code>instanceof</code> all the classes named.
+	 * <li>The Framework adds these service properties to the specified
+	 * <code>Dictionary</code> (which may be <code>null</code>): a property named
+	 * {@link Constants#SERVICE_ID} identifying the registration number of the
+	 * service and a property named {@link Constants#OBJECTCLASS} containing
+	 * all the specified classes. If any of these properties have already been
+	 * specified by the registering bundle, their values will be overwritten by
+	 * the Framework.
+	 * <li>The service is added to the Framework service registry and may now
+	 * be used by other bundles.
+	 * <li>A service event of type {@link ServiceEvent#REGISTERED} is
+	 * synchronously sent.
+	 * <li>A <code>ServiceRegistration</code> object for this registration is
+	 * returned.
+	 * </ol>
+	 * 
+	 * @param clazzes The class names under which the service can be located.
+	 *        The class names in this array will be stored in the service's
+	 *        properties under the key {@link Constants#OBJECTCLASS}.
+	 * @param service The service object or a <code>ServiceFactory</code> object.
+	 * @param properties The properties for this service. The keys in the
+	 *        properties object must all be <code>String</code> objects. See
+	 *        {@link Constants} for a list of standard service property keys.
+	 *        Changes should not be made to this object after calling this
+	 *        method. To update the service's properties the
+	 *        {@link ServiceRegistration#setProperties} method must be called.
+	 *        The set of properties may be <code>null</code> if the service has no
+	 *        properties.
+	 * 
+	 * @return A <code>ServiceRegistration</code> object for use by the bundle
+	 *         registering the service to update the service's properties or to
+	 *         unregister the service.
+	 * 
+	 * @exception java.lang.IllegalArgumentException If one of the following is
+	 *            true:
+	 *            <ul>
+	 *            <li><code>service</code> is <code>null</code>.
+	 *            <li><code>service</code> is not a <code>ServiceFactory</code>
+	 *            object and is not an instance of all the named classes in
+	 *            <code>clazzes</code>.
+	 *            <li><code>properties</code> contains case variants of the same
+	 *            key name.
+	 *            </ul>
+	 * 
+	 * @exception java.lang.SecurityException If the caller does not have the
+	 *            <code>ServicePermission</code> to register the service for all
+	 *            the named classes and the Java Runtime Environment supports
+	 *            permissions.
+	 * 
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 * 
+	 * @see ServiceRegistration
+	 * @see ServiceFactory
+	 */
+	public abstract ServiceRegistration registerService(String[] clazzes,
+			Object service, Dictionary properties);
+
+	/**
+	 * Registers the specified service object with the specified properties
+	 * under the specified class name with the Framework.
+	 * 
+	 * <p>
+	 * This method is otherwise identical to
+	 * {@link #registerService(java.lang.String[], java.lang.Object,
+	 * java.util.Dictionary)} and is provided as a convenience when
+	 * <code>service</code> will only be registered under a single class name.
+	 * Note that even in this case the value of the service's
+	 * {@link Constants#OBJECTCLASS} property will be an array of strings,
+	 * rather than just a single string.
+	 * 
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 * @see #registerService(java.lang.String[], java.lang.Object,
+	 *      java.util.Dictionary)
+	 */
+	public abstract ServiceRegistration registerService(String clazz,
+			Object service, Dictionary properties);
+
+	/**
+	 * Returns an array of <code>ServiceReference</code> objects. The returned
+	 * array of <code>ServiceReference</code> objects contains services that
+	 * were registered under the specified class, match the specified filter
+	 * criteria, and the packages for the class names under which the services
+	 * were registered match the context bundle's packages as defined in
+	 * {@link ServiceReference#isAssignableTo(Bundle, String)}.
+	 * 
+	 * <p>
+	 * The list is valid at the time of the call to this method, however since the
+	 * Framework is a very dynamic environment, services can be modified or
+	 * unregistered at anytime.
+	 * 
+	 * <p>
+	 * <code>filter</code> is used to select the registered service whose
+	 * properties objects contain keys and values which satisfy the filter. See
+	 * {@link Filter} for a description of the filter string syntax.
+	 * 
+	 * <p>
+	 * If <code>filter</code> is <code>null</code>, all registered services are
+	 * considered to match the filter.
+	 * If <code>filter</code> cannot be parsed, an {@link InvalidSyntaxException}
+	 * will be thrown with a human readable message where the filter became
+	 * unparsable.
+	 * 
+	 * <p>
+	 * The following steps are required to select a set of 
+	 * <code>ServiceReference</code> objects:
+	 * <ol>
+	 * <li>If the filter string is not <code>null</code>, the filter string is
+	 * parsed and the set <code>ServiceReference</code> objects of registered
+	 * services that satisfy the filter is produced. If the filter string is
+	 * <code>null</code>, then all registered
+	 * services are considered to satisfy the filter.
+	 * <li>If the Java Runtime Environment supports permissions, the
+	 * set of <code>ServiceReference</code> objects produced by the
+	 * previous step is reduced by checking that the caller has
+	 * the <code>ServicePermission</code> to get at least one
+	 * of the class names under which the service was registered. If the caller
+	 * does not have the correct permission for a particular
+	 * <code>ServiceReference</code> object, then it is removed from the set.
+	 * <li>If <code>clazz</code> is not <code>null</code>, the set is further
+	 * reduced to those services that are an <code>instanceof</code> and were
+	 * registered under the specified class. The complete list of classes of
+	 * which a service is an instance and which were specified when the service
+	 * was registered is available from the service's
+	 * {@link Constants#OBJECTCLASS} property.
+	 * <li>The set is reduced one final time by cycling through each
+	 * <code>ServiceReference</code> object and calling
+	 * {@link ServiceReference#isAssignableTo(Bundle, String)} with the
+	 * context bundle and each class name under which the
+	 * <code>ServiceReference</code> object was registered. For any
+	 * given <code>ServiceReference</code> object, if any call to
+	 * {@link ServiceReference#isAssignableTo(Bundle, String)} returns
+	 * <code>false</code>, then it is removed from the set of
+	 * <code>ServiceReference</code> objects.
+	 * <li>An array of the remaining <code>ServiceReference</code> objects
+	 * is returned.
+	 * </ol>
+	 * 
+	 * @param clazz The class name with which the service was registered or
+	 *        <code>null</code> for all services.
+	 * @param filter The filter criteria.
+	 * @return An array of <code>ServiceReference</code> objects or <code>null</code>
+	 *         if no services are registered which satisfy the search.
+	 * @exception InvalidSyntaxException If <code>filter</code> contains an
+	 *            invalid filter string that cannot be parsed.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 */
+	public abstract ServiceReference[] getServiceReferences(String clazz,
+			String filter) throws InvalidSyntaxException;
+
+	/**
+	 * Returns an array of <code>ServiceReference</code> objects. The returned
+	 * array of <code>ServiceReference</code> objects contains services that
+	 * were registered under the specified class and match the
+	 * specified filter criteria.
+	 * 
+	 * <p>
+	 * The list is valid at the time of the call to this method, however since the
+	 * Framework is a very dynamic environment, services can be modified or
+	 * unregistered at anytime.
+	 * 
+	 * <p>
+	 * <code>filter</code> is used to select the registered service whose
+	 * properties objects contain keys and values which satisfy the filter. See
+	 * {@link Filter} for a description of the filter string syntax.
+	 * 
+	 * <p>
+	 * If <code>filter</code> is <code>null</code>, all registered services are
+	 * considered to match the filter.
+	 * If <code>filter</code> cannot be parsed, an {@link InvalidSyntaxException}
+	 * will be thrown with a human readable message where the filter became
+	 * unparsable.
+	 * 
+	 * <p>
+	 * The following steps are required to select a set of 
+	 * <code>ServiceReference</code> objects:
+	 * <ol>
+	 * <li>If the filter string is not <code>null</code>, the filter string is
+	 * parsed and the set <code>ServiceReference</code> objects of registered
+	 * services that satisfy the filter is produced. If the filter string is
+	 * <code>null</code>, then all registered
+	 * services are considered to satisfy the filter.
+	 * <li>If the Java Runtime Environment supports permissions, the
+	 * set of <code>ServiceReference</code> objects produced by the
+	 * previous step is reduced by checking that the caller has
+	 * the <code>ServicePermission</code> to get at least one
+	 * of the class names under which the service was registered. If the caller
+	 * does not have the correct permission for a particular
+	 * <code>ServiceReference</code> object, then it is removed from the set.
+	 * <li>If <code>clazz</code> is not <code>null</code>, the set is further
+	 * reduced to those services that are an <code>instanceof</code> and were
+	 * registered under the specified class. The complete list of classes of
+	 * which a service is an instance and which were specified when the service
+	 * was registered is available from the service's
+	 * {@link Constants#OBJECTCLASS} property.
+	 * <li>An array of the remaining <code>ServiceReference</code> objects
+	 * is returned.
+	 * </ol>
+	 * 
+	 * @param clazz The class name with which the service was registered or
+	 *        <code>null</code> for all services.
+	 * @param filter The filter criteria.
+	 * @return An array of <code>ServiceReference</code> objects or <code>null</code>
+	 *         if no services are registered which satisfy the search.
+	 * @exception InvalidSyntaxException If <code>filter</code> contains an
+	 *            invalid filter string that cannot be parsed.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 */
+	public abstract ServiceReference[] getAllServiceReferences(String clazz, 
+			String filter) throws InvalidSyntaxException;
+
+	/**
+	 * Returns a <code>ServiceReference</code> object for a service that
+	 * implements and was registered under the specified class.
+	 * 
+	 * <p>
+	 * This <code>ServiceReference</code> object is valid at the time of the call
+	 * to this method, however as the Framework is a very dynamic environment,
+	 * services can be modified or unregistered at anytime.
+	 * 
+	 * <p>
+	 * This method is the same as calling
+	 * {@link BundleContext#getServiceReferences(String, String)} with a
+	 * <code>null</code> filter string. It is provided as a convenience for when
+	 * the caller is interested in any service that implements the specified
+	 * class.
+	 * <p>
+	 * If multiple such services exist, the service with the highest ranking (as
+	 * specified in its {@link Constants#SERVICE_RANKING} property) is returned.
+	 * <p>
+	 * If there is a tie in ranking, the service with the lowest service ID (as
+	 * specified in its {@link Constants#SERVICE_ID} property); that is, the
+	 * service that was registered first is returned.
+	 * 
+	 * @param clazz The class name with which the service was registered.
+	 * @return A <code>ServiceReference</code> object, or <code>null</code> if no
+	 *         services are registered which implement the named class.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 * @see #getServiceReferences(String, String)
+	 */
+	public abstract ServiceReference getServiceReference(String clazz);
+
+	/**
+	 * Returns the specified service object for a service.
+	 * <p>
+	 * A bundle's use of a service is tracked by the bundle's use count of that
+	 * service. Each time a service's service object is returned by
+	 * {@link #getService(ServiceReference)} the context bundle's use count for
+	 * that service is incremented by one. Each time the service is released by
+	 * {@link #ungetService(ServiceReference)} the context bundle's use count
+	 * for that service is decremented by one.
+	 * <p>
+	 * When a bundle's use count for a service drops to zero, the bundle should
+	 * no longer use that service.
+	 * 
+	 * <p>
+	 * This method will always return <code>null</code> when the service
+	 * associated with this <code>reference</code> has been unregistered.
+	 * 
+	 * <p>
+	 * The following steps are required to get the service object:
+	 * <ol>
+	 * <li>If the service has been unregistered, <code>null</code> is returned.
+	 * <li>The context bundle's use count for this service is incremented by
+	 * one.
+	 * <li>If the context bundle's use count for the service is currently one
+	 * and the service was registered with an object implementing the
+	 * <code>ServiceFactory</code> interface, the
+	 * {@link ServiceFactory#getService(Bundle, ServiceRegistration)} method
+	 * is called to create a service object for the context bundle. This service
+	 * object is cached by the Framework. While the context bundle's use count
+	 * for the service is greater than zero, subsequent calls to get the
+	 * services's service object for the context bundle will return the cached
+	 * service object.
+	 * <br>
+	 * If the service object returned by the <code>ServiceFactory</code> object is
+	 * not an <code>instanceof</code> all the classes named when the service was
+	 * registered or the <code>ServiceFactory</code> object throws an exception,
+	 * <code>null</code> is returned and a Framework event of type
+	 * {@link FrameworkEvent#ERROR} is broadcast.
+	 * <li>The service object for the service is returned.
+	 * </ol>
+	 * 
+	 * @param reference A reference to the service.
+	 * @return A service object for the service associated with
+	 *         <code>reference</code> or <code>null</code> if the service is not
+	 *         registered or does not implement the classes under which it was
+	 *         registered in the case of a <code>ServiceFactory</code>.
+	 * @exception java.lang.SecurityException If the caller does not have the
+	 *            <code>ServicePermission</code> to get the service using at least
+	 *            one of the named classes the service was registered under and
+	 *            the Java Runtime Environment supports permissions.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 * @see #ungetService(ServiceReference)
+	 * @see ServiceFactory
+	 */
+	public abstract Object getService(ServiceReference reference);
+
+	/**
+	 * Releases the service object referenced by the specified
+	 * <code>ServiceReference</code> object. If the context bundle's use count for
+	 * the service is zero, this method returns <code>false</code>. Otherwise,
+	 * the context bundle's use count for the service is decremented by one.
+	 * 
+	 * <p>
+	 * The service's service object should no longer be used and all references
+	 * to it should be destroyed when a bundle's use count for the service drops
+	 * to zero.
+	 * 
+	 * <p>
+	 * The following steps are required to unget the service object:
+	 * <ol>
+	 * <li>If the context bundle's use count for the service is zero or the
+	 * service has been unregistered, <code>false</code> is returned.
+	 * <li>The context bundle's use count for this service is decremented by
+	 * one.
+	 * <li>If the context bundle's use count for the service is currently zero
+	 * and the service was registered with a <code>ServiceFactory</code> object,
+	 * the {@link ServiceFactory#ungetService(Bundle, ServiceRegistration, Object)}
+	 * method is called to release the service object for the context bundle.
+	 * <li><code>true</code> is returned.
+	 * </ol>
+	 * 
+	 * @param reference A reference to the service to be released.
+	 * @return <code>false</code> if the context bundle's use count for the
+	 *         service is zero or if the service has been unregistered;
+	 *         <code>true</code> otherwise.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 * @see #getService
+	 * @see ServiceFactory
+	 */
+	public abstract boolean ungetService(ServiceReference reference);
+
+	/**
+	 * Creates a <code>File</code> object for a file in the persistent storage
+	 * area provided for the bundle by the Framework. This method will return
+	 * <code>null</code> if the platform does not have file system support.
+	 * 
+	 * <p>
+	 * A <code>File</code> object for the base directory of the persistent storage
+	 * area provided for the context bundle by the Framework can be obtained by
+	 * calling this method with an empty string as <code>filename</code>.
+	 * 
+	 * <p>
+	 * If the Java Runtime Environment supports permissions, the Framework will
+	 * ensure that the bundle has the <code>java.io.FilePermission</code> with
+	 * actions <code>read</code>,<code>write</code>,<code>delete</code> for all
+	 * files (recursively) in the persistent storage area provided for the
+	 * context bundle.
+	 * 
+	 * @param filename A relative name to the file to be accessed.
+	 * @return A <code>File</code> object that represents the requested file or
+	 *         <code>null</code> if the platform does not have file system
+	 *         support.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 */
+	public abstract File getDataFile(String filename);
+
+	/**
+	 * Creates a <code>Filter</code> object. This <code>Filter</code> object may be
+	 * used to match a <code>ServiceReference</code> object or a
+	 * <code>Dictionary</code> object. 
+	 * 
+	 * <p>
+	 * If the filter cannot be parsed, an {@link InvalidSyntaxException} will be
+	 * thrown with a human readable message where the filter became unparsable.
+	 * 
+	 * @param filter The filter string.
+	 * @return A <code>Filter</code> object encapsulating the filter string.
+	 * @exception InvalidSyntaxException If <code>filter</code> contains an
+	 *            invalid filter string that cannot be parsed.
+	 * @exception NullPointerException If <code>filter</code> is null.
+	 * @exception java.lang.IllegalStateException If this BundleContext is no
+	 *            longer valid.
+	 * 
+	 * @since 1.1
+	 * @see "Framework specification for a description of the filter string syntax."
+	 */
+	public abstract Filter createFilter(String filter)
+			throws InvalidSyntaxException;
+}
+
diff --git a/src/org/osgi/framework/BundleEvent.java b/src/org/osgi/framework/BundleEvent.java
new file mode 100644
index 0000000..dcd6e8e
--- /dev/null
+++ b/src/org/osgi/framework/BundleEvent.java
@@ -0,0 +1,146 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/BundleEvent.java,v 1.10 2005/05/13 20:32:54 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.util.EventObject;
+
+/**
+ * A Framework event describing a bundle lifecycle change.
+ * <p>
+ * <code>BundleEvent</code> objects are delivered to <code>BundleListener</code>
+ * objects when a change occurs in a bundle's lifecycle. A type code is used to
+ * identify the event type for future extendability.
+ * 
+ * <p>
+ * OSGi Alliance reserves the right to extend the set of types.
+ * 
+ * @version $Revision: 1.10 $
+ */
+
+public class BundleEvent extends EventObject {
+	static final long		serialVersionUID	= 4080640865971756012L;
+	/**
+	 * Bundle that had a change occur in its lifecycle.
+	 */
+	private Bundle			bundle;
+
+	/**
+	 * Type of bundle lifecycle change.
+	 */
+	private int				type;
+
+	/**
+	 * The bundle has been installed.
+	 * <p>
+	 * The value of <code>INSTALLED</code> is 0x00000001.
+	 * 
+	 * @see BundleContext#installBundle(String)
+	 */
+	public final static int	INSTALLED			= 0x00000001;
+
+	/**
+	 * The bundle has been started.
+	 * <p>
+	 * The value of <code>STARTED</code> is 0x00000002.
+	 * 
+	 * @see Bundle#start
+	 */
+	public final static int	STARTED				= 0x00000002;
+
+	/**
+	 * The bundle has been stopped.
+	 * <p>
+	 * The value of <code>STOPPED</code> is 0x00000004.
+	 * 
+	 * @see Bundle#stop
+	 */
+	public final static int	STOPPED				= 0x00000004;
+
+	/**
+	 * The bundle has been updated.
+	 * <p>
+	 * The value of <code>UPDATED</code> is 0x00000008.
+	 * 
+	 * @see Bundle#update()
+	 */
+	public final static int	UPDATED				= 0x00000008;
+
+	/**
+	 * The bundle has been uninstalled.
+	 * <p>
+	 * The value of <code>UNINSTALLED</code> is 0x00000010.
+	 * 
+	 * @see Bundle#uninstall
+	 */
+	public final static int	UNINSTALLED			= 0x00000010;
+
+	/**
+	 * The bundle has been resolved.
+	 * <p>
+	 * The value of <code>RESOLVED</code> is 0x00000020.
+	 * 
+	 * @see Bundle#RESOLVED
+	 * @since 1.3
+	 */
+	public final static int	RESOLVED	= 0x00000020;
+
+	/**
+	 * The bundle has been unresolved.
+	 * <p>
+	 * The value of <code>UNRESOLVED</code> is 0x00000040.
+	 * 
+	 * @see Bundle#INSTALLED
+	 * @since 1.3
+	 */
+	public final static int	UNRESOLVED	= 0x00000040;
+
+	/**
+	 * Creates a bundle event of the specified type.
+	 * 
+	 * @param type The event type.
+	 * @param bundle The bundle which had a lifecycle change.
+	 */
+
+	public BundleEvent(int type, Bundle bundle) {
+		super(bundle);
+		this.bundle = bundle;
+		this.type = type;
+	}
+
+	/**
+	 * Returns the bundle which had a lifecycle change. This bundle is the
+	 * source of the event.
+	 * 
+	 * @return The bundle that had a change occur in its lifecycle.
+	 */
+	public Bundle getBundle() {
+		return bundle;
+	}
+
+	/**
+	 * Returns the type of lifecyle event. The type values are:
+	 * <ul>
+	 * <li>{@link #INSTALLED}
+	 * <li>{@link #STARTED}
+	 * <li>{@link #STOPPED}
+	 * <li>{@link #UPDATED}
+	 * <li>{@link #UNINSTALLED}
+	 * <li>{@link #RESOLVED}
+	 * <li>{@link #UNRESOLVED}
+	 * </ul>
+	 * 
+	 * @return The type of lifecycle event.
+	 */
+
+	public int getType() {
+		return type;
+	}
+}
\ No newline at end of file
diff --git a/src/org/osgi/framework/BundleException.java b/src/org/osgi/framework/BundleException.java
new file mode 100644
index 0000000..c6cade1
--- /dev/null
+++ b/src/org/osgi/framework/BundleException.java
@@ -0,0 +1,95 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/BundleException.java,v 1.10 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+/**
+ * A Framework exception used to indicate that a bundle lifecycle problem
+ * occurred.
+ * 
+ * <p>
+ * <code>BundleException</code> object is created by the Framework to denote an
+ * exception condition in the lifecycle of a bundle. <code>BundleException</code>s
+ * should not be created by bundle developers.
+ * 
+ * <p>
+ * This exception is updated to conform to the general purpose exception
+ * chaining mechanism.
+ * 
+ * @version $Revision: 1.10 $
+ */
+
+public class BundleException extends Exception {
+	static final long	serialVersionUID	= 3571095144220455665L;
+	/**
+	 * Nested exception.
+	 */
+	private Throwable	cause;
+
+	/**
+	 * Creates a <code>BundleException</code> that wraps another exception.
+	 * 
+	 * @param msg The associated message.
+	 * @param cause The cause of this exception.
+	 */
+	public BundleException(String msg, Throwable cause) {
+		super(msg);
+		this.cause = cause;
+	}
+
+	/**
+	 * Creates a <code>BundleException</code> object with the specified message.
+	 * 
+	 * @param msg The message.
+	 */
+	public BundleException(String msg) {
+		super(msg);
+		this.cause = null;
+	}
+
+	/**
+	 * Returns any nested exceptions included in this exception.
+	 * 
+	 * <p>
+	 * This method predates the general purpose exception chaining mechanism.
+	 * The {@link #getCause()} method is now the preferred means of obtaining
+	 * this information.
+	 * 
+	 * @return The nested exception; <code>null</code> if there is no nested
+	 *         exception.
+	 */
+	public Throwable getNestedException() {
+		return cause;
+	}
+
+	/**
+	 * Returns the cause of this exception or <code>null</code> if no cause was
+	 * specified when this exception was created.
+	 * 
+	 * @return The cause of this exception or <code>null</code> if no cause was
+	 *         specified.
+	 * @since 1.3
+	 */
+	public Throwable getCause() {
+		return cause;
+	}
+
+	/**
+	 * The cause of this exception can only be set when constructed.
+	 * 
+	 * @throws java.lang.IllegalStateException This method will always throw an
+	 *         <code>IllegalStateException</code> since the cause of this
+	 *         exception can only be set when constructed.
+	 * @since 1.3
+	 */
+	public Throwable initCause(Throwable cause) {
+		throw new IllegalStateException();
+	}
+}
\ No newline at end of file
diff --git a/src/org/osgi/framework/BundleListener.java b/src/org/osgi/framework/BundleListener.java
new file mode 100644
index 0000000..88c38aa
--- /dev/null
+++ b/src/org/osgi/framework/BundleListener.java
@@ -0,0 +1,38 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/BundleListener.java,v 1.7 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.util.EventListener;
+
+/**
+ * A <code>BundleEvent</code> listener.
+ * 
+ * <p>
+ * <code>BundleListener</code> is a listener interface that may be implemented by
+ * a bundle developer.
+ * <p>
+ * A <code>BundleListener</code> object is registered with the Framework using the
+ * {@link BundleContext#addBundleListener} method. <code>BundleListener</code>s
+ * are called with a <code>BundleEvent</code> object when a bundle has been
+ * installed, resolved, started, stopped, updated, unresolved, or uninstalled.
+ * 
+ * @version $Revision: 1.7 $
+ * @see BundleEvent
+ */
+
+public abstract interface BundleListener extends EventListener {
+	/**
+	 * Receives notification that a bundle has had a lifecycle change.
+	 * 
+	 * @param event The <code>BundleEvent</code>.
+	 */
+	public abstract void bundleChanged(BundleEvent event);
+}
diff --git a/src/org/osgi/framework/BundlePermission.java b/src/org/osgi/framework/BundlePermission.java
new file mode 100644
index 0000000..62b2113
--- /dev/null
+++ b/src/org/osgi/framework/BundlePermission.java
@@ -0,0 +1,578 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/BundlePermission.java,v 1.10 2005/06/21 16:22:12 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2004, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.io.IOException;
+import java.security.*;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * A bundle's authority to require or provide a bundle or to receive or attach
+ * fragments.
+ * 
+ * <p>
+ * A bundle symbolic name defines a unique fully qualified name.
+ * <p>
+ * For example:
+ * 
+ * <pre>
+ * <code>
+ * org.osgi.example.bundle
+ * </code>
+ * </pre>
+ * 
+ * <p>
+ * <code>BundlePermission</code> has four actions: <code>PROVIDE</code>,
+ * <code>REQUIRE</code>,<code>HOST</code>, and <code>FRAGMENT</code>.
+ * The <code>PROVIDE</code> action implies the <code>REQUIRE</code> action.
+ * 
+ * @since 1.3
+ */
+
+public final class BundlePermission extends BasicPermission {
+
+	private static final long	serialVersionUID	= 3257846601685873716L;
+
+	/**
+	 * The action string <code>provide</code>.
+	 */
+	public final static String	PROVIDE				= "provide";
+
+	/**
+	 * The action string <code>require</code>.
+	 */
+	public final static String	REQUIRE				= "require";
+
+	/**
+	 * The action string <code>host</code>.
+	 */
+	public final static String	HOST				= "host";
+
+	/**
+	 * The action string <code>fragment</code>.
+	 */
+	public final static String	FRAGMENT			= "fragment";
+
+	private final static int	ACTION_PROVIDE		= 0x00000001;
+	private final static int	ACTION_REQUIRE		= 0x00000002;
+	private final static int	ACTION_HOST			= 0x00000004;
+	private final static int	ACTION_FRAGMENT		= 0x00000008;
+	private final static int	ACTION_ALL			= ACTION_PROVIDE
+															| ACTION_REQUIRE
+															| ACTION_HOST
+															| ACTION_FRAGMENT;
+	private final static int	ACTION_NONE			= 0;
+	private final static int	ACTION_ERROR		= 0x80000000;
+
+	/**
+	 * The actions mask.
+	 */
+	private transient int		action_mask			= ACTION_NONE;
+
+	/**
+	 * The actions in canonical form.
+	 * 
+	 * @serial
+	 */
+	private String				actions				= null;
+
+	/**
+	 * Defines the authority to provide and/or require and or specify a host
+	 * fragment symbolic name within the OSGi environment.
+	 * <p>
+	 * Bundle Permissions are granted over all possible versions of a bundle.
+	 * 
+	 * A bundle that needs to provide a bundle must have the appropriate
+	 * <code>BundlePermission</code> for the symbolic name; a bundle that
+	 * requires a bundle must have the appropriate <code>BundlePermssion</code>
+	 * for that symbolic name; a bundle that specifies a fragment host must have
+	 * the appropriate <code>BundlePermission</code> for that symbolic name.
+	 * 
+	 * @param symbolicName the bundle symbolic name.
+	 * @param actions <code>PROVIDE</code>,<code>REQUIRE</code>,
+	 *        <code>HOST</code>,<code>FRAGMENT</code> (canonical order).
+	 */
+
+	public BundlePermission(String symbolicName, String actions) {
+		this(symbolicName, getMask(actions));
+	}
+
+	/**
+	 * Bundle private constructor used by BundlePermissionCollection.
+	 * 
+	 * @param symbolicName the bundle symbolic name
+	 * @param mask the action mask
+	 */
+	BundlePermission(String symbolicName, int mask) {
+		super(symbolicName);
+		init(mask);
+	}
+
+	/**
+	 * Called by constructors and when deserialized.
+	 * 
+	 * @param mask
+	 */
+	private void init(int mask) {
+		if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
+			throw new IllegalArgumentException("invalid action string");
+		}
+
+		action_mask = mask;
+	}
+
+	/**
+	 * Parse action string into action mask.
+	 * 
+	 * @param actions Action string.
+	 * @return action mask.
+	 */
+	private static int getMask(String actions) {
+		boolean seencomma = false;
+
+		int mask = ACTION_NONE;
+
+		if (actions == null) {
+			return (mask);
+		}
+
+		char[] a = actions.toCharArray();
+
+		int i = a.length - 1;
+		if (i < 0)
+			return (mask);
+
+		while (i != -1) {
+			char c;
+
+			// skip whitespace
+			while ((i != -1)
+					&& ((c = a[i]) == ' ' || c == '\r' || c == '\n'
+							|| c == '\f' || c == '\t'))
+				i--;
+
+			// check for the known strings
+			int matchlen;
+
+			if (i >= 6 && (a[i - 6] == 'p' || a[i - 6] == 'P')
+					&& (a[i - 5] == 'r' || a[i - 5] == 'R')
+					&& (a[i - 4] == 'o' || a[i - 4] == 'O')
+					&& (a[i - 3] == 'v' || a[i - 3] == 'V')
+					&& (a[i - 2] == 'i' || a[i - 2] == 'I')
+					&& (a[i - 1] == 'd' || a[i - 1] == 'D')
+					&& (a[i] == 'e' || a[i] == 'E')) {
+				matchlen = 7;
+				mask |= ACTION_PROVIDE | ACTION_REQUIRE;
+			}
+			else
+				if (i >= 6 && (a[i - 6] == 'r' || a[i - 6] == 'R')
+						&& (a[i - 5] == 'e' || a[i - 5] == 'E')
+						&& (a[i - 4] == 'q' || a[i - 4] == 'Q')
+						&& (a[i - 3] == 'u' || a[i - 3] == 'U')
+						&& (a[i - 2] == 'i' || a[i - 2] == 'I')
+						&& (a[i - 1] == 'r' || a[i - 1] == 'R')
+						&& (a[i] == 'e' || a[i] == 'E')) {
+					matchlen = 7;
+					mask |= ACTION_REQUIRE;
+				}
+				else
+					if (i >= 3 && (a[i - 3] == 'h' || a[i - 3] == 'H')
+							&& (a[i - 2] == 'o' || a[i - 2] == 'O')
+							&& (a[i - 1] == 's' || a[i - 1] == 'S')
+							&& (a[i] == 't' || a[i] == 'T')) {
+						matchlen = 4;
+						mask |= ACTION_HOST;
+					}
+					else
+						if (i >= 7 && (a[i - 7] == 'f' || a[i - 7] == 'F')
+								&& (a[i - 6] == 'r' || a[i - 6] == 'R')
+								&& (a[i - 5] == 'a' || a[i - 5] == 'A')
+								&& (a[i - 4] == 'g' || a[i - 4] == 'G')
+								&& (a[i - 3] == 'm' || a[i - 3] == 'M')
+								&& (a[i - 2] == 'e' || a[i - 2] == 'E')
+								&& (a[i - 1] == 'n' || a[i - 1] == 'N')
+								&& (a[i] == 't' || a[i] == 'T')) {
+							matchlen = 8;
+							mask |= ACTION_FRAGMENT;
+						}
+						else {
+							// parse error
+							throw new IllegalArgumentException(
+									"invalid permission: " + actions);
+						}
+
+			// make sure we didn't just match the tail of a word
+			// like "ackbarfrequire". Also, skip to the comma.
+			seencomma = false;
+			while (i >= matchlen && !seencomma) {
+				switch (a[i - matchlen]) {
+					case ',' :
+						seencomma = true;
+					/* FALLTHROUGH */
+					case ' ' :
+					case '\r' :
+					case '\n' :
+					case '\f' :
+					case '\t' :
+						break;
+					default :
+						throw new IllegalArgumentException(
+								"invalid permission: " + actions);
+				}
+				i--;
+			}
+
+			// point i at the location of the comma minus one (or -1).
+			i -= matchlen;
+		}
+
+		if (seencomma) {
+			throw new IllegalArgumentException("invalid permission: " + actions);
+		}
+
+		return (mask);
+	}
+
+	/**
+	 * Determines if the specified permission is implied by this object.
+	 * 
+	 * <p>
+	 * This method checks that the symbolic name of the target is implied by the
+	 * symbolic name of this object. The list of <code>BundlePermission</code>
+	 * actions must either match or allow for the list of the target object to
+	 * imply the target <code>BundlePermission</code> action.
+	 * <p>
+	 * The permission to provide a bundle implies the permission to require the
+	 * named symbolic name.
+	 * 
+	 * <pre>
+	 *      x.y.*,&quot;provide&quot; -&gt; x.y.z,&quot;provide&quot; is true
+	 *      *,&quot;require&quot; -&gt; x.y, &quot;require&quot;      is true
+	 *      *,&quot;provide&quot; -&gt; x.y, &quot;require&quot;      is true
+	 *      x.y,&quot;provide&quot; -&gt; x.y.z, &quot;provide&quot;  is false
+	 * </pre>
+	 * 
+	 * @param p The target permission to interrogate.
+	 * @return <code>true</code> if the specified
+	 *         <code>BundlePermission</code> action is implied by this object;
+	 *         <code>false</code> otherwise.
+	 */
+
+	public boolean implies(Permission p) {
+		if (p instanceof BundlePermission) {
+			BundlePermission target = (BundlePermission) p;
+
+			return (((action_mask & target.action_mask) == target.action_mask) && super
+					.implies(p));
+		}
+
+		return (false);
+	}
+
+	/**
+	 * Returns the canonical string representation of the
+	 * <code>BundlePermission</code> actions.
+	 * 
+	 * <p>
+	 * Always returns present <code>BundlePermission</code> actions in the
+	 * following order: <code>PROVIDE</code>,<code>REQUIRE</code>,
+	 * <code>HOST</code>,<code>FRAGMENT.
+	 * @return Canonical string representation of the <code>BundlePermission</code> actions.
+	 */
+
+	public String getActions() {
+		if (actions == null) {
+			StringBuffer sb = new StringBuffer();
+			boolean comma = false;
+
+			if ((action_mask & ACTION_PROVIDE) == ACTION_PROVIDE) {
+				sb.append(PROVIDE);
+				comma = true;
+			}
+
+			if ((action_mask & ACTION_REQUIRE) == ACTION_REQUIRE) {
+				if (comma)
+					sb.append(',');
+				sb.append(REQUIRE);
+				comma = true;
+			}
+
+			if ((action_mask & ACTION_HOST) == ACTION_HOST) {
+				if (comma)
+					sb.append(',');
+				sb.append(HOST);
+			}
+
+			if ((action_mask & ACTION_FRAGMENT) == ACTION_FRAGMENT) {
+				if (comma)
+					sb.append(',');
+				sb.append(FRAGMENT);
+			}
+
+			actions = sb.toString();
+		}
+
+		return (actions);
+	}
+
+	/**
+	 * Returns a new <code>PermissionCollection</code> object suitable for
+	 * storing <code>BundlePermission</code> objects.
+	 * 
+	 * @return A new <code>PermissionCollection</code> object.
+	 */
+	public PermissionCollection newPermissionCollection() {
+		return (new BundlePermissionCollection());
+	}
+
+	/**
+	 * Determines the equality of two <code>BundlePermission</code> objects.
+	 * 
+	 * This method checks that specified bundle has the same bundle symbolic
+	 * name and <code>BundlePermission</code> actions as this
+	 * <code>BundlePermission</code> object.
+	 * 
+	 * @param obj The object to test for equality with this
+	 *        <code>BundlePermission</code> object.
+	 * @return <code>true</code> if <code>obj</code> is a
+	 *         <code>BundlePermission</code>, and has the same bundle
+	 *         symbolic name and actions as this <code>BundlePermission</code>
+	 *         object; <code>false</code> otherwise.
+	 */
+	public boolean equals(Object obj) {
+		if (obj == this) {
+			return (true);
+		}
+
+		if (!(obj instanceof BundlePermission)) {
+			return (false);
+		}
+
+		BundlePermission p = (BundlePermission) obj;
+
+		return ((action_mask == p.action_mask) && getName().equals(p.getName()));
+	}
+
+	/**
+	 * Returns the hash code value for this object.
+	 * 
+	 * @return A hash code value for this object.
+	 */
+
+	public int hashCode() {
+		return (getName().hashCode() ^ getActions().hashCode());
+	}
+
+	/**
+	 * Returns the current action mask.
+	 * <p>
+	 * Used by the BundlePermissionCollection class.
+	 * 
+	 * @return Current action mask.
+	 */
+	int getMask() {
+		return (action_mask);
+	}
+
+	/**
+	 * WriteObject is called to save the state of the
+	 * <code>BundlePermission</code> object to a stream. The actions are
+	 * serialized, and the superclass takes care of the name.
+	 */
+
+	private synchronized void writeObject(java.io.ObjectOutputStream s)
+			throws IOException {
+		// Write out the actions. The superclass takes care of the name
+		// call getActions to make sure actions field is initialized
+		if (actions == null)
+			getActions();
+		s.defaultWriteObject();
+	}
+
+	/**
+	 * readObject is called to restore the state of the BundlePermission from a
+	 * stream.
+	 */
+	private synchronized void readObject(java.io.ObjectInputStream s)
+			throws IOException, ClassNotFoundException {
+		// Read in the action, then initialize the rest
+		s.defaultReadObject();
+		init(getMask(actions));
+	}
+}
+
+/**
+ * Stores a set of <code>BundlePermission</code> permissions.
+ * 
+ * @see java.security.Permission
+ * @see java.security.Permissions
+ * @see java.security.PermissionCollection
+ */
+
+final class BundlePermissionCollection extends PermissionCollection {
+
+	/**
+	 * Comment for <code>serialVersionUID</code>
+	 */
+	private static final long	serialVersionUID	= 3258407326846433079L;
+
+	/**
+	 * Table of permissions.
+	 * 
+	 * @serial
+	 */
+	private Hashtable			permissions;
+
+	/**
+	 * Boolean saying if "*" is in the collection.
+	 * 
+	 * @serial
+	 */
+	private boolean				all_allowed;
+
+	/**
+	 * Create an empty BundlePermissions object.
+	 * 
+	 */
+
+	public BundlePermissionCollection() {
+		permissions = new Hashtable();
+		all_allowed = false;
+	}
+
+	/**
+	 * Adds a permission to the <code>BundlePermission</code> objects. The key
+	 * for the hash is the symbolic name.
+	 * 
+	 * @param permission The <code>BundlePermission</code> object to add.
+	 * 
+	 * @exception IllegalArgumentException If the permission is not a
+	 *            <code>BundlePermission</code> instance.
+	 * 
+	 * @exception SecurityException If this
+	 *            <code>BundlePermissionCollection</code> object has been
+	 *            marked read-only.
+	 */
+
+	public void add(Permission permission) {
+		if (!(permission instanceof BundlePermission))
+			throw new IllegalArgumentException("invalid permission: "
+					+ permission);
+		if (isReadOnly())
+			throw new SecurityException("attempt to add a Permission to a "
+					+ "readonly PermissionCollection");
+
+		BundlePermission bp = (BundlePermission) permission;
+		String name = bp.getName();
+
+		BundlePermission existing = (BundlePermission) permissions.get(name);
+
+		if (existing != null) {
+			int oldMask = existing.getMask();
+			int newMask = bp.getMask();
+			if (oldMask != newMask) {
+				permissions.put(name, new BundlePermission(name, oldMask
+						| newMask));
+
+			}
+		}
+		else {
+			permissions.put(name, permission);
+		}
+
+		if (!all_allowed) {
+			if (name.equals("*"))
+				all_allowed = true;
+		}
+	}
+
+	/**
+	 * Determines if the specified permissions implies the permissions expressed
+	 * in <code>permission</code>.
+	 * 
+	 * @param permission The Permission object to compare with this
+	 *        <code>BundlePermission</code> object.
+	 * 
+	 * @return <code>true</code> if <code>permission</code> is a proper
+	 *         subset of a permission in the set; <code>false</code>
+	 *         otherwise.
+	 */
+
+	public boolean implies(Permission permission) {
+		if (!(permission instanceof BundlePermission))
+			return (false);
+
+		BundlePermission bp = (BundlePermission) permission;
+		BundlePermission x;
+
+		int desired = bp.getMask();
+		int effective = 0;
+
+		// short circuit if the "*" Permission was added
+		if (all_allowed) {
+			x = (BundlePermission) permissions.get("*");
+			if (x != null) {
+				effective |= x.getMask();
+				if ((effective & desired) == desired)
+					return (true);
+			}
+		}
+
+		// strategy:
+		// Check for full match first. Then work our way up the
+		// name looking for matches on a.b.*
+
+		String name = bp.getName();
+
+		x = (BundlePermission) permissions.get(name);
+
+		if (x != null) {
+			// we have a direct hit!
+			effective |= x.getMask();
+			if ((effective & desired) == desired)
+				return (true);
+		}
+
+		// work our way up the tree...
+		int last, offset;
+
+		offset = name.length() - 1;
+
+		while ((last = name.lastIndexOf(".", offset)) != -1) {
+
+			name = name.substring(0, last + 1) + "*";
+			x = (BundlePermission) permissions.get(name);
+
+			if (x != null) {
+				effective |= x.getMask();
+				if ((effective & desired) == desired)
+					return (true);
+			}
+			offset = last - 1;
+		}
+
+		// we don't have to check for "*" as it was already checked
+		// at the top (all_allowed), so we just return false
+		return (false);
+	}
+
+	/**
+	 * Returns an enumeration of all <code>BundlePermission</code> objects in
+	 * the container.
+	 * 
+	 * @return Enumeration of all <code>BundlePermission</code> objects.
+	 */
+
+	public Enumeration elements() {
+		return (permissions.elements());
+	}
+}
diff --git a/src/org/osgi/framework/Configurable.java b/src/org/osgi/framework/Configurable.java
new file mode 100644
index 0000000..27f5ec2
--- /dev/null
+++ b/src/org/osgi/framework/Configurable.java
@@ -0,0 +1,44 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/Configurable.java,v 1.7 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+/**
+ * Supports a configuration object.
+ *
+ * <p><code>Configurable</code> is an interface that should be used by a bundle developer in support
+ * of a configurable service.
+ * Bundles that need to configure a service may test to determine
+ * if the service object is an <code>instanceof Configurable</code>.
+ *
+ * @version $Revision: 1.7 $
+ * @deprecated Please use the Configuration Admin
+ */
+public abstract interface Configurable
+{
+    /**
+     * Returns this service's configuration object.
+     *
+     * <p>Services implementing <code>Configurable</code> should take care when returning a
+     * service configuration object since this object is probably sensitive.
+     * <p>If the Java Runtime Environment supports permissions, it is recommended that
+     * the caller is checked for the appropriate permission before returning the configuration object.
+     * It is recommended that callers possessing the appropriate
+     * {@link AdminPermission} always be allowed to get the configuration object.
+     *
+     * @return The configuration object for this service.
+     * @exception java.lang.SecurityException If the caller does not have
+     * an appropriate permission and the Java Runtime Environment supports permissions.
+     * @deprecated Please use the Configuration Admin
+     */
+    public abstract Object getConfigurationObject();
+}
+
+
diff --git a/src/org/osgi/framework/Constants.java b/src/org/osgi/framework/Constants.java
new file mode 100644
index 0000000..d4b012f
--- /dev/null
+++ b/src/org/osgi/framework/Constants.java
@@ -0,0 +1,1015 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/Constants.java,v 1.18 2005/06/21 15:45:08 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.util.Dictionary;
+
+/**
+ * Defines standard names for the OSGi environment property, service property,
+ * and Manifest header attribute keys.
+ * 
+ * <p>
+ * The values associated with these keys are of type <code>java.lang.String</code>,
+ * unless otherwise indicated.
+ * 
+ * @version $Revision: 1.18 $
+ * @since 1.1
+ * @see Bundle#getHeaders()
+ * @see BundleContext#getProperty
+ * @see BundleContext#registerService(String[],Object,Dictionary)
+ */
+
+public interface Constants {
+	/**
+	 * Location identifier of the OSGi <i>system bundle </i>, which is defined
+	 * to be &quot;System Bundle&quot;.
+	 */
+	public static final String	SYSTEM_BUNDLE_LOCATION					= "System Bundle";
+
+	/**
+	 * Alias for the symbolic name of the OSGi <i>system bundle </i>. It is defined
+	 * to be &quot;system.bundle&quot;.
+	 * @since 1.3
+	 */
+	public static final String	SYSTEM_BUNDLE_SYMBOLICNAME				= "system.bundle";
+
+	/**
+	 * Manifest header (named &quot;Bundle-Category&quot;) identifying the
+	 * bundle's category.
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	BUNDLE_CATEGORY							= "Bundle-Category";
+
+	/**
+	 * Manifest header (named &quot;Bundle-ClassPath&quot;) identifying a list
+	 * of directories and embedded JAR files, which are bundle resources used
+	 * to extend the bundle's classpath.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	BUNDLE_CLASSPATH						= "Bundle-ClassPath";
+
+	/**
+	 * Manifest header (named &quot;Bundle-Copyright&quot;) identifying the
+	 * bundle's copyright information.
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	BUNDLE_COPYRIGHT						= "Bundle-Copyright";
+
+	/**
+	 * Manifest header (named &quot;Bundle-Description&quot;) containing a brief
+	 * description of the bundle's functionality.
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	BUNDLE_DESCRIPTION						= "Bundle-Description";
+
+	/**
+	 * Manifest header (named &quot;Bundle-Name&quot;) identifying the bundle's
+	 * name.
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	BUNDLE_NAME								= "Bundle-Name";
+
+	/**
+	 * Manifest header (named &quot;Bundle-NativeCode&quot;) identifying a
+	 * number of hardware environments and the native language code libraries
+	 * that the bundle is carrying for each of these environments.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	BUNDLE_NATIVECODE						= "Bundle-NativeCode";
+
+	/**
+	 * Manifest header (named &quot;Export-Package&quot;) identifying 
+	 * the packages that the bundle offers to the Framework for export.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	EXPORT_PACKAGE							= "Export-Package";
+
+	/**
+	 * Manifest header (named &quot;Export-Service&quot;) identifying the fully
+	 * qualified class names of the services that the bundle may register (used
+	 * for informational purposes only).
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	EXPORT_SERVICE							= "Export-Service";
+
+	/**
+	 * Manifest header (named &quot;Import-Package&quot;) identifying
+	 * the packages on which the bundle depends.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	IMPORT_PACKAGE							= "Import-Package";
+
+	/**
+	 * Manifest header (named &quot;DynamicImport-Package&quot;) identifying
+	 * the packages that the bundle may dynamically import during
+	 * execution.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 * 
+	 * @since 1.2
+	 */
+	public static final String	DYNAMICIMPORT_PACKAGE					= "DynamicImport-Package";
+
+	/**
+	 * Manifest header (named &quot;Import-Service&quot;) identifying the fully
+	 * qualified class names of the services that the bundle requires (used for
+	 * informational purposes only).
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	IMPORT_SERVICE							= "Import-Service";
+
+	/**
+	 * Manifest header (named &quot;Bundle-Vendor&quot;) identifying the
+	 * bundle's vendor.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	BUNDLE_VENDOR							= "Bundle-Vendor";
+
+	/**
+	 * Manifest header (named &quot;Bundle-Version&quot;) identifying the
+	 * bundle's version.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	BUNDLE_VERSION							= "Bundle-Version";
+
+	/**
+	 * Manifest header (named &quot;Bundle-DocURL&quot;) identifying the
+	 * bundle's documentation URL, from which further information about the
+	 * bundle may be obtained.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	BUNDLE_DOCURL							= "Bundle-DocURL";
+
+	/**
+	 * Manifest header (named &quot;Bundle-ContactAddress&quot;) identifying the
+	 * contact address where problems with the bundle may be reported; for
+	 * example, an email address.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	BUNDLE_CONTACTADDRESS					= "Bundle-ContactAddress";
+
+	/**
+	 * Manifest header attribute (named &quot;Bundle-Activator&quot;)
+	 * identifying the bundle's activator class.
+	 * 
+	 * <p>
+	 * If present, this header specifies the name of the bundle resource class
+	 * that implements the <code>BundleActivator</code> interface and whose
+	 * <code>start</code> and <code>stop</code> methods are called by the Framework
+	 * when the bundle is started and stopped, respectively.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	BUNDLE_ACTIVATOR						= "Bundle-Activator";
+
+	/**
+	 * Manifest header (named &quot;Bundle-UpdateLocation&quot;) identifying the
+	 * location from which a new bundle version is obtained during a bundle
+	 * update operation.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 */
+	public static final String	BUNDLE_UPDATELOCATION					= "Bundle-UpdateLocation";
+
+	/**
+	 * Manifest header attribute (named &quot;specification-version&quot;)
+	 * identifying the version of a package specified in the Export-Package or
+	 * Import-Package manifest header.
+	 * 
+	 * <p>
+	 * The attribute value is encoded in the Export-Package or Import-Package
+	 * manifest header like:
+	 * 
+	 * <pre>
+	 *  Import-Package: org.osgi.framework ; specification-version=&quot;1.1&quot;
+	 * </pre>
+	 * @deprecated Since 1.3, this has been replaced by {@link #VERSION_ATTRIBUTE}.
+	 */
+	public static final String	PACKAGE_SPECIFICATION_VERSION			= "specification-version";
+
+	/**
+	 * Manifest header attribute (named &quot;processor&quot;) identifying the
+	 * processor required to run native bundle code specified in the
+	 * Bundle-NativeCode manifest header).
+	 * 
+	 * <p>
+	 * The attribute value is encoded in the Bundle-NativeCode manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Bundle-NativeCode: http.so ; processor=x86 ...
+	 * </pre>
+	 */
+	public static final String	BUNDLE_NATIVECODE_PROCESSOR				= "processor";
+
+	/**
+	 * Manifest header attribute (named &quot;osname&quot;) identifying the
+	 * operating system required to run native bundle code specified in the
+	 * Bundle-NativeCode manifest header).
+	 * <p>
+	 * The attribute value is encoded in the Bundle-NativeCode manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Bundle-NativeCode: http.so ; osname=Linux ...
+	 * </pre>
+	 */
+	public static final String	BUNDLE_NATIVECODE_OSNAME				= "osname";
+
+	/**
+	 * Manifest header attribute (named &quot;osversion&quot;) identifying the
+	 * operating system version required to run native bundle code specified in
+	 * the Bundle-NativeCode manifest header).
+	 * <p>
+	 * The attribute value is encoded in the Bundle-NativeCode manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Bundle-NativeCode: http.so ; osversion=&quot;2.34&quot; ...
+	 * </pre>
+	 */
+	public static final String	BUNDLE_NATIVECODE_OSVERSION				= "osversion";
+
+	/**
+	 * Manifest header attribute (named &quot;language&quot;) identifying the
+	 * language in which the native bundle code is written specified in the
+	 * Bundle-NativeCode manifest header. See ISO 639 for possible values.
+	 * <p>
+	 * The attribute value is encoded in the Bundle-NativeCode manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Bundle-NativeCode: http.so ; language=nl_be ...
+	 * </pre>
+	 */
+	public static final String	BUNDLE_NATIVECODE_LANGUAGE				= "language";
+
+	/**
+	 * Manifest header (named &quot;Bundle-RequiredExecutionEnvironment&quot;)
+	 * identifying the required execution environment for the bundle. The
+	 * service platform may run this bundle if any of the execution environments
+	 * named in this header matches one of the execution environments it
+	 * implements.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 * 
+	 * @since 1.2
+	 */
+	public static final String	BUNDLE_REQUIREDEXECUTIONENVIRONMENT		= "Bundle-RequiredExecutionEnvironment";
+
+	/*
+	 * Framework environment properties.
+	 */
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.framework.version&quot;) identifying the Framework
+	 * version.
+	 * 
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 */
+	public static final String	FRAMEWORK_VERSION						= "org.osgi.framework.version";
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.framework.vendor&quot;) identifying the Framework
+	 * implementation vendor.
+	 * 
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 */
+	public static final String	FRAMEWORK_VENDOR						= "org.osgi.framework.vendor";
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.framework.language&quot;) identifying the Framework
+	 * implementation language (see ISO 639 for possible values).
+	 * 
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 */
+	public static final String	FRAMEWORK_LANGUAGE						= "org.osgi.framework.language";
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.framework.os.name&quot;) identifying the Framework
+	 * host-computer's operating system.
+	 * 
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 */
+	public static final String	FRAMEWORK_OS_NAME						= "org.osgi.framework.os.name";
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.framework.os.version&quot;) identifying the Framework
+	 * host-computer's operating system version number.
+	 * 
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 */
+	public static final String	FRAMEWORK_OS_VERSION					= "org.osgi.framework.os.version";
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.framework.processor&quot;) identifying the Framework
+	 * host-computer's processor name.
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 */
+	public static final String	FRAMEWORK_PROCESSOR						= "org.osgi.framework.processor";
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.framework.executionenvironment&quot;) identifying
+	 * execution environments provided by the Framework.
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 * 
+	 * @since 1.2
+	 */
+	public static final String	FRAMEWORK_EXECUTIONENVIRONMENT			= "org.osgi.framework.executionenvironment";
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.framework.bootdelegation&quot;) identifying
+	 * packages for which the Framework must delegate class loading to the boot class path.
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 * 
+	 * @since 1.3
+	 */
+	public static final String	FRAMEWORK_BOOTDELEGATION			= "org.osgi.framework.bootdelegation";
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.framework.system.packages&quot;) identifying
+	 * package which the system bundle must export.
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 * 
+	 * @since 1.3
+	 */
+	public static final String	FRAMEWORK_SYSTEMPACKAGES			= "org.osgi.framework.system.packages";
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.supports.framework.extension&quot;) identifying
+	 * whether the Framework supports framework extension bundles.
+	 * If the value of this property is <code>true</code>, then the Framework
+	 * supports framework extension bundles.
+	 * The default value is <code>false</code>.
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 * 
+	 * @since 1.3
+	 */
+	public static final String	SUPPORTS_FRAMEWORK_EXTENSION			= "org.osgi.supports.framework.extension";
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.supports.bootclasspath.extension&quot;) identifying
+	 * whether the Framework supports bootclasspath extension bundles.
+	 * If the value of this property is <code>true</code>, then the Framework
+	 * supports bootclasspath extension bundles.
+	 * The default value is <code>false</code>.
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 * 
+	 * @since 1.3
+	 */
+	public static final String	SUPPORTS_BOOTCLASSPATH_EXTENSION		= "org.osgi.supports.bootclasspath.extension";
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.supports.framework.fragment&quot;) identifying
+	 * whether the Framework supports fragment bundles.
+	 * If the value of this property is <code>true</code>, then the Framework
+	 * supports fragment bundles.
+	 * The default value is <code>false</code>.
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 * 
+	 * @since 1.3
+	 */
+	public static final String	SUPPORTS_FRAMEWORK_FRAGMENT			= "org.osgi.supports.framework.fragment";
+
+	/**
+	 * Framework environment property (named
+	 * &quot;org.osgi.supports.framework.requirebundle&quot;) identifying
+	 * whether the Framework supports the <code>Require-Bundle</code> manifest header.
+	 * If the value of this property is <code>true</code>, then the Framework
+	 * supports the <code>Require-Bundle</code> manifest header.
+	 * The default value is <code>false</code>.
+	 * <p>
+	 * The value of this property may be retrieved by calling the
+	 * <code>BundleContext.getProperty</code> method.
+	 * 
+	 * @since 1.3
+	 */
+	public static final String	SUPPORTS_FRAMEWORK_REQUIREBUNDLE			= "org.osgi.supports.framework.requirebundle";
+
+	/*
+	 * Service properties.
+	 */
+
+	/**
+	 * Service property (named &quot;objectClass&quot;) identifying all of the
+	 * class names under which a service was registered in the Framework (of
+	 * type <code>java.lang.String[]</code>).
+	 * 
+	 * <p>
+	 * This property is set by the Framework when a service is registered.
+	 */
+	public static final String	OBJECTCLASS								= "objectClass";
+
+	/**
+	 * Service property (named &quot;service.id&quot;) identifying a service's
+	 * registration number (of type <code>java.lang.Long</code>).
+	 * 
+	 * <p>
+	 * The value of this property is assigned by the Framework when a service is
+	 * registered. The Framework assigns a unique value that is larger than all
+	 * previously assigned values since the Framework was started. These values
+	 * are NOT persistent across restarts of the Framework.
+	 */
+	public static final String	SERVICE_ID								= "service.id";
+
+	/**
+	 * Service property (named &quot;service.pid&quot;) identifying a service's
+	 * persistent identifier.
+	 * 
+	 * <p>
+	 * This property may be supplied in the <code>properties</code>
+	 * <code>Dictionary</code>
+	 * object passed to the <code>BundleContext.registerService</code> method.
+	 * 
+	 * <p>
+	 * A service's persistent identifier uniquely identifies the service and
+	 * persists across multiple Framework invocations.
+	 * 
+	 * <p>
+	 * By convention, every bundle has its own unique namespace, starting with
+	 * the bundle's identifier (see {@link Bundle#getBundleId}) and followed by
+	 * a dot (.). A bundle may use this as the prefix of the persistent
+	 * identifiers for the services it registers.
+	 */
+	public static final String	SERVICE_PID								= "service.pid";
+
+	/**
+	 * Service property (named &quot;service.ranking&quot;) identifying a
+	 * service's ranking number (of type <code>java.lang.Integer</code>).
+	 * 
+	 * <p>
+	 * This property may be supplied in the <code>properties
+	 * Dictionary</code>
+	 * object passed to the <code>BundleContext.registerService</code> method.
+	 * 
+	 * <p>
+	 * The service ranking is used by the Framework to determine the <i>default
+	 * </i> service to be returned from a call to the
+	 * {@link BundleContext#getServiceReference}method: If more than one
+	 * service implements the specified class, the <code>ServiceReference</code>
+	 * object with the highest ranking is returned.
+	 * 
+	 * <p>
+	 * The default ranking is zero (0). A service with a ranking of
+	 * <code>Integer.MAX_VALUE</code> is very likely to be returned as the default
+	 * service, whereas a service with a ranking of <code>Integer.MIN_VALUE</code>
+	 * is very unlikely to be returned.
+	 * 
+	 * <p>
+	 * If the supplied property value is not of type <code>java.lang.Integer</code>,
+	 * it is deemed to have a ranking value of zero.
+	 */
+	public static final String	SERVICE_RANKING							= "service.ranking";
+
+	/**
+	 * Service property (named &quot;service.vendor&quot;) identifying a
+	 * service's vendor.
+	 * 
+	 * <p>
+	 * This property may be supplied in the properties <code>Dictionary</code>
+	 * object passed to the <code>BundleContext.registerService</code> method.
+	 */
+	public static final String	SERVICE_VENDOR							= "service.vendor";
+
+	/**
+	 * Service property (named &quot;service.description&quot;) identifying a
+	 * service's description.
+	 * 
+	 * <p>
+	 * This property may be supplied in the properties <code>Dictionary</code>
+	 * object passed to the <code>BundleContext.registerService</code> method.
+	 */
+	public static final String	SERVICE_DESCRIPTION						= "service.description";
+
+	/**
+	 * Manifest header (named &quot;Bundle-SymbolicName&quot;) identifying the
+	 * bundle's symbolic name.
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	BUNDLE_SYMBOLICNAME						= "Bundle-SymbolicName";
+
+	/**
+	 * Manifest header directive (named &quot;singleton&quot;) identifying
+	 * whether a bundle is a singleton. The default value is <code>false</code>.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Bundle-SymbolicName manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Bundle-SymbolicName: com.acme.module.test; singleton:=true
+	 * </pre>
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	SINGLETON_DIRECTIVE						= "singleton";
+
+	/**
+	 * Manifest header directive (named &quot;fragment-attachment&quot;)
+	 * identifying if and when a fragment may attach to a host bundle. The
+	 * default value is <code>&quot;always&quot;</code>.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Bundle-SymbolicName manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Bundle-SymbolicName: com.acme.module.test; fragment-attachment:=&quot;never&quot;
+	 * </pre>
+	 * 
+	 * @see Constants#FRAGMENT_ATTACHMENT_ALWAYS
+	 * @see Constants#FRAGMENT_ATTACHMENT_RESOLVETIME
+	 * @see Constants#FRAGMENT_ATTACHMENT_NEVER
+	 * @since 1.3
+	 */
+	public final static String	FRAGMENT_ATTACHMENT_DIRECTIVE			= "fragment-attachment";
+
+	/**
+	 * Manifest header directive value (named &quot;always&quot;) identifying a
+	 * fragment attachment type of always. A fragment attachment type of always
+	 * indicates that fragments are allowed to attach to the host bundle at any
+	 * time (while the host is resolved or during the process of resolving the
+	 * host bundle).
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Bundle-SymbolicName manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Bundle-SymbolicName: com.acme.module.test; fragment-attachment:=&quot;always&quot;
+	 * </pre>
+	 * 
+	 * @see Constants#FRAGMENT_ATTACHMENT_DIRECTIVE
+	 * @since 1.3
+	 */
+	public final static String	FRAGMENT_ATTACHMENT_ALWAYS				= "always";
+
+	/**
+	 * Manifest header directive value (named &quot;resolve-time&quot;)
+	 * identifying a fragment attachment type of resolve-time. A fragment
+	 * attachment type of resolve-time indicates that fragments are allowed to
+	 * attach to the host bundle only during the process of resolving the host
+	 * bundle.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Bundle-SymbolicName manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Bundle-SymbolicName: com.acme.module.test; fragment-attachment:=&quot;resolve-time&quot;
+	 * </pre>
+	 * 
+	 * @see Constants#FRAGMENT_ATTACHMENT_DIRECTIVE
+	 * @since 1.3
+	 */
+	public final static String	FRAGMENT_ATTACHMENT_RESOLVETIME			= "resolve-time";
+
+	/**
+	 * Manifest header directive value (named &quot;never&quot;) identifying a
+	 * fragment attachment type of never. A fragment attachment type of never
+	 * indicates that no fragments are allowed to attach to the host bundle at
+	 * any time.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Bundle-SymbolicName manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Bundle-SymbolicName: com.acme.module.test; fragment-attachment:=&quot;never&quot;
+	 * </pre>
+	 * 
+	 * @see Constants#FRAGMENT_ATTACHMENT_DIRECTIVE
+	 * @since 1.3
+	 */
+	public final static String	FRAGMENT_ATTACHMENT_NEVER				= "never";
+
+	/**
+	 * Manifest header (named &quot;Bundle-Localization&quot;) identifying the
+	 * base name of the bundle's localization entries.
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 * 
+	 * @see #BUNDLE_LOCALIZATION_DEFAULT_BASENAME
+	 * @since 1.3
+	 */
+	public final static String	BUNDLE_LOCALIZATION						= "Bundle-Localization";
+
+	/**
+	 * Default value for the <code>Bundle-Localization</code> manifest header.
+	 * 
+	 * @see #BUNDLE_LOCALIZATION
+	 * @since 1.3
+	 */
+	public final static String	BUNDLE_LOCALIZATION_DEFAULT_BASENAME	= "OSGI-INF/l10n/bundle";
+
+	/**
+	 * Manifest header (named &quot;Require-Bundle&quot;) identifying the
+	 * symbolic names of other bundles required by the bundle.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	REQUIRE_BUNDLE							= "Require-Bundle";
+
+	/**
+	 * Manifest header attribute (named &quot;bundle-version&quot;) identifying
+	 * a range of versions for a bundle specified in the Require-Bundle or
+	 * Fragment-Host manifest headers. The default value is <code>0.0.0</code>.
+	 * 
+	 * <p>
+	 * The attribute value is encoded in the Require-Bundle manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Require-Bundle: com.acme.module.test; bundle-version=&quot;1.1&quot;
+	 *  Require-Bundle: com.acme.module.test; bundle-version=&quot;[1.0,2.0)&quot;
+	 * </pre>
+	 * 
+	 * <p>
+	 * The bundle-version attribute value uses a mathematical interval notation
+	 * to specify a range of bundle versions. A bundle-version attribute value
+	 * specified as a single version means a version range that includes any
+	 * bundle version greater than or equal to the specified version.
+	 * 
+	 * @since 1.3
+	 */
+	public static final String	BUNDLE_VERSION_ATTRIBUTE				= "bundle-version";
+
+	/**
+	 * Manifest header (named &quot;Fragment-Host&quot;) identifying the
+	 * symbolic name of another bundle for which that the bundle is a fragment.
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	FRAGMENT_HOST							= "Fragment-Host";
+
+	/**
+	 * Manifest header directive (named &quot;multiple-hosts&quot;) identifying
+	 * if the fragment should attach to each bundle selected by the
+	 * Fragment-Host manifest header. The default value is <code>false</code>.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Fragment-Host manifest header like:
+	 * 
+	 * <pre>
+	 *  Fragment-Host: com.acme.module.test; multiple-hosts:=&quot;false&quot;
+	 * </pre>
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	MULTIPLE_HOSTS_DIRECTIVE				= "multiple-hosts";
+
+	/**
+	 * Manifest header attribute (named &quot;selection-filter&quot;) is used
+	 * for selection by filtering based upon system properties.
+	 * 
+	 * <p>
+	 * The attribute value is encoded in manifest headers like:
+	 * 
+	 * <pre>
+	 *  Bundle-NativeCode: libgtk.so; selection-filter=&quot;(ws=gtk)&quot;; ...
+	 * </pre>
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	SELECTION_FILTER_ATTRIBUTE				= "selection-filter";
+
+	/**
+	 * Manifest header (named &quot;Bundle-ManifestVersion&quot;) identifying
+	 * the bundle manifest version. A bundle manifest may express the version of
+	 * the syntax in which it is written by specifying a bundle manifest
+	 * version. Bundles exploiting OSGi R4, or later, syntax must specify a
+	 * bundle manifest version.
+	 * <p>
+	 * The bundle manifest version defined by OSGi R4 or, more specifically, by
+	 * V1.3 of the OSGi Framework Specification is "2".
+	 * 
+	 * <p>
+	 * The attribute value may be retrieved from the <code>Dictionary</code>
+	 * object returned by the <code>Bundle.getHeaders</code> method.
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	BUNDLE_MANIFESTVERSION					= "Bundle-ManifestVersion";
+
+	/**
+	 * Manifest header attribute (named &quot;version&quot;) identifying the
+	 * version of a package specified in the Export-Package or Import-Package
+	 * manifest header.
+	 * 
+	 * <p>
+	 * The attribute value is encoded in the Export-Package or Import-Package
+	 * manifest header like:
+	 * 
+	 * <pre>
+	 *  Import-Package: org.osgi.framework; version=&quot;1.1&quot;
+	 * </pre>
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	VERSION_ATTRIBUTE						= "version";
+
+	/**
+	 * Manifest header attribute (named &quot;bundle-symbolic-name&quot;)
+	 * identifying the symbolic name of a bundle that exports a package
+	 * specified in the Import-Package manifest header.
+	 * 
+	 * <p>
+	 * The attribute value is encoded in the Import-Package manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Import-Package: org.osgi.framework; bundle-symbolic-name=&quot;com.acme.module.test&quot;
+	 * </pre>
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	BUNDLE_SYMBOLICNAME_ATTRIBUTE			= "bundle-symbolic-name";
+
+	/**
+	 * Manifest header directive (named &quot;resolution&quot;) identifying the
+	 * resolution type in the Import-Package or Require-Bundle manifest header.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Import-Package or Require-Bundle
+	 * manifest header like:
+	 * 
+	 * <pre>
+	 *  Import-Package: org.osgi.framework; resolution:=&quot;optional&quot;
+	 *  Require-Bundle: com.acme.module.test; resolution:=&quot;optional&quot;
+	 * </pre>
+	 * 
+	 * @see Constants#RESOLUTION_MANDATORY
+	 * @see Constants#RESOLUTION_OPTIONAL
+	 * @since 1.3
+	 */
+	public final static String	RESOLUTION_DIRECTIVE					= "resolution";
+
+	/**
+	 * Manifest header directive value (named &quot;mandatory&quot;) identifying
+	 * a mandatory resolution type. A mandatory resolution type indicates that
+	 * the import package or require bundle must be resolved when the bundle is
+	 * resolved. If such an import or require bundle cannot be resolved, the
+	 * module fails to resolve.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Import-Package or Require-Bundle
+	 * manifest header like:
+	 * 
+	 * <pre>
+	 *  Import-Package: org.osgi.framework; resolution:=&quot;manditory&quot;
+	 *  Require-Bundle: com.acme.module.test; resolution:=&quot;manditory&quot;
+	 * </pre>
+	 * 
+	 * @see Constants#RESOLUTION_DIRECTIVE
+	 * @since 1.3
+	 */
+	public final static String	RESOLUTION_MANDATORY					= "mandatory";
+
+	/**
+	 * Manifest header directive value (named &quot;optional&quot;) identifying
+	 * an optional resolution type. An optional resolution type indicates that
+	 * the import or require bundle is optional and the bundle may be resolved
+	 * without the import or require bundle being resolved. If the import or
+	 * require bundle is not resolved when the bundle is resolved, the import or
+	 * require bundle may not be resolved before the bundle is refreshed.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Import-Package or Require-Bundle
+	 * manifest header like:
+	 * 
+	 * <pre>
+	 *  Import-Package: org.osgi.framework; resolution:=&quot;optional&quot;
+	 *  Require-Bundle: com.acme.module.test; resolution:=&quot;optional&quot;
+	 * </pre>
+	 * 
+	 * @see Constants#RESOLUTION_DIRECTIVE
+	 * @since 1.3
+	 */
+	public final static String	RESOLUTION_OPTIONAL						= "optional";
+
+	/**
+	 * Manifest header directive (named &quot;uses&quot;) identifying a list of
+	 * packages that an exported package uses.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Export-Package manifest header like:
+	 * 
+	 * <pre>
+	 *  Export-Package: org.osgi.util.tracker; uses:=&quot;org.osgi.framework&quot;
+	 * </pre>
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	USES_DIRECTIVE						= "uses";
+
+	/**
+	 * Manifest header directive (named &quot;include&quot;) identifying a list
+	 * of classes and/or resources of the specified package which must be
+	 * allowed to be exported in the Export-Package manifest header.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Export-Package manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Export-Package: org.osgi.framework; include:=&quot;MyStuff*&quot;
+	 * </pre>
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	INCLUDE_DIRECTIVE						= "include";
+
+	/**
+	 * Manifest header directive (named &quot;exclude&quot;) identifying a list
+	 * of classes and/or resources of the specified package which must not be
+	 * allowed to be exported in the Export-Package manifest header.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Export-Package manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Export-Package: org.osgi.framework; exclude:=&quot;MyStuff*&quot;
+	 * </pre>
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	EXCLUDE_DIRECTIVE						= "exclude";
+
+	/**
+	 * Manifest header directive (named &quot;mandatory&quot;) identifying names
+	 * of matching attributes which must be specified by matching Import-Package
+	 * statements in the Export-Package manifest header.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Export-Package manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Export-Package: org.osgi.framework; mandatory:=&quot;bundle-symbolic-name&quot;
+	 * </pre>
+	 * 
+	 * @since 1.3
+	 */
+	public final static String	MANDATORY_DIRECTIVE						= "mandatory";
+
+	/**
+	 * Manifest header directive (named &quot;visibility&quot;) identifying the
+	 * visibility of a reqiured bundle in the Require-Bundle manifest header.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Require-Bundle manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Require-Bundle: com.acme.module.test; visibility:=&quot;reexport&quot;
+	 * </pre>
+	 * 
+	 * @see Constants#VISIBILITY_PRIVATE
+	 * @see Constants#VISIBILITY_REEXPORT
+	 * @since 1.3
+	 */
+	public final static String	VISIBILITY_DIRECTIVE					= "visibility";
+
+	/**
+	 * Manifest header directive value (named &quot;private&quot;) identifying a
+	 * private visibility type. A private visibility type indicates that any
+	 * packages that are exported by the required bundle are not made visible on
+	 * the export signature of the requiring bundle.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Require-Bundle manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Require-Bundle: com.acme.module.test; visibility:=&quot;private&quot;
+	 * </pre>
+	 * 
+	 * @see Constants#VISIBILITY_DIRECTIVE
+	 * @since 1.3
+	 */
+	public final static String	VISIBILITY_PRIVATE						= "private";
+
+	/**
+	 * Manifest header directive value (named &quot;reexport&quot;) identifying
+	 * a reexport visibility type. A reexport visibility type indicates any
+	 * packages that are exported by the required bundle are re-exported by the
+	 * requiring bundle. Any arbitrary arbitrary matching attributes with which
+	 * they were exported by the required bundle are deleted.
+	 * 
+	 * <p>
+	 * The directive value is encoded in the Require-Bundle manifest header
+	 * like:
+	 * 
+	 * <pre>
+	 *  Require-Bundle: com.acme.module.test; visibility:=&quot;reexport&quot;
+	 * </pre>
+	 * 
+	 * @see Constants#VISIBILITY_DIRECTIVE
+	 * @since 1.3
+	 */
+	public final static String	VISIBILITY_REEXPORT						= "reexport";
+}
\ No newline at end of file
diff --git a/src/org/osgi/framework/Filter.java b/src/org/osgi/framework/Filter.java
new file mode 100644
index 0000000..262675f
--- /dev/null
+++ b/src/org/osgi/framework/Filter.java
@@ -0,0 +1,111 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/Filter.java,v 1.11 2005/05/13 20:32:56 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+package org.osgi.framework;
+
+import java.util.Dictionary;
+
+/**
+ * An RFC 1960-based Filter.
+ * <p>
+ * <code>Filter</code> objects can be created by calling
+ * {@link BundleContext#createFilter} with the chosen filter string.
+ * <p>
+ * A <code>Filter</code> object can be used numerous times to determine if the
+ * match argument matches the filter string that was used to create the
+ * <code>Filter</code> object.
+ * <p>
+ * Some examples of LDAP filters are:
+ * 
+ * <pre>
+ *     &quot;(cn=Babs Jensen)&quot;
+ *     &quot;(!(cn=Tim Howes))&quot;
+ *     &quot;(&amp;(&quot; + Constants.OBJECTCLASS + &quot;=Person)(|(sn=Jensen)(cn=Babs J*)))&quot;
+ *     &quot;(o=univ*of*mich*)&quot;
+ * </pre>
+ * 
+ * @version $Revision: 1.11 $
+ * @since 1.1
+ * @see "Framework specification for a description of the filter string syntax."
+ */
+public interface Filter {
+	/**
+	 * Filter using a service's properties.
+	 * <p>
+	 * The filter is executed using the keys and values of the referenced service's
+	 * properties.  The keys are case insensitively matched with the filter.
+	 * 
+	 * @param reference The reference to the service whose properties are used
+	 *        in the match.
+	 * 
+	 * @return <code>true</code> if the service's properties match this filter;
+	 *         <code>false</code> otherwise.
+	 */
+	public boolean match(ServiceReference reference);
+
+	/**
+	 * Filter using a <code>Dictionary</code> object. The Filter is executed using
+	 * the <code>Dictionary</code> object's keys and values.
+	 * The keys are case insensitively matched with the filter.
+	 * 
+	 * @param dictionary The <code>Dictionary</code> object whose keys are used in
+	 *        the match.
+	 * 
+	 * @return <code>true</code> if the <code>Dictionary</code> object's keys and
+	 *         values match this filter; <code>false</code> otherwise.
+	 * 
+	 * @exception IllegalArgumentException If <code>dictionary</code> contains
+	 *            case variants of the same key name.
+	 */
+	public boolean match(Dictionary dictionary);
+
+	/**
+	 * Returns this <code>Filter</code> object's filter string.
+	 * <p>
+	 * The filter string is normalized by removing whitespace which does not
+	 * affect the meaning of the filter.
+	 * 
+	 * @return Filter string.
+	 */
+	public String toString();
+
+	/**
+	 * Compares this <code>Filter</code> object to another object.
+	 * 
+	 * @param obj The object to compare against this <code>Filter</code> object.
+	 * 
+	 * @return If the other object is a <code>Filter</code> object, then returns
+	 *         <code>this.toString().equals(obj.toString()</code>;<code>false</code>
+	 *         otherwise.
+	 */
+	public boolean equals(Object obj);
+
+	/**
+	 * Returns the hashCode for this <code>Filter</code> object.
+	 * 
+	 * @return The hashCode of the filter string; that is,
+	 *         <code>this.toString().hashCode()</code>.
+	 */
+	public int hashCode();
+
+	/**
+	 * Filter with case sensitivity using a <code>Dictionary</code> object. The
+	 * Filter is executed using the <code>Dictionary</code> object's keys and
+	 * values. The keys are case sensitively matched with the filter.
+	 * 
+	 * @param dictionary The <code>Dictionary</code> object whose keys are used in
+	 *        the match.
+	 * 
+	 * @return <code>true</code> if the <code>Dictionary</code> object's keys and
+	 *         values match this filter; <code>false</code> otherwise.
+	 * 
+	 * @since 1.3
+	 */
+	public boolean matchCase(Dictionary dictionary);
+}
\ No newline at end of file
diff --git a/src/org/osgi/framework/FrameworkEvent.java b/src/org/osgi/framework/FrameworkEvent.java
new file mode 100644
index 0000000..b226dab
--- /dev/null
+++ b/src/org/osgi/framework/FrameworkEvent.java
@@ -0,0 +1,199 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/FrameworkEvent.java,v 1.9 2005/05/13 20:32:56 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2004, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.util.EventObject;
+
+/**
+ * A general Framework event.
+ * 
+ * <p>
+ * <code>FrameworkEvent</code> is the event class used when notifying listeners of
+ * general events occuring within the OSGI environment. A type code is used to
+ * identify the event type for future extendability.
+ * 
+ * <p>
+ * OSGi Alliance reserves the right to extend the set of event types.
+ * 
+ * @version $Revision: 1.9 $
+ */
+
+public class FrameworkEvent extends EventObject {
+	static final long		serialVersionUID	= 207051004521261705L;
+	/**
+	 * Bundle related to the event.
+	 */
+	private Bundle			bundle;
+
+	/**
+	 * Exception related to the event.
+	 */
+	private Throwable		throwable;
+
+	/**
+	 * Type of event.
+	 */
+	private int				type;
+
+	/**
+	 * The Framework has started.
+	 * 
+	 * <p>
+	 * This event is broadcast when the Framework has started after all
+	 * installed bundles that are marked to be started have been started and the
+	 * Framework has reached the intitial start level.
+	 * 
+	 * <p>
+	 * The value of <code>STARTED</code> is 0x00000001.
+	 * 
+	 * @see "<code>StartLevel</code>"
+	 */
+	public final static int	STARTED				= 0x00000001;
+
+	/**
+	 * An error has occurred.
+	 * 
+	 * <p>
+	 * There was an error associated with a bundle.
+	 * 
+	 * <p>
+	 * The value of <code>ERROR</code> is 0x00000002.
+	 */
+	public final static int	ERROR				= 0x00000002;
+
+	/**
+	 * A PackageAdmin.refreshPackage operation has completed.
+	 * 
+	 * <p>
+	 * This event is broadcast when the Framework has completed the refresh
+	 * packages operation initiated by a call to the
+	 * PackageAdmin.refreshPackages method.
+	 * 
+	 * <p>
+	 * The value of <code>PACKAGES_REFRESHED</code> is 0x00000004.
+	 * 
+	 * @since 1.2
+	 * @see "<code>PackageAdmin.refreshPackages</code>"
+	 */
+	public final static int	PACKAGES_REFRESHED	= 0x00000004;
+
+	/**
+	 * A StartLevel.setStartLevel operation has completed.
+	 * 
+	 * <p>
+	 * This event is broadcast when the Framework has completed changing the
+	 * active start level initiated by a call to the StartLevel.setStartLevel
+	 * method.
+	 * 
+	 * <p>
+	 * The value of <code>STARTLEVEL_CHANGED</code> is 0x00000008.
+	 * 
+	 * @since 1.2
+	 * @see "<code>StartLevel</code>"
+	 */
+	public final static int	STARTLEVEL_CHANGED	= 0x00000008;
+
+	/**
+	 * A warning has occurred.
+	 * 
+	 * <p>
+	 * There was a warning associated with a bundle.
+	 * 
+	 * <p>
+	 * The value of <code>WARNING</code> is 0x00000010.
+	 * 
+	 * @since 1.3
+	 */
+	public final static int	WARNING				= 0x00000010;
+
+	/**
+	 * An informational event has occurred.
+	 * 
+	 * <p>
+	 * There was an informational event associated with a bundle.
+	 * 
+	 * <p>
+	 * The value of <code>INFO</code> is 0x00000020.
+	 * 
+	 * @since 1.3
+	 */
+	public final static int	INFO				= 0x00000020;
+
+	/**
+	 * Creates a Framework event.
+	 * 
+	 * @param type The event type.
+	 * @param source The event source object. This may not be <code>null</code>.
+	 * @deprecated Since 1.2. This constructor is deprecated in favor of using
+	 *             the other constructor with the System Bundle as the event
+	 *             source.
+	 */
+	public FrameworkEvent(int type, Object source) {
+		super(source);
+		this.type = type;
+		this.bundle = null;
+		this.throwable = null;
+	}
+
+	/**
+	 * Creates a Framework event regarding the specified bundle.
+	 * 
+	 * @param type The event type.
+	 * @param bundle The event source.
+	 * @param throwable The related exception. This argument may be
+	 *        <code>null</code> if there is no related exception.
+	 */
+	public FrameworkEvent(int type, Bundle bundle, Throwable throwable) {
+		super(bundle);
+		this.type = type;
+		this.bundle = bundle;
+		this.throwable = throwable;
+	}
+
+	/**
+	 * Returns the exception related to this event.
+	 * 
+	 * @return The related exception or <code>null</code> if none.
+	 */
+	public Throwable getThrowable() {
+		return throwable;
+	}
+
+	/**
+	 * Returns the bundle associated with the event. This bundle is also the
+	 * source of the event.
+	 * 
+	 * @return The bundle associated with the event.
+	 */
+	public Bundle getBundle() {
+		return bundle;
+	}
+
+	/**
+	 * Returns the type of framework event.
+	 * <p>
+	 * The type values are:
+	 * <ul>
+	 * <li>{@link #STARTED}
+	 * <li>{@link #ERROR}
+	 * <li>{@link #WARNING}
+	 * <li>{@link #INFO}
+	 * <li>{@link #PACKAGES_REFRESHED}
+	 * <li>{@link #STARTLEVEL_CHANGED}
+	 * </ul>
+	 * 
+	 * @return The type of state change.
+	 */
+
+	public int getType() {
+		return type;
+	}
+}
diff --git a/src/org/osgi/framework/FrameworkListener.java b/src/org/osgi/framework/FrameworkListener.java
new file mode 100644
index 0000000..e97b4e4
--- /dev/null
+++ b/src/org/osgi/framework/FrameworkListener.java
@@ -0,0 +1,39 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/FrameworkListener.java,v 1.6 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.util.EventListener;
+
+/**
+ * A <code>FrameworkEvent</code> listener.
+ * 
+ * <p>
+ * <code>FrameworkListener</code> is a listener interface that may be implemented
+ * by a bundle developer. A <code>FrameworkListener</code> object is registered
+ * with the Framework using the {@link BundleContext#addFrameworkListener}
+ * method. <code>FrameworkListener</code> objects are called with a
+ * <code>FrameworkEvent</code> objects when the Framework starts and when
+ * asynchronous errors occur.
+ * 
+ * @version $Revision: 1.6 $
+ * @see FrameworkEvent
+ */
+
+public abstract interface FrameworkListener extends EventListener {
+
+	/**
+	 * Receives notification of a general <code>FrameworkEvent</code> object.
+	 * 
+	 * @param event The <code>FrameworkEvent</code> object.
+	 */
+	public abstract void frameworkEvent(FrameworkEvent event);
+}
+
diff --git a/src/org/osgi/framework/FrameworkUtil.java b/src/org/osgi/framework/FrameworkUtil.java
new file mode 100644
index 0000000..6a95479
--- /dev/null
+++ b/src/org/osgi/framework/FrameworkUtil.java
@@ -0,0 +1,48 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/FrameworkUtil.java,v 1.1 2005/07/14 20:32:46 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import org.apache.osgi.framework.FilterImpl;
+
+/**
+ * Framework Utility class.
+ * 
+ * <p>
+ * This class contains utility methods which access Framework functions that may
+ * be useful to bundles.
+ * 
+ * @version $Revision: 1.1 $
+ * @since 1.3
+ */
+public class FrameworkUtil {
+
+	/**
+	 * Creates a <code>Filter</code> object. This <code>Filter</code> object
+	 * may be used to match a <code>ServiceReference</code> object or a
+	 * <code>Dictionary</code> object.
+	 * 
+	 * <p>
+	 * If the filter cannot be parsed, an {@link InvalidSyntaxException} will be
+	 * thrown with a human readable message where the filter became unparsable.
+	 * 
+	 * @param filter The filter string.
+	 * @return A <code>Filter</code> object encapsulating the filter string.
+	 * @throws InvalidSyntaxException If <code>filter</code> contains an
+	 *            invalid filter string that cannot be parsed.
+	 * @throws NullPointerException If <code>filter</code> is null.
+	 * 
+	 * @see Filter
+	 */
+	public static Filter createFilter(String filter)
+			throws InvalidSyntaxException {
+		return new FilterImpl(filter);
+	}
+}
diff --git a/src/org/osgi/framework/InvalidSyntaxException.java b/src/org/osgi/framework/InvalidSyntaxException.java
new file mode 100644
index 0000000..8d1782d
--- /dev/null
+++ b/src/org/osgi/framework/InvalidSyntaxException.java
@@ -0,0 +1,107 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/InvalidSyntaxException.java,v 1.10 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+/**
+ * A Framework exception.
+ * 
+ * <p>
+ * An <code>InvalidSyntaxException</code> object indicates that a filter string
+ * parameter has an invalid syntax and cannot be parsed.
+ * 
+ * <p>
+ * See {@link Filter} for a description of the filter string syntax.
+ * 
+ * @version $Revision: 1.10 $
+ */
+
+public class InvalidSyntaxException extends Exception {
+	static final long	serialVersionUID	= -4295194420816491875L;
+	/**
+	 * The invalid filter string.
+	 */
+	private String		filter;
+	/**
+	 * Nested exception.
+	 */
+	private Throwable	cause;
+
+	/**
+	 * Creates an exception of type <code>InvalidSyntaxException</code>.
+	 * 
+	 * <p>
+	 * This method creates an <code>InvalidSyntaxException</code> object with the
+	 * specified message and the filter string which generated the exception.
+	 * 
+	 * @param msg The message.
+	 * @param filter The invalid filter string.
+	 */
+	public InvalidSyntaxException(String msg, String filter) {
+		super(msg);
+		this.filter = filter;
+		this.cause = null;
+	}
+
+	/**
+	 * Creates an exception of type <code>InvalidSyntaxException</code>.
+	 * 
+	 * <p>
+	 * This method creates an <code>InvalidSyntaxException</code> object with the
+	 * specified message and the filter string which generated the exception.
+	 * 
+	 * @param msg The message.
+	 * @param filter The invalid filter string.
+	 * @param cause The cause of this exception.
+	 * @since 1.3
+	 */
+	public InvalidSyntaxException(String msg, String filter, Throwable cause) {
+		super(msg);
+		this.filter = filter;
+		this.cause = cause;
+	}
+
+	/**
+	 * Returns the filter string that generated the
+	 * <code>InvalidSyntaxException</code> object.
+	 * 
+	 * @return The invalid filter string.
+	 * @see BundleContext#getServiceReferences
+	 * @see BundleContext#addServiceListener(ServiceListener,String)
+	 */
+	public String getFilter() {
+		return filter;
+	}
+
+	/**
+	 * Returns the cause of this exception or <code>null</code> if no cause was
+	 * specified when this exception was created.
+	 * 
+	 * @return The cause of this exception or <code>null</code> if no cause was
+	 *         specified.
+	 * @since 1.3
+	 */
+	public Throwable getCause() {
+		return cause;
+	}
+
+	/**
+	 * The cause of this exception can only be set when constructed.
+	 * 
+	 * @throws java.lang.IllegalStateException This method will always throw an
+	 *         <code>IllegalStateException</code> since the cause of this
+	 *         exception can only be set when constructed.
+	 * @since 1.3
+	 */
+	public Throwable initCause(Throwable cause) {
+		throw new IllegalStateException();
+	}
+}
+
diff --git a/src/org/osgi/framework/PackagePermission.java b/src/org/osgi/framework/PackagePermission.java
new file mode 100644
index 0000000..29d2980
--- /dev/null
+++ b/src/org/osgi/framework/PackagePermission.java
@@ -0,0 +1,534 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/PackagePermission.java,v 1.10 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.io.IOException;
+import java.security.*;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * A bundle's authority to import or export a package.
+ * 
+ * <p>
+ * A package is a dot-separated string that defines a fully qualified Java
+ * package.
+ * <p>
+ * For example:
+ * 
+ * <pre>
+ * <code>
+ * org.osgi.service.http
+ * </code>
+ * </pre>
+ * 
+ * <p>
+ * <code>PackagePermission</code> has two actions: <code>EXPORT</code> and
+ * <code>IMPORT</code>. The <code>EXPORT</code> action implies the <code>IMPORT</code>
+ * action.
+ * 
+ * @version $Revision: 1.10 $
+ */
+
+public final class PackagePermission extends BasicPermission {
+	static final long			serialVersionUID	= -5107705877071099135L;
+	/**
+	 * The action string <code>export</code>.
+	 */
+	public final static String	EXPORT				= "export";
+
+	/**
+	 * The action string <code>import</code>.
+	 */
+	public final static String	IMPORT				= "import";
+
+	private final static int	ACTION_EXPORT		= 0x00000001;
+	private final static int	ACTION_IMPORT		= 0x00000002;
+	private final static int	ACTION_ALL			= ACTION_EXPORT
+															| ACTION_IMPORT;
+	private final static int	ACTION_NONE			= 0;
+	private final static int	ACTION_ERROR		= 0x80000000;
+
+	/**
+	 * The actions mask.
+	 */
+	private transient int		action_mask			= ACTION_NONE;
+
+	/**
+	 * The actions in canonical form.
+	 * 
+	 * @serial
+	 */
+	private String				actions				= null;
+
+	/**
+	 * Defines the authority to import and/or export a package within the OSGi
+	 * environment.
+	 * <p>
+	 * The name is specified as a normal Java package name: a dot-separated
+	 * string. Wildcards may be used. For example:
+	 * 
+	 * <pre>
+	 * 
+	 *  org.osgi.service.http
+	 *  javax.servlet.*
+	 *  *
+	 *  
+	 * </pre>
+	 * 
+	 * <p>
+	 * Package Permissions are granted over all possible versions of a package.
+	 * 
+	 * A bundle that needs to export a package must have the appropriate
+	 * <code>PackagePermission</code> for that package; similarly, a bundle that
+	 * needs to import a package must have the appropriate
+	 * <code>PackagePermssion</code> for that package.
+	 * <p>
+	 * Permission is granted for both classes and resources.
+	 * 
+	 * @param name Package name.
+	 * @param actions <code>EXPORT</code>,<code>IMPORT</code> (canonical order).
+	 */
+
+	public PackagePermission(String name, String actions) {
+		this(name, getMask(actions));
+	}
+
+	/**
+	 * Package private constructor used by PackagePermissionCollection.
+	 * 
+	 * @param name class name
+	 * @param mask action mask
+	 */
+	PackagePermission(String name, int mask) {
+		super(name);
+		init(mask);
+	}
+
+	/**
+	 * Called by constructors and when deserialized.
+	 * 
+	 * @param mask action mask
+	 */
+	private void init(int mask) {
+		if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
+			throw new IllegalArgumentException("invalid action string");
+		}
+
+		action_mask = mask;
+	}
+
+	/**
+	 * Parse action string into action mask.
+	 * 
+	 * @param actions Action string.
+	 * @return action mask.
+	 */
+	private static int getMask(String actions) {
+		boolean seencomma = false;
+
+		int mask = ACTION_NONE;
+
+		if (actions == null) {
+			return (mask);
+		}
+
+		char[] a = actions.toCharArray();
+
+		int i = a.length - 1;
+		if (i < 0)
+			return (mask);
+
+		while (i != -1) {
+			char c;
+
+			// skip whitespace
+			while ((i != -1)
+					&& ((c = a[i]) == ' ' || c == '\r' || c == '\n'
+							|| c == '\f' || c == '\t'))
+				i--;
+
+			// check for the known strings
+			int matchlen;
+
+			if (i >= 5 && (a[i - 5] == 'i' || a[i - 5] == 'I')
+					&& (a[i - 4] == 'm' || a[i - 4] == 'M')
+					&& (a[i - 3] == 'p' || a[i - 3] == 'P')
+					&& (a[i - 2] == 'o' || a[i - 2] == 'O')
+					&& (a[i - 1] == 'r' || a[i - 1] == 'R')
+					&& (a[i] == 't' || a[i] == 'T')) {
+				matchlen = 6;
+				mask |= ACTION_IMPORT;
+
+			}
+			else
+				if (i >= 5 && (a[i - 5] == 'e' || a[i - 5] == 'E')
+						&& (a[i - 4] == 'x' || a[i - 4] == 'X')
+						&& (a[i - 3] == 'p' || a[i - 3] == 'P')
+						&& (a[i - 2] == 'o' || a[i - 2] == 'O')
+						&& (a[i - 1] == 'r' || a[i - 1] == 'R')
+						&& (a[i] == 't' || a[i] == 'T')) {
+					matchlen = 6;
+					mask |= ACTION_EXPORT | ACTION_IMPORT;
+
+				}
+				else {
+					// parse error
+					throw new IllegalArgumentException("invalid permission: "
+							+ actions);
+				}
+
+			// make sure we didn't just match the tail of a word
+			// like "ackbarfimport". Also, skip to the comma.
+			seencomma = false;
+			while (i >= matchlen && !seencomma) {
+				switch (a[i - matchlen]) {
+					case ',' :
+						seencomma = true;
+					/* FALLTHROUGH */
+					case ' ' :
+					case '\r' :
+					case '\n' :
+					case '\f' :
+					case '\t' :
+						break;
+					default :
+						throw new IllegalArgumentException(
+								"invalid permission: " + actions);
+				}
+				i--;
+			}
+
+			// point i at the location of the comma minus one (or -1).
+			i -= matchlen;
+		}
+
+		if (seencomma) {
+			throw new IllegalArgumentException("invalid permission: " + actions);
+		}
+
+		return (mask);
+	}
+
+	/**
+	 * Determines if the specified permission is implied by this object.
+	 * 
+	 * <p>
+	 * This method checks that the package name of the target is implied by the
+	 * package name of this object. The list of <code>PackagePermission</code>
+	 * actions must either match or allow for the list of the target object to
+	 * imply the target <code>PackagePermission</code> action.
+	 * <p>
+	 * The permission to export a package implies the permission to import the
+	 * named package.
+	 * 
+	 * <pre>
+	 *  x.y.*,&quot;export&quot; -&gt; x.y.z,&quot;export&quot; is true
+	 *  *,&quot;import&quot; -&gt; x.y, &quot;import&quot;      is true
+	 *  *,&quot;export&quot; -&gt; x.y, &quot;import&quot;      is true
+	 *  x.y,&quot;export&quot; -&gt; x.y.z, &quot;export&quot;  is false
+	 * </pre>
+	 * 
+	 * @param p The target permission to interrogate.
+	 * @return <code>true</code> if the specified <code>PackagePermission</code>
+	 *         action is implied by this object; <code>false</code> otherwise.
+	 */
+
+	public boolean implies(Permission p) {
+		if (p instanceof PackagePermission) {
+			PackagePermission target = (PackagePermission) p;
+
+			return (((action_mask & target.action_mask) == target.action_mask) && super
+					.implies(p));
+		}
+
+		return (false);
+	}
+
+	/**
+	 * Returns the canonical string representation of the
+	 * <code>PackagePermission</code> actions.
+	 * 
+	 * <p>
+	 * Always returns present <code>PackagePermission</code> actions in the
+	 * following order: <code>EXPORT</code>,<code>IMPORT</code>.
+	 * 
+	 * @return Canonical string representation of the <code>PackagePermission</code>
+	 *         actions.
+	 */
+
+	public String getActions() {
+		if (actions == null) {
+			StringBuffer sb = new StringBuffer();
+			boolean comma = false;
+
+			if ((action_mask & ACTION_EXPORT) == ACTION_EXPORT) {
+				sb.append(EXPORT);
+				comma = true;
+			}
+
+			if ((action_mask & ACTION_IMPORT) == ACTION_IMPORT) {
+				if (comma)
+					sb.append(',');
+				sb.append(IMPORT);
+			}
+
+			actions = sb.toString();
+		}
+
+		return (actions);
+	}
+
+	/**
+	 * Returns a new <code>PermissionCollection</code> object suitable for storing
+	 * <code>PackagePermission</code> objects.
+	 * 
+	 * @return A new <code>PermissionCollection</code> object.
+	 */
+	public PermissionCollection newPermissionCollection() {
+		return (new PackagePermissionCollection());
+	}
+
+	/**
+	 * Determines the equality of two <code>PackagePermission</code> objects.
+	 * 
+	 * This method checks that specified package has the same package name and
+	 * <code>PackagePermission</code> actions as this <code>PackagePermission</code>
+	 * object.
+	 * 
+	 * @param obj The object to test for equality with this
+	 *        <code>PackagePermission</code> object.
+	 * @return <code>true</code> if <code>obj</code> is a <code>PackagePermission</code>,
+	 *         and has the same package name and actions as this
+	 *         <code>PackagePermission</code> object; <code>false</code> otherwise.
+	 */
+	public boolean equals(Object obj) {
+		if (obj == this) {
+			return (true);
+		}
+
+		if (!(obj instanceof PackagePermission)) {
+			return (false);
+		}
+
+		PackagePermission p = (PackagePermission) obj;
+
+		return ((action_mask == p.action_mask) && getName().equals(p.getName()));
+	}
+
+	/**
+	 * Returns the hash code value for this object.
+	 * 
+	 * @return A hash code value for this object.
+	 */
+
+	public int hashCode() {
+		return (getName().hashCode() ^ getActions().hashCode());
+	}
+
+	/**
+	 * Returns the current action mask.
+	 * <p>
+	 * Used by the PackagePermissionCollection class.
+	 * 
+	 * @return Current action mask.
+	 */
+	int getMask() {
+		return (action_mask);
+	}
+
+	/**
+	 * WriteObject is called to save the state of this permission object to a
+	 * stream. The actions are serialized, and the superclass takes care of the
+	 * name.
+	 */
+
+	private synchronized void writeObject(java.io.ObjectOutputStream s)
+			throws IOException {
+		// Write out the actions. The superclass takes care of the name
+		// call getActions to make sure actions field is initialized
+		if (actions == null)
+			getActions();
+		s.defaultWriteObject();
+	}
+
+	/**
+	 * readObject is called to restore the state of this permission from a
+	 * stream.
+	 */
+	private synchronized void readObject(java.io.ObjectInputStream s)
+			throws IOException, ClassNotFoundException {
+		// Read in the action, then initialize the rest
+		s.defaultReadObject();
+		init(getMask(actions));
+	}
+}
+
+/**
+ * Stores a set of <code>PackagePermission</code> permissions.
+ * 
+ * @see java.security.Permission
+ * @see java.security.Permissions
+ * @see java.security.PermissionCollection
+ */
+
+final class PackagePermissionCollection extends PermissionCollection {
+	static final long	serialVersionUID	= -3350758995234427603L;
+	/**
+	 * Table of permissions.
+	 * 
+	 * @serial
+	 */
+	private Hashtable	permissions;
+
+	/**
+	 * Boolean saying if "*" is in the collection.
+	 * 
+	 * @serial
+	 */
+	private boolean		all_allowed;
+
+	/**
+	 * Create an empty PackagePermissions object.
+	 *  
+	 */
+
+	public PackagePermissionCollection() {
+		permissions = new Hashtable();
+		all_allowed = false;
+	}
+
+	/**
+	 * Adds a permission to the <code>PackagePermission</code> objects. The key
+	 * for the hash is the name.
+	 * 
+	 * @param permission The <code>PackagePermission</code> object to add.
+	 * 
+	 * @exception IllegalArgumentException If the permission is not a
+	 *            <code>PackagePermission</code> instance.
+	 * 
+	 * @exception SecurityException If this <code>PackagePermissionCollection</code>
+	 *            object has been marked read-only.
+	 */
+
+	public void add(Permission permission) {
+		if (!(permission instanceof PackagePermission))
+			throw new IllegalArgumentException("invalid permission: "
+					+ permission);
+		if (isReadOnly())
+			throw new SecurityException("attempt to add a Permission to a "
+					+ "readonly PermissionCollection");
+
+		PackagePermission pp = (PackagePermission) permission;
+		String name = pp.getName();
+
+		PackagePermission existing = (PackagePermission) permissions.get(name);
+
+		if (existing != null) {
+			int oldMask = existing.getMask();
+			int newMask = pp.getMask();
+			if (oldMask != newMask) {
+				permissions.put(name, new PackagePermission(name, oldMask
+						| newMask));
+
+			}
+		}
+		else {
+			permissions.put(name, permission);
+		}
+
+		if (!all_allowed) {
+			if (name.equals("*"))
+				all_allowed = true;
+		}
+	}
+
+	/**
+	 * Determines if the specified permissions implies the permissions expressed
+	 * in <code>permission</code>.
+	 * 
+	 * @param permission The Permission object to compare with this
+	 *        <code>PackagePermission</code> object.
+	 * 
+	 * @return <code>true</code> if <code>permission</code> is a proper subset of a
+	 *         permission in the set; <code>false</code> otherwise.
+	 */
+
+	public boolean implies(Permission permission) {
+		if (!(permission instanceof PackagePermission))
+			return (false);
+
+		PackagePermission pp = (PackagePermission) permission;
+		PackagePermission x;
+
+		int desired = pp.getMask();
+		int effective = 0;
+
+		// short circuit if the "*" Permission was added
+		if (all_allowed) {
+			x = (PackagePermission) permissions.get("*");
+			if (x != null) {
+				effective |= x.getMask();
+				if ((effective & desired) == desired)
+					return (true);
+			}
+		}
+
+		// strategy:
+		// Check for full match first. Then work our way up the
+		// name looking for matches on a.b.*
+
+		String name = pp.getName();
+
+		x = (PackagePermission) permissions.get(name);
+
+		if (x != null) {
+			// we have a direct hit!
+			effective |= x.getMask();
+			if ((effective & desired) == desired)
+				return (true);
+		}
+
+		// work our way up the tree...
+		int last, offset;
+
+		offset = name.length() - 1;
+
+		while ((last = name.lastIndexOf(".", offset)) != -1) {
+
+			name = name.substring(0, last + 1) + "*";
+			x = (PackagePermission) permissions.get(name);
+
+			if (x != null) {
+				effective |= x.getMask();
+				if ((effective & desired) == desired)
+					return (true);
+			}
+			offset = last - 1;
+		}
+
+		// we don't have to check for "*" as it was already checked
+		// at the top (all_allowed), so we just return false
+		return (false);
+	}
+
+	/**
+	 * Returns an enumeration of all <code>PackagePermission</code> objects in the
+	 * container.
+	 * 
+	 * @return Enumeration of all <code>PackagePermission</code> objects.
+	 */
+
+	public Enumeration elements() {
+		return (permissions.elements());
+	}
+}
+
diff --git a/src/org/osgi/framework/ServiceEvent.java b/src/org/osgi/framework/ServiceEvent.java
new file mode 100644
index 0000000..29d3650
--- /dev/null
+++ b/src/org/osgi/framework/ServiceEvent.java
@@ -0,0 +1,129 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/ServiceEvent.java,v 1.9 2005/05/13 20:32:56 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.util.Dictionary;
+import java.util.EventObject;
+
+/**
+ * A service lifecycle change event.
+ * <p>
+ * <code>ServiceEvent</code> objects are delivered to a <code>ServiceListener</code>
+ * objects when a change occurs in this service's lifecycle. A type code is used
+ * to identify the event type for future extendability.
+ * 
+ * <p>
+ * OSGi Alliance reserves the right to extend the set of types.
+ * 
+ * @version $Revision: 1.9 $
+ * @see ServiceListener
+ */
+
+public class ServiceEvent extends EventObject {
+	static final long			serialVersionUID	= 8792901483909409299L;
+	/**
+	 * Reference to the service that had a change occur in its lifecycle.
+	 */
+	private ServiceReference	reference;
+
+	/**
+	 * Type of service lifecycle change.
+	 */
+	private int					type;
+
+	/**
+	 * This service has been registered.
+	 * <p>
+	 * This event is synchronously delivered <strong>after </strong> the service
+	 * has been registered with the Framework.
+	 * 
+	 * <p>
+	 * The value of <code>REGISTERED</code> is 0x00000001.
+	 * 
+	 * @see BundleContext#registerService(String[],Object,Dictionary)
+	 */
+	public final static int		REGISTERED			= 0x00000001;
+
+	/**
+	 * The properties of a registered service have been modified.
+	 * <p>
+	 * This event is synchronously delivered <strong>after </strong> the service
+	 * properties have been modified.
+	 * 
+	 * <p>
+	 * The value of <code>MODIFIED</code> is 0x00000002.
+	 * 
+	 * @see ServiceRegistration#setProperties
+	 */
+	public final static int		MODIFIED			= 0x00000002;
+
+	/**
+	 * This service is in the process of being unregistered.
+	 * <p>
+	 * This event is synchronously delivered <strong>before </strong> the
+	 * service has completed unregistering.
+	 * 
+	 * <p>
+	 * If a bundle is using a service that is <code>UNREGISTERING</code>, the
+	 * bundle should release its use of the service when it receives this event.
+	 * If the bundle does not release its use of the service when it receives
+	 * this event, the Framework will automatically release the bundle's use of
+	 * the service while completing the service unregistration operation.
+	 * 
+	 * <p>
+	 * The value of UNREGISTERING is 0x00000004.
+	 * 
+	 * @see ServiceRegistration#unregister
+	 * @see BundleContext#ungetService
+	 */
+	public final static int		UNREGISTERING		= 0x00000004;
+
+	/**
+	 * Creates a new service event object.
+	 * 
+	 * @param type The event type.
+	 * @param reference A <code>ServiceReference</code> object to the service that
+	 *        had a lifecycle change.
+	 */
+	public ServiceEvent(int type, ServiceReference reference) {
+		super(reference);
+		this.reference = reference;
+		this.type = type;
+	}
+
+	/**
+	 * Returns a reference to the service that had a change occur in its
+	 * lifecycle.
+	 * <p>
+	 * This reference is the source of the event.
+	 * 
+	 * @return Reference to the service that had a lifecycle change.
+	 */
+	public ServiceReference getServiceReference() {
+		return (reference);
+	}
+
+	/**
+	 * Returns the type of event. The event type values are:
+	 * <ul>
+	 * <li>{@link #REGISTERED}
+	 * <li>{@link #MODIFIED}
+	 * <li>{@link #UNREGISTERING}
+	 * </ul>
+	 * 
+	 * @return Type of service lifecycle change.
+	 */
+
+	public int getType() {
+		return (type);
+	}
+}
+
diff --git a/src/org/osgi/framework/ServiceFactory.java b/src/org/osgi/framework/ServiceFactory.java
new file mode 100644
index 0000000..04041c3
--- /dev/null
+++ b/src/org/osgi/framework/ServiceFactory.java
@@ -0,0 +1,89 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/ServiceFactory.java,v 1.6 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+/**
+ * Allows services to provide customized service objects in the OSGi
+ * environment.
+ * 
+ * <p>
+ * When registering a service, a <code>ServiceFactory</code> object can be used
+ * instead of a service object, so that the bundle developer can gain control of
+ * the specific service object granted to a bundle that is using the service.
+ * 
+ * <p>
+ * When this happens, the <code>BundleContext.getService(ServiceReference)</code>
+ * method calls the <code>ServiceFactory.getService</code> method to create a
+ * service object specifically for the requesting bundle. The service object
+ * returned by the <code>ServiceFactory</code> object is cached by the Framework
+ * until the bundle releases its use of the service.
+ * 
+ * <p>
+ * When the bundle's use count for the service equals zero (including the bundle
+ * stopping or the service being unregistered), the
+ * <code>ServiceFactory.ungetService</code> method is called.
+ * 
+ * <p>
+ * <code>ServiceFactory</code> objects are only used by the Framework and are not
+ * made available to other bundles in the OSGi environment.
+ * 
+ * @version $Revision: 1.6 $
+ * @see BundleContext#getService
+ */
+
+public abstract interface ServiceFactory {
+	/**
+	 * Creates a new service object.
+	 * 
+	 * <p>
+	 * The Framework invokes this method the first time the specified
+	 * <code>bundle</code> requests a service object using the
+	 * <code>BundleContext.getService(ServiceReference)</code> method. The service
+	 * factory can then return a specific service object for each bundle.
+	 * 
+	 * <p>
+	 * The Framework caches the value returned (unless it is <code>null</code>),
+	 * and will return the same service object on any future call to
+	 * <code>BundleContext.getService</code> from the same bundle.
+	 * 
+	 * <p>
+	 * The Framework will check if the returned service object is an instance of
+	 * all the classes named when the service was registered. If not, then
+	 * <code>null</code> is returned to the bundle.
+	 * 
+	 * @param bundle The bundle using the service.
+	 * @param registration The <code>ServiceRegistration</code> object for the
+	 *        service.
+	 * @return A service object that <strong>must </strong> be an instance of
+	 *         all the classes named when the service was registered.
+	 * @see BundleContext#getService
+	 */
+	public abstract Object getService(Bundle bundle,
+			ServiceRegistration registration);
+
+	/**
+	 * Releases a service object.
+	 * 
+	 * <p>
+	 * The Framework invokes this method when a service has been released by a
+	 * bundle. The service object may then be destroyed.
+	 * 
+	 * @param bundle The bundle releasing the service.
+	 * @param registration The <code>ServiceRegistration</code> object for the
+	 *        service.
+	 * @param service The service object returned by a previous call to the
+	 *        <code>ServiceFactory.getService</code> method.
+	 * @see BundleContext#ungetService
+	 */
+	public abstract void ungetService(Bundle bundle,
+			ServiceRegistration registration, Object service);
+}
+
diff --git a/src/org/osgi/framework/ServiceListener.java b/src/org/osgi/framework/ServiceListener.java
new file mode 100644
index 0000000..699c888
--- /dev/null
+++ b/src/org/osgi/framework/ServiceListener.java
@@ -0,0 +1,51 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/ServiceListener.java,v 1.8 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.util.EventListener;
+
+/**
+ * A <code>ServiceEvent</code> listener.
+ *
+ * <p><code>ServiceListener</code> is a listener interface that may be implemented by a bundle
+ * developer.
+ * <p>A <code>ServiceListener</code> object is registered with the Framework using the
+ * <code>BundleContext.addServiceListener</code> method.
+ * <code>ServiceListener</code> objects are called with a <code>ServiceEvent</code> object when
+ * a service is registered, modified, or is in the process of unregistering.
+ *
+ * <p><code>ServiceEvent</code> object delivery to <code>ServiceListener</code> objects is filtered by the
+ * filter specified when the listener was registered. If the Java Runtime Environment
+ * supports permissions, then additional filtering is done.
+ * <code>ServiceEvent</code> objects are only delivered to the listener if the bundle which defines
+ * the listener object's class has the appropriate <code>ServicePermission</code> to get the service
+ * using at least one of the named classes the service was registered under.
+ *
+ * <p><code>ServiceEvent</code> object delivery to <code>ServiceListener</code> objects is
+ * further filtered according to package sources as defined in
+ * {@link ServiceReference#isAssignableTo(Bundle, String)}.
+ * 
+ * @version $Revision: 1.8 $
+ * @see ServiceEvent
+ * @see ServicePermission
+ */
+
+public abstract interface ServiceListener extends EventListener
+{
+    /**
+     * Receives notification that a service has had a lifecycle change.
+     *
+     * @param event The <code>ServiceEvent</code> object.
+     */
+    public abstract void serviceChanged(ServiceEvent event);
+}
+
+
diff --git a/src/org/osgi/framework/ServicePermission.java b/src/org/osgi/framework/ServicePermission.java
new file mode 100644
index 0000000..49242ea
--- /dev/null
+++ b/src/org/osgi/framework/ServicePermission.java
@@ -0,0 +1,502 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/ServicePermission.java,v 1.10 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.io.IOException;
+import java.security.*;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * Indicates a bundle's authority to register or get a service.
+ * <ul>
+ * <li>The <code>ServicePermission.REGISTER</code> action allows a bundle to
+ * register a service on the specified names.
+ * <li>The <code>ServicePermission.GET</code> action allows a bundle to detect a
+ * service and get it.
+ * </ul>
+ * Permission to get a service is required in order to detect events regarding
+ * the service. Untrusted bundles should not be able to detect the presence of
+ * certain services unless they have the appropriate <code>ServicePermission</code>
+ * to get the specific service.
+ * 
+ * @version $Revision: 1.10 $
+ */
+
+final public class ServicePermission extends BasicPermission {
+	static final long			serialVersionUID	= -7662148639076511574L;
+	/**
+	 * The action string <code>get</code> (Value is "get").
+	 */
+	public final static String	GET					= "get";
+	/**
+	 * The action string <code>register</code> (Value is "register").
+	 */
+	public final static String	REGISTER			= "register";
+
+	private final static int	ACTION_GET			= 0x00000001;
+	private final static int	ACTION_REGISTER		= 0x00000002;
+	private final static int	ACTION_ALL			= ACTION_GET
+															| ACTION_REGISTER;
+	private final static int	ACTION_NONE			= 0;
+	private final static int	ACTION_ERROR		= 0x80000000;
+
+	/**
+	 * The actions mask.
+	 */
+	private transient int		action_mask			= ACTION_NONE;
+
+	/**
+	 * The actions in canonical form.
+	 * 
+	 * @serial
+	 */
+	private String				actions				= null;
+
+	/**
+	 * Create a new ServicePermission.
+	 * 
+	 * <p>
+	 * The name of the service is specified as a fully qualified class name.
+	 * 
+	 * <pre>
+	 * 
+	 *  ClassName ::= &lt;class name&gt; | &lt;class name ending in &quot;.*&quot;&gt;
+	 *  
+	 * </pre>
+	 * 
+	 * Examples:
+	 * 
+	 * <pre>
+	 *     org.osgi.service.http.HttpService
+	 *     org.osgi.service.http.*
+	 *     org.osgi.service.snmp.*
+	 * </pre>
+	 * 
+	 * <p>
+	 * There are two possible actions: <code>get</code> and <code>register</code>.
+	 * The <code>get</code> permission allows the owner of this permission to
+	 * obtain a service with this name. The <code>register</code> permission
+	 * allows the bundle to register a service under that name.
+	 * 
+	 * @param name class name
+	 * @param actions <code>get</code>,<code>register</code> (canonical order)
+	 */
+
+	public ServicePermission(String name, String actions) {
+		this(name, getMask(actions));
+	}
+
+	/**
+	 * Package private constructor used by ServicePermissionCollection.
+	 * 
+	 * @param name class name
+	 * @param mask action mask
+	 */
+	ServicePermission(String name, int mask) {
+		super(name);
+
+		init(mask);
+	}
+
+	/**
+	 * Called by constructors and when deserialized.
+	 * 
+	 * @param mask action mask
+	 */
+	private void init(int mask) {
+		if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
+			throw new IllegalArgumentException("invalid action string");
+		}
+
+		action_mask = mask;
+	}
+
+	/**
+	 * Parse action string into action mask.
+	 * 
+	 * @param actions Action string.
+	 * @return action mask.
+	 */
+	private static int getMask(String actions) {
+		boolean seencomma = false;
+
+		int mask = ACTION_NONE;
+
+		if (actions == null) {
+			return mask;
+		}
+
+		char[] a = actions.toCharArray();
+
+		int i = a.length - 1;
+		if (i < 0)
+			return mask;
+
+		while (i != -1) {
+			char c;
+
+			// skip whitespace
+			while ((i != -1)
+					&& ((c = a[i]) == ' ' || c == '\r' || c == '\n'
+							|| c == '\f' || c == '\t'))
+				i--;
+
+			// check for the known strings
+			int matchlen;
+
+			if (i >= 2 && (a[i - 2] == 'g' || a[i - 2] == 'G')
+					&& (a[i - 1] == 'e' || a[i - 1] == 'E')
+					&& (a[i] == 't' || a[i] == 'T')) {
+				matchlen = 3;
+				mask |= ACTION_GET;
+
+			}
+			else
+				if (i >= 7 && (a[i - 7] == 'r' || a[i - 7] == 'R')
+						&& (a[i - 6] == 'e' || a[i - 6] == 'E')
+						&& (a[i - 5] == 'g' || a[i - 5] == 'G')
+						&& (a[i - 4] == 'i' || a[i - 4] == 'I')
+						&& (a[i - 3] == 's' || a[i - 3] == 'S')
+						&& (a[i - 2] == 't' || a[i - 2] == 'T')
+						&& (a[i - 1] == 'e' || a[i - 1] == 'E')
+						&& (a[i] == 'r' || a[i] == 'R')) {
+					matchlen = 8;
+					mask |= ACTION_REGISTER;
+
+				}
+				else {
+					// parse error
+					throw new IllegalArgumentException("invalid permission: "
+							+ actions);
+				}
+
+			// make sure we didn't just match the tail of a word
+			// like "ackbarfregister". Also, skip to the comma.
+			seencomma = false;
+			while (i >= matchlen && !seencomma) {
+				switch (a[i - matchlen]) {
+					case ',' :
+						seencomma = true;
+					/* FALLTHROUGH */
+					case ' ' :
+					case '\r' :
+					case '\n' :
+					case '\f' :
+					case '\t' :
+						break;
+					default :
+						throw new IllegalArgumentException(
+								"invalid permission: " + actions);
+				}
+				i--;
+			}
+
+			// point i at the location of the comma minus one (or -1).
+			i -= matchlen;
+		}
+
+		if (seencomma) {
+			throw new IllegalArgumentException("invalid permission: " + actions);
+		}
+
+		return mask;
+	}
+
+	/**
+	 * Determines if a <code>ServicePermission</code> object "implies" the
+	 * specified permission.
+	 * 
+	 * @param p The target permission to check.
+	 * @return <code>true</code> if the specified permission is implied by this
+	 *         object; <code>false</code> otherwise.
+	 */
+
+	public boolean implies(Permission p) {
+		if (p instanceof ServicePermission) {
+			ServicePermission target = (ServicePermission) p;
+
+			return (((action_mask & target.action_mask) == target.action_mask) && super
+					.implies(p));
+		}
+
+		return (false);
+	}
+
+	/**
+	 * Returns the canonical string representation of the actions. Always
+	 * returns present actions in the following order: <code>get</code>,
+	 * <code>register</code>.
+	 * 
+	 * @return The canonical string representation of the actions.
+	 */
+	public String getActions() {
+		if (actions == null) {
+			StringBuffer sb = new StringBuffer();
+			boolean comma = false;
+
+			if ((action_mask & ACTION_GET) == ACTION_GET) {
+				sb.append(GET);
+				comma = true;
+			}
+
+			if ((action_mask & ACTION_REGISTER) == ACTION_REGISTER) {
+				if (comma)
+					sb.append(',');
+				sb.append(REGISTER);
+			}
+
+			actions = sb.toString();
+		}
+
+		return (actions);
+	}
+
+	/**
+	 * Returns a new <code>PermissionCollection</code> object for storing
+	 * <code>ServicePermission<code> objects.
+	 *
+	 * @return A new <code>PermissionCollection</code> object suitable for storing
+	 * <code>ServicePermission</code> objects.
+	 */
+	public PermissionCollection newPermissionCollection() {
+		return (new ServicePermissionCollection());
+	}
+
+	/**
+	 * Determines the equalty of two ServicePermission objects.
+	 * 
+	 * Checks that specified object has the same class name and action as this
+	 * <code>ServicePermission</code>.
+	 * 
+	 * @param obj The object to test for equality.
+	 * @return true if obj is a <code>ServicePermission</code>, and has the same
+	 *         class name and actions as this <code>ServicePermission</code>
+	 *         object; <code>false</code> otherwise.
+	 */
+	public boolean equals(Object obj) {
+		if (obj == this) {
+			return (true);
+		}
+
+		if (!(obj instanceof ServicePermission)) {
+			return (false);
+		}
+
+		ServicePermission p = (ServicePermission) obj;
+
+		return ((action_mask == p.action_mask) && getName().equals(p.getName()));
+	}
+
+	/**
+	 * Returns the hash code value for this object.
+	 * 
+	 * @return Hash code value for this object.
+	 */
+
+	public int hashCode() {
+		return (getName().hashCode() ^ getActions().hashCode());
+	}
+
+	/**
+	 * Returns the current action mask. Used by the ServicePermissionCollection
+	 * object.
+	 * 
+	 * @return The actions mask.
+	 */
+	int getMask() {
+		return (action_mask);
+	}
+
+	/**
+	 * WriteObject is called to save the state of this permission to a stream.
+	 * The actions are serialized, and the superclass takes care of the name.
+	 */
+
+	private synchronized void writeObject(java.io.ObjectOutputStream s)
+			throws IOException {
+		// Write out the actions. The superclass takes care of the name
+		// call getActions to make sure actions field is initialized
+		if (actions == null)
+			getActions();
+		s.defaultWriteObject();
+	}
+
+	/**
+	 * readObject is called to restore the state of this permission from a
+	 * stream.
+	 */
+	private synchronized void readObject(java.io.ObjectInputStream s)
+			throws IOException, ClassNotFoundException {
+		// Read in the action, then initialize the rest
+		s.defaultReadObject();
+		init(getMask(actions));
+	}
+}
+
+/**
+ * Stores a set of ServicePermission permissions.
+ * 
+ * @see java.security.Permission
+ * @see java.security.Permissions
+ * @see java.security.PermissionCollection
+ */
+
+final class ServicePermissionCollection extends PermissionCollection {
+	static final long	serialVersionUID	= 662615640374640621L;
+	/**
+	 * Table of permissions.
+	 * 
+	 * @serial
+	 */
+	private Hashtable	permissions;
+
+	/**
+	 * Boolean saying if "*" is in the collection.
+	 * 
+	 * @serial
+	 */
+	private boolean		all_allowed;
+
+	/**
+	 * Creates an empty ServicePermissions object.
+	 *  
+	 */
+
+	public ServicePermissionCollection() {
+		permissions = new Hashtable();
+		all_allowed = false;
+	}
+
+	/**
+	 * Adds a permission to the <code>ServicePermission</code> objects using the
+	 * key for the hash as the name.
+	 * 
+	 * @param permission The Permission object to add.
+	 * 
+	 * @exception IllegalArgumentException If the permission is not a
+	 *            ServicePermission object.
+	 * 
+	 * @exception SecurityException If this <code>ServicePermissionCollection</code>
+	 *            object has been marked read-only.
+	 */
+
+	public void add(Permission permission) {
+		if (!(permission instanceof ServicePermission))
+			throw new IllegalArgumentException("invalid permission: "
+					+ permission);
+		if (isReadOnly())
+			throw new SecurityException("attempt to add a Permission to a "
+					+ "readonly PermissionCollection");
+
+		ServicePermission sp = (ServicePermission) permission;
+		String name = sp.getName();
+
+		ServicePermission existing = (ServicePermission) permissions.get(name);
+
+		if (existing != null) {
+			int oldMask = existing.getMask();
+			int newMask = sp.getMask();
+			if (oldMask != newMask) {
+				permissions.put(name, new ServicePermission(name, oldMask
+						| newMask));
+			}
+		}
+		else {
+			permissions.put(name, permission);
+		}
+
+		if (!all_allowed) {
+			if (name.equals("*"))
+				all_allowed = true;
+		}
+	}
+
+	/**
+	 * Determines if a set of permissions implies the permissions expressed in
+	 * <code>permission</code>.
+	 * 
+	 * @param permission The Permission object to compare.
+	 * 
+	 * @return <code>true</code> if <code>permission</code> is a proper subset of a
+	 *         permission in the set; <code>false</code> otherwise.
+	 */
+
+	public boolean implies(Permission permission) {
+		if (!(permission instanceof ServicePermission))
+			return (false);
+
+		ServicePermission sp = (ServicePermission) permission;
+		ServicePermission x;
+
+		int desired = sp.getMask();
+		int effective = 0;
+
+		// short circuit if the "*" Permission was added
+		if (all_allowed) {
+			x = (ServicePermission) permissions.get("*");
+			if (x != null) {
+				effective |= x.getMask();
+				if ((effective & desired) == desired)
+					return (true);
+			}
+		}
+
+		// strategy:
+		// Check for full match first. Then work our way up the
+		// name looking for matches on a.b.*
+
+		String name = sp.getName();
+
+		x = (ServicePermission) permissions.get(name);
+
+		if (x != null) {
+			// we have a direct hit!
+			effective |= x.getMask();
+			if ((effective & desired) == desired)
+				return (true);
+		}
+
+		// work our way up the tree...
+		int last, offset;
+
+		offset = name.length() - 1;
+
+		while ((last = name.lastIndexOf(".", offset)) != -1) {
+
+			name = name.substring(0, last + 1) + "*";
+			x = (ServicePermission) permissions.get(name);
+
+			if (x != null) {
+				effective |= x.getMask();
+				if ((effective & desired) == desired)
+					return (true);
+			}
+			offset = last - 1;
+		}
+
+		// we don't have to check for "*" as it was already checked
+		// at the top (all_allowed), so we just return false
+		return (false);
+	}
+
+	/**
+	 * Returns an enumeration of all the <code>ServicePermission</code> objects in
+	 * the container.
+	 * 
+	 * @return Enumeration of all the ServicePermission objects.
+	 */
+
+	public Enumeration elements() {
+		return (permissions.elements());
+	}
+}
+
diff --git a/src/org/osgi/framework/ServiceReference.java b/src/org/osgi/framework/ServiceReference.java
new file mode 100644
index 0000000..87b16e5
--- /dev/null
+++ b/src/org/osgi/framework/ServiceReference.java
@@ -0,0 +1,146 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/ServiceReference.java,v 1.11 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.util.Dictionary;
+
+/**
+ * A reference to a service.
+ * 
+ * <p>
+ * The Framework returns <code>ServiceReference</code> objects from the
+ * <code>BundleContext.getServiceReference</code> and
+ * <code>BundleContext.getServiceReferences</code> methods.
+ * <p>
+ * A <code>ServiceReference</code> object may be shared between bundles and can be
+ * used to examine the properties of the service and to get the service object.
+ * <p>
+ * Every service registered in the Framework has a unique
+ * <code>ServiceRegistration</code> object and may have multiple, distinct
+ * <code>ServiceReference</code> objects referring to it.
+ * <code>ServiceReference</code> objects associated with a
+ * <code>ServiceRegistration</code> object have the same <code>hashCode</code>
+ * and are considered equal (more specifically, their <code>equals()</code>
+ * method will return <code>true</code> when compared).
+ * <p>
+ * If the same service object is registered multiple times,
+ * <code>ServiceReference</code> objects associated with different
+ * <code>ServiceRegistration</code> objects are not equal.
+ * 
+ * @version $Revision: 1.11 $
+ * @see BundleContext#getServiceReference
+ * @see BundleContext#getServiceReferences
+ * @see BundleContext#getService
+ */
+
+public abstract interface ServiceReference {
+	/**
+	 * Returns the property value to which the specified property key is mapped
+	 * in the properties <code>Dictionary</code> object of the service
+	 * referenced by this <code>ServiceReference</code> object.
+	 * 
+	 * <p>
+	 * Property keys are case-insensitive.
+	 * 
+	 * <p>
+	 * This method must continue to return property values after the service has
+	 * been unregistered. This is so references to unregistered services (for
+	 * example, <code>ServiceReference</code> objects stored in the log) can
+	 * still be interrogated.
+	 * 
+	 * @param key The property key.
+	 * @return The property value to which the key is mapped; <code>null</code>
+	 *         if there is no property named after the key.
+	 */
+	public abstract Object getProperty(String key);
+
+	/**
+	 * Returns an array of the keys in the properties <code>Dictionary</code>
+	 * object of the service referenced by this <code>ServiceReference</code>
+	 * object.
+	 * 
+	 * <p>
+	 * This method will continue to return the keys after the service has been
+	 * unregistered. This is so references to unregistered services (for
+	 * example, <code>ServiceReference</code> objects stored in the log) can
+	 * still be interrogated.
+	 * 
+	 * <p>
+	 * This method is <i>case-preserving </i>; this means that every key in the
+	 * returned array must have the same case as the corresponding key in the
+	 * properties <code>Dictionary</code> that was passed to the
+	 * {@link BundleContext#registerService(String[],Object,Dictionary)}or
+	 * {@link ServiceRegistration#setProperties}methods.
+	 * 
+	 * @return An array of property keys.
+	 */
+	public abstract String[] getPropertyKeys();
+
+	/**
+	 * Returns the bundle that registered the service referenced by this
+	 * <code>ServiceReference</code> object.
+	 * 
+	 * <p>
+	 * This method must return <code>null</code> when the service has
+	 * been unregistered. This can be used to determine if the service has been
+	 * unregistered.
+	 * 
+	 * @return The bundle that registered the service referenced by this
+	 *         <code>ServiceReference</code> object; <code>null</code> if
+	 *         that service has already been unregistered.
+	 * @see BundleContext#registerService(String[],Object,Dictionary)
+	 */
+	public abstract Bundle getBundle();
+
+	/**
+	 * Returns the bundles that are using the service referenced by this
+	 * <code>ServiceReference</code> object. Specifically, this method returns
+	 * the bundles whose usage count for that service is greater than zero.
+	 * 
+	 * @return An array of bundles whose usage count for the service referenced
+	 *         by this <code>ServiceReference</code> object is greater than
+	 *         zero; <code>null</code> if no bundles are currently using that
+	 *         service.
+	 * 
+	 * @since 1.1
+	 */
+	public abstract Bundle[] getUsingBundles();
+
+	/**
+	 * Tests if the bundle that registered the service referenced by this
+	 * <code>ServiceReference</code> and the specified bundle use the same source
+	 * for the package of the specified class name.
+	 * <p>
+	 * This method performs the following checks:
+	 * <ol>
+	 * <li>Get the package name from the specified class name.</li>
+	 * <li>For the bundle that registered the service referenced by this
+	 * <code>ServiceReference</code> (registrant bundle); find the source for the
+	 * package. If no source is found then return <code>true</code> if the
+	 * registrant bundle is equal to the specified bundle; otherwise return
+	 * <code>false</code>.</li>
+	 * <li>If the package source of the registrant bundle is equal to the
+	 * package source of the specified bundle then return <code>true</code>;
+	 * otherwise return <code>false</code>.</li>
+	 * </ol>
+	 * 
+	 * @param bundle The <code>Bundle</code> object to check.
+	 * @param className The class name to check.
+	 * @return <code>true</code> if the bundle which registered the service
+	 *         referenced by this <code>ServiceReference</code> and the specified
+	 *         bundle use the same source for the package of the specified class
+	 *         name. Otherwise <code>false</code> is returned.
+	 * 
+	 * @since 1.3
+	 */
+	public abstract boolean isAssignableTo(Bundle bundle, String className);
+
+}
diff --git a/src/org/osgi/framework/ServiceRegistration.java b/src/org/osgi/framework/ServiceRegistration.java
new file mode 100644
index 0000000..5b4f026
--- /dev/null
+++ b/src/org/osgi/framework/ServiceRegistration.java
@@ -0,0 +1,105 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/ServiceRegistration.java,v 1.8 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.util.Dictionary;
+
+/**
+ * A registered service.
+ * 
+ * <p>
+ * The Framework returns a <code>ServiceRegistration</code> object when a
+ * <code>BundleContext.registerService</code> method invocation is successful.
+ * The <code>ServiceRegistration</code> object is for the private use of the
+ * registering bundle and should not be shared with other bundles.
+ * <p>
+ * The <code>ServiceRegistration</code> object may be used to update the
+ * properties of the service or to unregister the service.
+ * 
+ * @version $Revision: 1.8 $
+ * @see BundleContext#registerService(String[],Object,Dictionary)
+ */
+
+public abstract interface ServiceRegistration {
+	/**
+	 * Returns a <code>ServiceReference</code> object for a service being
+	 * registered.
+	 * <p>
+	 * The <code>ServiceReference</code> object may be shared with other bundles.
+	 * 
+	 * @exception java.lang.IllegalStateException If this
+	 *            <code>ServiceRegistration</code> object has already been
+	 *            unregistered.
+	 * @return <code>ServiceReference</code> object.
+	 */
+	public abstract ServiceReference getReference();
+
+	/**
+	 * Updates the properties associated with a service.
+	 * 
+	 * <p>
+	 * The {@link Constants#OBJECTCLASS} and {@link Constants#SERVICE_ID} keys
+	 * cannot be modified by this method. These values are set by the Framework
+	 * when the service is registered in the OSGi environment.
+	 * 
+	 * <p>
+	 * The following steps are required to modify service properties:
+	 * <ol>
+	 * <li>The service's properties are replaced with the provided properties.
+	 * <li>A service event of type {@link ServiceEvent#MODIFIED} is
+	 * synchronously sent.
+	 * </ol>
+	 * 
+	 * @param properties The properties for this service. See {@link Constants}
+	 *        for a list of standard service property keys. Changes should not
+	 *        be made to this object after calling this method. To update the
+	 *        service's properties this method should be called again.
+	 * 
+	 * @exception IllegalStateException If this <code>ServiceRegistration</code>
+	 *            object has already been unregistered.
+	 * 
+	 * @exception IllegalArgumentException If <code>properties</code> contains
+	 *            case variants of the same key name.
+	 */
+	public abstract void setProperties(Dictionary properties);
+
+	/**
+	 * Unregisters a service. Remove a <code>ServiceRegistration</code> object
+	 * from the Framework service registry. All <code>ServiceReference</code>
+	 * objects associated with this <code>ServiceRegistration</code> object can no
+	 * longer be used to interact with the service.
+	 * 
+	 * <p>
+	 * The following steps are required to unregister a service:
+	 * <ol>
+	 * <li>The service is removed from the Framework service registry so that
+	 * it can no longer be used. <code>ServiceReference</code> objects for the
+	 * service may no longer be used to get a service object for the service.
+	 * <li>A service event of type {@link ServiceEvent#UNREGISTERING} is
+	 * synchronously sent so that bundles using this service can release their
+	 * use of it.
+	 * <li>For each bundle whose use count for this service is greater than
+	 * zero: <br>
+	 * The bundle's use count for this service is set to zero. <br>
+	 * If the service was registered with a {@link ServiceFactory} object, the
+	 * <code>ServiceFactory.ungetService</code> method is called to release the
+	 * service object for the bundle.
+	 * </ol>
+	 * 
+	 * @exception java.lang.IllegalStateException If this
+	 *            <code>ServiceRegistration</code> object has already been
+	 *            unregistered.
+	 * @see BundleContext#ungetService
+	 * @see ServiceFactory#ungetService
+	 */
+	public abstract void unregister();
+}
+
diff --git a/src/org/osgi/framework/SynchronousBundleListener.java b/src/org/osgi/framework/SynchronousBundleListener.java
new file mode 100644
index 0000000..edbe0b3
--- /dev/null
+++ b/src/org/osgi/framework/SynchronousBundleListener.java
@@ -0,0 +1,43 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/SynchronousBundleListener.java,v 1.8 2005/05/13 20:32:54 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2001, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+/**
+ * A synchronous <code>BundleEvent</code> listener.
+ * 
+ * <p>
+ * <code>SynchronousBundleListener</code> is a listener interface that may be
+ * implemented by a bundle developer.
+ * <p>
+ * A <code>SynchronousBundleListener</code> object is registered with the
+ * Framework using the {@link BundleContext#addBundleListener} method.
+ * <code>SynchronousBundleListener</code> objects are called with a
+ * <code>BundleEvent</code> object when a bundle has been installed,
+ * resolved, started, stopped, updated, unresolved, or uninstalled.
+ * <p>
+ * Unlike normal <code>BundleListener</code> objects,
+ * <code>SynchronousBundleListener</code>s are synchronously called during bundle
+ * lifecycle processing. The bundle lifecycle processing will not proceed
+ * until all <code>SynchronousBundleListener</code>s have completed.
+ * <code>SynchronousBundleListener</code> objects will be called prior to
+ * <code>BundleListener</code> objects.
+ * <p>
+ * <code>AdminPermission</code> is required to add or remove a
+ * <code>SynchronousBundleListener</code> object.
+ * 
+ * @version $Revision: 1.8 $
+ * @since 1.1
+ * @see BundleEvent
+ */
+
+public abstract interface SynchronousBundleListener extends BundleListener {
+}
+
diff --git a/src/org/osgi/framework/Version.java b/src/org/osgi/framework/Version.java
new file mode 100644
index 0000000..93e3173
--- /dev/null
+++ b/src/org/osgi/framework/Version.java
@@ -0,0 +1,344 @@
+/*
+ * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/Version.java,v 1.13 2005/05/13 20:32:55 hargrave Exp $
+ * 
+ * Copyright (c) OSGi Alliance (2004, 2005). All Rights Reserved.
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this 
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
+ */
+
+package org.osgi.framework;
+
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+/**
+ * Version identifier for bundles and packages.
+ * 
+ * <p>
+ * Version identifiers have four components.
+ * <ol>
+ * <li>Major version. A non-negative integer.</li>
+ * <li>Minor version. A non-negative integer.</li>
+ * <li>Micro version. A non-negative integer.</li>
+ * <li>Qualifier. A text string. See <code>Version(String)</code> for the
+ * format of the qualifier string.</li>
+ * </ol>
+ * 
+ * <p>
+ * <code>Version</code> objects are immutable.
+ * 
+ * @version $Revision: 1.13 $
+ * @since 1.3
+ */
+
+public class Version implements Comparable {
+	private final int			major;
+	private final int			minor;
+	private final int			micro;
+	private final String		qualifier;
+	private static final String	SEPARATOR		= ".";					//$NON-NLS-1$
+
+	/**
+	 * The empty version "0.0.0". Equivalent to calling
+	 * <code>new Version(0,0,0)</code>.
+	 */
+	public static final Version	emptyVersion	= new Version(0, 0, 0);
+
+	/**
+	 * Creates a version identifier from the specified numerical components.
+	 * 
+	 * <p>
+	 * The qualifier is set to the empty string.
+	 * 
+	 * @param major Major component of the version identifier.
+	 * @param minor Minor component of the version identifier.
+	 * @param micro Micro component of the version identifier.
+	 * @throws IllegalArgumentException If the numerical components are
+	 *         negative.
+	 */
+	public Version(int major, int minor, int micro) {
+		this(major, minor, micro, null);
+	}
+
+	/**
+	 * Creates a version identifier from the specifed components.
+	 * 
+	 * @param major Major component of the version identifier.
+	 * @param minor Minor component of the version identifier.
+	 * @param micro Micro component of the version identifier.
+	 * @param qualifier Qualifier component of the version identifier. If
+	 *        <code>null</code> is specified, then the qualifier will be set
+	 *        to the empty string.
+	 * @throws IllegalArgumentException If the numerical components are negative
+	 *         or the qualifier string is invalid.
+	 */
+	public Version(int major, int minor, int micro, String qualifier) {
+		if (qualifier == null) {
+			qualifier = ""; //$NON-NLS-1$
+		}
+
+		this.major = major;
+		this.minor = minor;
+		this.micro = micro;
+		this.qualifier = qualifier;
+		validate();
+	}
+
+	/**
+	 * Created a version identifier from the specified string.
+	 * 
+	 * <p>
+	 * Here is the grammar for version strings.
+	 * 
+	 * <pre>
+	 *       version ::= major('.'minor('.'micro('.'qualifier)?)?)?
+	 *       major ::= digit+
+	 *       minor ::= digit+
+	 *       micro ::= digit+
+	 *       qualifier ::= (alpha|digit|'_'|'-')+
+	 *       digit ::= [0..9]
+	 *       alpha ::= [a..zA..Z]
+	 * </pre>
+	 * There must be no whitespace in version.
+	 * 
+	 * @param version String representation of the version identifier.
+	 * @throws IllegalArgumentException If <code>version</code> is improperly
+	 *         formatted.
+	 */
+	public Version(String version) {
+		int major = 0;
+		int minor = 0;
+		int micro = 0;
+		String qualifier = ""; //$NON-NLS-1$
+
+		try {
+			StringTokenizer st = new StringTokenizer(version, SEPARATOR, true);
+			major = Integer.parseInt(st.nextToken());
+
+			if (st.hasMoreTokens()) {
+				st.nextToken(); // consume delimiter
+				minor = Integer.parseInt(st.nextToken());
+
+				if (st.hasMoreTokens()) {
+					st.nextToken(); // consume delimiter
+					micro = Integer.parseInt(st.nextToken());
+
+					if (st.hasMoreTokens()) {
+						st.nextToken(); // consume delimiter
+						qualifier = st.nextToken();
+
+						if (st.hasMoreTokens()) {
+							throw new IllegalArgumentException("invalid format"); //$NON-NLS-1$
+						}
+					}
+				}
+			}
+		}
+		catch (NoSuchElementException e) {
+			throw new IllegalArgumentException("invalid format"); //$NON-NLS-1$
+		}
+
+		this.major = major;
+		this.minor = minor;
+		this.micro = micro;
+		this.qualifier = qualifier;
+		validate();
+	}
+
+	/**
+	 * Called by the Version constructors to validate the version components.
+	 * 
+	 * @throws IllegalArgumentException If the numerical components are negative
+	 *         or the qualifier string is invalid.
+	 */
+	private void validate() {
+		if (major < 0) {
+			throw new IllegalArgumentException("negative major"); //$NON-NLS-1$
+		}
+		if (minor < 0) {
+			throw new IllegalArgumentException("negative minor"); //$NON-NLS-1$
+		}
+		if (micro < 0) {
+			throw new IllegalArgumentException("negative micro"); //$NON-NLS-1$
+		}
+		int length = qualifier.length();
+		for (int i = 0; i < length; i++) {
+			if ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-".indexOf(qualifier.charAt(i)) == -1) { //$NON-NLS-1$
+				throw new IllegalArgumentException("invalid qualifier"); //$NON-NLS-1$
+			}
+		}
+	}
+
+	/**
+	 * Parses a version identifier from the specified string.
+	 * 
+	 * <p>
+	 * See <code>Version(String)</code> for the format of the version string.
+	 * 
+	 * @param version String representation of the version identifier. Leading
+	 *        and trailing whitespace will be ignored.
+	 * @return A <code>Version</code> object representing the version
+	 *         identifier. If <code>version</code> is <code>null</code> or
+	 *         the empty string then <code>emptyVersion</code> will be
+	 *         returned.
+	 * @throws IllegalArgumentException If <code>version</code> is improperly
+	 *         formatted.
+	 */
+	public static Version parseVersion(String version) {
+		if (version == null) {
+			return emptyVersion;
+		}
+
+		version = version.trim();
+		if (version.length() == 0) {
+			return emptyVersion;
+		}
+
+		return new Version(version);
+	}
+
+	/**
+	 * Returns the major component of this version identifier.
+	 * 
+	 * @return The major component.
+	 */
+	public int getMajor() {
+		return major;
+	}
+
+	/**
+	 * Returns the minor component of this version identifier.
+	 * 
+	 * @return The minor component.
+	 */
+	public int getMinor() {
+		return minor;
+	}
+
+	/**
+	 * Returns the micro component of this version identifier.
+	 * 
+	 * @return The micro component.
+	 */
+	public int getMicro() {
+		return micro;
+	}
+
+	/**
+	 * Returns the qualifier component of this version identifier.
+	 * 
+	 * @return The qualifier component.
+	 */
+	public String getQualifier() {
+		return qualifier;
+	}
+
+	/**
+	 * Returns the string representation of this version identifier.
+	 * 
+	 * <p>
+	 * The format of the version string will be <code>major.minor.micro</code>
+	 * if qualifier is the empty string or
+	 * <code>major.minor.micro.qualifier</code> otherwise.
+	 * 
+	 * @return The string representation of this version identifier.
+	 */
+	public String toString() {
+		String base = major + SEPARATOR + minor + SEPARATOR + micro;
+		if (qualifier.length() == 0) { //$NON-NLS-1$
+			return base;
+		}
+		else {
+			return base + SEPARATOR + qualifier;
+		}
+	}
+
+	/**
+	 * Returns a hash code value for the object.
+	 * 
+	 * @return An integer which is a hash code value for this object.
+	 */
+	public int hashCode() {
+		return (major << 24) + (minor << 16) + (micro << 8)
+				+ qualifier.hashCode();
+	}
+
+	/**
+	 * Compares this <code>Version</code> object to another object.
+	 * 
+	 * <p>
+	 * A version is considered to be <b>equal to </b> another version if the
+	 * major, minor and micro components are equal and the qualifier component
+	 * is equal (using <code>String.equals</code>).
+	 * 
+	 * @param object The <code>Version</code> object to be compared.
+	 * @return <code>true</code> if <code>object</code> is a
+	 *         <code>Version</code> and is equal to this object;
+	 *         <code>false</code> otherwise.
+	 */
+	public boolean equals(Object object) {
+		if (object == this) { // quicktest
+			return true;
+		}
+
+		if (!(object instanceof Version)) {
+			return false;
+		}
+
+		Version other = (Version) object;
+		return (major == other.major) && (minor == other.minor)
+				&& (micro == other.micro) && qualifier.equals(other.qualifier);
+	}
+
+	/**
+	 * Compares this <code>Version</code> object to another object.
+	 * 
+	 * <p>
+	 * A version is considered to be <b>less than </b> another version if its
+	 * major component is less than the other version's major component, or the
+	 * major components are equal and its minor component is less than the other
+	 * version's minor component, or the major and minor components are equal
+	 * and its micro component is less than the other version's micro component,
+	 * or the major, minor and micro components are equal and it's qualifier
+	 * component is less than the other version's qualifier component (using
+	 * <code>String.compareTo</code>).
+	 * 
+	 * <p>
+	 * A version is considered to be <b>equal to</b> another version if the
+	 * major, minor and micro components are equal and the qualifier component
+	 * is equal (using <code>String.compareTo</code>).
+	 * 
+	 * @param object The <code>Version</code> object to be compared.
+	 * @return A negative integer, zero, or a positive integer if this object is
+	 *         less than, equal to, or greater than the specified
+	 *         <code>Version</code> object.
+	 * @throws ClassCastException If the specified object is not a
+	 *         <code>Version</code>.
+	 */
+	public int compareTo(Object object) {
+		if (object == this) { // quicktest
+			return 0;
+		}
+
+		Version other = (Version) object;
+
+		int result = major - other.major;
+		if (result != 0) {
+			return result;
+		}
+
+		result = minor - other.minor;
+		if (result != 0) {
+			return result;
+		}
+
+		result = micro - other.micro;
+		if (result != 0) {
+			return result;
+		}
+
+		return qualifier.compareTo(other.qualifier);
+	}
+}
\ No newline at end of file