Package org.apache.geronimo.jetty8.handler

Source Code of org.apache.geronimo.jetty8.handler.GeronimoWebAppContext$BundleFileResource

/*
* 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.geronimo.jetty8.handler;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.naming.NamingException;
import javax.security.auth.login.LoginException;
import javax.security.jacc.PolicyContextException;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletSecurityElement;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.geronimo.connector.outbound.connectiontracking.ConnectorInstanceContext;
import org.apache.geronimo.connector.outbound.connectiontracking.SharedConnectorInstanceContext;
import org.apache.geronimo.osgi.web.WABApplicationConstants;
import org.apache.geronimo.osgi.web.WebApplicationUtils;
import org.apache.geronimo.security.jacc.ApplicationPolicyConfigurationManager;
import org.apache.geronimo.security.jacc.ComponentPermissions;
import org.apache.geronimo.web.WebApplicationConstants;
import org.apache.geronimo.web.WebApplicationName;
import org.apache.geronimo.web.WebModuleListener;
import org.apache.geronimo.web.assembler.Assembler;
import org.apache.geronimo.web.info.WebAppInfo;
import org.apache.geronimo.web.security.SpecSecurityBuilder;
import org.apache.geronimo.web.security.WebSecurityConstraintStore;
import org.apache.xbean.osgi.bundle.util.BundleUtils;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.URLResource;
import org.eclipse.jetty.webapp.WebAppContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @version $Rev: 1331657 $ $Date: 2012-04-28 10:17:12 +0800 (Sat, 28 Apr 2012) $
*/
public class GeronimoWebAppContext extends WebAppContext {

    private static final Logger logger = LoggerFactory.getLogger(GeronimoWebAppContext.class);

    private final IntegrationContext integrationContext;
    private final String modulePath;
    private final ClassLoader classLoader;
    private final WebAppInfo webAppInfo;
    private final WebSecurityConstraintStore webSecurityConstraintStore;
    private final String policyContextId;
    private final ApplicationPolicyConfigurationManager applicationPolicyConfigurationManager;
    private ServiceRegistration serviceRegistration;
    boolean fullyStarted = false;
    private String webModuleName;
    private final List webModuleListeners;

    public GeronimoWebAppContext(SecurityHandler securityHandler,
                                 SessionHandler sessionHandler,
                                 ServletHandler servletHandler,
                                 ErrorHandler errorHandler,
                                 IntegrationContext integrationContext,
                                 ClassLoader classLoader,
                                 String modulePath,
                                 WebAppInfo webAppInfo,
                                 String policyContextId,
                                 ApplicationPolicyConfigurationManager applicationPolicyConfigurationManager,
                                 List<String> webModuleListenerClassNames) {
        super(sessionHandler, securityHandler, servletHandler, errorHandler);
        _scontext = new Context();
        this.integrationContext = integrationContext;
        setClassLoader(classLoader);
        this.classLoader = classLoader;

        Bundle bundle = BundleUtils.unwrapBundle(integrationContext.getBundle());

        setAttribute(WABApplicationConstants.BUNDLE_CONTEXT_ATTRIBUTE,
                     bundle.getBundleContext());

        setAttribute(WebApplicationConstants.WEB_APP_INFO, webAppInfo);

        setAttribute("org.springframework.osgi.web." + BundleContext.class.getName(),
                     bundle.getBundleContext());

        setAttribute(WebApplicationConstants.WEB_APP_NAME, webModuleName);

        // now set the module context ValidatorFactory in a context property.
        try {
            javax.naming.Context ctx = integrationContext.getComponentContext();
            Object validatorFactory = ctx.lookup("comp/ValidatorFactory");
            setAttribute("javax.faces.validator.beanValidator.ValidatorFactory", validatorFactory);
        } catch (NamingException e) {
            // ignore.  We just don't set the property if it's not available.
        }
        this.modulePath = modulePath;
        this.webAppInfo = webAppInfo;
        this.policyContextId = policyContextId;
        this.applicationPolicyConfigurationManager = applicationPolicyConfigurationManager;
        //TODO schemaVersion >= 2.5f && !metaComplete but only for a while....
        boolean annotationScanRequired = true;
        webSecurityConstraintStore = new WebSecurityConstraintStore(webAppInfo, integrationContext.getBundle(), annotationScanRequired, _scontext);

        if (webModuleListenerClassNames != null && webModuleListenerClassNames.size() > 0) {
            webModuleListeners = new ArrayList(webModuleListenerClassNames.size());
            for (String webModuleListenerClassName : webModuleListenerClassNames) {
                try {
                    Class<?> cls = classLoader.loadClass(webModuleListenerClassName);
                    Object webModuleListener = cls.newInstance();
                    webModuleListeners.add(webModuleListener);
                } catch (ClassNotFoundException e) {
                    logger.warn("Unable to load the listener class" + webModuleListenerClassName, e);
                } catch (InstantiationException e) {
                    logger.warn("Unable to create the listener instance " + webModuleListenerClassName, e);
                } catch (IllegalAccessException e) {
                    logger.warn("Unable to create the listener instance " + webModuleListenerClassName, e);
                }
            }
        } else {
            webModuleListeners = Collections.emptyList();
        }
    }

    public void setWebModuleName(String webModuleName) {
        this.webModuleName = webModuleName;
    }

    public void registerServletContext() {
        // for OSGi Web Applications support register ServletContext in service registry
        Bundle bundle = integrationContext.getBundle();
        if (WebApplicationUtils.isWebApplicationBundle(bundle)) {
            serviceRegistration = WebApplicationUtils.registerServletContext(bundle, getServletContext());
        }
    }

    public void unregisterServletContext() {
        if (serviceRegistration != null) {
            serviceRegistration.unregister();
        }
    }

    @Override
    protected void doStart() throws Exception {
        javax.naming.Context context = integrationContext.setContext();
        boolean txActive = integrationContext.isTxActive();
        SharedConnectorInstanceContext newContext = integrationContext.newConnectorInstanceContext(null);
        ConnectorInstanceContext connectorContext = integrationContext.setConnectorInstance(null, newContext);
        String oldApplicationName = WebApplicationName.getName();
        WebApplicationName.setName(integrationContext.getWebApplicationIdentity());
        try {
            setRestrictListeners(false);
            for (Object webModuleListener : webModuleListeners) {
                if (webModuleListener instanceof WebModuleListener) {
                    ((WebModuleListener) webModuleListener).moduleInitialized(getServletContext());
                } else {
                    logger.warn("Invalid WebModuleListener " + webModuleListener.getClass().getName());
                }
            }
            try {
                Assembler assembler = new Assembler();
                assembler.assemble(getServletContext(), webAppInfo);
                webSecurityConstraintStore.setAnnotationScanRequired(true);
                ((GeronimoWebAppContext.Context) _scontext).webXmlProcessed = true;
                for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry: integrationContext.getServletContainerInitializerMap().entrySet()) {
                     entry.getKey().onStartup(entry.getValue(), getServletContext());
                }
                super.doStart();
                if (!isAvailable()) {
                    Throwable e = getUnavailableException();
                    if (e instanceof Exception) {
                        throw (Exception)e;
                    }
                    if (e instanceof Throwable) {
                        throw new Exception("Could not start web app", e);
                    }
                    throw new Exception("Could not start web app for unknown reason");
                }
                if (applicationPolicyConfigurationManager != null) {
                    SpecSecurityBuilder specSecurityBuilder = new SpecSecurityBuilder(webSecurityConstraintStore.exportMergedWebAppInfo());
                    Map<String, ComponentPermissions> contextIdPermissionsMap = new HashMap<String, ComponentPermissions>();
                    contextIdPermissionsMap.put(policyContextId, specSecurityBuilder.buildSpecSecurityConfig());
                    //Update ApplicationPolicyConfigurationManager
                    try {
                        applicationPolicyConfigurationManager.updateApplicationPolicyConfiguration(contextIdPermissionsMap);
                    } catch (LoginException e) {
                        throw new RuntimeException("Fail to set application policy configurations", e);
                    } catch (PolicyContextException e) {
                        throw new RuntimeException("Fail to set application policy configurations", e);
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException("Fail to set application policy configurations", e);
                    } finally {
                        //Clear SpecSecurityBuilder
                        specSecurityBuilder.clear();
                    }
                }
                fullyStarted = true;
            } finally {
                setRestrictListeners(true);
                integrationContext.restoreConnectorContext(connectorContext, null, newContext);
            }
        } finally {
            integrationContext.restoreContext(context);
            integrationContext.completeTx(txActive, null);
            WebApplicationName.setName(oldApplicationName);
        }
    }

    @Override
    protected void doStop() throws Exception {
        javax.naming.Context context = integrationContext.setContext();
        boolean txActive = integrationContext.isTxActive();
        SharedConnectorInstanceContext newContext = integrationContext.newConnectorInstanceContext(null);
        ConnectorInstanceContext connectorContext = integrationContext.setConnectorInstance(null, newContext);
        String oldApplicationName = WebApplicationName.getName();
        WebApplicationName.setName(integrationContext.getWebApplicationIdentity());
        try {
            try {
                super.doStop();
            } finally {
                integrationContext.restoreConnectorContext(connectorContext, null, newContext);
            }
            for (Object webModuleListener : webModuleListeners) {
                if (webModuleListener instanceof WebModuleListener) {
                    ((WebModuleListener) webModuleListener).moduleDestoryed(getServletContext());
                } else {
                    logger.warn("Invalid WebModuleListener " + webModuleListener.getClass().getName());
                }
            }
        } finally {
            integrationContext.restoreContext(context);
            integrationContext.completeTx(txActive, null);
            WebApplicationName.setName(oldApplicationName);
        }
    }

    @Override
    public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        javax.naming.Context context = integrationContext.setContext();
        boolean txActive = integrationContext.isTxActive();
        SharedConnectorInstanceContext newContext = integrationContext.newConnectorInstanceContext(baseRequest);
        ConnectorInstanceContext connectorContext = integrationContext.setConnectorInstance(baseRequest, newContext);
        String oldApplicationName = WebApplicationName.getName();
        WebApplicationName.setName(integrationContext.getWebApplicationIdentity());
        try {
            try {
                super.doScope(target, baseRequest, request, response);
            } finally {
                integrationContext.restoreConnectorContext(connectorContext, baseRequest, newContext);
            }
        } finally {
            integrationContext.restoreContext(context);
            integrationContext.completeTx(txActive, baseRequest);
            WebApplicationName.setName(oldApplicationName);
        }
    }

    @Override
    protected boolean isProtectedTarget(String target) {
        while (target.startsWith("//")) {
            target=URIUtil.compactPath(target);
        }

        return StringUtil.startsWithIgnoreCase(target, "/web-inf") ||
               StringUtil.startsWithIgnoreCase(target, "/meta-inf") ||
               StringUtil.startsWithIgnoreCase(target, "/osgi-inf") ||
               StringUtil.startsWithIgnoreCase(target, "/osgi-opt");
    }

    @Override
    public Resource newResource(String url) throws IOException {
        if (url == null) {
            return null;
        }
        return newResource(new URL(url));
    }

    @Override
    public Resource newResource(URL url) throws IOException {
        if (url == null) {
            return null;
        }
        String protocol = url.getProtocol();
        if ("bundle".equals(protocol) ||
            "bundleentry".equals(protocol)) {
            return lookupResource(url.getPath());
        } else {
            return super.newResource(url);
        }
    }

    @Override
    public Resource getResource(String uriInContext) throws MalformedURLException {
        if (uriInContext == null || !uriInContext.startsWith("/")) {
            throw new MalformedURLException("Path must not be null and must start with '/': " + uriInContext);
        }
        if (modulePath != null) {
            uriInContext = modulePath + uriInContext;
        }
        return lookupResource(uriInContext);
    }

    @Override
    public Set<String> getResourcePaths(String uriInContext) {
        if (uriInContext == null || !uriInContext.startsWith("/")) {
            return Collections.emptySet();
        }
        if (modulePath != null) {
            uriInContext = modulePath + uriInContext;
        }
        HashSet<String> paths = new HashSet<String>();
        Bundle bundle = integrationContext.getBundle();
        Enumeration<String> e = bundle.getEntryPaths(uriInContext);
        if (e != null) {
            while (e.hasMoreElements()) {
                paths.add("/" + e.nextElement());
            }
        }
        return paths;
    }

    @Override
    protected ServletRegistration.Dynamic dynamicHolderAdded(ServletHolder holder) {
        ServletRegistration.Dynamic registration = holder.getRegistration();
        String servletClassName = holder.getClassName();
        Servlet servlet = holder.getServletInstance();
        if (servlet == null || webSecurityConstraintStore.isContainerCreatedDynamicServlet(servlet)) {
            webSecurityConstraintStore.addContainerCreatedDynamicServletEntry(registration, servletClassName);
        }
        return registration;
    }

    public Set<String> setServletSecurity(ServletRegistration.Dynamic registration, ServletSecurityElement servletSecurityElement) {
        return webSecurityConstraintStore.setDynamicServletSecurity(registration, servletSecurityElement);
    }

    @Override
    protected void addRoles(String... roles) {
        webSecurityConstraintStore.declareRoles(roles);
    }

    private Resource lookupResource(String uriInContext) {
        Bundle bundle = integrationContext.getBundle();
        URL url;
        try {
            url = BundleUtils.getEntry(bundle, uriInContext);
        } catch (MalformedURLException e) {
            logger.warn("MalformedURLException when getting entry:" + uriInContext + " from bundle " + bundle.getSymbolicName(), e);
            url = null;
        }
        if (url == null) {
            url = bundle.getResource("META-INF/resources" + uriInContext);
            if (url == null) {
                return null;
            }
        }
        if (uriInContext.endsWith("/")) {
            Enumeration<String> paths = BundleUtils.getEntryPaths(bundle, uriInContext);
            return new BundlePathResource(url, paths);
        } else {
            return new BundleFileResource(url);
        }
    }

    private static class BundleFileResource extends URLResource {

        protected BundleFileResource(URL url) {
            super(url, null);
        }

        /*
         * Always return true as we are pretty sure the resource does exist. This prevents
         * NPE as described at https://bugs.eclipse.org/bugs/show_bug.cgi?id=193269
         */
        @Override
        public boolean exists() {
            return true;
        }
    }

    public class Context extends WebAppContext.Context {

        protected boolean webXmlProcessed = false;

        @Override
        public <T extends Filter> T createFilter(Class<T> c) throws ServletException {
            try {
                return (T) integrationContext.getHolder().newInstance(c.getName(), classLoader, integrationContext.getComponentContext());
            } catch (IllegalAccessException e) {
                throw new ServletException("Could not create filter " + c.getName(), e);
            } catch (InstantiationException e) {
                throw new ServletException("Could not create filter " + c.getName(), e);
            }
        }

        @Override
        public <T extends EventListener> T createListener(Class<T> c) throws ServletException {
            try {
                return (T) integrationContext.getHolder().newInstance(c.getName(), classLoader, integrationContext.getComponentContext());
            } catch (IllegalAccessException e) {
                throw new ServletException("Could not create listener " + c.getName(), e);
            } catch (InstantiationException e) {
                throw new ServletException("Could not create listener " + c.getName(), e);
            }
        }

        @Override
        public <T extends Servlet> T createServlet(Class<T> c) throws ServletException {
            try {
                T servlet = (T) integrationContext.getHolder().newInstance(c.getName(), classLoader, integrationContext.getComponentContext());
                webSecurityConstraintStore.addContainerCreatedDynamicServlet(servlet);
                return servlet;
            } catch (IllegalAccessException e) {
                throw new ServletException("Could not create servlet " + c.getName(), e);
            } catch (InstantiationException e) {
                throw new ServletException("Could not create servlet " + c.getName(), e);
            }
        }

    }

}
TOP

Related Classes of org.apache.geronimo.jetty8.handler.GeronimoWebAppContext$BundleFileResource

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.