blob: 58c2af675ec46abab63d36e961f6eba227e9c155 [file] [log] [blame]
/*
* Copyright (c) 2009, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.embeddable;
import org.glassfish.embeddable.spi.RuntimeBuilder;
import java.util.Iterator;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This is the entry point API to bootstrap GlassFish.
*
* <p/>A GlassFishRuntime represents just the runtime environment,
* i.e., no active services yet. e.g., there won't be any web container
* started just by creating a GlassFishRuntime object.
*
* <p/> The services will be activated when GlassFish instance is
* started by doing omething like:
*
* <pre>
* GlassFishRuntime runtime = GlassFishRuntime.bootstrap(); // no active services
* GlassFish glassfish = runtime.newGlassFish();
* glassfish.start(); // active services.
* </pre>
* @author Sanjeeb.Sahoo@Sun.COM
* @author bhavanishankar@dev.java.net
*/
public abstract class GlassFishRuntime {
private static final Logger logger = Logger.getLogger(GlassFishRuntime.class.getPackage().getName());
protected GlassFishRuntime() {
// Empty protected constructor so that it does not show up in the javadoc.
}
/**
* Bootstrap a GlassFishRuntime with default {@link BootstrapProperties}.
*
* @return Bootstrapped GlassFishRuntime
* @throws GlassFishException if the GlassFishRuntime is already bootstrapped.
*/
public static GlassFishRuntime bootstrap() throws GlassFishException {
return bootstrap(new BootstrapProperties(), GlassFishRuntime.class.getClassLoader());
}
/**
* Bootstrap GlassFish runtime based on runtime configuration passed in the bootstrapProperties object.
* This is a convenience method. Calling this method is same as
* calling {@link #bootstrap(BootstrapProperties , ClassLoader)} with null as second argument.
*
* @param bootstrapProperties BootstrapProperties used to setup the runtime
* @throws GlassFishException
*/
public static GlassFishRuntime bootstrap(BootstrapProperties bootstrapProperties) throws GlassFishException {
return bootstrap(bootstrapProperties, GlassFishRuntime.class.getClassLoader());
}
/**
* Bootstrap GlassFish runtime based on runtime configuration passed in the bootstrapProperties object.
* Calling this method twice will throw a GlassFishException
*
* @param bootstrapProperties BootstrapProperties used to setup the runtime
* @param cl ClassLoader used as parent loader by GlassFish modules. If null is passed, the class loader
* of this class is used.
* @return a bootstrapped runtime that can now be used to create new GlassFish instances
* @throws GlassFishException
*/
public static GlassFishRuntime bootstrap(BootstrapProperties bootstrapProperties, ClassLoader cl) throws GlassFishException {
return _bootstrap(bootstrapProperties, cl);
}
/**
* Shuts down the Runtime and dispose off all the GlassFish objects
* created via this Runtime
*
* @throws GlassFishException
*/
public abstract void shutdown() throws GlassFishException;
/**
* Create a new instance of GlassFish with default {@link org.glassfish.embeddable.GlassFishProperties}
*
* @return New GlassFish instance.
* @throws GlassFishException If at all fails to create a new GlassFish instance.
*/
public GlassFish newGlassFish() throws GlassFishException {
return newGlassFish(new GlassFishProperties());
}
/**
* Creates a new instance of GlassFish.
*
* @param glassfishProperties GlassFishProperties used to setup the GlassFish instance
* @return newly instantiated GlassFish object. It will be in {@link GlassFish.Status#INIT} state.
* @throws GlassFishException
*/
public abstract GlassFish newGlassFish(GlassFishProperties glassfishProperties) throws GlassFishException;
/*
* INTERNAL IMPLEMENTATION DETAILS
* Be careful while introducing dependencies in this class, as this is shipped as part of api jar used
* by users.
*/
/**
* Singleton
*/
private static GlassFishRuntime me;
private synchronized static GlassFishRuntime _bootstrap(BootstrapProperties bootstrapProperties, ClassLoader cl) throws GlassFishException {
if (me != null) {
throw new GlassFishException("Already bootstrapped", null);
}
RuntimeBuilder runtimeBuilder = getRuntimeBuilder(bootstrapProperties, cl != null ? cl : GlassFishRuntime.class.getClassLoader());
me = runtimeBuilder.build(bootstrapProperties);
return me;
}
protected synchronized static void shutdownInternal() throws GlassFishException {
if (me == null) {
throw new GlassFishException("Already shutdown", null);
}
me = null;
}
private static RuntimeBuilder getRuntimeBuilder(BootstrapProperties bootstrapProperties, ClassLoader cl) throws GlassFishException {
// StringBuilder sb = new StringBuilder("Launcher Class Loader = " + cl);
// if (cl instanceof URLClassLoader) {
// sb.append("has following Class Path: ");
// for (URL url : URLClassLoader.class.cast(cl).getURLs()) {
// sb.append(url).append(", ");
// }
// }
// System.out.println(sb);
Iterator<RuntimeBuilder> runtimeBuilders = ServiceLoader.load(RuntimeBuilder.class, cl).iterator();
while (runtimeBuilders.hasNext()) {
try {
RuntimeBuilder builder = runtimeBuilders.next();
logger.logp(Level.FINE, "GlassFishRuntime", "getRuntimeBuilder", "builder = {0}", new Object[]{builder});
if (builder.handles(bootstrapProperties)) {
return builder;
}
} catch (ServiceConfigurationError sce) {
// Ignore the exception and move ahead to the next builder.
logger.logp(Level.FINE, "GlassFishRuntime", "getRuntimeBuilder", "Ignoring", sce);
} catch (NoClassDefFoundError ncdfe) {
// On IBM JDK, we seem to be getting NoClassDefFoundError instead of ServiceConfigurationError
// when OSgiRuntimeBuilder is not able to be loaded in non-OSGi mode because of absence of
// OSGi classes in classpath. So, we need to catch it and ignore.
logger.logp(Level.FINE, "GlassFishRuntime", "getRuntimeBuilder", "Ignoring", ncdfe);
}
}
throw new GlassFishException("No runtime builder available for this configuration: " + bootstrapProperties.getProperties(), null);
}
}