⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 executequery.java

📁 很不错的js应用框架
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 uk.ltd.getahead.dwr.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;

import uk.ltd.getahead.dwr.AccessControl;
import uk.ltd.getahead.dwr.Call;
import uk.ltd.getahead.dwr.Calls;
import uk.ltd.getahead.dwr.ConversionConstants;
import uk.ltd.getahead.dwr.ConversionException;
import uk.ltd.getahead.dwr.ConverterManager;
import uk.ltd.getahead.dwr.Creator;
import uk.ltd.getahead.dwr.CreatorManager;
import uk.ltd.getahead.dwr.InboundContext;
import uk.ltd.getahead.dwr.TypeHintContext;
import uk.ltd.getahead.dwr.InboundVariable;
import uk.ltd.getahead.dwr.Messages;
import uk.ltd.getahead.dwr.OutboundContext;
import uk.ltd.getahead.dwr.OutboundVariable;
import uk.ltd.getahead.dwr.WebContext;
import uk.ltd.getahead.dwr.WebContextFactory;
import uk.ltd.getahead.dwr.util.JavascriptUtil;
import uk.ltd.getahead.dwr.util.LocalUtil;
import uk.ltd.getahead.dwr.util.Logger;

/**
 * This class represents a query made by a client in terms of the data that is
 * passed in to be converted to Java objects.
 * @author Joe Walker [joe at getahead dot ltd dot uk]
 */
public class ExecuteQuery
{
    /**
     * Simple ctor
     * @param creatorManager The way we get an object to call methods on
     * @param converterManager The way we convert javascript to java
     * @param accessControl The security manager
     */
    public ExecuteQuery(CreatorManager creatorManager, ConverterManager converterManager, AccessControl accessControl)
    {
        this.creatorManager = creatorManager;
        this.converterManager = converterManager;
        this.accessControl = accessControl;
    }

    /**
     * Check (as far as we can) that the execute method will succeed.
     * @param req The original browser's request
     * @return The call details the methods we are calling
     * @throws IOException If reading from the request body stream fails
     */
    public Calls execute(HttpServletRequest req) throws IOException
    {
        Calls calls = null;

        if (req.getMethod().equals("GET")) //$NON-NLS-1$
        {
            calls = parseParameters(parseGet(req));
        }
        else
        {
            calls = parseParameters(parsePost(req));
        }

        // Since we are passing all the responses back in one script, there is
        // only one outbound context.
        OutboundContext converted = new OutboundContext();

        for (int callNum = 0; callNum < calls.getCallCount(); callNum++)
        {
            Call call = calls.getCall(callNum);
            InboundContext inctx = call.getInboundContext();

            try
            {
                // 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);
                if (method == null)
                {
                    String name = call.getScriptName() + '.' + call.getMethodName();
                    throw new IllegalArgumentException(Messages.getString("ExecuteQuery.UnknownMethod", name)); //$NON-NLS-1$
                }

                // Check this method is accessible
                String reason = accessControl.getReasonToNotExecute(req, creator, call.getScriptName(), method);
                if (reason != null)
                {
                    log.error("Access denied: " + reason); //$NON-NLS-1$
                    log.error("  From: "  + req.getRemoteAddr() + " asking for: " + req.getRequestURI()); //$NON-NLS-1$ //$NON-NLS-2$
                    throw new SecurityException(Messages.getString("ExecuteQuery.AccessDenied")); //$NON-NLS-1$
                }

                // 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(method, j);

                        params[j] = converterManager.convertInbound(paramType, param, inctx, incc);
                    }
                    catch (ConversionException ex)
                    {
                        throw new ConversionException(Messages.getString("ExecuteQuery.ConversionError", call.getScriptName(), call.getMethodName(), ex.getMessage()), ex); //$NON-NLS-1$
                    }
                }

                // 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.REQUEST))
                    {
                        object = webcx.getHttpServletRequest().getAttribute(call.getScriptName());
                    }
                    // Creator.PAGE scope means we create one every time anyway

                    // If we don't have an object the call the creator
                    if (object == null)
                    {
                        create = true;
                        object = creator.getInstance();
                    }

                    // We might need to remember it for next time
                    if (scope.equals(Creator.APPLICATION))
                    {
                        webcx.getServletContext().setAttribute(call.getScriptName(), object);
                    }
                    else if (scope.equals(Creator.SESSION))
                    {
                        webcx.getSession().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[" + callNum + "]: " + call.getScriptName() + "." + call.getMethodName() + "()"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
                if (log.isDebugEnabled())
                {
                    StringBuffer buffer = new StringBuffer();

                    if (create)
                    {
                        buffer.append("--Object created, "); //$NON-NLS-1$
                        if (!scope.equals(Creator.PAGE))
                        {
                            buffer.append(" stored in "); //$NON-NLS-1$
                            buffer.append(scope);
                        }
                        else
                        {
                            buffer.append(" not stored"); //$NON-NLS-1$
                        }
                    }
                    else
                    {
                        buffer.append("--Object found in "); //$NON-NLS-1$
                        buffer.append(scope);
                    }

                    buffer.append(". Call params ("); //$NON-NLS-1$
                    for (int j = 0; j < inctx.getParameterCount(callNum); j++)
                    {
                        if (j != 0)
                        {
                            buffer.append(", "); //$NON-NLS-1$
                        }
                        InboundVariable param = inctx.getParameter(callNum, j);
                        buffer.append(param.toString());
                    }
                    buffer.append(") id="); //$NON-NLS-1$
                    buffer.append(call.getId());

                    buffer.append(". Using ("); //$NON-NLS-1$
                    buffer.append(calls.isXhrMode() ? "XHR" : "IFrame"); //$NON-NLS-1$ //$NON-NLS-2$
                    buffer.append(","); //$NON-NLS-1$
                    buffer.append(req.getMethod());
                    buffer.append(")"); //$NON-NLS-1$

                    log.debug(buffer.toString());
                }

                // Execute
                Object reply = method.invoke(object, params);

                OutboundVariable ov = converterManager.convertOutbound(reply, converted);
                call.setReply(ov);
            }
            catch (InvocationTargetException ex)
            {
                log.warn("Method execution failed: ", ex.getTargetException()); //$NON-NLS-1$
                call.setThrowable(convertException(converted, ex.getTargetException()));
            }
            catch (Throwable ex)
            {
                log.warn("Method execution failed: ", ex); //$NON-NLS-1$
                call.setThrowable(convertException(converted, ex));
            }
        }

        return calls;
    }

    /**
     * Parse an HTTP POST request to fill out the scriptName, methodName and
     * paramList properties. This method should not fail unless it will not
     * be possible to return any sort of error to the user. Failure cases should
     * be handled by the <code>checkParams()</code> method.
     * @param req The original browser's request
     * @return The equivalent of HttpServletRequest.getParameterMap() for now
     * @throws IOException If reading from the request body stream fails
     */
    private Map parsePost(HttpServletRequest req) throws IOException
    {
        Map paramMap = new HashMap();

        // I've had reports of data loss in Tomcat 5.0 that relate to this bug
        //   http://issues.apache.org/bugzilla/show_bug.cgi?id=27447
        // See mails to users@dwr.dev.java.net:
        //   Subject: "Tomcat 5.x read-ahead problem"
        //   From: CAKALIC, JAMES P [AG-Contractor/1000]
        // It would be more normal to do the following:
        // BufferedReader in = req.getReader();
        BufferedReader in = new BufferedReader(new InputStreamReader(req.getInputStream()));

        if (in == null)
        {
            // it is not a post message
            throw new RuntimeException(Messages.getString("ExecuteQuery.ErrorNullPost")); //$NON-NLS-1$
        }

        int lines = 0;
        while (true)
        {
            String line = in.readLine();

            if (line == null)
            {
                break;
            }

            lines++;

            if (line.indexOf('&') != -1)
            {
                // If there are any &s then this must be iframe post and all the
                // parameters have got dumped on one line, split with &

⌨️ 快捷键说明

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