com.liferay.web.extender.servlet.BundleServletContext.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.web.extender.servlet.BundleServletContext.java

Source

/**
 * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library 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.
 */

package com.liferay.web.extender.servlet;

import com.liferay.portal.apache.bridges.struts.LiferayServletContext;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.FileUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.osgi.OSGiConstants;
import com.liferay.portal.util.PortalUtil;
import com.liferay.web.extender.service.HttpServiceTracker;

import java.io.InputStream;

import java.net.MalformedURLException;
import java.net.URL;

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionListener;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.NamespaceException;

/**
 * @author Raymond Aug
 */
public class BundleServletContext extends LiferayServletContext {

    public BundleServletContext(ServletContext servletContext, Servlet portletServlet) {

        super(servletContext);

        _portletServlet = portletServlet;
    }

    public static String getServletContextName(Bundle bundle) {
        Dictionary<String, String> headers = bundle.getHeaders();

        String webContextPath = headers.get(OSGiConstants.WEB_CONTEXTPATH);

        if (Validator.isNull(webContextPath)) {
            return null;
        }

        return webContextPath.substring(1);
    }

    public void close() {
        if (_httpServiceTracker == null) {
            return;
        }

        _httpServiceTracker.close();
    }

    @Override
    public Object getAttribute(String name) {
        if (name.equals("bundle.classloader")) {
            return _classLoader;
        }

        Object value = _contextAttributes.get(name);

        if ((value != null) || name.equals("org.springframework.web.context.WebApplicationContext.ROOT")) {

            return value;
        }

        return super.getAttribute(name);
    }

    public ClassLoader getClassLoader() {
        if (_classLoader == null) {
            Bundle bundle = (Bundle) getAttribute(OSGiConstants.OSGI_BUNDLE);

            BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);

            _classLoader = bundleWiring.getClassLoader();
        }

        return _classLoader;
    }

    @Override
    public String getContextPath() {
        if (_contextPath == null) {
            StringBundler sb = new StringBundler(4);

            String contextPath = super.getContextPath();

            if (!contextPath.equals(StringPool.SLASH)) {
                sb.append(contextPath);
            }

            sb.append(PortalUtil.getPathMain());
            sb.append(OSGiServlet.SERVLET_MAPPING);
            sb.append(getServletContextName());

            _contextPath = sb.toString();
        }

        return _contextPath;
    }

    @Override
    public RequestDispatcher getRequestDispatcher(String path) {
        String alias = path;

        FilterChain filterChain = getFilterChain(alias);

        if (path.startsWith(OSGiServlet.SERVLET_MAPPING) && path.endsWith(OSGiServlet.INVOKER_PATH)) {

            return new BundleRequestDispatcher(path, false, path, _portletServlet, filterChain);
        }

        if (!isValidPath(path)) {
            return null;
        }

        if (Validator.isNull(alias)) {
            alias = StringPool.SLASH;
        }

        if (_servletsMap.containsKey(alias)) {
            return new BundleRequestDispatcher(alias, false, path, _servletsMap.get(alias), filterChain);
        }

        String extensionMapping = FileUtil.getExtension(alias).toLowerCase();

        if (Validator.isNotNull(extensionMapping)) {
            extensionMapping = _EXTENSION_PREFIX.concat(extensionMapping);
        }

        alias = alias.substring(0, alias.lastIndexOf(StringPool.SLASH));

        while (alias.length() != 0) {
            if (_servletsMap.containsKey(alias)) {
                return new BundleRequestDispatcher(alias, false, path, _servletsMap.get(alias), filterChain);
            } else if (_servletsMap.containsKey(alias.concat(extensionMapping))) {
                return new BundleRequestDispatcher(alias.concat(extensionMapping), true, path,
                        _servletsMap.get(alias.concat(extensionMapping)), filterChain);
            }

            alias = alias.substring(0, alias.lastIndexOf(StringPool.SLASH));
        }

        if (_servletsMap.containsKey(StringPool.SLASH.concat(extensionMapping))) {

            return new BundleRequestDispatcher(StringPool.SLASH.concat(extensionMapping), true, path,
                    _servletsMap.get(StringPool.SLASH.concat(extensionMapping)), filterChain);
        }

        if (_servletsMap.containsKey(StringPool.SLASH)) {
            return new BundleRequestDispatcher(StringPool.SLASH, false, path, _servletsMap.get(StringPool.SLASH),
                    filterChain);
        }

        return null;
    }

    @Override
    public URL getResource(String path) throws MalformedURLException {
        Bundle bundle = (Bundle) getAttribute(OSGiConstants.OSGI_BUNDLE);

        try {
            return bundle.getEntry(path);
        } catch (IllegalStateException ise) {
            return null;
        }
    }

    @Override
    public InputStream getResourceAsStream(String path) {
        try {
            URL resource = getResource(path);

            if (resource != null) {
                return resource.openStream();
            }
        } catch (Exception e) {
            if (_log.isDebugEnabled()) {
                _log.debug(e, e);
            }
        }

        return null;
    }

    @Override
    public Set<String> getResourcePaths(String path) {
        Set<String> resourcePaths = new HashSet<String>();

        Bundle bundle = (Bundle) getAttribute(OSGiConstants.OSGI_BUNDLE);

        Enumeration<String> resources = bundle.getEntryPaths(path);

        if ((resources != null) && resources.hasMoreElements()) {
            while (resources.hasMoreElements()) {
                resourcePaths.add(resources.nextElement());
            }
        }

        return resourcePaths;
    }

    @Override
    public String getServletContextName() {
        if (_servletContextName == null) {
            Bundle bundle = (Bundle) getAttribute(OSGiConstants.OSGI_BUNDLE);

            _servletContextName = getServletContextName(bundle);
        }

        return _servletContextName;
    }

    public void open() {
        Bundle bundle = (Bundle) getAttribute(OSGiConstants.OSGI_BUNDLE);

        Dictionary<String, String> headers = bundle.getHeaders();

        String webContextPath = headers.get(OSGiConstants.WEB_CONTEXTPATH);

        BundleContext bundleContext = bundle.getBundleContext();

        Hashtable<String, Object> properties = new Hashtable<String, Object>();

        properties.put("osgi.web.symbolicname", bundle.getSymbolicName());
        properties.put("osgi.web.version", bundle.getVersion().toString());
        properties.put("osgi.web.contextpath", webContextPath);

        bundleContext.registerService(ServletContext.class, this, properties);

        _httpServiceTracker = new HttpServiceTracker(bundleContext);

        _httpServiceTracker.open();
    }

    public void registerFilter(String filterMapping, Filter filter, Dictionary initParams, HttpContext httpContext)
            throws ServletException, NamespaceException {

        validate(filterMapping, filter, httpContext);

        FilterConfig filterConfig = new BundleFilterConfig(this, filterMapping, initParams, httpContext);

        filter.init(filterConfig);

        _filtersMap.put(filterMapping, filter);
        _filterList.add(new Object[] { filterMapping, filter });
    }

    public void registerListener(String listenerClassName, Object listener, Dictionary initParams,
            HttpContext httpContext) throws ServletException {

        if (listener instanceof HttpSessionListener) {
            // TODO throw new UnsupportedOperationException();
        } else if (listener instanceof HttpSessionAttributeListener) {
            // TODO throw new UnsupportedOperationException();
        } else if (listener instanceof ServletContextListener) {
            ServletContextListener servletContextListener = (ServletContextListener) listener;

            ServletContextEvent servletContextEvent = new ServletContextEvent(this);

            servletContextListener.contextInitialized(servletContextEvent);
        } else if (listener instanceof ServletContextAttributeListener) {
            _contextAttributeListeners.put(listenerClassName, (ServletContextAttributeListener) listener);
        } else if (listener instanceof ServletRequestListener) {
            // TODO throw new UnsupportedOperationException();
        } else if (listener instanceof ServletRequestAttributeListener) {
            // TODO throw new UnsupportedOperationException();
        }
    }

    public void registerResources(String alias, String name, HttpContext httpContext) throws NamespaceException {

        validate(name);

        Servlet servlet = new ResourceServlet(name, httpContext);

        try {
            registerServlet(alias, servlet, null, httpContext);
        } catch (ServletException se) {
            throw new IllegalArgumentException(se);
        }
    }

    public void registerServlet(String alias, Servlet servlet, Dictionary initParams, HttpContext httpContext)
            throws ServletException, NamespaceException {

        validate(alias, servlet, httpContext);

        ServletConfig servletConfig = new BundleServletConfig(this, alias, initParams, httpContext);

        servlet.init(servletConfig);

        _servletsMap.put(alias, servlet);
    }

    @Override
    public void removeAttribute(String name) {
        Object value = _contextAttributes.remove(name);

        for (ServletContextAttributeListener listener : _contextAttributeListeners.values()) {

            listener.attributeRemoved(new ServletContextAttributeEvent(this, name, value));
        }
    }

    @Override
    public void setAttribute(String name, Object value) {
        Object originalValue = _contextAttributes.get(name);

        _contextAttributes.put(name, value);

        for (ServletContextAttributeListener listener : _contextAttributeListeners.values()) {

            if (originalValue != null) {
                listener.attributeReplaced(new ServletContextAttributeEvent(this, name, originalValue));
            } else {
                listener.attributeAdded(new ServletContextAttributeEvent(this, name, value));
            }
        }
    }

    public void unregister(String alias) {
        Servlet servlet = _servletsMap.remove(alias);

        if (servlet != null) {
            servlet.destroy();
        }
    }

    public void unregisterFilter(String filterMapping) {
        Filter filter = _filtersMap.get(filterMapping);

        if (filter != null) {
            filter.destroy();
        }
    }

    public void unregisterListener(String listenerClassName) {
        Object listener = _listeners.get(listenerClassName);

        if (listener instanceof HttpSessionListener) {
        } else if (listener instanceof HttpSessionAttributeListener) {
        } else if (listener instanceof ServletContextListener) {
            ServletContextListener servletContextListener = (ServletContextListener) listener;

            ServletContextEvent servletContextEvent = new ServletContextEvent(this);

            servletContextListener.contextDestroyed(servletContextEvent);
        } else if (listener instanceof ServletContextAttributeListener) {
            _contextAttributeListeners.remove(listenerClassName);
        } else if (listener instanceof ServletRequestListener) {
        } else if (listener instanceof ServletRequestAttributeListener) {
        }
    }

    protected FilterChain getFilterChain(String alias) {
        BundleFilterChain bundleFilterChain = new BundleFilterChain();

        for (Object[] filterDefinition : _filterList) {
            String filterMapping = (String) filterDefinition[0];
            Filter filter = (Filter) filterDefinition[1];

            if (filterMapping.equals(alias)) {
                bundleFilterChain.addFilter(filter);
            }

            if (filterMapping.contains(StringPool.STAR)) {
                filterMapping = filterMapping.replaceAll(StringPool.STAR, ".*");
            }

            if (alias.matches(filterMapping)) {
                bundleFilterChain.addFilter(filter);
            }
        }

        return bundleFilterChain;
    }

    protected boolean isValidPath(String path) {
        for (String illegalPath : _ILLEGAL_PATHS) {
            if (path.contains(illegalPath)) {
                return false;
            }
        }

        return true;
    }

    protected void validate(String name) {
        if (name == null) {
            throw new IllegalArgumentException("Name cannot be null");
        }

        if (name.endsWith(StringPool.SLASH) && !name.equals(StringPool.SLASH)) {
            throw new IllegalArgumentException("Invalid name " + name);
        }
    }

    protected void validate(String filterMapping, Filter filter, HttpContext httpContext)
            throws NamespaceException {

        if (filterMapping == null) {
            throw new IllegalArgumentException("FilterMapping cannot be null");
        }

        if (filterMapping.endsWith(StringPool.SLASH) && !filterMapping.equals(StringPool.SLASH)) {

            throw new IllegalArgumentException("Invalid filterMapping " + filterMapping);
        }

        if (filter == null) {
            throw new IllegalArgumentException("Filter must not be null");
        }

        if (_filtersMap.containsValue(filter)) {
            throw new IllegalArgumentException("Filter is already registered");
        }

        if (httpContext == null) {
            throw new IllegalArgumentException("HttpContext cannot be null");
        }
    }

    protected void validate(String alias, Servlet servlet, HttpContext httpContext) throws NamespaceException {

        if (Validator.isNull(alias)) {
            throw new IllegalArgumentException("Empty aliases are not allowed");
        }

        if (!alias.startsWith(StringPool.SLASH)
                || (alias.endsWith(StringPool.SLASH) && !alias.equals(StringPool.SLASH))) {

            throw new IllegalArgumentException("Alias must start with / but must not end with it");
        }

        if (_servletsMap.containsKey(alias)) {
            throw new NamespaceException("Alias " + alias + " already exists");
        }

        if (servlet == null) {
            throw new IllegalArgumentException("Servlet must not be null");
        }

        if (_servletsMap.containsValue(servlet)) {
            throw new IllegalArgumentException("Servlet is already registered");
        }

        if (httpContext == null) {
            throw new IllegalArgumentException("HttpContext cannot be null");
        }
    }

    private static final String[] _ILLEGAL_PATHS = new String[] { "WEB-INF/", "OSGI-INF/", "META-INF/",
            "OSGI-OPT/" };
    private static final String _INVOKER_PATH = "/invoke";
    private static final String _EXTENSION_PREFIX = "*.";

    private static final Log _log = LogFactoryUtil.getLog(BundleServletContext.class);

    private ClassLoader _classLoader;
    private Map<String, Object> _contextAttributes = new ConcurrentHashMap<String, Object>();
    private Map<String, ServletContextAttributeListener> _contextAttributeListeners = new ConcurrentHashMap<String, ServletContextAttributeListener>();
    private String _contextPath;
    private Map<String, Filter> _filtersMap = new ConcurrentHashMap<String, Filter>();
    private List<Object[]> _filterList = new ArrayList<Object[]>();
    private HttpServiceTracker _httpServiceTracker;
    private Map<String, Object> _listeners = new ConcurrentHashMap<String, Object>();
    //private ServiceRegistration<ServletContext> _serviceRegisteration;
    private String _servletContextName;
    private Map<String, Servlet> _servletsMap = new ConcurrentHashMap<String, Servlet>();
    private Servlet _portletServlet;

}