Author: cziegeler
Date: Sat Jan 22 17:12:36 2011
New Revision: 1062205

URL: http://svn.apache.org/viewvc?rev=1062205&view=rev
Log:
SLING-1946 : Transformer should only be invoked once on an untransformed 
resource

Modified:
    
sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java
    
sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java
    
sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/SortingServiceTracker.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=1062205&r1=1062204&r2=1062205&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
 Sat Jan 22 17:12:36 2011
@@ -47,8 +47,10 @@ import org.apache.sling.installer.api.ta
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
 import org.osgi.framework.BundleListener;
+import org.osgi.framework.Constants;
 import org.osgi.framework.FrameworkEvent;
 import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -542,30 +544,42 @@ public class OsgiInstallerImpl
     private void transformResources() {
         boolean changed = false;
 
-        final List<ResourceTransformer> services = 
this.transformerTracker.getSortedServices();
+        final List<ServiceReference> serviceRefs = 
this.transformerTracker.getSortedServiceReferences();
 
-        if ( services.size() > 0 ) {
+        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 ResourceTransformer transformer : services) {
-                    try {
-                        final TransformationResult[] result = 
transformer.transform(resource);
-                        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;
+                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++;
@@ -600,7 +614,7 @@ public class OsgiInstallerImpl
             eventsCount++;
         }
         final int t = e.getType();
-        if(t == BundleEvent.INSTALLED || t == BundleEvent.RESOLVED || t == 
BundleEvent.STARTED || t == BundleEvent.UPDATED) {
+        if (t == BundleEvent.INSTALLED || t == BundleEvent.RESOLVED || t == 
BundleEvent.STARTED || t == BundleEvent.UPDATED) {
             logger.debug("Received BundleEvent that might allow installed 
bundles to start, scheduling retries if any");
             // TODO - for now we always reschedule regardless if we have 
retries
             // If the config task factory is only registered when config admin 
is available we can relax this again.

Modified: 
sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java?rev=1062205&r1=1062204&r2=1062205&view=diff
==============================================================================
--- 
sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java
 (original)
+++ 
sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java
 Sat Jan 22 17:12:36 2011
@@ -479,6 +479,7 @@ public class RegisteredResourceImpl
                 this.digest,
                 this.priority,
                 this.urlScheme);
+        rr.attributes.putAll(this.attributes);
         rr.update(transformationResult);
 
         return rr;

Modified: 
sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/SortingServiceTracker.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/SortingServiceTracker.java?rev=1062205&r1=1062204&r2=1062205&view=diff
==============================================================================
--- 
sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/SortingServiceTracker.java
 (original)
+++ 
sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/SortingServiceTracker.java
 Sat Jan 22 17:12:36 2011
@@ -38,8 +38,12 @@ public class SortingServiceTracker<T>
 
     private int lastCount = -1;
 
+    private int lastRefCount = -1;
+
     private List<T> sortedServiceCache;
 
+    private List<ServiceReference> sortedReferences;
+
     /**
      * Constructor
      */
@@ -56,6 +60,7 @@ public class SortingServiceTracker<T>
     @Override
     public void removedService(ServiceReference reference, Object service) {
         this.sortedServiceCache = null;
+        this.sortedReferences = null;
         this.context.ungetService(reference);
     }
 
@@ -65,6 +70,7 @@ public class SortingServiceTracker<T>
     @Override
     public void modifiedService(ServiceReference reference, Object service) {
         this.sortedServiceCache = null;
+        this.sortedReferences = null;
     }
 
     /**
@@ -73,15 +79,15 @@ public class SortingServiceTracker<T>
     @Override
     public Object addingService(ServiceReference reference) {
         this.sortedServiceCache = null;
-        // new factory has been added, wake up main thread
+        this.sortedReferences = null;
+        // new factory or resource transformer has been added, wake up main 
thread
         this.listener.wakeUp();
         return context.getService(reference);
     }
 
     /**
-     * Return a sorted array of the services.
+     * Return a sorted list of the services.
      */
-    @SuppressWarnings("unchecked")
     public List<T> getSortedServices() {
         if ( this.sortedServiceCache == null || this.lastCount < 
this.getTrackingCount() ) {
             this.lastCount = this.getTrackingCount();
@@ -92,6 +98,7 @@ public class SortingServiceTracker<T>
                 Arrays.sort(references);
                 this.sortedServiceCache = new ArrayList<T>();
                 for(int i=0;i<references.length;i++) {
+                    @SuppressWarnings("unchecked")
                     final T service = 
(T)this.getService(references[references.length - 1 - i]);
                     if ( service != null ) {
                         this.sortedServiceCache.add(service);
@@ -101,4 +108,24 @@ public class SortingServiceTracker<T>
         }
         return this.sortedServiceCache;
     }
+
+    /**
+     * Return a sorted list of the services references.
+     */
+    public List<ServiceReference> getSortedServiceReferences() {
+        if ( this.sortedReferences == null || this.lastRefCount < 
this.getTrackingCount() ) {
+            this.lastRefCount = this.getTrackingCount();
+            final ServiceReference[] references = this.getServiceReferences();
+            if ( references == null || references.length == 0 ) {
+                this.sortedReferences = Collections.emptyList();
+            } else {
+                Arrays.sort(references);
+                this.sortedReferences = new ArrayList<ServiceReference>();
+                for(int i=0;i<references.length;i++) {
+                    this.sortedReferences.add(references[i]);
+                }
+            }
+        }
+        return this.sortedReferences;
+    }
 }


Reply via email to