You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2008/09/01 17:08:10 UTC

svn commit: r690991 [7/20] - in /cxf/sandbox/dosgi: ./ discovery/ discovery/local/ discovery/local/src/ discovery/local/src/main/ discovery/local/src/main/java/ discovery/local/src/main/java/org/ discovery/local/src/main/java/org/apache/ discovery/loca...

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,777 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.framework;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.felix.framework.util.FelixConstants;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.hooks.service.ListenerHook;
+
+
+public class ServiceRegistry
+{
+    private Logger m_logger = null;
+    private long m_currentServiceId = 1L;
+    // Maps bundle to an array of service registrations.
+    private Map m_serviceRegsMap = new HashMap();
+    // Maps registration to thread to keep track when a
+    // registration is in use, which will cause other
+    // threads to wait.
+    private Map m_lockedRegsMap = new HashMap();
+    // Maps bundle to an array of usage counts.
+    private Map m_inUseMap = new HashMap();
+
+    private ServiceListener m_serviceListener = null;
+
+    private List<ListenerHook> listenerHooks = 
+        new CopyOnWriteArrayList<ListenerHook>();
+
+    public ServiceRegistry(Logger 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)
+        {
+            registerHooks(classNames, svcObj);
+        	
+            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;
+    }
+
+    private void registerHooks(String[] classNames, Object svcObj) {
+        
+        if (hookRequested(classNames, ListenerHook.class.getName())) {
+            listenerHooks.add((ListenerHook)svcObj);
+        }
+    }
+
+    protected boolean hookRequested(String[] classNames, String hookClass) {
+    	for (String name : classNames) {
+    	    if (name.equals(hookClass)) {
+    		return true;
+    	    }
+    	}
+    	return false;
+    }
+    
+    public void unregisterService(Bundle bundle, ServiceRegistration reg)
+    {
+        synchronized (this)
+        {
+            // Note that we don't lock the service registration here using
+            // the m_lockedRegsMap because we want to allow bundles to get
+            // the service during the unregistration process. However, since
+            // we do remove the registration from the service registry, no
+            // new bundles will be able to look up the service.
+
+            // Now remove the registered service.
+            ServiceRegistration[] regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
+            m_serviceRegsMap.put(bundle, removeServiceRegistration(regs, reg));
+        }
+
+        // Fire the service event which gives all client bundles the
+        // opportunity to unget their service object.
+        fireServiceChanged(new ServiceEvent(ServiceEvent.UNREGISTERING, reg.getReference()));
+
+        // Now forcibly unget the service object for all stubborn clients.
+        synchronized (this)
+        {
+            Bundle[] clients = getUsingBundles(reg.getReference());
+            for (int i = 0; (clients != null) && (i < clients.length); i++)
+            {
+                while (ungetService(clients[i], reg.getReference()))
+                    ; // Keep removing until it is no longer possible
+            }
+            ((ServiceRegistrationImpl) reg).invalidate();
+        }
+    }
+
+    /**
+     * This method retrieves all services registrations for the specified
+     * bundle and invokes <tt>ServiceRegistration.unregister()</tt> on each
+     * one. This method is only called be the framework to clean up after
+     * a stopped bundle.
+     * @param bundle the bundle whose services should be unregistered.
+    **/
+    public void unregisterServices(Bundle bundle)
+    {
+        // Simply remove all service registrations for the bundle.
+        ServiceRegistration[] regs = null;
+        synchronized (this)
+        {
+            regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
+        }
+
+        // Note, there is no race condition here with respect to the
+        // bundle registering more services, because its bundle context
+        // has already been invalidated by this point, so it would not
+        // be able to register more services.
+
+        // Unregister each service.
+        for (int i = 0; (regs != null) && (i < regs.length); i++)
+        {
+            regs[i].unregister();
+        }
+
+        // Now remove the bundle itself.
+        synchronized (this)
+        {
+            m_serviceRegsMap.remove(bundle);
+        }
+    }
+
+    public List getServiceReferences(
+        Bundle findingBundle, String className, Filter filter)
+    {
+          // 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 Object getService(Bundle bundle, ServiceReference ref)
+    {
+        
+        UsageCount usage = null;
+        Object svcObj = null;
+
+        // Get the service registration.
+        ServiceRegistrationImpl reg = ((ServiceReferenceImpl) ref).getServiceRegistration();
+
+        synchronized (this)
+        {
+            // First make sure that no existing operation is currently
+            // being performed by another thread on the service registration.
+            for (Object o = m_lockedRegsMap.get(reg); (o != null); o = m_lockedRegsMap.get(reg))
+            {
+                // We don't allow cycles when we call out to the service factory.
+                if (o.equals(Thread.currentThread()))
+                {
+                    throw new IllegalStateException(
+                        "ServiceFactory.getService() resulted in a cycle.");
+                }
+
+                // Otherwise, wait for it to be freed.
+                try
+                {
+                    wait();
+                }
+                catch (InterruptedException ex)
+                {
+                }
+            }
+
+            // Lock the service registration.
+            m_lockedRegsMap.put(reg, Thread.currentThread());
+
+            // Make sure the service registration is still valid.
+            if (!reg.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.
+                flushUsageCount(bundle, 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.
+            }
+            else
+            {
+                // Get the usage count, if any.
+                usage = getUsageCount(bundle, ref);
+
+                // If the service object is cached, then increase the usage
+                // count and return the cached service object.
+                if (usage != null)
+                {
+                    usage.m_count++;
+                    svcObj = usage.m_svcObj;
+                }
+            }
+        }
+
+        // If we have a valid registration, but no usage count, that means we
+        // don't have a cached service object, so we need to create one now
+        // without holding the lock, since we will potentially call out to a
+        // service factory.
+        try
+        {
+            if (reg.isValid() && (usage == null))
+            {
+                // Get service object from service registration.
+                svcObj = reg.getService(bundle);
+
+                // Cache the service object.
+                if (svcObj != null)
+                {
+                    synchronized (this)
+                    {
+                        // Unregistration can happen concurrently, so we need
+                        // to double-check that we are still valid.
+                        if (reg.isValid())
+                        {
+                            addUsageCount(bundle, ref, svcObj);
+                        }
+                        else
+                        {
+                            // The service must have been unregistered in the
+                            // middle of our get operation, so null it.
+                            svcObj = null;
+                        }
+                    }
+                }
+            }
+        }
+        finally
+        {
+            // Finally, unlock the service registration so that any threads
+            // waiting for it can continue.
+            synchronized (this)
+            {
+                m_lockedRegsMap.remove(reg);
+                notifyAll();
+            }
+        }
+
+        return svcObj;
+    }
+
+    public boolean ungetService(Bundle bundle, ServiceReference ref)
+    {
+        UsageCount usage = null;
+        ServiceRegistrationImpl reg = ((ServiceReferenceImpl) ref).getServiceRegistration();
+
+        synchronized (this)
+        {
+            // First make sure that no existing operation is currently
+            // being performed by another thread on the service registration.
+            for (Object o = m_lockedRegsMap.get(reg); (o != null); o = m_lockedRegsMap.get(reg))
+            {
+                // We don't allow cycles when we call out to the service factory.
+                if (o.equals(Thread.currentThread()))
+                {
+                    throw new IllegalStateException(
+                        "ServiceFactory.ungetService() resulted in a cycle.");
+                }
+
+                // Otherwise, wait for it to be freed.
+                try
+                {
+                    wait();
+                }
+                catch (InterruptedException ex)
+                {
+                }
+            }
+
+            // Get the usage count.
+            usage = getUsageCount(bundle, ref);
+            // If there is no cached services, then just return immediately.
+            if (usage == null)
+            {
+                return false;
+            }
+
+            // Lock the service registration.
+            m_lockedRegsMap.put(reg, Thread.currentThread());
+
+            // Make sure the service registration is still valid.
+            if (!reg.isValid())
+            {
+                // If the service registration is not valid, then this means
+                // that the service provider unregistered the service, so just
+                // flush the usage count and we are done.
+                flushUsageCount(bundle, ref);
+            }
+            else if (reg.isValid())
+            {
+                // Decrement usage count.
+                usage.m_count--;
+            }
+
+            // If the usage count has reached zero, the flush it.
+            if (usage.m_count == 0)
+            {
+                flushUsageCount(bundle, ref);
+            }
+        }
+
+        // If usage count goes to zero, then unget the service
+        // from the registration; we do this outside the lock
+        // since this might call out to the service factory.
+        try
+        {
+            if (usage.m_count == 0)
+            {
+                // Remove reference from usages array.
+                ((ServiceReferenceImpl) ref)
+                    .getServiceRegistration().ungetService(bundle, usage.m_svcObj);
+                usage.m_svcObj = null;
+            }
+
+        }
+        finally
+        {
+            // Finally, unlock the service registration so that any threads
+            // waiting for it can continue.
+            synchronized (this)
+            {
+                m_lockedRegsMap.remove(reg);
+                notifyAll();
+            }
+        }
+
+        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 void ungetServices(Bundle bundle)
+    {
+        UsageCount[] usages;
+        synchronized (this)
+        {
+            usages = (UsageCount[]) m_inUseMap.get(bundle);
+        }
+        
+        if (usages == null)
+        {
+            return;
+        }
+
+        // Note, there is no race condition here with respect to the
+        // bundle using more services, because its bundle context
+        // has already been invalidated by this point, so it would not
+        // be able to look up more services.
+
+        // 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 Logger 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;
+        synchronized (this)
+        {
+            listener = m_serviceListener;
+        }
+        // If not null, then dispatch event.
+        if (listener != null)
+        {
+            listener.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;
+            }
+        }
+    }
+
+    /**
+     * Utility method to retrieve the specified bundle's usage count for the
+     * specified service reference.
+     * @param bundle The bundle whose usage counts are being searched.
+     * @param ref The service reference to find in the bundle's usage counts.
+     * @return The associated usage count or null if not found.
+    **/
+    private UsageCount getUsageCount(Bundle bundle, ServiceReference ref)
+    {
+        UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+        for (int i = 0; (usages != null) && (i < usages.length); i++)
+        {
+            if (usages[i].m_ref.equals(ref))
+            {
+                return usages[i];
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Utility method to update the specified bundle's usage count array to
+     * include the specified service. This method should only be called
+     * to add a usage count for a previously unreferenced service. If the
+     * service already has a usage count, then the existing usage count
+     * counter simply needs to be incremented.
+     * @param bundle The bundle acquiring the service.
+     * @param ref The service reference of the acquired service.
+     * @param svcObj The service object of the acquired service.
+    **/
+    private void addUsageCount(Bundle bundle, ServiceReference ref, Object svcObj)
+    {
+        UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+
+        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;
+        }
+
+        m_inUseMap.put(bundle, usages);
+    }
+
+    /**
+     * Utility method to flush the specified bundle's usage count for the
+     * specified service reference. This should be called to completely
+     * remove the associated usage count object for the specified service
+     * reference. If the goal is to simply decrement the usage, then get
+     * the usage count and decrement its counter. This method will also
+     * remove the specified bundle from the "in use" map if it has no more
+     * usage counts after removing the usage count for the specified service
+     * reference.
+     * @param bundle The bundle whose usage count should be removed.
+     * @param ref The service reference whose usage count should be removed.
+    **/
+    private void flushUsageCount(Bundle bundle, ServiceReference ref)
+    {
+        UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+        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 = null;
+                }
+                // 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;
+                }
+            }
+        }
+
+        if (usages != null)
+        {
+            m_inUseMap.put(bundle, usages);
+        }
+        else
+        {
+            m_inUseMap.remove(bundle);
+        }
+    }
+
+    protected List<ListenerHook> getListenerHooks() {
+        return Collections.unmodifiableList(listenerHooks);
+    }
+    
+    protected void removeHook(Object svcObj) {
+        
+        if (svcObj instanceof ListenerHook) {
+            listenerHooks.remove(svcObj);
+        }
+    }
+    
+    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

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/StartLevelActivator.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/StartLevelActivator.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/StartLevelActivator.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/StartLevelActivator.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,49 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.framework;
+
+import org.osgi.framework.*;
+
+class StartLevelActivator implements BundleActivator
+{
+    private Logger m_logger = null;
+    private Felix m_felix = null;
+    private StartLevelImpl m_startLevel = null;
+    private ServiceRegistration m_reg = null;
+
+    public StartLevelActivator(Logger logger, Felix felix)
+    {
+        m_logger = logger;
+        m_felix = felix;
+    }
+
+    public void start(BundleContext context) throws Exception
+    {
+        m_startLevel = new StartLevelImpl(m_logger, m_felix);
+        m_reg = context.registerService(
+            org.osgi.service.startlevel.StartLevel.class.getName(),
+            m_startLevel, null);
+    }
+
+    public void stop(BundleContext context) throws Exception
+    {
+        m_reg.unregister();
+        m_startLevel.stop();
+    }
+}

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/StartLevelActivator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/StartLevelActivator.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,274 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.framework;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.framework.AdminPermission;
+import org.osgi.framework.Bundle;
+import org.osgi.service.startlevel.StartLevel;
+
+/**
+ * @author rickhall
+ *
+ * To change the template for this generated type comment go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+**/
+public class StartLevelImpl implements StartLevel, Runnable
+{
+    private static final int BUNDLE_IDX = 0;
+    private static final int STARTLEVEL_IDX = 1;
+
+    private Logger m_logger = null;
+    private Felix m_felix = null;
+    private List m_requestList = null;
+    private Bundle m_systemBundle = null;
+    private Thread m_thread = null;
+
+    public StartLevelImpl(Logger logger, Felix felix)
+    {
+        m_logger = logger;
+        m_felix = felix;
+        m_requestList = new ArrayList();
+        m_systemBundle = m_felix.getBundle(0);
+        // Start a thread to perform asynchronous package refreshes.
+        m_thread = new Thread(this, "FelixStartLevel");
+        m_thread.setDaemon(true);
+        m_thread.start();
+    }
+    
+    /**
+     * Stops the FelixStartLevel thread on system shutdown. Shutting down the
+     * thread explicitly is required in the embedded case, where Felix may be
+     * stopped without the Java VM being stopped. In this case the
+     * FelixStartLevel thread must be stopped explicitly.
+     * <p>
+     * This method is called by the
+     * {@link StartLevelActivator#stop(BundleContext)} method.
+     */
+    void stop()
+    {
+        synchronized (m_requestList)
+        {
+            if (m_thread != null)
+            {
+                // Null thread variable to signal to the thread that
+                // we want it to exit.
+                m_thread = null;
+                
+                // Wake up the thread, if it is currently in the wait() state
+                // for more work.
+                m_requestList.notifyAll();
+            }
+        }
+    }
+    
+    /* (non-Javadoc)
+     * @see org.osgi.service.startlevel.StartLevel#getStartLevel()
+    **/
+    public int getStartLevel()
+    {
+        return m_felix.getStartLevel();
+    }
+
+    /* (non-Javadoc)
+     * @see org.osgi.service.startlevel.StartLevel#setStartLevel(int)
+    **/
+    public void setStartLevel(int startlevel)
+    {
+        Object sm = System.getSecurityManager();
+        
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(
+                new AdminPermission(m_systemBundle, AdminPermission.STARTLEVEL));
+        }
+        
+        if (startlevel <= 0)
+        {
+            throw new IllegalArgumentException(
+                "Start level must be greater than zero.");
+        }
+        
+        synchronized (m_requestList)
+        {
+            m_requestList.add(new Integer(startlevel));
+            m_requestList.notifyAll();
+        }
+    }
+
+    /**
+     * This method is currently only called by the by the thread that calls
+     * the Felix.start() method and the shutdown thread when the
+     * framework is shutting down.
+     * @param startlevel
+    **/
+    /* package */ void setStartLevelAndWait(int startlevel)
+    {
+        Object request = new Integer(startlevel);
+        synchronized (request)
+        {
+            synchronized (m_requestList)
+            {
+                m_requestList.add(request);
+                m_requestList.notifyAll();
+            }
+
+            try
+            {
+                request.wait();
+            }
+            catch (InterruptedException ex)
+            {
+                // Log it and ignore since it won't cause much of an issue.
+                m_logger.log(
+                    Logger.LOG_WARNING,
+                    "Wait for start level change during shutdown interrupted.",
+                    ex);
+            }
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.osgi.service.startlevel.StartLevel#getBundleStartLevel(org.osgi.framework.Bundle)
+    **/
+    public int getBundleStartLevel(Bundle bundle)
+    {
+        return m_felix.getBundleStartLevel(bundle);
+    }
+
+    /* (non-Javadoc)
+     * @see org.osgi.service.startlevel.StartLevel#setBundleStartLevel(org.osgi.framework.Bundle, int)
+    **/
+    public void setBundleStartLevel(Bundle bundle, int startlevel)
+    {
+        Object sm = System.getSecurityManager();
+        
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(
+                new AdminPermission(bundle, AdminPermission.STARTLEVEL));
+        }
+        
+        if (bundle.getBundleId() == 0)
+        {
+            throw new IllegalArgumentException(
+                "Cannot change system bundle start level.");
+        }
+        else if (startlevel <= 0)
+        {
+            throw new IllegalArgumentException(
+                "Start level must be greater than zero.");
+        }
+        synchronized (m_requestList)
+        {
+            m_requestList.add(new Object[] { bundle, new Integer(startlevel) });
+            m_requestList.notifyAll();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.osgi.service.startlevel.StartLevel#getInitialBundleStartLevel()
+    **/
+    public int getInitialBundleStartLevel()
+    {
+        return m_felix.getInitialBundleStartLevel();
+    }
+
+    /* (non-Javadoc)
+     * @see org.osgi.service.startlevel.StartLevel#setInitialBundleStartLevel(int)
+    **/
+    public void setInitialBundleStartLevel(int startlevel)
+    {
+        Object sm = System.getSecurityManager();
+        
+        if (sm != null)
+        {
+            ((SecurityManager) sm).checkPermission(
+                new AdminPermission(m_systemBundle, AdminPermission.STARTLEVEL));
+        }
+        m_felix.setInitialBundleStartLevel(startlevel);
+    }
+
+    /* (non-Javadoc)
+     * @see org.osgi.service.startlevel.StartLevel#isBundlePersistentlyStarted(org.osgi.framework.Bundle)
+    **/
+    public boolean isBundlePersistentlyStarted(Bundle bundle)
+    {
+        return m_felix.isBundlePersistentlyStarted(bundle);
+    }
+
+    public void run()
+    {
+        Object request = null;
+
+        // This thread loops forever, thus it should
+        // be a daemon thread.
+        while (true)
+        {
+            synchronized (m_requestList)
+            {
+                // Wait for a request.
+                while (m_requestList.size() == 0)
+                {
+                    // Terminate the thread if requested to do so (see stop()).
+                    if (m_thread == null)
+                    {
+                        return;
+                    }
+                    
+                    try
+                    {
+                        m_requestList.wait();
+                    }
+                    catch (InterruptedException ex)
+                    {
+                        // Ignore.
+                    }
+                }
+                
+                // Get the requested start level.
+                request = m_requestList.remove(0);
+            }
+
+            // If the request object is an Integer, then the request
+            // is to set the framework start level. If the request is
+            // an Object array, then the request is to set the start
+            // level for a bundle.
+            if (request instanceof Integer)
+            {
+                // Set the new framework start level.
+                m_felix.setFrameworkStartLevel(((Integer) request).intValue());
+            }
+            else
+            {
+                Bundle bundle = (Bundle) ((Object[]) request)[BUNDLE_IDX];
+                int startlevel = ((Integer) ((Object[]) request)[STARTLEVEL_IDX]).intValue();
+                m_felix.setBundleStartLevel(bundle, startlevel);
+            }
+
+            // Notify any waiting thread that this request is done.
+            synchronized (request)
+            {
+                request.notifyAll();
+            }
+        }
+    }
+}
\ No newline at end of file

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/StartLevelImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/SystemBundleArchive.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/SystemBundleArchive.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/SystemBundleArchive.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/SystemBundleArchive.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.framework;
+
+import org.apache.felix.framework.cache.*;
+import java.io.File;
+import java.io.InputStream;
+import java.util.Map;
+
+import org.apache.felix.framework.util.FelixConstants;
+import org.apache.felix.framework.util.StringMap;
+import org.apache.felix.moduleloader.IContent;
+import org.apache.felix.moduleloader.IModule;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+
+/**
+ * <p>
+ * This class represents the bundle archive of the system bundle. It is a
+ * special case that is mostly just an empty implementation, since the system
+ * bundle is not a real archive.
+ * </p>
+**/
+public class SystemBundleArchive extends BundleArchive
+{
+    private BundleCache m_cache;
+    private Map m_headerMap = new StringMap(false);
+    private BundleRevision m_revision;
+
+    public SystemBundleArchive(BundleCache cache)
+    {
+        m_cache = cache;
+
+        try
+        {
+            m_revision = new BundleRevision(null, null, null) {
+
+                public Map getManifestHeader() throws Exception
+                {
+                    return m_headerMap;
+                }
+
+                public IContent getContent() throws Exception
+                {
+                    return null;
+                }
+
+                public void dispose() throws Exception
+                {
+                }
+            };
+        }
+        catch (Exception ex)
+        {
+            // This should never happen.
+        }
+    }
+
+    public long getId()
+    {
+        return 0;
+    }
+
+    public String getLocation() throws Exception
+    {
+        return FelixConstants.SYSTEM_BUNDLE_LOCATION;
+    }
+
+    public String getCurrentLocation() throws Exception
+    {
+        return null;
+    }
+
+    public void setCurrentLocation(String location) throws Exception
+    {
+    }
+
+    public int getPersistentState() throws Exception
+    {
+        return Bundle.ACTIVE;
+    }
+
+    public void setPersistentState(int state) throws Exception
+    {
+    }
+
+    public int getStartLevel() throws Exception
+    {
+        return FelixConstants.SYSTEMBUNDLE_DEFAULT_STARTLEVEL;
+    }
+
+    public void setStartLevel(int level) throws Exception
+    {
+    }
+
+    public File getDataFile(String fileName) throws Exception
+    {
+        return m_cache.getSystemBundleDataFile(fileName);
+    }
+
+    public BundleActivator getActivator(IModule module)
+        throws Exception
+    {
+        return null;
+    }
+
+    public void setActivator(Object obj) throws Exception
+    {
+    }
+
+    public int getRevisionCount()
+    {
+        return 1;
+    }
+
+    public BundleRevision getRevision(int i)
+    {
+        return m_revision;
+    }
+
+    public void revise(String location, InputStream is)
+        throws Exception
+    {
+    }
+
+    public  void purge() throws Exception
+    {
+    }
+
+    public void dispose() throws Exception
+    {
+    }
+
+    public Map getManifestHeader(int revision)
+    {
+        return m_headerMap;
+    }
+
+    public void setManifestHeader(Map headerMap)
+    {
+        m_headerMap = headerMap;
+    }
+}
\ No newline at end of file

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/SystemBundleArchive.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/SystemBundleArchive.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlers.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlers.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlers.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,638 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.framework;
+
+import java.io.IOException;
+import java.net.*;
+import java.util.*;
+
+import org.apache.felix.framework.searchpolicy.ContentClassLoader;
+import org.apache.felix.framework.util.*;
+
+/**
+ * <p>
+ * This class is a singleton and implements the stream and content handler
+ * factories for all framework instances executing within the JVM. Any
+ * calls to retrieve stream or content handlers is routed through this class
+ * and it acts as a multiplexer for all framework instances. To achieve this,
+ * all framework instances register with this class when they are created so
+ * that it can maintain a centralized registry of instances.
+ * </p>
+ * <p>
+ * When this class receives a request for a stream or content handler, it
+ * always returns a proxy handler instead of only returning a proxy if a
+ * handler currently exists. This approach is used for three reasons:
+ * </p>
+ * <ol>
+ *   <li>Potential caching behavior by the JVM of stream handlers does not give
+ *       you a second chance to provide a handler.
+ *   </li>
+ *   <li>Due to the dynamic nature of OSGi services, handlers may appear at
+ *       any time, so always creating a proxy makes sense.
+ *   </li>
+ *   <li>Since these handler factories service all framework instances,
+ *       some instances may have handlers and others may not, so returning
+ *       a proxy is the only answer that makes sense.
+ *   </li>
+ * </ol>
+ * <p>
+ * It is possible to disable the URL Handlers service by setting the
+ * <tt>framework.service.urlhandlers</tt> configuration property to <tt>false</tt>.
+ * When multiple framework instances are in use, if no framework instances enable
+ * the URL Handlers service, then the singleton stream and content factories will
+ * never be set (i.e., <tt>URL.setURLStreamHandlerFactory()</tt> and
+ * <tt>URLConnection.setContentHandlerFactory()</tt>). However, if one instance
+ * enables URL Handlers service, then the factory methods will be invoked. In
+ * that case, framework instances that disable the URL Handlers service will
+ * simply not provide that services to their contained bundles, while framework
+ * instances with the service enabled will.
+ * </p>
+**/
+class URLHandlers implements URLStreamHandlerFactory, ContentHandlerFactory
+{
+    private static final String STREAM_HANDLER_PACKAGE_PROP = "java.protocol.handler.pkgs";
+    private static final String CONTENT_HANDLER_PACKAGE_PROP = "java.content.handler.pkgs";
+    private static final String DEFAULT_STREAM_HANDLER_PACKAGE = "sun.net.www.protocol|com.ibm.oti.net.www.protocol|gnu.java.net.protocol|wonka.net|com.acunia.wonka.net|org.apache.harmony.luni.internal.net.www.protocol|weblogic.utils|weblogic.net|javax.net.ssl|COM.newmonics.www.protocols";
+    private static final String DEFAULT_CONTENT_HANDLER_PACKAGE = "sun.net.www.content|com.ibm.oti.net.www.content|gnu.java.net.content|org.apache.harmony.luni.internal.net.www.content|COM.newmonics.www.content";
+
+    private static final SecureAction m_secureAction = new SecureAction();
+
+    private static SecurityManagerEx m_sm = null;
+    private static URLHandlers m_handler = null;
+
+    // This maps classloaders of URLHandlers in other classloaders to lists of 
+    // their frameworks.
+    private static Map m_classloaderToFrameworkLists = new HashMap();
+
+    // The list to hold all enabled frameworks registered with this handlers 
+    private static final List m_frameworks = new ArrayList();
+
+    private static Map m_contentHandlerCache = null;
+    private static Map m_streamHandlerCache = null;
+    private static URLStreamHandlerFactory m_streamHandlerFactory;
+    private static ContentHandlerFactory m_contentHandlerFactory;
+
+    /**
+     * <p>
+     * Only one instance of this class is created per classloader 
+     * and that one instance is registered as the stream and content handler
+     * factories for the JVM. Unless, we already register one from a different
+     * classloader. In this case we attach to this root.
+     * </p> 
+    **/
+    private URLHandlers()
+    {
+        synchronized (URL.class)
+        {
+            try
+            {
+                URL.setURLStreamHandlerFactory(this);
+                m_streamHandlerFactory = this;
+            }
+            catch (Error err)
+            {
+                try
+                {
+                    // there already is a factory set so try to swap it with ours.
+                    m_streamHandlerFactory = (URLStreamHandlerFactory)
+                        m_secureAction.swapStaticFieldIfNotClass(URL.class, 
+                        URLStreamHandlerFactory.class, URLHandlers.class, "streamHandlerLock");
+                    
+                    if (m_streamHandlerFactory == null)
+                    {
+                        throw err;
+                    }
+                    if (!m_streamHandlerFactory.getClass().getName().equals(URLHandlers.class.getName()))
+                    {
+                        URL.setURLStreamHandlerFactory(this);
+                    }
+                    else if (URLHandlers.class != m_streamHandlerFactory.getClass())
+                    {
+                        try
+                        {
+                            m_secureAction.invoke(
+                                m_secureAction.getDeclaredMethod(m_streamHandlerFactory.getClass(), 
+                                "registerFrameworkListsForContextSearch", 
+                                new Class[]{ClassLoader.class, List.class}), 
+                                m_streamHandlerFactory, new Object[]{ URLHandlers.class.getClassLoader(), 
+                                    m_frameworks });
+                        }
+                        catch (Exception ex)
+                        {
+                            new RuntimeException(ex.getMessage());
+                        }
+                    }
+                }
+                catch (Exception e)
+                {
+                    throw err;
+                }
+            }
+            
+            try
+            {
+                URLConnection.setContentHandlerFactory(this);
+                m_contentHandlerFactory = this;
+            }
+            catch (Error err)
+            {
+                // there already is a factory set so try to swap it with ours.
+                try
+                {   
+                    m_contentHandlerFactory = (ContentHandlerFactory) 
+                        m_secureAction.swapStaticFieldIfNotClass(
+                            URLConnection.class, ContentHandlerFactory.class, 
+                            URLHandlers.class, null);
+                    if (m_contentHandlerFactory == null)
+                    {
+                        throw err;
+                    }
+                    if (!m_contentHandlerFactory.getClass().getName().equals(
+                        URLHandlers.class.getName()))
+                    {
+                        URLConnection.setContentHandlerFactory(this);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    throw err;
+                }
+            }
+        }
+        // are we not the new root?
+        if ((m_streamHandlerFactory == this) || !URLHandlers.class.getName().equals(
+            m_streamHandlerFactory.getClass().getName()))
+        {
+            // we only need a security manager in the root
+            m_sm = new SecurityManagerEx();
+        }
+    }
+
+    static void registerFrameworkListsForContextSearch(ClassLoader index, 
+        List frameworkLists)
+    {
+        synchronized (URL.class)
+        {
+            synchronized (m_classloaderToFrameworkLists)
+            {
+                m_classloaderToFrameworkLists.put(index, frameworkLists);
+            }
+        }
+    }
+
+    static void unregisterFrameworkListsForContextSearch(ClassLoader index)
+    {
+        synchronized (URL.class)
+        {
+            synchronized (m_classloaderToFrameworkLists)
+            {
+                m_classloaderToFrameworkLists.remove(index);
+                if (m_classloaderToFrameworkLists.isEmpty() )
+                {
+                    synchronized (m_frameworks)
+                    {
+                        if (m_frameworks.isEmpty())
+                        {
+                            try
+                            {
+                                m_secureAction.swapStaticFieldIfNotClass(URL.class, 
+                                    URLStreamHandlerFactory.class, null, "streamHandlerLock");
+                            }
+                            catch (Exception ex)
+                            {
+                                // TODO log this
+                                ex.printStackTrace();
+                            }
+                            
+                            if (m_streamHandlerFactory.getClass() != URLHandlers.class)
+                            {
+                                URL.setURLStreamHandlerFactory(m_streamHandlerFactory);
+                            }
+                            try
+                            {
+                                m_secureAction.swapStaticFieldIfNotClass(
+                                    URLConnection.class, ContentHandlerFactory.class, 
+                                    null, null);
+                            }
+                            catch (Exception ex)
+                            {
+                                // TODO log this
+                                ex.printStackTrace();
+                            }
+                            
+                            if (m_contentHandlerFactory.getClass() != URLHandlers.class)
+                            {
+                                URLConnection.setContentHandlerFactory(m_contentHandlerFactory);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * This is a method implementation for the <tt>URLStreamHandlerFactory</tt>
+     * interface. It simply creates a stream handler proxy object for the
+     * specified protocol. It caches the returned proxy; therefore, subsequent
+     * requests for the same protocol will receive the same handler proxy.
+     * </p>
+     * @param protocol the protocol for which a stream handler should be returned.
+     * @return a stream handler proxy for the specified protocol.
+    **/
+    public URLStreamHandler createURLStreamHandler(String protocol)
+    {
+        synchronized (this)
+        {
+            // See if there is a cached stream handler.
+            // IMPLEMENTATION NOTE: Caching is not strictly necessary for
+            // stream handlers since the Java runtime caches them. Caching is
+            // performed for code consistency between stream and content
+            // handlers and also because caching behavior may not be guaranteed
+            // across different JRE implementations.
+            URLStreamHandler handler = (URLStreamHandler) 
+                ((m_streamHandlerCache != null) ? m_streamHandlerCache.get(protocol) : null);
+            
+            if (handler != null)
+            {
+                return handler;
+            }
+            // If this is the framework's "bundle:" protocol, then return
+            // a handler for that immediately, since no one else can be
+            // allowed to deal with it.
+            if (protocol.equals(FelixConstants.BUNDLE_URL_PROTOCOL))
+            {
+                return addToStreamCache(protocol, 
+                    new URLHandlersBundleStreamHandler(m_secureAction));
+            }
+        
+            // If this is the framework's "felix:" extension protocol, then
+            // return the ExtensionManager.m_extensionManager handler for 
+            // that immediately - this is a workaround for certain jvms that
+            // do a toString() on the extension url we add to the global
+            // URLClassloader.
+            if (protocol.equals("felix"))
+            {
+                return addToStreamCache(protocol, new URLStreamHandler()
+                {
+                    protected URLConnection openConnection(URL url)
+                        throws IOException
+                    {
+                        Object framework = getFrameworkFromContext();
+                        
+                        try
+                        {
+                            Object handler =  m_secureAction.getDeclaredField(
+                                framework.getClass(),"m_extensionManager", framework);
+    
+                            return (URLConnection) m_secureAction.invoke(
+                                m_secureAction.getMethod(handler.getClass(), 
+                                "openConnection", new Class[]{URL.class}), handler, 
+                                new Object[]{url});
+                        }
+                        catch (Exception ex)
+                        {
+                            throw new IOException(ex.getMessage());
+                        }
+                    }
+                });
+            }
+
+            // If there was a custom factory then try to get the handler form it
+            if (m_streamHandlerFactory != this)
+            {
+                handler = 
+                    addToStreamCache(protocol, m_streamHandlerFactory.createURLStreamHandler(protocol));
+
+                if (handler != null)
+                {
+                    return handler;
+                }
+            }
+            // Check for built-in handlers for the protocol.
+            String pkgs = m_secureAction.getSystemProperty(STREAM_HANDLER_PACKAGE_PROP, "");
+            pkgs = (pkgs.equals(""))
+                ? DEFAULT_STREAM_HANDLER_PACKAGE
+                : pkgs + "|" + DEFAULT_STREAM_HANDLER_PACKAGE;
+
+            // Iterate over built-in packages.
+            StringTokenizer pkgTok = new StringTokenizer(pkgs, "| ");
+            while (pkgTok.hasMoreTokens())
+            {
+                String pkg = pkgTok.nextToken().trim();
+                String className = pkg + "." + protocol + ".Handler";
+                try
+                {
+                    // If a built-in handler is found then let the
+                    // JRE handle it.
+                    if (m_secureAction.forName(className) != null)
+                    {
+                        return null;
+                    }
+                }
+                catch (Exception ex)
+                {
+                    // This could be a class not found exception or an
+                    // instantiation exception, not much we can do in either
+                    // case other than ignore it.
+                }
+            }
+            // If built-in content handler, then create a proxy handler.
+            return addToStreamCache(protocol, new URLHandlersStreamHandlerProxy(protocol, m_secureAction));
+        }
+    }
+
+    /**
+     * <p>
+     * This is a method implementation for the <tt>ContentHandlerFactory</tt>
+     * interface. It simply creates a content handler proxy object for the
+     * specified mime type. It caches the returned proxy; therefore, subsequent
+     * requests for the same content type will receive the same handler proxy.
+     * </p>
+     * @param mimeType the mime type for which a content handler should be returned.
+     * @return a content handler proxy for the specified mime type.
+    **/
+    public ContentHandler createContentHandler(String mimeType)
+    {
+        synchronized (this)
+        {
+            // See if there is a cached stream handler.
+            // IMPLEMENTATION NOTE: Caching is not strictly necessary for
+            // stream handlers since the Java runtime caches them. Caching is
+            // performed for code consistency between stream and content
+            // handlers and also because caching behavior may not be guaranteed
+            // across different JRE implementations.
+            ContentHandler handler = (ContentHandler) 
+                ((m_contentHandlerCache != null) ? m_contentHandlerCache.get(mimeType) : null);
+            
+            if (handler != null)
+            {
+                return handler;
+            }
+            // If there was a custom factory then try to get the handler form it
+            if (m_contentHandlerFactory != this)
+            {
+                handler = addToContentCache(mimeType, 
+                    m_contentHandlerFactory.createContentHandler(mimeType));
+                
+                if (handler != null)
+                {
+                    return handler;
+                }
+            }
+    
+            // Check for built-in handlers for the mime type.
+            String pkgs = m_secureAction.getSystemProperty(CONTENT_HANDLER_PACKAGE_PROP, "");
+            pkgs = (pkgs.equals(""))
+                ? DEFAULT_CONTENT_HANDLER_PACKAGE
+                : pkgs + "|" + DEFAULT_CONTENT_HANDLER_PACKAGE;
+    
+            // Remove periods, slashes, and dashes from mime type.
+            String fixedType = mimeType.replace('.', '_').replace('/', '.').replace('-', '_');
+    
+            // Iterate over built-in packages.
+            StringTokenizer pkgTok = new StringTokenizer(pkgs, "| ");
+            while (pkgTok.hasMoreTokens())
+            {
+                String pkg = pkgTok.nextToken().trim();
+                String className = pkg + "." + fixedType;
+                try
+                {
+                    // If a built-in handler is found then let the
+                    // JRE handle it.
+                    if (m_secureAction.forName(className) != null)
+                    {
+                        return null;
+                    }
+                }
+                catch (Exception ex)
+                {
+                    // This could be a class not found exception or an
+                    // instantiation exception, not much we can do in either
+                    // case other than ignore it.
+                }
+            }
+    
+            return addToContentCache(mimeType, 
+                new URLHandlersContentHandlerProxy(mimeType, m_secureAction));
+        }
+    }
+
+    private ContentHandler addToContentCache(String mimeType, ContentHandler handler)
+    {
+        if (handler == null)
+        {
+            return null;
+        }
+        if (m_contentHandlerCache == null)
+        {
+            m_contentHandlerCache = new HashMap();
+            m_contentHandlerCache.put(mimeType, handler);
+        }
+        else
+        {
+            ContentHandler result = (ContentHandler) 
+                m_contentHandlerCache.get(mimeType);
+            
+            if (result == null)
+            {
+                m_contentHandlerCache.put(mimeType, handler);
+            }
+            else
+            {
+                handler = result;
+            }
+        }
+        return handler;
+    }
+
+    private URLStreamHandler addToStreamCache(String protocol, URLStreamHandler handler)
+    {
+        if (handler == null)
+        {
+            return null;
+        }
+        
+        if (m_streamHandlerCache == null)
+        {
+            m_streamHandlerCache = new HashMap();
+            m_streamHandlerCache.put(protocol, handler);
+        }
+        else
+        {
+            URLStreamHandler result = (URLStreamHandler) 
+                m_streamHandlerCache.get(protocol);
+            
+            if (result == null)
+            {
+                m_streamHandlerCache.put(protocol, handler);
+            }
+            else
+            {
+                handler = result;
+            }
+        }
+        return handler;
+    }
+
+    /**
+     * <p>
+     * Static method that adds a framework instance to the centralized
+     * instance registry.
+     * </p>
+     * @param framework the framework instance to be added to the instance
+     *        registry.
+     * @param enable a flag indicating whether or not the framework wants to
+     *        enable the URL Handlers service.
+    **/
+    public static void registerFrameworkInstance(Object framework, boolean enable)
+    {
+        synchronized (m_frameworks)
+        {
+            // If the URL Handlers service is not going to be enabled,
+            // then return immediately.
+            if (enable)
+            {
+                // We need to create an instance if this is the first
+                // time this method is called, which will set the handler
+                // factories.
+                if (m_handler == null)
+                {
+                    m_handler = new URLHandlers();
+                }
+                m_frameworks.add(framework);
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * Static method that removes a framework instance from the centralized
+     * instance registry.
+     * </p>
+     * @param framework the framework instance to be removed from the instance
+     *        registry.
+    **/
+    public static void unregisterFrameworkInstance(Object framework)
+    {
+        synchronized (m_frameworks)
+        {
+            if (m_frameworks.remove(framework) && m_frameworks.isEmpty())
+            {
+                if (m_handler.m_streamHandlerFactory.getClass().getName().equals(
+                    URLHandlers.class.getName()))
+                {
+                    try
+                    {
+                        m_secureAction.invoke(m_secureAction.getDeclaredMethod(
+                            m_handler.m_streamHandlerFactory.getClass(), 
+                            "unregisterFrameworkListsForContextSearch", 
+                            new Class[]{ ClassLoader.class}), 
+                            m_handler.m_streamHandlerFactory, 
+                            new Object[] {URLHandlers.class.getClassLoader()});
+                    }
+                    catch (Exception e)
+                    {
+                        // TODO this should not happen
+                        e.printStackTrace();
+                    }
+                }
+                m_handler = null;
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * This method returns the system bundle context for the caller.
+     * It determines the appropriate system bundle by retrieving the
+     * class call stack and find the first class that is loaded from
+     * a bundle. It then checks to see which of the registered framework
+     * instances owns the class and returns its system bundle context.
+     * </p>
+     * @return the system bundle context associated with the caller or
+     *         <tt>null</tt> if no associated framework was found.
+    **/
+    public static Object getFrameworkFromContext()
+    {
+        // get the current class call stack.
+        Class[] stack = m_sm.getClassContext();
+        // Find the first class that is loaded from a bundle.
+        Class targetClass = null;
+        for (int i = 0; i < stack.length; i++)
+        {
+            if ((stack[i].getClassLoader() != null) && 
+                ContentClassLoader.class.getName().equals(
+                stack[i].getClassLoader().getClass().getName()))
+            {
+                targetClass = stack[i];
+                break;
+            }
+        }
+        
+        // If we found a class loaded from a bundle, then iterate
+        // over the framework instances and see which framework owns
+        // the bundle that loaded the class.
+        if (targetClass != null)
+        {
+            synchronized (m_classloaderToFrameworkLists)
+            {
+                ClassLoader index = targetClass.getClassLoader().getClass().getClassLoader();
+                
+                List frameworks = (List) m_classloaderToFrameworkLists.get(
+                    index);
+                
+                if ((frameworks == null) && (index == URLHandlers.class.getClassLoader())) 
+                {
+                    frameworks = m_frameworks;
+                }
+                if (frameworks != null)
+                {
+                    synchronized (frameworks)
+                    {
+                        // Check the registry of framework instances
+                        for (int i = 0; i < frameworks.size(); i++)
+                        {
+                            Object framework = frameworks.get(i);
+                            try
+                            {
+                                if (m_secureAction.invoke(
+                                    m_secureAction.getDeclaredMethod(framework.getClass(), 
+                                    "getBundle", new Class[]{Class.class}),
+                                    framework, new Object[]{targetClass}) != null)
+                                {
+                                    return framework;
+                                }
+                            }
+                            catch (Exception ex)
+                            {
+                                // This should not happen but if it does there is 
+                                // not much we can do other then ignore it.
+                                // Maybe log this or something.
+                                ex.printStackTrace();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+}
\ No newline at end of file

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,65 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.framework;
+
+import java.util.Map;
+import org.apache.felix.framework.util.FelixConstants;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * <p>
+ * Simple activator class used by the system bundle to enable the
+ * URL Handlers service. The only purpose of this class is to call
+ * <tt>URLHandlers.registerInstance()</tt> when the framework is
+ * started and <tt>URLHandlers.unregisterInstance()</tt> when the
+ * framework is stopped.
+ *</p>
+**/
+class URLHandlersActivator implements BundleActivator
+{
+    private Map m_configMap = null;
+    private Felix m_framework = null;
+
+    public URLHandlersActivator(Map configMap, Felix framework)
+    {
+        m_configMap = configMap;
+        m_framework = framework;
+    }
+
+    //
+    // Bundle activator methods.
+    //
+
+    public void start(BundleContext context)
+    {
+        // Only register the framework with the URL Handlers service
+        // if the service is enabled.
+        boolean enable = (m_configMap.get(
+                FelixConstants.SERVICE_URLHANDLERS_PROP) == null)
+                ? true
+                : !m_configMap.get(FelixConstants.SERVICE_URLHANDLERS_PROP).equals("false");
+        URLHandlers.registerFrameworkInstance(m_framework, enable);
+    }
+
+    public void stop(BundleContext context)
+    {
+        URLHandlers.unregisterFrameworkInstance(m_framework);
+    }
+}

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersActivator.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,71 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.framework;
+
+import java.io.IOException;
+import java.net.*;
+
+import org.apache.felix.framework.util.SecureAction;
+
+class URLHandlersBundleStreamHandler extends URLStreamHandler
+{
+    private final Felix m_framework;
+    private final SecureAction m_action;
+
+    public URLHandlersBundleStreamHandler(Felix framework)
+    {
+        m_framework = framework;
+        m_action = null;
+    }
+
+    public URLHandlersBundleStreamHandler(SecureAction action)
+    {
+        m_framework = null;
+        m_action = action;
+    }
+
+    protected synchronized URLConnection openConnection(URL url) throws IOException
+    {
+        if (m_framework != null)
+        {
+            return new URLHandlersBundleURLConnection(url, m_framework);
+        }
+        
+        Object framework = URLHandlers.getFrameworkFromContext();
+        
+        if (framework != null)
+        {
+            // TODO: optimize this to not use reflection if not needed
+            try
+            {
+                Class targetClass = framework.getClass().getClassLoader().loadClass(
+                    URLHandlersBundleURLConnection.class.getName());
+                
+                return (URLConnection) m_action.invoke(m_action.getConstructor(targetClass, 
+                    new Class[]{URL.class, framework.getClass()}),
+                    new Object[]{url, framework});
+            }
+            catch (Exception ex)
+            {
+                throw new IOException(ex.getMessage());
+            }
+        }
+        throw new IOException("No framework context found");
+    }
+}
\ No newline at end of file

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleStreamHandler.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
URL: http://svn.apache.org/viewvc/cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java?rev=690991&view=auto
==============================================================================
--- cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java (added)
+++ cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java Mon Sep  1 08:08:01 2008
@@ -0,0 +1,183 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.felix.framework;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.Permission;
+
+import org.apache.felix.framework.util.Util;
+import org.apache.felix.moduleloader.IModule;
+
+class URLHandlersBundleURLConnection extends URLConnection
+{
+    private Felix m_framework;
+    private IModule m_targetModule;
+    private int m_classPathIdx = -1;
+    private int m_contentLength;
+    private long m_contentTime;
+    private String m_contentType;
+    private InputStream m_is;
+
+    public URLHandlersBundleURLConnection(URL url)
+    {
+        super(url);
+    }
+
+    public URLHandlersBundleURLConnection(URL url, Felix framework)
+        throws IOException
+    {
+        super(url);
+        m_framework = framework;
+
+        // If we don't have a framework instance, try to find
+        // one from the call context.
+        if (m_framework == null)
+        {
+            m_framework = (Felix) URLHandlers.getFrameworkFromContext();
+        }
+
+        // If there is still no framework, then error.
+        if (m_framework == null)
+        {
+            throw new IOException("Unable to find framework for URL: " + url);
+        }
+        // Verify that the resource pointed to by the URL exists.
+        // The URL is constructed like this:
+        //     bundle://<module-id>:<bundle-classpath-index>/<resource-path>
+        // Where <module-id> = <bundle-id>.<revision>
+        long bundleId = Util.getBundleIdFromModuleId(url.getHost());
+        FelixBundle bundle = (FelixBundle) m_framework.getBundle(bundleId);
+        if (bundle == null)
+        {
+            throw new IOException("No bundle associated with resource: " + url);
+        }
+        int revision = Util.getModuleRevisionFromModuleId(url.getHost());
+        IModule[] modules = bundle.getInfo().getModules();
+        if ((modules == null) || (revision < 0) || (revision >= modules.length))
+        {
+            throw new IOException("Resource does not exist: " + url);
+        }
+
+        // If the resource cannot be found at the current class path index,
+        // then search them all in order to see if it can be found. This is
+        // necessary since the user might create a resource URL from another
+        // resource URL and not realize they have the wrong class path entry.
+        // Of course, this approach won't work in cases where there are multiple
+        // resources with the same path, since it will always find the first
+        // one on the class path.
+        m_targetModule = modules[revision];
+        m_classPathIdx = url.getPort();
+        if (!modules[revision].getContentLoader().hasInputStream(m_classPathIdx, url.getPath()))
+        {
+            URL newurl = modules[revision].getContentLoader().getResource(url.getPath());
+            if (newurl == null)
+            {
+                throw new IOException("Resource does not exist: " + url);
+            }
+            m_classPathIdx = newurl.getPort();
+        }
+    }
+
+    public synchronized void connect() throws IOException
+    {
+        if (!connected)
+        {
+            if ((m_targetModule == null) || (m_classPathIdx < 0))
+            {
+                throw new IOException("Resource does not exist: " + url);
+            }
+            m_is = m_targetModule.getContentLoader()
+                .getInputStream(m_classPathIdx, url.getPath());
+            m_contentLength = (m_is == null) ? 0 : m_is.available();
+            m_contentTime = 0L;
+            m_contentType = URLConnection.guessContentTypeFromName(url.getFile());
+            connected = true;
+        }
+    }
+
+    public InputStream getInputStream()
+        throws IOException
+    {
+        connect();
+
+        return m_is;
+    }
+
+    public int getContentLength()
+    {
+        try
+        {
+            connect();
+        }
+        catch(IOException ex)
+        {
+            return -1;
+        }
+
+        return m_contentLength;
+    }
+
+    public long getLastModified()
+    {
+        try
+        {
+            connect();
+        }
+        catch(IOException ex)
+        {
+            return 0;
+        }
+
+        if (m_contentTime != -1L)
+        {
+            return m_contentTime;
+        }
+        else
+        {
+            return 0L;
+        }
+    }
+
+    public String getContentType()
+    {
+        try
+        {
+            connect();
+        }
+        catch (IOException ex)
+        {
+            return null;
+        }
+
+        return m_contentType;
+    }
+
+    public Permission getPermission()
+    {
+        // TODO: This should probably return a FilePermission
+        // to access the bundle JAR file, but we don't have the
+        // necessary information here to construct the absolute
+        // path of the JAR file...so it would take some
+        // re-arranging to get this to work.
+        return null;
+    }
+}

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/sandbox/dosgi/felix/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date