You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2017/05/05 09:27:22 UTC

svn commit: r1793992 - /sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java

Author: cziegeler
Date: Fri May  5 09:27:22 2017
New Revision: 1793992

URL: http://svn.apache.org/viewvc?rev=1793992&view=rev
Log:
SLING-6831 : ConcurrentModificationException in OSGi Installer

Modified:
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java?rev=1793992&r1=1793991&r2=1793992&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java Fri May  5 09:27:22 2017
@@ -103,16 +103,16 @@ implements OsgiInstaller, ResourceChange
     private final BundleContext ctx;
 
     /** New clients are joining through this map. */
-    private final Map<String, List<InternalResource>> newResourcesSchemes = new HashMap<String, List<InternalResource>>();
+    private final Map<String, List<InternalResource>> newResourcesSchemes = new HashMap<>();
 
     /** New resources added by clients. */
-    private final List<InternalResource> newResources = new LinkedList<InternalResource>();
+    private final List<InternalResource> newResources = new LinkedList<>();
 
     /** Removed resources from clients. */
-    private final Set<String> urlsToRemove = new HashSet<String>();
+    private final Set<String> urlsToRemove = new HashSet<>();
 
     /** Update infos to process. */
-    private final List<UpdateInfo> updateInfos = new ArrayList<OsgiInstallerImpl.UpdateInfo>();
+    private final List<UpdateInfo> updateInfos = new ArrayList<>();
 
     /** Are the required services satisfied? */
     private volatile boolean satisfied = false;
@@ -226,9 +226,9 @@ implements OsgiInstaller, ResourceChange
      */
     private void init() {
         // start service trackers
-        this.factoryTracker = new SortingServiceTracker<InstallTaskFactory>(ctx, InstallTaskFactory.class.getName(), this);
-        this.transformerTracker = new SortingServiceTracker<ResourceTransformer>(ctx, ResourceTransformer.class.getName(), this);
-        this.updateHandlerTracker = new SortingServiceTracker<UpdateHandler>(ctx, UpdateHandler.class.getName(), null);
+        this.factoryTracker = new SortingServiceTracker<>(ctx, InstallTaskFactory.class.getName(), this);
+        this.transformerTracker = new SortingServiceTracker<>(ctx, ResourceTransformer.class.getName(), this);
+        this.updateHandlerTracker = new SortingServiceTracker<>(ctx, UpdateHandler.class.getName(), null);
         this.factoryTracker.open();
         this.transformerTracker.open();
         this.updateHandlerTracker.open();
@@ -364,7 +364,7 @@ implements OsgiInstaller, ResourceChange
         checkScheme(scheme);
         List<InternalResource> createdResources = null;
         if ( resources != null && resources.length > 0 ) {
-            createdResources = new ArrayList<InternalResource>();
+            createdResources = new ArrayList<>();
             for(final InstallableResource r : resources ) {
                 try {
                     final InternalResource rr = InternalResource.create(scheme, r);
@@ -412,7 +412,7 @@ implements OsgiInstaller, ResourceChange
             synchronized ( this.resourcesLock ) {
                 if ( updatedResources != null && updatedResources.size() > 0 ) {
                     this.newResources.addAll(updatedResources);
-                    final Set<String> newUrls = new HashSet<String>();
+                    final Set<String> newUrls = new HashSet<>();
                     for(final InternalResource rsrc : updatedResources) {
                         newUrls.add(rsrc.getURL());
                     }
@@ -426,7 +426,7 @@ implements OsgiInstaller, ResourceChange
                     }
                 }
                 if ( ids != null && ids.length > 0 ) {
-                    final Set<String> removedUrls = new HashSet<String>();
+                    final Set<String> removedUrls = new HashSet<>();
                     for(final String id : ids) {
                         final String url = scheme + ':' + id;
                         // Will mark all resources which have r's URL as uninstallable
@@ -499,7 +499,7 @@ implements OsgiInstaller, ResourceChange
             this.closeInputStreams(resources);
         }
     }
-    
+
     /** When a resource from "incoming" is about to replace "existing", we might need to transfer their private
      *  data file, or delete it if it's not needed anymore.
      */
@@ -520,14 +520,14 @@ implements OsgiInstaller, ResourceChange
                     break;
                 }
             }
-            
+
             if(existing.getPrivateCopyOfFile() != null) {
                 logger.debug("Private data file not needed anymore, deleting it: {}", existing.getURL());
                 existing.getPrivateCopyOfFile().delete();
             }
         }
     }
-    
+
     private void mergeNewlyRegisteredResources() {
         synchronized ( this.resourcesLock ) {
             for(final Map.Entry<String, List<InternalResource>> entry : this.newResourcesSchemes.entrySet()) {
@@ -541,7 +541,7 @@ implements OsgiInstaller, ResourceChange
                 for(final String entityId : this.persistentList.getEntityIds()) {
                     final EntityResourceList group = this.persistentList.getEntityResourceList(entityId);
 
-                    final List<TaskResource> toRemove = new ArrayList<TaskResource>();
+                    final List<TaskResource> toRemove = new ArrayList<>();
                     boolean first = true;
                     for(final TaskResource r : group.listResources()) {
                         if ( r.getScheme().equals(scheme) ) {
@@ -639,7 +639,7 @@ implements OsgiInstaller, ResourceChange
      * Compute OSGi tasks based on our resources, and add to supplied list of tasks.
      */
     private SortedSet<InstallTask> computeTasks() {
-        final SortedSet<InstallTask> tasks = new TreeSet<InstallTask>();
+        final SortedSet<InstallTask> tasks = new TreeSet<>();
 
         // Walk the list of entities, and create appropriate OSGi tasks for each group
         final List<InstallTaskFactory> services = this.factoryTracker.getSortedServices();
@@ -911,11 +911,13 @@ implements OsgiInstaller, ResourceChange
      * @return <code>true</code> if another cycle should be started.
      */
     private boolean cleanupInstallableResources() {
-        final boolean result = this.persistentList.compact();
-        this.persistentList.save();
-        printResources("Compacted");
-        logger.debug("cleanupInstallableResources returns {}", result);
-        return result;
+        synchronized ( this.resourcesLock ) {
+            final boolean result = this.persistentList.compact();
+            this.persistentList.save();
+            printResources("Compacted");
+            logger.debug("cleanupInstallableResources returns {}", result);
+            return result;
+        }
     }
 
     /**
@@ -926,47 +928,49 @@ implements OsgiInstaller, ResourceChange
         final List<ServiceReference> serviceRefs = this.transformerTracker.getSortedServiceReferences();
 
         if ( serviceRefs.size() > 0 ) {
-            // Walk the list of unknown resources and invoke all transformers
-            int index = 0;
-            final List<RegisteredResource> unknownList = this.persistentList.getUntransformedResources();
-
-            while ( index < unknownList.size() ) {
-                final RegisteredResource resource = unknownList.get(index);
-                for(final ServiceReference reference : serviceRefs) {
-                    final Long id = (Long)reference.getProperty(Constants.SERVICE_ID);
-                    // check if this transformer has already been invoked for the resource
-                    final String transformers = (String)((RegisteredResourceImpl)resource).getAttribute(ResourceTransformer.class.getName());
-                    if ( id == null ||
-                            (transformers != null && transformers.contains(":" + id + ':'))) {
-                        continue;
-                    }
-                    final ResourceTransformer transformer = (ResourceTransformer) this.transformerTracker.getService(reference);
-                    if ( transformer != null ) {
-                        try {
-                            final TransformationResult[] result = transformer.transform(resource);
-                            final String newTransformers = (transformers == null ? ":" + id + ':' : transformers + id + ':');
-                            ((RegisteredResourceImpl)resource).setAttribute(ResourceTransformer.class.getName(), newTransformers);
-                            if ( logger.isDebugEnabled() ) {
-                                logger.debug("Invoked transformer {} on {} : {}",
-                                        new Object[] {transformer, resource, Arrays.toString(result)});
-                            }
-                            if ( result != null && result.length > 0 ) {
-                                this.persistentList.transform(resource, result);
-                                changed = true;
-                                index--;
-                                break;
+            synchronized ( this.resourcesLock ) {
+                // Walk the list of unknown resources and invoke all transformers
+                int index = 0;
+                final List<RegisteredResource> unknownList = this.persistentList.getUntransformedResources();
+
+                while ( index < unknownList.size() ) {
+                    final RegisteredResource resource = unknownList.get(index);
+                    for(final ServiceReference reference : serviceRefs) {
+                        final Long id = (Long)reference.getProperty(Constants.SERVICE_ID);
+                        // check if this transformer has already been invoked for the resource
+                        final String transformers = (String)((RegisteredResourceImpl)resource).getAttribute(ResourceTransformer.class.getName());
+                        if ( id == null ||
+                                (transformers != null && transformers.contains(":" + id + ':'))) {
+                            continue;
+                        }
+                        final ResourceTransformer transformer = (ResourceTransformer) this.transformerTracker.getService(reference);
+                        if ( transformer != null ) {
+                            try {
+                                final TransformationResult[] result = transformer.transform(resource);
+                                final String newTransformers = (transformers == null ? ":" + id + ':' : transformers + id + ':');
+                                ((RegisteredResourceImpl)resource).setAttribute(ResourceTransformer.class.getName(), newTransformers);
+                                if ( logger.isDebugEnabled() ) {
+                                    logger.debug("Invoked transformer {} on {} : {}",
+                                            new Object[] {transformer, resource, Arrays.toString(result)});
+                                }
+                                if ( result != null && result.length > 0 ) {
+                                    this.persistentList.transform(resource, result);
+                                    changed = true;
+                                    index--;
+                                    break;
+                                }
+                            } catch (final Throwable t) {
+                                logger.error("Uncaught exception during resource transformation!", t);
                             }
-                        } catch (final Throwable t) {
-                            logger.error("Uncaught exception during resource transformation!", t);
                         }
                     }
+                    index++;
                 }
-                index++;
             }
-        }
-        if ( changed ) {
-            this.persistentList.save();
-            printResources("Transformed");
+            if ( changed ) {
+                this.persistentList.save();
+                printResources("Transformed");
+            }
         }
     }
 
@@ -1077,7 +1081,7 @@ implements OsgiInstaller, ResourceChange
      * @see org.apache.sling.installer.api.ResourceChangeListener#resourceRemoved(java.lang.String, java.lang.String)
      */
     private void processUpdateInfos() {
-        final List<UpdateInfo> infos = new ArrayList<OsgiInstallerImpl.UpdateInfo>();
+        final List<UpdateInfo> infos = new ArrayList<>();
         synchronized ( resourcesLock ) {
             infos.addAll(updateInfos);
             updateInfos.clear();
@@ -1360,9 +1364,9 @@ implements OsgiInstaller, ResourceChange
         synchronized ( this.resourcesLock ) {
             final InstallationState state = new InstallationState() {
 
-                private final List<ResourceGroup> activeResources = new ArrayList<ResourceGroup>();
-                private final List<ResourceGroup> installedResources = new ArrayList<ResourceGroup>();
-                private final List<RegisteredResource> untransformedResources = new ArrayList<RegisteredResource>();
+                private final List<ResourceGroup> activeResources = new ArrayList<>();
+                private final List<ResourceGroup> installedResources = new ArrayList<>();
+                private final List<RegisteredResource> untransformedResources = new ArrayList<>();
 
                 @Override
                 public List<ResourceGroup> getActiveResources() {
@@ -1392,7 +1396,7 @@ implements OsgiInstaller, ResourceChange
                     final EntityResourceList group = this.persistentList.getEntityResourceList(entityId);
 
                     final String alias = group.getAlias();
-                    final List<Resource> resources = new ArrayList<Resource>();
+                    final List<Resource> resources = new ArrayList<>();
                     boolean first = true;
                     boolean isActive = false;
                     for(final TaskResource tr : group.getResources()) {