clean-up and new servlet method caching

pull/533/head
Michael Peter Christen 2 years ago
parent adbda4c71b
commit 1e1107c97c

@ -165,18 +165,7 @@
</target> </target>
<target name="compile-htroot" depends="init,resolve" description="compile YaCy servlets"> <target name="compile" depends="compile-core" description="compile YaCy core and YaCy servlets" />
<!-- compile htroot, htroot/yacy and htroot/htdocsdefault -->
<javac srcdir="${htroot}/"
excludes="processing/**"
source="${javacSource}" target="${javacTarget}"
debug="true" debuglevel="lines,vars,source" includeantruntime="false" encoding="UTF-8">
<classpath refid="project.class.path" />
<compilerarg value="-Xlint"/>
</javac>
</target>
<target name="compile" depends="compile-core, compile-htroot" description="compile YaCy core and YaCy servlets" />
<target name="all" depends="compile"> <target name="all" depends="compile">
</target> </target>
@ -309,7 +298,6 @@
source="${javacSource}" target="${javacTarget}" encoding="UTF-8"> source="${javacSource}" target="${javacTarget}" encoding="UTF-8">
<classpath> <classpath>
<pathelement location="${build}"/> <pathelement location="${build}"/>
<pathelement location="${htroot}"/>
<path refid="compile.path"/> <path refid="compile.path"/>
<path refid="test.path"/> <path refid="test.path"/>
</classpath> </classpath>
@ -328,7 +316,6 @@
<classpath> <classpath>
<pathelement location="${test}"/> <pathelement location="${test}"/>
<pathelement location="${build}"/> <pathelement location="${build}"/>
<pathelement location="${htroot}"/>
<fileset dir="${libt}" includes="**/*.jar" /> <fileset dir="${libt}" includes="**/*.jar" />
<fileset dir="${lib}" includes="**/*.jar" /> <fileset dir="${lib}" includes="**/*.jar" />
</classpath> </classpath>
@ -384,7 +371,6 @@
<delete failonerror="false"> <delete failonerror="false">
<fileset dir="${src}" includes="**/*.class" /> <fileset dir="${src}" includes="**/*.class" />
<fileset dir="${build}" includes="**/*.class" /> <fileset dir="${build}" includes="**/*.class" />
<fileset dir="${htroot}" includes="**/*.class" />
<fileset dir="test/" includes="**/*.class" /> <fileset dir="test/" includes="**/*.class" />
<fileset dir="." includes="TEST-*" /> <fileset dir="." includes="TEST-*" />
</delete> </delete>
@ -449,7 +435,6 @@
<java classname="net.yacy.yacy" fork="yes"> <java classname="net.yacy.yacy" fork="yes">
<classpath> <classpath>
<pathelement location="${build}"/> <pathelement location="${build}"/>
<pathelement location="${htroot}"/>
<pathelement location="${lib}" /> <pathelement location="${lib}" />
<fileset dir="${lib}" includes="**/*.jar" /> <fileset dir="${lib}" includes="**/*.jar" />
</classpath> </classpath>
@ -499,9 +484,6 @@
<fileset dir="source" defaultexcludes="yes"> <fileset dir="source" defaultexcludes="yes">
<include name="**/*.java" /> <include name="**/*.java" />
</fileset> </fileset>
<fileset dir="htroot" defaultexcludes="yes">
<include name="**/*.java" />
</fileset>
</javadoc> </javadoc>
</target> </target>

@ -29,7 +29,6 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.lang.ref.SoftReference;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -136,7 +135,7 @@ public class YaCyDefaultServlet extends HttpServlet {
protected File _htLocalePath; protected File _htLocalePath;
protected File _htDocsPath; protected File _htDocsPath;
protected static final serverClassLoader provider = new serverClassLoader(/*this.getClass().getClassLoader()*/); protected static final serverClassLoader provider = new serverClassLoader(/*this.getClass().getClassLoader()*/);
protected ConcurrentHashMap<File, SoftReference<Method>> templateMethodCache = null; protected ConcurrentHashMap<String, Method> templateMethodCache = null;
// settings for multipart/form-data // settings for multipart/form-data
protected static final File TMPDIR = new File(System.getProperty("java.io.tmpdir")); protected static final File TMPDIR = new File(System.getProperty("java.io.tmpdir"));
protected static final int SIZE_FILE_THRESHOLD = 1024 * 1024 * 1024; // 1GB is a lot but appropriate for multi-document pushed using the push_p.json servlet protected static final int SIZE_FILE_THRESHOLD = 1024 * 1024 * 1024; // 1GB is a lot but appropriate for multi-document pushed using the push_p.json servlet
@ -177,7 +176,7 @@ public class YaCyDefaultServlet extends HttpServlet {
if (ConcurrentLog.isFine("FILEHANDLER")) { if (ConcurrentLog.isFine("FILEHANDLER")) {
ConcurrentLog.fine("FILEHANDLER","YaCyDefaultServlet: resource base = " + this._resourceBase); ConcurrentLog.fine("FILEHANDLER","YaCyDefaultServlet: resource base = " + this._resourceBase);
} }
this.templateMethodCache = new ConcurrentHashMap<File, SoftReference<Method>>(); this.templateMethodCache = new ConcurrentHashMap<String, Method>();
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -262,8 +261,8 @@ public class YaCyDefaultServlet extends HttpServlet {
if (reqRanges == null && !endsWithSlash) { if (reqRanges == null && !endsWithSlash) {
final int p = pathInContext.lastIndexOf('.'); final int p = pathInContext.lastIndexOf('.');
if (p >= 0) { if (p >= 0) {
final Class<?> servletClass = rewriteClass(pathInContext); final Method rewriteMethod = rewriteMethod(pathInContext);
if (servletClass != null) { if (rewriteMethod != null) {
hasClass = true; hasClass = true;
} else { } else {
final String pathofClass = pathInContext.substring(0, p) + ".class"; final String pathofClass = pathInContext.substring(0, p) + ".class";
@ -659,13 +658,8 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
} }
protected Object invokeServlet(final Method targetMethod, final RequestHeader request, final serverObjects args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
protected Object invokeServlet(final File targetClass, final RequestHeader request, final serverObjects args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { return targetMethod.invoke(null, new Object[]{request, args, Switchboard.getSwitchboard()}); // add switchboard
return rewriteMethod(targetClass).invoke(null, new Object[]{request, args, Switchboard.getSwitchboard()}); // add switchboard
}
protected Object invokeServlet(final Class<?> targetClass, final RequestHeader request, final serverObjects args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
return rewriteMethod(targetClass).invoke(null, new Object[]{request, args, Switchboard.getSwitchboard()}); // add switchboard
} }
/** /**
@ -753,95 +747,46 @@ public class YaCyDefaultServlet extends HttpServlet {
return this._resourceBase.addPath(path).getFile(); return this._resourceBase.addPath(path).getFile();
} }
protected File rewriteClassFile(final File servletFile) { private final Method rewriteMethod(final String target) {
try {
String f = servletFile.getCanonicalPath();
final int p = f.lastIndexOf('.');
if (p < 0) {
return null;
}
f = f.substring(0, p) + ".class";
final File cf = new File(f);
if (cf.exists()) {
return cf;
}
return null;
} catch (final IOException e) {
return null;
}
}
protected Class<?> rewriteClass(String target) {
assert target.charAt(0) == '/'; assert target.charAt(0) == '/';
final Method cachedMethod = this.templateMethodCache.get(target);
if (cachedMethod != null) return cachedMethod;
final int p = target.lastIndexOf('.'); final int p = target.lastIndexOf('.');
if (p < 0) { if (p < 0) {
return null; return null;
} }
target = "net.yacy.htroot" + target.substring(0, p).replace('/', '.'); final String classname = "net.yacy.htroot" + target.substring(0, p).replace('/', '.');
try { try {
final Class<?> servletClass = Class.forName(target); final Class<?> servletClass = Class.forName(classname);
return servletClass; final Method rewriteMethod = rewriteMethod(servletClass);
} catch (final ClassNotFoundException e) { this.templateMethodCache.put(target, rewriteMethod);
return rewriteMethod;
} catch (final ClassNotFoundException | InvocationTargetException e) {
try { try {
final Class<?> servletClass = Class.forName(target + "_"); // for some targets we need alternative names final Class<?> servletClass = Class.forName(classname + "_"); // for some targets we need alternative names
return servletClass; final Method rewriteMethod = rewriteMethod(servletClass);
} catch (final ClassNotFoundException ee) { this.templateMethodCache.put(target, rewriteMethod);
return rewriteMethod;
} catch (final ClassNotFoundException | InvocationTargetException ee) {
return null; return null;
} }
} }
} }
protected Method rewriteMethod(final File classFile) throws InvocationTargetException { private final static Method rewriteMethod(final Class<?> rewriteClass) throws InvocationTargetException {
Method m = null;
// now make a class out of the stream
try {
final SoftReference<Method> ref = this.templateMethodCache.get(classFile);
if (ref != null) {
m = ref.get();
if (m == null) {
this.templateMethodCache.remove(classFile);
} else {
return m;
}
}
final Class<?> c = provider.loadClass(classFile);
final Class<?>[] params = (Class<?>[]) Array.newInstance(Class.class, 3); final Class<?>[] params = (Class<?>[]) Array.newInstance(Class.class, 3);
params[0] = RequestHeader.class; params[0] = RequestHeader.class;
params[1] = serverObjects.class; params[1] = serverObjects.class;
params[2] = serverSwitch.class; params[2] = serverSwitch.class;
m = c.getMethod("respond", params);
if (MemoryControl.shortStatus()) {
this.templateMethodCache.clear();
} else {
// store the method into the cache
this.templateMethodCache.put(classFile, new SoftReference<Method>(m));
}
} catch (final ClassNotFoundException e) {
ConcurrentLog.severe("FILEHANDLER","YaCyDefaultServlet: class " + classFile + " is missing:" + e.getMessage());
throw new InvocationTargetException(e, "class " + classFile + " is missing:" + e.getMessage());
} catch (final NoSuchMethodException e) {
ConcurrentLog.severe("FILEHANDLER","YaCyDefaultServlet: method 'respond' not found in class " + classFile + ": " + e.getMessage());
throw new InvocationTargetException(e, "method 'respond' not found in class " + classFile + ": " + e.getMessage());
}
return m;
}
protected Method rewriteMethod(final Class<?> rewriteClass) throws InvocationTargetException {
Method m = null;
try { try {
final Class<?>[] params = (Class<?>[]) Array.newInstance(Class.class, 3); final Method m = rewriteClass.getMethod("respond", params);
params[0]= RequestHeader.class; return m;
params[1] = serverObjects.class;
params[2] = serverSwitch.class;
m = rewriteClass.getMethod("respond", params);
} catch (final NoSuchMethodException e) { } catch (final NoSuchMethodException e) {
ConcurrentLog.severe("FILEHANDLER","YaCyDefaultServlet: method 'respond' not found in class " + rewriteClass.getName() + ": " + e.getMessage()); ConcurrentLog.severe("FILEHANDLER","YaCyDefaultServlet: method 'respond' not found in class " + rewriteClass.getName() + ": " + e.getMessage());
throw new InvocationTargetException(e, "method 'respond' not found in class " + rewriteClass.getName() + ": " + e.getMessage()); throw new InvocationTargetException(e, "method 'respond' not found in class " + rewriteClass.getName() + ": " + e.getMessage());
} }
return m;
} }
/** /**
@ -868,8 +813,7 @@ public class YaCyDefaultServlet extends HttpServlet {
} }
} }
final File targetLocalizedFile = getLocalizedFile(target, localeSelection); final File targetLocalizedFile = getLocalizedFile(target, localeSelection);
final File targetClassFile = rewriteClassFile(this._resourceBase.addPath(target).getFile()); final Method targetMethod = rewriteMethod(target);
final Class<?> targetClass = rewriteClass(target);
final String targetExt = target.substring(target.lastIndexOf('.') + 1); final String targetExt = target.substring(target.lastIndexOf('.') + 1);
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
@ -891,7 +835,7 @@ public class YaCyDefaultServlet extends HttpServlet {
response.setHeader(HeaderFramework.CORS_ALLOW_ORIGIN, "*"); response.setHeader(HeaderFramework.CORS_ALLOW_ORIGIN, "*");
} }
if ((targetClassFile != null || targetClass != null)) { if (targetMethod != null) {
final serverObjects args = new serverObjects(); final serverObjects args = new serverObjects();
final Enumeration<String> argNames = request.getParameterNames(); // on ssi jetty dispatcher merged local ssi query parameters final Enumeration<String> argNames = request.getParameterNames(); // on ssi jetty dispatcher merged local ssi query parameters
while (argNames.hasMoreElements()) { while (argNames.hasMoreElements()) {
@ -909,17 +853,9 @@ public class YaCyDefaultServlet extends HttpServlet {
try { try {
if (args.isEmpty()) { if (args.isEmpty()) {
// yacy servlets typically test for args != null (but not for args .isEmpty()) // yacy servlets typically test for args != null (but not for args .isEmpty())
if (targetClass == null) { tmp = invokeServlet(targetMethod, legacyRequestHeader, null);
tmp = invokeServlet(targetClassFile, legacyRequestHeader, null);
} else {
tmp = invokeServlet(targetClass, legacyRequestHeader, null);
}
} else { } else {
if (targetClass == null) { tmp = invokeServlet(targetMethod, legacyRequestHeader, args);
tmp = invokeServlet(targetClassFile, legacyRequestHeader, args);
} else {
tmp = invokeServlet(targetClass, legacyRequestHeader, args);
}
} }
} catch(final InvocationTargetException e) { } catch(final InvocationTargetException e) {
if(e.getCause() instanceof InvalidURLLicenceException) { if(e.getCause() instanceof InvalidURLLicenceException) {

Loading…
Cancel
Save