package org.springframework.roo.process.manager; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.ReferencePolicy; import org.apache.felix.scr.annotations.ReferenceStrategy; import org.apache.felix.scr.annotations.Service; import org.springframework.roo.process.manager.event.ProcessManagerStatus; import org.springframework.roo.shell.ExecutionStrategy; import org.springframework.roo.shell.ParseResult; /** * Used to dispatch shell {@link ExecutionStrategy} requests through * {@link ProcessManager#execute(org.springframework.roo.process.manager.CommandCallback)} * . * * @author Ben Alex * @since 1.0 */ @Component @Service @Reference(name = "processManager", strategy = ReferenceStrategy.EVENT, policy = ReferencePolicy.DYNAMIC, referenceInterface = ProcessManager.class, cardinality = ReferenceCardinality.MANDATORY_UNARY) public class ProcessManagerHostedExecutionStrategy implements ExecutionStrategy { private final Class<?> mutex = ProcessManagerHostedExecutionStrategy.class; private ProcessManager processManager; protected void bindProcessManager(final ProcessManager processManager) { synchronized (mutex) { this.processManager = processManager; } } public Object execute(final ParseResult parseResult) throws RuntimeException { Validate.notNull(parseResult, "Parse result required"); synchronized (mutex) { Validate.isTrue(isReadyForCommands(), "ProcessManagerHostedExecutionStrategy not yet ready for commands"); return processManager.execute(new CommandCallback<Object>() { public Object callback() { try { return parseResult.getMethod().invoke(parseResult.getInstance(), parseResult.getArguments()); } catch (Exception e) { throw new RuntimeException(ObjectUtils.defaultIfNull(ExceptionUtils.getRootCause(e), e)); } } }); } } public boolean isReadyForCommands() { synchronized (mutex) { if (processManager != null) { // BUSY_EXECUTION needed in case of recursive commands, such as // if executing a script // TERMINATED added in case of additional commands following a // quit or exit in a script - ROO-2270 final ProcessManagerStatus processManagerStatus = processManager.getProcessManagerStatus(); return processManagerStatus == ProcessManagerStatus.AVAILABLE || processManagerStatus == ProcessManagerStatus.BUSY_EXECUTING || processManagerStatus == ProcessManagerStatus.TERMINATED; } } return false; } public void terminate() { synchronized (mutex) { if (processManager != null) { processManager.terminate(); } } } protected void unbindProcessManager(final ProcessManager processManager) { synchronized (mutex) { this.processManager = null; } } }