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/service/condpermadmin/BundleLocationCondition.java b/src/org/osgi/service/condpermadmin/BundleLocationCondition.java
new file mode 100644
index 0000000..62962dd
--- /dev/null
+++ b/src/org/osgi/service/condpermadmin/BundleLocationCondition.java
@@ -0,0 +1,49 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.condpermadmin/src/org/osgi/service/condpermadmin/BundleLocationCondition.java,v 1.9 2005/05/25 16:22:46 twatson 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.service.condpermadmin;
+
+import java.io.FilePermission;
+import org.osgi.framework.Bundle;
+
+/**
+ *
+ * Checks to see if a Bundle matches the given location pattern. Pattern matching
+ * is done using FilePermission style patterns.
+ *
+ * @version $Revision: 1.9 $
+ */
+public class BundleLocationCondition {
+ private static final String CONDITION_TYPE = "org.osgi.service.condpermadmin.BundleLocationCondition";
+ /**
+ * Constructs a condition that tries to match the passed Bundle's location
+ * to the location pattern.
+ *
+ * @param bundle the Bundle being evaluated.
+ * @param info the ConditionInfo to construct the condition for. The args of the
+ * ConditionInfo specify the location to match the Bundle
+ * location to. Matching is done according to the patterns documented
+ * in FilePermission.
+ */
+ static public Condition getCondition(Bundle bundle, ConditionInfo info) {
+ if (!CONDITION_TYPE.equals(info.getType()))
+ throw new IllegalArgumentException("ConditionInfo must be of type \"" + CONDITION_TYPE + "\"");
+ String[] args = info.getArgs();
+ if (args.length != 1)
+ throw new IllegalArgumentException("Illegal number of args: " + args.length);
+ String location = args[0];
+ FilePermission locationPat = new FilePermission(location, "read");
+ FilePermission sourcePat = new FilePermission(bundle.getLocation().toString(), "read");
+ return locationPat.implies(sourcePat) ? Condition.TRUE : Condition.FALSE;
+ }
+
+ private BundleLocationCondition() {
+ // private constructor to prevent objects of this type
+ }
+}
diff --git a/src/org/osgi/service/condpermadmin/BundleSignerCondition.java b/src/org/osgi/service/condpermadmin/BundleSignerCondition.java
new file mode 100644
index 0000000..d62f811
--- /dev/null
+++ b/src/org/osgi/service/condpermadmin/BundleSignerCondition.java
@@ -0,0 +1,66 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.condpermadmin/src/org/osgi/service/condpermadmin/BundleSignerCondition.java,v 1.4 2005/05/25 16:22:46 twatson 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.service.condpermadmin;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * This condition checks the signer of a bundle. Since the bundle's signer can only change
+ * when the bundle is updated, this condition is immutable.
+ * <p>
+ * The condition expressed using a single String that specifies a Distinguished Name (DN)
+ * chain to match bundle signers against. DN's are encoded using IETF RFC 2253. Usually
+ * signers use certificates that are issued by certificate authorities, which also have a
+ * corresponding DN and certificate. The certificate authorities can form a chain of trust
+ * where the last DN and certificate is known by the framework. The signer of a bundle is
+ * expressed as signers DN followed by the DN of its issuer followed by the DN of the next
+ * issuer until the DN of the root certificate authority. Each DN is separated by a semicolon.
+ * <p>
+ * A bundle can satisfy this condition if one of its signers has a DN chain that matches the
+ * DN chain used to construct this condition.
+ * Wildcards (`*') can be used to allow greater flexibility in specifying the DN chains.
+ * Wildcards can be used in place of DNs, RDNs, or the value in an RDN. If a wildcard is
+ * used for a value of an RDN, the value must be exactly "*" and will match any value for
+ * the corresponding type in that RDN. If a wildcard is used for a RDN, it must be the
+ * first RDN and will match any number of RDNs (including zero RDNs).
+ *
+ * @version $Revision: 1.4 $
+ */
+public class BundleSignerCondition {
+ private static final String CONDITION_TYPE = "org.osgi.service.condpermadmin.BundleSignerCondition";
+ /**
+ * Constructs a condition that tries to match the passed Bundle's location
+ * to the location pattern.
+ *
+ * @param bundle the Bundle being evaluated.
+ * @param info the ConditionInfo to construct the condition for. The args of the
+ * ConditionInfo specify the chain of distinguished names pattern to match
+ * against the signer of the Bundle
+ */
+ static public Condition getCondition(Bundle bundle, ConditionInfo info) {
+/*
+ if (!CONDITION_TYPE.equals(info.getType()))
+ throw new IllegalArgumentException("ConditionInfo must be of type \"" + CONDITION_TYPE + "\"");
+ String[] args = info.getArgs();
+ if (args.length != 1)
+ throw new IllegalArgumentException("Illegal number of args: " + args.length);
+ // implementation specific code used here
+ AbstractBundle ab = (AbstractBundle) bundle;
+ return ab.getBundleData().matchDNChain(args[0]) ? Condition.TRUE : Condition.FALSE;
+*/
+ // TODO: Fix BundleSignerCondition.getCondition()
+ return null;
+ }
+
+ private BundleSignerCondition() {
+ // private constructor to prevent objects of this type
+ }
+}
diff --git a/src/org/osgi/service/condpermadmin/Condition.java b/src/org/osgi/service/condpermadmin/Condition.java
new file mode 100644
index 0000000..76dba1c
--- /dev/null
+++ b/src/org/osgi/service/condpermadmin/Condition.java
@@ -0,0 +1,97 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.condpermadmin/src/org/osgi/service/condpermadmin/Condition.java,v 1.9 2005/05/25 16:22:46 twatson 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.service.condpermadmin;
+
+import java.util.Dictionary;
+
+/**
+ * This interface is used to implement Conditions that are bound to Permissions
+ * using ConditionalPermissionCollection. The Permissions of the
+ * ConditionalPermissionCollection can only be used if the associated Condition
+ * is satisfied.
+ */
+public interface Condition {
+ /**
+ * A condition object that will always evaluate to true and that is never postponed.
+ */
+ public final static Condition TRUE = new BooleanCondition(true);
+
+ /**
+ * A condition object that will always evaluate to false and that is never postponed.
+ */
+ public final static Condition FALSE = new BooleanCondition(false);
+
+ /**
+ * This method returns true if the evaluation of the Condition must be postponed
+ * until the end of the permission check. If it returns false, it must be able
+ * to directly answer the isSatisfied method. In other
+ * words, isSatisfied() will return very quickly since no external sources,
+ * such as for example users, need to be consulted.
+ *
+ * @return false if evaluation is immediate, otherwise true to indicate the evaluation must be postponed.
+ */
+ boolean isPostponed();
+
+ /**
+ * This method returns true if the Condition is satisfied.
+ */
+ boolean isSatisfied();
+
+ /**
+ * This method returns true if the satisfiability may change.
+ */
+ boolean isMutable();
+
+ /**
+ * This method returns true if the set of Conditions are satisfied. Although
+ * this method is not static, it should be implemented as if it were static.
+ * All of the passed Conditions will have the same type and will correspond
+ * to the class type of the object on which this method is invoked.
+ *
+ * @param conds the array of Conditions that must be satisfied
+ * @param context a Dictionary object that implementors can use to track
+ * state. If this method is invoked multiple times in the same permission
+ * evaluation, the same Dictionary will be passed multiple times. The
+ * SecurityManager treats this Dictionary as an opaque object simply
+ * creates an empty dictionary and passes it to subsequent invocations
+ * if multiple invocatios are needed.
+ * @return true if all the Conditions are satisfied.
+ */
+ boolean isSatisfied(Condition conds[], Dictionary context);
+
+ /**
+ * Package internal class used to define the {@link Condition#FALSE} and
+ * {@link Condition#TRUE} constants.
+ */
+ final static class BooleanCondition implements Condition {
+ boolean satisfied;
+ BooleanCondition(boolean satisfied) {
+ this.satisfied = satisfied;
+ }
+ public boolean isPostponed() {
+ return false;
+ }
+ public boolean isSatisfied() {
+ return satisfied;
+ }
+ public boolean isMutable() {
+ return false;
+ }
+ public boolean isSatisfied(Condition[] conds, Dictionary context) {
+ for(int i = 0; i < conds.length; i++) {
+ if (!conds[i].isSatisfied())
+ return false;
+ }
+ return true;
+ }
+
+ }
+}
diff --git a/src/org/osgi/service/condpermadmin/ConditionInfo.java b/src/org/osgi/service/condpermadmin/ConditionInfo.java
new file mode 100644
index 0000000..6207c4f
--- /dev/null
+++ b/src/org/osgi/service/condpermadmin/ConditionInfo.java
@@ -0,0 +1,314 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.condpermadmin/src/org/osgi/service/condpermadmin/ConditionInfo.java,v 1.6 2005/05/13 20:33:31 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.service.condpermadmin;
+
+import java.util.Vector;
+
+/**
+ * Condition representation used by the Conditional Permission Admin service.
+ *
+ * <p>
+ * This class encapsulates two pieces of information: a Condition <i>type</i>
+ * (class name), which must implement <tt>Condition</tt>, and the arguments
+ * passed to its constructor.
+ *
+ * <p>
+ * In order for a Condition represented by a <tt>ConditionInfo</tt> to be
+ * instantiated and considered during a permission check, its Condition class
+ * must be available from the system classpath.
+ *
+ */
+
+public class ConditionInfo {
+
+ private String type;
+
+ private String args[];
+
+ /**
+ * Constructs a <tt>ConditionInfo</tt> from the given type and args.
+ *
+ * @param type
+ * The fully qualified class name of the condition represented by
+ * this <tt>ConditionInfo</tt>. The class must implement
+ * <tt>Condition</tt> and must define a constructor that takes
+ * a <tt>Bundle</tt> and the correct number of argument
+ * strings.
+ *
+ * @param args
+ * The arguments that will be passed to the constructor of the
+ * <tt>Conditon</tt> class identified by <tt>type</tt>.
+ *
+ * @exception java.lang.NullPointerException
+ * if <tt>type</tt> is <tt>null</tt>.
+ */
+ public ConditionInfo(String type, String args[]) {
+ this.type = type;
+ this.args = args;
+ if (type == null) {
+ throw new NullPointerException("type is null");
+ }
+ }
+
+ /**
+ * Constructs a <tt>ConditionInfo</tt> object from the given encoded
+ * <tt>ConditionInfo</tt> string.
+ *
+ * @param encodedCondition
+ * The encoded <tt>ConditionInfo</tt>.
+ * @see #getEncoded
+ * @exception java.lang.IllegalArgumentException
+ * if <tt>encodedCondition</tt> is not properly formatted.
+ */
+ public ConditionInfo(String encodedCondition) {
+ if (encodedCondition == null) {
+ throw new NullPointerException("missing encoded permission");
+ }
+ if (encodedCondition.length() == 0) {
+ throw new IllegalArgumentException("empty encoded permission");
+ }
+
+ try {
+ char[] encoded = encodedCondition.toCharArray();
+
+ /* the first character must be '[' */
+ if (encoded[0] != '[') {
+ throw new IllegalArgumentException(
+ "first character not open bracket");
+ }
+
+ /* type is not quoted or encoded */
+ int end = 1;
+ int begin = end;
+
+ while ((encoded[end] != ' ') && (encoded[end] != ')')) {
+ end++;
+ }
+
+ if (end == begin) {
+ throw new IllegalArgumentException("expecting type");
+ }
+
+ this.type = new String(encoded, begin, end - begin);
+
+ Vector args = new Vector();
+ /* type may be followed by name which is quoted and encoded */
+ while (encoded[end] == ' ') {
+ end++;
+
+ if (encoded[end] != '"') {
+ throw new IllegalArgumentException("expecting quoted name");
+ }
+
+ end++;
+ begin = end;
+
+ while (encoded[end] != '"') {
+ if (encoded[end] == '\\') {
+ end++;
+ }
+
+ end++;
+ }
+
+ args.add(decodeString(encoded, begin, end));
+ end++;
+ }
+ this.args = (String[]) args.toArray(new String[0]);
+ /* the final character must be ')' */
+ if ((encoded[end] != ']') || (end + 1 != encoded.length)) {
+ throw new IllegalArgumentException("last character not "
+ + "close bracket");
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalArgumentException("parsing terminated abruptly");
+ }
+ }
+
+ /**
+ * Returns the string encoding of this <tt>ConditionInfo</tt> in a form
+ * suitable for restoring this <tt>ConditionInfo</tt>.
+ *
+ * <p>
+ * The encoding format is:
+ *
+ * <pre>
+ *
+ * [type "arg0" "arg1" ...]
+ *
+ * </pre>
+ *
+ * where <i>argX</i> are strings that are encoded for proper parsing.
+ * Specifically, the <tt>"</tt>, <tt>\</tt>, carriage return, and
+ * linefeed characters are escaped using <tt>\"</tt>, <tt>\\</tt>,
+ * <tt>\r</tt>, and <tt>\n</tt>, respectively.
+ *
+ * <p>
+ * The encoded string must contain no leading or trailing whitespace
+ * characters. A single space character must be used between type and "<i>arg0</i>"
+ * and between all arguments.
+ *
+ * @return The string encoding of this <tt>ConditionInfo</tt>.
+ */
+ public final String getEncoded() {
+ StringBuffer output = new StringBuffer();
+ output.append('[');
+ output.append(type);
+
+ for (int i = 0; i < args.length; i++) {
+ output.append(" \"");
+ encodeString(args[i], output);
+ output.append('\"');
+ }
+
+ output.append(']');
+
+ return (output.toString());
+ }
+
+ /**
+ * Returns the string representation of this <tt>ConditionInfo</tt>. The
+ * string is created by calling the <tt>getEncoded</tt> method on this
+ * <tt>ConditionInfo</tt>.
+ *
+ * @return The string representation of this <tt>ConditionInfo</tt>.
+ */
+ public String toString() {
+ return (getEncoded());
+ }
+
+ /**
+ * Returns the fully qualified class name of the condition represented by
+ * this <tt>ConditionInfo</tt>.
+ *
+ * @return The fully qualified class name of the condition represented by
+ * this <tt>ConditionInfo</tt>.
+ */
+ public final String getType() {
+ return (type);
+ }
+
+ /**
+ * Returns arguments of this <tt>ConditionInfo</tt>.
+ *
+ * @return The arguments of this <tt>ConditionInfo</tt>. have a name.
+ */
+ public final String[] getArgs() {
+ return (args);
+ }
+
+ /**
+ * Determines the equality of two <tt>ConditionInfo</tt> objects.
+ *
+ * This method checks that specified object has the same type and args as
+ * this <tt>ConditionInfo</tt> object.
+ *
+ * @param obj
+ * The object to test for equality with this
+ * <tt>ConditionInfo</tt> object.
+ * @return <tt>true</tt> if <tt>obj</tt> is a <tt>ConditionInfo</tt>,
+ * and has the same type and args as this <tt>ConditionInfo</tt>
+ * object; <tt>false</tt> otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return (true);
+ }
+
+ if (!(obj instanceof ConditionInfo)) {
+ return (false);
+ }
+
+ ConditionInfo other = (ConditionInfo) obj;
+
+ if (!type.equals(other.type) || args.length != other.args.length)
+ return false;
+
+ for (int i = 0; i < args.length; i++) {
+ if (!args[i].equals(other.args[i]))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns the hash code value for this object.
+ *
+ * @return A hash code value for this object.
+ */
+
+ public int hashCode() {
+ int hash = type.hashCode();
+
+ for (int i = 0; i < args.length; i++) {
+ hash ^= args[i].hashCode();
+ }
+ return (hash);
+ }
+
+ /**
+ * This escapes the quotes, backslashes, \n, and \r in the string using a
+ * backslash and appends the newly escaped string to a StringBuffer.
+ */
+ private static void encodeString(String str, StringBuffer output) {
+ int len = str.length();
+
+ for (int i = 0; i < len; i++) {
+ char c = str.charAt(i);
+
+ switch (c) {
+ case '"':
+ case '\\':
+ output.append('\\');
+ output.append(c);
+ break;
+ case '\r':
+ output.append("\\r");
+ break;
+ case '\n':
+ output.append("\\n");
+ break;
+ default:
+ output.append(c);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Takes an encoded character array and decodes it into a new String.
+ */
+ private static String decodeString(char[] str, int begin, int end) {
+ StringBuffer output = new StringBuffer(end - begin);
+
+ for (int i = begin; i < end; i++) {
+ char c = str[i];
+
+ if (c == '\\') {
+ i++;
+
+ if (i < end) {
+ c = str[i];
+
+ if (c == 'n') {
+ c = '\n';
+ } else if (c == 'r') {
+ c = '\r';
+ }
+ }
+ }
+
+ output.append(c);
+ }
+
+ return (output.toString());
+ }
+}
diff --git a/src/org/osgi/service/condpermadmin/ConditionalPermissionAdmin.java b/src/org/osgi/service/condpermadmin/ConditionalPermissionAdmin.java
new file mode 100644
index 0000000..16fd7da
--- /dev/null
+++ b/src/org/osgi/service/condpermadmin/ConditionalPermissionAdmin.java
@@ -0,0 +1,89 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.condpermadmin/src/org/osgi/service/condpermadmin/ConditionalPermissionAdmin.java,v 1.6 2005/07/14 10:47:13 pkriens 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.service.condpermadmin;
+
+import java.security.AccessControlContext;
+import java.util.Enumeration;
+import org.osgi.service.permissionadmin.PermissionInfo;
+
+/**
+ * This is a framework service that allows ConditionalPermissionInfos to be
+ * added to, retrieved from, and removed from the framework.
+ *
+ * @version $Revision: 1.6 $
+ */
+public interface ConditionalPermissionAdmin {
+ /**
+ * Add a new Conditional Permission Info to the repository.
+ *
+ * The Conditional Permission Info will be given a unique, never reused name.
+ *
+ * @param conds the Conditions that need to be satisfied to enable the
+ * corresponding Permissions.
+ * @param perms the Permissions that are enable when the corresponding
+ * Conditions are satisfied.
+ * @return the ConditionalPermissionInfo that for the newly added Conditions
+ * and Permissions.
+ */
+ ConditionalPermissionInfo addConditionalPermissionInfo(
+ ConditionInfo conds[], PermissionInfo perms[]);
+
+ /**
+ * Set or create a Conditional Permission Info with conditions and
+ * permissions.
+ *
+ * If the given <code>name</code> is null or not used in the repository
+ * yet, a new Conditional Permission Info must be created, otherwise the
+ * existing Conditional Permission Info must be reused.
+ *
+ * @param name the name of this Conditional Permission Info, or
+ * <code>null</code>.
+ * @param conds the Conditions that need to be satisfied to enable the
+ * corresponding Permissions.
+ * @param perms the Permissions that are enable when the corresponding
+ * Conditions are satisfied.
+ * @return the ConditionalPermissionInfo that for the newly added Conditions
+ * and Permissions.
+ */
+ ConditionalPermissionInfo setConditionalPermissionInfo(String name,
+ ConditionInfo conds[], PermissionInfo perms[]);
+
+ /**
+ * Returns the ConditionalPermissionInfos that are currently managed by
+ * ConditionalPermissionAdmin. The Enumeration is made up of
+ * ConditionalPermissionInfos. Calling ConditionalPermissionInfo.delete()
+ * will remove the ConditionalPermissionInfo from
+ * ConditionalPermissionAdmin.
+ *
+ * @return the ConditionalPermissionInfos that are currently managed by
+ * ConditionalPermissionAdmin. The Enumeration is made up of
+ * ConditionalPermissionInfos.
+ */
+ Enumeration getConditionalPermissionInfos();
+
+ /**
+ * Return the the Conditional Permission Info with the given name.
+ *
+ * @param name the name of the Conditional Permission Info that must be
+ * returned
+ */
+ ConditionalPermissionInfo getConditionalPermissionInfo(String name);
+
+ /**
+ * Returns the AccessControlContext that corresponds to the given signers.
+ *
+ * @param signers the signers that will be checked agains
+ * BundleSignerCondition.
+ * @return an AccessControlContext that has the Permissions associated with
+ * the signer.
+ */
+ AccessControlContext getAccessControlContext(String signers[]);
+}
diff --git a/src/org/osgi/service/condpermadmin/ConditionalPermissionInfo.java b/src/org/osgi/service/condpermadmin/ConditionalPermissionInfo.java
new file mode 100644
index 0000000..c39e4f5
--- /dev/null
+++ b/src/org/osgi/service/condpermadmin/ConditionalPermissionInfo.java
@@ -0,0 +1,45 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.condpermadmin/src/org/osgi/service/condpermadmin/ConditionalPermissionInfo.java,v 1.7 2005/07/14 10:47:13 pkriens 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.service.condpermadmin;
+
+import org.osgi.service.permissionadmin.PermissionInfo;
+
+/**
+ * This interface describes a binding of a set of Conditions to a set of
+ * Permissions. Instances of this interface are obtained from the
+ * ConditionalPermissionAdmin service. This interface is also used to remove
+ * ConditionalPermissionCollections from ConditionPermissionAdmin.
+ */
+public interface ConditionalPermissionInfo {
+ /**
+ * Returns the ConditionInfos for the Conditions that must be satisfied to
+ * enable this ConditionalPermissionCollection.
+ */
+ ConditionInfo[] getConditionInfos();
+
+ /**
+ * Returns the PermissionInfos for the Permission in this
+ * ConditionalPermissionCollection.
+ */
+ PermissionInfo[] getPermissionInfos();
+
+ /**
+ * Removes the ConditionalPermissionCollection from the
+ * ConditionalPermissionAdmin.
+ */
+ void delete();
+
+ /**
+ * Return the name of this Conditional Permission Info object.
+ *
+ */
+ String getName();
+}
diff --git a/src/org/osgi/service/packageadmin/ExportedPackage.java b/src/org/osgi/service/packageadmin/ExportedPackage.java
new file mode 100644
index 0000000..ac6f362
--- /dev/null
+++ b/src/org/osgi/service/packageadmin/ExportedPackage.java
@@ -0,0 +1,90 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.packageadmin/src/org/osgi/service/packageadmin/ExportedPackage.java,v 1.8 2005/05/13 20:32:34 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.service.packageadmin;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * An exported package.
+ *
+ * Instances implementing this interface are created by the Package Admin
+ * service.
+ *
+ * <p>
+ * The information about an exported package provided by this object is valid
+ * only until the next time <code>PackageAdmin.refreshPackages()</code> is called.
+ * If an <code>ExportedPackage</code> object becomes stale (that is, the package
+ * it references has been updated or removed as a result of calling
+ * <code>PackageAdmin.refreshPackages()</code>), its <code>getName()</code> and
+ * <code>getSpecificationVersion()</code> continue to return their old values,
+ * <code>isRemovalPending()</code> returns <code>true</code>, and
+ * <code>getExportingBundle()</code> and <code>getImportingBundles()</code> return
+ * <code>null</code>.
+ *
+ * @version $Revision: 1.8 $
+ */
+public interface ExportedPackage {
+ /**
+ * Returns the name of the package associated with this
+ * <code>ExportedPackage</code> object.
+ *
+ * @return The name of this <code>ExportedPackage</code> object.
+ */
+ public String getName();
+
+ /**
+ * Returns the bundle exporting the package associated with this
+ * <code>ExportedPackage</code> object.
+ *
+ * @return The exporting bundle, or <code>null</code> if this
+ * <code>ExportedPackage</code> object has become stale.
+ */
+ public Bundle getExportingBundle();
+
+ /**
+ * Returns the resolved bundles that are currently importing the package
+ * associated with this <code>ExportedPackage</code> object.
+ *
+ * <p>
+ * Bundles which require the exporting bundle associated with this
+ * <code>ExportedPackage</code> object are considered to be importing bundles
+ * and are included in the returned array. See
+ * {@link RequiredBundle#getRequiringBundles()}
+ *
+ * @return The array of resolved bundles currently importing the package
+ * associated with this <code>ExportedPackage</code> object, or
+ * <code>null</code> if this <code>ExportedPackage</code> object has
+ * become stale.
+ */
+ public Bundle[] getImportingBundles();
+
+ /**
+ * Returns the specification version of this <code>ExportedPackage</code>, as
+ * specified in the exporting bundle's manifest file.
+ *
+ * @return The specification version of this <code>ExportedPackage</code>
+ * object, or <code>null</code> if no version information is
+ * available.
+ */
+ public String getSpecificationVersion();
+
+ /**
+ * Returns <code>true</code> if the package associated with this
+ * <code>ExportedPackage</code> object has been exported by a bundle that has
+ * been updated or uninstalled.
+ *
+ * @return <code>true</code> if the associated package is being exported by a
+ * bundle that has been updated or uninstalled, or if this
+ * <code>ExportedPackage</code> object has become stale;
+ * <code>false</code> otherwise.
+ */
+ public boolean isRemovalPending();
+}
\ No newline at end of file
diff --git a/src/org/osgi/service/packageadmin/PackageAdmin.java b/src/org/osgi/service/packageadmin/PackageAdmin.java
new file mode 100644
index 0000000..6c5307c
--- /dev/null
+++ b/src/org/osgi/service/packageadmin/PackageAdmin.java
@@ -0,0 +1,289 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.packageadmin/src/org/osgi/service/packageadmin/PackageAdmin.java,v 1.10 2005/05/13 20:32:34 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.service.packageadmin;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * Framework service which allows bundle programmers to inspect the packages
+ * exported in the Framework and eagerly update or uninstall bundles.
+ *
+ * If present, there will only be a single instance of this service registered
+ * with the Framework.
+ *
+ * <p>
+ * The term <i>exported package </i> (and the corresponding interface
+ * {@link ExportedPackage})refers to a package that has actually been exported
+ * (as opposed to one that is available for export).
+ *
+ * <p>
+ * The information about exported packages returned by this service is valid
+ * only until the next time {@link #refreshPackages}is called. If an
+ * <code>ExportedPackage</code> object becomes stale, (that is, the package it
+ * references has been updated or removed as a result of calling
+ * <code>PackageAdmin.refreshPackages()</code>), its <code>getName()</code> and
+ * <code>getSpecificationVersion()</code> continue to return their old values,
+ * <code>isRemovalPending()</code> returns <code>true</code>, and
+ * <code>getExportingBundle()</code> and <code>getImportingBundles()</code> return
+ * <code>null</code>.
+ *
+ * @version $Revision: 1.10 $
+ */
+public interface PackageAdmin {
+ /**
+ * Gets the packages exported by the specified bundle.
+ *
+ * @param bundle The bundle whose exported packages are to be returned, or
+ * <code>null</code> if all the packages currently exported in the
+ * Framework are to be returned. If the specified bundle is the
+ * system bundle (that is, the bundle with id zero), this method
+ * returns all the packages on the system classpath whose name does
+ * not start with "java.". In an environment where the exhaustive
+ * list of packages on the system classpath is not known in advance,
+ * this method will return all currently known packages on the system
+ * classpath, that is, all packages on the system classpath that
+ * contains one or more classes that have been loaded.
+ *
+ * @return The array of packages exported by the specified bundle, or
+ * <code>null</code> if the specified bundle has not exported any
+ * packages.
+ */
+ public ExportedPackage[] getExportedPackages(Bundle bundle);
+
+ /**
+ * Gets the <code>ExportedPackage</code> object with the specified package
+ * name. All exported packages will be checked for the specified name. The
+ * exported package with the highest version will be returned.
+ * <p>
+ * In an environment where the exhaustive list of packages on the system
+ * classpath is not known in advance, this method attempts to see if the
+ * named package is on the system classpath. This means that this method may
+ * discover an <code>ExportedPackage</code> object that was not present in the
+ * list returned by a prior call to <code>getExportedPackages()</code>.
+ *
+ * @param name The name of the exported package to be returned.
+ *
+ * @return The exported package with the specified name, or <code>null</code>
+ * if no exported packages with that name exists.
+ */
+ public ExportedPackage getExportedPackage(String name);
+
+ /**
+ * Forces the update (replacement) or removal of packages exported by the
+ * specified bundles.
+ *
+ * <p>
+ * If no bundles are specified, this method will update or remove any
+ * packages exported by any bundles that were previously updated or
+ * uninstalled since the last call to this method. The technique by which
+ * this is accomplished may vary among different Framework implementations.
+ * One permissible implementation is to stop and restart the Framework.
+ *
+ * <p>
+ * This method returns to the caller immediately and then performs the
+ * following steps in its own thread:
+ *
+ * <ol>
+ * <li>Compute a graph of bundles starting with the specified bundles. If
+ * no bundles are specified, compute a graph of bundles starting with
+ * previously updated or uninstalled ones. Add to the graph any bundle that
+ * imports a package that is currently exported by a bundle in the graph.
+ * The graph is fully constructed when there is no bundle outside the graph
+ * that imports a package from a bundle in the graph. The graph may contain
+ * <code>UNINSTALLED</code> bundles that are currently still exporting
+ * packages.
+ *
+ * <li>Each bundle in the graph that is in the <code>ACTIVE</code> state will
+ * be stopped as described in the <code>Bundle.stop</code> method.
+ *
+ * <li>Each bundle in the graph that is in the <code>RESOLVED</code> state is
+ * moved to the <code>INSTALLED</code> state. The effect of this step is that
+ * bundles in the graph are no longer <code>RESOLVED</code>.
+ *
+ * <li>Each bundle in the graph that is in the <code>UNINSTALLED</code> state
+ * is removed from the graph and is now completely removed from the
+ * Framework.
+ *
+ * <li>Each bundle in the graph that was in the <code>ACTIVE</code> state
+ * prior to Step 2 is started as described in the <code>Bundle.start</code>
+ * method, causing all bundles required for the restart to be resolved. It
+ * is possible that, as a result of the previous steps, packages that were
+ * previously exported no longer are. Therefore, some bundles may be
+ * unresolvable until another bundle offering a compatible package for
+ * export has been installed in the Framework.
+ * <li>A framework event of type <code>FrameworkEvent.PACKAGES_REFRESHED</code>
+ * is broadcast.
+ * </ol>
+ *
+ * <p>
+ * For any exceptions that are thrown during any of these steps, a
+ * <code>FrameworkEvent</code> of type <code>ERROR</code> is broadcast,
+ * containing the exception. The source bundle for these events should be
+ * the specific bundle to which the exception is related. If no specific
+ * bundle can be associated with the exception then the System Bundle must
+ * be used as the source bundle for the event.
+ *
+ * @param bundles the bundles whose exported packages are to be updated or
+ * removed, or <code>null</code> for all previously updated or
+ * uninstalled bundles.
+ *
+ * @exception SecurityException if the caller does not have the
+ * <code>AdminPermission</code> and the Java runtime environment
+ * supports permissions.
+ */
+ public void refreshPackages(Bundle[] bundles);
+
+ /**
+ * Get the <code>ExportedPackage</code> objects with the specified
+ * package name. All exported packages will be checked for the specified
+ * name.
+ * <p>
+ * In an environment where the exhaustive list of packages on the system
+ * classpath is not known in advance, this method attempts to see if the
+ * named package is on the system classpath. This means that this method may
+ * discover an <code>ExportedPackage</code> object that was not present in the
+ * list returned by a prior call to <code>getExportedPackages()</code>.
+ *
+ * @param name The name of the exported packages to be returned.
+ *
+ * @return An array of the exported packages with the specified name, or
+ * <code>null</code> if no exported packages with that name exists.
+ * @since 1.2
+ */
+ public ExportedPackage[] getExportedPackages(String name);
+
+ /**
+ * Resolve the specified bundles. The Framework must attempt to resolve the
+ * specified bundles that are unresolved. Additional bundles that are not
+ * included in the specified bundles may be resolved as a result of calling
+ * this method. A permissible implementation of this method is to attempt to
+ * resolve all unresolved bundles installed in the framework.
+ *
+ * <p>
+ * If <code>null</code> is specified then the Framework will attempt to
+ * resolve all unresolved bundles. This method must not cause any bundle to
+ * be refreshed, stopped, or started. This method will not return until the
+ * operation has completed.
+ *
+ * @param bundles The bundles to resolve or <code>null</code> to resolve all
+ * unresolved bundles installed in the Framework.
+ * @return <code>true</code> if all specified bundles are resolved;
+ * @since 1.2
+ */
+ public boolean resolveBundles(Bundle[] bundles);
+
+ /**
+ * Returns an array of RequiredBundles with the specified symbolic name. If
+ * the symbolic name argument is <code>null</code> then all RequiredBundles
+ * are returned.
+ *
+ * @param symbolicName The symbolic name of the RequiredBundle or
+ * <code>null</code> for all RequiredBundles in the Framework.
+ * @return An array of RequiredBundles with the specified symbolic name or
+ * <code>null</code> if no RequiredBundles exist with that symbolic
+ * name.
+ * @since 1.2
+ */
+ public RequiredBundle[] getRequiredBundles(String symbolicName);
+
+ /**
+ * Returns the bundles with the specified symbolic name within the specified
+ * version range. If no bundles are installed that have the specified
+ * symbolic name, then <code>null</code> is returned. If a version range is
+ * specified, then only the bundles that have the specified symbolic name
+ * and belong to the specified version range are returned. The returned
+ * bundles are ordered by version in descending version order so that the
+ * first element of the array contains the bundle with the highest version.
+ *
+ * @see org.osgi.framework.Constants#BUNDLE_VERSION_ATTRIBUTE
+ * @param symbolicName The symbolic name of the desired bundles.
+ * @param versionRange The version range of the desired bundles, or
+ * <code>null</code> if all versions are desired.
+ * @return An array of bundles with the specified name belonging to the
+ * specified version range ordered in descending version order, or
+ * <code>null</code> if no bundles are found.
+ * @since 1.2
+ */
+ public Bundle[] getBundles(String symbolicName, String versionRange);
+
+ /**
+ * Returns an array of attached fragment bundles for the specified bundle.
+ * If the specified bundle is a fragment then <code>null</code> is returned.
+ * If no fragments are attached to the specified bundle then <code>null</code>
+ * is returned.
+ * <p>
+ * This method does not attempt to resolve the specified bundle. If the
+ * specified bundle is not resolved then <code>null</code> is returned.
+ *
+ * @param bundle The bundle whose attached fragment bundles are to be
+ * returned.
+ * @return An array of fragment bundles or <code>null</code> if the bundle
+ * does not have any attached fragment bundles or the bundle is not
+ * resolved.
+ * @since 1.2
+ */
+ public Bundle[] getFragments(Bundle bundle);
+
+ /**
+ * Returns an array of host bundles to which the specified fragment bundle
+ * is attached or <code>null</code> if the specified bundle is not attached to
+ * a host or is not a fragment bundle.
+ *
+ * @param bundle The bundle whose host bundles are to be returned.
+ * @return An array of host bundles or <code>null</code> if the bundle does
+ * not have any host bundles.
+ * @since 1.2
+ */
+ public Bundle[] getHosts(Bundle bundle);
+
+ /**
+ * Returns the bundle for which the specified class is loaded from. The
+ * classloader of the bundle returned must have been used to load the
+ * specified class. If the class was not loaded by a bundle classloader then
+ * <code>null</code> is returned.
+ *
+ * @param clazz the class object to get a bundle for
+ * @return the bundle from which the specified class is loaded or
+ * <code>null</code> if the class was not loaded by a bundle
+ * classloader
+ * @since 1.2
+ */
+ public Bundle getBundle(Class clazz);
+
+ /**
+ * The bundle is a fragment bundle.
+ *
+ * <p>
+ * The value of <code>BUNDLE_TYPE_FRAGMENT</code> is 0x00000001.
+ *
+ * @since 1.2
+ */
+ public static final int BUNDLE_TYPE_FRAGMENT = 0x00000001;
+
+ /**
+ * Returns the special type of the specified bundle. The bundle type values
+ * are:
+ * <ul>
+ * <li>{@link #BUNDLE_TYPE_FRAGMENT}
+ * </ul>
+ *
+ * A bundle may be more than one type at a time. A type code is used to
+ * identify the bundle type for future extendability.
+ *
+ * <p>
+ * If a bundle is not one or more of the defined types then 0x00000000 is
+ * returned.
+ *
+ * @return The special type of the bundle.
+ * @since 1.2
+ */
+ public int getBundleType(Bundle bundle);
+}
\ No newline at end of file
diff --git a/src/org/osgi/service/packageadmin/RequiredBundle.java b/src/org/osgi/service/packageadmin/RequiredBundle.java
new file mode 100644
index 0000000..0da07c4
--- /dev/null
+++ b/src/org/osgi/service/packageadmin/RequiredBundle.java
@@ -0,0 +1,77 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.packageadmin/src/org/osgi/service/packageadmin/RequiredBundle.java,v 1.5 2005/05/13 20:32:34 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.service.packageadmin;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+
+/**
+ * A required bundle.
+ *
+ * Instances implementing this interface are created by the Package Admin
+ * service.
+ *
+ * <p>
+ * The information about a <code>RequiredBundle</code> provided by this object is
+ * valid only until the next time <code>PackageAdmin.refreshPackages()</code>
+ * called. If a <code>RequiredBundle</code> object becomes stale (that is, the
+ * bundle it references has been updated or removed as a result of calling
+ * <code>PackageAdmin.refreshPackages()</code>), its <code>getSymbolicName()</code>
+ * and <code>getVersion()</code> continue to return their old values,
+ * <code>isRemovalPending()</code> returns true, and <code>getBundle()</code> and
+ * <code>getRequiringBundles()</code> return <code>null</code>.
+ *
+ * @since 1.2
+ */
+public interface RequiredBundle {
+ /**
+ * Returns the bundle which defines this RequiredBundle.
+ *
+ * @return The bundle, or <code>null</code> if this <code>RequiredBundle</code>
+ * object has become stale.
+ */
+ public Bundle getBundle();
+
+ /**
+ * Returns the resolved bundles that currently require this bundle. If this
+ * <code>RequiredBundle</code> object is required and re-exported by another
+ * bundle then all the requiring bundles of the re-exporting bundle are
+ * included in the returned array.
+ *
+ * @return An array of resolved bundles currently requiring this bundle, or
+ * <code>null</code> if this <code>RequiredBundle</code> object has
+ * become stale.
+ */
+ public Bundle[] getRequiringBundles();
+
+ /**
+ * Returns the symbolic name of the bundle.
+ *
+ * @return The symbolic name of the bundle.
+ */
+ public String getSymbolicName();
+
+ /**
+ * Returns the version of the bundle.
+ *
+ * @return The version of the bundle.
+ */
+ public Version getVersion();
+
+ /**
+ * Returns <code>true</code> if the bundle has been updated or uninstalled.
+ *
+ * @return <code>true</code> if the bundle has been updated or uninstalled, or
+ * if the <code>RequiredBundle</code> object has become stale;
+ * <code>false</code> otherwise.
+ */
+ public boolean isRemovalPending();
+}
\ No newline at end of file
diff --git a/src/org/osgi/service/permissionadmin/PermissionAdmin.java b/src/org/osgi/service/permissionadmin/PermissionAdmin.java
new file mode 100644
index 0000000..904b318
--- /dev/null
+++ b/src/org/osgi/service/permissionadmin/PermissionAdmin.java
@@ -0,0 +1,113 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.permissionadmin/src/org/osgi/service/permissionadmin/PermissionAdmin.java,v 1.7 2005/05/13 20:33:46 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.service.permissionadmin;
+
+/**
+ * The Permission Admin service allows management agents to manage the
+ * permissions of bundles. There is at most one Permission Admin service present
+ * in the OSGi environment.
+ * <p>
+ * Access to the Permission Admin service is protected by corresponding
+ * <code>ServicePermission</code>. In addition <code>AdminPermission</code> is
+ * required to actually set permissions.
+ *
+ * <p>
+ * Bundle permissions are managed using a permission table. A bundle's location
+ * serves as the key into this permission table. The value of a table entry is
+ * the set of permissions (of type <code>PermissionInfo</code>) granted to the
+ * bundle named by the given location. A bundle may have an entry in the
+ * permission table prior to being installed in the Framework.
+ *
+ * <p>
+ * The permissions specified in <code>setDefaultPermissions</code> are used as the
+ * default permissions which are granted to all bundles that do not have an
+ * entry in the permission table.
+ *
+ * <p>
+ * Any changes to a bundle's permissions in the permission table will take
+ * effect no later than when bundle's <code>java.security.ProtectionDomain</code>
+ * is next involved in a permission check, and will be made persistent.
+ *
+ * <p>
+ * Only permission classes on the system classpath or from an exported package
+ * are considered during a permission check. Additionally, only permission
+ * classes that are subclasses of <code>java.security.Permission</code> and define
+ * a 2-argument constructor that takes a <i>name </i> string and an <i>actions
+ * </i> string can be used.
+ * <p>
+ * Permissions implicitly granted by the Framework (for example, a bundle's
+ * permission to access its persistent storage area) cannot be changed, and are
+ * not reflected in the permissions returned by <code>getPermissions</code> and
+ * <code>getDefaultPermissions</code>.
+ *
+ * @version $Revision: 1.7 $
+ */
+public interface PermissionAdmin {
+ /**
+ * Gets the permissions assigned to the bundle with the specified location.
+ *
+ * @param location The location of the bundle whose permissions are to be
+ * returned.
+ *
+ * @return The permissions assigned to the bundle with the specified
+ * location, or <code>null</code> if that bundle has not been assigned
+ * any permissions.
+ */
+ PermissionInfo[] getPermissions(String location);
+
+ /**
+ * Assigns the specified permissions to the bundle with the specified
+ * location.
+ *
+ * @param location The location of the bundle that will be assigned the
+ * permissions.
+ * @param permissions The permissions to be assigned, or <code>null</code> if
+ * the specified location is to be removed from the permission table.
+ * @exception SecurityException if the caller does not have the
+ * <code>AdminPermission</code>.
+ */
+ void setPermissions(String location, PermissionInfo[] permissions);
+
+ /**
+ * Returns the bundle locations that have permissions assigned to them, that
+ * is, bundle locations for which an entry exists in the permission table.
+ *
+ * @return The locations of bundles that have been assigned any permissions,
+ * or <code>null</code> if the permission table is empty.
+ */
+ String[] getLocations();
+
+ /**
+ * Gets the default permissions.
+ *
+ * <p>
+ * These are the permissions granted to any bundle that does not have
+ * permissions assigned to its location.
+ *
+ * @return The default permissions, or <code>null</code> if no default
+ * permissions are set.
+ */
+ PermissionInfo[] getDefaultPermissions();
+
+ /**
+ * Sets the default permissions.
+ *
+ * <p>
+ * These are the permissions granted to any bundle that does not have
+ * permissions assigned to its location.
+ *
+ * @param permissions The default permissions, or <code>null</code> if the
+ * default permissions are to be removed from the permission table.
+ * @exception SecurityException if the caller does not have the
+ * <code>AdminPermission</code>.
+ */
+ void setDefaultPermissions(PermissionInfo[] permissions);
+}
\ No newline at end of file
diff --git a/src/org/osgi/service/permissionadmin/PermissionInfo.java b/src/org/osgi/service/permissionadmin/PermissionInfo.java
new file mode 100644
index 0000000..3502e89
--- /dev/null
+++ b/src/org/osgi/service/permissionadmin/PermissionInfo.java
@@ -0,0 +1,360 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.permissionadmin/src/org/osgi/service/permissionadmin/PermissionInfo.java,v 1.8 2005/06/21 15:41:57 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.service.permissionadmin;
+
+/**
+ * Permission representation used by the Permission Admin service.
+ *
+ * <p>
+ * This class encapsulates three pieces of information: a Permission <i>type
+ * </i> (class name), which must be a subclass of
+ * <code>java.security.Permission</code>, and the <i>name </i> and <i>actions
+ * </i> arguments passed to its constructor.
+ *
+ * <p>
+ * In order for a permission represented by a <code>PermissionInfo</code> to be
+ * instantiated and considered during a permission check, its Permission class
+ * must be available from the system classpath or an exported package. This
+ * means that the instantiation of a permission represented by a
+ * <code>PermissionInfo</code> may be delayed until the package containing its
+ * Permission class has been exported by a bundle.
+ *
+ * @version $Revision: 1.8 $
+ */
+public class PermissionInfo {
+ private String type;
+ private String name;
+ private String actions;
+
+ /**
+ * Constructs a <code>PermissionInfo</code> from the given type, name, and
+ * actions.
+ *
+ * @param type The fully qualified class name of the permission represented
+ * by this <code>PermissionInfo</code>. The class must be a subclass
+ * of <code>java.security.Permission</code> and must define a
+ * 2-argument constructor that takes a <i>name </i> string and an
+ * <i>actions </i> string.
+ *
+ * @param name The permission name that will be passed as the first argument
+ * to the constructor of the <code>Permission</code> class identified
+ * by <code>type</code>.
+ *
+ * @param actions The permission actions that will be passed as the second
+ * argument to the constructor of the <code>Permission</code> class
+ * identified by <code>type</code>.
+ *
+ * @exception java.lang.NullPointerException if <code>type</code> is
+ * <code>null</code>.
+ * @exception java.lang.IllegalArgumentException if <code>action</code> is not
+ * <code>null</code> and <code>name</code> is <code>null</code>.
+ */
+ public PermissionInfo(String type, String name, String actions) {
+ this.type = type;
+ this.name = name;
+ this.actions = actions;
+ if (type == null) {
+ throw new NullPointerException("type is null");
+ }
+ if ((name == null) && (actions != null)) {
+ throw new IllegalArgumentException("name missing");
+ }
+ }
+
+ /**
+ * Constructs a <code>PermissionInfo</code> object from the given encoded
+ * <code>PermissionInfo</code> string.
+ *
+ * @param encodedPermission The encoded <code>PermissionInfo</code>.
+ * @see #getEncoded
+ * @exception java.lang.IllegalArgumentException if
+ * <code>encodedPermission</code> is not properly formatted.
+ */
+ public PermissionInfo(String encodedPermission) {
+ if (encodedPermission == null) {
+ throw new NullPointerException("missing encoded permission");
+ }
+ if (encodedPermission.length() == 0) {
+ throw new IllegalArgumentException("empty encoded permission");
+ }
+ try {
+ char[] encoded = encodedPermission.toCharArray();
+ /* the first character must be '(' */
+ if (encoded[0] != '(') {
+ throw new IllegalArgumentException(
+ "first character not open parenthesis");
+ }
+ /* type is not quoted or encoded */
+ int end = 1;
+ int begin = end;
+ while ((encoded[end] != ' ') && (encoded[end] != ')')) {
+ end++;
+ }
+ if (end == begin) {
+ throw new IllegalArgumentException("expecting type");
+ }
+ this.type = new String(encoded, begin, end - begin);
+ /* type may be followed by name which is quoted and encoded */
+ // TODO Need to support multiple spaces
+ if (encoded[end] == ' ') {
+ end++;
+ if (encoded[end] != '"') {
+ throw new IllegalArgumentException("expecting quoted name");
+ }
+ end++;
+ begin = end;
+ while (encoded[end] != '"') {
+ if (encoded[end] == '\\') {
+ end++;
+ }
+ end++;
+ }
+ this.name = decodeString(encoded, begin, end);
+ end++;
+ /* name may be followed by actions which is quoted and encoded */
+ // TODO Need to support multiple spaces
+ if (encoded[end] == ' ') {
+ end++;
+ if (encoded[end] != '"') {
+ throw new IllegalArgumentException(
+ "expecting quoted actions");
+ }
+ end++;
+ begin = end;
+ while (encoded[end] != '"') {
+ if (encoded[end] == '\\') {
+ end++;
+ }
+ end++;
+ }
+ this.actions = decodeString(encoded, begin, end);
+ end++;
+ }
+ }
+ /* the final character must be ')' */
+ if ((encoded[end] != ')') || (end + 1 != encoded.length)) {
+ throw new IllegalArgumentException("last character not "
+ + "close parenthesis");
+ }
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalArgumentException("parsing terminated abruptly");
+ }
+ }
+
+ /**
+ * Returns the string encoding of this <code>PermissionInfo</code> in a form
+ * suitable for restoring this <code>PermissionInfo</code>.
+ *
+ * <p>
+ * The encoded format is:
+ *
+ * <pre>
+ * (type)
+ * </pre>
+ *
+ * or
+ *
+ * <pre>
+ * (type "name")
+ * </pre>
+ *
+ * or
+ *
+ * <pre>
+ * (type "name" "actions")
+ * </pre>
+ *
+ * where <i>name</i> and <i>actions</i> are strings that are encoded for
+ * proper parsing. Specifically, the <code>"</code>,<code>\</code>, carriage
+ * return, and linefeed characters are escaped using <code>\"</code>,
+ * <code>\\</code>,<code>\r</code>, and <code>\n</code>, respectively.
+ *
+ * <p>
+ * The encoded string must contain no leading or trailing whitespace
+ * characters. A single space character must be used between <i>type</i> and
+ * "<i>name</i>" and between "<i>name</i>" and "<i>actions</i>".
+ *
+ * @return The string encoding of this <code>PermissionInfo</code>.
+ */
+ public final String getEncoded() {
+ StringBuffer output = new StringBuffer(
+ 8
+ + type.length()
+ + ((((name == null) ? 0 : name.length()) + ((actions == null) ? 0
+ : actions.length())) << 1));
+ output.append('(');
+ output.append(type);
+ if (name != null) {
+ output.append(" \"");
+ encodeString(name, output);
+ if (actions != null) {
+ output.append("\" \"");
+ encodeString(actions, output);
+ }
+ output.append('\"');
+ }
+ output.append(')');
+ return (output.toString());
+ }
+
+ /**
+ * Returns the string representation of this <code>PermissionInfo</code>. The
+ * string is created by calling the <code>getEncoded</code> method on this
+ * <code>PermissionInfo</code>.
+ *
+ * @return The string representation of this <code>PermissionInfo</code>.
+ */
+ public String toString() {
+ return (getEncoded());
+ }
+
+ /**
+ * Returns the fully qualified class name of the permission represented by
+ * this <code>PermissionInfo</code>.
+ *
+ * @return The fully qualified class name of the permission represented by
+ * this <code>PermissionInfo</code>.
+ */
+ public final String getType() {
+ return (type);
+ }
+
+ /**
+ * Returns the name of the permission represented by this
+ * <code>PermissionInfo</code>.
+ *
+ * @return The name of the permission represented by this
+ * <code>PermissionInfo</code>, or <code>null</code> if the permission
+ * does not have a name.
+ */
+ public final String getName() {
+ return (name);
+ }
+
+ /**
+ * Returns the actions of the permission represented by this
+ * <code>PermissionInfo</code>.
+ *
+ * @return The actions of the permission represented by this
+ * <code>PermissionInfo</code>, or <code>null</code> if the permission
+ * does not have any actions associated with it.
+ */
+ public final String getActions() {
+ return (actions);
+ }
+
+ /**
+ * Determines the equality of two <code>PermissionInfo</code> objects.
+ *
+ * This method checks that specified object has the same type, name and
+ * actions as this <code>PermissionInfo</code> object.
+ *
+ * @param obj The object to test for equality with this
+ * <code>PermissionInfo</code> object.
+ * @return <code>true</code> if <code>obj</code> is a <code>PermissionInfo</code>,
+ * and has the same type, name and actions as this
+ * <code>PermissionInfo</code> object; <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return (true);
+ }
+ if (!(obj instanceof PermissionInfo)) {
+ return (false);
+ }
+ PermissionInfo other = (PermissionInfo) obj;
+ if (!type.equals(other.type) || ((name == null) ^ (other.name == null))
+ || ((actions == null) ^ (other.actions == null))) {
+ return (false);
+ }
+ if (name != null) {
+ if (actions != null) {
+ return (name.equals(other.name) && actions
+ .equals(other.actions));
+ }
+ else {
+ return (name.equals(other.name));
+ }
+ }
+ else {
+ return (true);
+ }
+ }
+
+ /**
+ * Returns the hash code value for this object.
+ *
+ * @return A hash code value for this object.
+ */
+ public int hashCode() {
+ int hash = type.hashCode();
+ if (name != null) {
+ hash ^= name.hashCode();
+ if (actions != null) {
+ hash ^= actions.hashCode();
+ }
+ }
+ return (hash);
+ }
+
+ /**
+ * This escapes the quotes, backslashes, \n, and \r in the string using a
+ * backslash and appends the newly escaped string to a StringBuffer.
+ */
+ private static void encodeString(String str, StringBuffer output) {
+ int len = str.length();
+ for (int i = 0; i < len; i++) {
+ char c = str.charAt(i);
+ switch (c) {
+ case '"' :
+ case '\\' :
+ output.append('\\');
+ output.append(c);
+ break;
+ case '\r' :
+ output.append("\\r");
+ break;
+ case '\n' :
+ output.append("\\n");
+ break;
+ default :
+ output.append(c);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Takes an encoded character array and decodes it into a new String.
+ */
+ private static String decodeString(char[] str, int begin, int end) {
+ StringBuffer output = new StringBuffer(end - begin);
+ for (int i = begin; i < end; i++) {
+ char c = str[i];
+ if (c == '\\') {
+ i++;
+ if (i < end) {
+ c = str[i];
+ if (c == 'n') {
+ c = '\n';
+ }
+ else
+ if (c == 'r') {
+ c = '\r';
+ }
+ }
+ }
+ output.append(c);
+ }
+ return (output.toString());
+ }
+}
\ No newline at end of file
diff --git a/src/org/osgi/service/startlevel/StartLevel.java b/src/org/osgi/service/startlevel/StartLevel.java
new file mode 100644
index 0000000..e2421cd
--- /dev/null
+++ b/src/org/osgi/service/startlevel/StartLevel.java
@@ -0,0 +1,228 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.startlevel/src/org/osgi/service/startlevel/StartLevel.java,v 1.6 2005/05/13 20:34:03 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2002, 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.service.startlevel;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * The StartLevel service allows management agents to manage a start level
+ * assigned to each bundle and the active start level of the Framework. There is
+ * at most one StartLevel service present in the OSGi environment.
+ *
+ * <p>
+ * A start level is defined to be a state of execution in which the Framework
+ * exists. StartLevel values are defined as unsigned integers with 0 (zero)
+ * being the state where the Framework is not launched. Progressively higher
+ * integral values represent progressively higher start levels. e.g. 2 is a
+ * higher start level than 1.
+ * <p>
+ * Access to the StartLevel service is protected by corresponding
+ * <code>ServicePermission</code>. In addition the <code>AdminPermission</code>
+ * that is required to actually modify start level information.
+ * <p>
+ * Start Level support in the Framework includes the ability to control the
+ * beginning start level of the Framework, to modify the active start level of
+ * the Framework and to assign a specific start level to a bundle. How the
+ * beginning start level of a Framework is specified is implementation
+ * dependent. It may be a command line argument when invoking the Framework
+ * implementation.
+ * <p>
+ * When the Framework is first started it must be at start level zero. In this
+ * state, no bundles are running. This is the initial state of the Framework
+ * before it is launched.
+ *
+ * When the Framework is launched, the Framework will enter start level one and
+ * all bundles which are assigned to start level one and are persistently marked
+ * to be started are started as described in the <code>Bundle.start</code> method.
+ * Within a start level, bundles are started in ascending order by
+ * <code>Bundle.getBundleId</code>. The Framework will continue to increase the
+ * start level, starting bundles at each start level, until the Framework has
+ * reached a beginning start level. At this point the Framework has completed
+ * starting bundles and will then broadcast a Framework event of type
+ * <code>FrameworkEvent.STARTED</code> to announce it has completed its launch.
+ *
+ * <p>
+ * The StartLevel service can be used by management bundles to alter the active
+ * start level of the framework.
+ *
+ * @version $Revision: 1.6 $
+ */
+public interface StartLevel {
+ /**
+ * Return the active start level value of the Framework.
+ *
+ * If the Framework is in the process of changing the start level this
+ * method must return the active start level if this differs from the
+ * requested start level.
+ *
+ * @return The active start level value of the Framework.
+ */
+ public abstract int getStartLevel();
+
+ /**
+ * Modify the active start level of the Framework.
+ *
+ * <p>
+ * The Framework will move to the requested start level. This method will
+ * return immediately to the caller and the start level change will occur
+ * asynchronously on another thread.
+ *
+ * <p>
+ * If the specified start level is higher than the active start level, the
+ * Framework will continue to increase the start level until the Framework
+ * has reached the specified start level, starting bundles at each start
+ * level which are persistently marked to be started as described in the
+ * <code>Bundle.start</code> method.
+ *
+ * At each intermediate start level value on the way to and including the
+ * target start level, the framework must:
+ * <ol>
+ * <li>Change the active start level to the intermediate start level value.
+ * <li>Start bundles at the intermediate start level in ascending order by
+ * <code>Bundle.getBundleId</code>.
+ * </ol>
+ * When this process completes after the specified start level is reached,
+ * the Framework will broadcast a Framework event of type
+ * <code>FrameworkEvent.STARTLEVEL_CHANGED</code> to announce it has moved to
+ * the specified start level.
+ *
+ * <p>
+ * If the specified start level is lower than the active start level, the
+ * Framework will continue to decrease the start level until the Framework
+ * has reached the specified start level stopping bundles at each start
+ * level as described in the <code>Bundle.stop</code> method except that their
+ * persistently recorded state indicates that they must be restarted in the
+ * future.
+ *
+ * At each intermediate start level value on the way to and including the
+ * specified start level, the framework must:
+ * <ol>
+ * <li>Stop bundles at the intermediate start level in descending order by
+ * <code>Bundle.getBundleId</code>.
+ * <li>Change the active start level to the intermediate start level value.
+ * </ol>
+ * When this process completes after the specified start level is reached,
+ * the Framework will broadcast a Framework event of type
+ * <code>FrameworkEvent.STARTLEVEL_CHANGED</code> to announce it has moved to
+ * the specified start level.
+ *
+ * <p>
+ * If the specified start level is equal to the active start level, then no
+ * bundles are started or stopped, however, the Framework must broadcast a
+ * Framework event of type <code>FrameworkEvent.STARTLEVEL_CHANGED</code> to
+ * announce it has finished moving to the specified start level. This event
+ * may arrive before the this method return.
+ *
+ * @param startlevel The requested start level for the Framework.
+ * @throws IllegalArgumentException If the specified start level is less
+ * than or equal to zero.
+ * @throws SecurityException If the caller does not have the
+ * <code>AdminPermission</code> and the Java runtime environment
+ * supports permissions.
+ */
+ public abstract void setStartLevel(int startlevel);
+
+ /**
+ * Return the assigned start level value for the specified Bundle.
+ *
+ * @param bundle The target bundle.
+ * @return The start level value of the specified Bundle.
+ * @exception java.lang.IllegalArgumentException If the specified bundle has
+ * been uninstalled.
+ */
+ public abstract int getBundleStartLevel(Bundle bundle);
+
+ /**
+ * Assign a start level value to the specified Bundle.
+ *
+ * <p>
+ * The specified bundle will be assigned the specified start level. The
+ * start level value assigned to the bundle will be persistently recorded by
+ * the Framework.
+ *
+ * If the new start level for the bundle is lower than or equal to the
+ * active start level of the Framework, the Framework will start the
+ * specified bundle as described in the <code>Bundle.start</code> method if
+ * the bundle is persistently marked to be started. The actual starting of
+ * this bundle must occur asynchronously.
+ *
+ * If the new start level for the bundle is higher than the active start
+ * level of the Framework, the Framework will stop the specified bundle as
+ * described in the <code>Bundle.stop</code> method except that the
+ * persistently recorded state for the bundle indicates that the bundle must
+ * be restarted in the future. The actual stopping of this bundle must occur
+ * asynchronously.
+ *
+ * @param bundle The target bundle.
+ * @param startlevel The new start level for the specified Bundle.
+ * @throws IllegalArgumentException If the specified bundle has been
+ * uninstalled or if the specified start level is less than or equal
+ * to zero, or the specified bundle is the system bundle.
+ * @throws SecurityException if the caller does not have the
+ * <code>AdminPermission</code> and the Java runtime environment
+ * supports permissions.
+ */
+ public abstract void setBundleStartLevel(Bundle bundle, int startlevel);
+
+ /**
+ * Return the initial start level value that is assigned to a Bundle when it
+ * is first installed.
+ *
+ * @return The initial start level value for Bundles.
+ * @see #setInitialBundleStartLevel
+ */
+ public abstract int getInitialBundleStartLevel();
+
+ /**
+ * Set the initial start level value that is assigned to a Bundle when it is
+ * first installed.
+ *
+ * <p>
+ * The initial bundle start level will be set to the specified start level.
+ * The initial bundle start level value will be persistently recorded by the
+ * Framework.
+ *
+ * <p>
+ * When a Bundle is installed via <code>BundleContext.installBundle</code>,
+ * it is assigned the initial bundle start level value.
+ *
+ * <p>
+ * The default initial bundle start level value is 1 unless this method has
+ * been called to assign a different initial bundle start level value.
+ *
+ * <p>
+ * Thie method does not change the start level values of installed bundles.
+ *
+ * @param startlevel The initial start level for newly installed bundles.
+ * @throws IllegalArgumentException If the specified start level is less
+ * than or equal to zero.
+ * @throws SecurityException if the caller does not have the
+ * <code>AdminPermission</code> and the Java runtime environment
+ * supports permissions.
+ */
+ public abstract void setInitialBundleStartLevel(int startlevel);
+
+ /**
+ * Return the persistent state of the specified bundle.
+ *
+ * <p>
+ * This method returns the persistent state of a bundle. The persistent
+ * state of a bundle indicates whether a bundle is persistently marked to be
+ * started when it's start level is reached.
+ *
+ * @return <code>true</code> if the bundle is persistently marked to be
+ * started, <code>false</code> if the bundle is not persistently
+ * marked to be started.
+ * @exception java.lang.IllegalArgumentException If the specified bundle has
+ * been uninstalled.
+ */
+ public abstract boolean isBundlePersistentlyStarted(Bundle bundle);
+}
\ No newline at end of file
diff --git a/src/org/osgi/service/url/AbstractURLStreamHandlerService.java b/src/org/osgi/service/url/AbstractURLStreamHandlerService.java
new file mode 100644
index 0000000..03bfd1b
--- /dev/null
+++ b/src/org/osgi/service/url/AbstractURLStreamHandlerService.java
@@ -0,0 +1,142 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.url/src/org/osgi/service/url/AbstractURLStreamHandlerService.java,v 1.6 2005/05/13 20:32:35 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2002, 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.service.url;
+
+import java.net.*;
+
+/**
+ * Abstract implementation of the <code>URLStreamHandlerService</code> interface.
+ * All the methods simply invoke the corresponding methods on
+ * <code>java.net.URLStreamHandler</code> except for <code>parseURL</code> and
+ * <code>setURL</code>, which use the <code>URLStreamHandlerSetter</code>
+ * parameter. Subclasses of this abstract class should not need to override the
+ * <code>setURL</code> and <code>parseURL(URLStreamHandlerSetter,...)</code>
+ * methods.
+ *
+ * @version $Revision: 1.6 $
+ */
+public abstract class AbstractURLStreamHandlerService extends URLStreamHandler
+ implements URLStreamHandlerService {
+ /**
+ * @see "java.net.URLStreamHandler.openConnection"
+ */
+ public abstract URLConnection openConnection(URL u)
+ throws java.io.IOException;
+
+ /**
+ * The <code>URLStreamHandlerSetter</code> object passed to the parseURL
+ * method.
+ */
+ protected URLStreamHandlerSetter realHandler;
+
+ /**
+ * Parse a URL using the <code>URLStreamHandlerSetter</code> object. This
+ * method sets the <code>realHandler</code> field with the specified
+ * <code>URLStreamHandlerSetter</code> object and then calls
+ * <code>parseURL(URL,String,int,int)</code>.
+ *
+ * @param realHandler The object on which the <code>setURL</code> method must
+ * be invoked for the specified URL.
+ * @see "java.net.URLStreamHandler.parseURL"
+ */
+ public void parseURL(URLStreamHandlerSetter realHandler, URL u,
+ String spec, int start, int limit) {
+ this.realHandler = realHandler;
+ parseURL(u, spec, start, limit);
+ }
+
+ /**
+ * This method calls <code>super.toExternalForm</code>.
+ *
+ * @see "java.net.URLStreamHandler.toExternalForm"
+ */
+ public String toExternalForm(URL u) {
+ return super.toExternalForm(u);
+ }
+
+ /**
+ * This method calls <code>super.equals(URL,URL)</code>.
+ *
+ * @see "java.net.URLStreamHandler.equals(URL,URL)"
+ */
+ public boolean equals(URL u1, URL u2) {
+ return super.equals(u1, u2);
+ }
+
+ /**
+ * This method calls <code>super.getDefaultPort</code>.
+ *
+ * @see "java.net.URLStreamHandler.getDefaultPort"
+ */
+ public int getDefaultPort() {
+ return super.getDefaultPort();
+ }
+
+ /**
+ * This method calls <code>super.getHostAddress</code>.
+ *
+ * @see "java.net.URLStreamHandler.getHostAddress"
+ */
+ public InetAddress getHostAddress(URL u) {
+ return super.getHostAddress(u);
+ }
+
+ /**
+ * This method calls <code>super.hashCode(URL)</code>.
+ *
+ * @see "java.net.URLStreamHandler.hashCode(URL)"
+ */
+ public int hashCode(URL u) {
+ return super.hashCode(u);
+ }
+
+ /**
+ * This method calls <code>super.hostsEqual</code>.
+ *
+ * @see "java.net.URLStreamHandler.hostsEqual"
+ */
+ public boolean hostsEqual(URL u1, URL u2) {
+ return super.hostsEqual(u1, u2);
+ }
+
+ /**
+ * This method calls <code>super.sameFile</code>.
+ *
+ * @see "java.net.URLStreamHandler.sameFile"
+ */
+ public boolean sameFile(URL u1, URL u2) {
+ return super.sameFile(u1, u2);
+ }
+
+ /**
+ * This method calls
+ * <code>realHandler.setURL(URL,String,String,int,String,String)</code>.
+ *
+ * @see "java.net.URLStreamHandler.setURL(URL,String,String,int,String,String)"
+ * @deprecated This method is only for compatibility with handlers written
+ * for JDK 1.1.
+ */
+ protected void setURL(URL u, String proto, String host, int port,
+ String file, String ref) {
+ realHandler.setURL(u, proto, host, port, file, ref);
+ }
+
+ /**
+ * This method calls
+ * <code>realHandler.setURL(URL,String,String,int,String,String,String,String)</code>.
+ *
+ * @see "java.net.URLStreamHandler.setURL(URL,String,String,int,String,String,String,String)"
+ */
+ protected void setURL(URL u, String proto, String host, int port,
+ String auth, String user, String path, String query, String ref) {
+ realHandler.setURL(u, proto, host, port, auth, user, path, query, ref);
+ }
+}
\ No newline at end of file
diff --git a/src/org/osgi/service/url/URLConstants.java b/src/org/osgi/service/url/URLConstants.java
new file mode 100644
index 0000000..6915096
--- /dev/null
+++ b/src/org/osgi/service/url/URLConstants.java
@@ -0,0 +1,36 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.url/src/org/osgi/service/url/URLConstants.java,v 1.6 2005/05/13 20:32:35 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2002, 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.service.url;
+
+/**
+ * Defines standard names for property keys associated with
+ * {@link URLStreamHandlerService}and <code>java.net.ContentHandler</code>
+ * services.
+ *
+ * <p>
+ * The values associated with these keys are of type <code>java.lang.String[]</code>,
+ * unless otherwise indicated.
+ *
+ * @version $Revision: 1.6 $
+ */
+public interface URLConstants {
+ /**
+ * Service property naming the protocols serviced by a
+ * URLStreamHandlerService. The property's value is an array of protocol
+ * names.
+ */
+ public static final String URL_HANDLER_PROTOCOL = "url.handler.protocol";
+ /**
+ * Service property naming the MIME types serviced by a
+ * java.net.ContentHandler. The property's value is an array of MIME types.
+ */
+ public static final String URL_CONTENT_MIMETYPE = "url.content.mimetype";
+}
\ No newline at end of file
diff --git a/src/org/osgi/service/url/URLStreamHandlerService.java b/src/org/osgi/service/url/URLStreamHandlerService.java
new file mode 100644
index 0000000..9dea3ff
--- /dev/null
+++ b/src/org/osgi/service/url/URLStreamHandlerService.java
@@ -0,0 +1,84 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.url/src/org/osgi/service/url/URLStreamHandlerService.java,v 1.6 2005/05/13 20:32:35 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2002, 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.service.url;
+
+import java.net.*;
+
+/**
+ * Service interface with public versions of the protected
+ * <code>java.net.URLStreamHandler</code> methods.
+ * <p>
+ * The important differences between this interface and the
+ * <code>URLStreamHandler</code> class are that the <code>setURL</code> method is
+ * absent and the <code>parseURL</code> method takes a
+ * {@link URLStreamHandlerSetter}object as the first argument. Classes
+ * implementing this interface must call the <code>setURL</code> method on the
+ * <code>URLStreamHandlerSetter</code> object received in the <code>parseURL</code>
+ * method instead of <code>URLStreamHandler.setURL</code> to avoid a
+ * <code>SecurityException</code>.
+ *
+ * @see AbstractURLStreamHandlerService
+ *
+ * @version $Revision: 1.6 $
+ */
+public interface URLStreamHandlerService {
+ /**
+ * @see "java.net.URLStreamHandler.openConnection"
+ */
+ public URLConnection openConnection(URL u) throws java.io.IOException;
+
+ /**
+ * Parse a URL. This method is called by the <code>URLStreamHandler</code>
+ * proxy, instead of <code>java.net.URLStreamHandler.parseURL</code>, passing
+ * a <code>URLStreamHandlerSetter</code> object.
+ *
+ * @param realHandler The object on which <code>setURL</code> must be invoked
+ * for this URL.
+ * @see "java.net.URLStreamHandler.parseURL"
+ */
+ public void parseURL(URLStreamHandlerSetter realHandler, URL u,
+ String spec, int start, int limit);
+
+ /**
+ * @see "java.net.URLStreamHandler.toExternalForm"
+ */
+ public String toExternalForm(URL u);
+
+ /**
+ * @see "java.net.URLStreamHandler.equals(URL, URL)"
+ */
+ public boolean equals(URL u1, URL u2);
+
+ /**
+ * @see "java.net.URLStreamHandler.getDefaultPort"
+ */
+ public int getDefaultPort();
+
+ /**
+ * @see "java.net.URLStreamHandler.getHostAddress"
+ */
+ public InetAddress getHostAddress(URL u);
+
+ /**
+ * @see "java.net.URLStreamHandler.hashCode(URL)"
+ */
+ public int hashCode(URL u);
+
+ /**
+ * @see "java.net.URLStreamHandler.hostsEqual"
+ */
+ public boolean hostsEqual(URL u1, URL u2);
+
+ /**
+ * @see "java.net.URLStreamHandler.sameFile"
+ */
+ public boolean sameFile(URL u1, URL u2);
+}
\ No newline at end of file
diff --git a/src/org/osgi/service/url/URLStreamHandlerSetter.java b/src/org/osgi/service/url/URLStreamHandlerSetter.java
new file mode 100644
index 0000000..1d59988
--- /dev/null
+++ b/src/org/osgi/service/url/URLStreamHandlerSetter.java
@@ -0,0 +1,44 @@
+/*
+ * $Header: /cvshome/build/org.osgi.service.url/src/org/osgi/service/url/URLStreamHandlerSetter.java,v 1.6 2005/05/13 20:32:35 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2002, 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.service.url;
+
+import java.net.URL;
+
+/**
+ * Interface used by <code>URLStreamHandlerService</code> objects to call the
+ * <code>setURL</code> method on the proxy <code>URLStreamHandler</code> object.
+ *
+ * <p>
+ * Objects of this type are passed to the
+ * {@link URLStreamHandlerService#parseURL}method. Invoking the <code>setURL</code>
+ * method on the <code>URLStreamHandlerSetter</code> object will invoke the
+ * <code>setURL</code> method on the proxy <code>URLStreamHandler</code> object that
+ * is actually registered with <code>java.net.URL</code> for the protocol.
+ *
+ * @version $Revision: 1.6 $
+ */
+public interface URLStreamHandlerSetter {
+ /**
+ * @see "java.net.URLStreamHandler.setURL(URL,String,String,int,String,String)"
+ *
+ * @deprecated This method is only for compatibility with handlers written
+ * for JDK 1.1.
+ */
+ public void setURL(URL u, String protocol, String host, int port,
+ String file, String ref);
+
+ /**
+ * @see "java.net.URLStreamHandler.setURL(URL,String,String,int,String,String,String,String)"
+ */
+ public void setURL(URL u, String protocol, String host, int port,
+ String authority, String userInfo, String path, String query,
+ String ref);
+}
\ No newline at end of file