Author: radu Date: Mon Aug 31 10:55:07 2015 New Revision: 1700229 URL: http://svn.apache.org/r1700229 Log: SLING-4977 - Optimise the SightlyJavaCompilerService to provide objects faster
* changed the implementation of the UnitChangeMonitor so that repository POJOs are stored by class name instead of path * delayed repository reads in SightlyJavaCompilerService#getInstance * added tests for Java POJOs stored in bundles and the repository Added: sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/UnitChangeMonitor.java - copied, changed from r1700222, sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitChangeMonitor.java sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/Utils.java sling/trunk/bundles/scripting/sightly/testing-content/src/main/java/org/apache/sling/scripting/sightly/testing/use/ sling/trunk/bundles/scripting/sightly/testing-content/src/main/java/org/apache/sling/scripting/sightly/testing/use/Test.java sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java-pojo-bundle.html - copied, changed from r1700222, sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java.html sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java-pojo-repo.html - copied, changed from r1700222, sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java.html Removed: sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitChangeMonitor.java sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java.html Modified: sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngineFactory.java sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitLoader.java sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/JavaUseProvider.java sling/trunk/bundles/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerServiceTest.java sling/trunk/bundles/scripting/sightly/testing-content/pom.xml sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/Test.java sling/trunk/bundles/scripting/sightly/testing/pom.xml sling/trunk/bundles/scripting/sightly/testing/src/main/provisioning/model.txt sling/trunk/bundles/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/performance/PerformanceIT.java Modified: sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java?rev=1700229&r1=1700228&r2=1700229&view=diff ============================================================================== --- sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java (original) +++ sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java Mon Aug 31 10:55:07 2015 @@ -48,7 +48,6 @@ import org.apache.sling.commons.compiler import org.apache.sling.scripting.sightly.ResourceResolution; import org.apache.sling.scripting.sightly.SightlyException; import org.apache.sling.scripting.sightly.impl.engine.SightlyEngineConfiguration; -import org.apache.sling.scripting.sightly.impl.engine.UnitChangeMonitor; import org.apache.sling.scripting.sightly.impl.engine.UnitLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -96,50 +95,48 @@ public class SightlyJavaCompilerService * @return object instance of the requested class * @throws CompilerException in case of any runtime exception */ - public Object getInstance(ResourceResolver resolver, Resource callingScript, String className) { + public Object getInstance(ResourceResolver resolver, Resource callingScript, String className, boolean pojoHint) { if (className.contains(".")) { - String pojoPath = getPathFromJavaName(resolver, className); - if (unitChangeMonitor.getLastModifiedDateForJavaUseObject(pojoPath) > 0) { + if (unitChangeMonitor.getLastModifiedDateForJavaUseObject(className) > 0) { // it looks like the POJO comes from the repo and it was changed since it was last loaded - Resource pojoResource = resolver.getResource(pojoPath); - if (pojoResource != null) { - // clear the cache as we need to recompile the POJO object - unitChangeMonitor.clearJavaUseObject(pojoPath); - try { - return compileSource(IOUtils.toString(pojoResource.adaptTo(InputStream.class), "UTF-8"), className); - } catch (IOException e) { - throw new SightlyException(String.format("Unable to compile class %s from %s.", className, pojoPath), e); - } - } else { - throw new SightlyException(String.format("Resource %s identifying class %s has been removed.", pojoPath, className)); - } - } else { - try { - // the object either comes from a bundle or from the repo but it was not registered by the UnitChangeMonitor - return loadObject(className); - } catch (CompilerException cex) { - // the object definitely doesn't come from a bundle so we should attempt to compile it from the repo - Resource pojoResource = resolver.getResource(pojoPath); - if (pojoResource != null) { - try { - return compileSource(IOUtils.toString(pojoResource.adaptTo(InputStream.class), "UTF-8"), className); - } catch (IOException e) { - throw new SightlyException(String.format("Unable to compile class %s from %s.", className, pojoPath), e); - } - } - } + Object result = compileRepositoryJavaClass(resolver, className); + unitChangeMonitor.clearJavaUseObject(className); + return result; + } + if (pojoHint) { + return compileRepositoryJavaClass(resolver, className); + } + try { + // the object either comes from a bundle or from the repo but it was not registered by the UnitChangeMonitor + return loadObject(className); + } catch (CompilerException cex) { + // the object definitely doesn't come from a bundle so we should attempt to compile it from the repo + return compileRepositoryJavaClass(resolver, className); } } else { if (callingScript != null) { Resource pojoResource = ResourceResolution.getResourceFromSearchPath(callingScript, className + ".java"); if (pojoResource != null) { - return getInstance(resolver, null, getJavaNameFromPath(pojoResource.getPath())); + return getInstance(resolver, null, Utils.getJavaNameFromPath(pojoResource.getPath()), false); } } } throw new SightlyException("Cannot find class " + className + "."); } + private Object compileRepositoryJavaClass(ResourceResolver resolver, String className) { + String pojoPath = getPathFromJavaName(resolver, className); + Resource pojoResource = resolver.getResource(pojoPath); + if (pojoResource != null) { + try { + return compileSource(IOUtils.toString(pojoResource.adaptTo(InputStream.class), "UTF-8"), className); + } catch (IOException e) { + throw new SightlyException(String.format("Unable to compile class %s from %s.", className, pojoPath), e); + } + } + throw new SightlyException("Cannot find a a file corresponding to class " + className + " in the repository."); + } + /** * Compiles a class using the passed fully qualified class name and its source code. * @@ -149,6 +146,7 @@ public class SightlyJavaCompilerService * @throws CompilerException in case of any runtime exception */ public Object compileSource(String sourceCode, String fqcn) { + writeLock.lock(); try { if (sightlyEngineConfiguration.isDevMode()) { String path = "/" + fqcn.replaceAll("\\.", "/") + ".java"; @@ -157,9 +155,26 @@ public class SightlyJavaCompilerService IOUtils.closeQuietly(os); } CompilationUnit compilationUnit = new SightlyCompilationUnit(sourceCode, fqcn); - return compileJavaResource(compilationUnit); + + long start = System.currentTimeMillis(); + CompilationResult compilationResult = javaCompiler.compile(new CompilationUnit[]{compilationUnit}, options); + long end = System.currentTimeMillis(); + List<CompilerMessage> errors = compilationResult.getErrors(); + if (errors != null && errors.size() > 0) { + throw new CompilerException(CompilerException.CompilerExceptionCause.COMPILER_ERRORS, createErrorMsg(errors)); + } + if (LOG.isDebugEnabled()) { + LOG.debug("script compiled: {}", compilationResult.didCompile()); + LOG.debug("compilation took {}ms", end - start); + } + /** + * the class loader might have become dirty, so let the {@link ClassLoaderWriter} decide which class loader to return + */ + return classLoaderWriter.getClassLoader().loadClass(fqcn).newInstance(); } catch (Exception e) { throw new CompilerException(CompilerException.CompilerExceptionCause.COMPILER_ERRORS, e); + } finally { + writeLock.unlock(); } } @@ -237,8 +252,8 @@ public class SightlyJavaCompilerService * @return instance of class */ private Object loadObject(String className) { + readLock.lock(); try { - readLock.lock(); if (classLoaderWriter != null) { return classLoaderWriter.getClassLoader().loadClass(className).newInstance(); } @@ -250,35 +265,6 @@ public class SightlyJavaCompilerService } } - /** - * Compiles a class stored in the repository and returns an instance of the compiled class. - * - * @param compilationUnit a compilation unit - * @return instance of compiled class - * @throws Exception - */ - private Object compileJavaResource(CompilationUnit compilationUnit) throws Exception { - writeLock.lock(); - try { - long start = System.currentTimeMillis(); - CompilationResult compilationResult = javaCompiler.compile(new CompilationUnit[]{compilationUnit}, options); - long end = System.currentTimeMillis(); - List<CompilerMessage> errors = compilationResult.getErrors(); - if (errors != null && errors.size() > 0) { - throw new CompilerException(CompilerException.CompilerExceptionCause.COMPILER_ERRORS, createErrorMsg(errors)); - } - if (LOG.isDebugEnabled()) { - LOG.debug("script compiled: {}", compilationResult.didCompile()); - LOG.debug("compilation took {}ms", end - start); - } - return compilationResult.loadCompiledClass(compilationUnit.getMainClassName()).newInstance(); - } catch (Throwable t) { - throw new CompilerException(CompilerException.CompilerExceptionCause.COMPILER_ERRORS, t); - } finally { - writeLock.unlock(); - } - } - @Activate @SuppressWarnings("unused") protected void activate() { @@ -290,15 +276,10 @@ public class SightlyJavaCompilerService options.put(Options.KEY_SOURCE_VERSION, version); options.put(Options.KEY_TARGET_VERSION, version); options.put(Options.KEY_CLASS_LOADER_WRITER, classLoaderWriter); + options.put(Options.KEY_FORCE_COMPILATION, true); } //---------------------------------- private ----------------------------------- - private String getJavaNameFromPath(String path) { - if (path.endsWith(".java")) { - path = path.substring(0, path.length() - 5); - } - return path.substring(1).replace("/", ".").replace("-", "_"); - } private String getPathFromJavaName(ResourceResolver resolver, String className) { boolean sightlyGeneratedClass = false; Copied: sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/UnitChangeMonitor.java (from r1700222, sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitChangeMonitor.java) URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/UnitChangeMonitor.java?p2=sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/UnitChangeMonitor.java&p1=sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitChangeMonitor.java&r1=1700222&r2=1700229&rev=1700229&view=diff ============================================================================== --- sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitChangeMonitor.java (original) +++ sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/UnitChangeMonitor.java Mon Aug 31 10:55:07 2015 @@ -16,13 +16,14 @@ * specific language governing permissions and limitations * under the License. ******************************************************************************/ -package org.apache.sling.scripting.sightly.impl.engine; +package org.apache.sling.scripting.sightly.impl.compiler; import java.util.Dictionary; import java.util.Hashtable; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.apache.commons.lang.StringUtils; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; @@ -30,8 +31,11 @@ import org.apache.felix.scr.annotations. import org.apache.felix.scr.annotations.Service; import org.apache.sling.api.SlingConstants; import org.apache.sling.api.resource.LoginException; +import org.apache.sling.api.resource.ResourceMetadata; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ResourceResolverFactory; +import org.apache.sling.scripting.sightly.impl.engine.SightlyEngineConfiguration; +import org.apache.sling.scripting.sightly.impl.engine.SightlyScriptEngineFactory; import org.osgi.framework.ServiceRegistration; import org.osgi.service.component.ComponentContext; import org.osgi.service.event.Event; @@ -46,13 +50,16 @@ public class UnitChangeMonitor { private static final Logger LOG = LoggerFactory.getLogger(UnitChangeMonitor.class); - private Map<String, Long> slyScriptsMap = new ConcurrentHashMap<String, Long>(); + private Map<String, SightlyScript> slyScriptsMap = new ConcurrentHashMap<String, SightlyScript>(); private Map<String, Long> slyJavaUseMap = new ConcurrentHashMap<String, Long>(); private ServiceRegistration eventHandlerServiceRegistration; @Reference private ResourceResolverFactory rrf = null; + @Reference + private SightlyEngineConfiguration sightlyEngineConfiguration = null; + /** * Returns the last modified date for a Sightly script. * @@ -63,32 +70,62 @@ public class UnitChangeMonitor { if (script == null) { return 0; } - Long date = slyScriptsMap.get(script); - return date != null ? date : 0; + SightlyScript sightlyScript = slyScriptsMap.get(script); + if (sightlyScript != null) { + return sightlyScript.lastModified; + } + return 0; + } + + public String getScriptEncoding(String script) { + SightlyScript sightlyScript = slyScriptsMap.get(script); + return sightlyScript.encoding; } /** * Returns the last modified date for a Java Use-API object stored in the repository. * - * @param path the full path of the file defining the Java Use-API object + * @param className the full path of the file defining the Java Use-API object * @return the Java Use-API file's last modified date or 0 if there's no information about this file */ - public long getLastModifiedDateForJavaUseObject(String path) { - if (path == null) { + public long getLastModifiedDateForJavaUseObject(String className) { + if (className == null) { return 0; } - Long date = slyJavaUseMap.get(path); + Long date = slyJavaUseMap.get(className); return date != null ? date : 0; } public void touchScript(String script) { - slyScriptsMap.put(script, System.currentTimeMillis()); + SightlyScript sightlyScript = slyScriptsMap.get(script); + if (sightlyScript != null) { + sightlyScript.lastModified = System.currentTimeMillis(); + } else { + ResourceResolver resolver = null; + String encoding = null; + try { + resolver = rrf.getAdministrativeResourceResolver(null); + ResourceMetadata scriptResourceMetadata = resolver.getResource(script).getResourceMetadata(); + encoding = scriptResourceMetadata.getCharacterEncoding(); + } catch (LoginException e) { + // do nothing; we'll just return the default encoding + LOG.warn("Cannot read character encoding value for script " + script); + } finally { + if (resolver != null) { + resolver.close(); + } + } + if (StringUtils.isEmpty(encoding)) { + encoding = sightlyEngineConfiguration.getEncoding(); + } + slyScriptsMap.put(script, new SightlyScript(script, encoding, System.currentTimeMillis())); + } } - public void clearJavaUseObject(String path) { - if (path != null) { - slyJavaUseMap.remove(path); + public void clearJavaUseObject(String className) { + if (StringUtils.isNotEmpty(className)) { + slyJavaUseMap.remove(className); } } @@ -145,17 +182,48 @@ public class UnitChangeMonitor { String topic = event.getTopic(); if (SlingConstants.TOPIC_RESOURCE_ADDED.equals(topic) || SlingConstants.TOPIC_RESOURCE_CHANGED.equals(topic)) { if (path.endsWith(".java")) { - slyJavaUseMap.put(path, System.currentTimeMillis()); + slyJavaUseMap.put(Utils.getJavaNameFromPath(path), System.currentTimeMillis()); } else if (path.endsWith(SightlyScriptEngineFactory.EXTENSION)) { - slyScriptsMap.put(path, System.currentTimeMillis()); + ResourceResolver resolver = null; + String encoding = null; + try { + resolver = rrf.getAdministrativeResourceResolver(null); + ResourceMetadata scriptResourceMetadata = resolver.getResource(path).getResourceMetadata(); + encoding = scriptResourceMetadata.getCharacterEncoding(); + } catch (LoginException e) { + // do nothing; we'll just return the default encoding + LOG.warn("Cannot read character encoding value for script " + path); + } finally { + if (resolver != null) { + resolver.close(); + } + } + if (StringUtils.isEmpty(encoding)) { + encoding = sightlyEngineConfiguration.getEncoding(); + } + slyScriptsMap.put(path, new SightlyScript(path, encoding, System.currentTimeMillis())); } } else if (SlingConstants.TOPIC_RESOURCE_REMOVED.equals(topic)) { if (path.endsWith(".java")) { - slyJavaUseMap.remove(path); + slyJavaUseMap.remove(Utils.getJavaNameFromPath(path)); } else if (path.endsWith(SightlyScriptEngineFactory.EXTENSION)) { slyScriptsMap.remove(path); } } } + private class SightlyScript { + String encoding; + String className; + String path; + long lastModified; + + public SightlyScript(String path, String encoding, long lastModified) { + this.encoding = encoding; + className = Utils.getJavaNameFromPath(path); + this.path = path; + this.lastModified = lastModified; + } + } + } Added: sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/Utils.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/Utils.java?rev=1700229&view=auto ============================================================================== --- sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/Utils.java (added) +++ sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/Utils.java Mon Aug 31 10:55:07 2015 @@ -0,0 +1,28 @@ +/******************************************************************************* + * 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.sling.scripting.sightly.impl.compiler; + +public class Utils { + + public static String getJavaNameFromPath(String path) { + if (path.endsWith(".java")) { + path = path.substring(0, path.length() - 5); + } + return path.substring(1).replace("/", ".").replace("-", "_"); + } + +} Modified: sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngineFactory.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngineFactory.java?rev=1700229&r1=1700228&r2=1700229&view=diff ============================================================================== --- sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngineFactory.java (original) +++ sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngineFactory.java Mon Aug 31 10:55:07 2015 @@ -27,7 +27,7 @@ import org.apache.felix.scr.annotations. import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; -import org.apache.sling.commons.classloader.ClassLoaderWriter; +import org.apache.sling.commons.classloader.DynamicClassLoaderManager; import org.apache.sling.scripting.api.AbstractScriptEngineFactory; /** @@ -48,7 +48,7 @@ public class SightlyScriptEngineFactory private ExtensionRegistryService extensionRegistryService = null; @Reference - private ClassLoaderWriter classLoaderWriter = null; + private DynamicClassLoaderManager dynamicClassLoaderManager = null; public final static String SHORT_NAME = "sightly"; @@ -79,6 +79,6 @@ public class SightlyScriptEngineFactory } protected ClassLoader getClassLoader() { - return classLoaderWriter.getClassLoader(); + return dynamicClassLoaderManager.getDynamicClassLoader(); } } Modified: sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitLoader.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitLoader.java?rev=1700229&r1=1700228&r2=1700229&view=diff ============================================================================== --- sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitLoader.java (original) +++ sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitLoader.java Mon Aug 31 10:55:07 2015 @@ -43,6 +43,7 @@ import org.apache.sling.scripting.sightl import org.apache.sling.scripting.sightly.impl.compiler.SightlyCompilerService; import org.apache.sling.scripting.sightly.impl.compiler.SightlyJavaCompilerService; import org.apache.sling.scripting.sightly.impl.compiler.SightlyParsingException; +import org.apache.sling.scripting.sightly.impl.compiler.UnitChangeMonitor; import org.apache.sling.scripting.sightly.impl.compiler.util.GlobalShadowCheckBackend; import org.apache.sling.scripting.sightly.impl.engine.compiled.JavaClassTemplate; import org.apache.sling.scripting.sightly.impl.engine.compiled.SourceIdentifier; @@ -92,25 +93,24 @@ public class UnitLoader { * @throws Exception if the unit creation fails */ public RenderUnit createUnit(Resource scriptResource, Bindings bindings, RenderContextImpl renderContext) throws Exception { - ResourceMetadata resourceMetadata = scriptResource.getResourceMetadata(); - String encoding = resourceMetadata.getCharacterEncoding(); - if (encoding == null) { - encoding = sightlyEngineConfiguration.getEncoding(); - } - SlingHttpServletResponse response = (SlingHttpServletResponse) bindings.get(SlingBindings.RESPONSE); - response.setCharacterEncoding(encoding); ResourceResolver adminResolver = renderContext.getScriptResourceResolver(); SourceIdentifier sourceIdentifier = obtainIdentifier(scriptResource); Object obj; + String encoding; if (needsUpdate(sourceIdentifier)) { + unitChangeMonitor.touchScript(scriptResource.getPath()); + encoding = unitChangeMonitor.getScriptEncoding(scriptResource.getPath()); String sourceCode = getSourceCodeForScript(adminResolver, sourceIdentifier, bindings, encoding, renderContext); obj = sightlyJavaCompilerService.compileSource(sourceCode, sourceIdentifier.getFullyQualifiedName()); } else { - obj = sightlyJavaCompilerService.getInstance(adminResolver, null, sourceIdentifier.getFullyQualifiedName()); + encoding = unitChangeMonitor.getScriptEncoding(scriptResource.getPath()); + obj = sightlyJavaCompilerService.getInstance(adminResolver, null, sourceIdentifier.getFullyQualifiedName(), false); } if (!(obj instanceof RenderUnit)) { throw new SightlyException("Class is not a RenderUnit instance"); } + SlingHttpServletResponse response = (SlingHttpServletResponse) bindings.get(SlingBindings.RESPONSE); + response.setCharacterEncoding(encoding); return (RenderUnit) obj; } @@ -224,21 +224,10 @@ public class UnitLoader { return true; } String slyPath = sourceIdentifier.getResource().getPath(); + long slyScriptChangeDate = unitChangeMonitor.getLastModifiedDateForScript(slyPath); String javaCompilerPath = "/" + sourceIdentifier.getFullyQualifiedName().replaceAll("\\.", "/") + ".class"; long javaFileDate = classLoaderWriter.getLastModified(javaCompilerPath); - if (javaFileDate > -1) { - long slyScriptChangeDate = unitChangeMonitor.getLastModifiedDateForScript(slyPath); - if (slyScriptChangeDate != 0) { - if (slyScriptChangeDate < javaFileDate) { - return false; - } - } else { - unitChangeMonitor.touchScript(slyPath); - } - return true; - } - unitChangeMonitor.touchScript(slyPath); - return true; + return ((slyScriptChangeDate == 0 && javaFileDate > -1) || (slyScriptChangeDate > javaFileDate)); } } Modified: sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/JavaUseProvider.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/JavaUseProvider.java?rev=1700229&r1=1700228&r2=1700229&view=diff ============================================================================== --- sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/JavaUseProvider.java (original) +++ sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/JavaUseProvider.java Mon Aug 31 10:55:07 2015 @@ -34,9 +34,8 @@ import org.apache.sling.api.resource.Res import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.scripting.SlingBindings; import org.apache.sling.api.scripting.SlingScriptHelper; -import org.apache.sling.commons.classloader.DynamicClassLoaderManager; +import org.apache.sling.commons.classloader.ClassLoaderWriter; import org.apache.sling.scripting.sightly.ResourceResolution; -import org.apache.sling.scripting.sightly.impl.compiler.CompilerException; import org.apache.sling.scripting.sightly.impl.compiler.SightlyJavaCompilerService; import org.apache.sling.scripting.sightly.pojo.Use; import org.apache.sling.scripting.sightly.render.RenderContext; @@ -71,7 +70,7 @@ public class JavaUseProvider implements private SightlyJavaCompilerService sightlyJavaCompilerService = null; @Reference - private DynamicClassLoaderManager dynamicClassLoaderManager = null; + private ClassLoaderWriter classLoaderWriter = null; @Override public ProviderOutcome provide(String identifier, RenderContext renderContext, Bindings arguments) { @@ -89,7 +88,7 @@ public class JavaUseProvider implements Object result; try { - Class<?> cls = dynamicClassLoaderManager.getDynamicClassLoader().loadClass(identifier); + Class<?> cls = classLoaderWriter.getClassLoader().loadClass(identifier); result = resource.adaptTo(cls); if (result == null) { result = request.adaptTo(cls); @@ -98,7 +97,7 @@ public class JavaUseProvider implements return ProviderOutcome.success(result); } else { /** - * the object was cached by the classloader but it's not adaptable from {@link Resource} or {@link + * the object was cached by the class loader but it's not adaptable from {@link Resource} or {@link * SlingHttpServletRequest}; attempt to load it like a regular POJO that optionally could implement {@link Use} */ result = cls.newInstance(); @@ -108,27 +107,21 @@ public class JavaUseProvider implements return ProviderOutcome.notNullOrFailure(result); } } catch (ClassNotFoundException e) { - // this object might not be exported from a bundle; let's try to load it from the repository - return getPOJOFromRepository(renderContext, sling, identifier, bindings); - } catch (Exception e) { - // any other exception is an error - return ProviderOutcome.failure(e); - } finally { - resetRequestAttribute(request, overrides); - } - } - - private ProviderOutcome getPOJOFromRepository(RenderContext renderContext, SlingScriptHelper sling, String identifier, Bindings bindings) { - try { + /** + * this object is either not exported from a bundle, or it's a POJO from the repository that wasn't loaded before + */ ResourceResolver adminResolver = renderContext.getScriptResourceResolver(); - Resource resource = ResourceResolution.getResourceForRequest(adminResolver, sling.getRequest()); - Object result = sightlyJavaCompilerService.getInstance(adminResolver, resource, identifier); + Resource caller = ResourceResolution.getResourceForRequest(adminResolver, sling.getRequest()); + result = sightlyJavaCompilerService.getInstance(adminResolver, caller, identifier, true); if (result instanceof Use) { ((Use) result).init(bindings); } return ProviderOutcome.success(result); } catch (Exception e) { + // any other exception is an error return ProviderOutcome.failure(e); + } finally { + resetRequestAttribute(request, overrides); } } Modified: sling/trunk/bundles/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerServiceTest.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerServiceTest.java?rev=1700229&r1=1700228&r2=1700229&view=diff ============================================================================== --- sling/trunk/bundles/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerServiceTest.java (original) +++ sling/trunk/bundles/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerServiceTest.java Mon Aug 31 10:55:07 2015 @@ -26,13 +26,13 @@ import java.util.concurrent.ConcurrentHa import org.apache.commons.io.IOUtils; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.commons.classloader.ClassLoaderWriter; import org.apache.sling.commons.compiler.CompilationResult; import org.apache.sling.commons.compiler.CompilationUnit; import org.apache.sling.commons.compiler.CompilerMessage; import org.apache.sling.commons.compiler.JavaCompiler; import org.apache.sling.commons.compiler.Options; import org.apache.sling.scripting.sightly.impl.engine.SightlyEngineConfiguration; -import org.apache.sling.scripting.sightly.impl.engine.UnitChangeMonitor; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -42,7 +42,6 @@ import org.mockito.stubbing.Answer; import org.powermock.reflect.Whitebox; import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -52,13 +51,12 @@ public class SightlyJavaCompilerServiceT private SightlyJavaCompilerService compiler; private UnitChangeMonitor ucm; - private SightlyEngineConfiguration sightlyEngineConfiguration; @Before public void setUp() throws Exception { compiler = new SightlyJavaCompilerService(); ucm = spy(new UnitChangeMonitor()); - sightlyEngineConfiguration = mock(SightlyEngineConfiguration.class); + SightlyEngineConfiguration sightlyEngineConfiguration = mock(SightlyEngineConfiguration.class); when(sightlyEngineConfiguration.isDevMode()).thenReturn(false); Whitebox.setInternalState(compiler, "sightlyEngineConfiguration", sightlyEngineConfiguration); Whitebox.setInternalState(compiler, "unitChangeMonitor", ucm); @@ -94,13 +92,13 @@ public class SightlyJavaCompilerServiceT @Test public void testGetInstanceForCachedPojoFromRepo() throws Exception { final String pojoPath = "/apps/my-project/test_components/a/Pojo.java"; - String className = "apps.my_project.test_components.a.Pojo"; + final String className = "apps.my_project.test_components.a.Pojo"; Map<String, Long> slyJavaUseMap = new ConcurrentHashMap<String, Long>() {{ - put(pojoPath, System.currentTimeMillis()); + put(className, System.currentTimeMillis()); }}; Whitebox.setInternalState(ucm, "slyJavaUseMap", slyJavaUseMap); getInstancePojoTest(pojoPath, className); - verify(ucm).clearJavaUseObject(pojoPath); + verify(ucm).clearJavaUseObject(className); } private void getInstancePojoTest(String pojoPath, String className) throws Exception { @@ -118,8 +116,18 @@ public class SightlyJavaCompilerServiceT return MockPojo.class; } }); + ClassLoaderWriter clw = Mockito.mock(ClassLoaderWriter.class); + ClassLoader classLoader = Mockito.mock(ClassLoader.class); + when(clw.getClassLoader()).thenReturn(classLoader); + when(classLoader.loadClass(className)).thenAnswer(new Answer<Object>() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + return MockPojo.class; + } + }); + Whitebox.setInternalState(compiler, "classLoaderWriter", clw); Whitebox.setInternalState(compiler, "javaCompiler", javaCompiler); - Object obj = compiler.getInstance(resolver, null, className); + Object obj = compiler.getInstance(resolver, null, className, false); assertTrue("Expected to obtain a " + MockPojo.class.getName() + " object.", obj instanceof MockPojo); } } Modified: sling/trunk/bundles/scripting/sightly/testing-content/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/testing-content/pom.xml?rev=1700229&r1=1700228&r2=1700229&view=diff ============================================================================== --- sling/trunk/bundles/scripting/sightly/testing-content/pom.xml (original) +++ sling/trunk/bundles/scripting/sightly/testing-content/pom.xml Mon Aug 31 10:55:07 2015 @@ -205,6 +205,12 @@ <version>2.1.0</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.scripting.sightly</artifactId> + <version>1.0.2</version> + <scope>provided</scope> + </dependency> </dependencies> </project> Added: sling/trunk/bundles/scripting/sightly/testing-content/src/main/java/org/apache/sling/scripting/sightly/testing/use/Test.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/testing-content/src/main/java/org/apache/sling/scripting/sightly/testing/use/Test.java?rev=1700229&view=auto ============================================================================== --- sling/trunk/bundles/scripting/sightly/testing-content/src/main/java/org/apache/sling/scripting/sightly/testing/use/Test.java (added) +++ sling/trunk/bundles/scripting/sightly/testing-content/src/main/java/org/apache/sling/scripting/sightly/testing/use/Test.java Mon Aug 31 10:55:07 2015 @@ -0,0 +1,85 @@ +/******************************************************************************* + * 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.sling.scripting.sightly.testing.use; + +import java.util.Iterator; +import javax.script.Bindings; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.api.scripting.SlingBindings; +import org.apache.sling.scripting.sightly.pojo.Use; + +public class Test implements Use { + + public static final String PROPERTIES = "properties"; + public static final String TEXT = "text"; + public static final String TAG = "tag"; + public static final String INCLUDE_CHIDLREN = "includeChildren"; + + private String text = null; + + private String tag = null; + + private boolean includeChildren = false; + + private Iterator<Resource> children = null; + + public void init(Bindings bindings) { + Resource resource = (Resource)bindings.get(SlingBindings.RESOURCE); + ValueMap properties = (ValueMap)bindings.get(PROPERTIES); + + if (properties != null) { + text = properties.get(TEXT, resource.getPath()); + tag = properties.get(TAG, String.class); + includeChildren = properties.get(INCLUDE_CHIDLREN, false); + if (includeChildren) { + children = resource.listChildren(); + } + } + } + + public String getText() { + return this.text; + } + + public String getTag() { + return tag; + } + + public String getStartTag() { + if (tag == null) { + return null; + } + return "<" + tag + ">"; + } + + public String getEndTag() { + if (tag == null) { + return null; + } + return "</" + tag + ">"; + } + + public boolean getIncludeChildren() { + return includeChildren; + } + + public Iterator<Resource> getChildren() { + return this.children; + } +} \ No newline at end of file Modified: sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/Test.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/Test.java?rev=1700229&r1=1700228&r2=1700229&view=diff ============================================================================== --- sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/Test.java (original) +++ sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/Test.java Mon Aug 31 10:55:07 2015 @@ -24,10 +24,16 @@ import javax.script.Bindings; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.api.scripting.SlingBindings; import org.apache.sling.scripting.sightly.pojo.Use; public class Test implements Use { + public static final String PROPERTIES = "properties"; + public static final String TEXT = "text"; + public static final String TAG = "tag"; + public static final String INCLUDE_CHIDLREN = "includeChildren"; + private String text = null; private String tag = null; @@ -37,29 +43,16 @@ public class Test implements Use { private Iterator<Resource> children = null; public void init(Bindings bindings) { - Resource resource = (Resource)bindings.get("resource"); - ValueMap properties = (ValueMap)bindings.get("properties"); + Resource resource = (Resource)bindings.get(SlingBindings.RESOURCE); + ValueMap properties = (ValueMap)bindings.get(PROPERTIES); if (properties != null) { - Object text = properties.get("text"); - if (text != null) { - this.text = text.toString(); - } - - Object tag = properties.get("tag"); - if (tag != null) { - this.tag = tag.toString(); + text = properties.get(TEXT, resource.getPath()); + tag = properties.get(TAG, String.class); + includeChildren = properties.get(INCLUDE_CHIDLREN, false); + if (includeChildren) { + children = resource.listChildren(); } - - Object includeChildren = properties.get("includeChildren"); - if (includeChildren != null) { - this.includeChildren = Boolean.parseBoolean(includeChildren.toString()); - this.children = resource.listChildren(); - } - } - - if (this.text == null) { - this.text = resource.getPath(); } } Copied: sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java-pojo-bundle.html (from r1700222, sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java.html) URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java-pojo-bundle.html?p2=sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java-pojo-bundle.html&p1=sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java.html&r1=1700222&r2=1700229&rev=1700229&view=diff ============================================================================== --- sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java.html (original) +++ sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java-pojo-bundle.html Mon Aug 31 10:55:07 2015 @@ -16,7 +16,7 @@ ~ specific language governing permissions and limitations ~ under the License. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/--> -<div data-sly-use.test="apps.sightlyperf.test.Test" data-sly-unwrap> +<div data-sly-use.test="org.apache.sling.scripting.sightly.testing.use.Test" data-sly-unwrap> ${test.tag != null ? test.startTag : '' @ context = "unsafe"} ${test.text @ context = "text"} ${test.tag != null ? test.endTag : '' @ context = "unsafe"} Copied: sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java-pojo-repo.html (from r1700222, sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java.html) URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java-pojo-repo.html?p2=sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java-pojo-repo.html&p1=sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightlyperf/test/sly-java.html&r1=1700222&r2=1700229&rev=1700229&view=diff ============================================================================== (empty) Modified: sling/trunk/bundles/scripting/sightly/testing/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/testing/pom.xml?rev=1700229&r1=1700228&r2=1700229&view=diff ============================================================================== --- sling/trunk/bundles/scripting/sightly/testing/pom.xml (original) +++ sling/trunk/bundles/scripting/sightly/testing/pom.xml Mon Aug 31 10:55:07 2015 @@ -165,7 +165,7 @@ <server> <port>${http.port}</port> <controlPort>${sling.control.port}</controlPort> - <runmode>jackrabbit</runmode> + <runmode>oak</runmode> <contextPath>${http.base.path}</contextPath> <debug>${debug.options}</debug> </server> Modified: sling/trunk/bundles/scripting/sightly/testing/src/main/provisioning/model.txt URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/testing/src/main/provisioning/model.txt?rev=1700229&r1=1700228&r2=1700229&view=diff ============================================================================== --- sling/trunk/bundles/scripting/sightly/testing/src/main/provisioning/model.txt (original) +++ sling/trunk/bundles/scripting/sightly/testing/src/main/provisioning/model.txt Mon Aug 31 10:55:07 2015 @@ -16,7 +16,7 @@ # specific language governing permissions and limitations # under the License. # -[feature name=launchpad-testing] +[feature name=sling] # Dependencies [artifacts] org.apache.sling/org.apache.sling.launchpad/8-SNAPSHOT/slingstart @@ -28,9 +28,14 @@ # additional configuration for testing [configurations] - org.apache.sling.servlets.resolver.SlingServletResolver - # Set the servlet resolver's cache size to zero for testing - servletresolver.cacheSize=I"0" + org.apache.sling.jcr.webdav.impl.servlets.SimpleWebDavServlet + dav.root="/dav" + + org.apache.sling.commons.log.LogManager.factory.config-2ef75700-a318-4eae-bed4-86777e1bdfd2 + org.apache.sling.commons.log.pattern="{0,date,dd.MM.yyyy\ HH:mm:ss.SSS}\ *{4}*\ [{2}]\ {3}\ {5}" + org.apache.sling.commons.log.names=["org.apache.sling.scripting.sightly.js.impl.jsapi.ProxyAsyncScriptableFactory"] + org.apache.sling.commons.log.file="logs/error.log" + org.apache.sling.commons.log.level="error" [settings] sling.system.packages.class.com.vladium.emma.rt.RT=com.vladium.emma.rt Modified: sling/trunk/bundles/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/performance/PerformanceIT.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/performance/PerformanceIT.java?rev=1700229&r1=1700228&r2=1700229&view=diff ============================================================================== --- sling/trunk/bundles/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/performance/PerformanceIT.java (original) +++ sling/trunk/bundles/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/performance/PerformanceIT.java Mon Aug 31 10:55:07 2015 @@ -92,19 +92,25 @@ public class PerformanceIT { } @PerformanceTest(runinvocations = INVOCATIONS, warmupinvocations = WARMUP_INVOCATIONS, threshold = 2) - public void test3SlyJava() { - getStringContent("/sightlyperf/loop.html?selector=sly-java&count=" + CONTENT_LOOP_COUNT, + public void test3SlyJavaPojoRepo() { + getStringContent("/sightlyperf/loop.html?selector=sly-java-pojo-repo&count=" + CONTENT_LOOP_COUNT, HttpStatus.SC_OK); } - @PerformanceTest(runinvocations = INVOCATIONS, warmupinvocations = WARMUP_INVOCATIONS, threshold = 8) - public void test4SlyJSAsync() { + @PerformanceTest(runinvocations = INVOCATIONS, warmupinvocations = WARMUP_INVOCATIONS, threshold = 2) + public void test4SlyJavaPojoBundle() { + getStringContent("/sightlyperf/loop.html?selector=sly-java-pojo-bundle&count=" + CONTENT_LOOP_COUNT, + HttpStatus.SC_OK); + } + + @PerformanceTest(runinvocations = INVOCATIONS, warmupinvocations = WARMUP_INVOCATIONS, threshold = 4) + public void test5SlyJSAsync() { getStringContent("/sightlyperf/loop.html?selector=sly-js-async&count=" + CONTENT_LOOP_COUNT, HttpStatus.SC_OK); } - @PerformanceTest(runinvocations = INVOCATIONS, warmupinvocations = WARMUP_INVOCATIONS, threshold = 8) - public void test5SlyJSSync() { + @PerformanceTest(runinvocations = INVOCATIONS, warmupinvocations = WARMUP_INVOCATIONS, threshold = 4) + public void test6SlyJSSync() { getStringContent("/sightlyperf/loop.html?selector=sly-js-sync&count=" + CONTENT_LOOP_COUNT, HttpStatus.SC_OK); }