[FELIX-4812] BundleRepository can be quite CPU intensive when starting a lot of bundles

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1663370 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LazyLocalResourceImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LazyLocalResourceImpl.java
new file mode 100644
index 0000000..6837fc7
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LazyLocalResourceImpl.java
@@ -0,0 +1,120 @@
+/*
+ * 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.bundlerepository.impl;
+
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.utils.log.Logger;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.framework.wiring.BundleRevision;
+
+public class LazyLocalResourceImpl implements Resource
+{
+    private final Bundle m_bundle;
+    private final Logger m_logger;
+    private volatile Resource m_resource = null;
+
+    LazyLocalResourceImpl(Bundle bundle, Logger logger)
+    {
+        m_bundle = bundle;
+        m_logger = logger;
+    }
+
+    public boolean isLocal()
+    {
+        return true;
+    }
+
+    public Bundle getBundle()
+    {
+        return m_bundle;
+    }
+
+    public String toString()
+    {
+        return m_bundle.toString();
+    }
+
+    private final Resource getResource() {
+        if (m_resource == null) {
+            synchronized (this) {
+                try {
+                    m_resource = new LocalResourceImpl(m_bundle);
+                } catch (InvalidSyntaxException ex) {
+                    // This should never happen since we are generating filters,
+                    // but ignore the resource if it does occur.
+                    m_logger.log(Logger.LOG_WARNING, ex.getMessage(), ex);
+                    m_resource = new ResourceImpl();
+                }
+            }
+        }
+        return m_resource;
+    }
+
+    public Map getProperties() {
+        return getResource().getProperties();
+    }
+
+    public String getId() {
+        return getResource().getId();
+    }
+
+    public String getSymbolicName() {
+        return getResource().getSymbolicName();
+    }
+
+    public Version getVersion() {
+        return getResource().getVersion();
+    }
+
+    public String getPresentationName() {
+        return getResource().getPresentationName();
+    }
+
+    public String getURI() {
+        return getResource().getURI();
+    }
+
+    public Long getSize() {
+        return getResource().getSize();
+    }
+
+    public String[] getCategories() {
+        return getResource().getCategories();
+    }
+
+    public Capability[] getCapabilities() {
+        return getResource().getCapabilities();
+    }
+
+    public Requirement[] getRequirements() {
+        return getResource().getRequirements();
+    }
+}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalRepositoryImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalRepositoryImpl.java
index 5d52f3a..a97972e 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalRepositoryImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalRepositoryImpl.java
@@ -26,7 +26,6 @@
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceEvent;
 import org.osgi.framework.SynchronousBundleListener;
 import org.apache.felix.bundlerepository.*;
@@ -36,7 +35,7 @@
     private final BundleContext m_context;
     private final Logger m_logger;
     private long m_snapshotTimeStamp = 0;
-    private Map m_localResourceList = new HashMap();
+    private Map<Long, Resource> m_localResourceList = new HashMap<Long, Resource>();
 
     public LocalRepositoryImpl(BundleContext context, Logger logger)
     {
@@ -51,7 +50,7 @@
         {
             synchronized (this)
             {
-                addBundle(event.getBundle(), m_logger);
+                addBundle(event.getBundle());
                 m_snapshotTimeStamp = System.currentTimeMillis();
             }
         }
@@ -59,7 +58,7 @@
         {
             synchronized (this)
             {
-                removeBundle(event.getBundle(), m_logger);
+                removeBundle(event.getBundle());
                 m_snapshotTimeStamp = System.currentTimeMillis();
             }
         }
@@ -73,14 +72,14 @@
         {
             synchronized (this)
             {
-                removeBundle(bundle, m_logger);
-                addBundle(bundle, m_logger);
+                removeBundle(bundle);
+                addBundle(bundle);
                 m_snapshotTimeStamp = System.currentTimeMillis();
             }
         }
     }
 
-    private void addBundle(Bundle bundle, Logger logger)
+    private void addBundle(Bundle bundle)
     {
         /*
          * Concurrency note: This method MUST be called in a context which
@@ -93,19 +92,10 @@
         {
             return;
         }
-        try
-        {
-            m_localResourceList.put(new Long(bundle.getBundleId()), new LocalResourceImpl(bundle));
-        }
-        catch (InvalidSyntaxException ex)
-        {
-            // This should never happen since we are generating filters,
-            // but ignore the resource if it does occur.
-            m_logger.log(Logger.LOG_WARNING, ex.getMessage(), ex);
-        }
+        m_localResourceList.put(bundle.getBundleId(), new LazyLocalResourceImpl(bundle, m_logger));
     }
 
-    private void removeBundle(Bundle bundle, Logger logger)
+    private void removeBundle(Bundle bundle)
     {
         /*
          * Concurrency note: This method MUST be called in a context which
@@ -113,7 +103,7 @@
          * corruption.
          */
 
-        m_localResourceList.remove(new Long(bundle.getBundleId()));
+        m_localResourceList.remove(bundle.getBundleId());
     }
 
     public void dispose()
@@ -139,7 +129,7 @@
 
     public synchronized Resource[] getResources()
     {
-        return (Resource[]) m_localResourceList.values().toArray(new Resource[m_localResourceList.size()]);
+        return m_localResourceList.values().toArray(new Resource[m_localResourceList.size()]);
     }
 
     private void initialize()
@@ -159,7 +149,7 @@
             bundles = m_context.getBundles();
             for (int i = 0; (bundles != null) && (i < bundles.length); i++)
             {
-                addBundle(bundles[i], m_logger);
+                addBundle(bundles[i]);
             }
 
             m_snapshotTimeStamp = System.currentTimeMillis();