org.pentaho.platform.web.servlet.JAXRSPluginServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.platform.web.servlet.JAXRSPluginServlet.java

Source

/*!
 * This program is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
 * Foundation.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
 * or from the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * Copyright (c) 2002-2013 Pentaho Corporation..  All rights reserved.
 */

package org.pentaho.platform.web.servlet;

import com.sun.jersey.api.core.ResourceConfig;
import com.sun.jersey.spi.container.WebApplication;
import com.sun.jersey.spi.container.servlet.WebConfig;
import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * This should only be used by a plugin in the plugin.spring.xml file to initialize a Jersey. The presence of this
 * servlet in the spring file will make it possible to write JAX-RS POJOs in your plugin.
 *
 * @author Aaron Phillips
 */
public class JAXRSPluginServlet extends SpringServlet implements ApplicationContextAware {

    private static final long serialVersionUID = 457538570048660945L;
    private static final String APPLICATION_WADL = "application.wadl";

    // Matches: application.wadl, application.wadl/xsd0.xsd
    // Does not match: application.wadl/.xsd, application.wadl/xsd0/xsd0.xsd, application.wadl/a.xml
    private static final Pattern WADL_PATTERN = Pattern
            .compile("(.*)" + APPLICATION_WADL + "(/[A-Za-z0-9_]+(.xsd)+)*");

    private ApplicationContext applicationContext;

    public static final ThreadLocal requestThread = new ThreadLocal();

    private static final Log logger = LogFactory.getLog(JAXRSPluginServlet.class);

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    protected ConfigurableApplicationContext getContext() {
        return (ConfigurableApplicationContext) applicationContext;
    }

    @Override
    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        logger.debug("servicing request for resource " + request.getPathInfo()); //$NON-NLS-1$

        // Jersey's Servlet only responds to 'application.wadl', Plugin requests always have 'plugin/PLUGIN_NAME/api' as a
        // predicate i.e. /plugin/data-access/api/application.wadl.
        //
        // If the request ends with application.wadl, dispatch a Proxied request that rewrites the url to plain
        // 'application.wadl'. This is using a JDK Dynamic Proxy which increases overhead, but these requests should be
        // seldom and don't need to be that performant.
        if (WADL_PATTERN.matcher(request.getPathInfo()).find()) {
            final HttpServletRequest originalRequest = request;
            final String appWadlUrl = request.getPathInfo()
                    .substring(request.getPathInfo().indexOf(APPLICATION_WADL), request.getPathInfo().length());
            request = (HttpServletRequest) Proxy.newProxyInstance(getClass().getClassLoader(),
                    new Class[] { HttpServletRequest.class }, new InvocationHandler() {
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            if (method.getName().equals("getPathInfo")) {
                                return appWadlUrl;
                            } else if (method.getName().equals("getRequestURL")) {
                                String url = originalRequest.getRequestURL().toString();
                                return new StringBuffer(url.substring(0, url.indexOf(originalRequest.getPathInfo()))
                                        + "/" + appWadlUrl);
                            } else if (method.getName().equals("getRequestURI")) {
                                String uri = originalRequest.getRequestURI();
                                return uri.substring(0, uri.indexOf(originalRequest.getPathInfo())) + "/"
                                        + appWadlUrl;
                            }
                            // We don't care about the Method, delegate out to real Request object.
                            return method.invoke(originalRequest, args);
                        }
                    });
            if (originalRequest.getRequestURL() != null) {
                requestThread.set(originalRequest.getRequestURL().toString());
            } else if (originalRequest.getRequestURI() != null) {
                requestThread.set(originalRequest.getRequestURI().toString());
            }
        }
        super.service(request, response);
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        super.service(req, res);
    }

    @Override
    protected void initiate(ResourceConfig rc, WebApplication wa) {
        if (logger.isDebugEnabled()) {
            rc.getFeatures().put(ResourceConfig.FEATURE_TRACE, true);
            rc.getFeatures().put(ResourceConfig.FEATURE_TRACE_PER_REQUEST, true);
        }
        super.initiate(rc, wa);
    }

    protected ResourceConfig getDefaultResourceConfig(Map<String, Object> props, WebConfig webConfig)
            throws ServletException {
        props.put("com.sun.jersey.config.property.WadlGeneratorConfig",
                "org.pentaho.platform.web.servlet.PentahoWadlGeneratorConfig");
        return super.getDefaultResourceConfig(props, webConfig);
    }
}