use of org.directwebremoting.extend.Creator in project ma-core-public by infiniteautomation.
the class DefaultRemoter method execute.
/**
* Execute a single call object
* @param call The call to execute
* @return A Reply to the Call
*/
public Reply execute(Call call) {
try {
Method method = call.getMethod();
if (method == null || call.getException() != null) {
return new Reply(call.getCallId(), null, call.getException());
}
// Get a list of the available matching methods with the coerced
// parameters that we will use to call it if we choose to use that
// method.
Creator creator = creatorManager.getCreator(call.getScriptName());
// We don't need to check accessControl.getReasonToNotExecute()
// because the checks are made by the doExec method, but we do check
// if we can display it
accessControl.assertExecutionIsPossible(creator, call.getScriptName(), method);
// Get ourselves an object to execute a method on unless the
// method is static
Object object = null;
String scope = creator.getScope();
boolean create = false;
if (!Modifier.isStatic(method.getModifiers())) {
WebContext webcx = WebContextFactory.get();
// Check the various scopes to see if it is there
if (scope.equals(Creator.APPLICATION)) {
object = webcx.getServletContext().getAttribute(call.getScriptName());
} else if (scope.equals(Creator.SESSION)) {
object = webcx.getSession().getAttribute(call.getScriptName());
} else if (scope.equals(Creator.SCRIPT)) {
object = webcx.getScriptSession().getAttribute(call.getScriptName());
} else if (scope.equals(Creator.REQUEST)) {
object = webcx.getHttpServletRequest().getAttribute(call.getScriptName());
}
// If we don't have an object the call the creator
if (object == null) {
create = true;
object = creator.getInstance();
}
// Remember it for next time
if (create) {
if (scope.equals(Creator.APPLICATION)) {
// This might also be done at application startup by
// DefaultCreatorManager.addCreator(String, Creator)
webcx.getServletContext().setAttribute(call.getScriptName(), object);
} else if (scope.equals(Creator.SESSION)) {
webcx.getSession().setAttribute(call.getScriptName(), object);
} else if (scope.equals(Creator.SCRIPT)) {
webcx.getScriptSession().setAttribute(call.getScriptName(), object);
} else if (scope.equals(Creator.REQUEST)) {
webcx.getHttpServletRequest().setAttribute(call.getScriptName(), object);
}
// Creator.PAGE scope means we create one every time anyway
}
}
// Some debug
log.info("Exec: " + call.getScriptName() + "." + call.getMethodName() + "()");
if (log.isDebugEnabled()) {
StringBuffer buffer = new StringBuffer();
if (create) {
buffer.append("--Object created, ");
if (!scope.equals(Creator.PAGE)) {
buffer.append(" stored in ");
buffer.append(scope);
} else {
buffer.append(" not stored");
}
} else {
buffer.append("--Object found in ");
buffer.append(scope);
}
buffer.append(". ");
// It would be good to debug the params but it's not easy
// buffer.append("Call params (");
// for (int j = 0; j < inctx.getParameterCount(callNum); j++)
// {
// if (j != 0)
// {
// buffer.append(", ");
// }
// InboundVariable param = inctx.getParameter(callNum, j);
// buffer.append(param.toString());
// }
// buffer.append(") ");
buffer.append("id=");
buffer.append(call.getCallId());
log.debug(buffer.toString());
}
// Execute the filter chain method.toString()
final Iterator it = ajaxFilterManager.getAjaxFilters(call.getScriptName());
AjaxFilterChain chain = new AjaxFilterChain() {
public Object doFilter(Object obj, Method meth, Object[] p) throws Exception {
AjaxFilter next = (AjaxFilter) it.next();
return next.doFilter(obj, meth, p, this);
}
};
Object reply = chain.doFilter(object, method, call.getParameters());
return new Reply(call.getCallId(), reply);
} catch (InvocationTargetException ex) {
// Allow Jetty RequestRetry exception to propogate to container
Continuation.rethrowIfContinuation(ex);
log.warn("Method execution failed: ", ex.getTargetException());
return new Reply(call.getCallId(), null, ex.getTargetException());
} catch (Exception ex) {
// Allow Jetty RequestRetry exception to propogate to container
Continuation.rethrowIfContinuation(ex);
log.warn("Method execution failed: ", ex);
return new Reply(call.getCallId(), null, ex);
}
}
use of org.directwebremoting.extend.Creator in project ma-core-public by infiniteautomation.
the class DefaultRemoter method generateInterfaceScript.
/* (non-Javadoc)
* @see org.directwebremoting.Remoter#generateInterfaceScript(java.lang.String, java.lang.String)
*/
public String generateInterfaceScript(String scriptName, String path) throws SecurityException {
String actualPath = path;
if (overridePath != null) {
actualPath = overridePath;
}
StringBuffer buffer = new StringBuffer();
// Output the class definitions for the converted objects
Collection converterMatches = converterManager.getConverterMatchStrings();
Iterator it = converterMatches.iterator();
while (it.hasNext()) {
String match = (String) it.next();
try {
StringBuffer paramBuffer = new StringBuffer();
Converter conv = converterManager.getConverterByMatchString(match);
// We will only generate JavaScript classes for compound objects/beans
if (conv instanceof NamedConverter) {
NamedConverter boConv = (NamedConverter) conv;
String jsClassName = boConv.getJavascript();
// We need a configured JavaScript class name
if (jsClassName != null && !jsClassName.equals("")) {
// Wildcard match strings are currently not supported
if (match.indexOf("*") == -1) {
paramBuffer.append('\n');
// output: if (typeof <class> != "function") { var <class> = function() {
paramBuffer.append("if (typeof " + jsClassName + " != \"function\") {\n");
paramBuffer.append(" function " + jsClassName + "() {\n");
// output: this.<property> = <init-value>;
Class mappedType;
try {
mappedType = LocalUtil.classForName(match);
} catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(ex.getMessage());
}
Map properties = boConv.getPropertyMapFromClass(mappedType, true, true);
for (Iterator pit = properties.entrySet().iterator(); pit.hasNext(); ) {
Map.Entry entry = (Map.Entry) pit.next();
String name = (String) entry.getKey();
Property property = (Property) entry.getValue();
Class propType = property.getPropertyType();
// Property name
paramBuffer.append(" this." + name + " = ");
// Default property values
if (propType.isArray()) {
paramBuffer.append("[]");
} else if (propType == boolean.class) {
paramBuffer.append("false");
} else if (propType.isPrimitive()) {
paramBuffer.append("0");
} else {
paramBuffer.append("null");
}
paramBuffer.append(";\n");
}
paramBuffer.append(" }\n");
paramBuffer.append("}\n");
}
}
}
buffer.append(paramBuffer.toString());
} catch (Exception ex) {
log.warn("Failed to create parameter declaration for " + match, ex);
buffer.append("// Missing parameter declaration for " + match + ". See the server logs for details.");
}
}
Creator creator = creatorManager.getCreator(scriptName);
buffer.append('\n');
String init = EnginePrivate.getEngineInitScript();
buffer.append(init);
buffer.append("if (" + scriptName + " == null) var " + scriptName + " = {};\n");
buffer.append(scriptName + "._path = '" + actualPath + "';\n");
Method[] methods = creator.getType().getMethods();
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
String methodName = method.getName();
// check if we can display it
try {
accessControl.assertIsDisplayable(creator, scriptName, method);
} catch (SecurityException ex) {
if (!allowImpossibleTests) {
continue;
}
}
// Is it on the list of banned names
if (JavascriptUtil.isReservedWord(methodName)) {
continue;
}
// Check to see if the creator is reloadable
// If it is, then do not cache the generated Javascript
String script;
if (!creator.isCacheable()) {
script = getMethodJS(scriptName, method);
} else {
String key = scriptName + "." + method.getName();
// For optimal performance we might use the Memoizer pattern
// JCiP#108 however performance isn't a big issue and we are
// prepared to cope with getMethodJS() being run more than once.
script = (String) methodCache.get(key);
if (script == null) {
script = getMethodJS(scriptName, method);
methodCache.put(key, script);
}
}
buffer.append(script);
}
return buffer.toString();
}
use of org.directwebremoting.extend.Creator in project ma-core-public by infiniteautomation.
the class BaseCallMarshaller method findMethod.
/**
* Find the method the best matches the method name and parameters
* @param call The function call we are going to make
* @param inctx The data conversion context
* @return A matching method, or null if one was not found.
*/
private Method findMethod(Call call, InboundContext inctx) {
if (call.getScriptName() == null) {
throw new IllegalArgumentException(Messages.getString("BaseCallMarshaller.MissingClassParam"));
}
if (call.getMethodName() == null) {
throw new IllegalArgumentException(Messages.getString("BaseCallMarshaller.MissingMethodParam"));
}
Creator creator = creatorManager.getCreator(call.getScriptName());
Method[] methods = creator.getType().getMethods();
List available = new ArrayList();
methods: for (int i = 0; i < methods.length; i++) {
// Check method name and access
if (methods[i].getName().equals(call.getMethodName())) {
// Check number of parameters
if (methods[i].getParameterTypes().length == inctx.getParameterCount()) {
// Clear the previous conversion attempts (the param types
// will probably be different)
inctx.clearConverted();
// Check parameter types
for (int j = 0; j < methods[i].getParameterTypes().length; j++) {
Class paramType = methods[i].getParameterTypes()[j];
if (!converterManager.isConvertable(paramType)) {
// Give up with this method and try the next
continue methods;
}
}
available.add(methods[i]);
}
}
}
// Pick a method to call
if (available.size() > 1) {
log.warn("Warning multiple matching methods. Using first match.");
}
if (available.isEmpty()) {
return null;
}
// later increment we might pick the best implementation
return (Method) available.get(0);
}
use of org.directwebremoting.extend.Creator in project ma-core-public by infiniteautomation.
the class BaseCallMarshaller method marshallInbound.
/* (non-Javadoc)
* @see org.directwebremoting.extend.Marshaller#marshallInbound(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public Calls marshallInbound(HttpServletRequest request, HttpServletResponse response) throws IOException, ServerException {
// We must parse the parameters before we setup the conduit because it's
// only after doing this that we know the scriptSessionId
WebContext webContext = WebContextFactory.get();
Batch batch = (Batch) request.getAttribute(ATTRIBUTE_BATCH);
if (batch == null) {
batch = new Batch(request, crossDomainSessionSecurity, allowGetForSafariButMakeForgeryEasier, sessionCookieName);
// Save calls for retry exception
request.setAttribute(ATTRIBUTE_BATCH, batch);
}
// Various bits of the Batch need to be stashed away places
storeParsedRequest(request, webContext, batch);
Calls calls = batch.getCalls();
// Debug the environment
if (log.isDebugEnabled() && calls.getCallCount() > 0) {
// We can just use 0 because they are all shared
InboundContext inctx = (InboundContext) batch.getInboundContexts().get(0);
StringBuffer buffer = new StringBuffer();
for (Iterator it = inctx.getInboundVariableNames(); it.hasNext(); ) {
String key = (String) it.next();
InboundVariable value = inctx.getInboundVariable(key);
if (key.startsWith(ProtocolConstants.INBOUND_CALLNUM_PREFIX) && key.indexOf(ProtocolConstants.INBOUND_CALLNUM_SUFFIX + ProtocolConstants.INBOUND_KEY_ENV) != -1) {
buffer.append(key);
buffer.append('=');
buffer.append(value.toString());
buffer.append(", ");
}
}
if (buffer.length() > 0) {
log.debug("Environment: " + buffer.toString());
}
}
callLoop: for (int callNum = 0; callNum < calls.getCallCount(); callNum++) {
Call call = calls.getCall(callNum);
InboundContext inctx = (InboundContext) batch.getInboundContexts().get(callNum);
// Get a list of the available matching methods with the coerced
// parameters that we will use to call it if we choose to use
// that method.
Creator creator = creatorManager.getCreator(call.getScriptName());
// Which method are we using?
Method method = findMethod(call, inctx);
if (method == null) {
String name = call.getScriptName() + '.' + call.getMethodName();
String error = Messages.getString("BaseCallMarshaller.UnknownMethod", name);
log.warn("Marshalling exception: " + error);
call.setMethod(null);
call.setParameters(null);
call.setException(new IllegalArgumentException(error));
continue callLoop;
}
call.setMethod(method);
// Check this method is accessible
accessControl.assertExecutionIsPossible(creator, call.getScriptName(), method);
// Convert all the parameters to the correct types
Object[] params = new Object[method.getParameterTypes().length];
for (int j = 0; j < method.getParameterTypes().length; j++) {
try {
Class paramType = method.getParameterTypes()[j];
InboundVariable param = inctx.getParameter(callNum, j);
TypeHintContext incc = new TypeHintContext(converterManager, method, j);
params[j] = converterManager.convertInbound(paramType, param, inctx, incc);
} catch (MarshallException ex) {
log.warn("Marshalling exception", ex);
call.setMethod(null);
call.setParameters(null);
call.setException(ex);
continue callLoop;
}
}
call.setParameters(params);
}
return calls;
}
Aggregations