Search in sources :

Example 11 with Creator

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);
    }
}
Also used : WebContext(org.directwebremoting.WebContext) Method(java.lang.reflect.Method) Creator(org.directwebremoting.extend.Creator) AjaxFilterChain(org.directwebremoting.AjaxFilterChain) InvocationTargetException(java.lang.reflect.InvocationTargetException) InvocationTargetException(java.lang.reflect.InvocationTargetException) Iterator(java.util.Iterator) Reply(org.directwebremoting.extend.Reply) AjaxFilter(org.directwebremoting.AjaxFilter)

Example 12 with Creator

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();
}
Also used : NamedConverter(org.directwebremoting.extend.NamedConverter) Creator(org.directwebremoting.extend.Creator) Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException) Iterator(java.util.Iterator) Collection(java.util.Collection) NamedConverter(org.directwebremoting.extend.NamedConverter) Converter(org.directwebremoting.extend.Converter) HashMap(java.util.HashMap) Map(java.util.Map) Property(org.directwebremoting.extend.Property)

Example 13 with Creator

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);
}
Also used : ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) Creator(org.directwebremoting.extend.Creator) Method(java.lang.reflect.Method)

Example 14 with Creator

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;
}
Also used : Call(org.directwebremoting.extend.Call) WebContext(org.directwebremoting.WebContext) TypeHintContext(org.directwebremoting.extend.TypeHintContext) InboundContext(org.directwebremoting.extend.InboundContext) Calls(org.directwebremoting.extend.Calls) InboundVariable(org.directwebremoting.extend.InboundVariable) Creator(org.directwebremoting.extend.Creator) Method(java.lang.reflect.Method) MarshallException(org.directwebremoting.extend.MarshallException) Iterator(java.util.Iterator)

Aggregations

Creator (org.directwebremoting.extend.Creator)14 Iterator (java.util.Iterator)8 Method (java.lang.reflect.Method)6 Map (java.util.Map)4 Collection (java.util.Collection)3 HashMap (java.util.HashMap)3 List (java.util.List)3 WebContext (org.directwebremoting.WebContext)3 CreatorManager (org.directwebremoting.extend.CreatorManager)3 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 ArrayList (java.util.ArrayList)2 AjaxFilter (org.directwebremoting.AjaxFilter)2 AccessControl (org.directwebremoting.extend.AccessControl)2 AjaxFilterManager (org.directwebremoting.extend.AjaxFilterManager)2 ConverterManager (org.directwebremoting.extend.ConverterManager)2 TypeHintContext (org.directwebremoting.extend.TypeHintContext)2 BufferedReader (java.io.BufferedReader)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 InputStreamReader (java.io.InputStreamReader)1