com.sun.enterprise.v3.server.LifecycleModuleService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-micro Show documentation
Show all versions of payara-micro Show documentation
Micro Distribution of the Payara Project
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 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 com.sun.enterprise.v3.server;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import org.glassfish.api.FutureProvider;
import org.glassfish.api.StartupRunLevel;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.event.EventListener;
import org.glassfish.api.event.EventTypes;
import org.glassfish.api.event.Events;
import org.glassfish.deployment.common.DeploymentException;
import org.glassfish.hk2.api.PostConstruct;
import org.glassfish.hk2.api.PreDestroy;
import org.glassfish.hk2.runlevel.RunLevel;
import org.glassfish.internal.api.ServerContext;
import org.jvnet.hk2.annotations.Service;
import com.sun.appserv.server.LifecycleListener;
import com.sun.appserv.server.ServerLifecycleException;
import com.sun.enterprise.config.serverbeans.Application;
import com.sun.enterprise.config.serverbeans.Applications;
import com.sun.enterprise.config.serverbeans.ConfigBeansUtilities;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.ServerTags;
import com.sun.enterprise.util.Result;
/**
* Support class to assist in firing LifecycleEvent notifications to
* registered LifecycleListeners.
*/
@Service
@RunLevel(StartupRunLevel.VAL)
public class LifecycleModuleService implements PreDestroy, PostConstruct, EventListener, FutureProvider>{
@Inject
ServerContext context;
@Inject
Applications apps;
@Inject
Events events;
@Inject @Named( ServerEnvironment.DEFAULT_INSTANCE_NAME)
Server server;
@Inject
private ConfigBeansUtilities configBeansUtilities;
/**
* The set of registered LifecycleListeners for event notifications.
*/
private ArrayList listeners = new ArrayList();
List>> futures = new ArrayList();
public void postConstruct() {
events.register(this);
try {
onInitialization();
} catch (Exception e) {
addExceptionToFuture(e);
}
}
public void preDestroy() {
try {
onTermination();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public List>> getFutures() {
return futures;
}
public void event(Event event) {
try {
if (event.is(EventTypes.SERVER_STARTUP)) {
onStartup();
} else if (event.is(EventTypes.SERVER_READY)) {
onReady();
} else if (event.is(EventTypes.PREPARE_SHUTDOWN)) {
onShutdown();
}
} catch (Exception e) {
throw new DeploymentException(e);
}
}
private void onInitialization() throws ServerLifecycleException {
List applications = apps.getApplications();
List lcms = new ArrayList();;
for (Application app : applications) {
if (Boolean.valueOf(app.getDeployProperties().getProperty
(ServerTags.IS_LIFECYCLE))) {
lcms.add(app);
}
}
HashSet listenerSet = new HashSet();
for (Application next : lcms) {
Properties props = next.getDeployProperties();
String enabled = next.getEnabled();
if ( isEnabled(next.getName(), enabled) ) {
String strOrder = (String)props.remove(
ServerTags.LOAD_ORDER);
int order = Integer.MAX_VALUE;
if (strOrder != null && strOrder.length() > 0) {
try {
order = Integer.parseInt(strOrder);
} catch(NumberFormatException nfe) {
nfe.printStackTrace();
}
}
String className = (String)props.remove(
ServerTags.CLASS_NAME);
ServerLifecycleModule slcm =
new ServerLifecycleModule(context,
next.getName(), className);
slcm.setLoadOrder(order);
String classpath = (String)props.remove(
ServerTags.CLASSPATH);
slcm.setClasspath(classpath);
String isFailureFatal = (String)props.remove(
ServerTags.IS_FAILURE_FATAL);
slcm.setIsFatal(Boolean.valueOf(isFailureFatal));
props.remove(ServerTags.IS_LIFECYCLE);
props.remove(ServerTags.OBJECT_TYPE);
for (String propName : props.stringPropertyNames()) {
slcm.setProperty(propName, props.getProperty(propName));
}
LifecycleListener listener = slcm.loadServerLifecycle();
listenerSet.add(slcm);
}
}
sortModules(listenerSet);
initialize();
}
/**
* Returns true if life cycle module is enabled in the application
* level and in the application ref level.
*
* @return true if life cycle module is enabled
*/
private boolean isEnabled(String name, String enabled) {
// true if enabled in both lifecyle module and in the ref
return (Boolean.valueOf(enabled) &&
Boolean.valueOf(configBeansUtilities.getEnabled(
server.getName(), name)));
}
private void resetClassLoader(final ClassLoader c) {
// set the common class loader as the thread context class loader
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
Thread.currentThread().setContextClassLoader(c);
return null;
}
}
);
}
private void sortModules(HashSet listenerSet) {
// FIXME: use a better sorting algo
for(Iterator iter = listenerSet.iterator(); iter.hasNext();) {
ServerLifecycleModule next = (ServerLifecycleModule) iter.next();
int order = next.getLoadOrder();
int i=0;
for(;i order) {
break;
}
}
this.listeners.add(i,next);
}
}
private void initialize()
throws ServerLifecycleException {
if (listeners.isEmpty())
return;
final ClassLoader cl = Thread.currentThread().getContextClassLoader();
for(Iterator iter = listeners.iterator(); iter.hasNext();) {
ServerLifecycleModule next = (ServerLifecycleModule) iter.next();
next.onInitialization();
}
// set it back
resetClassLoader(cl);
}
private void onStartup() throws ServerLifecycleException {
if (listeners.isEmpty())
return;
final ClassLoader cl = Thread.currentThread().getContextClassLoader();
for(Iterator iter = listeners.iterator(); iter.hasNext();) {
ServerLifecycleModule next = (ServerLifecycleModule) iter.next();
next.onStartup();
}
// set it back
resetClassLoader(cl);
}
private void onReady() throws ServerLifecycleException {
if (listeners.isEmpty())
return;
final ClassLoader cl = Thread.currentThread().getContextClassLoader();
for(Iterator iter = listeners.iterator(); iter.hasNext();) {
ServerLifecycleModule next = (ServerLifecycleModule) iter.next();
next.onReady();
}
// set it back
resetClassLoader(cl);
}
private void onShutdown() throws ServerLifecycleException {
if (listeners.isEmpty())
return;
final ClassLoader cl = Thread.currentThread().getContextClassLoader();
for(Iterator iter = listeners.iterator(); iter.hasNext();) {
ServerLifecycleModule next = (ServerLifecycleModule) iter.next();
next.onShutdown();
}
// set it back
resetClassLoader(cl);
}
private void onTermination() throws ServerLifecycleException {
if (listeners.isEmpty())
return;
ClassLoader cl = Thread.currentThread().getContextClassLoader();
for(Iterator iter = listeners.iterator(); iter.hasNext();) {
ServerLifecycleModule next = (ServerLifecycleModule) iter.next();
next.onTermination();
}
// set it back
resetClassLoader(cl);
}
private Future> addExceptionToFuture(Throwable t) {
Future> future = new LifecycleModuleFuture();
((LifecycleModuleFuture)future).setResult(new Result(t));
futures.add(future);
return future;
}
public static final class LifecycleModuleFuture implements Future> {
Result result;
CountDownLatch latch = new CountDownLatch(1);
public void setResult(Result result) {
this.result = result;
latch.countDown();
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return latch.getCount() == 0;
}
@Override
public Result get() throws InterruptedException {
latch.await();
return result;
}
@Override
public Result get(long timeout, TimeUnit unit) throws InterruptedException {
latch.await(timeout, unit);
return result;
}
}
}