package org.opennaas.extensions.queuemanager;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.ws.rs.core.Response;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.opennaas.core.resources.ActivatorException;
import org.opennaas.core.resources.IResourceManager;
import org.opennaas.core.resources.Resource;
import org.opennaas.core.resources.ResourceException;
import org.opennaas.core.resources.ResourceNotFoundException;
import org.opennaas.core.resources.action.ActionException;
import org.opennaas.core.resources.action.ActionResponse;
import org.opennaas.core.resources.action.IAction;
import org.opennaas.core.resources.action.IActionSet;
import org.opennaas.core.resources.capability.AbstractCapability;
import org.opennaas.core.resources.capability.CapabilityException;
import org.opennaas.core.resources.capability.ICapability;
import org.opennaas.core.resources.descriptor.CapabilityDescriptor;
import org.opennaas.core.resources.descriptor.ResourceDescriptor;
import org.opennaas.core.resources.descriptor.ResourceDescriptorConstants;
import org.opennaas.core.resources.protocol.IProtocolManager;
import org.opennaas.core.resources.protocol.IProtocolSessionManager;
import org.opennaas.core.resources.protocol.ProtocolException;
import org.opennaas.core.resources.queue.ModifyParams;
import org.opennaas.core.resources.queue.QueueConstants;
import org.opennaas.core.resources.queue.QueueResponse;
public class QueueManager extends AbstractCapability implements
IQueueManagerCapability {
public final static String CAPABILITY_TYPE = "queue";
public final static String QUEUE = CAPABILITY_TYPE;
private final Log log = LogFactory.getLog(QueueManager.class);
private String resourceId = "";
private final Vector<IAction> queue = new Vector<IAction>();
/**
* Constructor to test the component
*
* @param queueDescriptor
*/
public QueueManager(CapabilityDescriptor queueDescriptor) {
super(queueDescriptor);
}
/**
* @param descriptor
* @param resourceId
*/
public QueueManager(CapabilityDescriptor descriptor, String resourceId) {
super(descriptor);
this.resourceId = resourceId;
log.debug("Built new Queue Capability");
}
/*
* (non-Javadoc)
*
* @see org.opennaas.core.resources.capability.ICapability#getCapabilityName()
*/
@Override
public String getCapabilityName() {
return CAPABILITY_TYPE;
}
/*
* @see org.opennaas.core.resources.capability.AbstractCapability#getActionSet()
*/
@Override
public IActionSet getActionSet() throws CapabilityException {
String name = this.descriptor
.getPropertyValue(ResourceDescriptorConstants.ACTION_NAME);
String protocol = this.descriptor
.getPropertyValue(ResourceDescriptorConstants.ACTION_PROTOCOL);
String version = this.descriptor
.getPropertyValue(ResourceDescriptorConstants.ACTION_VERSION);
try {
return Activator.getQueueActionSet(name, version, protocol);
} catch (ActivatorException e) {
throw new CapabilityException(e);
}
}
/*
* (non-Javadoc)
*
* @see org.opennaas.core.resources.capability.AbstractCapability#initialize()
*/
@Override
public void initialize() throws CapabilityException {
Dictionary<String, String> props = new Hashtable<String, String>();
props.put(ResourceDescriptorConstants.CAPABILITY, "queue");
props.put(ResourceDescriptorConstants.CAPABILITY_NAME, resourceId);
// registration = Activator.getContext().registerService(
// IQueueManagerCapability.class.getName(), this, props);
registerService(Activator.getContext(), CAPABILITY_TYPE, getResourceType(), getResourceName(),
IQueueManagerCapability.class.getName(), props);
super.initialize();
}
/*
* (non-Javadoc)
*
* @see org.opennaas.core.resources.capability.AbstractCapability#shutdown()
*/
@Override
public void shutdown() throws CapabilityException {
registration.unregister();
super.shutdown();
}
/*
* @see net.i2cat.mantychore.queuemanager.IQueueManagerCapability#clear()
*/
@Override
public void clear() {
log.info("Start of clear call");
log.debug("Clearing the queue...");
queue.clear();
log.info("End of clear call");
}
/*
* @see net.i2cat.mantychore.queuemanager.IQueueManagerCapability#getActions()
*/
@Override
public List<IAction> getActions() {
log.info("Start of getActions call");
log.debug("Get actions");
List<IAction> actions = new ArrayList<IAction>();
for (IAction action : queue) {
actions.add(action);
}
log.info("End of getActions call");
return actions;
}
/*
* (non-Javadoc)
*
* @see org.opennaas.extensions.queuemanager.IQueueManagerCapability#getActionsId()
*/
@Override
public Response getActionsId() {
List<String> ids = new ArrayList<String>();
List<IAction> actions = getActions();
for (IAction a : actions) {
ids.add(a.getActionID());
}
return Response.ok(ids.toString()).build();
}
/*
* @see net.i2cat.mantychore.queuemanager.IQueueManagerCapability#queueAction(org.opennaas.core.resources.action.IAction)
*/
@Override
public void queueAction(IAction action) {
log.info("Start of queueAction call");
log.debug("Queue new action");
queue.add(action);
log.info("End of queueAction call");
}
/**
* @param params
* to modify
* @return the response of modify the paramsor remove the action
* @throws CapabilityException
*/
@Override
public void modify(ModifyParams modifyParams) throws CapabilityException {
log.info("Start of modify call");
if (modifyParams.getQueueOper() == ModifyParams.Operations.REMOVE) {
remove(modifyParams.getPosAction());
} else {
throw new UnsupportedOperationException("Unsupported operation in modify: " + modifyParams.getQueueOper());
}
log.info("End of modify call");
}
/*
* @see net.i2cat.mantychore.queuemanager.IQueueManagerCapability#execute()
*/
@Override
public QueueResponse execute() throws CapabilityException {
log.info("Start of execute call");
// initialize queue response
long startTime = 0;
long stopTime = 0;
/* start time */
startTime = java.lang.System.currentTimeMillis();
QueueResponse queueResponse = QueueResponse.newQueueResponse(queue);
/* get protocol session manager */
IProtocolSessionManager protocolSessionManager = null;
try {
IProtocolManager protocolManager = Activator
.getProtocolManagerService();
protocolSessionManager = protocolManager
.getProtocolSessionManager(resourceId);
} catch (ProtocolException e) {
throw new CapabilityException(e);
} catch (ActivatorException e) {
throw new CapabilityException(e);
}
/* prepare action */
try {
log.debug("Preparing queue");
ActionResponse prepareResponse = prepare(protocolSessionManager);
queueResponse.setPrepareResponse(prepareResponse);
log.debug("Prepared!");
} catch (ActionException e1) {
throw new CapabilityException(e1);
}
boolean errorInPrepare = false;
if (queueResponse.getPrepareResponse().getStatus() == ActionResponse.STATUS.ERROR) {
errorInPrepare = true;
}
// note that restore should not be executed if there's been an error in
// prepare
if (!errorInPrepare) {
boolean errorHappened = false;
try {
/* execute queued actions */
queueResponse = executeQueuedActions(queueResponse,
protocolSessionManager);
/* Look for errors */
for (ActionResponse actionResponse : queueResponse.getResponses()) {
if (actionResponse.getStatus() == ActionResponse.STATUS.ERROR) {
errorHappened = true;
break;
}
}
if (!errorHappened) {
try {
/* commit action */
log.debug("Confirming actions");
ActionResponse confirmResponse = confirm(protocolSessionManager);
queueResponse.setConfirmResponse(confirmResponse);
log.debug("Confirmed!");
if (confirmResponse.getStatus() == ActionResponse.STATUS.ERROR)
errorHappened = true;
} catch (ActionException e) {
queueResponse.setConfirmResponse(ActionResponse.errorResponse(QueueConstants.CONFIRM, e.getLocalizedMessage()));
throw new CapabilityException(e);
}
}
} catch (Exception e) {
log.warn("Failed to execute queue", e);
// restore action
assert protocolSessionManager != null;
try {
log.debug("Restoring queue");
ActionResponse restoreResponse = restore(protocolSessionManager);
queueResponse.setRestoreResponse(restoreResponse);
log.debug("Restored!");
errorHappened = false;
} catch (ActionException ex) {
throw new CapabilityException(ex);
}
}
if (errorHappened) {
// restore action
assert protocolSessionManager != null;
try {
log.debug("Restoring queue");
ActionResponse restoreResponse = restore(protocolSessionManager);
queueResponse.setRestoreResponse(restoreResponse);
log.debug("Restored!");
} catch (ActionException e) {
throw new CapabilityException(e);
}
}
}
/* empty queue */
clear();
/* refresh operation */
if (resource instanceof Resource) {
try {
// FIXME WHAT CAN WE SO IF BOOTSTRAPPER IS NULL??
if (((Resource) resource).getBootstrapper() == null)
throw new ResourceException("Null Bootstrapper found. Could not reset model");
((Resource) resource).getBootstrapper().resetModel((Resource) resource);
sendRefresh();
} catch (ResourceException resourceExcept) {
log.warn("The resource couldn't reset its model...", resourceExcept);
}
try {
ActionResponse refreshResponse = executeRefreshActions(protocolSessionManager);
queueResponse.setRefreshResponse(refreshResponse);
} catch (ActionException e) {
throw new CapabilityException(e);
}
if (((Resource) resource).getProfile() != null) {
log.debug("Executing initModel from profile...");
((Resource) resource).getProfile().initModel(resource.getModel());
}
initVirtualResources();
}
/* stop time */
stopTime = java.lang.System.currentTimeMillis();
queueResponse.setTotalTime(stopTime - startTime);
clear();
log.info("End of execute call");
return queueResponse;
}
/**
* Refresh the actions of the queue
*
* @throws CapabilityException
*/
private void sendRefresh() throws CapabilityException {
for (ICapability capab : resource.getCapabilities()) {
// abstract capabilities have to be initialized
if (capab instanceof AbstractCapability) {
log.debug("Executing capabilities startup...");
try {
((AbstractCapability) capab).sendRefreshActions();
} catch (CapabilityException e) {
throw new CapabilityException(
"error in model refresh, when calling sendRefreshActions", e);
}
}
}
}
/**
* @throws CapabilityException
*/
private void initVirtualResources() throws CapabilityException {
String typeResource = resource.getResourceIdentifier().getType();
String parentId = resource.getResourceIdentifier().getId();
List<String> nameLogicalRouters = resource.getModel().getChildren();
IResourceManager manager;
try {
manager = Activator.getResourceManagerService();
} catch (ActivatorException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
throw new CapabilityException("Can't get ResourceManagerService!");
}
// initialize each resource
try {
for (String nameResource : nameLogicalRouters) {
try {
manager.getIdentifierFromResourceName(typeResource,
nameResource);
} catch (ResourceNotFoundException e) {
// TODO WHO IS RESPONSIBLE FOR CREATING A CHILD VIRTUAL RESOURCE?
log.error(e.getMessage());
log.info("Since this resource didn't exist, it has to be created.");
ResourceDescriptor newResourceDescriptor = newResourceDescriptor(
resource.getResourceDescriptor(), nameResource, parentId);
// create new resources
manager.createResource(newResourceDescriptor);
}
}
} catch (ResourceException e) {
throw new CapabilityException(e);
}
}
// FIXME this parameters shouldn't be in the queue because it is an opennaas module <br>
// Aux stuff from former Refresh as Karaf Command in OpenNaaS's Resources.
/**
* Create a new resource descriptor with the name = nameResource <br>
*
*
* @param resourceDescriptor
* @param nameResource
* @param parentId
* @return the resourceDescriptor
* @throws ResourceException
*/
private ResourceDescriptor newResourceDescriptor(
ResourceDescriptor resourceDescriptor, String nameResource, String parentId)
throws ResourceException {
try {
ResourceDescriptor newResourceDescriptor = (ResourceDescriptor) resourceDescriptor
.clone();
// the profiles will not be cloned
newResourceDescriptor.setProfileId("");
// Wet set the resource name
newResourceDescriptor.getInformation().setName(nameResource);
/* added virtual description */
Map<String, String> properties = new HashMap<String, String>();
properties.put(ResourceDescriptor.VIRTUAL, "true");
properties.put(ResourceDescriptor.HOSTED_BY, parentId);
newResourceDescriptor.setProperties(properties);
return newResourceDescriptor;
} catch (Exception e) {
throw new ResourceException(e.getMessage());
}
}
// end of Aux stuff from former Refresh as Karaf Command in OpenNaaS's
// Resources.
/**
* Executes actions in the queue.
*
* Queue execution stops at the first action to return error. Both an error ActionResponse an an ActionException are interpreted as an error.
*
* @param queueResponse
* to complete with actionResponses
* @param protocolSessionManager
* to use in actions execution
* @return given queueResponse with executed actions responses.
*/
private QueueResponse executeQueuedActions(QueueResponse queueResponse,
IProtocolSessionManager protocolSessionManager) {
int numAction = 0;
for (IAction action : queue) {
log.debug("Executing action: " + action.getActionID());
log.debug("Trying to print params:" + action.getParams());
ActionResponse actionResponse;
try {
actionResponse = action.execute(protocolSessionManager);
} catch (ActionException e) {
log.error("Error executing action " + action.getActionID(), e);
actionResponse = ActionResponse.errorResponse(action.getActionID(), e.getLocalizedMessage());
}
queueResponse.getResponses().set(numAction, actionResponse);
numAction++;
// If an action returned error, queue should stop executing actions.
// Restore mechanism should be activated in this case.
if (actionResponse.getStatus() == ActionResponse.STATUS.ERROR)
break;
}
return queueResponse;
}
/**
* Execute the actions of the queue
*
* @param protocolSessionManager
* @return the action response
* @throws ActionException
*/
private ActionResponse executeRefreshActions(IProtocolSessionManager protocolSessionManager) throws ActionException {
ActionResponse refreshResponse = ActionResponse.okResponse(QueueConstants.REFRESH);
for (IAction action : queue) {
/* use pool for get protocol session */
log.debug("getting protocol session...");
log.debug("Executing action: " + action.getActionID());
log.debug("Trying to print params:" + action.getParams());
ActionResponse actionResponse = action
.execute(protocolSessionManager);
// If an action returned error, queue should stop executing actions.
// Restore mechanism should be activated in this case.
if (actionResponse.getStatus() == ActionResponse.STATUS.ERROR) {
return actionResponse;
}
}
return refreshResponse;
}
/**
* Execute the confirm action of the queue
*
* @param protocolSessionManager
* @return the action response
* @throws ActionException
* @throws CapabilityException
*/
private ActionResponse confirm(
IProtocolSessionManager protocolSessionManager)
throws ActionException, CapabilityException {
IAction confirmAction = getActionSet().obtainAction(
QueueConstants.CONFIRM);
if (confirmAction == null) {
throw new CapabilityException("Error obtaining ConfirmAction");
}
ActionResponse restoreResponse = confirmAction
.execute(protocolSessionManager);
return restoreResponse;
}
/**
* Execute the prepare action of the queue
*
* @param protocolSessionManager
* @return the action response
* @throws ActionException
* @throws CapabilityException
*/
private ActionResponse prepare(
IProtocolSessionManager protocolSessionManager)
throws ActionException, CapabilityException {
IActionSet actionSet = getActionSet();
IAction prepareAction = actionSet.obtainAction(QueueConstants.PREPARE);
return prepareAction.execute(protocolSessionManager);
}
/**
* Execute the restore action of the queue
*
* @param protocolSessionManager
* @return the action response
* @throws ActionException
* @throws CapabilityException
*/
private ActionResponse restore(
IProtocolSessionManager protocolSessionManager)
throws ActionException, CapabilityException {
IAction restoreAction = getActionSet().obtainAction(
QueueConstants.RESTORE);
return restoreAction.execute(protocolSessionManager);
}
/**
* @param posAction
* position in the queue of the action to remove
* @return the response of remove the action
* @throws CapabilityException
* if invalid position is given
*/
private void remove(int posAction) throws CapabilityException {
try {
queue.remove(posAction);
log.debug("Removed action in pos: " + posAction);
} catch (ArrayIndexOutOfBoundsException e) {
throw new CapabilityException("Invalid index. Index " + posAction + " does not point to any action in the queue.");
}
}
}