basecallmarshaller.java

来自「反向的AJAX。最大的特性是我们成为反向的Ajax。DWR1.x允许你用java」· Java 代码 · 共 577 行 · 第 1/2 页

JAVA
577
字号
/* * Copyright 2005 Joe Walker * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.directwebremoting.dwrp;import java.io.IOException;import java.io.PrintWriter;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Map;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.directwebremoting.ScriptBuffer;import org.directwebremoting.WebContext;import org.directwebremoting.WebContextFactory;import org.directwebremoting.extend.AccessControl;import org.directwebremoting.extend.Call;import org.directwebremoting.extend.Calls;import org.directwebremoting.extend.ConverterManager;import org.directwebremoting.extend.Creator;import org.directwebremoting.extend.CreatorManager;import org.directwebremoting.extend.InboundContext;import org.directwebremoting.extend.InboundVariable;import org.directwebremoting.extend.MarshallException;import org.directwebremoting.extend.Marshaller;import org.directwebremoting.extend.PageNormalizer;import org.directwebremoting.extend.RealScriptSession;import org.directwebremoting.extend.EnginePrivate;import org.directwebremoting.extend.Replies;import org.directwebremoting.extend.Reply;import org.directwebremoting.extend.ScriptBufferUtil;import org.directwebremoting.extend.ScriptConduit;import org.directwebremoting.extend.ServerException;import org.directwebremoting.extend.TypeHintContext;import org.directwebremoting.util.DebuggingPrintWriter;import org.directwebremoting.util.Logger;import org.directwebremoting.util.Messages;/** * A Marshaller that output plain Javascript. * This marshaller can be tweaked to output Javascript in an HTML context. * This class works in concert with CallScriptConduit, they should be * considered closely related and it is important to understand what one does * while editing the other. * @author Joe Walker [joe at getahead dot ltd dot uk] */public abstract class BaseCallMarshaller implements Marshaller{    /* (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;    }    /**     * Build a Batch and put it in the request     * @param request Where we store the parsed data     * @param webContext We need to notify others of some of the data we find     * @param batch The parsed data to store     */    private void storeParsedRequest(HttpServletRequest request, WebContext webContext, Batch batch)    {        String normalizedPage = pageNormalizer.normalizePage(batch.getPage());        webContext.setCurrentPageInformation(normalizedPage, batch.getScriptSessionId());        // Remaining parameters get put into the request for later consumption        Map paramMap = batch.getSpareParameters();        if (paramMap.size() != 0)        {            for (Iterator it = paramMap.entrySet().iterator(); it.hasNext();)            {                Map.Entry entry = (Map.Entry) it.next();                String key = (String) entry.getKey();                String value = (String) entry.getValue();                request.setAttribute(key, value);                log.debug("Moved param to request: " + key + "=" + value);            }        }    }    /**     * 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;        }        // At the moment we are just going to take the first match, for a        // later increment we might pick the best implementation        return (Method) available.get(0);    }    /* (non-Javadoc)     * @see org.directwebremoting.Marshaller#marshallOutbound(org.directwebremoting.Replies, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)     */    public void marshallOutbound(Replies replies, HttpServletRequest request, HttpServletResponse response) throws IOException    {        // Get the output stream and setup the mimetype        response.setContentType(getOutboundMimeType());        PrintWriter out;        if (log.isDebugEnabled())        {            // This might be considered evil - altering the program flow            // depending on the log status, however DebuggingPrintWriter is            // very thin and only about logging            out = new DebuggingPrintWriter("", response.getWriter());        }        else        {            out = response.getWriter();        }        // The conduit to pass on reverse ajax scripts

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?