package org.opennaas.core.resources.capability; import java.io.IOException; import java.util.ArrayList; import java.util.Dictionary; import java.util.Hashtable; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opennaas.core.resources.IResource; import org.opennaas.core.resources.ResourceException; import org.opennaas.core.resources.action.Action; import org.opennaas.core.resources.action.ActionException; import org.opennaas.core.resources.action.ActionSet; import org.opennaas.core.resources.action.IAction; import org.opennaas.core.resources.action.IActionSet; import org.opennaas.core.resources.configurationadmin.ConfigurationAdminUtil; import org.opennaas.core.resources.descriptor.CapabilityDescriptor; import org.opennaas.core.resources.descriptor.Information; import org.opennaas.core.resources.profile.IProfile; import org.opennaas.core.resources.profile.IProfiled; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; /** * This class provides an abstract implementation for the ICapabilityLifecycle and IQueueingCapability interface. * * This class must be extended by each capability using actions and a queue. It provides a default implementation of ICapabilityLifecycle methods. * Those methods may be overridden in children classes if needed. * * @author Mathieu Lemay (ITI) * @author Scott Campbell(CRC) * @author Eduard Grasa (i2CAT) * @author Carlos Baez (i2CAT) * @author Isart Canyameres (i2CAT) - Make it implement ICapabilityLifecycle and IQueueingCapability * */ public abstract class AbstractCapability implements ICapabilityLifecycle, IQueueingCapability { private static final String REFRESH = "refresh"; Log log = LogFactory.getLog(AbstractCapability.class); /** The descriptor for this capability **/ private State state = null; protected CapabilityDescriptor descriptor; protected String capabilityId = null; protected IResource resource = null; protected IActionSet actionSet = null; protected IProfile profile = null; protected ServiceRegistration registration; /* * (non-Javadoc) * * @see org.opennaas.core.resources.capability.IQueueingCapability#queueAction(org.opennaas.core.resources.action.IAction) */ @Override public abstract void queueAction(IAction action) throws CapabilityException; /* * (non-Javadoc) * * @see org.opennaas.core.resources.capability.IQueueingCapability#getActionSet() */ @Override public abstract IActionSet getActionSet() throws CapabilityException; public AbstractCapability(CapabilityDescriptor descriptor) { this.descriptor = descriptor; this.capabilityId = descriptor.getCapabilityInformation().getType(); setState(State.INSTANTIATED); } /** * @return the resource name through the resource descriptor */ public String getResourceName() { String resourceName = ""; if (resource.getResourceDescriptor() != null && resource.getResourceDescriptor().getInformation() != null) { resourceName = resource.getResourceDescriptor().getInformation().getName(); } return resourceName; } /** * @return the resource type through the resource descriptor */ public String getResourceType() { String resourceType = ""; if (resource.getResourceDescriptor() != null && resource.getResourceDescriptor().getInformation() != null) { resourceType = resource.getResourceDescriptor().getInformation().getType(); } return resourceType; } // IQueueingCapability methods /* * (non-Javadoc) * * @see org.opennaas.core.resources.capability.ICapability#getCapabilityDescriptor() */ @Override public CapabilityDescriptor getCapabilityDescriptor() { return descriptor; } /* * (non-Javadoc) * * @see org.opennaas.core.resources.capability.ICapability#setCapabilityDescriptor(org.opennaas.core.resources.descriptor.CapabilityDescriptor) */ @Override public void setCapabilityDescriptor(CapabilityDescriptor descriptor) { this.descriptor = descriptor; } /* * (non-Javadoc) * * @see org.opennaas.core.resources.capability.ICapability#getCapabilityInformation() */ @Override public Information getCapabilityInformation() { return descriptor.getCapabilityInformation(); } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder builder = new StringBuilder(); if (getCapabilityInformation() != null) { builder.append("\nCapability Type: " + getCapabilityInformation().getType()); builder.append("\nCapability Description: " + getCapabilityInformation().getDescription()); builder.append("\nCapability Version: " + getCapabilityInformation().getName()); } return builder.toString(); } /** * The resource where this capability belongs * * @param resource */ @Override public void setResource(IResource resource) { this.resource = resource; } // ICapabilityLifecycle methods /** * Returns the current capability state * * @return state enum object */ @Override public State getState() { return state; } /** * Sets the current capability state */ public void setState(State state) { this.state = state; } /** * Initializes this capability, the status will be INITIALIZED, then will be ACTIVE if enabled. * * @throws ResourceException */ @Override public void initialize() throws CapabilityException { setState(State.INITIALIZED); } /** * Activates this capability and change state to ACTIVE. * * @throws ResourceException */ @Override public void activate() throws CapabilityException { setState(State.ACTIVE); } /** * Deactivate this capability and change state to INACTIVE * * @throws ResourceException */ @Override public void deactivate() throws CapabilityException { setState(State.INACTIVE); } /** * Prepares capability for Garbage Collection state will be SHUTDOWN until it is collected. * * @throws ResourceException */ @Override public void shutdown() throws CapabilityException { setState(State.SHUTDOWN); } // IQueueingCapability methods /* * (non-Javadoc) * * @see org.opennaas.core.resources.capability.IQueueingCapability#sendRefreshActions() */ @Override public void sendRefreshActions() throws CapabilityException { sendRefreshActions(new ArrayList<Object>()); } // TODO use when queue is in opennaas.core // @Override // public void queueuAction(IAction action) throws CapabilityException { // getQueuemanager().queueAction(action); // } // // /** // * // * @return // * @throws CapabilityException // */ // protected abstract IQueueManagerCapability getQueueManager() throws CapabilityException; /* * (non-Javadoc) * * @see org.opennaas.core.resources.capability.IQueueingCapability#createAction(java.lang.String) */ @Override public IAction createAction(String actionId) throws CapabilityException { try { log.debug("Trying to use profile"); IAction action = loadActionFromProfile(actionId); if (action == null) { log.debug("Profile doesn't contain desired action for this capability. Loading action from ActionSet. Action id is: " + actionId); ActionSet actionSet = (ActionSet) getActionSet(); action = actionSet.obtainAction(actionId); } return action; } catch (ActionException e) { throw new CapabilityException(e); } } /** * Sends to the queue necessary actions that should be executed before this capability is operative. * * @param actionsParameters * A parameter will be taken from the list for each refreshActions. Fist action will get first parameter, second action the second... * null parameter will be passed if there are more actions than parameters. . * @return * @throws CapabilityException */ public void sendRefreshActions(List<Object> params) throws CapabilityException { List<String> refreshActions = getActionSet().getRefreshActionName(); IAction action; int numAction = 0; for (String refreshAction : refreshActions) { Object param = null; if (numAction < params.size()) { param = params.get(numAction); numAction++; } else { param = null; } action = createActionAndCheckParams(refreshAction, param); queueAction(action); } } /** * * @param actionId * @param actionParameters * @return created action with given parameters * @throws CapabilityException * if an error occurs creating the action or checking it's parameters. */ protected IAction createActionAndCheckParams(String actionId, Object actionParameters) throws CapabilityException { IAction action = createAction(actionId); action.setParams(actionParameters); action.setModelToUpdate(resource.getModel()); // FIXME define checkParams signature. Should it return exception if fails or return false??? // now both Exception and return false have same meaning. // returning exception is preferred, because reason can be specified in exception msg and displayed to the usr. boolean isOk = action.checkParams(action.getParams()); if (!isOk) { throw new CapabilityException("Invalid parameters for action " + actionId); } return action; } /** * Register the capability like a web service through DOSGi * * @param name * @param resourceId * @return * @throws CapabilityException */ protected ServiceRegistration registerService(BundleContext bundleContext, String capabilityName, String resourceType, String resourceName, String ifaceName) throws CapabilityException { Dictionary<String, String> props = new Hashtable<String, String>(); return registration = registerService(bundleContext, capabilityName, resourceType, resourceName, ifaceName, props); } /** * Register the capability like a web service through DOSGi * * @param name * @param resourceId * @return * @throws CapabilityException */ protected ServiceRegistration registerService(BundleContext bundleContext, String capabilityName, String resourceType, String resourceName, String ifaceName, Dictionary<String, String> props) throws CapabilityException { try { ConfigurationAdminUtil configurationAdmin = new ConfigurationAdminUtil(bundleContext); String url = configurationAdmin.getProperty("org.opennaas", "ws.rest.url"); if (props != null) { // Rest props.put("service.exported.interfaces", "*"); props.put("service.exported.configs", "org.apache.cxf.rs"); props.put("service.exported.intents", "HTTP"); props.put("org.apache.cxf.rs.httpservice.context", url + "/" + resourceType + "/" + resourceName + "/" + capabilityName); props.put("org.apache.cxf.rs.address", "/"); props.put("org.apache.cxf.httpservice.requirefilter", "true"); } log.info("Registering ws: \n " + "in url: " + props.get("org.apache.cxf.rs.address") + "\n" + "in context: " + props.get("org.apache.cxf.rs.httpservice.context")); registration = bundleContext.registerService(ifaceName, this, props); } catch (IOException e) { throw new CapabilityException(e); } return registration; } protected void unregisterService() { if (registration != null) registration.unregister(); } /** * * @return Action for this capability with given id stored in profile, or null if there is no such action in profile. * @throws ActionException * if there is a problem instantiating the action */ private Action loadActionFromProfile(String actionId) throws ActionException { Action action = null; if (resource instanceof IProfiled) { if (((IProfiled) resource).hasProfile()) { IProfile profile = ((IProfiled) resource).getProfile(); ActionSet actionSet = null; actionSet = (ActionSet) profile.getActionSetForCapability(capabilityId); if (actionSet != null) { // try to load the actionId from profile ActionSet action = actionSet.obtainAction(actionId); } } } return action; } }