You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by we...@apache.org on 2009/09/09 09:14:31 UTC
svn commit: r812796 - in /myfaces/extensions/scripting/trunk: ./
core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/
core/ core/src/main/java/org/apache/myfaces/scripting/api/
core/src/main/java/org/apache/myfaces/scripting/core/...
Author: werpu
Date: Wed Sep 9 07:14:30 2009
New Revision: 812796
URL: http://svn.apache.org/viewvc?rev=812796&view=rev
Log:
http://issues.apache.org/jira/browse/EXTSCRIPT-13
Added:
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/_ScriptingClass.java
Modified:
myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/CompilerFacade.java
myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/ContainerFileManager.java
myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/RecompiledClassLoader.java
myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/ReflectCompilerFacade.java
myfaces/extensions/scripting/trunk/core/pom.xml
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/api/BaseWeaver.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/api/DynamicCompiler.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/core/CoreWeaver.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/core/util/ClassUtils.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/factories/ScriptingApplicationFactory.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/NavigationHandlerProxy.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/VariableResolverProxy.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/ViewHandlerProxy.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/groovy/DynamicClassIdentifier.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/DynamicClassIdentifier.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/JavaScriptingWeaver.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/ScriptingClass.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/jci/CompilerFacade.java
myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/refresh/FileChangedDaemon.java
myfaces/extensions/scripting/trunk/pom.xml
Modified: myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/CompilerFacade.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/CompilerFacade.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/CompilerFacade.java (original)
+++ myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/CompilerFacade.java Wed Sep 9 07:14:30 2009
@@ -19,6 +19,7 @@
package org.apache.myfaces.scripting.loaders.java.jsr199;
import org.apache.myfaces.scripting.api.DynamicCompiler;
+import org.apache.myfaces.scripting.core.util.ClassUtils;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
@@ -36,31 +37,50 @@
* @version $Revision: 812255 $ $Date: 2009-09-07 20:51:39 +0200 (Mo, 07 Sep 2009) $
*/
public class CompilerFacade implements DynamicCompiler {
- //TODO add optional ecj dependencies here
- JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+
+ JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector();
ContainerFileManager fileManager = null;
private static final String FILE_SEPARATOR = File.separator;
public CompilerFacade() {
super();
+ fileManager = new ContainerFileManager(javaCompiler.getStandardFileManager(diagnosticCollector, null, null));
+ if (javaCompiler == null) {
+ //TODO add other compilers as fallbacks here eclipse ecq being the first
+ }
+ }
- //TODO move this all into the introspection domain
- //so that we can shift to jdk5
- fileManager = new ContainerFileManager(compiler.getStandardFileManager(diagnosticCollector, null, null));
+ //ok this is a point of no return we cannot avoid it thanks to the dreaded
+ //windows file locking, but since this is not for production we can live with it
+ public Class compileFile(String sourceRoot, String classPath, String relativeFileName) throws ClassNotFoundException {
- }
+ Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects(sourceRoot + FILE_SEPARATOR + relativeFileName);
+ String[] options = new String[]{"-cp", fileManager.getClassPath(), "-d", fileManager.getTempDir().getAbsolutePath(), "-sourcepath", sourceRoot, "-g"};
+ javaCompiler.getTask(null, fileManager, diagnosticCollector, Arrays.asList(options), null, fileObjects).call();
+ handleDiagnostics(diagnosticCollector);
+
+ //now we do a dynamic bytecode reingeneering, to add the needed interfaces
+ //so that we can locate the dynamically compiled jsf artefact in a non blocking way.
+ String className = ClassUtils.relativeFileToClassName(relativeFileName);
+ ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+ if (!(oldClassLoader instanceof RecompiledClassLoader)) {
+ try {
+ RecompiledClassLoader classLoader = (RecompiledClassLoader) fileManager.getClassLoader(null);
+ Thread.currentThread().setContextClassLoader(classLoader);
- public Class compileFile(String sourceRoot, String classPath, String filePath) throws ClassNotFoundException {
- Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects(sourceRoot + FILE_SEPARATOR + filePath);
+ ClassUtils.markAsDynamicJava(fileManager.getTempDir().getAbsolutePath(), className);
- //TODO add the core jar from our lib dir
- //the compiler otherwise cannot find the file
- String[] options = new String[]{"-cp", fileManager.getClassPath(), "-d", fileManager.getTempDir().getAbsolutePath(), "-sourcepath", sourceRoot, "-g"};
- compiler.getTask(null, fileManager, diagnosticCollector, Arrays.asList(options), null, fileObjects).call();
- //TODO collect the diagnostics and if an error was issued dump it on the log
- //and throw an unmanaged exeption which routes later on into myfaces
+ return classLoader.loadClass(className);
+ } finally {
+ Thread.currentThread().setContextClassLoader(oldClassLoader);
+ }
+ }
+ return null;
+ }
+
+ private void handleDiagnostics(DiagnosticCollector<JavaFileObject> diagnosticCollector) throws ClassNotFoundException {
if (diagnosticCollector.getDiagnostics().size() > 0) {
Log log = LogFactory.getLog(this.getClass());
StringBuilder errors = new StringBuilder();
@@ -75,20 +95,6 @@
}
throw new ClassNotFoundException("Compile error of java file:" + errors.toString());
}
-
- ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
- if (!(oldClassLoader instanceof RecompiledClassLoader)) {
- try {
- RecompiledClassLoader classLoader = (RecompiledClassLoader) fileManager.getClassLoader(null);
- Thread.currentThread().setContextClassLoader(classLoader);
- String classFile = filePath.replaceAll("\\\\", ".").replaceAll("\\/", ".");
- classFile = classFile.substring(0, classFile.lastIndexOf("."));
-
- return classLoader.loadClass(classFile);
- } finally {
- Thread.currentThread().setContextClassLoader(oldClassLoader);
- }
- }
- return null;
}
+
}
\ No newline at end of file
Modified: myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/ContainerFileManager.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/ContainerFileManager.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/ContainerFileManager.java (original)
+++ myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/ContainerFileManager.java Wed Sep 9 07:14:30 2009
@@ -18,17 +18,16 @@
*/
package org.apache.myfaces.scripting.loaders.java.jsr199;
-import javax.tools.*;
-import java.io.IOException;
+import org.apache.myfaces.shared_impl.util.ClassUtils;
+
+import javax.tools.FileObject;
+import javax.tools.ForwardingJavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
import java.io.File;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.ArrayList;
-import java.util.List;
-import java.net.URLClassLoader;
+import java.io.IOException;
import java.net.URL;
-
-import org.apache.myfaces.shared_impl.util.ClassUtils;
+import java.net.URLClassLoader;
/**
Modified: myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/RecompiledClassLoader.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/RecompiledClassLoader.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/RecompiledClassLoader.java (original)
+++ myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/RecompiledClassLoader.java Wed Sep 9 07:14:30 2009
@@ -18,6 +18,8 @@
*/
package org.apache.myfaces.scripting.loaders.java.jsr199;
+import org.apache.myfaces.scripting.core.util.ClassUtils;
+
import java.io.File;
import java.io.FileInputStream;
@@ -28,6 +30,8 @@
public class RecompiledClassLoader extends ClassLoader {
File tempDir = null;
+ static double _tempMarker = Math.random();
+
RecompiledClassLoader(ClassLoader classLoader) {
super(classLoader);
@@ -36,8 +40,9 @@
if (tempDir != null) {
return;
}
+
String baseTempPath = System.getProperty("java.io.tmpdir");
- String tempDirName = "myfaces_compilation_" + Math.random();
+ String tempDirName = "myfaces_compilation_" + _tempMarker;
tempDir = new File(baseTempPath + File.separator + tempDirName);
while (tempDir.exists()) {
@@ -57,8 +62,7 @@
@Override
public Class<?> loadClass(String className) throws ClassNotFoundException {
//check if our class exists in the tempDir
- String classFile = className.replaceAll("\\.", File.separator) + ".class";
- File target = new File(tempDir.getAbsolutePath() + File.separator + classFile);
+ File target = getClassFile(className);
if (target.exists()) {
FileInputStream iStream = null;
@@ -86,6 +90,10 @@
return super.loadClass(className); //To change body of overridden methods use File | Settings | File Templates.
}
+ public File getClassFile(String className) {
+ return ClassUtils.classNameToFile(tempDir.getAbsolutePath(), className);
+ }
+
public File getTempDir() {
return tempDir;
}
Modified: myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/ReflectCompilerFacade.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/ReflectCompilerFacade.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/ReflectCompilerFacade.java (original)
+++ myfaces/extensions/scripting/trunk/core-java6/src/main/java/org/apache/myfaces/scripting/loaders/java/jsr199/ReflectCompilerFacade.java Wed Sep 9 07:14:30 2009
@@ -22,7 +22,6 @@
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.scripting.core.util.Null;
import org.apache.myfaces.scripting.core.util.Cast;
-import org.apache.myfaces.scripting.core.util.Array;
import org.apache.myfaces.scripting.core.util.ClassUtils;
@@ -33,11 +32,8 @@
import java.util.Collection;
import java.nio.charset.Charset;
-import static org.apache.myfaces.scripting.core.util.ClassUtils.*;
import org.apache.myfaces.scripting.api.DynamicCompiler;
-import javax.tools.StandardJavaFileManager;
-
/**
* @author Werner Punz (latest modification by $Author$)
* @version $Revision$ $Date$
@@ -72,7 +68,7 @@
Object fileObjects = ClassUtils.executeFunction(fileManager, "getJavaFileObjectsSingle", sourceRoot + FILE_SEPARATOR + filePath) ;
//TODO add the core jar from our lib dir
- //the compiler otherwise cannot find the file
+ //the javaCompiler otherwise cannot find the file
String[] options = new String[]{"-cp",
(String) ClassUtils.executeFunction(fileManager, "getClassPath"), "-d", (String) ClassUtils.executeFunction(ClassUtils.executeFunction(fileManager, "getTempDir"), "getAbsolutePath"), "-sourcepath", sourceRoot, "-g"};
Modified: myfaces/extensions/scripting/trunk/core/pom.xml
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/pom.xml?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/pom.xml (original)
+++ myfaces/extensions/scripting/trunk/core/pom.xml Wed Sep 9 07:14:30 2009
@@ -1,6 +1,6 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns = "http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core</artifactId>
<packaging>jar</packaging>
@@ -25,7 +25,7 @@
</repositories>
<dependencies>
-
+
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
@@ -54,6 +54,25 @@
<artifactId>commons-beanutils</artifactId>
<version>1.8.0</version>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.bcel</groupId>
+ <artifactId>bcel</artifactId>
+ <version>5.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-jci-core</artifactId>
+ <version>1.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-jci-javac</artifactId>
+ <version>1.0</version>
+ </dependency>
+
</dependencies>
<build>
@@ -80,10 +99,8 @@
</dependency>
</dependencies>
</plugin>
-
+
</plugins>
</build>
-
-
</project>
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/api/BaseWeaver.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/api/BaseWeaver.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/api/BaseWeaver.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/api/BaseWeaver.java Wed Sep 9 07:14:30 2009
@@ -26,7 +26,7 @@
* initialisation code so no thread safety needed
*/
protected List<String> scriptPaths = new LinkedList<String>();
-
+
public BaseWeaver() {
//work around for yet another groovy bug
@@ -38,7 +38,6 @@
}
-
/**
* add custom source lookup paths
*
@@ -124,15 +123,22 @@
if (metadata == null)
return aclass;
- if(!assertScriptingEngine(metadata)) {
+ if (!assertScriptingEngine(metadata)) {
return null;
}
if (!metadata.isTainted()) {
//if not tained then we can recycle the last class loaded
return metadata.getAClass();
}
-
- return loadScriptingClassFromFile(metadata.getSourcePath(), metadata.getFileName());
+ synchronized (BaseWeaver.class) {
+ //another chance just in case someone has reloaded between
+ //the last if and synchronized, that way we can reduce the number of waiting threads
+ if (!metadata.isTainted()) {
+ //if not tained then we can recycle the last class loaded
+ return metadata.getAClass();
+ }
+ return loadScriptingClassFromFile(metadata.getSourcePath(), metadata.getFileName());
+ }
}
/**
@@ -142,11 +148,10 @@
* @return a valid class if the sources could be found null if nothing could be found
*/
public Class loadScriptingClassFromName(String className) {
- if(className.contains("TestBean2")) {
- getLog().debug("debugpoint found");
+ if (className.contains("TestBean2")) {
+ getLog().debug("debugpoint found");
}
-
Map<String, ReloadingMetadata> classMap = getClassMap();
ReloadingMetadata metadata = classMap.get(className);
if (metadata == null) {
@@ -156,9 +161,19 @@
//already given in the Groovy classloader, this needs further testing
for (String pathEntry : getScriptPaths()) {
- Class retVal = (Class) loadScriptingClassFromFile(pathEntry, fileName);
- if (retVal != null) {
- return retVal;
+ /**
+ * the reload has to be performed synchronized
+ * hence there is no chance to do it unsynchronized
+ */
+ synchronized (BaseWeaver.class) {
+ metadata = classMap.get(className);
+ if (metadata != null) {
+ return reloadScriptingClass(metadata.getAClass());
+ }
+ Class retVal = (Class) loadScriptingClassFromFile(pathEntry, fileName);
+ if (retVal != null) {
+ return retVal;
+ }
}
}
@@ -209,6 +224,7 @@
}
protected abstract void mapProperties(Object target, Object src);
+
protected abstract Class loadScriptingClassFromFile(String sourceRoot, String file);
public abstract boolean isDynamic(Class clazz);
@@ -217,5 +233,4 @@
return scriptPaths;
}
-
}
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/api/DynamicCompiler.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/api/DynamicCompiler.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/api/DynamicCompiler.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/api/DynamicCompiler.java Wed Sep 9 07:14:30 2009
@@ -19,21 +19,26 @@
package org.apache.myfaces.scripting.api;
/**
- * @author Werner Punz
- * Interface marking generic compiler facades which can
- * plug various compiler backends into our system
- * (for now jsr 199 is supported but in the long run JCI will
- * be integrated for pre 1.6 jdks)
+ * @author Werner Punz
+ * Interface marking generic compiler facades which can
+ * plug various compiler backends into our system
+ * (for now jsr 199 is supported but in the long run JCI will
+ * be integrated for pre 1.6 jdks)
+ * <p/>
+ * Note the class does not have to be thread safe, the
+ * callers have to take care of the synchronisation
+ * the class is definitely called synchronized to avoid
+ * the windows file locking issues
*/
public interface DynamicCompiler {
- /**
+ /**
* compiles a single file into a class
*
- * @param sourceRoot the source search path (root of our source)
- * @param filePath the relative path of our file
+ * @param sourceRoot the source search path (root of our source)
+ * @param filePath the relative path of our file
* @return a valid java class of our file
* @throws ClassNotFoundException in case of the class neither could be found
- * in our sources nor could be referenced in binary form from the classloader
+ * in our sources nor could be referenced in binary form from the classloader
*/
Class compileFile(String sourceRoot, String classPath, String filePath) throws ClassNotFoundException;
}
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/core/CoreWeaver.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/core/CoreWeaver.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/core/CoreWeaver.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/core/CoreWeaver.java Wed Sep 9 07:14:30 2009
@@ -38,9 +38,6 @@
List<ScriptingWeaver> _weavers = new ArrayList<ScriptingWeaver>();
public CoreWeaver(ScriptingWeaver... weavers) {
- //_groovyWeaver = groovyWeaver;
- //_javaWeaver = javaWeaver;
-
for (ScriptingWeaver weaver : weavers) {
_weavers.add(weaver);
}
@@ -83,10 +80,6 @@
@Override
public Class loadScriptingClassFromName(String className) {
- if (className.contains("TestBean2")) {
- System.out.println("Debugpoint found");
- }
-
for (ScriptingWeaver weaver : _weavers) {
Class retVal = weaver.loadScriptingClassFromName(className);
if (retVal != null) {
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/core/util/ClassUtils.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/core/util/ClassUtils.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/core/util/ClassUtils.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/core/util/ClassUtils.java Wed Sep 9 07:14:30 2009
@@ -19,13 +19,22 @@
package org.apache.myfaces.scripting.core.util;
+import org.apache.bcel.util.SyntheticRepository;
+import org.apache.bcel.util.ClassPath;
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.generic.ClassGen;
+
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Constructor;
+import java.io.IOException;
+import java.io.File;
/**
* @author werpu
- * helper class to bypass a groovy related bug
+ * <p/>
+ * A generic utils class dealing with different aspects
+ * (naming and reflection) of java classes
*/
public class ClassUtils {
@@ -229,4 +238,46 @@
return new Null(clazz);
}
+
+ /**
+ * we use the BCEL here to add a marker interface dynamically on the compiled java class
+ * so that later we can identify the marked class as being of dynamic origin
+ * that way we dont have to hammer any data structure but can work over introspection
+ * to check for an implemented marker interface
+ *
+ * @param classPath the root classPath which hosts our class
+ * @param className the className from the class which has to be rewritten
+ * @throws ClassNotFoundException
+ */
+ public static void markAsDynamicJava(String classPath, String className) throws ClassNotFoundException {
+ SyntheticRepository repo = SyntheticRepository.getInstance(new ClassPath(classPath));
+ JavaClass javaClass = repo.loadClass(className);
+ ClassGen classGen = new ClassGen(javaClass);
+ classGen.addInterface("org.apache.myfaces.scripting.loaders.java._ScriptingClass");
+ classGen.update();
+
+ File target = classNameToFile(classPath, className);
+
+ try {
+ classGen.getJavaClass().dump(target);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static File classNameToFile(String classPath, String className) {
+ String classFileName = classNameToRelativeFileName(className);
+ File target = new File(classPath + File.separator + classFileName);
+ return target;
+ }
+
+ private static String classNameToRelativeFileName(String className) {
+ return className.replaceAll("\\.", File.separator) + ".class";
+ }
+
+ public static String relativeFileToClassName(String relativeFileName) {
+ String className = relativeFileName.replaceAll("\\\\", ".").replaceAll("\\/", ".");
+ className = className.substring(0, className.lastIndexOf("."));
+ return className;
+ }
}
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/factories/ScriptingApplicationFactory.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/factories/ScriptingApplicationFactory.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/factories/ScriptingApplicationFactory.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/factories/ScriptingApplicationFactory.java Wed Sep 9 07:14:30 2009
@@ -30,13 +30,13 @@
* Application factory which introduces
* scripting proxies for their artefacts
*
- * Not we use a mix of AOP and helper constructs
+ * We use a mix of AOP and helper constructs
* to reach the goal to be dynamic.
* For most artefacts we just need to
- * check if the object is a groovy object
+ * check if the object is a Groovy object
* and then reload at their connection interfaces
*
- * some artefacts have a longer lifespan and/or are stateless
+ * Some artefacts have a longer lifespan and/or are stateless
* for those we have to work with reloading AOP
*
*
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/NavigationHandlerProxy.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/NavigationHandlerProxy.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/NavigationHandlerProxy.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/NavigationHandlerProxy.java Wed Sep 9 07:14:30 2009
@@ -31,9 +31,6 @@
*/
public class NavigationHandlerProxy extends NavigationHandler implements Decorated {
-
-
-
private void weaveDelegate() {
_delegate = (NavigationHandler) ProxyUtils.getWeaver().reloadScriptingInstance(_delegate);
}
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/VariableResolverProxy.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/VariableResolverProxy.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/VariableResolverProxy.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/VariableResolverProxy.java Wed Sep 9 07:14:30 2009
@@ -34,8 +34,6 @@
public class VariableResolverProxy extends VariableResolver implements Decorated {
VariableResolver _delegate;
-
-
public VariableResolverProxy(VariableResolver delegate) {
_delegate = delegate;
}
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/ViewHandlerProxy.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/ViewHandlerProxy.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/ViewHandlerProxy.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/jsf/dynamicdecorators/implemetations/ViewHandlerProxy.java Wed Sep 9 07:14:30 2009
@@ -43,7 +43,6 @@
}
}
-
public ViewHandlerProxy(ViewHandler delegate) {
_delegate = delegate;
}
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/groovy/DynamicClassIdentifier.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/groovy/DynamicClassIdentifier.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/groovy/DynamicClassIdentifier.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/groovy/DynamicClassIdentifier.java Wed Sep 9 07:14:30 2009
@@ -20,6 +20,9 @@
import org.apache.myfaces.scripting.api.ScriptingConst;
+import java.util.Map;
+import java.util.HashMap;
+
/**
* This class checks for reloadable class patterns
* we do it on the java side for existing groovy objects
@@ -27,19 +30,38 @@
* @author Werner Punz
*/
public class DynamicClassIdentifier implements org.apache.myfaces.scripting.api.DynamicClassIdentifier {
+ static ThreadLocal _checked = new ThreadLocal();
+
public boolean isDynamic(Class clazz) {
+ Map<String, Boolean> alreadyChecked = getAlreadyChecked();
+ if (alreadyChecked.containsKey(clazz.getName())) {
+ return alreadyChecked.get(clazz.getName());
+ }
+
Class[] interfaces = clazz.getInterfaces();
for (int cnt = 0; cnt < interfaces.length; cnt++) {
- if (interfaces[cnt].getName().startsWith("groovy.lang"))
+ if (interfaces[cnt].getName().startsWith("groovy.lang")) {
+ alreadyChecked.put(clazz.getName(), Boolean.TRUE);
return true;
+ }
}
+ alreadyChecked.put(clazz.getName(), Boolean.FALSE);
return false;
}
+ private Map<String, Boolean> getAlreadyChecked() {
+ Map<String, Boolean> checked = (Map<String, Boolean>) _checked.get();
+ if (checked == null) {
+ checked = new HashMap<String, Boolean>();
+ }
+ return checked;
+ }
+
+
public int getEngineType(Class clazz) {
- if(isDynamic(clazz)) {
+ if (isDynamic(clazz)) {
return ScriptingConst.ENGINE_TYPE_GROOVY;
- }else{
+ } else {
return ScriptingConst.ENGINE_TYPE_NO_ENGINE;
}
}
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/DynamicClassIdentifier.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/DynamicClassIdentifier.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/DynamicClassIdentifier.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/DynamicClassIdentifier.java Wed Sep 9 07:14:30 2009
@@ -19,24 +19,67 @@
package org.apache.myfaces.scripting.loaders.java;
import org.apache.myfaces.scripting.api.ScriptingConst;
-import org.apache.myfaces.scripting.loaders.java.ScriptingClass;
import java.lang.annotation.Annotation;
+import java.util.Map;
+import java.util.HashMap;
/**
* @author werpu
- * A dynamic class identifier for java classes
+ * A dynamic class identifier for java classes
*/
public class DynamicClassIdentifier implements org.apache.myfaces.scripting.api.DynamicClassIdentifier {
+ static ThreadLocal _checked = new ThreadLocal();
+
public boolean isDynamic(Class clazz) {
+ Map<String, Boolean> alreadyChecked = getAlreadyChecked();
+ if (alreadyChecked.containsKey(clazz.getName())) {
+ return alreadyChecked.get(clazz.getName());
+ }
+ if (checkForAnnotation(clazz)) {
+ alreadyChecked.put(clazz.getName(), Boolean.TRUE);
+ return true;
+ }
+ boolean retVal = checkForInterface(clazz);
+ //alreadyChecked.put(clazz.getName(), retVal ? Boolean.TRUE : Boolean.FALSE);
+ return retVal;
+ }
+
+
+ private Map<String, Boolean> getAlreadyChecked() {
+ Map<String, Boolean> checked = (Map<String, Boolean>) _checked.get();
+ if (checked == null) {
+ checked = new HashMap<String, Boolean>();
+ }
+ return checked;
+ }
+
+ private boolean checkForInterface(Class clazz) {
+ Class[] interfaces = clazz.getInterfaces();
+ if (interfaces == null) {
+ return false;
+
+ }
+
+ for (Class theInterface : interfaces) {
+ if (theInterface.equals(_ScriptingClass.class)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean checkForAnnotation(Class clazz) {
Annotation identifier = clazz.getAnnotation(ScriptingClass.class);
- return identifier != null;
+ boolean annotated = identifier != null;
+ return annotated;
}
public int getEngineType(Class clazz) {
- if(isDynamic(clazz)) {
+ if (isDynamic(clazz)) {
return ScriptingConst.ENGINE_TYPE_JAVA;
- }else{
+ } else {
return ScriptingConst.ENGINE_TYPE_NO_ENGINE;
}
}
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/JavaScriptingWeaver.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/JavaScriptingWeaver.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/JavaScriptingWeaver.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/JavaScriptingWeaver.java Wed Sep 9 07:14:30 2009
@@ -84,6 +84,8 @@
/**
* loads a class from a given sourceroot and filename
+ * note this method does not have to be thread safe
+ * it is called in a thread safe manner by the base class
*
* @param sourceRoot the source search lookup path
* @param file the filename to be compiled and loaded
@@ -107,7 +109,7 @@
try {
//we initialize the compiler lazy
//because the facade itself is lazy
- DynamicCompiler compiler = (DynamicCompiler) ClassUtils.instantiate("org.apache.myfaces.scripting.loaders.java.jsr199.ReflectCompilerFacade");//new ReflectCompilerFacade();
+ DynamicCompiler compiler = (DynamicCompiler) ClassUtils.instantiate("org.apache.myfaces.scripting.loaders.java.jsr199.CompilerFacade");//new ReflectCompilerFacade();
retVal = compiler.compileFile(sourceRoot, classPath, file);
} catch (ClassNotFoundException e) {
//can be safely ignored
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/ScriptingClass.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/ScriptingClass.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/ScriptingClass.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/ScriptingClass.java Wed Sep 9 07:14:30 2009
@@ -25,8 +25,8 @@
/**
* @author werpu
- * this annotation adds scripting behavior
- * only classes using this annotation will be reloaded
+ * this annotation adds scripting behavior
+ * only classes using this annotation will be reloaded
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
Added: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/_ScriptingClass.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/_ScriptingClass.java?rev=812796&view=auto
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/_ScriptingClass.java (added)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/_ScriptingClass.java Wed Sep 9 07:14:30 2009
@@ -0,0 +1,10 @@
+package org.apache.myfaces.scripting.loaders.java;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ *
+ * internally used identifier for auto class marking
+ */
+public interface _ScriptingClass {
+}
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/jci/CompilerFacade.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/jci/CompilerFacade.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/jci/CompilerFacade.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/loaders/java/jci/CompilerFacade.java Wed Sep 9 07:14:30 2009
@@ -19,12 +19,13 @@
package org.apache.myfaces.scripting.loaders.java.jci;
import org.apache.myfaces.scripting.api.DynamicCompiler;
+import org.apache.myfaces.shared_impl.util.ClassUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.jci.compilers.JavaCompiler;
import org.apache.commons.jci.compilers.JavaCompilerFactory;
import org.apache.commons.jci.compilers.CompilationResult;
-import org.apache.commons.jci.compilers.EclipseJavaCompiler;
+
import org.apache.commons.jci.readers.ResourceReader;
import org.apache.commons.jci.readers.FileResourceReader;
import org.apache.commons.jci.stores.MemoryResourceStore;
@@ -63,8 +64,12 @@
result = compiler.compile(toCompile, reader, target);
if (result.getErrors().length == 0) {
+ //TODO add marker mechanism for the compiled resources
+ //ClassUtils.markAsDynamicJava(fileManager.getTempDir().getAbsolutePath(), className);
+ //for now until we have this added please use the annotation
+
ResourceStore[] stores = {target};
- ResourceStoreClassLoader loader = new ResourceStoreClassLoader(Thread.currentThread().getContextClassLoader(), stores);
+ ResourceStoreClassLoader loader = new ResourceStoreClassLoader(ClassUtils.getContextClassLoader(), stores);
return loader.loadClass(className);
} else {
Log log = LogFactory.getLog(this.getClass());
Modified: myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/refresh/FileChangedDaemon.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/refresh/FileChangedDaemon.java?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/refresh/FileChangedDaemon.java (original)
+++ myfaces/extensions/scripting/trunk/core/src/main/java/org/apache/myfaces/scripting/refresh/FileChangedDaemon.java Wed Sep 9 07:14:30 2009
@@ -36,22 +36,18 @@
* loaded by the various engine loaders for
* for file changes and then if one has changed we have to mark
* it for further processing
- *
- * TODO to get optimal performance we operate on a deep copy of the underlying map
- * the map itself has read write access and access the map can only happen synchronized
- * the write acces has to happen through this class which is sort of the gatekeeper,
- * the read access happens on a non synchronized instance of the map
- * which is accessed for readonly reasons, non synchronized map
- * is refreshed after every interval if something was tainted with
- * an assignment operation so that nothing can happen
- * (lisp trick again, immutable data structure == thread safety)
- *
- *
+ * <p/>
*/
public class FileChangedDaemon extends Thread {
static FileChangedDaemon instance = null;
+ //TODO replace the synchronized map with a segmented map to reduce
+ //the number of synchronisation locks on parallel access
+ //we have to have in mind that the compiler facades access this map
+ //in a writable way as well to update their meta data so we
+ //should replace the map with something segmented, probably
+ //a balanced tree of depth 2
Map<String, ReloadingMetadata> classMap = Collections.synchronizedMap(new HashMap<String, ReloadingMetadata>());
boolean running = false;
Log log = LogFactory.getLog(FileChangedDaemon.class);
@@ -61,15 +57,14 @@
if (instance == null) {
instance = new FileChangedDaemon();
instance.setDaemon(true);
- instance.setRunning(true);
+ instance.setRunning(true);
instance.start();
}
-
+
return instance;
}
-
public void run() {
while (running) {
Modified: myfaces/extensions/scripting/trunk/pom.xml
URL: http://svn.apache.org/viewvc/myfaces/extensions/scripting/trunk/pom.xml?rev=812796&r1=812795&r2=812796&view=diff
==============================================================================
--- myfaces/extensions/scripting/trunk/pom.xml (original)
+++ myfaces/extensions/scripting/trunk/pom.xml Wed Sep 9 07:14:30 2009
@@ -151,35 +151,7 @@
<version>1.5</version>
</dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-jci-core</artifactId>
- <version>1.0</version>
- </dependency>
-
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-jci-javac</artifactId>
- <version>1.0</version>
- </dependency>
-
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-jci-eclipse</artifactId>
- <version>1.0</version>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-jci-janino</artifactId>
- <version>1.0</version>
- </dependency>
-
- <dependency>
- <groupId>org.apache.bcel</groupId>
- <artifactId>bcel</artifactId>
- <version>5.2</version>
- </dependency>
<!--
<dependency>