Package org.apache.wink.server.internal

Source Code of org.apache.wink.server.internal.RequestProcessor

/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.apache.wink.server.internal;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.apache.wink.common.RuntimeContext;
import org.apache.wink.common.WinkApplication;
import org.apache.wink.common.internal.i18n.Messages;
import org.apache.wink.common.internal.runtime.RuntimeContextTLS;
import org.apache.wink.server.internal.application.ServletApplicationFileLoader;
import org.apache.wink.server.internal.handlers.SearchResult;
import org.apache.wink.server.internal.handlers.ServerMessageContext;
import org.apache.wink.server.internal.registry.ResourceInstance;
import org.apache.wink.server.internal.resources.HtmlServiceDocumentResource;
import org.apache.wink.server.internal.resources.RootResource;
import org.apache.wink.server.utils.RegistrationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Responsible for request processing.
*/
public class RequestProcessor {

    private static final Logger           logger                           =
                                                                               LoggerFactory
                                                                                   .getLogger(RequestProcessor.class);
    private static final String           PROPERTY_ROOT_RESOURCE_NONE      = "none";                                  //$NON-NLS-1$
    private static final String           PROPERTY_ROOT_RESOURCE_ATOM      = "atom";                                  //$NON-NLS-1$
    private static final String           PROPERTY_ROOT_RESOURCE_ATOM_HTML = "atom+html";                             //$NON-NLS-1$
    private static final String           PROPERTY_ROOT_RESOURCE_DEFAULT   =
                                                                               PROPERTY_ROOT_RESOURCE_ATOM_HTML;
    private static final String           PROPERTY_ROOT_RESOURCE           = "wink.rootResource";                     //$NON-NLS-1$
    private static final String           PROPERTY_ROOT_RESOURCE_CSS       =
                                                                               "wink.serviceDocumentCssPath";         //$NON-NLS-1$
    private static final String           PROPERTY_LOAD_WINK_APPLICATIONS  =
                                                                               "wink.loadApplications";               //$NON-NLS-1$

    private final DeploymentConfiguration configuration;

    public RequestProcessor(DeploymentConfiguration configuration) {
        this.configuration = configuration;
        registerDefaultApplication();
        registerRootResources();
    }

    private void registerDefaultApplication() {
        try {
            String loadWinkApplicationsProperty =
                configuration.getProperties().getProperty(PROPERTY_LOAD_WINK_APPLICATIONS,
                                                          Boolean.toString(true));
            logger.debug("{} property is set to: {}", //$NON-NLS-1$
                         PROPERTY_LOAD_WINK_APPLICATIONS,
                         loadWinkApplicationsProperty);
            final Set<Class<?>> classes =
                new ServletApplicationFileLoader(Boolean.parseBoolean(loadWinkApplicationsProperty))
                    .getClasses();
            RegistrationUtils.InnerApplication application =
                new RegistrationUtils.InnerApplication(classes);
            application.setPriority(WinkApplication.SYSTEM_PRIORITY);
            configuration.addApplication(application, true);
        } catch (FileNotFoundException e) {
            throw new WebApplicationException(e);
        }
    }

    private void registerRootResources() {
        Properties properties = configuration.getProperties();
        String registerRootResource =
            properties.getProperty(PROPERTY_ROOT_RESOURCE, PROPERTY_ROOT_RESOURCE_DEFAULT);
        logger.debug("{} property is set to: {}", PROPERTY_ROOT_RESOURCE, registerRootResource); //$NON-NLS-1$
        if (registerRootResource.equals(PROPERTY_ROOT_RESOURCE_ATOM)) {
            RegistrationUtils.InnerApplication application =
                new RegistrationUtils.InnerApplication(RootResource.class);
            application.setPriority(WinkApplication.SYSTEM_PRIORITY);
            configuration.addApplication(application, true);
        } else if (registerRootResource.equals(PROPERTY_ROOT_RESOURCE_NONE)) {
            // do nothing
        } else {
            String css = properties.getProperty(PROPERTY_ROOT_RESOURCE_CSS);
            logger.debug("{} property is set to: {}", PROPERTY_ROOT_RESOURCE_CSS, css); //$NON-NLS-1$
            HtmlServiceDocumentResource instance = new HtmlServiceDocumentResource();
            if (css != null) {
                instance.setServiceDocumentCssPath(css);
            }
            RegistrationUtils.InnerApplication application =
                new RegistrationUtils.InnerApplication(instance);
            application.setPriority(WinkApplication.SYSTEM_PRIORITY);
            configuration.addApplication(application, true);
        }
    }

    // --- request processing ---

    /**
     * Dispatches the request and fills the response (even with an error
     * message.
     *
     * @param request AS or mock request
     * @param response AS or mock response
     * @throws IOException I/O error
     */
    public void handleRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException {
        try {
            handleRequestWithoutFaultBarrier(request, response);
        } catch (Throwable t) {
            // exception was not handled properly
            if (logger.isDebugEnabled()) {
                logger.debug(Messages.getMessage("unhandledExceptionToContainer"), t); //$NON-NLS-1$
            } else {
                if (logger.isInfoEnabled()) {
                    logger.info(Messages.getMessage("unhandledExceptionToContainer")); //$NON-NLS-1$
                }
            }
            if (t instanceof RuntimeException) {
                // let the servlet container to handle the runtime exception
                throw (RuntimeException)t;
            }
            throw new ServletException(t);
        }
    }

    private void handleRequestWithoutFaultBarrier(HttpServletRequest request,
                                                  HttpServletResponse response) throws Throwable {
        boolean isReleaseResourcesCalled = false;
        try {
            ServerMessageContext msgContext = createMessageContext(request, response);
            RuntimeContextTLS.setRuntimeContext(msgContext);
            logger.debug("Set message context and starting request handlers chain: {}", msgContext); //$NON-NLS-1$
            // run the request handler chain
            configuration.getRequestHandlersChain().run(msgContext);
            logger
                .debug("Finished request handlers chain and starting response handlers chain: {}", //$NON-NLS-1$
                       msgContext);
            // run the response handler chain
            configuration.getResponseHandlersChain().run(msgContext);

            logger.debug("Attempting to release resource instance");
            isReleaseResourcesCalled = true;
            try {
                releaseResources(msgContext);
            } catch (Exception e) {
                logger.debug("Caught exception when releasing resource object", e);
                throw e;
            }
        } catch (Throwable t) {
            RuntimeContext originalContext = RuntimeContextTLS.getRuntimeContext();
            ServerMessageContext msgContext = null;
            try {
                logException(t);
                msgContext = createMessageContext(request, response);
                RuntimeContextTLS.setRuntimeContext(msgContext);
                msgContext.setResponseEntity(t);
                // run the error handler chain
                logger.debug("Exception occured, starting error handlers chain: {}", msgContext); //$NON-NLS-1$
                configuration.getErrorHandlersChain().run(msgContext);

                RuntimeContextTLS.setRuntimeContext(originalContext);
                if (!isReleaseResourcesCalled) {
                    isReleaseResourcesCalled = true;
                    try {
                        releaseResources(originalContext);
                    } catch (Exception e2) {
                        logger.debug("Caught exception when releasing resource object", e2);
                    }
                }
            } catch (Exception e) {
                RuntimeContextTLS.setRuntimeContext(originalContext);
                if (!isReleaseResourcesCalled) {
                    isReleaseResourcesCalled = true;
                    try {
                        releaseResources(originalContext);
                    } catch (Exception e2) {
                        logger.debug("Caught exception when releasing resource object", e2);
                    }
                }
                throw e;
            }
        } finally {
            logger.debug("Finished response handlers chain"); //$NON-NLS-1$
            RuntimeContextTLS.setRuntimeContext(null);
        }
    }

    private void releaseResources(RuntimeContext msgContext) throws Exception {
        SearchResult searchResult = msgContext.getAttribute(SearchResult.class);
        if (searchResult != null) {
            List<ResourceInstance> resourceInstances = searchResult.getData().getMatchedResources();
            for (ResourceInstance res : resourceInstances) {
                logger.debug("Releasing resource instance");
                res.releaseInstance(msgContext);
            }
        }
    }

    private void logException(Throwable t) {
        String exceptionName = t.getClass().getSimpleName();
        String messageFormat =
            Messages.getMessage("exceptionOccurredDuringInvocation", exceptionName);
        if (t instanceof WebApplicationException) {
            WebApplicationException wae = (WebApplicationException)t;
            int statusCode = wae.getResponse().getStatus();
            Status status = Response.Status.fromStatusCode(statusCode);
            String statusSep = "";
            String statusMessage = "";
            if (status != null) {
                statusSep = " - ";
                statusMessage = status.toString();
            }
            exceptionName =
                String.format("%s (%d%s%s)", exceptionName, statusCode, statusSep, statusMessage);
            if (statusCode >= 500) {
                if (logger.isDebugEnabled()) {
                    logger.debug(messageFormat, t);
                } else {
                    logger.info(messageFormat);
                }
            } else {
                // don't log the whole call stack for sub-500 return codes
                // unless debugging
                if (logger.isDebugEnabled()) {
                    logger.debug(messageFormat, t);
                } else {
                    logger.info(messageFormat);
                }
            }
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug(messageFormat, t);
            } else {
                logger.info(messageFormat);
            }
        }
    }

    private ServerMessageContext createMessageContext(HttpServletRequest request,
                                                      HttpServletResponse response) {
        ServerMessageContext messageContext =
            new ServerMessageContext(request, response, configuration);
        return messageContext;
    }

    public DeploymentConfiguration getConfiguration() {
        return configuration;
    }

    public static RequestProcessor getRequestProcessor(ServletContext servletContext,
                                                       String attributeName) {
        if (attributeName == null) {
            attributeName = RequestProcessor.class.getName();
        }
        RequestProcessor requestProcessor =
            (RequestProcessor)servletContext.getAttribute(attributeName);
        logger
            .debug("Retrieving request processor {} using attribute name {} in servlet context {}", //$NON-NLS-1$
                   new Object[] {requestProcessor, attributeName, servletContext});
        return requestProcessor;
    }

    public void storeRequestProcessorOnServletContext(ServletContext servletContext,
                                                      String attributeName) {
        if (attributeName == null || attributeName.length() == 0) {
            attributeName = RequestProcessor.class.getName();
        }
        logger.debug("Storing request processor {} using attribute name {} in servlet context {}", //$NON-NLS-1$
                     new Object[] {this, attributeName, servletContext});
        servletContext.setAttribute(attributeName, this);
    }
}
TOP

Related Classes of org.apache.wink.server.internal.RequestProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.