You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2005/08/16 20:34:41 UTC
svn commit: r233031 [7/21] - in /incubator/oscar/trunk: ./ etc/ lib/ src/
src/org/ src/org/apache/ src/org/apache/osgi/ src/org/apache/osgi/bundle/
src/org/apache/osgi/bundle/bundlerepository/
src/org/apache/osgi/bundle/bundlerepository/kxmlsax/ src/or...
Added: incubator/oscar/trunk/src/org/apache/osgi/framework/FilterImpl.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/FilterImpl.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/FilterImpl.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/FilterImpl.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.framework;
+
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.util.*;
+
+import org.apache.osgi.framework.util.CaseInsensitiveMap;
+import org.apache.osgi.framework.util.ldap.*;
+import org.osgi.framework.*;
+
+/**
+ * This class implements an RFC 1960-based filter. The syntax of the
+ * filter string is the string representation of LDAP search filters
+ * as defined in RFC 1960. These filters are used to search for services
+ * and to track services using <tt>ServiceTracker</tt> objects.
+**/
+public class FilterImpl implements Filter
+{
+ private LogWrapper m_logger = null;
+ private String m_toString = null;
+ private Evaluator m_evaluator = null;
+ private SimpleMapper m_mapper = null;
+
+// TODO: FilterImpl needs a logger, this is a hack to get FrameworkUtil to compile.
+ public FilterImpl(String expr) throws InvalidSyntaxException
+ {
+ this(null, expr);
+ }
+
+ /**
+ * Construct a filter for a given filter expression string.
+ * @param expr the filter expression string for the filter.
+ **/
+ public FilterImpl(LogWrapper logger, String expr) throws InvalidSyntaxException
+ {
+ m_logger = logger;
+ if (expr == null)
+ {
+ throw new InvalidSyntaxException("Filter cannot be null", null);
+ }
+
+ if (expr != null)
+ {
+ CharArrayReader car = new CharArrayReader(expr.toCharArray());
+ LdapLexer lexer = new LdapLexer(car);
+ Parser parser = new Parser(lexer);
+ try
+ {
+ if (!parser.start())
+ {
+ throw new InvalidSyntaxException(
+ "Failed to parse LDAP query.", expr);
+ }
+ }
+ catch (ParseException ex)
+ {
+ throw new InvalidSyntaxException(
+ ex.getMessage(), expr);
+ }
+ catch (IOException ex)
+ {
+ throw new InvalidSyntaxException(
+ ex.getMessage(), expr);
+ }
+ m_evaluator = new Evaluator(parser.getProgram());
+ m_mapper = new SimpleMapper();
+ }
+ }
+
+ /**
+ * Compares the <tt>Filter</tt> object to another.
+ * @param o the object to compare this <tt>Filter</tt> against.
+ * @return If the other object is a <tt>Filter</tt> object, it
+ * returns <tt>this.toString().equals(obj.toString())</tt>;
+ * <tt>false</tt> otherwise.
+ **/
+ public boolean equals(Object o)
+ {
+ if (o == null)
+ {
+ return false;
+ }
+ else if (o instanceof Filter)
+ {
+ return toString().equals(o.toString());
+ }
+ return false;
+ }
+
+ /**
+ * Returns the hash code for the <tt>Filter</tt> object.
+ * @return The value <tt>this.toString().hashCode()</tt>.
+ **/
+ public int hashCode()
+ {
+ return toString().hashCode();
+ }
+
+ /**
+ * Filter using a <tt>Dictionary</tt> object. The <tt>Filter</tt>
+ * is executed using the <tt>Dictionary</tt> object's keys and values.
+ * @param dict the <tt>Dictionary</tt> object whose keys and values
+ * are used to determine a match.
+ * @return <tt>true</tt> if the <tt>Dictionary</tt> object's keys
+ * and values match this filter; <tt>false</tt> otherwise.
+ * @throws IllegalArgumentException if the dictionary contains case
+ * variants of the same key name.
+ **/
+ public boolean match(Dictionary dict)
+ throws IllegalArgumentException
+ {
+ try
+ {
+ m_mapper.setSource(dict);
+ return m_evaluator.evaluate(m_mapper);
+ }
+ catch (AttributeNotFoundException ex)
+ {
+ m_logger.log(LogWrapper.LOG_DEBUG, "FilterImpl: " + ex);
+ }
+ catch (EvaluationException ex)
+ {
+ m_logger.log(LogWrapper.LOG_ERROR, "FilterImpl: " + toString(), ex);
+ }
+ return false;
+ }
+
+ /**
+ * Filter using a service's properties. The <tt>Filter</tt>
+ * is executed using the properties of the referenced service.
+ * @param ref A reference to the service whose properties
+ * are used to determine a match.
+ * @return <tt>true</tt> if the service's properties match this
+ * filter; <tt>false</tt> otherwise.
+ **/
+ public boolean match(ServiceReference ref)
+ {
+ try
+ {
+ m_mapper.setSource(ref);
+ return m_evaluator.evaluate(m_mapper);
+ }
+ catch (AttributeNotFoundException ex)
+ {
+ m_logger.log(LogWrapper.LOG_DEBUG, "FilterImpl: " + ex);
+ }
+ catch (EvaluationException ex)
+ {
+ m_logger.log(LogWrapper.LOG_ERROR, "FilterImpl: " + toString(), ex);
+ }
+ return false;
+ }
+
+ public boolean matchCase(Dictionary dictionary)
+ {
+ // TODO: Implement Filter.matchCase()
+ return false;
+ }
+
+ /**
+ * Returns the <tt>Filter</tt> object's filter string.
+ * @return Filter string.
+ **/
+ public String toString()
+ {
+ if (m_toString == null)
+ {
+ m_toString = m_evaluator.toStringInfix();
+ }
+ return m_toString;
+ }
+
+ static class SimpleMapper implements Mapper
+ {
+ private ServiceReference m_ref = null;
+ private Map m_map = null;
+
+ public void setSource(ServiceReference ref)
+ {
+ m_ref = ref;
+ m_map = null;
+ }
+
+ public void setSource(Dictionary dict)
+ {
+ if (m_map == null)
+ {
+ m_map = new CaseInsensitiveMap();
+ }
+ else
+ {
+ m_map.clear();
+ }
+
+ if (dict != null)
+ {
+ Enumeration keys = dict.keys();
+ while (keys.hasMoreElements())
+ {
+ Object key = keys.nextElement();
+ if (m_map.get(key) == null)
+ {
+ m_map.put(key, dict.get(key));
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Duplicate attribute: " + key.toString());
+ }
+ }
+ }
+ m_ref = null;
+ }
+
+ public Object lookup(String name)
+ {
+ if (m_map == null)
+ {
+ return m_ref.getProperty(name);
+ }
+ return m_map.get(name);
+ }
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/framework/FrameworkUtil.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/FrameworkUtil.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/FrameworkUtil.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/FrameworkUtil.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.framework;
+
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+
+public class FrameworkUtil
+{
+ public static Filter createFilter(String filter)
+ throws InvalidSyntaxException
+ {
+ return new FilterImpl(filter);
+ }
+}
Added: incubator/oscar/trunk/src/org/apache/osgi/framework/LogWrapper.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/LogWrapper.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/LogWrapper.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/LogWrapper.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.framework;
+
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * <p>
+ * This class mimics the standard OSGi <tt>LogService</tt> interface. An
+ * instance of this class will be used by the framework for all logging. Currently,
+ * the implementation of this class just sends log messages to standard output,
+ * but in the future it will be modified to use a log service if one is
+ * installed in the framework. To do so, it will need to use reflection to
+ * call the log service methods, since it will not have access to the
+ * <tt>LogService</tt> class.
+ * </p>
+**/
+// TODO: Modify LogWrapper to get LogService service object and invoke with reflection.
+public class LogWrapper
+{
+ public static final int LOG_ERROR = 1;
+ public static final int LOG_WARNING = 2;
+ public static final int LOG_INFO = 3;
+ public static final int LOG_DEBUG = 4;
+
+ private Object m_logObj = null;
+
+ public LogWrapper()
+ {
+ }
+
+ public void log(int level, String msg)
+ {
+ synchronized (this)
+ {
+ if (m_logObj != null)
+ {
+// Will use reflection.
+// m_logObj.log(level, msg);
+ }
+ else
+ {
+ _log(null, level, msg, null);
+ }
+ }
+ }
+
+ public void log(int level, String msg, Throwable ex)
+ {
+ synchronized (this)
+ {
+ if (m_logObj != null)
+ {
+// Will use reflection.
+// m_logObj.log(level, msg);
+ }
+ else
+ {
+ _log(null, level, msg, ex);
+ }
+ }
+ }
+
+ public void log(ServiceReference sr, int level, String msg)
+ {
+ synchronized (this)
+ {
+ if (m_logObj != null)
+ {
+// Will use reflection.
+// m_logObj.log(level, msg);
+ }
+ else
+ {
+ _log(sr, level, msg, null);
+ }
+ }
+ }
+
+ public void log(ServiceReference sr, int level, String msg, Throwable ex)
+ {
+ synchronized (this)
+ {
+ if (m_logObj != null)
+ {
+// Will use reflection.
+// m_logObj.log(level, msg);
+ }
+ else
+ {
+ _log(sr, level, msg, ex);
+ }
+ }
+ }
+
+ private void _log(ServiceReference sr, int level, String msg, Throwable ex)
+ {
+ String s = (sr == null) ? null : "SvcRef " + sr;
+ s = (s == null) ? msg : s + " " + msg;
+ s = (ex == null) ? s : s + " (" + ex + ")";
+ switch (level)
+ {
+ case LOG_DEBUG:
+ System.out.println("DEBUG: " + s);
+ break;
+ case LOG_ERROR:
+ System.out.println("ERROR: " + s);
+ if (ex != null)
+ {
+ if ((ex instanceof BundleException) &&
+ (((BundleException) ex).getNestedException() != null))
+ {
+ ex = ((BundleException) ex).getNestedException();
+ }
+ ex.printStackTrace();
+ }
+ break;
+ case LOG_INFO:
+ System.out.println("INFO: " + s);
+ break;
+ case LOG_WARNING:
+ System.out.println("WARNING: " + s);
+ break;
+ default:
+ System.out.println("UNKNOWN[" + level + "]: " + s);
+ }
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/framework/Main.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/Main.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/Main.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/Main.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,481 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.framework;
+
+import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import org.apache.osgi.framework.cache.DefaultBundleCache;
+import org.apache.osgi.framework.util.CaseInsensitiveMap;
+import org.apache.osgi.framework.util.MutablePropertyResolverImpl;
+
+/**
+ * <p>
+ * This class is the default way to instantiate and execute the framework. It is not
+ * intended to be the only way to instantiate and execute the framework; rather, it is
+ * one example of how to do so. When embedding the framework in a host application,
+ * this class can serve as a simple guide of how to do so. It may even be
+ * worthwhile to reuse some of its property handling capabilities. This class
+ * is completely static and is only intended to start a single instance of
+ * the framework.
+ * </p>
+**/
+public class Main
+{
+ /**
+ * The system property name used to specify an URL to the system
+ * property file.
+ **/
+ public static final String SYSTEM_PROPERTIES_PROP = "felix.system.properties";
+ /**
+ * The default name used for the system properties file.
+ **/
+ public static final String SYSTEM_PROPERTIES_FILE_VALUE = "system.properties";
+ /**
+ * The system property name used to specify an URL to the configuration
+ * property file to be used for the created the framework instance.
+ **/
+ public static final String CONFIG_PROPERTIES_PROP = "felix.config.properties";
+ /**
+ * The default name used for the configuration properties file.
+ **/
+ public static final String CONFIG_PROPERTIES_FILE_VALUE = "config.properties";
+
+ private static Felix m_felix = null;
+
+ /**
+ * <p>
+ * This method performs the main task of constructing an framework instance
+ * and starting its execution. The following functions are performed
+ * when invoked:
+ * </p>
+ * <ol>
+ * <li><i><b>Read the system properties file.<b></i> This is a file
+ * containing properties to be pushed into <tt>System.setProperty()</tt>
+ * before starting the framework. This mechanism is mainly shorthand
+ * for people starting the framework from the command line to avoid having
+ * to specify a bunch of <tt>-D</tt> system property definitions.
+ * The only properties defined in this file that will impact the framework's
+ * behavior are the those concerning setting HTTP proxies, such as
+ * <tt>http.proxyHost</tt>, <tt>http.proxyPort</tt>, and
+ * <tt>http.proxyAuth</tt>.
+ * </li>
+ * <li><i><b>Perform system property variable substitution on system
+ * properties.</b></i> Any system properties in the system property
+ * file whose value adheres to <tt>${<system-prop-name>}</tt>
+ * syntax will have their value substituted with the appropriate
+ * system property value.
+ * </li>
+ * <li><i><b>Read the framework's configuration property file.</b></i> This is
+ * a file containing properties used to configure the framework
+ * instance and to pass configuration information into
+ * bundles installed into the framework instance. The configuration
+ * property file is called <tt>config.properties</tt> by default
+ * and is located in the same directory as the <tt>felix.jar</tt>
+ * file, which is typically in the <tt>lib/</tt> directory of the
+ * Felix installation directory. It is possible to use a different
+ * location for the property file by specifying the desired URL
+ * using the <tt>felix.config.properties</tt> system property;
+ * this should be set using the <tt>-D</tt> syntax when executing
+ * the JVM. Refer to the
+ * <a href="Felix.html#start(org.apache.osgi.framework.util.MutablePropertyResolver, org.apache.osgi.framework.util.MutablePropertyResolver, java.util.List)">
+ * <tt>Felix.start()</tt></a> method documentation for more
+ * information on the framework configuration options.
+ * </li>
+ * <li><i><b>Perform system property variable substitution on configuration
+ * properties.</b></i> Any configuration properties whose value adheres to
+ * <tt>${<system-prop-name>}</tt> syntax will have their value
+ * substituted with the appropriate system property value.
+ * </li>
+ * <li><i><b>Ensure the default bundle cache has sufficient information to
+ * initialize.</b></i> The default implementation of the bundle cache
+ * requires either a profile name or a profile directory in order to
+ * start. The configuration properties are checked for at least one
+ * of the <tt>felix.cache.profile</tt> or <tt>felix.cache.profiledir</tt>
+ * properties. If neither is found, the user is asked to supply a profile
+ * name that is added to the configuration property set. See the
+ * <a href="cache/DefaultBundleCache.html"><tt>DefaultBundleCache</tt></a>
+ * documentation for more details its configuration options.
+ * </li>
+ * <li><i><b>Creates and starts a framework instance.</b></i> A simple
+ * <a href="util/MutablePropertyResolver.html"><tt>MutablePropertyResolver</tt></a>
+ * is created for the configuration property file and is passed
+ * into the framework when it is started.
+ * </li>
+ * </ol>
+ * <p>
+ * It should be noted that simply starting an instance of the framework is not enough
+ * to create an interactive session with it. It is necessary to install
+ * and start bundles that provide an interactive shell; this is generally
+ * done by specifying an "auto-start" property in the framework configuration
+ * property file. If no interactive shell bundles are installed or if
+ * the configuration property file cannot be found, the framework will appear to
+ * be hung or deadlocked. This is not the case, it is executing correctly,
+ * there is just no way to interact with it. Refer to the
+ * <a href="Felix.html#start(org.apache.osgi.framework.util.MutablePropertyResolver, org.apache.osgi.framework.util.MutablePropertyResolver, java.util.List)">
+ * <tt>Felix.start()</tt></a> method documentation for more information on
+ * framework configuration options.
+ * </p>
+ * @param argv An array of arguments, all of which are ignored.
+ * @throws Exception If an error occurs.
+ **/
+ public static void main(String[] argv) throws Exception
+ {
+ // Load system properties.
+ Main.loadSystemProperties();
+
+ // Read configuration properties.
+ Properties configProps = Main.readConfigProperties();
+
+ // See if the profile name property was specified.
+ String profileName = configProps.getProperty(DefaultBundleCache.CACHE_PROFILE_PROP);
+
+ // See if the profile directory property was specified.
+ String profileDirName = configProps.getProperty(DefaultBundleCache.CACHE_PROFILE_DIR_PROP);
+
+ // Print welcome banner.
+ System.out.println("\nWelcome to Felix.");
+ System.out.println("=================\n");
+
+ // If no profile or profile directory is specified in the
+ // properties, then ask for a profile name.
+ if ((profileName == null) && (profileDirName == null))
+ {
+ System.out.print("Enter profile name: ");
+ BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+ try
+ {
+ profileName = in.readLine();
+ }
+ catch (IOException ex)
+ {
+ System.err.println("Could not read input.");
+ System.exit(-1);
+ }
+ System.out.println("");
+ if (profileName.length() != 0)
+ {
+ configProps.setProperty(DefaultBundleCache.CACHE_PROFILE_PROP, profileName);
+ }
+ }
+
+ // A profile directory or name must be specified.
+ if ((profileDirName == null) && (profileName.length() == 0))
+ {
+ System.err.println("You must specify a profile name or directory.");
+ System.exit(-1);
+ }
+
+ try
+ {
+ // Now create an instance of the framework.
+ m_felix = new Felix();
+ m_felix.start(
+ new MutablePropertyResolverImpl(new CaseInsensitiveMap(configProps)),
+ null);
+ }
+ catch (Exception ex)
+ {
+ System.err.println("Could not create framework: " + ex);
+ ex.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ /**
+ * <p>
+ * Loads the properties in the system property file associated with the
+ * framework installation into <tt>System.setProperty()</tt>. These properties
+ * are not directly used by the framework in anyway. By default, the system property
+ * file is located in the same directory as the <tt>felix.jar</tt> file and
+ * is called "<tt>system.properties</tt>". This may be changed by setting the
+ * "<tt>felix.system.properties</tt>" system property to an
+ * arbitrary URL.
+ * </p>
+ **/
+ public static void loadSystemProperties()
+ {
+ // The system properties file is either specified by a system
+ // property or it is in the same directory as the Felix JAR file.
+ // Try to load it from one of these places.
+
+ // See if the property URL was specified as a property.
+ URL propURL = null;
+ String custom = System.getProperty(SYSTEM_PROPERTIES_PROP);
+ if (custom != null)
+ {
+ try
+ {
+ propURL = new URL(custom);
+ }
+ catch (MalformedURLException ex)
+ {
+ System.err.print("Main: " + ex);
+ return;
+ }
+ }
+ else
+ {
+ // Determine where felix.jar is located by looking at the
+ // system class path.
+ String jarLoc = null;
+ String classpath = System.getProperty("java.class.path");
+ int index = classpath.toLowerCase().indexOf("felix.jar");
+ int start = classpath.lastIndexOf(File.pathSeparator, index) + 1;
+ if (index > start)
+ {
+ jarLoc = classpath.substring(start, index);
+ if (jarLoc.length() == 0)
+ {
+ jarLoc = ".";
+ }
+ }
+ else
+ {
+ // Can't figure it out so use the current directory as default.
+ jarLoc = System.getProperty("user.dir");
+ }
+
+ try
+ {
+ propURL = new File(jarLoc, SYSTEM_PROPERTIES_FILE_VALUE).toURL();
+ }
+ catch (MalformedURLException ex)
+ {
+ System.err.print("Main: " + ex);
+ return;
+ }
+ }
+
+ // Read the properties file.
+ Properties props = new Properties();
+ InputStream is = null;
+ try
+ {
+ is = propURL.openConnection().getInputStream();
+ props.load(is);
+ is.close();
+ }
+ catch (FileNotFoundException ex)
+ {
+ // Ignore file not found.
+ }
+ catch (Exception ex)
+ {
+ System.err.println(
+ "Main: Error loading system properties from " + propURL);
+ System.err.println("Main: " + ex);
+ try
+ {
+ if (is != null) is.close();
+ }
+ catch (IOException ex2)
+ {
+ // Nothing we can do.
+ }
+ return;
+ }
+
+ // Perform variable substitution for system properties.
+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); )
+ {
+ String name = (String) e.nextElement();
+ System.setProperty(name, substVars((String) props.getProperty(name)));
+ }
+ }
+
+ /**
+ * <p>
+ * Reads the configuration properties in the configuration property
+ * file associated with the framework installation; these properties are
+ * only accessible to the framework and are intended for configuration
+ * purposes. By default, the configuration property file is located in
+ * the same directory as the <tt>felix.jar</tt> file and is called
+ * "<tt>config.properties</tt>". This may be changed by setting the
+ * "<tt>felix.config.properties</tt>" system property to an
+ * arbitrary URL.
+ * </p>
+ * @return A <tt>Properties</tt> instance or <tt>null</tt> if there was an error.
+ **/
+ public static Properties readConfigProperties()
+ {
+ // The config properties file is either specified by a system
+ // property or it is in the same directory as the Felix JAR file.
+ // Try to load it from one of these places.
+
+ // See if the property URL was specified as a property.
+ URL propURL = null;
+ String custom = System.getProperty(CONFIG_PROPERTIES_PROP);
+ if (custom != null)
+ {
+ try
+ {
+ propURL = new URL(custom);
+ }
+ catch (MalformedURLException ex)
+ {
+ System.err.print("Main: " + ex);
+ return null;
+ }
+ }
+ else
+ {
+ // Determine where felix.jar is located by looking at the
+ // system class path.
+ String jarLoc = null;
+ String classpath = System.getProperty("java.class.path");
+ int index = classpath.toLowerCase().indexOf("felix.jar");
+ int start = classpath.lastIndexOf(File.pathSeparator, index) + 1;
+ if (index > start)
+ {
+ jarLoc = classpath.substring(start, index);
+ if (jarLoc.length() == 0)
+ {
+ jarLoc = ".";
+ }
+ }
+ else
+ {
+ // Can't figure it out so use the current directory as default.
+ jarLoc = System.getProperty("user.dir");
+ }
+
+ try
+ {
+ propURL = new File(jarLoc, CONFIG_PROPERTIES_FILE_VALUE).toURL();
+ }
+ catch (MalformedURLException ex)
+ {
+ System.err.print("Main: " + ex);
+ return null;
+ }
+ }
+
+ // Read the properties file.
+ Properties props = new Properties();
+ InputStream is = null;
+ try
+ {
+ is = propURL.openConnection().getInputStream();
+ props.load(is);
+ is.close();
+ }
+ catch (FileNotFoundException ex)
+ {
+ // Ignore file not found.
+ }
+ catch (Exception ex)
+ {
+ System.err.println(
+ "Error loading config properties from " + propURL);
+ System.err.println("Main: " + ex);
+ try
+ {
+ if (is != null) is.close();
+ }
+ catch (IOException ex2)
+ {
+ // Nothing we can do.
+ }
+ return null;
+ }
+
+ // Perform variable substitution for system properties.
+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); )
+ {
+ String name = (String) e.nextElement();
+ props.setProperty(name, substVars((String) props.getProperty(name)));
+ }
+
+ return props;
+ }
+
+ private static final String DELIM_START = "${";
+ private static final char DELIM_STOP = '}';
+ private static final int DELIM_START_LEN = 2;
+ private static final int DELIM_STOP_LEN = 1;
+
+ /**
+ * <p>
+ * This method performs system property variable substitution on the
+ * specified string value. If the specified string contains the
+ * syntax <tt>${<system-prop-name>}</tt>, then the corresponding
+ * system property value is substituted for the marker.
+ * </p>
+ * @param val The string on which to perform system property substitution.
+ * @return The value of the specified string after system property substitution.
+ * @throws IllegalArgumentException If there was a syntax error in the
+ * system property variable marker syntax.
+ **/
+ public static String substVars(String val)
+ throws IllegalArgumentException
+ {
+ StringBuffer sbuf = new StringBuffer();
+
+ if (val == null)
+ {
+ return val;
+ }
+
+ int i = 0;
+ int j, k;
+
+ while (true)
+ {
+ j = val.indexOf(DELIM_START, i);
+ if (j == -1)
+ {
+ if (i == 0)
+ {
+ return val;
+ }
+ else
+ {
+ sbuf.append(val.substring(i, val.length()));
+ return sbuf.toString();
+ }
+ }
+ else
+ {
+ sbuf.append(val.substring(i, j));
+ k = val.indexOf(DELIM_STOP, j);
+ if (k == -1)
+ {
+ throw new IllegalArgumentException(
+ '"' + val +
+ "\" has no closing brace. Opening brace at position "
+ + j + '.');
+ }
+ else
+ {
+ j += DELIM_START_LEN;
+ String key = val.substring(j, k);
+ // Try system properties.
+ String replacement = System.getProperty(key, null);
+ if (replacement != null)
+ {
+ sbuf.append(replacement);
+ }
+ i = k + DELIM_STOP_LEN;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/framework/OSGiLibrarySource.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/OSGiLibrarySource.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/OSGiLibrarySource.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/OSGiLibrarySource.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.framework;
+
+import org.apache.osgi.framework.cache.BundleCache;
+import org.apache.osgi.framework.util.LibraryInfo;
+import org.apache.osgi.moduleloader.LibrarySource;
+import org.osgi.framework.Constants;
+
+public class OSGiLibrarySource implements LibrarySource
+{
+ private LogWrapper m_logger = null;
+ private boolean m_opened = false;
+ private BundleCache m_cache = null;
+ private long m_bundleId = -1;
+ private int m_revision = -1;
+ private String m_os = null;
+ private String m_processor = null;
+ private LibraryInfo[] m_libraries = null;
+
+ public OSGiLibrarySource(
+ LogWrapper logger, BundleCache cache, long bundleId, int revision,
+ String os, String processor, LibraryInfo[] libraries)
+ {
+ m_logger = logger;
+ m_cache = cache;
+ m_bundleId = bundleId;
+ m_revision = revision;
+ m_os = normalizePropertyValue(Constants.FRAMEWORK_OS_NAME, os);
+ m_processor = normalizePropertyValue(Constants.FRAMEWORK_PROCESSOR, processor);
+ m_libraries = libraries;
+ }
+
+ public void open()
+ {
+ m_opened = true;
+ }
+
+ public void close()
+ {
+ m_opened = false;
+ }
+
+ public String getPath(String name) throws IllegalStateException
+ {
+ if (!m_opened)
+ {
+ throw new IllegalStateException("OSGiLibrarySource is not open");
+ }
+
+ if (m_libraries != null)
+ {
+ String libname = System.mapLibraryName(name);
+
+ // Check to see if we have a matching library.
+ // TODO: This "matching" algorithm does not fully
+ // match the spec and should be improved.
+ LibraryInfo library = null;
+ for (int i = 0; (library == null) && (i < m_libraries.length); i++)
+ {
+ boolean osOkay = checkOS(m_libraries[i].getOSNames());
+ boolean procOkay = checkProcessor(m_libraries[i].getProcessors());
+ if (m_libraries[i].getName().endsWith(libname) && osOkay && procOkay)
+ {
+ library = m_libraries[i];
+ }
+ }
+
+ if (library != null)
+ {
+ try {
+ return m_cache.getArchive(m_bundleId)
+ .findLibrary(m_revision, library.getName());
+ } catch (Exception ex) {
+ m_logger.log(LogWrapper.LOG_ERROR, "OSGiLibrarySource: Error finding library.", ex);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private boolean checkOS(String[] osnames)
+ {
+ for (int i = 0; (osnames != null) && (i < osnames.length); i++)
+ {
+ String osname =
+ normalizePropertyValue(Constants.FRAMEWORK_OS_NAME, osnames[i]);
+ if (m_os.equals(osname))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean checkProcessor(String[] processors)
+ {
+ for (int i = 0; (processors != null) && (i < processors.length); i++)
+ {
+ String processor =
+ normalizePropertyValue(Constants.FRAMEWORK_PROCESSOR, processors[i]);
+ if (m_processor.equals(processor))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * This is simply a hack to try to create some standardized
+ * property values, since there seems to be many possible
+ * values for each JVM implementation. Currently, this
+ * focuses on Windows and Linux and will certainly need
+ * to be changed in the future or at least edited.
+ **/
+ public static String normalizePropertyValue(String prop, String value)
+ {
+ prop = prop.toLowerCase();
+ value = value.toLowerCase();
+
+ if (prop.equals(Constants.FRAMEWORK_OS_NAME))
+ {
+ if (value.startsWith("linux"))
+ {
+ return "linux";
+ }
+ else if (value.startsWith("win"))
+ {
+ String os = "win";
+ if (value.indexOf("95") >= 0)
+ {
+ os = "win95";
+ }
+ else if (value.indexOf("98") >= 0)
+ {
+ os = "win98";
+ }
+ else if (value.indexOf("NT") >= 0)
+ {
+ os = "winnt";
+ }
+ else if (value.indexOf("2000") >= 0)
+ {
+ os = "win2000";
+ }
+ else if (value.indexOf("xp") >= 0)
+ {
+ os = "winxp";
+ }
+ return os;
+ }
+ }
+ else if (prop.equals(Constants.FRAMEWORK_PROCESSOR))
+ {
+ if (value.endsWith("86"))
+ {
+ return "x86";
+ }
+ }
+
+ return value;
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/framework/OSGiURLPolicy.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/OSGiURLPolicy.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/OSGiURLPolicy.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/OSGiURLPolicy.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.framework;
+
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+
+import org.apache.osgi.framework.util.FelixConstants;
+import org.apache.osgi.moduleloader.*;
+
+public class OSGiURLPolicy implements URLPolicy
+{
+ private Felix m_felix = null;
+ private BundleURLStreamHandler m_handler = null;
+ private FakeURLStreamHandler m_fakeHandler = null;
+
+ public OSGiURLPolicy(Felix felix)
+ {
+ m_felix = felix;
+ }
+
+ public URL createCodeSourceURL(ModuleManager mgr, Module module)
+ {
+ URL url = null;
+/*
+ BundleImpl bundle = null;
+ try
+ {
+ bundle = (BundleImpl)
+ m_felix.getBundle(BundleInfo.getBundleIdFromModuleId(module.getId()));
+ if (bundle != null)
+ {
+ url = new URL(bundle.getInfo().getLocation());
+ }
+ }
+ catch (NumberFormatException ex)
+ {
+ url = null;
+ }
+ catch (MalformedURLException ex)
+ {
+ if (m_fakeHandler == null)
+ {
+ m_fakeHandler = new FakeURLStreamHandler();
+ }
+ try
+ {
+ url = new URL(null,
+ FelixConstants.FAKE_URL_PROTOCOL_VALUE
+ + "//" + bundle.getLocation(), m_fakeHandler);
+ }
+ catch (Exception ex2)
+ {
+ url = null;
+ }
+ }
+*/
+ return url;
+ }
+
+ public URL createResourceURL(ModuleManager mgr, Module module, int rsIdx, String name)
+ {
+ if (m_handler == null)
+ {
+ m_handler = new BundleURLStreamHandler(mgr);
+ }
+
+ // Add a slash if there is one already, otherwise
+ // the is no slash separating the host from the file
+ // in the resulting URL.
+ if (!name.startsWith("/"))
+ {
+ name = "/" + name;
+ }
+
+ try
+ {
+ if (System.getSecurityManager() != null)
+ {
+ return (URL) AccessController.doPrivileged(
+ new CreateURLPrivileged(module.getId(), rsIdx, name));
+ }
+ else
+ {
+ return new URL(FelixConstants.BUNDLE_URL_PROTOCOL,
+ module.getId(), -1, "/" + rsIdx + name, m_handler);
+ }
+ }
+ catch (Exception ex)
+ {
+ System.err.println("OSGiURLPolicy: " + ex);
+ return null;
+ }
+ }
+
+ /**
+ * This simple class is used to perform the privileged action of
+ * creating a URL using the "bundle:" protocol stream handler.
+ **/
+ private class CreateURLPrivileged implements PrivilegedExceptionAction
+ {
+ private String m_id = null;
+ private int m_rsIdx = 0;
+ private String m_name = null;
+
+ public CreateURLPrivileged(String id, int rsIdx, String name)
+ {
+ m_id = id;
+ m_rsIdx = rsIdx;
+ m_name = name;
+ }
+
+ public Object run() throws Exception
+ {
+ return new URL("bundle", m_id, -1, "/" + m_rsIdx + m_name, m_handler);
+ }
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/framework/PackageAdminActivator.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/PackageAdminActivator.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/PackageAdminActivator.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/PackageAdminActivator.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.framework;
+
+import org.osgi.framework.*;
+
+class PackageAdminActivator implements BundleActivator
+{
+ private Felix m_felix = null;
+ private ServiceRegistration m_reg = null;
+
+ public PackageAdminActivator(Felix felix)
+ {
+ m_felix = felix;
+ }
+
+ public void start(BundleContext context) throws Exception
+ {
+ m_reg = context.registerService(
+ org.osgi.service.packageadmin.PackageAdmin.class.getName(),
+ new PackageAdminImpl(m_felix),
+ null);
+ }
+
+ public void stop(BundleContext context) throws Exception
+ {
+ m_reg.unregister();
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/framework/PackageAdminImpl.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/PackageAdminImpl.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/PackageAdminImpl.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/PackageAdminImpl.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.framework;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.packageadmin.*;
+
+class PackageAdminImpl implements PackageAdmin, Runnable
+{
+ private Felix m_felix = null;
+ private Bundle[][] m_reqBundles = null;
+
+ public PackageAdminImpl(Felix felix)
+ {
+ m_felix = felix;
+
+ // Start a thread to perform asynchronous package refreshes.
+ Thread t = new Thread(this, "FelixPackageAdmin");
+ t.setDaemon(true);
+ t.start();
+ }
+
+ /**
+ * Returns the exported package associated with the specified
+ * package name.
+ *
+ * @param name the name of the exported package to find.
+ * @return the exported package or null if no matching package was found.
+ **/
+ public ExportedPackage getExportedPackage(String name)
+ {
+ return m_felix.getExportedPackage(name);
+ }
+
+ /**
+ * Returns the packages exported by the specified bundle.
+ *
+ * @param bundle the bundle whose exported packages are to be returned.
+ * @return an array of packages exported by the bundle or null if the
+ * bundle does not export any packages.
+ **/
+ public ExportedPackage[] getExportedPackages(Bundle b)
+ {
+ return m_felix.getExportedPackages(b);
+ }
+
+ /**
+ * The OSGi specification states that refreshing packages is
+ * asynchronous; this method simply notifies the package admin
+ * thread to do a refresh.
+ * @param bundles array of bundles to refresh or <tt>null</tt> to refresh
+ * any bundles in need of refreshing.
+ **/
+ public synchronized void refreshPackages(Bundle[] bundles)
+ throws SecurityException
+ {
+ // Save our request parameters and notify all.
+ if (m_reqBundles == null)
+ {
+ m_reqBundles = new Bundle[][] { bundles };
+ }
+ else
+ {
+ Bundle[][] newReqBundles = new Bundle[m_reqBundles.length + 1][];
+ System.arraycopy(m_reqBundles, 0,
+ newReqBundles, 0, m_reqBundles.length);
+ newReqBundles[m_reqBundles.length] = bundles;
+ m_reqBundles = newReqBundles;
+ }
+ notifyAll();
+ }
+
+ /**
+ * The OSGi specification states that package refreshes happen
+ * asynchronously; this is the run() method for the package
+ * refreshing thread.
+ **/
+ public void run()
+ {
+ // This thread loops forever, thus it should
+ // be a daemon thread.
+ Bundle[] bundles = null;
+ while (true)
+ {
+ synchronized (this)
+ {
+ // Wait for a refresh request.
+ while (m_reqBundles == null)
+ {
+ try
+ {
+ wait();
+ }
+ catch (InterruptedException ex)
+ {
+ }
+ }
+
+ // Get the bundles parameter for the current
+ // refresh request.
+ if (m_reqBundles != null)
+ {
+ bundles = m_reqBundles[0];
+ }
+ }
+
+ // Perform refresh.
+ m_felix.refreshPackages(bundles);
+
+ // Remove the first request since it is now completed.
+ synchronized (this)
+ {
+ if (m_reqBundles.length == 1)
+ {
+ m_reqBundles = null;
+ }
+ else
+ {
+ Bundle[][] newReqBundles = new Bundle[m_reqBundles.length - 1][];
+ System.arraycopy(m_reqBundles, 1,
+ newReqBundles, 0, m_reqBundles.length - 1);
+ m_reqBundles = newReqBundles;
+ }
+ }
+ }
+ }
+
+ public ExportedPackage[] getExportedPackages(String name)
+ {
+ // TODO: Implement PackageAdmin.getExportedPackages()
+ return null;
+ }
+
+ public boolean resolveBundles(Bundle[] bundles)
+ {
+ // TODO: Implement PackageAdmin.resolveBundles()
+ return false;
+ }
+
+ public RequiredBundle[] getRequiredBundles(String symbolicName)
+ {
+ // TODO: Implement PackageAdmin.getRequiredBundles()
+ return null;
+ }
+
+ public Bundle[] getBundles(String symbolicName, String versionRange)
+ {
+ // TODO: Implement PackageAdmin.getBundles()
+ return null;
+ }
+
+ public Bundle[] getFragments(Bundle bundle)
+ {
+ // TODO: Implement PackageAdmin.getFragments()
+ return null;
+ }
+
+ public Bundle[] getHosts(Bundle bundle)
+ {
+ // TODO: Implement PackageAdmin.getHosts()
+ return null;
+ }
+
+ public Bundle getBundle(Class clazz)
+ {
+ // TODO: Implement PackageAdmin.getBundle()
+ return null;
+ }
+
+ public int getBundleType(Bundle bundle)
+ {
+ // TODO: Implement PackageAdmin.getBundleType()
+ return 0;
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/framework/ServiceReferenceImpl.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/ServiceReferenceImpl.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/ServiceReferenceImpl.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/ServiceReferenceImpl.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.framework;
+
+import org.apache.osgi.framework.searchpolicy.R4SearchPolicy;
+import org.apache.osgi.framework.searchpolicy.R4Wire;
+import org.apache.osgi.framework.util.FelixConstants;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+
+class ServiceReferenceImpl implements ServiceReference
+{
+ private ServiceRegistrationImpl m_registration = null;
+ private Bundle m_bundle = null;
+
+ public ServiceReferenceImpl(ServiceRegistrationImpl reg, Bundle bundle)
+ {
+ m_registration = reg;
+ m_bundle = bundle;
+ }
+
+ protected ServiceRegistrationImpl getServiceRegistration()
+ {
+ return m_registration;
+ }
+
+ public Object getProperty(String s)
+ {
+ return m_registration.getProperty(s);
+ }
+
+ public String[] getPropertyKeys()
+ {
+ return m_registration.getPropertyKeys();
+ }
+
+ public Bundle getBundle()
+ {
+ return m_bundle;
+ }
+
+ public Bundle[] getUsingBundles()
+ {
+ return m_registration.getUsingBundles();
+ }
+
+ public boolean equals(Object obj)
+ {
+ try
+ {
+ ServiceReferenceImpl ref = (ServiceReferenceImpl) obj;
+ return ref.m_registration == m_registration;
+ }
+ catch (ClassCastException ex)
+ {
+ // Ignore and return false.
+ }
+ catch (NullPointerException ex)
+ {
+ // Ignore and return false.
+ }
+
+ return false;
+ }
+
+ public int hashCode()
+ {
+ if (m_registration.getReference() != null)
+ {
+ if (m_registration.getReference() != this)
+ {
+ return m_registration.getReference().hashCode();
+ }
+ return super.hashCode();
+ }
+ return 0;
+ }
+
+ public String toString()
+ {
+ String[] ocs = (String[]) getProperty("objectClass");
+ String oc = "[";
+ for(int i = 0; i < ocs.length; i++)
+ {
+ oc = oc + ocs[i];
+ if (i < ocs.length - 1)
+ oc = oc + ", ";
+ }
+ oc = oc + "]";
+ return oc;
+ }
+
+ public boolean isAssignableTo(Bundle requester, String className)
+ {
+ // Always return true if the requester is the same as the provider.
+ if (requester == m_bundle)
+ {
+ return true;
+ }
+
+ // Boolean flag.
+ boolean allow = true;
+ // Get the package.
+ String pkgName =
+ org.apache.osgi.moduleloader.Util.getClassPackage(className);
+ // Get package wiring from service provider and requester.
+ R4Wire requesterWire = R4SearchPolicy.getWire(
+ ((BundleImpl) requester).getInfo().getCurrentModule(), pkgName);
+ R4Wire providerWire = R4SearchPolicy.getWire(
+ ((BundleImpl) m_bundle).getInfo().getCurrentModule(), pkgName);
+
+ // There are three situations that may occur here:
+ // 1. The requester does not have a wire for the package.
+ // 2. The provider does not have a wire for the package.
+ // 3. Both have a wire for the package.
+ // For case 1, we do not filter the service reference since we
+ // assume that the bundle is using reflection or that it won't
+ // use that class at all since it does not import it. For
+ // case 2, we have to try to load the class from the class
+ // loader of the service object and then compare the class
+ // loaders to determine if we should filter the service
+ // refernce. In case 3, we simply compare the exporting
+ // modules from the package wiring to determine if we need
+ // to filter the service reference.
+
+ // Case 1: Always include service reference.
+ if (requesterWire == null)
+ {
+ // This is an intentional no-op.
+ }
+ // Case 2: Only include service reference if the service
+ // object uses the same class as the requester.
+ else if (providerWire == null)
+ {
+ try
+ {
+ // Load the class from the requesting bundle.
+ Class requestClass =
+ ((BundleImpl) requester).getInfo().getCurrentModule().getClassLoader()
+ .loadClass(className);
+ // Get the service registration and ask it to check
+ // if the service object is assignable to the requesting
+ // bundle's class.
+ allow = getServiceRegistration().isClassAccessible(requestClass);
+ }
+ catch (Exception ex)
+ {
+ // This should not happen, filter to be safe.
+ allow = false;
+ }
+ }
+ // Case 3: Include service reference if the wires have the
+ // same source module.
+ else
+ {
+ allow = providerWire.m_module.equals(requesterWire.m_module);
+ }
+
+ return allow;
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/framework/ServiceRegistrationImpl.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/ServiceRegistrationImpl.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/ServiceRegistrationImpl.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/ServiceRegistrationImpl.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.framework;
+
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.util.*;
+
+import org.apache.osgi.framework.util.CaseInsensitiveMap;
+import org.osgi.framework.*;
+
+class ServiceRegistrationImpl implements ServiceRegistration
+{
+ // Service registry.
+ private ServiceRegistry m_registry = null;
+ // Bundle implementing the service.
+ private Bundle m_bundle = null;
+ // Interfaces associated with the service object.
+ private String[] m_classes = null;
+ // Service Id associated with the service object.
+ private Long m_serviceId = null;
+ // Service object.
+ private Object m_svcObj = null;
+ // Service factory interface.
+ private ServiceFactory m_factory = null;
+ // Associated property dictionary.
+ private Map m_propMap = null;
+ // Re-usable service reference.
+ private ServiceReferenceImpl m_ref = null;
+
+ public ServiceRegistrationImpl(
+ ServiceRegistry registry, Bundle bundle,
+ String[] classes, Long serviceId,
+ Object svcObj, Dictionary dict)
+ {
+ m_registry = registry;
+ m_bundle = bundle;
+ m_classes = classes;
+ m_serviceId = serviceId;
+ m_svcObj = svcObj;
+ m_factory = (m_svcObj instanceof ServiceFactory)
+ ? (ServiceFactory) m_svcObj : null;
+
+ initializeProperties(dict);
+
+ // This reference is the "standard" reference for this
+ // service and will always be returned by getReference().
+ // Since all reference to this service are supposed to
+ // be equal, we use the hashcode of this reference for
+ // a references to this service in ServiceReference.
+ m_ref = new ServiceReferenceImpl(this, m_bundle);
+ }
+
+ protected boolean isValid()
+ {
+ return (m_svcObj != null);
+ }
+
+ public ServiceReference getReference()
+ {
+ return m_ref;
+ }
+
+ public void setProperties(Dictionary dict)
+ {
+ // Make sure registration is valid.
+ if (!isValid())
+ {
+ throw new IllegalStateException(
+ "The service registration is no longer valid.");
+ }
+ // Set the properties.
+ initializeProperties(dict);
+ // Tell registry about it.
+ m_registry.servicePropertiesModified(this);
+ }
+
+ public void unregister()
+ {
+ m_registry.unregisterService(m_bundle, this);
+ m_svcObj = null;
+ m_factory = null;
+ }
+
+ //
+ // Utility methods.
+ //
+
+ /**
+ * This method determines if the class loader of the service object
+ * has access to the specified class.
+ * @param clazz the class to test for reachability.
+ * @return <tt>true</tt> if the specified class is reachable from the
+ * service object's class loader, <tt>false</tt> otherwise.
+ **/
+ protected boolean isClassAccessible(Class clazz)
+ {
+ ClassLoader loader = (m_factory != null)
+ ? m_factory.getClass().getClassLoader()
+ : m_svcObj.getClass().getClassLoader();
+ try
+ {
+ Class target = loader.loadClass(clazz.getName());
+ return (target.getClassLoader() == clazz.getClassLoader());
+ }
+ catch (Exception ex)
+ {
+ }
+ return false;
+ }
+
+ protected Object getProperty(String key)
+ {
+ return m_propMap.get(key);
+ }
+
+ private transient ArrayList m_list = new ArrayList();
+
+ protected String[] getPropertyKeys()
+ {
+ synchronized (m_list)
+ {
+ m_list.clear();
+ Iterator i = m_propMap.entrySet().iterator();
+ while (i.hasNext())
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ m_list.add(entry.getKey());
+ }
+ return (String[]) m_list.toArray(new String[m_list.size()]);
+ }
+ }
+
+ protected Bundle[] getUsingBundles()
+ {
+ return m_registry.getUsingBundles(m_ref);
+ }
+
+ protected Object getService(Bundle acqBundle)
+ {
+ // If the service object is a service factory, then
+ // let it create the service object.
+ if (m_factory != null)
+ {
+ try
+ {
+ if (System.getSecurityManager() != null)
+ {
+ return AccessController.doPrivileged(
+ new ServiceFactoryPrivileged(acqBundle, null));
+ }
+ else
+ {
+ return getFactoryUnchecked(acqBundle);
+ }
+ }
+ catch (Exception ex)
+ {
+ m_registry.getLogger().log(
+ LogWrapper.LOG_ERROR, "ServiceRegistrationImpl: Error getting service.", ex);
+ return null;
+ }
+ }
+ else
+ {
+ return m_svcObj;
+ }
+ }
+
+ protected void ungetService(Bundle relBundle, Object svcObj)
+ {
+ // If the service object is a service factory, then
+ // let is release the service object.
+ if (m_factory != null)
+ {
+ try
+ {
+ if (System.getSecurityManager() != null)
+ {
+ AccessController.doPrivileged(
+ new ServiceFactoryPrivileged(relBundle, svcObj));
+ }
+ else
+ {
+ ungetFactoryUnchecked(relBundle, svcObj);
+ }
+ }
+ catch (Exception ex)
+ {
+ m_registry.getLogger().log(
+ LogWrapper.LOG_ERROR, "ServiceRegistrationImpl: Error ungetting service.", ex);
+ }
+ }
+ }
+
+ private void initializeProperties(Dictionary dict)
+ {
+ // Create a case insensitive map.
+ if (m_propMap == null)
+ {
+ m_propMap = new CaseInsensitiveMap();
+ }
+ else
+ {
+ m_propMap.clear();
+ }
+
+ if (dict != null)
+ {
+ Enumeration keys = dict.keys();
+ while (keys.hasMoreElements())
+ {
+ Object key = keys.nextElement();
+ m_propMap.put(key, dict.get(key));
+ }
+ }
+
+ // Add the framework assigned properties.
+ m_propMap.put(Constants.OBJECTCLASS, m_classes);
+ m_propMap.put(Constants.SERVICE_ID, m_serviceId);
+ }
+
+ private Object getFactoryUnchecked(Bundle bundle)
+ {
+ return m_factory.getService(bundle, this);
+ }
+
+ private void ungetFactoryUnchecked(Bundle bundle, Object svcObj)
+ {
+ m_factory.ungetService(bundle, this, svcObj);
+ }
+
+ /**
+ * This simple class is used to ensure that when a service factory
+ * is called, that no other classes on the call stack interferes
+ * with the permissions of the factory itself.
+ **/
+ private class ServiceFactoryPrivileged implements PrivilegedExceptionAction
+ {
+ private Bundle m_bundle = null;
+ private Object m_svcObj = null;
+
+ public ServiceFactoryPrivileged(Bundle bundle, Object svcObj)
+ {
+ m_bundle = bundle;
+ m_svcObj = svcObj;
+ }
+
+ public Object run() throws Exception
+ {
+ if (m_svcObj == null)
+ {
+ return getFactoryUnchecked(m_bundle);
+ }
+ else
+ {
+ ungetFactoryUnchecked(m_bundle, m_svcObj);
+ }
+ return null;
+ }
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/framework/ServiceRegistry.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/ServiceRegistry.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/ServiceRegistry.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/ServiceRegistry.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,522 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.framework;
+
+import java.util.*;
+
+import org.apache.osgi.framework.util.FelixConstants;
+import org.osgi.framework.*;
+
+public class ServiceRegistry
+{
+ private LogWrapper m_logger = null;
+ private long m_currentServiceId = 1L;
+ // Maps bundle to an array of service registrations.
+ private Map m_serviceRegsMap = new HashMap();
+ // Maps bundle to an array of usage counts.
+ private Map m_inUseMap = new HashMap();
+
+ private ServiceListener m_serviceListener = null;
+
+ public ServiceRegistry(LogWrapper logger)
+ {
+ m_logger = logger;
+ }
+
+ public synchronized ServiceReference[] getRegisteredServices(Bundle bundle)
+ {
+ ServiceRegistration[] regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
+ if (regs != null)
+ {
+ ServiceReference[] refs = new ServiceReference[regs.length];
+ for (int i = 0; i < refs.length; i++)
+ {
+ refs[i] = regs[i].getReference();
+ }
+ return refs;
+ }
+ return null;
+ }
+
+ public ServiceRegistration registerService(
+ Bundle bundle, String[] classNames, Object svcObj, Dictionary dict)
+ {
+ ServiceRegistration reg = null;
+
+ synchronized (this)
+ {
+ // Create the service registration.
+ reg = new ServiceRegistrationImpl(
+ this, bundle, classNames, new Long(m_currentServiceId++), svcObj, dict);
+ // Get the bundles current registered services.
+ ServiceRegistration[] regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
+ m_serviceRegsMap.put(bundle, addServiceRegistration(regs, reg));
+ }
+ fireServiceChanged(new ServiceEvent(ServiceEvent.REGISTERED, reg.getReference()));
+ return reg;
+ }
+
+ public void unregisterService(Bundle bundle, ServiceRegistration reg)
+ {
+ synchronized (this)
+ {
+ ServiceRegistration[] regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
+ m_serviceRegsMap.put(bundle, removeServiceRegistration(regs, reg));
+ }
+ fireServiceChanged(new ServiceEvent(ServiceEvent.UNREGISTERING, reg.getReference()));
+ }
+
+ public void unregisterServices(Bundle bundle)
+ {
+ // Simply remove all service registrations for the bundle.
+ ServiceRegistration[] regs = null;
+ synchronized (this)
+ {
+ regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
+ m_serviceRegsMap.remove(bundle);
+ }
+
+ // Fire all events outside of synchronized block.
+ for (int i = 0; (regs != null) && (i < regs.length); i++)
+ {
+ fireServiceChanged(
+ new ServiceEvent(ServiceEvent.UNREGISTERING, regs[i].getReference()));
+ }
+ }
+
+ public synchronized List getServiceReferences(String className, Filter filter)
+ throws InvalidSyntaxException
+ {
+ // Create a filtered list of service references.
+ List list = new ArrayList();
+
+ // Iterator over all service registrations.
+ for (Iterator i = m_serviceRegsMap.entrySet().iterator(); i.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ ServiceRegistration[] regs = (ServiceRegistration[]) entry.getValue();
+
+ for (int regIdx = 0;
+ (regs != null) && (regIdx < regs.length);
+ regIdx++)
+ {
+ // Determine if the registered services matches
+ // the search criteria.
+ boolean matched = false;
+
+ // If className is null, then look at filter only.
+ if ((className == null) &&
+ ((filter == null) || filter.match(regs[regIdx].getReference())))
+ {
+ matched = true;
+ }
+ // If className is not null, then first match the
+ // objectClass property before looking at the
+ // filter.
+ else if (className != null)
+ {
+ String[] objectClass = (String[])
+ ((ServiceRegistrationImpl) regs[regIdx]).getProperty(FelixConstants.OBJECTCLASS);
+ for (int classIdx = 0;
+ classIdx < objectClass.length;
+ classIdx++)
+ {
+ if (objectClass[classIdx].equals(className) &&
+ ((filter == null) || filter.match(regs[regIdx].getReference())))
+ {
+ matched = true;
+ break;
+ }
+ }
+ }
+
+ // Add reference if it was a match.
+ if (matched)
+ {
+ list.add(regs[regIdx].getReference());
+ }
+ }
+ }
+
+ return list;
+ }
+
+ public synchronized ServiceReference[] getServicesInUse(Bundle bundle)
+ {
+ UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+ if (usages != null)
+ {
+ ServiceReference[] refs = new ServiceReference[usages.length];
+ for (int i = 0; i < refs.length; i++)
+ {
+ refs[i] = usages[i].m_ref;
+ }
+ return refs;
+ }
+ return null;
+ }
+
+ public synchronized Object getService(Bundle bundle, ServiceReference ref)
+ {
+ // Get usage counts for specified bundle.
+ UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+
+ // Make sure the service registration is still valid.
+ if (!((ServiceReferenceImpl) ref).getServiceRegistration().isValid())
+ {
+ // If the service registration is not valid, then this means
+ // that the service provider unregistered the service. The spec
+ // says that calls to get an unregistered service should always
+ // return null (assumption: even if it is currently cached
+ // by the bundle). So in this case, flush the service reference
+ // from the cache and return null.
+ m_inUseMap.put(bundle, removeUsageCount(usages, ref));
+
+ // It is not necessary to unget the service object from
+ // the providing bundle, since the associated service is
+ // unregistered and hence not in the list of registered services
+ // of the providing bundle. This is precisely why the service
+ // registration was not found above in the first place.
+ return null;
+ }
+
+ // Get the service registration.
+ ServiceRegistrationImpl reg = ((ServiceReferenceImpl) ref).getServiceRegistration();
+
+ // Get the usage count, if any.
+ UsageCount usage = getUsageCount(usages, ref);
+
+ // If the service object is cached, then increase the usage
+ // count and return the cached service object.
+ Object svcObj = null;
+ if (usage != null)
+ {
+ usage.m_count++;
+ svcObj = usage.m_svcObj;
+ }
+ else
+ {
+ // Get service object from service registration.
+ svcObj = reg.getService(bundle);
+
+ // Cache the service object.
+ if (svcObj != null)
+ {
+ m_inUseMap.put(bundle, addUsageCount(usages, ref, svcObj));
+ }
+ }
+
+ return svcObj;
+ }
+
+ public synchronized boolean ungetService(Bundle bundle, ServiceReference ref)
+ {
+ // Get usage count.
+ UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+ UsageCount usage = getUsageCount(usages, ref);
+
+ // If no usage count, then return.
+ if (usage == null)
+ {
+ return false;
+ }
+
+ // Make sure the service registration is still valid.
+ if (!((ServiceReferenceImpl) ref).getServiceRegistration().isValid())
+ {
+ // If the service registration is not valid, then this means
+ // that the service provider unregistered the service. The spec
+ // says that calls to get an unregistered service should always
+ // return null (assumption: even if it is currently cached
+ // by the bundle). So in this case, flush the service reference
+ // from the cache and return null.
+ m_inUseMap.put(bundle, removeUsageCount(usages, ref));
+ return false;
+ }
+
+ // Decrement usage count.
+ usage.m_count--;
+
+ // Remove reference when usage count goes to zero
+ // and unget the service object from the exporting
+ // bundle.
+ if (usage.m_count == 0)
+ {
+ m_inUseMap.put(bundle, removeUsageCount(usages, ref));
+ ServiceRegistrationImpl reg =
+ ((ServiceReferenceImpl) ref).getServiceRegistration();
+ reg.ungetService(bundle, usage.m_svcObj);
+ usage.m_svcObj = null;
+ }
+
+ // Return true if the usage count is greater than zero.
+ return (usage.m_count > 0);
+ }
+
+
+ /**
+ * This is a utility method to release all services being
+ * used by the specified bundle.
+ * @param bundle the bundle whose services are to be released.
+ **/
+ public synchronized void ungetServices(Bundle bundle)
+ {
+ UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+ if (usages == null)
+ {
+ return;
+ }
+
+ // Remove each service object from the
+ // service cache.
+ for (int i = 0; i < usages.length; i++)
+ {
+ // Keep ungetting until all usage count is zero.
+ while (ungetService(bundle, usages[i].m_ref))
+ {
+ // Empty loop body.
+ }
+ }
+ }
+
+ public synchronized Bundle[] getUsingBundles(ServiceReference ref)
+ {
+ Bundle[] bundles = null;
+ for (Iterator iter = m_inUseMap.entrySet().iterator(); iter.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) iter.next();
+ Bundle bundle = (Bundle) entry.getKey();
+ UsageCount[] usages = (UsageCount[]) entry.getValue();
+ for (int useIdx = 0; useIdx < usages.length; useIdx++)
+ {
+ if (usages[useIdx].m_ref.equals(ref))
+ {
+ // Add the bundle to the array to be returned.
+ if (bundles == null)
+ {
+ bundles = new Bundle[] { bundle };
+ }
+ else
+ {
+ Bundle[] nbs = new Bundle[bundles.length + 1];
+ System.arraycopy(bundles, 0, nbs, 0, bundles.length);
+ nbs[bundles.length] = bundle;
+ bundles = nbs;
+ }
+ }
+ }
+ }
+ return bundles;
+ }
+
+ public void servicePropertiesModified(ServiceRegistration reg)
+ {
+ fireServiceChanged(new ServiceEvent(ServiceEvent.MODIFIED, reg.getReference()));
+ }
+
+ public LogWrapper getLogger()
+ {
+ return m_logger;
+ }
+
+ private static ServiceRegistration[] addServiceRegistration(
+ ServiceRegistration[] regs, ServiceRegistration reg)
+ {
+ if (regs == null)
+ {
+ regs = new ServiceRegistration[] { reg };
+ }
+ else
+ {
+ ServiceRegistration[] newRegs = new ServiceRegistration[regs.length + 1];
+ System.arraycopy(regs, 0, newRegs, 0, regs.length);
+ newRegs[regs.length] = reg;
+ regs = newRegs;
+ }
+ return regs;
+ }
+
+ private static ServiceRegistration[] removeServiceRegistration(
+ ServiceRegistration[] regs, ServiceRegistration reg)
+ {
+ for (int i = 0; (regs != null) && (i < regs.length); i++)
+ {
+ if (regs[i].equals(reg))
+ {
+ // If this is the only usage, then point to empty list.
+ if ((regs.length - 1) == 0)
+ {
+ regs = new ServiceRegistration[0];
+ }
+ // Otherwise, we need to do some array copying.
+ else
+ {
+ ServiceRegistration[] newRegs = new ServiceRegistration[regs.length - 1];
+ System.arraycopy(regs, 0, newRegs, 0, i);
+ if (i < newRegs.length)
+ {
+ System.arraycopy(
+ regs, i + 1, newRegs, i, newRegs.length - i);
+ }
+ regs = newRegs;
+ }
+ }
+ }
+ return regs;
+ }
+
+ public synchronized void addServiceListener(ServiceListener l)
+ {
+ m_serviceListener = ServiceListenerMulticaster.add(m_serviceListener, l);
+ }
+
+ public synchronized void removeServiceListener(ServiceListener l)
+ {
+ m_serviceListener = ServiceListenerMulticaster.remove(m_serviceListener, l);
+ }
+
+ protected void fireServiceChanged(ServiceEvent event)
+ {
+ // Grab a copy of the listener list.
+ ServiceListener listener = m_serviceListener;
+ // If not null, then dispatch event.
+ if (listener != null)
+ {
+ m_serviceListener.serviceChanged(event);
+ }
+ }
+
+ private static class ServiceListenerMulticaster implements ServiceListener
+ {
+ protected ServiceListener m_a = null, m_b = null;
+
+ protected ServiceListenerMulticaster(ServiceListener a, ServiceListener b)
+ {
+ m_a = a;
+ m_b = b;
+ }
+
+ public void serviceChanged(ServiceEvent e)
+ {
+ m_a.serviceChanged(e);
+ m_b.serviceChanged(e);
+ }
+
+ public static ServiceListener add(ServiceListener a, ServiceListener b)
+ {
+ if (a == null)
+ {
+ return b;
+ }
+ else if (b == null)
+ {
+ return a;
+ }
+ else
+ {
+ return new ServiceListenerMulticaster(a, b);
+ }
+ }
+
+ public static ServiceListener remove(ServiceListener a, ServiceListener b)
+ {
+ if ((a == null) || (a == b))
+ {
+ return null;
+ }
+ else if (a instanceof ServiceListenerMulticaster)
+ {
+ return add(
+ remove(((ServiceListenerMulticaster) a).m_a, b),
+ remove(((ServiceListenerMulticaster) a).m_b, b));
+ }
+ else
+ {
+ return a;
+ }
+ }
+ }
+
+ private static UsageCount getUsageCount(UsageCount[] usages, ServiceReference ref)
+ {
+ for (int i = 0; (usages != null) && (i < usages.length); i++)
+ {
+ if (usages[i].m_ref.equals(ref))
+ {
+ return usages[i];
+ }
+ }
+ return null;
+ }
+
+ private static UsageCount[] addUsageCount(UsageCount[] usages, ServiceReference ref, Object svcObj)
+ {
+ UsageCount usage = new UsageCount();
+ usage.m_ref = ref;
+ usage.m_svcObj = svcObj;
+ usage.m_count++;
+
+ if (usages == null)
+ {
+ usages = new UsageCount[] { usage };
+ }
+ else
+ {
+ UsageCount[] newUsages = new UsageCount[usages.length + 1];
+ System.arraycopy(usages, 0, newUsages, 0, usages.length);
+ newUsages[usages.length] = usage;
+ usages = newUsages;
+ }
+ return usages;
+ }
+
+ private static UsageCount[] removeUsageCount(UsageCount[] usages, ServiceReference ref)
+ {
+ for (int i = 0; (usages != null) && (i < usages.length); i++)
+ {
+ if (usages[i].m_ref.equals(ref))
+ {
+ // If this is the only usage, then point to empty list.
+ if ((usages.length - 1) == 0)
+ {
+ usages = new UsageCount[0];
+ }
+ // Otherwise, we need to do some array copying.
+ else
+ {
+ UsageCount[] newUsages= new UsageCount[usages.length - 1];
+ System.arraycopy(usages, 0, newUsages, 0, i);
+ if (i < newUsages.length)
+ {
+ System.arraycopy(
+ usages, i + 1, newUsages, i, newUsages.length - i);
+ }
+ usages = newUsages;
+ }
+ }
+ }
+
+ return usages;
+ }
+
+ private static class UsageCount
+ {
+ public int m_count = 0;
+ public ServiceReference m_ref = null;
+ public Object m_svcObj = null;
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/framework/StartLevelActivator.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/StartLevelActivator.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/StartLevelActivator.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/StartLevelActivator.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.framework;
+
+import org.osgi.framework.*;
+
+class StartLevelActivator implements BundleActivator
+{
+ private Felix m_felix = null;
+ private ServiceRegistration m_reg = null;
+
+ public StartLevelActivator(Felix felix)
+ {
+ m_felix = felix;
+ }
+
+ public void start(BundleContext context) throws Exception
+ {
+ m_reg = context.registerService(
+ org.osgi.service.startlevel.StartLevel.class.getName(),
+ new StartLevelImpl(m_felix),
+ null);
+ }
+
+ public void stop(BundleContext context) throws Exception
+ {
+ m_reg.unregister();
+ }
+}