/*
* Copyright 2005-2007 WSO2, Inc. (http://wso2.com)
*
* 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.wso2.carbon.core.transports;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.xpath.AXIOMXPath;
import org.apache.axiom.util.blob.OverflowBlob;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.transport.http.AxisServlet;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.util.XMLUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.protocol.HTTP;
import org.jaxen.SimpleNamespaceContext;
import org.jaxen.XPath;
import org.osgi.util.tracker.ServiceTracker;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.core.internal.CarbonCoreDataHolder;
import org.wso2.carbon.core.transports.metering.MeteredServletRequest;
import org.wso2.carbon.core.transports.metering.MeteredServletResponse;
import org.wso2.carbon.core.transports.metering.RequestDataPersister;
import org.wso2.carbon.utils.ServerConstants;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.util.*;
/**
* This is the main HTTP and HTTPS transport
*/
public class CarbonServlet extends AxisServlet {
private static final long serialVersionUID = 3460108128756524161L;
private Map<String, HttpGetRequestProcessor> getRequestProcessors =
new LinkedHashMap<String, HttpGetRequestProcessor>();
private static final QName ITEM_QN = new QName(ServerConstants.CARBON_SERVER_XML_NAMESPACE, "Item");
private static final QName CLASS_QN = new QName(ServerConstants.CARBON_SERVER_XML_NAMESPACE, "Class");
private static final Log log = LogFactory.getLog(CarbonServlet.class);
public CarbonServlet(ConfigurationContext configurationContext){
this.configContext = configurationContext;
}
public void init(ServletConfig config) throws ServletException {
this.axisConfiguration = this.configContext.getAxisConfiguration();
this.servletConfig = config;
populateGetRequestProcessors();
configContext.setProperty("GETRequestProcessorMap", getRequestProcessors);
initParams();
}
private void populateGetRequestProcessors() throws ServletException {
try {
OMElement docEle = XMLUtils.toOM(ServerConfiguration.getInstance().getDocumentElement());
if (docEle != null) {
SimpleNamespaceContext nsCtx = new SimpleNamespaceContext();
nsCtx.addNamespace("wsas", ServerConstants.CARBON_SERVER_XML_NAMESPACE);
XPath xp = new AXIOMXPath("//wsas:HttpGetRequestProcessors/wsas:Processor");
xp.setNamespaceContext(nsCtx);
List nodeList = xp.selectNodes(docEle);
for (Object aNodeList : nodeList) {
OMElement processorEle = (OMElement) aNodeList;
OMElement itemEle = processorEle.getFirstChildWithName(ITEM_QN);
if (itemEle == null) {
throw new ServletException("Required element, 'Item' not found!");
}
OMElement classEle = processorEle.getFirstChildWithName(CLASS_QN);
HttpGetRequestProcessor processor;
if (classEle == null) {
throw new ServletException("Required element, 'Class' not found!");
} else {
processor =
(HttpGetRequestProcessor)
Class.forName(classEle.getText().trim()).newInstance();
}
getRequestProcessors.put(itemEle.getText().trim(), processor);
}
}
} catch (Exception e) {
log.error("Cannot populate HTTPGetRequestProcessors", e);
throw new ServletException(e);
}
}
/**
* WSAS specific GET implementation
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
initContextRoot(request);
boolean isRequestHandled = false;
try {
String queryString = request.getQueryString();
if (queryString != null) {
for (String item : getRequestProcessors.keySet()) {
if (queryString.indexOf(item) == 0 &&
(queryString.equals(item) ||
queryString.indexOf("&") == item.length() ||
queryString.indexOf("=") == item.length())) {
processWithGetProcessor(request, response, item);
isRequestHandled = true;
break;
}
}
}
if (!isRequestHandled) {
handleRestRequest(request, response); // Assume that this is a REST request
}
} catch (Exception e) {
throw AxisFault.makeFault(e);
}
}
private void processWithGetProcessor(HttpServletRequest request,
HttpServletResponse response,
String item) throws Exception {
OverflowBlob temporaryData = new OverflowBlob(256, 4048, "_servlet", ".dat");
try {
CarbonHttpRequest carbonHttpRequest = new CarbonHttpRequest(
"GET", request.getRequestURI(), request.getRequestURL().toString());
Enumeration names = request.getParameterNames();
while (names.hasMoreElements()) {
Object name = names.nextElement();
if (name != null && name instanceof String) {
carbonHttpRequest.setParameter((String) name,
request.getParameter((String) name));
}
}
carbonHttpRequest.setContextPath(request.getContextPath());
carbonHttpRequest.setQueryString(request.getQueryString());
CarbonHttpResponse carbonHttpResponse = new CarbonHttpResponse(
temporaryData.getOutputStream());
(getRequestProcessors.get(item)).process(carbonHttpRequest,
carbonHttpResponse, configContext);
// adding headers
Map responseHeaderMap = carbonHttpResponse.getHeaders();
for (Object key : responseHeaderMap.keySet()) {
Object value = responseHeaderMap.get(key);
response.setHeader(key.toString(), value.toString());
}
// setting status code
response.setStatus(carbonHttpResponse.getStatusCode());
// setting error codes
if (carbonHttpResponse.isError()) {
if (carbonHttpResponse.getStatusMessage() != null) {
response.sendError(carbonHttpResponse.getStatusCode(),
carbonHttpResponse.getStatusMessage());
} else {
response.sendError(carbonHttpResponse.getStatusCode());
}
}
if (carbonHttpResponse.isRedirect()) {
response.sendRedirect(carbonHttpResponse.getRedirect());
}
if (carbonHttpResponse.getHeaders().get(HTTP.CONTENT_TYPE) != null) {
response.setContentType(
carbonHttpResponse.getHeaders().get(HTTP.CONTENT_TYPE));
}
temporaryData.writeTo(response.getOutputStream());
} finally {
temporaryData.release();
}
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// Here we are using MeteredServletRequest and MeteredServletResponse to meter
// the request and response.
// TODO: only wrap the request and response if a carbon.xml entry"metering=true
MeteredServletRequest wrappedRequest = new MeteredServletRequest(request);
MeteredServletResponse wrappedResponse = new MeteredServletResponse(response);
super.doPost(wrappedRequest, wrappedResponse);
// Call the callback to persist the wrapped request and wrapped response data
persistRequestData(wrappedRequest, wrappedResponse);
}
protected void persistRequestData(MeteredServletRequest wrappedRequest,
MeteredServletResponse wrappedResponse) {
RequestDataPersister requestDataPersister = null;
ServiceTracker meteringDataPersistTracker =
new ServiceTracker(CarbonCoreDataHolder.getInstance().getBundleContext(),
RequestDataPersister.class.getName(),
null);
meteringDataPersistTracker.open();
try {
requestDataPersister = (RequestDataPersister) meteringDataPersistTracker.getService();
} finally {
meteringDataPersistTracker.close();
}
if (requestDataPersister != null) {
requestDataPersister.persist(wrappedRequest, wrappedResponse);
}
}
protected void handleRestRequest(HttpServletRequest request,
HttpServletResponse response) throws IOException,
ServletException {
if (!disableREST) {
new RestRequestProcessor(HTTPConstants.HTTP_METHOD_GET,
request,
response).processURLRequest();
} else {
showRestDisabledErrorMessage(response);
}
}
public void addGetRequestProcessor(String key, HttpGetRequestProcessor processor) {
getRequestProcessors.put(key, processor);
}
public void removeGetRequestProcessor(String key) {
getRequestProcessors.remove(key);
}
}