📄 run.java
字号:
/**
* Copyright (c) 2005, Paul Tuckey
* All rights reserved.
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
package org.tuckey.web.filters.urlrewrite;
import org.tuckey.web.filters.urlrewrite.utils.Log;
import org.tuckey.web.filters.urlrewrite.utils.StringUtils;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Hashtable;
/**
* Defines a run element, the ability to run a methodStr
* (eg, xx(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse))
*
* @author Paul Tuckey
* @version $Revision: 1.10 $ $Date: 2005/12/07 10:27:03 $
*/
public class Run {
private static Log log = Log.getLog(Run.class);
/**
* Weather or not the user wants the classStr created for each run.
*/
private boolean newEachTime = false;
private String classStr;
private static final String DEAULT_METHOD_STR = "run";
private String methodStr = DEAULT_METHOD_STR;
/**
* Used to identify the condition.
*/
private int id = 0;
/**
* Error message from the regular expression compilation.
*/
private String error = null;
private boolean valid = false;
private boolean initialised = false;
/**
* The instance of the classStr to run. Note, will be null if newEachTime is true.
*/
private Object runClassInstance;
/**
* handles to the methods we are going to run.
*/
private Constructor runConstructor;
private Method initMethod;
private Method runMethod;
private Method destroyMethod;
/**
* The config that we pass to the objectwe are trying to run.
*/
private RunConfig runServletConfig;
private Hashtable initParams = new Hashtable();
/**
* The parameter types used for run methods.
*/
private static Class[] runMethodParameterTypesHttp = new Class[2];
static {
runMethodParameterTypesHttp[0] = HttpServletRequest.class;
runMethodParameterTypesHttp[1] = HttpServletResponse.class;
}
/**
* For second try.
*/
private static Class[] runMethodParameterTypes = new Class[2];
static {
runMethodParameterTypes[0] = ServletRequest.class;
runMethodParameterTypes[1] = ServletResponse.class;
}
private static boolean checkRunObjectExists = true;
/**
* Initialise the Run, this will check specified classStr, constructor and methodStr exist.
*/
public boolean initialise(ServletContext context) {
log.debug("initialising run");
runServletConfig = new RunConfig(context, initParams);
initialised = true;
valid = false;
if (StringUtils.isBlank(classStr)) {
setError("cannot initialise run " + id + " value is empty");
return valid;
}
if (methodStr == null) {
methodStr = DEAULT_METHOD_STR;
}
if (checkRunObjectExists) {
prepareRunObject();
} else {
valid = true;
}
return valid;
}
/**
* Prepare the object for running by constructing and setting up method handles.
*/
private void prepareRunObject() {
if (log.isDebugEnabled()) {
log.debug("looking for class " + classStr);
}
Class runClass;
try {
runClass = Class.forName(classStr);
if (runClass == null) {
setError("had trouble finding " + classStr + " after Class.forName got a null object");
return;
}
} catch (ClassNotFoundException e) {
setError("could not find " + classStr + " got a " + e.toString(), e);
return;
} catch (NoClassDefFoundError e) {
setError("could not find " + classStr + " got a " + e.toString(), e);
return;
}
try {
runConstructor = runClass.getConstructor(null);
} catch (NoSuchMethodException e) {
setError("could not get constructor for " + classStr, e);
return;
}
if (log.isDebugEnabled()) {
log.debug("looking for " + methodStr + "(ServletRequest, ServletResponse)");
}
try {
runMethod = runClass.getMethod(methodStr, runMethodParameterTypes);
} catch (NoSuchMethodException e) {
if (log.isDebugEnabled()) {
log.debug("looking for " + methodStr + "(HttpServletRequest, HttpServletResponse)");
}
try {
runMethod = runClass.getMethod(methodStr, runMethodParameterTypesHttp);
} catch (NoSuchMethodException e2) {
setError("could not find " + methodStr + "(ServletRequest, ServletResponse) on " + classStr, e);
setError("or " + methodStr + "(HttpServletRequest, HttpServletResponse) on " + classStr, e);
return;
}
}
Method[] methods = runClass.getMethods();
// todo: there should be a tidier way of doing this
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
if ("destroy".equals(method.getName()) && method.getParameterTypes().length == 0) {
log.debug("found destroy methodStr");
destroyMethod = method;
}
if ("init".equals(method.getName()) && method.getParameterTypes().length == 1 &&
ServletConfig.class.getName().equals(method.getParameterTypes()[0].getName())) {
log.debug("found init methodStr");
initMethod = method;
}
if (initMethod != null && destroyMethod != null) break;
}
if (!newEachTime) {
runClassInstance = fetchNewInstance();
}
valid = true;
}
private void invokeDestroy(Object runClassInstanceToDestroy) {
if (runClassInstanceToDestroy != null && destroyMethod != null) {
if (log.isDebugEnabled()) {
log.debug("running " + classStr + ".destroy()");
}
try {
destroyMethod.invoke(runClassInstanceToDestroy, null);
} catch (IllegalAccessException e) {
logInvokeException("destroy()", e);
} catch (InvocationTargetException e) {
logInvokeException("destroy()", e);
}
}
}
/**
* Invokes the run method.
* <p/>
* Exceptions at invocation time are either rethrown as a ServletException or as thr original exception if we can
* manage to do it.
* <p/>
* We don't log exceptions here, the container can do that.
*/
private void invokeRunMethod(Object classInstanceToRun, Object[] args) throws IOException, ServletException {
if (log.isDebugEnabled()) {
log.debug("running " + classStr + "." + methodStr + "(HttpServletRequest, HttpServletResponse)");
}
if (classInstanceToRun == null || runMethod == null) return;
try {
runMethod.invoke(classInstanceToRun, args);
} catch (IllegalAccessException e) {
if (log.isDebugEnabled()) log.debug(e);
throw new ServletException(e);
} catch (InvocationTargetException e) {
if (log.isDebugEnabled()) log.debug(e);
Throwable originalThrowable = e.getTargetException();
if (originalThrowable == null) throw new ServletException(e);
if (originalThrowable instanceof RuntimeException) throw (RuntimeException) originalThrowable;
if (originalThrowable instanceof ServletException) throw (ServletException) originalThrowable;
if (originalThrowable instanceof IOException) throw (IOException) originalThrowable;
throw new ServletException(originalThrowable);
}
}
public static class SimpleInvocationHandler implements InvocationHandler {
private Object theWrappedPojo;
SimpleInvocationHandler(Object pojo) {
// When constructed, remember the instance we were constructed with
theWrappedPojo = pojo;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
try {
return m.invoke(theWrappedPojo, args);
} catch (InvocationTargetException e) {
// rethrow the original exception to make the wrapping transparent
throw e.getTargetException();
}
}
}
/**
* Run the underlying destroy methodStr on the run classStr.
*/
public void destroy() {
initialised = false;
valid = false;
invokeDestroy(runClassInstance);
// be paranoid and clean up all hooks to users classStr
destroyMethod = null;
runMethod = null;
initMethod = null;
runServletConfig = null;
runConstructor = null;
runClassInstance = null;
methodStr = null;
classStr = null;
error = null;
}
/**
* Will invoke the instance created in initialise.
*
* @param httpServletRequest
* @param httpServletResponse
*/
public void execute(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws IOException, ServletException {
if (!initialised) {
log.debug("not initialised skipping");
return;
}
if (!valid) {
log.debug("not valid skipping");
return;
}
Object[] args = new Object[2];
args[0] = httpServletRequest;
args[1] = httpServletResponse;
if (newEachTime) {
Object newRunClassInstance = fetchNewInstance();
invokeRunMethod(newRunClassInstance, args);
invokeDestroy(newRunClassInstance);
} else {
invokeRunMethod(runClassInstance, args);
}
}
private void logInvokeException(String methodStr, Exception e) {
Throwable cause = e.getCause();
if (cause == null) {
setError("when invoking " + methodStr + " on " + classStr
+ " got an " + e.toString(), e);
} else {
setError("when invoking " + methodStr + " on " + classStr
+ " got an " + e.toString() + " caused by " + cause.toString(), cause);
}
}
/**
* Get a new instance of the classStr we want to run and init if required.
*
* @return the new instance
*/
private Object fetchNewInstance() {
Object obj;
log.debug("getting new instance of " + classStr);
try {
obj = runConstructor.newInstance(null);
} catch (InstantiationException e) {
logInvokeException("constructor", e);
return null;
} catch (IllegalAccessException e) {
logInvokeException("constructor", e);
return null;
} catch (InvocationTargetException e) {
logInvokeException("constructor", e);
return null;
}
if (initMethod != null) {
log.debug("about to run init(ServletConfig) on " + classStr);
Object[] args = new Object[1];
args[0] = runServletConfig;
try {
initMethod.invoke(obj, args);
} catch (IllegalAccessException e) {
logInvokeException("init(ServletConfig)", e);
return null;
} catch (InvocationTargetException e) {
logInvokeException("init(ServletConfig)", e);
return null;
}
}
return obj;
}
public String getError() {
return error;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public boolean isValid() {
return valid;
}
public boolean isInitialised() {
return initialised;
}
/**
* The name of the classStr that will be run for each rule match.
*
* @return String eg, org.tuckey.YellowObject
*/
public String getClassStr() {
return classStr;
}
/**
* The name of the methodStr that will be run for each rule match.
*
* @return String eg, setDate
*/
public String getMethodStr() {
return methodStr;
}
public boolean isNewEachTime() {
return newEachTime;
}
public void setNewEachTime(boolean newEachTime) {
this.newEachTime = newEachTime;
}
/**
* Gets a handle on the instance of the class run is running.
* <p/>
* If newEachTime is set to true this will always return null.
*/
public Object getRunClassInstance() {
return runClassInstance;
}
public void addInitParam(String name, String value) {
if (name != null) {
initParams.put(name, value);
}
}
public String getInitParam(String paramName) {
return (String) initParams.get(paramName);
}
public void setClassStr(String classStr) {
this.classStr = classStr;
}
public void setMethodStr(String methodStr) {
this.methodStr = methodStr;
}
public static void setCheckRunObjectExists(boolean checkRunObjectExists) {
Run.checkRunObjectExists = checkRunObjectExists;
}
public void setError(String error, Throwable t) {
this.error = error;
log.error(error, t);
}
public void setError(String error) {
this.error = error;
log.error(error);
}
public String getDisplayName() {
return "Run " + id;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -