package org.opennaas.core.resources; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opennaas.core.resources.capability.ICapability; import org.opennaas.core.resources.capability.ICapabilityLifecycle; import org.opennaas.core.resources.descriptor.Information; import org.opennaas.core.resources.descriptor.ResourceDescriptor; import org.opennaas.core.resources.profile.IProfile; import org.opennaas.core.resources.profile.IProfiled; /** * Main resource class * * @author Mathieu Lemay * @author Isart Canyameres Giménez (i2cat) * */ public class Resource implements IResource, ILifecycle, IProfiled { /** The logger **/ Log logger = LogFactory.getLog(Resource.class); /** The resource identifier **/ private IResourceIdentifier resourceIdentifier = null; /** The resource current state **/ private State state = null; /** The resource descriptor **/ private ResourceDescriptor resourceDescriptor = null; /** The resource capabilities **/ private List<ICapabilityLifecycle> capabilities = null; /** The resource specific bootstapper class */ private IResourceBootstrapper bootstrapper = null; private IModel model; private IProfile profile = null; public Resource() { capabilities = new ArrayList<ICapabilityLifecycle>(); setState(State.INSTANTIATED); } @Override public State getState() { return state; } @Override public void setState(State state) { this.state = state; } @Override public IResourceIdentifier getResourceIdentifier() { return resourceIdentifier; } @Override public void initialize() throws IncorrectLifecycleStateException, ResourceException { if (!(getState().equals(State.INSTANTIATED) || getState().equals(State.SHUTDOWN))) throw new IncorrectLifecycleStateException("Unrecognized transition method (initialize) in state " + getState(), getState()); // for (int i = 0; i < capabilities.size(); i++) { // capabilities.get(i).initialize(); // } setState(State.INITIALIZED); } @Override public void activate() throws IncorrectLifecycleStateException, ResourceException, CorruptStateException { if (!getState().equals(State.INITIALIZED)) throw new IncorrectLifecycleStateException("Unrecognized transition method (activate) in state " + getState(), getState()); startCapabilities(capabilities.size() - 1, true); try { if (bootstrapper != null) { bootstrapper.bootstrap(this); } } catch (ResourceException e) { try { // roll back stopCapabilities(capabilities.size() - 1, false); } catch (ResourceException re) { throw new CorruptStateException("Failed to rollback activate", re); } catch (IncorrectLifecycleStateException ie) { throw new CorruptStateException("Failed to rollback activate", ie); } throw e; } setState(State.ACTIVE); } @Override public void deactivate() throws IncorrectLifecycleStateException, ResourceException, CorruptStateException { if (!getState().equals(State.ACTIVE)) throw new IncorrectLifecycleStateException("Unrecognized transition method (deactivate) in state " + getState(), getState()); if (bootstrapper != null) { bootstrapper.revertBootstrap(this); } try { stopCapabilities(capabilities.size() - 1, true); } catch (ResourceException e) { // cannot recover revertBootstrap markAsCorrupt("Failed to rollback deactivate.", e); } catch (IncorrectLifecycleStateException e) { // cannot recover revertBootstrap markAsCorrupt("Failed to rollback deactivate", e); } // setState(State.INACTIVE); setState(State.INITIALIZED); } public void forceDeactivate() throws ResourceException { String problemMessages = ""; try { if (bootstrapper != null) { bootstrapper.revertBootstrap(this); } } catch (ResourceException e) { problemMessages = e.getMessage() + '\n'; } for (ICapabilityLifecycle capability : capabilities) { try { capability.deactivate(); } catch (Exception e) { problemMessages = e.getMessage() + '\n' + problemMessages; } } if (!problemMessages.isEmpty()) throw new ResourceException(problemMessages); setState(State.INITIALIZED); } @Override public void shutdown() throws IncorrectLifecycleStateException, ResourceException { if (!getState().equals(State.INITIALIZED)) throw new IncorrectLifecycleStateException("Unrecognized transition method (shutdown) in state " + getState(), getState()); // for (int i = 0; i < capabilities.size(); i++) { // capabilities.get(i).shutdown(); // } setState(State.SHUTDOWN); } @Override public ResourceDescriptor getResourceDescriptor() { return resourceDescriptor; } // @Override public void setResourceDescriptor(ResourceDescriptor resourceDescriptor) { this.resourceDescriptor = resourceDescriptor; } // @Override public void setResourceIdentifier(IResourceIdentifier resourceIdentifier) { this.resourceIdentifier = resourceIdentifier; } // @Override public void addCapability(ICapability capability) { if (!(capability instanceof ICapabilityLifecycle)) throw new IllegalArgumentException("Given capability must be of type " + ICapabilityLifecycle.class.getName()); capabilities.add((ICapabilityLifecycle) capability); } @Override public ICapability getCapabilityByType(String type) throws ResourceException { for (ICapability capability : getCapabilities()) { if (capability.getCapabilityInformation().getType().equals(type)) { return capability; } } throw new ResourceException("Error getting capability " + type); } @Override public ICapability getCapability(Information information) { Iterator<? extends ICapability> capabilityIterator = getCapabilities().iterator(); while (capabilityIterator.hasNext()) { ICapability capability = capabilityIterator.next(); if (capability.getCapabilityInformation().equals(information)) { return capability; } } return null; } // @Override public ICapability removeCapability(Information information) { ICapability capability = getCapability(information); capabilities.remove(capability); return capability; } @Override public List<? extends ICapability> getCapabilities() { return capabilities; } @SuppressWarnings("unchecked") // @Override public void setCapabilities(List<? extends ICapability> capabilities) { for (ICapability capability : capabilities) { if (!(capability instanceof ICapabilityLifecycle)) throw new IllegalArgumentException("Given capability must be of type " + ICapabilityLifecycle.class.getName()); } this.capabilities = (List<ICapabilityLifecycle>) capabilities; } @Override public List<ICapability> getCapabilitiesByInterface(Class<? extends ICapability> interfaze) { List<ICapability> filteredCapabilities = new ArrayList<ICapability>(); for (ICapability capability : getCapabilities()) { if (interfaze.isInstance(capability)) { filteredCapabilities.add(capability); } } return filteredCapabilities; } @Override public ICapability getCapabilityByInterface(Class<? extends ICapability> interfaze) throws ResourceException { for (ICapability capability : getCapabilities()) { if (interfaze.isInstance(capability)) { return capability; } } throw new ResourceException("Cannot find capability with interface " + interfaze); } // @Override public void start() throws ResourceException, CorruptStateException { logger.info("Resource is in " + this.getState() + " state. Trying to start it"); try { // initialize(); activate(); } catch (IncorrectLifecycleStateException e) { throw new ResourceException(e); } } // @Override public void stop() throws ResourceException, CorruptStateException { logger.info("Resource is in " + this.getState() + " state. Trying to stop it"); try { deactivate(); // shutdown(); } catch (IncorrectLifecycleStateException e) { throw new ResourceException(e); } } /** * @return the bootstrapper */ // @Override public IResourceBootstrapper getBootstrapper() { return bootstrapper; } /** * @param bootstrapper * the bootstrapper to set */ // @Override public void setBootstrapper(IResourceBootstrapper bootstrapper) { this.bootstrapper = bootstrapper; } /** * @param model * the model to set */ // @Override public void setModel(IModel model) { this.model = model; } /** * @return the model */ @Override public IModel getModel() { return model; } @Override public boolean hasProfile() { return (profile != null); } @Override public IProfile getProfile() { return profile; } @Override public void setProfile(IProfile profile) { this.profile = profile; } /** * Tries to initialize and activate all capabilities in capabilities [0,lastCapabilityIndex]. If specified, on fail it performs a rollback * operation to leave capabilities in same state as they were * * @param lastCapabilityIndex * @param rollback * flag to activate rollback in case of failure * @throws ResourceException * @throws IncorrectLifecycleStateException * @throws CorruptStateException * if fails to start and fails to roll back, leaving resource in a corrupt state */ private void startCapabilities(int lastCapabilityIndex, boolean rollback) throws ResourceException, IncorrectLifecycleStateException, CorruptStateException { if (lastCapabilityIndex < 0) return; if (lastCapabilityIndex > capabilities.size()) lastCapabilityIndex = capabilities.size() - 1; for (int i = 0; i <= lastCapabilityIndex; i++) { try { capabilities.get(i).initialize(); capabilities.get(i).activate(); } catch (ResourceException e) { if (rollback) { try { if (capabilities.get(i).getState().equals(ICapabilityLifecycle.State.INITIALIZED)) { capabilities.get(i).shutdown(); } if (i > 0) // stop capabilities without roll back -> if so it may incur in an infinite loop! stopCapabilities(i - 1, false); } catch (ResourceException re) { markAsCorrupt("Failed to roll back startCapabilities.", re); } catch (IncorrectLifecycleStateException le) { markAsCorrupt("Failed to roll back startCapabilities.", le); } } throw e; } catch (IncorrectLifecycleStateException e) { if (rollback) { try { if (capabilities.get(i).getState().equals(ICapabilityLifecycle.State.INITIALIZED)) { capabilities.get(i).shutdown(); } if (i > 0) // stop capabilities without roll back -> if so it may incur in an infinite loop! stopCapabilities(i - 1, false); } catch (ResourceException re) { markAsCorrupt("Failed to roll back startCapabilities.", re); } catch (IncorrectLifecycleStateException le) { markAsCorrupt("Failed to roll back startCapabilities.", le); } } throw new ResourceException(e); } } } /** * Tries to deactivate and shutdown all capabilities in capabilities [0,lastCapabilityIndex]. If specified, on fail it performs a rollback * operation to leave capabilities in same state as they were * * @param lastCapabilityIndex * @param rollback * flag to activate rollback in case of failure * @throws ResourceException * @throws IncorrectLifecycleStateException * @throws CorruptStateException * if fails to start and fails to roll back, leaving resource in a corrupt state */ private void stopCapabilities(int lastCapabilityIndex, boolean rollback) throws ResourceException, IncorrectLifecycleStateException, CorruptStateException { if (lastCapabilityIndex < 0) return; if (lastCapabilityIndex > capabilities.size()) lastCapabilityIndex = capabilities.size() - 1; for (int i = 0; i <= lastCapabilityIndex; i++) { try { capabilities.get(i).deactivate(); capabilities.get(i).shutdown(); } catch (ResourceException e) { if (rollback) { try { if (capabilities.get(i).getState().equals(ICapabilityLifecycle.State.INITIALIZED)) { capabilities.get(i).activate(); } if (i > 0) // stop capabilities without roll back -> if so it may incur in an infinite loop! startCapabilities(i - 1, false); } catch (ResourceException re) { markAsCorrupt("Failed to roll back stopCapabilities.", re); } catch (IncorrectLifecycleStateException le) { markAsCorrupt("Failed to roll back stopCapabilities.", le); } } throw e; } catch (IncorrectLifecycleStateException e) { if (rollback) { try { if (capabilities.get(i).getState().equals(ICapabilityLifecycle.State.INITIALIZED)) { capabilities.get(i).activate(); } if (i > 0) // stop capabilities without roll back -> if so it may incur in an infinite loop! startCapabilities(i - 1, false); } catch (ResourceException re) { markAsCorrupt("Failed to roll back stopCapabilities.", re); } catch (IncorrectLifecycleStateException le) { markAsCorrupt("Failed to roll back stopCapabilities.", le); } } throw new ResourceException(e); } } } /** * @param errorMessage * @param cause * @throws CorruptStateException */ private void markAsCorrupt(String errorMessage, Throwable cause) throws CorruptStateException { setState(State.ERROR); throw new CorruptStateException(errorMessage + " Resource is in a corrupt state.", cause); } }