package org.apache.sling.webresource.eventhandlers; import java.util.ArrayList; import java.util.Dictionary; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.query.InvalidQueryException; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.sling.jcr.api.SlingRepository; import org.apache.sling.webresource.WebResourceInventoryManager; import org.apache.sling.webresource.WebResourceScriptCache; import org.apache.sling.webresource.exception.WebResourceCompileException; import org.apache.sling.webresource.model.WebResourceGroup; import org.osgi.framework.BundleContext; import org.osgi.service.component.ComponentContext; import org.osgi.service.event.Event; import org.osgi.service.event.EventAdmin; import org.osgi.service.event.EventConstants; import org.osgi.service.event.EventHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component(metatype = true, immediate = true) public class BackgroundCompilerHandler implements EventHandler { @Reference private SlingRepository repository; @Reference private WebResourceScriptCache webResourceScriptCache; @Reference private WebResourceInventoryManager webResourceInventoryManager; @Reference private EventAdmin eventAdmin; private ExecutorService executorService; private BundleContext bundleContext; private final Logger log = LoggerFactory.getLogger(getClass()); protected void activate(ComponentContext context) { bundleContext = context.getBundleContext(); this.executorService = Executors.newFixedThreadPool(4); compilePaths(new ArrayList<String>( this.webResourceInventoryManager.getAllWebResourcePaths())); String[] compileTopics = new String[] { WebResourceInventoryManager.COMPILE_EVENT, WebResourceInventoryManager.COMPILE_ALL_EVENT }; Dictionary<String, Object> backgroundCompilerProps = new Hashtable<String, Object>(); backgroundCompilerProps.put(EventConstants.EVENT_TOPIC, compileTopics); bundleContext.registerService(EventHandler.class.getName(), this, backgroundCompilerProps); log.debug("Background Compiler Activated"); } @Override public void handleEvent(Event event) { List<String> paths = null; if (event.getTopic().equals( WebResourceInventoryManager.COMPILE_ALL_EVENT)) { paths = new ArrayList<String>( this.webResourceInventoryManager.getAllWebResourcePaths()); } else { paths = (List<String>) event.getProperty("paths"); } compilePaths(paths); } private void compilePaths(final List<String> paths) { Runnable compileTask = new Runnable() { private List<String> pathList = paths; @Override public void run() { Iterator<String> pendingWebResourcePathIt = this.pathList .iterator(); // Find all web resource nodes log.info("Checking for Web Resource Group Paths that need compilation"); // Compile all web resource nodes if (pendingWebResourcePathIt.hasNext()) { processPendingWebRequests(pendingWebResourcePathIt); } } }; this.executorService.submit(compileTask); } private void processPendingWebRequests(Iterator<String> pendingWebRequestIt) { Session jcrSession = null; log.info("Starting Background Compile"); try { jcrSession = repository.loginAdministrative(null); if (jcrSession != null) { while (pendingWebRequestIt.hasNext()) { try { Node currentWebResourceGroup = jcrSession .getNode(pendingWebRequestIt.next()); log.info("Compiling: " + currentWebResourceGroup.getPath()); WebResourceGroup webResourceGroup = new WebResourceGroup( currentWebResourceGroup); Map<String, List<String>> webResourceGroupPaths = webResourceScriptCache .getCompiledWebResourceGroupPaths(jcrSession, webResourceGroup.getName(), true); if (currentWebResourceGroup .hasNode(WebResourceGroup.INVENTORY)) { currentWebResourceGroup.getNode( WebResourceGroup.INVENTORY).remove(); } Node inventoryNode = currentWebResourceGroup.addNode( WebResourceGroup.INVENTORY, "webresource:Inventory"); for (Entry<String, List<String>> currentWebResourceTypeEntry : webResourceGroupPaths .entrySet()) { String[] webResourcePaths = currentWebResourceTypeEntry .getValue().toArray(new String[0]); inventoryNode.setProperty( currentWebResourceTypeEntry.getKey(), webResourcePaths); } jcrSession.save(); pendingWebRequestIt.remove(); } catch (InvalidQueryException e) { log.error("Unable to compile WebResource", e); } catch (RepositoryException e) { log.error("Unable to compile WebResource", e); } catch (WebResourceCompileException e) { log.error("Unable to compile WebResource", e); } } } } catch (RepositoryException e) { log.error("Unable to login as admin", e); } finally { if (jcrSession != null) { jcrSession.logout(); } } } public void setRepository(SlingRepository repository) { this.repository = repository; } public void setWebResourceScriptCache( WebResourceScriptCache webResourceScriptCache) { this.webResourceScriptCache = webResourceScriptCache; } }