https://issues.apache.org/jira/browse/EXTSCRIPT-143
fixup for the refactoring bugs introduced by changing the central watchdog datastructure to something closer to bernhards code
also we now move the trunk over to the latest 2.0.2-snapshot for testing reasons
git-svn-id: https://svn.apache.org/repos/asf/myfaces/extensions/scripting/trunk@996518 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/api/Configuration.java b/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/api/Configuration.java
index 3af7f33..2637fac 100644
--- a/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/api/Configuration.java
+++ b/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/api/Configuration.java
@@ -144,6 +144,29 @@
dirs.add(sourceDir);
}
+ /**
+ * <p>Resolves and returns a File handle that represents the class file of
+ * the given class on the file system. However, note that this method only
+ * returns <code>null</code> if an error occured while resolving the class
+ * file. A non-null valuee doesn't necessarily mean that the class file
+ * actually exists. In oder to check the existence call the according
+ * method on the returned object.</p>
+ *
+ * @param className the name of the class that you want to resolve
+ * @return a File handle that represents the class file of the given class
+ * on the file system
+ * @see java.io.File#exists()
+ */
+ public File resolveClassFile(String className) {
+ //if(className.contains("rg/apache/myfaces/javaloader/componentTest/JavaTestComponent$PropertyKeys")) {
+ // System.out.println("Debuginfo found");
+ //}
+ //int subClassPos = className.indexOf("$");
+ //className = (subClassPos != -1)? className.substring(0, subClassPos) :className;
+ return new File(getCompileTarget(),
+ className.replaceAll("\\.", "/").concat(".class"));
+ }
+
public File getCompileTarget() {
return _compileTarget;
}
diff --git a/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/api/MyFacesBeanHandler.java b/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/api/MyFacesBeanHandler.java
index 41da284..654b4cd 100644
--- a/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/api/MyFacesBeanHandler.java
+++ b/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/api/MyFacesBeanHandler.java
@@ -22,18 +22,19 @@
import org.apache.myfaces.config.annotation.LifecycleProvider;
import org.apache.myfaces.config.annotation.LifecycleProviderFactory;
import org.apache.myfaces.config.element.ManagedBean;
+import org.apache.myfaces.config.element.ManagedProperty;
import org.apache.myfaces.extensions.scripting.core.util.ReflectUtil;
import org.apache.myfaces.extensions.scripting.core.util.WeavingContext;
import org.apache.myfaces.extensions.scripting.monitor.ClassResource;
import org.apache.myfaces.extensions.scripting.monitor.RefreshContext;
import org.apache.myfaces.extensions.scripting.monitor.RefreshAttribute;
+import org.apache.myfaces.util.ContainerUtils;
+import javax.el.ELContext;
+import javax.el.ExpressionFactory;
import javax.faces.context.FacesContext;
import java.lang.reflect.InvocationTargetException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -76,6 +77,41 @@
}
/**
+ * scans the dependencies on el level
+ * Not working out for now
+ */
+ /* public void scanElDependencies() {
+ Map<String, ManagedBean> mbeans = RuntimeConfig.getCurrentInstance(FacesContext.getCurrentInstance().getExternalContext()).getManagedBeans();
+ for(Map.Entry<String, ManagedBean> entry: mbeans.entrySet()) {
+ Object bean = entry.getValue();
+ if(bean instanceof org.apache.myfaces.config.impl.digester.elements.ManagedBean) {
+ org.apache.myfaces.config.impl.digester.elements.ManagedBean workBean = (org.apache.myfaces.config.impl.digester.elements.ManagedBean) bean;
+
+ Object props = ReflectUtil.executeMethod(workBean,"getManagedProperties");
+ if(props instanceof Iterator) {
+ //myfaces 1.2
+ } else {
+ for(ManagedProperty prop: ((Collection<ManagedProperty>) props)) {
+ ExpressionFactory expFactory = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
+ ELContext elContext = FacesContext.getCurrentInstance().getELContext();
+ expFactory.coerceToType("#{myFactory['booga']}");
+ //if(ContainerUtils.isValueReference((String) prop.getV))
+ elContext.getELResolver().getType(elContext,"myFactory","booga");
+ }
+ }
+
+
+ }
+ //Iterator<ManagedProperty> it = bean.getManagedProperties();
+ //we rescan all managed props to cover pure object
+ //references as well as class references
+ //while(it.hasNext()) {
+ // ManagedProperty prop = it.next();
+ //}
+ }
+ } */
+
+ /**
* Refreshes all managed beans
* session, and personal scoped ones
* <p/>
@@ -92,6 +128,8 @@
Set<String> tainted = getTaintedClasses();
+ //scanElDependencies();
+
if (tainted.size() > 0) {
//We now have to check if the tainted classes belong to the managed beans
Set<String> managedBeanClasses = new HashSet<String>();
diff --git a/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/loaders/java/RecompiledClassLoader.java b/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/loaders/java/RecompiledClassLoader.java
index d1ea4dc..1deb1f1 100644
--- a/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/loaders/java/RecompiledClassLoader.java
+++ b/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/loaders/java/RecompiledClassLoader.java
@@ -18,6 +18,9 @@
*/
package org.apache.myfaces.extensions.scripting.loaders.java;
+import org.apache.myfaces.extensions.scripting.core.util.WeavingContext;
+import org.apache.myfaces.extensions.scripting.monitor.ClassResource;
+
import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedActionException;
@@ -111,18 +114,32 @@
public Class<?> loadClass(String className) throws ClassNotFoundException {
//check if our class exists in the tempDir
final ClassLoader _parent = getParent();
+ if(className.contains("JavaTestComponent")) {
+ System.out.println("Debugpoint found");
+ }
+ ClassResource resource = WeavingContext.getFileChangedDaemon().getClassMap().get(className);
+
+ //preemptive check if the resource either is not loaded or requires a refresh
+ //if yes we generated a new classloader to load the class anew
+ if(resource == null || resource.getAClass() == null || resource.isRecompiled()) {
+ return _loadClass(className, _parent);
+ }
+ return resource.getAClass();
+ }
+
+ private Class<?> _loadClass(String className, ClassLoader _parent) throws ClassNotFoundException {
try {
_throwAwayLoader = AccessController.doPrivileged(
new _Action(_parent, _scriptingEngine, _engineExtension, _unTaintClasses)
);
- //_throwAwayLoader.setSourceRoot(getSourceRoot());
return _throwAwayLoader.loadClass(className);
} catch (PrivilegedActionException e) {
logSevere(e);
+ return null;
}
- return null;
}
+
protected Class<?> findClass(String name) throws ClassNotFoundException {
return _throwAwayLoader.findClassExposed(name);
}
diff --git a/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/loaders/java/ThrowawayClassloader.java b/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/loaders/java/ThrowawayClassloader.java
index 90fecfe..280d917 100644
--- a/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/loaders/java/ThrowawayClassloader.java
+++ b/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/loaders/java/ThrowawayClassloader.java
@@ -46,7 +46,6 @@
int _scriptingEngine;
String _engineExtension;
-
public ThrowawayClassloader(ClassLoader classLoader, int scriptingEngine, String engineExtension) {
super(classLoader);
@@ -89,25 +88,36 @@
}
@Override
+ /**
+ * load called either if the class is not loaded at all
+ * or if the class has been recompiled (check upfront)
+ */
public Class<?> loadClass(String className) throws ClassNotFoundException {
//check if our class exists in the tempDir
- File target = getClassFile(className);
+ if(className.contains("JavaTestComponent")) {
+ System.out.println("Debuginfo found");
+ }
+
+ //TODO handle the $ case which should not revert to a new classloader
+
+ File target = WeavingContext.getConfiguration().resolveClassFile(className);
if (target.exists()) {
- _logger.log(Level.FINE,"[EXT-SCRIPTING] target {0} exists", className);
+
+ _logger.log(Level.FINE, "[EXT-SCRIPTING] target {0} exists", className);
ClassResource data = WeavingContext.getFileChangedDaemon().getClassMap().get(className);
- if (data != null && !data.getRefreshAttribute().requiresRefresh()) {
- _logger.log(Level.INFO,"[EXT-SCRIPTING] data from target {0} found but not tainted yet", className);
+ //this check must be present because
+ //the vm recycles old classloaders to load classes a anew
+ //if we dont do it we get an exception
+ if(data != null && !data.isRecompiled()) {
return data.getAClass();
}
- _logger.log(Level.FINER,"[EXT-SCRIPTING] loading class {0} from filesystem", className);
-
- FileInputStream iStream = null;
-
+ //a load must happen anyway because the target was recompiled
int fileLength;
byte[] fileContent;
+ FileInputStream iStream = null;
try {
//we cannot load while a compile is in progress
//we have to wait until it is one
@@ -119,23 +129,6 @@
_logger.log(Level.FINER, "read {0} bytes", String.valueOf(result));
}
- Class retVal;
-
- //we have to do it here because just in case
- //a dependent class is loaded as well we run into classcast exceptions
- if (data != null) {
- data.getRefreshAttribute().executedRefresh();
-
- retVal = super.defineClass(className, fileContent, 0, fileLength);
-
- data.setAClass(retVal);
- return retVal;
- } else {
- //we store the initial reloading meta data information so that it is refreshed
- //later on, this we we cover dependent classes on the initial load
- return storeReloadableDefinitions(className, fileLength, fileContent);
- }
-
} catch (FileNotFoundException e) {
throw new ClassNotFoundException(e.toString());
} catch (IOException e) {
@@ -150,8 +143,32 @@
}
}
}
+
+ if (data != null) {
+ File sourceFile = data.getFile();
+
+ _logger.log(Level.FINER, "[EXT-SCRIPTING] loading class {0} from filesystem", className);
+
+ Class retVal;
+
+ //we have to do it here because just in case
+ //a dependent class is loaded as well we run into classcast exceptions
+ //we only store the class the weaver has to trigger the refresh time trigger
+ retVal = super.defineClass(className, fileContent, 0, fileLength);
+ data.setAClass(retVal);
+ data.executeLastLoaded();
+ return retVal;
+
+ } else {
+ //we store the initial reloading meta data information so that it is refreshed
+ //later on, this we we cover dependent classes on the initial load
+ if(className.contains("JavaTestComponen")) {
+ System.out.println("Debuginfo found");
+ }
+ return storeReloadableDefinitions(className, fileLength, fileContent);
+ }
}
- _logger.log(Level.FINER,"[EXT-SCRIPTING] target {0} does not exist", target.getAbsolutePath());
+ _logger.log(Level.FINER, "[EXT-SCRIPTING] target {0} does not exist", target.getAbsolutePath());
return super.loadClass(className);
}
@@ -163,7 +180,10 @@
//find the source for the given class and then
//store the filename
String separator = FileUtils.getFileSeparatorForRegex();
- String fileName = className.replaceAll("\\.", separator) + getStandardFileExtension();
+ String fileName = className.replaceAll("\\.", separator);
+ fileName = (fileName.indexOf("$") != -1)? fileName.substring(0,fileName.indexOf("$")): fileName;
+
+ fileName = fileName.replaceAll("\\.", separator) + getStandardFileExtension();
Collection<String> sourceDirs = WeavingContext.getConfiguration().getSourceDirs(_scriptingEngine);
String rootDir = null;
File sourceFile = null;
@@ -182,12 +202,14 @@
return retVal;
}
- reloadingMetaData.setFile(new File(rootDir+File.separator+fileName));
+ reloadingMetaData.setFile(new File(rootDir + File.separator + fileName));
reloadingMetaData.getRefreshAttribute().requestRefresh();
reloadingMetaData.getRefreshAttribute().executedRefresh();
+
reloadingMetaData.setScriptingEngine(_scriptingEngine);
WeavingContext.getFileChangedDaemon().getClassMap().put(className, reloadingMetaData);
+ reloadingMetaData.executeLastLoaded();
return retVal;
}
@@ -202,16 +224,17 @@
//some classloaders fail to resolve the resource properly, we have
//to drag our local paths in to keep track of the compiled resources
//for different scripting languages
- public URL getResource(String resource) {
- URL res = super.getResource(resource);
- if(res != null) return res;
- //if we do get a null value we try to remap to our custom paths
- if(!resource.endsWith(".class")) return null;
- resource = resource.substring(0, resource.length() - 6);
- resource = resource.replaceAll("\\/",".");
- File clsFile = getClassFile(resource);
- if(!clsFile.exists()) return null;
+ public URL getResource(String resource) {
+ URL res = super.getResource(resource);
+ if (res != null) return res;
+ //if we do get a null value we try to remap to our custom paths
+ if (!resource.endsWith(".class")) return null;
+ resource = resource.substring(0, resource.length() - 6);
+ resource = resource.replaceAll("\\/", ".");
+
+ File clsFile = WeavingContext.getConfiguration().resolveClassFile(resource);
+ if (!clsFile.exists()) return null;
try {
return clsFile.toURI().toURL();
} catch (MalformedURLException e) {
@@ -220,10 +243,4 @@
}
}
-
- public File getClassFile(String className) {
- return ClassUtils.classNameToFile(WeavingContext.getConfiguration().getCompileTarget().getAbsolutePath(), className);
- }
-
-
}
diff --git a/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/monitor/ClassResource.java b/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/monitor/ClassResource.java
index b07f820..4f5254b 100644
--- a/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/monitor/ClassResource.java
+++ b/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/monitor/ClassResource.java
@@ -24,6 +24,7 @@
import java.io.File;
import java.util.Collection;
+import java.util.logging.Logger;
/**
* @author Werner Punz (latest modification by $Author$)
@@ -42,6 +43,7 @@
//caching the info however probably is faster
volatile Class _aClass = null;
volatile File _sourceFile;
+ volatile long _lastLoaded = -1l;
volatile int _scriptingEngine = ScriptingConst.ENGINE_TYPE_JSF_NO_ENGINE;
//todo clean up the sourcepath and filename
@@ -102,6 +104,7 @@
return _sourceFile.getAbsolutePath().substring(getSourceDir().length()+1);
}
+
public String getSourceDir() {
Collection<String> sourceRoots = WeavingContext.getConfiguration().getSourceDirs(_scriptingEngine);
String fileDir = _sourceFile.getAbsolutePath();
@@ -115,4 +118,27 @@
return null;
}
+ public void executeLastLoaded() {
+ _lastLoaded = System.currentTimeMillis();
+ }
+
+ public long getLastLoaded() {
+ return _lastLoaded;
+ }
+
+ /**
+ *
+ * @return true if the class file has been recompiled since the last request for recompilation
+ */
+ public boolean isRecompiled() {
+ File classFile = WeavingContext.getConfiguration().resolveClassFile(_aClass.getName());
+ if(!classFile.exists()) {
+ return false;
+ }
+ Logger log = Logger.getLogger(this.getClass().getName());
+ log.info(this.getAClass().getName() + (classFile.lastModified() - _lastLoaded));
+ return _sourceFile.lastModified() > _lastLoaded;
+ }
+
+
}
diff --git a/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/servlet/CustomChainLoader.java b/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/servlet/CustomChainLoader.java
index 3a84933..bfaea46 100644
--- a/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/servlet/CustomChainLoader.java
+++ b/extscript-core-root/extscript-core/src/main/java/org/apache/myfaces/extensions/scripting/servlet/CustomChainLoader.java
@@ -66,7 +66,9 @@
else if (name.startsWith("org.apache") && !name.startsWith("org.apache.myfaces")) {
return null;
}
-
+ if(name.contains("JavaTestComponent")){
+ System.out.println("Debugpoint found");
+ }
return _scriptingWeaver.loadScriptingClassFromName(name);
}
diff --git a/extscript-core-root/extscript-core/src/test/java/org/apache/myfaces/extensions/scripting/core/classIdentifier/DynamicClassloader.java b/extscript-core-root/extscript-core/src/test/java/org/apache/myfaces/extensions/scripting/core/classIdentifier/DynamicClassloader.java
index b82163d..b2613fa 100644
--- a/extscript-core-root/extscript-core/src/test/java/org/apache/myfaces/extensions/scripting/core/classIdentifier/DynamicClassloader.java
+++ b/extscript-core-root/extscript-core/src/test/java/org/apache/myfaces/extensions/scripting/core/classIdentifier/DynamicClassloader.java
@@ -46,6 +46,10 @@
public Class loadClass(String className, boolean resolve) throws ClassNotFoundException {
+ if(className.contains("rg/apache/myfaces/javaloader/componentTest/JavaTestComponent$PropertyKeys")) {
+ System.out.println("Debuginfo found");
+ }
+
if (className.contains(Consts.JAVA_LANG)) {
return super.loadClass(className, resolve);
}
diff --git a/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/componentTest/JavaTestRenderer1.java b/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/componentTest/JavaTestRenderer1.java
index 0198789..49bed03 100644
--- a/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/componentTest/JavaTestRenderer1.java
+++ b/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/componentTest/JavaTestRenderer1.java
@@ -41,6 +41,7 @@
* class to the other
*/
+@FacesRenderer(componentFamily = "javax.faces.Input", rendererType = "at.irian.JavaTestRenderer")
public class JavaTestRenderer1 extends HtmlTextRendererBase {
diff --git a/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/componentTest/JavaTestRenderer2.java b/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/componentTest/JavaTestRenderer2.java
index d5f1845..3d1607d 100644
--- a/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/componentTest/JavaTestRenderer2.java
+++ b/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/componentTest/JavaTestRenderer2.java
@@ -32,7 +32,6 @@
* @author Werner Punz (latest modification by $Author$)
* @version $Revision$ $Date$
*/
-@FacesRenderer(componentFamily = "javax.faces.Input", rendererType = "at.irian.JavaTestRenderer")
public class JavaTestRenderer2 extends HtmlTextareaRendererBase {
diff --git a/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/elResolverTest/Receiver.java b/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/elResolverTest/Receiver.java
index 626f285..3124a0b 100644
--- a/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/elResolverTest/Receiver.java
+++ b/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/elResolverTest/Receiver.java
@@ -37,7 +37,7 @@
public Object getMyBean() {
return myBean;
- }
+ }
public void setMyBean(Object myBean) {
this.myBean = myBean;
diff --git a/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/test/TestBean4.java b/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/test/TestBean4.java
index 8f220f3..7a95524 100644
--- a/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/test/TestBean4.java
+++ b/extscript-examples/myfaces20-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/javaloader/test/TestBean4.java
@@ -26,11 +26,13 @@
public class TestBean4 {
- private String hello = "Hello world from test Bean 4";
+ private String hello = "Hello world from test Bean 4 xxx";
+
public String getHello() {
return hello;
}
+
public void setHello(String hello) {
this.hello = hello;
diff --git a/pom.xml b/pom.xml
index fd166d1..af84733 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
<properties>
<myfaces12.version>1.2.8</myfaces12.version>
- <myfaces2.version>2.0.1-SNAPSHOT</myfaces2.version>
+ <myfaces2.version>2.0.2-SNAPSHOT</myfaces2.version>
<groovy.version>1.7.1</groovy.version>
<extval.version>2.0.4-SNAPSHOT</extval.version>
</properties>