All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.osgihttp.Activator Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2009-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package org.glassfish.osgihttp;

import com.sun.enterprise.web.WebContainer;
import com.sun.enterprise.web.WebModule;
import com.sun.enterprise.web.WebModuleConfig;
import com.sun.enterprise.module.bootstrap.ModuleStartup;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.VirtualServer;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.Realm;
import org.apache.catalina.Container;
import org.apache.catalina.Manager;
import org.apache.catalina.session.StandardManager;
import org.apache.catalina.startup.ContextConfig;
import org.apache.catalina.core.StandardContext;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.event.*;
import org.glassfish.api.event.EventListener;
import org.glassfish.internal.api.Globals;
import org.glassfish.internal.api.ClassLoaderHierarchy;
import org.osgi.framework.*;
import org.osgi.service.http.HttpService;
import org.osgi.util.tracker.ServiceTracker;
import org.jvnet.hk2.component.Habitat;

import java.util.*;
import java.util.logging.Level;

/**
 * This is the entry point to our implementation of OSGi/HTTP service.
 * For every virtual server in the configuration, it creates HTTPService.
 * Every service has same context path. The context path can be defined
 * by user using configuration property org.glassfish.web.osgihttp.ContextPath.
 * If it is absent, we use a default value of "/osgi." After initializing
 * the HttpService factory with necessary details, we register the factory
 * OSGi service registry.
 *
 * @author [email protected]
 */
public class Activator implements BundleActivator {

    // TODO(Sahoo): Use config admin to configure context path, virtual server, etc.
    
    private BundleContext bctx;
    private Map vss = new HashMap();
    private String contextPath;
    private List registrations = new ArrayList();

    // configuration property used to select context root under which
    // this service is deployed.
    private static final String CONTEXT_PATH_PROP =
            Activator.class.getPackage().getName() + ".ContextPath";
    private ServiceTracker serverTracker;

    public void start(BundleContext context) throws Exception {
        bctx = context;
        serverTracker = new GlassFishServerTracker(bctx);
        serverTracker.open();
    }

    /**
     * This method is responsible for registering a HTTPService for every virtual server.
     * Each service is registered with a service property called "VirtualServer," which can be used by clients
     * to select a service. e.g., web console can use this to select __asadmin virtual server.
     * While registering the service for the default virtual server, it sets the service.ranking
     * to the maximum value so that any client just looking for an HTTPService gets to see the
     * HTTPService bound to default virtual server.
     * @param webContainer
     */
    private void doActualWork(WebContainer webContainer) {
        String defaultVsId = getDefaultVirtualServer();
        final StringTokenizer vsIds = new StringTokenizer(getAllVirtualServers(), ",");
        while (vsIds.hasMoreTokens()) {
            String vsId = vsIds.nextToken().trim();
            try {
                StandardContext standardContext = getStandardContext(webContainer, vsId);
                if (standardContext == null) continue;
                GlassFishHttpService httpService = new GlassFishHttpService(standardContext);
                Properties props = new Properties();
                props.put("VirtualServer", vsId);
                if (vsId.equals(defaultVsId)) {
                    props.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE);
                }
                ServiceRegistration registration = bctx.registerService(HttpService.class.getName(),
                        new HttpServiceWrapper.HttpServiceFactory(httpService),
                        props);
                registrations.add(registration);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private StandardContext getStandardContext(WebContainer webContainer, String vsId) throws Exception {
        Engine engine = webContainer.getEngine();
        Host vs = (Host) engine.findChild(vsId);
        if (vs == null) return null; // this can happen if some one deleted a virtual server after we read domain.xml
        vss.put(vsId, vs);
        contextPath = bctx.getProperty(CONTEXT_PATH_PROP);
        if (contextPath == null) {
            contextPath = "/osgi"; // default value
        }
        // create a new context under which all OSGi HTTP wrappers
        // will be registered.
        WebModule standardContext = new WebModule();
        standardContext.setWebContainer(webContainer);
        standardContext.setName(contextPath);
        standardContext.setPath(contextPath);
        // TODO(Sahoo): Need to set proper values for these directories
        standardContext.setDocBase(System.getProperty("java.io.tmpdir"));
        standardContext.setWorkDir(System.getProperty("java.io.tmpdir"));
        // standardContext.setJ2EEServer(System.getProperty("com.sun.aas.instanceName"));
        standardContext.setJ2EEServer(getInstanceName());
        standardContext.addLifecycleListener(new ContextConfig());
        Realm realm = Globals.getDefaultHabitat().getByContract(Realm.class);
        standardContext.setRealm(realm);
        WebModuleConfig wmConfig = new WebModuleConfig();
        wmConfig.setWorkDirBase(System.getProperty("java.io.tmpdir"));
        wmConfig.setVirtualServers(vsId);

        // Setting it in WebModuleConfig does not work, Ceck with Jan.
//        wmConfig.setAppClassLoader(getCommonClassLoader());
        standardContext.setParentClassLoader(getCommonClassLoader());
        standardContext.setWebModuleConfig(wmConfig);

        // Since there is issue about locating user classes that are part
        // of some OSGi bundle while deserializing, we switch off session
        // persistence.
        switchOffSessionPersistence(standardContext);
        vs.addChild(standardContext);
//        StandardContext standardContext =
//                StandardContext.class.cast(vs.findChild(contextPath));
        return standardContext;
    }

    private ClassLoader getCommonClassLoader()
    {
        ClassLoaderHierarchy clh =
                Globals.getDefaultHabitat().getComponent(ClassLoaderHierarchy.class);
        return clh.getAPIClassLoader();
    }

    public void stop(BundleContext context) throws Exception {
        if (serverTracker != null) serverTracker.close();
        for (ServiceRegistration registration : registrations) registration.unregister();
        for (Host vs : vss.values()) {
            StandardContext standardContext =
                    StandardContext.class.cast(vs.findChild(contextPath));
            for (Container child : standardContext.findChildren()) {
                standardContext.removeChild(child);
            }
            vs.removeChild(standardContext);
        }
        // TODO(Sahoo): Need to call stop on all wrappers if they are not
        // automatically stopped when removed from context.
    }

    private void switchOffSessionPersistence(StandardContext ctx) {
        // See Jan's blog about how to switch off
        // Session persistence:
        // http://blogs.sun.com/jluehe/entry/how_to_disable_persisting_of
        Manager mgr = ctx.getManager();
        if (mgr == null) {
            mgr = new StandardManager();
            StandardManager.class.cast(mgr).setPathname(null);
            ctx.setManager(mgr);
        } else {
            try {
                StandardManager.class.cast(mgr).setPathname(null);
            } catch (ClassCastException cce) {
                System.out.println(mgr +
                        " does not allow path name of session store to be configured.");
            }
        }
    }

    /**
     * Tracks Habitat and obtains EVents service from it and registers a listener
     * that takes care of doing the actual work.
     */
    private class GlassFishServerTracker extends ServiceTracker {
        public GlassFishServerTracker(BundleContext context)
        {
            super(context, Habitat.class.getName(), null);
        }

        @Override
        public Object addingService(ServiceReference reference)
        {
            ServiceReference habitatServiceRef = context.getServiceReference(Habitat.class.getName());
            final Habitat habitat = Habitat.class.cast(context.getService(habitatServiceRef));
            Events events = habitat.getComponent(Events.class);
            EventListener listener = new org.glassfish.api.event.EventListener() {
                public void event(Event event)
                {
                    if (EventTypes.SERVER_READY.equals(event.type())) {
                        WebContainer wc = habitat.getComponent(WebContainer.class);
                        doActualWork(wc);
                    }
                }
            };
            events.register(listener);
            // We can get into infinite waiting loop if server is already started. So check the status once.
            if (habitat.getComponent(ServerEnvironment.class).getStatus() == ServerEnvironment.Status.started) {
                WebContainer wc = habitat.getComponent(WebContainer.class);
                doActualWork(wc);
            }
            close(); // no need to track any more
            return super.addingService(reference);
        }
    }


    /**
     * @return comma-separated list of all defined virtual servers (including __asadmin)
     */
    private String getAllVirtualServers() {
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        Domain domain = Globals.get(Domain.class);
        String target = getInstanceName();
        Server server = domain.getServerNamed(target);
        if (server != null) {
            Config config = server.getConfig();
            if (config != null) {
                com.sun.enterprise.config.serverbeans.HttpService httpService = config.getHttpService();
                if (httpService != null) {
                    List hosts = httpService.getVirtualServer();
                    if (hosts != null) {
                        for (VirtualServer host : hosts) {
                            if (first) {
                                sb.append(host.getId());
                                first = false;
                            } else {
                                sb.append(",");
                                sb.append(host.getId());
                            }
                        }
                    }
                }
            }
        }
        return sb.toString();
    }

    private String getInstanceName() {
        ServerEnvironment se = Globals.get(ServerEnvironment.class);
        String target = se.getInstanceName();
        return target;
    }

    /**
     * @return the dafault virtual server
     */
    private String getDefaultVirtualServer() {
        com.sun.grizzly.config.dom.NetworkListener nl = Globals.get(com.sun.grizzly.config.dom.NetworkListener.class);
        return nl.findHttpProtocol().getHttp().getDefaultVirtualServer();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy