/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.system.microcontainer;
import java.util.HashMap;
import java.util.Map;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanServer;
import org.jboss.dependency.spi.Controller;
import org.jboss.dependency.spi.ControllerState;
import org.jboss.dependency.spi.ControllerStateModel;
import org.jboss.system.ServiceController;
/**
* Holds the needed kernel bus lifecycle invocation info.
* Used by {@link ServiceControllerContext#lifecycleInvocation(String, Object[], String[])}
* to make invocations on the MBean lifecycle methods.
*
* @author <a href="mailto:ales.justin@jboss.org">Ales Justin</a>
*/
public class LifecycleInfo
{
private ServiceControllerContext context;
private Map<String, StateInfo> lifecycleOps;
/**
* @param context the ServiceControllerContext
* @throws Throwable for any error
*/
public LifecycleInfo(ServiceControllerContext context) throws Throwable
{
if (context == null)
throw new IllegalArgumentException("Null context");
this.context = context;
// build possible lifecycle ops
lifecycleOps = new HashMap<String, StateInfo>();
lifecycleOps.put("create", new StateInfo(false, true, ControllerState.CREATE));
lifecycleOps.put("start", new StateInfo(false, true, ControllerState.INSTALLED));
lifecycleOps.put("stop", new StateInfo(false, false, ControllerState.CREATE));
lifecycleOps.put("destroy", new StateInfo(false, false, ControllerState.CONFIGURED));
ServiceController controller = context.getServiceController();
MBeanServer server = controller.getMBeanServer();
if (server != null)
{
MBeanInfo info = server.getMBeanInfo(context.getObjectName());
MBeanOperationInfo[] ops = info.getOperations();
if (ops != null)
{
for (MBeanOperationInfo op : ops)
{
String name = op.getName();
StateInfo flag = lifecycleOps.get(name);
if (flag == null)
{
continue;
}
// Validate that is a no-arg void return type method
if (op.getReturnType().equals("void") == false)
{
continue;
}
if (op.getSignature().length != 0)
{
continue;
}
flag.opExists = true;
}
}
}
}
/**
* Is this invocation a lifecycle invocation.
*
* Return state value to which this context should be moved
* or return current state if we're already past the lifecycle state
* or null if the invocation is actually not a lifecycle invocation.
*
* @param opName operation name
* @param signature method's parameter types / signatures
* @return state to which we should move this context, or null if this is not lifecycle invocation
* @throws Throwable for any error
*/
public ControllerState lifecycleInvocation(String opName, String[] signature) throws Throwable
{
if (signature != null && signature.length > 0)
return null;
StateInfo flag = lifecycleOps.get(opName);
if (flag == null || flag.opExists == false)
return null;
Controller controller = context.getController();
ControllerStateModel model = controller.getStates();
ControllerState state = context.getState();
if (flag.installPhase)
{
if (model.isAfterState(flag.state, state))
return flag.state;
else
return state;
}
else
{
if (model.isBeforeState(flag.state, state))
return flag.state;
else
return state;
}
}
/**
* State info holder.
*/
private class StateInfo
{
boolean opExists;
boolean installPhase;
ControllerState state;
private StateInfo(boolean opExists, boolean installPhase, ControllerState state)
{
this.opExists = opExists;
this.installPhase = installPhase;
this.state = state;
}
}
}