Package org.apache.geronimo.wink.deployment

Source Code of org.apache.geronimo.wink.deployment.WinkModuleBuilderExtension

/**
* 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.wink.deployment;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarFile;

import javax.servlet.http.HttpServlet;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

import org.apache.geronimo.common.DeploymentException;
import org.apache.geronimo.deployment.ModuleIDBuilder;
import org.apache.geronimo.deployment.service.EnvironmentBuilder;
import org.apache.geronimo.gbean.AbstractName;
import org.apache.geronimo.gbean.annotation.GBean;
import org.apache.geronimo.gbean.annotation.ParamAttribute;
import org.apache.geronimo.gbean.annotation.ParamReference;
import org.apache.geronimo.j2ee.deployment.EARContext;
import org.apache.geronimo.j2ee.deployment.Module;
import org.apache.geronimo.j2ee.deployment.ModuleBuilderExtension;
import org.apache.geronimo.j2ee.deployment.NamingBuilder;
import org.apache.geronimo.j2ee.deployment.WebModule;
import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
import org.apache.geronimo.kernel.Naming;
import org.apache.geronimo.kernel.config.ConfigurationStore;
import org.apache.geronimo.kernel.repository.Environment;
import org.apache.geronimo.wink.GeronimoRestServlet;
import org.apache.geronimo.wink.GeronimoWinkDeloymentConfiguration;
import org.apache.openejb.jee.FacesConfig;
import org.apache.openejb.jee.FacesManagedBean;
import org.apache.openejb.jee.ParamValue;
import org.apache.openejb.jee.Servlet;
import org.apache.openejb.jee.ServletMapping;
import org.apache.openejb.jee.WebApp;
import org.apache.wink.server.internal.servlet.RestServlet;
import org.apache.xbean.finder.BundleAssignableClassFinder;
import org.apache.xbean.finder.ClassFinder;
import org.apache.xbean.osgi.bundle.util.BundleClassFinder;
import org.apache.xbean.osgi.bundle.util.ClassDiscoveryFilter;
import org.apache.xbean.osgi.bundle.util.DiscoveryRange;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.service.packageadmin.PackageAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @version $Rev $Date
*/

@GBean(j2eeType = NameFactory.MODULE_BUILDER)
public class WinkModuleBuilderExtension implements ModuleBuilderExtension {

    private static final Logger log = LoggerFactory.getLogger(WinkModuleBuilderExtension.class);
   
    private static final boolean JAX_RS_SUPPORT = Boolean.valueOf(System.getProperty("org.apache.geronimo.jaxrs.support", "true"));

    private final Environment defaultEnvironment;

    private final NamingBuilder namingBuilders;

    private static final String REST_APPLICATION_AS_SERVLET_NAME = Application.class.getName();

    private static final String REST_SERVLET_NAME = GeronimoRestServlet.class.getName();

    public static final EARContext.Key<Set<Class<? extends Application>>> JAXRS_APPLICATION_SUBCLASSES = new EARContext.Key<Set<Class<? extends Application>>>() {

        @Override
        public Set<Class<? extends Application>> get(Map<EARContext.Key, Object> context) {
            return (Set<Class<? extends Application>>) context.get(this);
        }
    };

    /*
     * public static final EARContext.Key<Set<Resource>> JSF_FACELET_CONFIG_RESOURCES = new
     * EARContext.Key<Set<ConfigurationResource>>() {
     *
     * @Override public Set<ConfigurationResource> get(Map<EARContext.Key, Object> context) { return
     * (Set<ConfigurationResource>) context.get(this); } };
     */

    public WinkModuleBuilderExtension(@ParamAttribute(name = "defaultEnvironment") Environment defaultEnvironment,
            @ParamReference(name = "NamingBuilders", namingType = NameFactory.MODULE_BUILDER) NamingBuilder namingBuilders) {
        this.defaultEnvironment = defaultEnvironment;
        this.namingBuilders = namingBuilders;
    }

    public void createModule(Module module, Bundle bundle, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
        if (!JAX_RS_SUPPORT) {
            return;
        }
        mergeEnvironment(module);
    }

    public void createModule(Module module, Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, Environment environment, Object moduleContextInfo, AbstractName earName, Naming naming,
            ModuleIDBuilder idBuilder) throws DeploymentException {
        if (!JAX_RS_SUPPORT) {
            return;
        }
        mergeEnvironment(module);
    }

    private void mergeEnvironment(Module module) {
        if (!(module instanceof WebModule)) {
            // not a web module, nothing to do
            return;
        }
        EnvironmentBuilder.mergeEnvironments(module.getEnvironment(), defaultEnvironment);
    }

    public void installModule(JarFile earFile, EARContext earContext, Module module, Collection configurationStores, ConfigurationStore targetConfigurationStore, Collection repository)
            throws DeploymentException {
        if (!(module instanceof WebModule) || !JAX_RS_SUPPORT) {
            return;
        }
    }

    @SuppressWarnings("unchecked")
    public void initContext(EARContext earContext, Module module, Bundle bundle) throws DeploymentException {
       
        if (!(module instanceof WebModule) || !JAX_RS_SUPPORT) {
            // not a web module, nothing to do
            return;
        }
        WebModule webModule = (WebModule) module;
        WebApp webApp = webModule.getSpecDD();
        ServiceReference reference = bundle.getBundleContext().getServiceReference(PackageAdmin.class.getName());
        Set<Class<? extends Application>> applicationClasses = new HashSet<Class<? extends Application>>();
        try {
            PackageAdmin packageAdmin = (PackageAdmin) bundle.getBundleContext().getService(reference);

            BundleClassFinder bundleClassFinder = new BundleAssignableClassFinder(packageAdmin, bundle, new Class<?>[] { Application.class }, new ClassDiscoveryFilter() {

                @Override
                public boolean directoryDiscoveryRequired(String directory) {
                    return true;
                }

                @Override
                public boolean jarFileDiscoveryRequired(String jarUrl) {
                    return true;
                }

                @Override
                public boolean packageDiscoveryRequired(String packageName) {
                    return true;
                }

                @Override
                public boolean rangeDiscoveryRequired(DiscoveryRange discoveryRange) {
                    return discoveryRange.equals(DiscoveryRange.BUNDLE_CLASSPATH);
                }
            });

            Set<String> classes = bundleClassFinder.find();

            for (String clazz : classes) {
                applicationClasses.add(bundle.loadClass(clazz).asSubclass(Application.class));
            }

        } catch (Exception e) {
            log.warn("Fail to scan javax.ws.rs.core.Application sub classes in application", e);
        } finally {
            bundle.getBundleContext().ungetService(reference);
        }

        // JAX-RS specific code here to initialize the runtime and setup the mapping etc.

        // there's no Application sub classes found
        if (applicationClasses == null || applicationClasses.size() == 0) {
            /*
             * TODO jaxrs 1.1 spec section 2.3.2 If no Application subclass is present the added servlet MUST be named ...
             */
            return;
        }

        /*
         *  jaxrs 1.1 spec section 2.3.2 If an Application subclass is present and there is already a servlet defined that has a servlet initialization
         * ...
         */
        Class<? extends Application> applicationClass;
        for (Servlet servlet : webApp.getServlet()) {
            List<ParamValue> params = servlet.getInitParam();
            for (ParamValue parm : params) {
                if (!parm.getParamName().trim().equals("javax.ws.rs.Application")) {
                    continue;
                }
                for (Class<? extends Application> clazz : applicationClasses) {
                    if (clazz.getName().equalsIgnoreCase(parm.getParamValue().trim())) {
                        applicationClass = clazz;
                        Class<?> servletClass = null;
                        try {
                            servletClass = bundle.loadClass(servlet.getServletClass());
                        } catch (ClassNotFoundException e) {
                            log.warn("failed to load servlet class:" + servlet.getServletClass());
                        }
                        if ((servletClass == null) || !servletClass.isAssignableFrom(HttpServlet.class)) {
                            servlet.setServletClass(REST_SERVLET_NAME);
                        }
                        ParamValue paramDeploymentConfig = new ParamValue();
                        paramDeploymentConfig.setParamName(RestServlet.DEPLOYMENT_CONF_PARAM);
                        paramDeploymentConfig.setParamValue(GeronimoWinkDeloymentConfiguration.class.getName());
                        servlet.getInitParam().add(paramDeploymentConfig);
                        return;
                    }
                }

            }
        }

        /*
         * jaxrs 1.1 spec section 2.3.2 If an Application subclass is present ...
         *
         *
         * TODO It is an error for more than one application to be deployed at the same effective servlet mapping
         */

        applicationClass = applicationClasses.iterator().next();

        Servlet restServletInfo = new Servlet();
        restServletInfo.setServletClass(REST_SERVLET_NAME);
        restServletInfo.setServletName(REST_SERVLET_NAME);

        ParamValue paramApplication = new ParamValue();
        paramApplication.setParamName("javax.ws.rs.Application");
        paramApplication.setParamValue(applicationClass.getName());
        restServletInfo.getInitParam().add(paramApplication);

        ParamValue paramDeploymentConfig = new ParamValue();
        paramDeploymentConfig.setParamName("deploymentConfiguration");
        paramDeploymentConfig.setParamValue(GeronimoWinkDeloymentConfiguration.class.getName());

        restServletInfo.getInitParam().add(paramDeploymentConfig);

        if (applicationClass.isAnnotationPresent(ApplicationPath.class)) {

            ApplicationPath ap = applicationClass.getAnnotation(ApplicationPath.class);

            String mapping = ap.value();

            if (!mapping.startsWith("/") || !mapping.startsWith("*.")) {

                mapping = "/" + mapping;
            }

            if (!mapping.endsWith("/*")) {

                if (mapping.endsWith("/"))
                    mapping = mapping + "*";
                else {
                    mapping = mapping + "/*";
                }
            }

            ServletMapping restServletMapping = new ServletMapping();
            restServletMapping.setServletName(REST_SERVLET_NAME);
            restServletMapping.getUrlPattern().add(mapping);
            webApp.getServletMapping().add(restServletMapping);

        }

        webApp.getServlet().add(restServletInfo);

    }

    public void addGBeans(EARContext earContext, Module module, Bundle bundle, Collection repository) throws DeploymentException {
        if (!JAX_RS_SUPPORT) {
            return;
        }
    }

    protected ClassFinder createWinkClassFinder(List<FacesConfig> facesConfigs, Set<Class<?>> annotatedJAXRSClasses, Bundle bundle) throws DeploymentException {
        List<Class<?>> managedBeanClasses = new ArrayList<Class<?>>();
        for (FacesConfig facesConfig : facesConfigs) {
            for (FacesManagedBean managedBean : facesConfig.getManagedBean()) {
                String className = managedBean.getManagedBeanClass().trim();
                Class<?> clas;
                try {
                    clas = bundle.loadClass(className);
                    while (clas != null) {
                        managedBeanClasses.add(clas);
                        clas = clas.getSuperclass();
                    }
                } catch (ClassNotFoundException e) {
                    log.warn("WinkModuleBuilderExtension: Could not load managed bean class: " + className);
                }
            }
        }
        if (annotatedJAXRSClasses != null) {
            for (Class<?> clas : annotatedJAXRSClasses) {
                while (clas != null) {
                    managedBeanClasses.add(clas);
                    clas = clas.getSuperclass();
                }
            }
        }
        return new ClassFinder(managedBeanClasses);
    }

    private boolean hasRestApplicationAsServlet(WebApp webApp) {
        for (Servlet servlet : webApp.getServlet()) {
            if (servlet.getServletClass() != null && REST_APPLICATION_AS_SERVLET_NAME.equals(servlet.getServletClass().trim())) {
                return true;
            }
        }
        return false;
    }   

}
TOP

Related Classes of org.apache.geronimo.wink.deployment.WinkModuleBuilderExtension

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.