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 [12/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/o...

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/DispatchQueue.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/DispatchQueue.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/DispatchQueue.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/DispatchQueue.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,420 @@
+/*
+ *   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.util;
+
+import java.util.*;
+
+import org.apache.osgi.framework.LogWrapper;
+
+/**
+ * This class implements an event dispatching queue to simplify delivering
+ * events to a list of event listener. To use this class, simply create an
+ * instance and use it to keep track of your event listeners, much like
+ * <tt>javax.swing.event.EventListenerList</tt>. To dispatch an event,
+ * simply create an instance of a <tt>Dispatcher</tt> and pass the instance
+ * to <tt>DispatchQueue.dispatch()</tt> method, for example:
+ * <pre>
+ *  Dispatcher d = new Dispatcher() {
+ *      public void dispatch(EventListener l, Object eventObj)
+ *      {
+ *          ((FooListener) l).fooXXX((FooEvent) eventObj);
+ *      }
+ *  };
+ *  FooEvent event = new FooEvent(this);
+ *  dispatchQueue.dispatch(d, FooListener.class, event);
+ * </pre>
+ * In the above code substitute a specific listener and event for the
+ * <tt>Foo</tt> listener and event. Since <tt>Dispatcher</tt>s are
+ * reusable, it is probably a good idea to create one for each type of
+ * event to be delivered and just reuse them everytime to avoid unnecessary
+ * memory allocation.
+ * <p>
+ * Currently, the <tt>DispatchQueue</tt> creates an internal thread with
+ * which all events are delivered; this means that events are never delivered
+ * using the caller's thread.
+**/
+public class DispatchQueue
+{
+    // Representation of an empty listener list.
+    private static final Object[] m_emptyList = new Object[0];
+
+    // The event listeners for a particular queue instance.
+    private Object[] m_listeners = m_emptyList;
+
+    // A single thread is used to deliver events for all dispatchers.
+    private static Thread m_thread = null;
+    private static String m_threadLock = "thread lock";
+    private static boolean m_stopping = false;
+    private static boolean m_stopped = false;
+
+    // List of dispatch requests.
+    private static final ArrayList m_requestList = new ArrayList();
+    // Cached dispatch requests to avoid memory allocation.
+    private static final ArrayList m_requestCache = new ArrayList();
+    // The logger for dispatch queue.
+    private static LogWrapper m_logger = null;
+
+    /**
+     * Constructs a dispatch queue and starts a dispather thread if
+     * necessary.
+    **/
+    public DispatchQueue(LogWrapper logger)
+    {
+        synchronized (m_threadLock)
+        {
+            // Start event dispatching thread if necessary.
+            if (m_thread == null)
+            {
+                m_logger = logger;
+                m_thread = new Thread(new Runnable() {
+                    public void run()
+                    {
+                        DispatchQueue.run();
+                    }
+                }, "FelixDispatchQueue");
+                m_thread.start();
+            }
+        }
+    }
+
+    /**
+     * Terminates the dispatching thread for a graceful shutdown
+     * of the dispatching queue; the caller will block until the
+     * dispatching thread has completed all pending dispatches.
+     * Since there is only one thread per all instances of
+     * <tt>DispatchQueue</tt>, this method should only be called
+     * prior to exiting the JVM.
+    **/
+    public static void shutdown()
+    {
+        synchronized (m_threadLock)
+        {
+            // Return if already stopped.
+            if (m_stopped)
+            {
+                return;
+            }
+
+            // Signal dispatch thread.
+            m_stopping = true;
+            synchronized (m_requestList)
+            {
+                m_requestList.notify();
+            }
+
+            // Wait for dispatch thread to stop.
+            while (!m_stopped)
+            {
+                try {
+                    m_threadLock.wait();
+                } catch (InterruptedException ex) {
+                }
+            }
+        }
+    }
+
+    public static LogWrapper getLogger()
+    {
+        return m_logger;
+    }
+
+    /**
+     * Returns a pointer to the array of event listeners. The array stores pairs
+     * of associated <tt>Class</tt> and <tt>EventListener</tt> objects; a pair
+     * corresponds to the arguments passed in to the <tt>addListener()</tt> method.
+     * Even numbered array elements are the class object and odd numbered elements
+     * are the corresponding event listener instance.
+     *
+     * @return guaranteed to return a non-null object array.
+    **/
+    public Object[] getListeners()
+    {
+        return m_listeners;
+    }
+
+    /**
+     * Returns the listener if it is already in the dispatch queue.
+     * @param clazz the class of the listener to find.
+     * @param l the listener instance to find.
+     * @return the listener instance or <tt>null</tt> if the listener was
+     *         not found.
+    **/
+    public EventListener getListener(Class clazz, EventListener l)
+    {
+        // Verify listener.
+        if (l == null)
+        {
+            throw new IllegalArgumentException("Listener is null");
+        }
+        else if (!clazz.isInstance(l))
+        {
+            throw new IllegalArgumentException(
+                "Listener not of type " + clazz.getName());
+        }
+
+        // Lock the object.
+        synchronized (this)
+        {
+            // Try to find the instance in our list.
+            for (int i = 0; i < m_listeners.length; i += 2)
+            {
+                if ((m_listeners[i] == clazz) &&
+                    (m_listeners[i + 1].equals(l)))
+                {
+                    return (EventListener) m_listeners[i + 1];
+                }
+            }
+        }
+        
+        return null;
+    }
+
+    /**
+     * Adds a listener to the dispatch queue's listener list; the listener
+     * is then able to receive events.
+     *
+     * @param clazz the class object associated with the event listener type.
+     * @param l the instance of the event listener to add.
+    **/
+    public void addListener(Class clazz, EventListener l)
+    {
+        // Verify listener.
+        if (l == null)
+        {
+            throw new IllegalArgumentException("Listener is null");
+        }
+        else if (!clazz.isInstance(l))
+        {
+            throw new IllegalArgumentException(
+                "Listener not of type " + clazz.getName());
+        }
+
+        // Lock the object.
+        synchronized (this)
+        {
+            // If we have no listeners, then just add the new listener.
+            if (m_listeners == m_emptyList)
+            {
+                m_listeners = new Object[] { clazz, l };
+            }
+            // Otherwise, we need to do some array copying.
+            // Notice, the old array is always valid, so if
+            // the dispatch thread is in the middle of a dispatch,
+            // then it has a reference to the old listener array
+            // and is not affected by the new value.
+            else
+            {
+                Object[] newList = new Object[m_listeners.length + 2];
+                System.arraycopy(m_listeners, 0, newList, 0, m_listeners.length);
+                newList[m_listeners.length] = clazz;
+                newList[m_listeners.length + 1] = l;
+                m_listeners = newList;
+            }
+        }
+    }
+
+    /**
+     * Removes a listener from the dispatch queue's listener list; the listener
+     * is no longer able to receive events.
+     *
+     * @param clazz the class object associated with the event listener type.
+     * @param l the instance of the event listener to remove.
+    **/
+    public void removeListener(Class clazz, EventListener l)
+    {
+        // Verify listener.
+        if (l == null)
+        {
+            throw new IllegalArgumentException("Listener is null");
+        }
+        else if (!clazz.isInstance(l))
+        {
+            throw new IllegalArgumentException(
+                "Listener not of type " + clazz.getName());
+        }
+
+        // Lock the object.
+        synchronized (this)
+        {
+            // Try to find the instance in our list.
+            int idx = -1;
+            for (int i = 0; i < m_listeners.length; i += 2)
+            {
+                if ((m_listeners[i] == clazz) &&
+                    (m_listeners[i + 1].equals(l)))
+                {
+                    idx = i;
+                    break;
+                }
+            }
+
+            // If we have the instance, then remove it.
+            if (idx >= 0)
+            {
+                // If this is the last listener, then point to empty list.
+                if ((m_listeners.length - 2) == 0)
+                {
+                    m_listeners = m_emptyList;
+                }
+                // Otherwise, we need to do some array copying.
+                // Notice, the old array is always valid, so if
+                // the dispatch thread is in the middle of a dispatch,
+                // then it has a reference to the old listener array
+                // and is not affected by the new value.
+                else
+                {
+                    Object[] newList  = new Object[m_listeners.length - 2];
+                    System.arraycopy(m_listeners, 0, newList, 0, idx);
+                    if (idx < newList.length)
+                    {
+                        System.arraycopy(m_listeners, idx + 2, newList, idx,
+                            newList.length - idx);
+                    }
+                    m_listeners = newList;
+                }
+            }
+        }
+    }
+
+    /**
+     * Dispatches an event to a set of event listeners using a specified
+     * dispatcher object.
+     *
+     * @param d the dispatcher used to actually dispatch the event; this
+     *          varies according to the type of event listener.
+     * @param clazz the class associated with the target event listener type;
+     *              only event listeners of this type will receive the event.
+     * @param eventObj the actual event object to dispatch.
+    **/
+    public void dispatch(Dispatcher d, Class clazz, EventObject eventObj)
+    {
+        dispatch(m_listeners, d, clazz, eventObj);
+    }
+
+    protected void dispatch(
+        Object[] listeners, Dispatcher d, Class clazz, EventObject eventObj)
+    {
+        // If dispatch thread is stopped, then ignore dispatch request.
+        if (m_stopped)
+        {
+            return;
+        }
+
+        // First get a dispatch request from the cache or
+        // create one if necessary.
+        DispatchRequest dr = null;
+        synchronized (m_requestCache)
+        {
+            if (m_requestCache.size() > 0)
+                dr = (DispatchRequest) m_requestCache.remove(0);
+            else
+                dr = new DispatchRequest();
+        }
+
+        // Initialize dispatch request.
+        dr.m_listeners = listeners;
+        dr.m_dispatcher = d;
+        dr.m_clazz = clazz;
+        dr.m_eventObj = eventObj;
+
+        // Lock the request list.
+        synchronized (m_requestList)
+        {
+            // Add our request to the list.
+            m_requestList.add(dr);
+            // Notify the dispatch thread that there is
+            // work to do.
+            m_requestList.notify();
+        }
+    }
+
+    private static void run()
+    {
+        DispatchRequest dr = null;
+        while (true)
+        {
+            // Lock the request list so we can try to get a
+            // dispatch request from it.
+            synchronized (m_requestList)
+            {
+                // Wait while there are no requests to dispatch. If the
+                // dispatcher thread is supposed to stop, then let the
+                // dispatcher thread exit the loop and stop.
+                while ((m_requestList.size() == 0) && !m_stopping)
+                {
+                    // Wait until some signals us for work.
+                    try {
+                        m_requestList.wait();
+                    } catch (InterruptedException ex) {
+                        m_logger.log(LogWrapper.LOG_ERROR, "DispatchQueue: Thread interrupted.", ex);
+                    }
+                }
+
+                // If there are no events to dispatch and shutdown
+                // has been called then exit, otherwise dispatch event.
+                if ((m_requestList.size() == 0) && (m_stopping))
+                {
+                    synchronized (m_threadLock)
+                    {
+                        m_stopped = true;
+                        m_threadLock.notifyAll();
+                    }
+                    return;
+                }
+
+                // Get the dispatch request.
+                dr = (DispatchRequest) m_requestList.remove(0);
+            }
+
+            // Deliver event outside of synchronized block
+            // so that we don't block other requests from being
+            // queued during event processing.
+
+            // Try to dispatch to the listeners.
+            if (dr.m_listeners.length > 0)
+            {
+                // Notify appropriate listeners.
+                for (int i = dr.m_listeners.length - 2; i >= 0; i -= 2)
+                {
+                    if (dr.m_listeners[i] == dr.m_clazz)
+                    {
+                        try {
+                            dr.m_dispatcher.dispatch(
+                                (EventListener) dr.m_listeners[i + 1], dr.m_eventObj);
+                        } catch (Throwable th) {
+                            m_logger.log(LogWrapper.LOG_ERROR, "DispatchQueue: Error during dispatch.", th);
+                        }
+                    }
+                }
+            }
+
+            // Put dispatch request in cache.
+            synchronized (m_requestCache)
+            {
+                m_requestCache.add(dr);
+            }
+        }
+    }
+
+    private static class DispatchRequest
+    {
+        public Object[] m_listeners = null;
+        public Dispatcher m_dispatcher = null;
+        public Class m_clazz = null;
+        public EventObject m_eventObj = null;
+    }
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/Dispatcher.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/Dispatcher.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/Dispatcher.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/Dispatcher.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,51 @@
+/*
+ *   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.util;
+
+import java.util.EventListener;
+import java.util.EventObject;
+
+/**
+ * This interface is used by <tt>DispatchQueue</tt> to dispatch events.
+ * Generally speaking, each type of event to dispatch will have an instance
+ * of a <tt>Dispatcher</tt> so that the dispatch queue can dispatch to
+ * the appropriate listener method for the specific listener type,
+ * for example:
+ * <pre>
+ *  Dispatcher d = new Dispatcher() {
+ *      public void dispatch(EventListener l, EventObject eventObj)
+ *      {
+ *          ((FooListener) l).fooXXX((FooEvent) eventObj);
+ *      }
+ *  };
+ *  FooEvent event = new FooEvent(this);
+ *  dispatchQueue.dispatch(d, FooListener.class, event);
+ * </pre>
+ * In the above code substitute a specific listener and event for the
+ * <tt>Foo</tt> listener and event. <tt>Dispatcher</tt>s can be reused, so
+ * it is a good idea to cache them to avoid unnecessary memory allocations.
+**/
+public interface Dispatcher
+{
+    /**
+     * Dispatch an event to a specified event listener.
+     *
+     * @param l the event listener to receive the event.
+     * @param eventObj the event to dispatch.
+    **/
+    public void dispatch(EventListener l, EventObject eventObj);
+}

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/FelixConstants.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/FelixConstants.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/FelixConstants.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/FelixConstants.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,60 @@
+/*
+ *   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.util;
+
+public interface FelixConstants extends org.osgi.framework.Constants
+{
+    // Framework constants and values.
+    public static final String FRAMEWORK_VERSION_VALUE = "4.0";
+    public static final String FRAMEWORK_VENDOR_VALUE = "Apache";
+
+    // Framework constants and values.
+    public static final String FELIX_VERSION_PROPERTY = "felix.version";
+    public static final String FELIX_VERSION_VALUE = "2.0.0.alpha8";
+
+    // Miscellaneous manifest constants.
+    public static final String DIRECTIVE_SEPARATOR = ":=";
+    public static final String ATTRIBUTE_SEPARATOR = "=";
+    public static final String CLASS_PATH_SEPARATOR = ",";
+    public static final String CLASS_PATH_DOT = ".";
+    public static final String PACKAGE_SEPARATOR = ";";
+    public static final String VERSION_SEGMENT_SEPARATOR = ".";
+    public static final int VERSION_SEGMENT_COUNT = 3;
+
+    // Miscellaneous OSGi constants.
+    public static final String BUNDLE_URL_PROTOCOL = "bundle";
+
+    // Miscellaneous framework configuration property names.
+    public static final String AUTO_INSTALL_PROP = "felix.auto.install";
+    public static final String AUTO_START_PROP = "felix.auto.start";
+    public static final String EMBEDDED_EXECUTION_PROP = "felix.embedded.execution";
+    public static final String STRICT_OSGI_PROP = "felix.strict.osgi";
+    public static final String CACHE_CLASS_PROP = "felix.cache.class";
+    public static final String FRAMEWORK_STARTLEVEL_PROP
+        = "felix.startlevel.framework";
+    public static final String BUNDLE_STARTLEVEL_PROP
+        = "felix.startlevel.bundle";
+
+    // Start level-related constants.
+    public static final int FRAMEWORK_INACTIVE_STARTLEVEL = 0;
+    public static final int FRAMEWORK_DEFAULT_STARTLEVEL = 1;
+    public static final int SYSTEMBUNDLE_DEFAULT_STARTLEVEL = 0;
+    public static final int BUNDLE_DEFAULT_STARTLEVEL = 1;
+
+    // Miscellaneous properties values.
+    public static final String FAKE_URL_PROTOCOL_VALUE = "location:";
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/FelixDispatchQueue.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/FelixDispatchQueue.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/FelixDispatchQueue.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/FelixDispatchQueue.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,147 @@
+/*
+ *   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.util;
+
+import java.util.EventListener;
+import java.util.EventObject;
+
+import org.apache.osgi.framework.LogWrapper;
+import org.osgi.framework.*;
+
+/**
+ * This is a subclass of <tt>DispatchQueue</tt> that specifically adds support
+ * for <tt>SynchronousBundleListener</tt>s; the OSGi specification
+ * says that synchronous bundle listeners should receive their events
+ * immediately, i.e., they should not be delivered on a separate thread
+ * like is the case with the <tt>DispatchQueue</tt>. To achieve this
+ * functionality, this class overrides the dispatch method to automatically
+ * fire any bundle events to synchronous bundle listeners using the
+ * calling thread. In order to ensure that synchronous bundle listeners
+ * do not receive an event twice, it wraps the passed in <tt>Dipatcher</tt>
+ * instance so that it filters synchronous bundle listeners.
+**/
+public class FelixDispatchQueue extends DispatchQueue
+{
+    public FelixDispatchQueue(LogWrapper logger)
+    {
+        super(logger);
+    }
+
+    /**
+     * Dispatches an event to a set of event listeners using a specified
+     * dispatcher object. This overrides the definition of the super class
+     * to deliver events to <tt>ServiceListener</tt>s and
+     * <tt>SynchronousBundleListener</tt>s using
+     * the calling thread instead of the event dispatching thread. All
+     * other events are still delivered asynchronously.
+     *
+     * @param dispatcher the dispatcher used to actually dispatch the event; this
+     *          varies according to the type of event listener.
+     * @param clazz the class associated with the target event listener type;
+     *              only event listeners of this type will receive the event.
+     * @param eventObj the actual event object to dispatch.
+    **/
+    public void dispatch(Dispatcher dispatcher, Class clazz, EventObject eventObj)
+    {
+        Object[] listeners = getListeners();
+
+        // If this is an event for service listeners, then dispatch it
+        // immediately since service events are never asynchronous.
+        if ((clazz == ServiceListener.class) && (listeners.length > 0))
+        {
+            // Notify appropriate listeners.
+            for (int i = listeners.length - 2; i >= 0; i -= 2)
+            {
+                // If the original listener is a synchronous bundle listener
+                // or a service listener, then dispatch event immediately
+                // per the specification.
+                ListenerWrapper lw = (ListenerWrapper) listeners[i + 1];
+                if (lw.getListenerClass() == ServiceListener.class)
+                {
+                    try {
+                        dispatcher.dispatch(
+                            (EventListener) lw, eventObj);
+                    } catch (Throwable th) {
+                        getLogger().log(
+                            LogWrapper.LOG_ERROR,
+                            "FelixDispatchQueue: Error during dispatch.", th);
+                    }
+                }
+            }
+        }
+        // Dispatch bundle events to synchronous bundle listeners immediately,
+        // but deliver to standard bundle listeners asynchronously.
+        else if ((clazz == BundleListener.class) && (listeners.length > 0))
+        {
+            // Notify appropriate listeners.
+            for (int i = listeners.length - 2; i >= 0; i -= 2)
+            {
+                // If the original listener is a synchronous bundle listener,
+                // then dispatch event immediately per the specification.
+                ListenerWrapper lw = (ListenerWrapper) listeners[i + 1];
+                if (lw.getListenerClass() == SynchronousBundleListener.class)
+                {
+                    try {
+                        dispatcher.dispatch(
+                            (EventListener) lw, eventObj);
+                    } catch (Throwable th) {
+                        getLogger().log(
+                            LogWrapper.LOG_ERROR,
+                            "FelixDispatchQueue: Error during dispatch.", th);
+                    }
+                }
+            }
+
+            // Wrap the dispatcher so that it ignores synchronous
+            // bundle listeners since they have already been dispatched.
+            IgnoreSynchronousDispatcher ignoreDispatcher = new IgnoreSynchronousDispatcher();
+            ignoreDispatcher.setDispatcher(dispatcher);
+
+            // Dispatch the bundle listener asynchronously.
+            dispatch(listeners, ignoreDispatcher, clazz, eventObj);
+        }
+        // All other events are dispatched asynchronously.
+        else
+        {
+            dispatch(listeners, dispatcher, clazz, eventObj);
+        }
+    }
+
+    private static class IgnoreSynchronousDispatcher implements Dispatcher
+    {
+        private Dispatcher m_dispatcher = null;
+
+        public void setDispatcher(Dispatcher dispatcher)
+        {
+            m_dispatcher = dispatcher;
+        }
+
+        public void dispatch(EventListener l, EventObject eventObj)
+        {
+            if (l instanceof ListenerWrapper)
+            {
+                ListenerWrapper lw = (ListenerWrapper) l;
+                // Do not dispatch events to synchronous listeners,
+                // since they are dispatched immediately above.
+                if (!(lw.getListenerClass() == SynchronousBundleListener.class))
+                {
+                    m_dispatcher.dispatch(l, eventObj);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/FrameworkListenerWrapper.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/FrameworkListenerWrapper.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/FrameworkListenerWrapper.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/FrameworkListenerWrapper.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,55 @@
+/*
+ *   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.util;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.osgi.framework.*;
+
+public class FrameworkListenerWrapper extends ListenerWrapper implements FrameworkListener
+{
+    public FrameworkListenerWrapper(Bundle bundle, FrameworkListener l)
+    {
+        super(bundle, FrameworkListener.class, l);
+    }
+
+    public void frameworkEvent(final FrameworkEvent event)
+    {
+        // The spec says only active bundles receive asynchronous events,
+        // but we will include starting bundles too otherwise
+        // it is impossible to see everything.
+        if ((getBundle().getState() == Bundle.STARTING) ||
+            (getBundle().getState() == Bundle.ACTIVE))
+        {
+            if (System.getSecurityManager() != null)
+            {
+                AccessController.doPrivileged(new PrivilegedAction() {
+                    public Object run()
+                    {
+                        ((FrameworkListener) getListener()).frameworkEvent(event);
+                        return null;
+                    }
+                });
+            }
+            else
+            {
+                ((FrameworkListener) getListener()).frameworkEvent(event);
+            }
+        }
+    }
+}

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/IteratorToEnumeration.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/IteratorToEnumeration.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/IteratorToEnumeration.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/IteratorToEnumeration.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,44 @@
+/*
+ *   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.util;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+
+public class IteratorToEnumeration implements Enumeration
+{
+    private Iterator m_iter = null;
+
+    public IteratorToEnumeration(Iterator iter)
+    {
+        m_iter = iter;
+    }
+
+    public boolean hasMoreElements()
+    {
+        if (m_iter == null)
+            return false;
+        return m_iter.hasNext();
+    }
+
+    public Object nextElement()
+    {
+        if (m_iter == null)
+            return null;
+        return m_iter.next();
+    }
+}

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/LibraryInfo.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/LibraryInfo.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/LibraryInfo.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/LibraryInfo.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.util;
+
+import java.util.*;
+
+import org.osgi.framework.Constants;
+
+public class LibraryInfo
+{
+    private String m_name = null;
+    private String[] m_osnames = null;
+    private String[] m_osversions = null;
+    private String[] m_processors = null;
+    private String[] m_languages = null;
+
+    public LibraryInfo(String name, String[] osnames, String[] osversions,
+        String[] processors, String[] languages)
+    {
+        m_name = name;
+        m_osnames = osnames;
+        m_osversions = osversions;
+        m_processors = processors;
+        m_languages = languages;
+    }
+
+    public LibraryInfo(LibraryInfo library)
+    {
+        m_name = library.m_name;
+        m_osnames = library.m_osnames;
+        m_osversions = library.m_osversions;
+        m_processors = library.m_processors;
+        m_languages = library.m_languages;
+    }
+
+    public String getName()
+    {
+        return m_name;
+    }
+
+    public String[] getOSNames()
+    {
+        return m_osnames;
+    }
+
+    public String[] getOSVersions()
+    {
+        return m_osversions;
+    }
+
+    public String[] getProcessors()
+    {
+        return m_processors;
+    }
+
+    public static LibraryInfo[] parse(String s)
+    {
+        try
+        {
+            if ((s == null) || (s.length() == 0))
+            {
+                return null;
+            }
+
+            // The tokens are separated by semicolons and may include
+            // any number of libraries (whose name starts with a "/")
+            // along with one set of associated properties.
+            StringTokenizer st = new StringTokenizer(s, ";");
+            String[] libs = new String[st.countTokens()];
+            List osNameList = new ArrayList();
+            List osVersionList = new ArrayList();
+            List processorList = new ArrayList();
+            List languageList = new ArrayList();
+            int libCount = 0;
+            while (st.hasMoreTokens())
+            {
+                String token = st.nextToken().trim();
+                if (token.indexOf('=') < 0)
+                {
+                    // Remove the slash, if necessary.
+                    libs[libCount] = (token.charAt(0) == '/')
+                        ? token.substring(1)
+                        : token;
+                    libCount++;
+                }
+                else
+                {
+                    // Check for valid native library properties; defined as
+                    // a property name, an equal sign, and a value.
+                    StringTokenizer stProp = new StringTokenizer(token, "=");
+                    if (stProp.countTokens() != 2)
+                    {
+                        throw new IllegalArgumentException(
+                            "Bundle manifest native library entry malformed: " + token);
+                    }
+                    String property = stProp.nextToken().trim().toLowerCase();
+                    String value = stProp.nextToken().trim();
+                    
+                    // Values may be quoted, so remove quotes if present.
+                    if (value.charAt(0) == '"')
+                    {
+                        // This should always be true, otherwise the
+                        // value wouldn't be properly quoted, but we
+                        // will check for safety.
+                        if (value.charAt(value.length() - 1) == '"')
+                        {
+                            value = value.substring(1, value.length() - 1);
+                        }
+                        else
+                        {
+                            value = value.substring(1);
+                        }
+                    }
+                    // Add the value to its corresponding property list.
+                    if (property.equals(Constants.BUNDLE_NATIVECODE_OSNAME))
+                    {
+                        osNameList.add(value);
+                    }
+                    else if (property.equals(Constants.BUNDLE_NATIVECODE_OSVERSION))
+                    {
+                        osVersionList.add(value);
+                    }
+                    else if (property.equals(Constants.BUNDLE_NATIVECODE_PROCESSOR))
+                    {
+                        processorList.add(value);
+                    }
+                    else if (property.equals(Constants.BUNDLE_NATIVECODE_LANGUAGE))
+                    {
+                        languageList.add(value);
+                    }
+                }
+            }
+
+            if (libCount == 0)
+            {
+                return null;
+            }
+
+            LibraryInfo[] libraries = new LibraryInfo[libCount];
+            for (int i = 0; i < libCount; i++)
+            {
+                libraries[i] =
+                    new LibraryInfo(
+                        libs[i],
+                        (String[]) osNameList.toArray(new String[0]),
+                        (String[]) osVersionList.toArray(new String[0]),
+                        (String[]) processorList.toArray(new String[0]),
+                        (String[]) languageList.toArray(new String[0]));
+            }
+
+            return libraries;
+
+        }
+        catch (RuntimeException ex)
+        {
+            ex.printStackTrace();
+            throw ex;
+        }
+    }
+
+    public String toString()
+    {
+        return m_name;
+    }
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/ListenerWrapper.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/ListenerWrapper.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/ListenerWrapper.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/ListenerWrapper.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,66 @@
+/*
+ *   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.util;
+
+import java.util.EventListener;
+
+import org.osgi.framework.Bundle;
+
+public class ListenerWrapper
+{
+    // The bundle associated with the listener.
+    private Bundle m_bundle = null;
+    // Listener class.
+    private Class m_class = null;
+    // The original listener.
+    private EventListener m_listener = null;
+
+    public ListenerWrapper(Bundle bundle, Class clazz, EventListener l)
+    {
+        m_bundle = bundle;
+        m_class = clazz;
+        m_listener = l;
+    }
+
+    public Bundle getBundle()
+    {
+        return m_bundle;
+    }
+
+    protected Class getListenerClass()
+    {
+        return m_class;
+    }
+
+    protected EventListener getListener()
+    {
+        return m_listener;
+    }
+
+    public boolean equals(Object obj)
+    {
+        if (obj instanceof ListenerWrapper)
+        {
+            return (((ListenerWrapper) obj).m_listener == m_listener);
+        }
+        else if (obj instanceof EventListener)
+        {
+            return (obj == m_listener);
+        }
+        return false;
+    }
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/MapToDictionary.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/MapToDictionary.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/MapToDictionary.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/MapToDictionary.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,92 @@
+/*
+ *   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.util;
+
+import java.util.*;
+
+
+/**
+ * This is a simple class that implements a <tt>Dictionary</tt>
+ * from a <tt>Map</tt>. The resulting dictionary is immutatable.
+**/
+public class MapToDictionary extends Dictionary
+{
+    /**
+     * Map source.
+    **/
+    private Map m_map = null;
+
+    public MapToDictionary(Map map)
+    {
+        m_map = map;
+    }
+
+    public Enumeration elements()
+    {
+        if (m_map == null)
+        {
+            return null;
+        }
+        return new IteratorToEnumeration(m_map.values().iterator());
+    }
+
+    public Object get(Object key)
+    {
+        if (m_map == null)
+        {
+            return null;
+        }
+        return m_map.get(key);
+    }
+
+    public boolean isEmpty()
+    {
+        if (m_map == null)
+        {
+            return true;
+        }
+        return m_map.isEmpty();
+    }
+
+    public Enumeration keys()
+    {
+        if (m_map == null)
+        {
+            return null;
+        }
+        return new IteratorToEnumeration(m_map.keySet().iterator());
+    }
+
+    public Object put(Object key, Object value)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public Object remove(Object key)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public int size()
+    {
+        if (m_map == null)
+        {
+            return 0;
+        }
+        return m_map.size();
+    }
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/MutablePropertyResolver.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/MutablePropertyResolver.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/MutablePropertyResolver.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/MutablePropertyResolver.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,22 @@
+/*
+ *   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.util;
+
+public interface MutablePropertyResolver extends PropertyResolver
+{
+    public String put(String key, String value);
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/MutablePropertyResolverImpl.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/MutablePropertyResolverImpl.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/MutablePropertyResolverImpl.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/MutablePropertyResolverImpl.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,44 @@
+/*
+ *   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.util;
+
+import java.util.Map;
+
+public class MutablePropertyResolverImpl implements MutablePropertyResolver
+{
+    private Map m_props = null;
+    
+    public MutablePropertyResolverImpl(Map props)
+    {
+        m_props = props;
+    }
+
+    public synchronized String put(String key, String value)
+    {
+        return (String) m_props.put(key, value);
+    }
+
+    public synchronized String get(String key)
+    {
+        return (String) m_props.get(key);
+    }
+
+    public synchronized String[] getKeys()
+    {
+        return (String[]) m_props.keySet().toArray(new String[0]);
+    }
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/ObjectInputStreamX.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/ObjectInputStreamX.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/ObjectInputStreamX.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/ObjectInputStreamX.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,53 @@
+/*
+ *   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.util;
+
+import java.io.*;
+
+/**
+ * The ObjectInputStreamX class is a simple extension to the ObjectInputStream
+ * class.  The purpose of ObjectInputStreamX is to allow objects to be deserialized
+ * when their classes are not in the CLASSPATH (e.g., in a JAR file).
+ */
+public class ObjectInputStreamX extends ObjectInputStream
+{
+    private ClassLoader m_loader = null;
+
+    /**
+     * Construct an ObjectInputStreamX for the specified InputStream and the specified
+     * ClassLoader.
+     * @param in the input stream to read.
+     * @param loader the class loader used to resolve classes.
+     */
+    public ObjectInputStreamX(InputStream in, ClassLoader loader)
+        throws IOException, StreamCorruptedException
+    {
+        super(in);
+        this.m_loader = loader;
+    }
+
+    /**
+     * By overloading this method, the ObjectInputStreamX can resolve a class
+     * from the class loader that was passed into it at construction time.
+     */
+    protected Class resolveClass(ObjectStreamClass v)
+        throws IOException, ClassNotFoundException
+    {
+        Class clazz = m_loader.loadClass(v.getName());
+        return clazz;
+    }
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/PropertyResolver.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/PropertyResolver.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/PropertyResolver.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/PropertyResolver.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,23 @@
+/*
+ *   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.util;
+
+public interface PropertyResolver
+{
+    public String get(String key);
+    public String[] getKeys();
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/ServiceListenerWrapper.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/ServiceListenerWrapper.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/ServiceListenerWrapper.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/ServiceListenerWrapper.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,114 @@
+/*
+ *   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.util;
+
+import java.security.*;
+
+import org.osgi.framework.*;
+
+public class ServiceListenerWrapper extends ListenerWrapper implements ServiceListener
+{
+    // LDAP query filter.
+    private Filter m_filter = null;
+    // Remember the security context.
+    private AccessControlContext m_acc = null;
+
+    public ServiceListenerWrapper(Bundle bundle, ServiceListener l, Filter filter)
+    {
+        super(bundle, ServiceListener.class, l);
+        m_filter = filter;
+
+        // Remember security context for filtering
+        // events based on security.
+        if (System.getSecurityManager() != null)
+        {
+            m_acc = AccessController.getContext();
+        }
+    }
+
+    public void setFilter(Filter filter)
+    {
+        m_filter = filter;
+    }
+    
+    public void serviceChanged(final ServiceEvent event)
+    {
+        // Service events should be delivered to STARTING,
+        // STOPPING, and ACTIVE bundles.
+        if ((getBundle().getState() != Bundle.STARTING) &&
+            (getBundle().getState() != Bundle.STOPPING) &&
+            (getBundle().getState() != Bundle.ACTIVE))
+        {
+            return;
+        }
+
+        // Check that the bundle has permission to get at least
+        // one of the service interfaces; the objectClass property
+        // of the service stores its service interfaces.
+        ServiceReference ref = event.getServiceReference();
+        String[] objectClass = (String[]) ref.getProperty(Constants.OBJECTCLASS);
+
+        // On the safe side, if there is no objectClass property
+        // then ignore event altogether.
+        if (objectClass != null)
+        {
+            boolean hasPermission = false;
+            if (m_acc != null)
+            {
+                for (int i = 0;
+                    !hasPermission && (i < objectClass.length);
+                    i++)
+                {
+                    try {
+                        ServicePermission perm =
+                            new ServicePermission(
+                                objectClass[i], ServicePermission.GET);
+                        m_acc.checkPermission(perm);
+                        hasPermission = true;
+                    } catch (Exception ex) {
+                    }
+                }
+            }
+            else
+            {
+                hasPermission = true;
+            }
+
+            if (hasPermission)
+            {
+                // Dispatch according to the filter.
+                if ((m_filter == null) || m_filter.match(event.getServiceReference()))
+                {
+                    if (System.getSecurityManager() != null)
+                    {
+                        AccessController.doPrivileged(new PrivilegedAction() {
+                            public Object run()
+                            {
+                                ((ServiceListener) getListener()).serviceChanged(event);
+                                return null;
+                            }
+                        });
+                    }
+                    else
+                    {
+                        ((ServiceListener) getListener()).serviceChanged(event);
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/Util.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/Util.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/Util.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/Util.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.util;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Util
+{
+    /**
+     * Parses delimited string and returns an array containing the tokens. This
+     * parser obeys quotes, so the delimiter character will be ignored if it is
+     * inside of a quote. This method assumes that the quote character is not
+     * included in the set of delimiter characters.
+     * @param value the delimited string to parse.
+     * @param delim the characters delimiting the tokens.
+     * @return an array of string tokens or null if there were no tokens.
+    **/
+    public static String[] parseDelimitedString(String value, String delim)
+    {
+        if (value == null)
+        {
+           value = "";
+        }
+
+        List list = new ArrayList();
+
+        int CHAR = 1;
+        int DELIMITER = 2;
+        int STARTQUOTE = 4;
+        int ENDQUOTE = 8;
+
+        StringBuffer sb = new StringBuffer();
+
+        int expecting = (CHAR | DELIMITER | STARTQUOTE);
+        
+        for (int i = 0; i < value.length(); i++)
+        {
+            char c = value.charAt(i);
+
+            boolean isDelimiter = (delim.indexOf(c) >= 0);
+            boolean isQuote = (c == '"');
+
+            if (isDelimiter && ((expecting & DELIMITER) > 0))
+            {
+                list.add(sb.toString().trim());
+                sb.delete(0, sb.length());
+                expecting = (CHAR | DELIMITER | STARTQUOTE);
+            }
+            else if (isQuote && ((expecting & STARTQUOTE) > 0))
+            {
+                sb.append(c);
+                expecting = CHAR | ENDQUOTE;
+            }
+            else if (isQuote && ((expecting & ENDQUOTE) > 0))
+            {
+                sb.append(c);
+                expecting = (CHAR | STARTQUOTE | DELIMITER);
+            }
+            else if ((expecting & CHAR) > 0)
+            {
+                sb.append(c);
+            }
+            else
+            {
+                throw new IllegalArgumentException("Invalid delimited string: " + value);
+            }
+        }
+
+        if (sb.length() > 0)
+        {
+            list.add(sb.toString().trim());
+        }
+
+        return (String[]) list.toArray(new String[list.size()]);
+    }
+
+    /**
+     * Parses native code manifest headers.
+     * @param libStrs an array of native library manifest header
+     *        strings from the bundle manifest.
+     * @return an array of <tt>LibraryInfo</tt> objects for the
+     *         passed in strings.
+    **/
+    public static LibraryInfo[] parseLibraryStrings(String[] libStrs)
+        throws IllegalArgumentException
+    {
+        if (libStrs == null)
+        {
+            return null;
+        }
+
+        List libList = new ArrayList();
+
+        for (int i = 0; i < libStrs.length; i++)
+        {
+            LibraryInfo[] libs = LibraryInfo.parse(libStrs[i]);
+            for (int libIdx = 0;
+                (libs != null) && (libIdx < libs.length);
+                libIdx++)
+            {
+                libList.add(libs[libIdx]);
+            }
+        }
+
+        if (libList.size() == 0)
+        {
+            return null;
+        }
+
+        return (LibraryInfo[]) libList.toArray(new LibraryInfo[libList.size()]);
+    }
+
+    private static final byte encTab[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
+        0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
+        0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64,
+        0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+        0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31,
+        0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f };
+
+    private static final byte decTab[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1,
+        -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1,
+        -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+        18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29,
+        30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+        48, 49, 50, 51, -1, -1, -1, -1, -1 };
+
+    public static String base64Encode(String s) throws IOException
+    {
+        return encode(s.getBytes(), 0);
+    }
+
+    /**
+     * Encode a raw byte array to a Base64 String.
+     * 
+     * @param in Byte array to encode.
+     * @param len Length of Base64 lines. 0 means no line breaks.
+    **/
+    public static String encode(byte[] in, int len) throws IOException
+    {
+        ByteArrayOutputStream baos = null;
+        ByteArrayInputStream bais = null;
+        try
+        {
+            baos = new ByteArrayOutputStream();
+            bais = new ByteArrayInputStream(in);
+            encode(bais, baos, len);
+            // ASCII byte array to String
+            return (new String(baos.toByteArray()));
+        }
+        finally
+        {
+            if (baos != null)
+            {
+                baos.close();
+            }
+            if (bais != null)
+            {
+                bais.close();
+            }
+        }
+    }
+
+    public static void encode(InputStream in, OutputStream out, int len)
+        throws IOException
+    {
+
+        // Check that length is a multiple of 4 bytes
+        if (len % 4 != 0)
+        {
+            throw new IllegalArgumentException("Length must be a multiple of 4");
+        }
+
+        // Read input stream until end of file
+        int bits = 0;
+        int nbits = 0;
+        int nbytes = 0;
+        int b;
+
+        while ((b = in.read()) != -1)
+        {
+            bits = (bits << 8) | b;
+            nbits += 8;
+            while (nbits >= 6)
+            {
+                nbits -= 6;
+                out.write(encTab[0x3f & (bits >> nbits)]);
+                nbytes++;
+                // New line
+                if (len != 0 && nbytes >= len)
+                {
+                    out.write(0x0d);
+                    out.write(0x0a);
+                    nbytes -= len;
+                }
+            }
+        }
+
+        switch (nbits)
+        {
+            case 2:
+                out.write(encTab[0x3f & (bits << 4)]);
+                out.write(0x3d); // 0x3d = '='
+                out.write(0x3d);
+                break;
+            case 4:
+                out.write(encTab[0x3f & (bits << 2)]);
+                out.write(0x3d);
+                break;
+        }
+
+        if (len != 0)
+        {
+            if (nbytes != 0)
+            {
+                out.write(0x0d);
+                out.write(0x0a);
+            }
+            out.write(0x0d);
+            out.write(0x0a);
+        }
+    }
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/AttributeNotFoundException.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/AttributeNotFoundException.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/AttributeNotFoundException.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/AttributeNotFoundException.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,25 @@
+/*
+ *   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.util.ldap;
+
+public class AttributeNotFoundException extends EvaluationException
+{
+    public AttributeNotFoundException(String msg)
+    {
+        super(msg);
+    }
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Driver.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Driver.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Driver.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Driver.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,150 @@
+/*
+ *   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.util.ldap;
+
+import java.io.*;
+import java.util.*;
+
+public class Driver {
+
+    public static void main(String[] argv)
+    {
+    Mapper mapper = new DriverMapper();
+
+    if(argv== null || argv.length == 0) {
+        System.err.println("usage: Driver <ldap spec file>");
+        return;
+    }
+    LdapLexer lexer = new LdapLexer();
+    FileReader fr = null;
+    char[] line = null;
+    Evaluator engine = new Evaluator();
+
+    Parser parser = new Parser();
+//	parser.setDebug(System.out);
+
+    try {
+        File spec = new File(argv[0]);
+        fr = new FileReader(spec);
+
+        // The basic operation of the driver is:
+        // 1. read a line from the file
+        // 2. parse that line
+        // 3. print the resulting program
+        // 4. repeat 1 until eof
+
+        for(;;) {
+        line = getLine(fr);
+        if(line == null) break;
+        System.out.println("Driver: filter: "+new String(line));
+        CharArrayReader car = new CharArrayReader(line);
+        lexer.setReader(car);
+        parser.reset(lexer);
+        boolean status = false;
+        try {
+            status = parser.start();
+            if(!status) {
+            System.err.println("parse failed");
+            printErrorLocation(line,lexer.charno());
+            }
+        } catch (ParseException pe) {
+            System.err.println(pe.toString());
+            printErrorLocation(line,lexer.charno());
+        }
+        if(status) {
+            try {
+            engine.reset(parser.getProgram());
+//            System.out.println("Driver: program: "+engine.toString());
+            System.out.println("Driver: program: "+engine.toStringInfix());
+            System.out.println("Eval = " + engine.evaluate(mapper));
+            } catch (EvaluationException ee) {
+            System.err.print("Driver: ");
+            printEvaluationStack(engine.getOperands());
+            System.err.println(ee.toString());
+            }
+        }
+        }
+    } catch (Exception e) {
+        System.err.println(e.toString());
+        printErrorLocation(line,lexer.charno());
+        e.printStackTrace();
+    }
+    }
+
+    // Get a line of input at a time and return a char[] buffer
+    // containing the line
+
+    static char[] getLine(Reader reader) throws IOException
+    {
+    StringBuffer buf = new StringBuffer();
+    for(;;) {
+        int c = reader.read();
+        if(c == '\r') continue;
+        if(c < 0) {
+        if(buf.length() == 0) return null; // no more lines
+        break;
+        }
+        if(c == '\n') break;
+        buf.append((char)c);
+    }
+
+    char[] cbuf = new char[buf.length()];
+    buf.getChars(0,buf.length(),cbuf,0);
+    return cbuf;
+    }
+
+
+    static void printErrorLocation(char[] line, int charno)
+    {
+    System.err.print("|");
+    if(line != null) System.err.print(new String(line));
+    System.err.println("|");
+    for(int i=0;i<charno;i++) System.err.print(" ");
+    System.err.println("^");
+    }
+
+    // Report the final contents of the evaluation stack
+    static void printEvaluationStack(Stack stack)
+    {
+    System.err.print("Stack:");
+    // recast operands as Vector to make interior access easier
+    Vector operands = stack;
+    int len = operands.size();
+    for(int i=0;i<len;i++) System.err.print(" "+operands.elementAt(i));
+    System.err.println();
+    }
+
+}
+
+class DriverMapper implements Mapper {
+
+    Hashtable hash = new Hashtable();
+
+    public DriverMapper()
+    {
+        hash.put("cn","Babs Jensen");
+        hash.put("objectClass","Person");
+        hash.put("sn","Jensen");
+        hash.put("o","university of michigan");
+        hash.put("foo","bar");
+    }
+
+    public Object lookup(String key)
+    {
+        return hash.get(key);
+    }
+}

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/EvaluationException.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/EvaluationException.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/EvaluationException.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/EvaluationException.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.util.ldap;
+
+public class EvaluationException extends Exception
+{
+    private Class m_unsupportedType = null;
+
+    public EvaluationException(String msg)
+    {
+        super(msg);
+    }
+    
+    public EvaluationException(String msg, Class clazz)
+    {
+        super(msg);
+        m_unsupportedType = clazz;
+    }
+    
+    public boolean isUnsupportedType()
+    {
+        return (m_unsupportedType != null);
+    }
+    
+    public Class getUnsupportedType()
+    {
+        return m_unsupportedType;
+    }
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Evaluator.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Evaluator.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Evaluator.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Evaluator.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,186 @@
+/*
+ *   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.util.ldap;
+
+import java.util.Stack;
+import java.util.Vector;
+
+public class Evaluator {
+
+    Object[] program = null;
+    Stack operands = new Stack();
+    Mapper mapper = null;
+
+    public Evaluator()
+    {
+        reset();
+    }
+
+    public Evaluator(Object[] prog)
+    {
+        reset(prog);
+    }
+
+    public void reset()
+    {
+        program = null;
+        mapper = null;
+        operands.clear();
+    }
+
+    public void reset(Object[] prog)
+    {
+        reset();
+        setProgram(prog);
+    }
+
+    public void setProgram(Object[] prog)
+    {
+        program = prog;
+    }
+
+    public void setMapper(Mapper mapper)
+    {
+        this.mapper = mapper;
+    }
+
+    public Stack getOperands()
+    {
+        return operands;
+    }
+
+    public boolean evaluate(Mapper mapper) throws EvaluationException
+    {
+        try
+        {
+            // The following code is a little complicated because it
+            // is trying to deal with evaluating a given filter expression
+            // when it contains an attribute that does not exist in the
+            // supplied mapper. In such a situation the code below
+            // catches the "attribute not found" exception and inserts
+            // an instance of Unknown, which is used as a marker for
+            // non-existent attributes. The Unknown instance forces the
+            // operator to throw an "unsupported type" exception, which
+            // the code below converts into a FALSE and this has the effect
+            // of evaluating the subexpression that contained the
+            // non-existent attribute to FALSE. The rest of the filter
+            // expression evaluates normally. Any other exceptions are
+            // rethrown.
+            setMapper(mapper);
+            for (int i = 0; i < program.length; i++)
+            {
+                try
+                {
+                    Operator op = (Operator) program[i];
+                    op.execute(operands, mapper);
+//                    printAction(op); // for debug output
+                }
+                catch (AttributeNotFoundException ex)
+                {
+                    operands.push(new Unknown());
+                }
+                catch (EvaluationException ex)
+                {
+                    // If the exception is for an unsupported type of
+                    // type Unknown, then just push FALSE onto the
+                    // operand stack because this type will only appear
+                    // if an attribute was not found.
+                    if (ex.isUnsupportedType() &&
+                        (ex.getUnsupportedType() == Unknown.class))
+                    {
+                        operands.push(Boolean.FALSE);
+                    }
+                    // Otherwise, rethrow the exception.
+                    else
+                    {
+                        throw ex;
+                    }
+                }
+            }
+
+            if (operands.empty())
+            {
+                throw new EvaluationException(
+                    "Evaluation.evalute: final stack is empty");
+            }
+
+            Object result = operands.pop();
+
+            if (!operands.empty())
+            {
+                throw new EvaluationException(
+                    "Evaluation.evalute: final stack has more than one result");
+            }
+
+            if (!(result instanceof Boolean))
+            {
+                throw new EvaluationException(
+                    "Evaluation.evalute: final result is not Boolean");
+            }
+
+            return ((Boolean) result).booleanValue();
+        }
+        finally
+        {
+            // Clear the operands just in case an exception was thrown,
+            // otherwise stuff will be left in the stack.
+            operands.clear();
+        }
+    }
+
+    // For debugging; Dump the operator and stack
+    void printAction(Operator op)
+    {
+        System.err.println("Operator:"+op.toString());
+        System.err.print("Stack After:");
+        // recast operands as Vector to make interior access easier
+        Vector v = operands;
+        int len = v.size();
+        for (int i = 0; i < len; i++)
+            System.err.print(" " + v.elementAt(i));
+        System.err.println();
+    }
+
+    public String toString()
+    {
+        StringBuffer buf = new StringBuffer();
+        for (int i = 0; i < program.length; i++)
+        {
+            buf.append((i==0) ? "{" : ";");
+                buf.append(((Operator) program[i]).toString());
+        }
+        buf.append("}");
+        return buf.toString();
+    }
+
+    public String toStringInfix()
+    {
+        // First, we "evaluate" the program
+        // but for the purpose of re-constructing
+        // a parsetree.
+        operands.clear();
+        for (int i = 0; i < program.length; i++)
+        {
+            ((Operator) program[i]).buildTree(operands);
+        }
+        StringBuffer b = new StringBuffer();
+        Object result = operands.pop();
+        ((Operator)result).toStringInfix(b);
+        operands.clear();
+        return b.toString();
+    }
+}

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/LdapLexer.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/LdapLexer.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/LdapLexer.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/LdapLexer.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,98 @@
+/*
+ *   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.util.ldap;
+
+import java.io.IOException;
+import java.io.Reader;
+
+public class LdapLexer {
+
+    static final int EOF = -1;
+    static final int NOCHAR = 0; // signal no peeked char; different from EOF
+
+    public static final String WHITESPACE = " \t\n\r";
+
+    Reader reader = null;
+
+    int nextChar = NOCHAR; // last peeked character
+
+    public LdapLexer() {}
+
+    public LdapLexer(Reader r)
+    {
+    setReader(r);
+    charno = 1;
+    }
+
+    public void setReader(Reader r)
+    {
+    reader = r;
+    }
+
+    /*
+    The procedures get(),peek(),skipwhitespace(),getnw(), and peeknw()
+    provide the essential LdapLexer interface.
+    */
+
+    public int get() throws IOException // any next char
+    {
+    if(nextChar == NOCHAR) return readChar();
+    int c = nextChar;
+    nextChar = NOCHAR;
+    return c;
+    }
+
+    public int peek() throws IOException
+    {
+    if(nextChar == NOCHAR) {
+        nextChar = readChar();
+    }
+    return nextChar;
+    }
+
+    void skipwhitespace() throws IOException
+    {
+    while(WHITESPACE.indexOf(peek()) >= 0) get();
+    }
+
+    public int getnw() throws IOException // next non-whitespace char
+    {					   // (note: not essential but useful)
+    skipwhitespace();
+    return get();
+    }
+
+    public int peeknw() throws IOException // next non-whitespace char
+    {					   // (note: not essential but useful)
+    skipwhitespace();
+    return peek();
+    }
+
+    // Following is for error reporting
+
+    // Pass all character reads thru this so we can track char count
+
+    int charno; // 1-based
+
+    public int charno() {return charno;}
+
+    int readChar() throws IOException
+    {
+    charno++;
+    return reader.read();
+    }
+
+}

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Mapper.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Mapper.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Mapper.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Mapper.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,22 @@
+/*
+ *   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.util.ldap;
+
+public interface Mapper
+{
+    public Object lookup(String key);
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Operator.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Operator.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Operator.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/Operator.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,34 @@
+/*
+ *   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.util.ldap;
+
+import java.util.Stack;
+
+public abstract class Operator
+{
+    public abstract void execute(Stack operands, Mapper mapper)
+        throws EvaluationException;
+
+    public abstract String toString();
+
+    public abstract void buildTree(Stack operands); // re-build the parsetree
+    public abstract void toStringInfix(StringBuffer b); // convert to canonical string
+
+    // Place to store the reconstructed parsetree
+    // Vector -> ArrayList is using jdk1.2 or later
+    public Operator[] children = null;
+}
\ No newline at end of file

Added: incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/ParseException.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/ParseException.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/ParseException.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/framework/util/ldap/ParseException.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,22 @@
+/*
+ *   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.util.ldap;
+
+public class ParseException extends Exception {
+    public ParseException() {super();}
+    public ParseException(String msg) {super(msg);}
+}