Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.apache.wink.server.internal.RequestProcessor Maven / Gradle / Ivy
/*******************************************************************************
* 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.application.ApplicationExceptionAttribute;
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.registry.ResourceRecord;
import org.apache.wink.server.internal.registry.ResourceRegistry;
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$
// keep track of whether an application-originated exception has already been logged so we don't
// accidentally log sensitive application stack information
private boolean alreadyLogged = false;
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.trace("{} property is set to: {}", //$NON-NLS-1$
PROPERTY_LOAD_WINK_APPLICATIONS,
loadWinkApplicationsProperty);
final Set> 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.trace("{} 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.trace("{} 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 {
if (logger.isDebugEnabled()) {
String requestMethod = request.getMethod();
String requestString = request.getRequestURL().toString();
requestString +=
((request.getQueryString() != null && request.getQueryString().length() > 0)
? ("?" + request.getQueryString()) : ""); //$NON-NLS-1$ $NON-NLS-2$
logger
.debug(Messages
.getMessage("processingRequestTo", requestMethod, requestString, request.getContentType(), request.getHeader("Accept"))); //$NON-NLS-1$ $NON-NLS-2$
}
handleRequestWithoutFaultBarrier(request, response);
} catch (Throwable t) {
// exception was not handled properly
ApplicationExceptionAttribute appEx = null;
RuntimeContext runtimeContext = RuntimeContextTLS.getRuntimeContext();
if (runtimeContext != null) {
appEx = runtimeContext.getAttribute(ApplicationExceptionAttribute.class);
}
if (appEx != null && (appEx.getDebugMsg() != null)) {
// This exception originated from an application class, such as a resource or provider
// See unittest class DebugResourceThrowsExceptionTest.
if (logger.isDebugEnabled()) {
logger.debug(appEx.getDebugMsg());
}
// although we may not have actually called the logger, we want to prevent logging sensitive application stack
alreadyLogged = true;
} else {
if (logger.isTraceEnabled()) {
if (alreadyLogged) {
// don't log possibly sensitive application stack
logger.trace(Messages.getMessage("unhandledExceptionToContainer")); //$NON-NLS-1$
} else {
logger.trace(Messages.getMessage("unhandledExceptionToContainer"), t); //$NON-NLS-1$
}
} else {
if (logger.isErrorEnabled()) {
if (alreadyLogged) {
// don't log possibly sensitive application stack
logger.error(Messages.getMessage("unhandledExceptionToContainer")); //$NON-NLS-1$
} else {
logger.error(Messages.getMessage("unhandledExceptionToContainer"), t); //$NON-NLS-1$
}
}
}
}
// reset flag:
alreadyLogged = false;
if (t instanceof RuntimeException) {
// let the servlet container 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.trace("Set message context and starting request handlers chain: {}", msgContext); //$NON-NLS-1$
// run the request handler chain
configuration.getRequestHandlersChain().run(msgContext);
logger
.trace("Finished request handlers chain and starting response handlers chain: {}", //$NON-NLS-1$
msgContext);
// run the response handler chain
configuration.getResponseHandlersChain().run(msgContext);
logger.trace("Attempting to release resource instance");
isReleaseResourcesCalled = true;
try {
releaseResources(msgContext);
} catch (Exception e) {
logger.trace("Caught exception when releasing resource object", e);
throw e;
}
} catch (Throwable t) {
RuntimeContext originalContext = RuntimeContextTLS.getRuntimeContext();
ServerMessageContext msgContext = null;
try {
logException(t, request);
msgContext = createMessageContext(request, response);
RuntimeContextTLS.setRuntimeContext(msgContext);
msgContext.setResponseEntity(t);
// run the error handler chain
logger.trace("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.trace("Caught exception when releasing resource object", e2);
}
}
} catch (Exception e) {
RuntimeContextTLS.setRuntimeContext(originalContext);
if (!isReleaseResourcesCalled) {
isReleaseResourcesCalled = true;
try {
releaseResources(originalContext);
} catch (Exception e2) {
logger.trace("Caught exception when releasing resource object", e2);
}
}
throw e;
}
} finally {
logger.trace("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 resourceInstances = searchResult.getData().getMatchedResources();
for (ResourceInstance res : resourceInstances) {
logger.trace("Releasing resource instance");
res.releaseInstance(msgContext);
}
}
}
private void logException(Throwable t, HttpServletRequest request) {
ApplicationExceptionAttribute appEx = RuntimeContextTLS.getRuntimeContext().getAttribute(ApplicationExceptionAttribute.class);
if (appEx != null && (appEx.getDebugMsg() != null)) {
// This exception originated from an application class, such as a resource or provider
// See unittest class DebugResourceThrowsExceptionTest.
if (logger.isDebugEnabled()) {
logger.debug(appEx.getDebugMsg());
}
// although we may not have actually called the logger, we want to prevent logging sensitive application stack
alreadyLogged = true;
return;
}
String messageFormat;
String requestMethod = request.getMethod();
String requestString = request.getRequestURL().toString();
requestString +=
((request.getQueryString() != null && request.getQueryString().length() > 0)
? ("?" + request.getQueryString()) : ""); //$NON-NLS-1$ $NON-NLS-2$
if (t instanceof WebApplicationException) {
WebApplicationException wae = (WebApplicationException)t;
int statusCode = wae.getResponse().getStatus();
Status status = Response.Status.fromStatusCode(statusCode);
String statusSep = ""; //$NON-NLS-1$
String statusMessage = ""; //$NON-NLS-1$
if (status != null) {
statusSep = " - "; //$NON-NLS-1$
statusMessage = status.toString();
}
String exceptionName =
String
.format("%s (%d%s%s)", t.getClass().getSimpleName(), statusCode, statusSep, statusMessage); //$NON-NLS-1$
messageFormat =
Messages
.getMessage("exceptionOccurredDuringInvocation", exceptionName, wae.getMessage(), requestMethod, requestString); //$NON-NLS-1$
} else {
messageFormat =
Messages
.getMessage("exceptionOccurredDuringInvocation", t.getClass().getSimpleName(), t.getMessage(), requestMethod, requestString); //$NON-NLS-1$
}
if (logger.isDebugEnabled()) {
logger.debug(messageFormat, t);
ResourceRegistry rr = this.configuration.getResourceRegistry();
List resourceRecords = rr.getRecords();
StringBuffer sb = new StringBuffer();
String newLine = System.getProperty("line.separator"); //$NON-NLS-1$
for (ResourceRecord record : resourceRecords) {
sb.append(newLine + " " + record.toString()); //$NON-NLS-1$
}
logger
.debug(Messages
.getMessage("registeredResources", (sb.toString().length() > 0) ? sb.toString() : "{}")); //$NON-NLS-1$ $NON-NLS-2$
logger.debug(this.configuration.getProvidersRegistry()
.getLogFormattedProvidersList(true));
} else {
logger.info(messageFormat); // TODO should we log all the 404s?
}
}
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
.trace("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.trace("Storing request processor {} using attribute name {} in servlet context {}", //$NON-NLS-1$
new Object[] {this, attributeName, servletContext});
servletContext.setAttribute(attributeName, this);
}
}