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; + } }