From: Mathieu Baudier Date: Tue, 19 Apr 2011 17:04:02 +0000 (+0000) Subject: JCR UI can run processes X-Git-Tag: argeo-slc-2.1.7~976 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;ds=sidebyside;h=a181e3d059185a9dc108e81f38c66f48f4e4aac8;p=gpl%2Fargeo-slc.git JCR UI can run processes NEW - bug 17: Generalize agent management and registration beyond JMS https://bugzilla.argeo.org/show_bug.cgi?id=17 git-svn-id: https://svn.argeo.org/slc/trunk@4454 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/demo/slc_demo_rcp.properties b/demo/slc_demo_rcp.properties index 247b07ec6..f90dd780f 100644 --- a/demo/slc_demo_rcp.properties +++ b/demo/slc_demo_rcp.properties @@ -10,5 +10,5 @@ org.argeo.security.ui.initialPerspective=org.argeo.slc.client.ui.slcExecutionPer log4j.configuration=file:../../log4j.properties -argeo.node.repo.home=${system_property:osgi.instance.area}/noderepo -argeo.node.repo.dburl=jdbc:h2:${system_property:osgi.instance.area}/h2/noderepo_db +argeo.node.repo.home=data/noderepo +argeo.node.repo.dburl=jdbc:h2:data/h2/noderepo_db diff --git a/eclipse/plugins/org.argeo.slc.client.rcp/src/main/java/org/argeo/slc/client/rcp/SlcSecureWorkbenchAdvisor.java b/eclipse/plugins/org.argeo.slc.client.rcp/src/main/java/org/argeo/slc/client/rcp/SlcSecureWorkbenchAdvisor.java index 12057541b..a9802c536 100644 --- a/eclipse/plugins/org.argeo.slc.client.rcp/src/main/java/org/argeo/slc/client/rcp/SlcSecureWorkbenchAdvisor.java +++ b/eclipse/plugins/org.argeo.slc.client.rcp/src/main/java/org/argeo/slc/client/rcp/SlcSecureWorkbenchAdvisor.java @@ -39,9 +39,10 @@ public class SlcSecureWorkbenchAdvisor extends WorkbenchAdvisor { @Override public void initialize(IWorkbenchConfigurer configurer) { super.initialize(configurer); - // To remember the user's layout and window size for the next time he // starts the application // configurer.setSaveAndRestore(true); } + + } diff --git a/eclipse/plugins/org.argeo.slc.client.rcp/src/main/java/org/argeo/slc/client/rcp/SlcSecureWorkbenchWindowAdvisor.java b/eclipse/plugins/org.argeo.slc.client.rcp/src/main/java/org/argeo/slc/client/rcp/SlcSecureWorkbenchWindowAdvisor.java index a7d73ba84..1cfd3ddd1 100644 --- a/eclipse/plugins/org.argeo.slc.client.rcp/src/main/java/org/argeo/slc/client/rcp/SlcSecureWorkbenchWindowAdvisor.java +++ b/eclipse/plugins/org.argeo.slc.client.rcp/src/main/java/org/argeo/slc/client/rcp/SlcSecureWorkbenchWindowAdvisor.java @@ -2,8 +2,9 @@ package org.argeo.slc.client.rcp; import org.argeo.security.ui.rcp.SecureWorkbenchWindowAdvisor; import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.DropTargetAdapter; +import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; @@ -12,9 +13,8 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tray; import org.eclipse.swt.widgets.TrayItem; import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.application.ActionBarAdvisor; -import org.eclipse.ui.application.IActionBarConfigurer; import org.eclipse.ui.application.IWorkbenchWindowConfigurer; +import org.eclipse.ui.part.EditorInputTransfer; /** * Set here initial default size of the UI @@ -27,20 +27,54 @@ public class SlcSecureWorkbenchWindowAdvisor extends private TrayItem trayItem; - public SlcSecureWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer, String username) { + public SlcSecureWorkbenchWindowAdvisor( + IWorkbenchWindowConfigurer configurer, String username) { super(configurer, username); } -// public ActionBarAdvisor createActionBarAdvisor( -// IActionBarConfigurer configurer) { -// return new ApplicationActionBarAdvisor(configurer); -// } - + // public ActionBarAdvisor createActionBarAdvisor( + // IActionBarConfigurer configurer) { + // return new ApplicationActionBarAdvisor(configurer); + // } + + public void postWindowOpen() { initTray(); } + + + @Override + public void preWindowOpen() { + getWindowConfigurer().addEditorAreaTransfer(EditorInputTransfer.getInstance()); + getWindowConfigurer().configureEditorAreaDropListener(new DropTargetAdapter() { + + @Override + public void dragEnter(DropTargetEvent event) { + System.out.println("DROP enter!!! " + event); + } + + @Override + public void dragLeave(DropTargetEvent event) { + System.out.println("DROP leave!!! " + event); + } + + public void drop(DropTargetEvent event) { + System.out.println("DROP drop!!! " + event); + + } + + @Override + public void dropAccept(DropTargetEvent event) { + System.out.println("DROP accept!!! " + event); + super.dropAccept(event); + } + + }); + super.preWindowOpen(); + } + @Override public boolean preWindowShellClose() { // hide but do not dispose if tray is supported diff --git a/eclipse/plugins/org.argeo.slc.client.ui/META-INF/MANIFEST.MF b/eclipse/plugins/org.argeo.slc.client.ui/META-INF/MANIFEST.MF index 212722d7b..4b677086c 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/META-INF/MANIFEST.MF +++ b/eclipse/plugins/org.argeo.slc.client.ui/META-INF/MANIFEST.MF @@ -7,13 +7,15 @@ Bundle-Activator: org.argeo.slc.client.ui.ClientUiPlugin Require-Bundle: org.eclipse.ui;resolution:=optional, org.eclipse.core.runtime;resolution:=optional, org.eclipse.rap.ui;resolution:=optional, - org.eclipse.rap.ui.workbench;resolution:=optional + org.eclipse.rap.ui.workbench;resolution:=optional, + org.eclipse.ui.forms Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: J2SE-1.5 Export-Package: org.argeo.slc.client.ui, org.argeo.slc.client.ui.listeners, org.argeo.slc.client.ui.views Import-Package: javax.jcr;version="2.0.0", + javax.jcr.nodetype;version="2.0.0", javax.jcr.observation;version="2.0.0", org.apache.commons.io;version="1.4.0", org.apache.commons.logging;version="1.1.1", @@ -21,6 +23,7 @@ Import-Package: javax.jcr;version="2.0.0", org.argeo.eclipse.spring, org.argeo.eclipse.ui, org.argeo.eclipse.ui.jcr, + org.argeo.jcr, org.argeo.jcr.spring, org.argeo.slc, org.argeo.slc.build, @@ -37,6 +40,7 @@ Import-Package: javax.jcr;version="2.0.0", org.argeo.slc.deploy, org.argeo.slc.execution, org.argeo.slc.jcr, + org.argeo.slc.jcr.execution, org.argeo.slc.msg.test.tree, org.argeo.slc.process, org.argeo.slc.runtime, diff --git a/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/editors.xml b/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/editors.xml new file mode 100644 index 000000000..2ddbd7f10 --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/editors.xml @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/osgi.xml b/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/osgi.xml index 8b613485e..67caaabde 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/osgi.xml +++ b/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/osgi.xml @@ -11,6 +11,15 @@ Implements SLC specific RCP UIs. + + + + + + + @@ -18,9 +27,6 @@ interface="org.argeo.slc.core.test.tree.TreeTestResultListener" /> - - diff --git a/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/views.xml b/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/views.xml index ba6a8ec94..a4c7634e4 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/views.xml +++ b/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/views.xml @@ -5,45 +5,45 @@ http://www.springframework.org/schema/beans/spring-beans.xsd"> - - - - - - - diff --git a/eclipse/plugins/org.argeo.slc.client.ui/plugin.xml b/eclipse/plugins/org.argeo.slc.client.ui/plugin.xml index a32b21999..39cadc59f 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/plugin.xml +++ b/eclipse/plugins/org.argeo.slc.client.ui/plugin.xml @@ -214,4 +214,21 @@ name="SLC Execution"> + + + + + + + + diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/ClientUiPlugin.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/ClientUiPlugin.java index 8552b50be..c1043c435 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/ClientUiPlugin.java +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/ClientUiPlugin.java @@ -1,88 +1,35 @@ package org.argeo.slc.client.ui; import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.graphics.Image; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; -/** - * The activator class controls the plug-in life cycle - */ +/** The activator class controls the plug-in life cycle */ public class ClientUiPlugin extends AbstractUIPlugin { - - // The plug-in ID - public static final String PLUGIN_ID = "org.argeo.slc.client.ui"; - - // The shared instance + public static final String ID = "org.argeo.slc.client.ui"; private static ClientUiPlugin plugin; - private BundleContext bundleContext; - - /** - * The constructor - */ - public ClientUiPlugin() { - } - - /* - * (non-Javadoc) - * - * @see - * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext - * ) - */ public void start(BundleContext context) throws Exception { super.start(context); - this.bundleContext = context; plugin = this; } - /* - * (non-Javadoc) - * - * @see - * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext - * ) - */ public void stop(BundleContext context) throws Exception { plugin = null; super.stop(context); } - /** - * Returns the shared instance - * - * @return the shared instance - */ public static ClientUiPlugin getDefault() { return plugin; } - /** - * Returns an image descriptor for the image file at the given plug-in - * relative path - * - * @param path - * the path - * @return the image descriptor - */ - public static ImageDescriptor getImageDescriptor(String path) { - return imageDescriptorFromPlugin(PLUGIN_ID, path); - } - - @Override - protected void initializeImageRegistry(ImageRegistry reg) { - reg.put("agent", getImageDescriptor("icons/agent.gif")); - reg.put("executionModule", getImageDescriptor("icons/module.png")); - reg.put("folder", getImageDescriptor("icons/folder.gif")); - reg.put("flow", getImageDescriptor("icons/flow.png")); - reg.put("processes", getImageDescriptor("icons/processes.gif")); - reg.put("passedTest", getImageDescriptor("icons/passed.gif")); - reg.put("failedTest", getImageDescriptor("icons/error.gif")); + /** Creates the image */ + public static Image img(String path) { + return getImageDescriptor(path).createImage(); } - public BundleContext getBundleContext() { - return bundleContext; + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(ID, path); } - } diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/SlcExecutionPerspective.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/SlcExecutionPerspective.java index 81547347b..5374dd17f 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/SlcExecutionPerspective.java +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/SlcExecutionPerspective.java @@ -8,7 +8,7 @@ public class SlcExecutionPerspective implements IPerspectiveFactory { public void createInitialLayout(IPageLayout layout) { String editorArea = layout.getEditorArea(); - layout.setEditorAreaVisible(false); + layout.setEditorAreaVisible(true); layout.setFixed(false); // Create the main ui layout @@ -17,30 +17,28 @@ public class SlcExecutionPerspective implements IPerspectiveFactory { // current space and the part on bottom gets the rest. Likewise, for a // horizontal split, the part at left gets the specified ratio of the // current space. - IFolderLayout main = layout.createFolder("main", IPageLayout.RIGHT, - 0.3f, editorArea); +// IFolderLayout main = layout.createFolder("main", IPageLayout.RIGHT, +// 0.3f, editorArea); IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, 0.3f, editorArea); IFolderLayout bottom = layout.createFolder("bottom", - IPageLayout.BOTTOM, 0.65f, "main"); + IPageLayout.BOTTOM, 0.65f, editorArea); + bottom.addView("org.argeo.slc.client.ui.processListView"); - IFolderLayout topRight = layout.createFolder("topRight", - IPageLayout.RIGHT, 0.6f, "main"); +// IFolderLayout topRight = layout.createFolder("topRight", +// IPageLayout.RIGHT, 0.6f, "main"); // add the views to the corresponding place holder left.addView("org.argeo.slc.client.ui.jcrExecutionModulesView"); left.addView("org.argeo.slc.client.ui.resultListView"); - main.addView("org.argeo.slc.client.ui.processBuilderView"); - main.addPlaceholder("org.argeo.slc.client.ui.resultDetailView:UUID-*"); - // main.addView("org.argeo.slc.client.ui.resultExcelView"); - // main.addPlaceholder("org.argeo.slc.client.ui.resultExcelView:UUID-*"); - main.addPlaceholder("org.argeo.slc.client.ui.processDetailView:UUID-*"); +// main.addView("org.argeo.slc.client.ui.processBuilderView"); +// main.addPlaceholder("org.argeo.slc.client.ui.resultDetailView:UUID-*"); +// main.addPlaceholder("org.argeo.slc.client.ui.processDetailView:UUID-*"); - bottom.addView("org.argeo.slc.client.ui.processListView"); - topRight.addView("org.argeo.slc.client.ui.processParametersView"); +// topRight.addView("org.argeo.slc.client.ui.processParametersView"); } } diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/SlcImages.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/SlcImages.java new file mode 100644 index 000000000..1bc7ff512 --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/SlcImages.java @@ -0,0 +1,18 @@ +package org.argeo.slc.client.ui; + +import org.eclipse.swt.graphics.Image; +import static org.argeo.slc.client.ui.ClientUiPlugin.img; + +/** Shared images. */ +public class SlcImages { + public final static Image AGENT = img("icons/agent.gif"); + public final static Image MODULE = img("icons/module.png"); + public final static Image FOLDER = img("icons/folder.gif"); + public final static Image FLOW = img("icons/flow.png"); + public final static Image PROCESSES = img("icons/processes.gif"); + public final static Image PASSED = img("icons/passed.gif"); + public final static Image ERROR = img("icons/error.gif"); + public final static Image LAUNCH = img("icons/launch.gif"); + public final static Image REMOVE_ONE = img("icons/remove_one.gif"); + public final static Image REMOVE_ALL = img("icons/removeAll.png"); +} diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/commands/LaunchBatchHandler.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/commands/LaunchBatchHandler.java index e770c34b0..1263164c8 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/commands/LaunchBatchHandler.java +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/commands/LaunchBatchHandler.java @@ -7,13 +7,10 @@ import org.eclipse.core.commands.ExecutionException; import org.eclipse.ui.handlers.HandlerUtil; /** + * Launch the batch built in the ProcessBuilderView * - * @author bsinou - * - * Launch the batch built in the ProcessBuilderView - * - * NOTE : only one batch is supported with this command, if more than - * one batch is planned, this class must be updated with parameter. + * NOTE : only one batch is supported with this command, if more than one batch + * is planned, this class must be updated with parameter. */ public class LaunchBatchHandler extends AbstractHandler { // private final static Log log = diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/controllers/ProcessController.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/controllers/ProcessController.java index 311b64ac0..ccb54b5a0 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/controllers/ProcessController.java +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/controllers/ProcessController.java @@ -1,25 +1,85 @@ package org.argeo.slc.client.ui.controllers; +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.RepositoryException; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.jcr.SlcJcrConstants; +import org.argeo.slc.jcr.SlcJcrUtils; +import org.argeo.slc.jcr.SlcNames; +import org.argeo.slc.jcr.execution.JcrExecutionProcess; import org.argeo.slc.process.SlcExecution; import org.argeo.slc.runtime.SlcAgent; +import org.argeo.slc.runtime.SlcAgentFactory; import org.argeo.slc.services.SlcExecutionService; public class ProcessController { private final static Log log = LogFactory.getLog(ProcessController.class); private SlcExecutionService slcExecutionService; + private Map agentFactories = new HashMap(); public void execute(SlcAgent agent, SlcExecution slcExecution) { slcExecutionService.newExecution(slcExecution); - agent.runSlcExecution(slcExecution); + agent.process(slcExecution); if (log.isDebugEnabled()) log.debug("SlcExcution " + slcExecution.getUuid() + " launched on Agent " + agent.toString()); } + public void process(Node processNode) { + try { + // we currently only deal with single agents + Node flowNode = processNode.getNode(SlcNames.SLC_FLOW); + NodeIterator nit = flowNode.getNodes(); + if (nit.hasNext()) { + Node firstFlow = nit.nextNode(); + // we assume there is an nt:address + String firstFlowPath = firstFlow.getNode(SlcNames.SLC_ADDRESS) + .getProperty(Property.JCR_PATH).getString(); + String agentFactoryPath = SlcJcrUtils + .flowAgentFactoryPath(firstFlowPath); + if (!agentFactories.containsKey(agentFactoryPath)) + throw new SlcException("No agent factory registered under " + + agentFactoryPath); + SlcAgentFactory agentFactory = agentFactories + .get(agentFactoryPath); + String agentUuid = ((Node) processNode + .getAncestor(SlcJcrUtils.AGENT_FACTORY_DEPTH + 1)) + .getName(); + + // process + SlcAgent slcAgent = agentFactory.getAgent(agentUuid); + slcAgent.process(new JcrExecutionProcess(processNode)); + } + } catch (RepositoryException e) { + throw new SlcException("Cannot execute " + processNode, e); + } + } + public void setSlcExecutionService(SlcExecutionService slcExecutionService) { this.slcExecutionService = slcExecutionService; } + public synchronized void register(SlcAgentFactory agentFactory, + Map properties) { + String path = properties.get(SlcJcrConstants.PROPERTY_PATH); + if (log.isDebugEnabled()) + log.debug("Agent factory registered under " + path); + agentFactories.put(path, agentFactory); + } + + public synchronized void unregister(SlcAgentFactory agentFactory, + Map properties) { + String path = properties.get(SlcJcrConstants.PROPERTY_PATH); + if (log.isDebugEnabled()) + log.debug("Agent factory unregistered from " + path); + agentFactories.remove(path); + } } diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessBuilderPage.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessBuilderPage.java new file mode 100644 index 000000000..6a0e2652a --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessBuilderPage.java @@ -0,0 +1,395 @@ +package org.argeo.slc.client.ui.editors; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventIterator; +import javax.jcr.observation.EventListener; +import javax.jcr.observation.ObservationManager; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.slc.SlcException; +import org.argeo.slc.client.ui.SlcImages; +import org.argeo.slc.execution.ExecutionProcess; +import org.argeo.slc.jcr.SlcJcrUtils; +import org.argeo.slc.jcr.SlcNames; +import org.argeo.slc.jcr.SlcTypes; +import org.argeo.slc.process.RealizedFlow; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerDropAdapter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.dnd.TransferData; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.forms.AbstractFormPart; +import org.eclipse.ui.forms.IManagedForm; +import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ScrolledForm; + +public class ProcessBuilderPage extends FormPage implements SlcNames, SlcTypes { + public final static String ID = "processBuilderPage"; + private final static Log log = LogFactory.getLog(ProcessBuilderPage.class); + + private Node processNode; + + private TreeViewer flowsViewer; + private Label status; + + private AbstractFormPart formPart; + private StatusObserver statusObserver; + + public ProcessBuilderPage(ProcessEditor editor, Node processNode) { + super(editor, ID, "Definition"); + this.processNode = processNode; + + } + + @Override + protected void createFormContent(IManagedForm mf) { + try { + ScrolledForm form = mf.getForm(); + form.setText("Process " + processNode.getName()); + GridLayout mainLayout = new GridLayout(1, true); + form.getBody().setLayout(mainLayout); + + createControls(form.getBody()); + createBuilder(form.getBody()); + + // form + formPart = new AbstractFormPart() { + + }; + getManagedForm().addPart(formPart); + if (getProcessStatus().equals(ExecutionProcess.UNINITIALIZED)) + formPart.markDirty(); + + // observation + statusObserver = new StatusObserver(); + ObservationManager observationManager = processNode.getSession() + .getWorkspace().getObservationManager(); + observationManager.addEventListener(statusObserver, + Event.PROPERTY_CHANGED, processNode.getPath(), true, null, + null, false); + + } catch (RepositoryException e) { + throw new ArgeoException("Cannot create form content", e); + } + } + + protected void createControls(Composite parent) { + FormToolkit tk = getManagedForm().getToolkit(); + + Composite controls = tk.createComposite(parent); + controls.setLayout(new RowLayout()); + controls.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + + Button run = tk.createButton(controls, null, SWT.PUSH); + run.setToolTipText("Run"); + run.setImage(SlcImages.LAUNCH); + run.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + ((ProcessEditor) getEditor()).process(); + } + + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }); + + Button remove = tk.createButton(controls, null, SWT.PUSH); + remove.setImage(SlcImages.REMOVE_ONE); + remove.setToolTipText("Remove selected flows"); + remove.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + removeSelectedFlows(); + } + + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }); + + Button clear = tk.createButton(controls, null, SWT.PUSH); + clear.setImage(SlcImages.REMOVE_ALL); + clear.setToolTipText("Clear all flows"); + clear.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + removeAllFlows(); + } + + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }); + + status = tk.createLabel(controls, getProcessStatus()); + } + + protected String getProcessStatus() { + try { + return processNode.getProperty(SLC_STATUS).getString(); + } catch (RepositoryException e) { + throw new SlcException("Cannot retrieve status for " + processNode, + e); + } + } + + protected void createBuilder(Composite parent) { + FormToolkit tk = getManagedForm().getToolkit(); + SashForm sashForm = new SashForm(parent, SWT.HORIZONTAL); + sashForm.setSashWidth(4); + sashForm.setLayout(new FillLayout()); + sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + Composite top = tk.createComposite(sashForm); + GridLayout gl = new GridLayout(1, false); + top.setLayout(gl); + + flowsViewer = new TreeViewer(top); + flowsViewer.getTree().setLayoutData( + new GridData(SWT.FILL, SWT.FILL, true, true)); + flowsViewer.setLabelProvider(new ViewLabelProvider()); + flowsViewer.setContentProvider(new ViewContentProvider()); + flowsViewer.addSelectionChangedListener(new SelectionChangedListener()); + + int operations = DND.DROP_COPY | DND.DROP_MOVE; + Transfer[] tt = new Transfer[] { TextTransfer.getInstance() }; + flowsViewer.addDropSupport(operations, tt, new ViewDropListener( + flowsViewer)); + + flowsViewer.setInput(getEditorSite()); + flowsViewer.setInput(processNode); + + Composite bottom = tk.createComposite(sashForm); + bottom.setLayout(new GridLayout(1, false)); + sashForm.setWeights(getWeights()); + } + + protected int[] getWeights() { + return new int[] { 70, 30 }; + } + + /* + * CONTROLLERS + */ + protected void addFlow(String path) { + try { + Node flowNode = processNode.getNode(SLC_FLOW).addNode(SLC_FLOW); + flowNode.addMixin(SLC_REALIZED_FLOW); + Node address = flowNode.addNode(SLC_ADDRESS, NodeType.NT_ADDRESS); + address.setProperty(Property.JCR_PATH, path); + flowsViewer.refresh(); + formPart.markDirty(); + } catch (RepositoryException e) { + throw new SlcException("Cannot drop " + path, e); + } + } + + @SuppressWarnings("unchecked") + protected void removeSelectedFlows() { + if (!flowsViewer.getSelection().isEmpty()) { + Iterator it = ((StructuredSelection) flowsViewer + .getSelection()).iterator(); + while (it.hasNext()) { + Node node = (Node) it.next(); + try { + node.remove(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot remove " + node, e); + } + } + flowsViewer.refresh(); + formPart.markDirty(); + } + } + + protected void removeAllFlows() { + try { + for (NodeIterator nit = processNode.getNode(SLC_FLOW).getNodes(); nit + .hasNext();) { + nit.nextNode().remove(); + } + flowsViewer.refresh(); + formPart.markDirty(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot remove flows from " + processNode, + e); + } + } + + public void commit(Boolean onSave) { + formPart.commit(onSave); + } + + @Override + public void setFocus() { + flowsViewer.getTree().setFocus(); + } + + @Override + public void dispose() { + try { + if (statusObserver != null) { + processNode.getSession().getWorkspace().getObservationManager() + .removeEventListener(statusObserver); + } + } catch (Exception e) { + log.error("Cannot dispose observer for " + processNode + ": " + e); + } + super.dispose(); + } + + // Specific Providers for the current view. + protected class ViewContentProvider implements ITreeContentProvider { + public void inputChanged(Viewer arg0, Object arg1, Object arg2) { + } + + public void dispose() { + } + + public Object[] getElements(Object obj) { + if (!(obj instanceof Node)) + return new Object[0]; + + try { + Node node = (Node) obj; + List children = new ArrayList(); + for (NodeIterator nit = node.getNode(SLC_FLOW).getNodes(); nit + .hasNext();) + children.add(nit.nextNode()); + return children.toArray(); + } catch (RepositoryException e) { + throw new SlcException("Cannot list children of " + obj, e); + } + } + + public Object[] getChildren(Object parentElement) { + return null; + } + + public Object getParent(Object element) { + return null; + } + + public boolean hasChildren(Object element) { + return false; + } + + } + + protected class ViewLabelProvider extends ColumnLabelProvider { + + @Override + public String getText(Object element) { + Node node = (Node) element; + try { + if (node.isNodeType(SLC_REALIZED_FLOW)) { + if (node.hasNode(SLC_ADDRESS)) { + String path = node.getNode(SLC_ADDRESS) + .getProperty(Property.JCR_PATH).getString(); + return SlcJcrUtils.flowExecutionModuleName(path) + ":" + + SlcJcrUtils.flowRelativePath(path); + } + } + } catch (RepositoryException e) { + throw new SlcException("Cannot display " + element, e); + } + return super.getText(element); + } + + @Override + public Image getImage(Object element) { + Node node = (Node) element; + try { + if (node.isNodeType(SLC_REALIZED_FLOW)) { + return SlcImages.FLOW; + } + } catch (RepositoryException e) { + throw new SlcException("Cannot display " + element, e); + } + return super.getImage(element); + } + + } + + // Parameter view is updated each time a new line is selected + class SelectionChangedListener implements ISelectionChangedListener { + public void selectionChanged(SelectionChangedEvent evt) { + + IStructuredSelection curSelection = (IStructuredSelection) evt + .getSelection(); + Object obj = curSelection.getFirstElement(); + + if (obj instanceof RealizedFlow) { + // RealizedFlow rf = (RealizedFlow) obj; + // curSelectedRow = realizedFlows.indexOf(rf); + // refreshParameterview(); + // setFocus(); + } + } + } + + protected class ViewDropListener extends ViewerDropAdapter { + + public ViewDropListener(Viewer viewer) { + super(viewer); + } + + @Override + public boolean performDrop(Object data) { + String path = data.toString(); + addFlow(path); + return true; + } + + @Override + public boolean validateDrop(Object target, int operation, + TransferData transferType) { + return true; + } + } + + class StatusObserver implements EventListener { + + public void onEvent(EventIterator events) { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + status.setText(getProcessStatus()); + } + }); + // flowsViewer.refresh(); + } + + } +} diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditor.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditor.java new file mode 100644 index 000000000..92f1b194f --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditor.java @@ -0,0 +1,149 @@ +package org.argeo.slc.client.ui.editors; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.UUID; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; + +import org.argeo.jcr.JcrUtils; +import org.argeo.slc.SlcException; +import org.argeo.slc.client.ui.ClientUiPlugin; +import org.argeo.slc.client.ui.controllers.ProcessController; +import org.argeo.slc.execution.ExecutionProcess; +import org.argeo.slc.jcr.SlcJcrConstants; +import org.argeo.slc.jcr.SlcNames; +import org.argeo.slc.jcr.SlcTypes; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.forms.editor.FormEditor; + +public class ProcessEditor extends FormEditor implements SlcTypes, SlcNames { + public final static String ID = ClientUiPlugin.ID + ".processEditor"; + + private Session session; + private Node processNode; + private ProcessController processController; + + private ProcessBuilderPage builderPage; + private ProcessLogPage logPage; + + @Override + public void init(IEditorSite site, IEditorInput input) + throws PartInitException { + super.init(site, input); + ProcessEditorInput pei = (ProcessEditorInput) input; + String processPath = pei.getProcessPath(); + try { + if (processPath != null) { + if (!session.itemExists(processPath)) + throw new SlcException("Process " + processPath + + " does not exist"); + processNode = session.getNode(processPath); + } else {// new + processNode = newProcessNode(pei); + } + setPartName(processNode.getName()); + } catch (RepositoryException e) { + throw new SlcException("Cannot initialize editor for " + pei, e); + } + + } + + protected Node newProcessNode(ProcessEditorInput pei) + throws RepositoryException { + Calendar now = new GregorianCalendar(); + String uuid = UUID.randomUUID().toString(); + String processPath = SlcJcrConstants.PROCESSES_BASE_PATH + '/' + + JcrUtils.dateAsPath(now, true) + uuid; + Node processNode = JcrUtils.mkdirs(session, processPath, SLC_PROCESS); + processNode.setProperty(SLC_UUID, uuid); + processNode.setProperty(SLC_STATUS, ExecutionProcess.UNINITIALIZED); + Node processFlow = processNode.addNode(SLC_FLOW); + processFlow.addMixin(SLC_REALIZED_FLOW); + + // add initial flows + for (String path : pei.getInitialFlowPaths()) { + Node realizedFlow = processFlow.addNode(SLC_FLOW); + realizedFlow.addMixin(SLC_REALIZED_FLOW); + Node address = realizedFlow.addNode(SLC_ADDRESS, + NodeType.NT_ADDRESS); + address.setProperty(Property.JCR_PATH, path); + } + return processNode; + } + + @Override + public void dispose() { + JcrUtils.logoutQuietly(session); + } + + /** Actually runs the process. */ + public void process() { + // the modifications have to be saved before execution + try { + processNode.setProperty(SLC_STATUS, ExecutionProcess.SCHEDULED); + } catch (RepositoryException e) { + throw new SlcException("Cannot update status of " + processNode, e); + } + doSave(null); + processController.process(processNode); + } + + @Override + protected void addPages() { + try { + builderPage = new ProcessBuilderPage(this, processNode); + addPage(builderPage); + firePropertyChange(PROP_DIRTY); + logPage = new ProcessLogPage(this); + addPage(logPage); + } catch (PartInitException e) { + throw new SlcException("Cannot add pages", e); + } + + } + + @Override + public void doSave(IProgressMonitor monitor) { + try { + String status = processNode.getProperty(SLC_STATUS).getString(); + if (status.equals(ExecutionProcess.UNINITIALIZED)) + processNode.setProperty(SLC_STATUS, + ExecutionProcess.INITIALIZED); + session.save(); + builderPage.commit(true); + firePropertyChange(PROP_DIRTY); + } catch (RepositoryException e) { + throw new SlcException("Cannot save " + processNode, e); + } finally { + JcrUtils.discardQuietly(session); + } + } + + @Override + public void doSaveAs() { + } + + @Override + public boolean isSaveAsAllowed() { + return false; + } + + /** Expects one session per editor. */ + public void setSession(Session session) { + this.session = session; + } + + public void setProcessController(ProcessController processController) { + this.processController = processController; + } + +} diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditorInput.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditorInput.java new file mode 100644 index 000000000..9a94566da --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditorInput.java @@ -0,0 +1,77 @@ +package org.argeo.slc.client.ui.editors; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IPersistableElement; + +public class ProcessEditorInput implements IEditorInput, IPersistableElement { + private String processPath; + private List initialFlowPaths = new ArrayList(); + private Boolean launchImmediately = false; + + /** New empty process */ + public ProcessEditorInput() { + } + + /** New process with some flows */ + public ProcessEditorInput(List initialFlowPaths, + Boolean launchImmediately) { + this.initialFlowPaths = initialFlowPaths; + this.launchImmediately = launchImmediately; + } + + /** Existing process */ + public ProcessEditorInput(String processPath) { + this.processPath = processPath; + } + + @SuppressWarnings("rawtypes") + public Object getAdapter(Class arg0) { + return null; + } + + public boolean exists() { + return processPath != null; + } + + public ImageDescriptor getImageDescriptor() { + return null; + } + + public String getName() { + return processPath != null ? processPath : ""; + } + + public IPersistableElement getPersistable() { + return this; + } + + public String getToolTipText() { + return ""; + } + + public void saveState(IMemento memento) { + memento.putString("processPath", processPath); + } + + public String getFactoryId() { + return ProcessEditorInputFactory.ID; + } + + public String getProcessPath() { + return processPath; + } + + public List getInitialFlowPaths() { + return initialFlowPaths; + } + + public Boolean getLaunchImmediately() { + return launchImmediately; + } + +} diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditorInputFactory.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditorInputFactory.java new file mode 100644 index 000000000..b5a5d7081 --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditorInputFactory.java @@ -0,0 +1,17 @@ +package org.argeo.slc.client.ui.editors; + +import org.argeo.slc.client.ui.ClientUiPlugin; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.ui.IElementFactory; +import org.eclipse.ui.IMemento; + +public class ProcessEditorInputFactory implements IElementFactory { + public final static String ID = ClientUiPlugin.ID + + ".processEditorInputFactory"; + + public IAdaptable createElement(IMemento memento) { + String path = memento.getString("processPath"); + return new ProcessEditorInput(path); + } + +} diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessLogPage.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessLogPage.java new file mode 100644 index 000000000..f50b5b99f --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessLogPage.java @@ -0,0 +1,13 @@ +package org.argeo.slc.client.ui.editors; + +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.FormPage; + +public class ProcessLogPage extends FormPage { + public final static String ID = "processLogrPage"; + + public ProcessLogPage(FormEditor editor) { + super(editor, ID, "Log"); + } + +} diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/ExecutionModulesView.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/ExecutionModulesView.java index 96eca15d3..ae28c63f2 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/ExecutionModulesView.java +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/ExecutionModulesView.java @@ -12,7 +12,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; import org.argeo.slc.client.oxm.OxmInterface; -import org.argeo.slc.client.ui.ClientUiPlugin; +import org.argeo.slc.client.ui.SlcImages; import org.argeo.slc.client.ui.controllers.ProcessController; import org.argeo.slc.client.ui.providers.ExecutionModulesContentProvider; import org.argeo.slc.client.ui.providers.ExecutionModulesContentProvider.FlowNode; @@ -95,17 +95,13 @@ public class ExecutionModulesView extends ViewPart { public Image getImage(Object obj) { if (obj instanceof ExecutionModulesContentProvider.AgentNode) - return ClientUiPlugin.getDefault().getImageRegistry() - .get("agent"); + return SlcImages.AGENT; else if (obj instanceof ExecutionModulesContentProvider.ExecutionModuleNode) - return ClientUiPlugin.getDefault().getImageRegistry() - .get("executionModule"); + return SlcImages.MODULE; else if (obj instanceof ExecutionModulesContentProvider.FolderNode) - return ClientUiPlugin.getDefault().getImageRegistry() - .get("folder"); + return SlcImages.FOLDER; else if (obj instanceof ExecutionModulesContentProvider.FlowNode) - return ClientUiPlugin.getDefault().getImageRegistry() - .get("flow"); + return SlcImages.FLOW; else return PlatformUI.getWorkbench().getSharedImages() .getImage(ISharedImages.IMG_OBJ_ELEMENT); diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrExecutionModulesView.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrExecutionModulesView.java index dc9f9b404..eaa4cdd88 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrExecutionModulesView.java +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrExecutionModulesView.java @@ -1,13 +1,10 @@ package org.argeo.slc.client.ui.views; -import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Properties; -import java.util.UUID; import javax.jcr.Node; import javax.jcr.NodeIterator; @@ -18,22 +15,23 @@ import javax.jcr.observation.Event; import javax.jcr.observation.EventIterator; import javax.jcr.observation.EventListener; -import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.argeo.ArgeoException; import org.argeo.eclipse.ui.jcr.DefaultNodeLabelProvider; import org.argeo.eclipse.ui.jcr.NodesWrapper; import org.argeo.eclipse.ui.jcr.SimpleNodeContentProvider; import org.argeo.eclipse.ui.jcr.WrappedNode; import org.argeo.slc.SlcException; -import org.argeo.slc.client.ui.ClientUiPlugin; +import org.argeo.slc.client.ui.SlcImages; import org.argeo.slc.client.ui.controllers.ProcessController; -import org.argeo.slc.client.ui.providers.ExecutionModulesContentProvider; +import org.argeo.slc.client.ui.editors.ProcessEditor; +import org.argeo.slc.client.ui.editors.ProcessEditorInput; import org.argeo.slc.client.ui.providers.ExecutionModulesContentProvider.FlowNode; import org.argeo.slc.jcr.SlcJcrConstants; import org.argeo.slc.jcr.SlcNames; import org.argeo.slc.jcr.SlcTypes; import org.argeo.slc.process.RealizedFlow; -import org.argeo.slc.process.SlcExecution; import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; @@ -42,18 +40,19 @@ import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DragSourceAdapter; import org.eclipse.swt.dnd.DragSourceEvent; -import org.eclipse.swt.dnd.DragSourceListener; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; public class JcrExecutionModulesView extends ViewPart implements SlcTypes, SlcNames { - // private final static Log log = LogFactory - // .getLog(JcrExecutionModulesView.class); + private final static Log log = LogFactory + .getLog(JcrExecutionModulesView.class); public static final String ID = "org.argeo.slc.client.ui.jcrExecutionModulesView"; @@ -74,8 +73,10 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes, viewer.setLabelProvider(viewLabelProvider); viewer.setInput(getViewSite()); viewer.addDoubleClickListener(new ViewDoubleClickListener()); - int operations = DND.DROP_COPY | DND.DROP_MOVE; + Transfer[] tt = new Transfer[] { TextTransfer.getInstance() }; + // Transfer[] tt = new Transfer[] { EditorInputTransfer.getInstance() }; + int operations = DND.DROP_COPY | DND.DROP_MOVE; viewer.addDragSupport(operations, tt, new ViewDragListener()); try { @@ -205,17 +206,13 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes, public Image getImage(Node node) throws RepositoryException { if (node.getParent().isNodeType(SlcTypes.SLC_AGENT_PROXY)) - return ClientUiPlugin.getDefault().getImageRegistry() - .get("agent"); + return SlcImages.AGENT; else if (node.isNodeType(SlcTypes.SLC_MODULE)) - return ClientUiPlugin.getDefault().getImageRegistry() - .get("executionModule"); + return SlcImages.MODULE; else if (node.isNodeType(SlcTypes.SLC_EXECUTION_FLOW)) - return ClientUiPlugin.getDefault().getImageRegistry() - .get("flow"); + return SlcImages.FLOW; else - return ClientUiPlugin.getDefault().getImageRegistry() - .get("folder"); + return SlcImages.FOLDER; } public String getToolTipText(Node node) throws RepositoryException { @@ -231,35 +228,57 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes, public void doubleClick(DoubleClickEvent evt) { Object obj = ((IStructuredSelection) evt.getSelection()) .getFirstElement(); - if (obj instanceof ExecutionModulesContentProvider.FlowNode) { - ExecutionModulesContentProvider.FlowNode fn = (ExecutionModulesContentProvider.FlowNode) obj; - - List realizedFlows = new ArrayList(); - RealizedFlow realizedFlow = new RealizedFlow(); - realizedFlow.setModuleName(fn.getExecutionModuleNode() - .getDescriptor().getName()); - realizedFlow.setModuleVersion(fn.getExecutionModuleNode() - .getDescriptor().getVersion()); - realizedFlow.setFlowDescriptor(fn.getExecutionModuleNode() - .getFlowDescriptors().get(fn.getFlowName())); - realizedFlows.add(realizedFlow); - - SlcExecution slcExecution = new SlcExecution(); - slcExecution.setUuid(UUID.randomUUID().toString()); - slcExecution.setRealizedFlows(realizedFlows); - slcExecution.setHost(fn.getExecutionModuleNode().getAgentNode() - .getAgent().toString()); - processController.execute(fn.getExecutionModuleNode() - .getAgentNode().getAgent(), slcExecution); + try { + if (obj instanceof Node) { + Node node = (Node) obj; + if (node.isNodeType(SLC_EXECUTION_FLOW)) { + List paths = new ArrayList(); + paths.add(node.getPath()); + PlatformUI + .getWorkbench() + .getActiveWorkbenchWindow() + .getActivePage() + .openEditor( + new ProcessEditorInput(paths, true), + ProcessEditor.ID); + } + } + } catch (Exception e) { + throw new SlcException("Cannot open " + obj, e); } + + // if (obj instanceof ExecutionModulesContentProvider.FlowNode) { + // ExecutionModulesContentProvider.FlowNode fn = + // (ExecutionModulesContentProvider.FlowNode) obj; + // + // List realizedFlows = new ArrayList(); + // RealizedFlow realizedFlow = new RealizedFlow(); + // realizedFlow.setModuleName(fn.getExecutionModuleNode() + // .getDescriptor().getName()); + // realizedFlow.setModuleVersion(fn.getExecutionModuleNode() + // .getDescriptor().getVersion()); + // realizedFlow.setFlowDescriptor(fn.getExecutionModuleNode() + // .getFlowDescriptors().get(fn.getFlowName())); + // realizedFlows.add(realizedFlow); + // + // SlcExecution slcExecution = new SlcExecution(); + // slcExecution.setUuid(UUID.randomUUID().toString()); + // slcExecution.setRealizedFlows(realizedFlows); + // slcExecution.setHost(fn.getExecutionModuleNode().getAgentNode() + // .getAgent().toString()); + // processController.execute(fn.getExecutionModuleNode() + // .getAgentNode().getAgent(), slcExecution); + // } } } - class ViewDragListener implements DragSourceListener { + class ViewDragListener extends DragSourceAdapter { public void dragStart(DragSourceEvent event) { - System.out.println("Start Drag"); + if (log.isDebugEnabled()) + log.debug("Start Drag " + event); + super.dragStart(event); } public void dragSetData(DragSourceEvent event) { @@ -268,36 +287,65 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes, IStructuredSelection selection = (IStructuredSelection) viewer .getSelection(); - if (selection.getFirstElement() instanceof ExecutionModulesContentProvider.FlowNode) { + if (selection.getFirstElement() instanceof Node) { + Node node = (Node) selection.getFirstElement(); + // try { + // if (node.isNodeType(SLC_EXECUTION_FLOW)) { + // if (EditorInputTransfer.getInstance().isSupportedType( + // event.dataType)) { + // ProcessEditorInput pei = new ProcessEditorInput( + // node.getPath()); + // EditorInputData eid = EditorInputTransfer + // .createEditorInputData(ProcessEditor.ID, + // pei); + // event.data = new EditorInputTransfer.EditorInputData[] { eid + // }; + // + // } + // } + // } catch (RepositoryException e1) { + // throw new SlcException("Cannot drag " + node, e1); + // } if (TextTransfer.getInstance().isSupportedType(event.dataType)) { - ExecutionModulesContentProvider.FlowNode flowNode = (ExecutionModulesContentProvider.FlowNode) selection - .getFirstElement(); - - Properties props = new Properties(); - flowNodeAsProperties(props, flowNode); - props.setProperty("agentId", flowNode - .getExecutionModuleNode().getAgentNode().getAgent() - .getAgentUuid()); - props.setProperty("host", flowNode.getExecutionModuleNode() - .getAgentNode().getAgent().toString()); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); try { - props.store(out, ""); - event.data = new String(out.toByteArray()); - } catch (IOException e) { - throw new SlcException( - "Cannot transform realized flow", e); - } finally { - IOUtils.closeQuietly(out); + event.data = node.getPath(); + } catch (RepositoryException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); } + // + // // ExecutionModulesContentProvider.FlowNode flowNode = + // (ExecutionModulesContentProvider.FlowNode) selection + // // .getFirstElement(); + // // + // // Properties props = new Properties(); + // // flowNodeAsProperties(props, flowNode); + // // props.setProperty("agentId", flowNode + // // .getExecutionModuleNode().getAgentNode().getAgent() + // // .getAgentUuid()); + // // props.setProperty("host", + // flowNode.getExecutionModuleNode() + // // .getAgentNode().getAgent().toString()); + // // + // // ByteArrayOutputStream out = new + // ByteArrayOutputStream(); + // // try { + // // props.store(out, ""); + // // event.data = new String(out.toByteArray()); + // // } catch (IOException e) { + // // throw new SlcException( + // // "Cannot transform realized flow", e); + // // } finally { + // // IOUtils.closeQuietly(out); + // // } } } } public void dragFinished(DragSourceEvent event) { - System.out.println("Finished Drag"); + if (log.isDebugEnabled()) + log.debug("Finished Drag " + event); } protected void flowNodeAsProperties(Properties props, FlowNode fn) { diff --git a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/ProcessParametersView.java b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/ProcessParametersView.java index 5ae234d70..5ffcf2ac4 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/ProcessParametersView.java +++ b/eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/ProcessParametersView.java @@ -24,21 +24,18 @@ import org.eclipse.swt.widgets.Table; import org.eclipse.ui.part.ViewPart; /** + * This view, directly linked with the ProcessBuilderView enables + * the display and editing the parameters of a given process. * - * @author bsinou * - * This view, directly linked with the ProcessBuilderView - * enables the display and editing the parameters of a given process. + * Note that for a given RealizedFlow : * + * + parameters value are set using + * RealizedFlow.ExecutionFlowDescriptor.values, that might have + * default values * - * Note that for a given RealizedFlow : - * - * + paramaters value are set using - * RealizedFlow.ExecutionFlowDescriptor.values, that might - * have default values - * - * + possible "values" for a given parameters are stored in - * RealizedFlow.ExecutionSpec. + * + possible "values" for a given parameters are stored in + * RealizedFlow.ExecutionSpec. * */ public class ProcessParametersView extends ViewPart { diff --git a/modules/server/org.argeo.slc.server.jcr/META-INF/MANIFEST.MF b/modules/server/org.argeo.slc.server.jcr/META-INF/MANIFEST.MF index 023fd63df..e27a76ff5 100644 --- a/modules/server/org.argeo.slc.server.jcr/META-INF/MANIFEST.MF +++ b/modules/server/org.argeo.slc.server.jcr/META-INF/MANIFEST.MF @@ -20,6 +20,7 @@ Import-Package: javax.jcr, org.argeo.slc.dao.test, org.argeo.slc.dao.test.tree, org.argeo.slc.execution, + org.argeo.slc.jcr, org.argeo.slc.jcr.dao, org.argeo.slc.jcr.execution, org.argeo.slc.process, diff --git a/modules/server/org.argeo.slc.server.jcr/META-INF/spring/jcr-osgi.xml b/modules/server/org.argeo.slc.server.jcr/META-INF/spring/jcr-osgi.xml index a629e465e..1bf180908 100644 --- a/modules/server/org.argeo.slc.server.jcr/META-INF/spring/jcr-osgi.xml +++ b/modules/server/org.argeo.slc.server.jcr/META-INF/spring/jcr-osgi.xml @@ -1,10 +1,13 @@ + http://www.springframework.org/schema/beans/spring-beans-2.5.xsd + http://www.springframework.org/schema/util + http://www.springframework.org/schema/util/spring-util-2.5.xsd"> - + + + + + + + + + + diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java index e16ad65f7..06c05248b 100644 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java @@ -27,12 +27,13 @@ import org.argeo.slc.execution.ExecutionContext; import org.argeo.slc.execution.ExecutionFlow; import org.argeo.slc.execution.ExecutionFlowDescriptorConverter; import org.argeo.slc.execution.ExecutionModulesManager; +import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.process.RealizedFlow; -import org.argeo.slc.process.SlcExecution; import org.argeo.slc.process.SlcExecutionNotifier; import org.argeo.slc.process.SlcExecutionStep; /** Provides the base feature of an execution module manager. */ +@SuppressWarnings("deprecation") public abstract class AbstractExecutionModulesManager implements ExecutionModulesManager { private final static Log log = LogFactory @@ -51,10 +52,6 @@ public abstract class AbstractExecutionModulesManager implements protected abstract ExecutionFlowDescriptorConverter getExecutionFlowDescriptorConverter( String moduleName, String moduleVersion); - public void process(SlcExecution slcExecution) { - new ProcessThread(this, slcExecution).start(); - } - public void execute(RealizedFlow realizedFlow) { if (log.isTraceEnabled()) log.trace("Executing " + realizedFlow); @@ -82,7 +79,7 @@ public abstract class AbstractExecutionModulesManager implements // } - public void dispatchUpdateStatus(SlcExecution slcExecution, + public void dispatchUpdateStatus(ExecutionProcess slcExecution, String oldStatus, String newStatus) { for (Iterator it = getSlcExecutionNotifiers() .iterator(); it.hasNext();) { @@ -90,7 +87,8 @@ public abstract class AbstractExecutionModulesManager implements } } - public void dispatchAddStep(SlcExecution slcExecution, SlcExecutionStep step) { + public void dispatchAddStep(ExecutionProcess slcExecution, + SlcExecutionStep step) { List steps = new ArrayList(); steps.add(step); for (Iterator it = getSlcExecutionNotifiers() diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionThread.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionThread.java index 9190ea6fc..52040fd50 100644 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionThread.java +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionThread.java @@ -60,7 +60,10 @@ public class ExecutionThread extends Thread { if (autoUpgrade != null && autoUpgrade.equals("true")) processThread.getExecutionModulesManager().upgrade( realizedFlow.getModuleNameVersion()); + + // START FLOW processThread.getExecutionModulesManager().execute(realizedFlow); + // END FLOW } catch (Exception e) { // TODO: re-throw exception ? String msg = "Execution of flow " + flowName + " failed."; diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThread.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThread.java index 5af3262d5..9474656fd 100644 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThread.java +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThread.java @@ -17,11 +17,15 @@ package org.argeo.slc.core.execution; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; import org.argeo.slc.execution.ExecutionModulesManager; +import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.process.RealizedFlow; import org.argeo.slc.process.SlcExecution; @@ -30,61 +34,95 @@ public class ProcessThread extends Thread { private final static Log log = LogFactory.getLog(ProcessThread.class); private final ExecutionModulesManager executionModulesManager; - private final SlcExecution slcProcess; + private final ExecutionProcess process; private final ProcessThreadGroup processThreadGroup; - private final List flowsToProcess = new ArrayList(); + + private Set executionThreads = new HashSet(); private Boolean hadAnError = false; public ProcessThread(ExecutionModulesManager executionModulesManager, - SlcExecution slcExecution) { + ExecutionProcess process) { super(executionModulesManager.getProcessesThreadGroup(), - "SLC Process #" + slcExecution.getUuid()); + "SLC Process #" + process.getUuid()); this.executionModulesManager = executionModulesManager; - this.slcProcess = slcExecution; + this.process = process; processThreadGroup = new ProcessThreadGroup(executionModulesManager, this); } public void run() { - log.info("\n##\n## SLC Process #" + slcProcess.getUuid() + log.info("\n##\n## SLC Process #" + process.getUuid() + " STARTED\n##\n"); - slcProcess.setStatus(SlcExecution.STATUS_RUNNING); - executionModulesManager.dispatchUpdateStatus(slcProcess, - SlcExecution.STATUS_SCHEDULED, SlcExecution.STATUS_RUNNING); + process.setStatus(SlcExecution.RUNNING); + executionModulesManager.dispatchUpdateStatus(process, + SlcExecution.SCHEDULED, SlcExecution.RUNNING); + + process(); + + // waits for all execution threads to complete (in case they were + // started asynchronously) + for (ExecutionThread executionThread : executionThreads) { + if (executionThread.isAlive()) { + try { + executionThread.join(); + } catch (InterruptedException e) { + log.error("Execution thread " + executionThread + + " was interrupted"); + } + } + } + + // TODO: error management at flow level? + if (hadAnError) + process.setStatus(SlcExecution.ERROR); + else + process.setStatus(SlcExecution.COMPLETED); + executionModulesManager.dispatchUpdateStatus(process, + SlcExecution.RUNNING, process.getStatus()); + + log.info("\n## SLC Process #" + process.getUuid() + " COMPLETED\n"); + } - flowsToProcess.addAll(slcProcess.getRealizedFlows()); + /** + * Implementation specific execution. To be overridden in order to deal with + * custom process types. Default expects an {@link SlcExecution}. + */ + protected void process() { + if (!(process instanceof SlcExecution)) + throw new SlcException("Unsupported process type " + + process.getClass()); + SlcExecution slcExecution = (SlcExecution) process; + List flowsToProcess = new ArrayList(); + flowsToProcess.addAll(slcExecution.getRealizedFlows()); while (flowsToProcess.size() > 0) { - RealizedFlow flow = flowsToProcess.remove(0); - ExecutionThread thread = new ExecutionThread(this, flow); - thread.start(); + RealizedFlow realizedFlow = flowsToProcess.remove(0); + execute(realizedFlow, true); + } + } + protected void execute(RealizedFlow realizedFlow, Boolean synchronous) { + ExecutionThread thread = new ExecutionThread(this, realizedFlow); + executionThreads.add(thread); + thread.start(); + + if (synchronous) { try { thread.join(); } catch (InterruptedException e) { - log.error("Flow " + flow + " was interrupted", e); + log.error("Flow " + realizedFlow + " was interrupted", e); } - - // synchronized (this) { - // try { - // wait(); - // } catch (InterruptedException e) { - // // silent - // } - // } } - // TODO: error management at flow level? - if (hadAnError) - slcProcess.setStatus(SlcExecution.STATUS_ERROR); - else - slcProcess.setStatus(SlcExecution.STATUS_FINISHED); - executionModulesManager.dispatchUpdateStatus(slcProcess, - SlcExecution.STATUS_RUNNING, slcProcess.getStatus()); - - log.info("\n## SLC Process #" + slcProcess.getUuid() + " COMPLETED\n"); + // synchronized (this) { + // try { + // wait(); + // } catch (InterruptedException e) { + // // silent + // } + // } } public void notifyError() { @@ -95,8 +133,8 @@ public class ProcessThread extends Thread { // notifyAll(); } - public SlcExecution getSlcProcess() { - return slcProcess; + public ExecutionProcess getProcess() { + return process; } public ProcessThreadGroup getProcessThreadGroup() { diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThreadGroup.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThreadGroup.java index 1574b97d6..61e8c2f2a 100644 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThreadGroup.java +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThreadGroup.java @@ -17,6 +17,7 @@ package org.argeo.slc.core.execution; import org.argeo.slc.execution.ExecutionModulesManager; +import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.process.SlcExecution; import org.argeo.slc.process.SlcExecutionStep; @@ -27,19 +28,20 @@ public class ProcessThreadGroup extends ThreadGroup { public ProcessThreadGroup(ExecutionModulesManager executionModulesManager, ProcessThread processThread) { - super("SLC Process #" + processThread.getSlcProcess().getUuid() + super("SLC Process #" + processThread.getProcess().getUuid() + " thread group"); this.executionModulesManager = executionModulesManager; this.processThread = processThread; } - public SlcExecution getSlcProcess() { - return processThread.getSlcProcess(); - } + // public SlcExecution getSlcProcess() { + // return processThread.getSlcProcess(); + // } public void dispatchAddStep(SlcExecutionStep step) { - SlcExecution slcProcess = processThread.getSlcProcess(); - slcProcess.getSteps().add(step); + ExecutionProcess slcProcess = processThread.getProcess(); + if (slcProcess instanceof SlcExecution) + ((SlcExecution) slcProcess).getSteps().add(step); executionModulesManager.dispatchAddStep(slcProcess, step); } diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/runtime/DefaultAgent.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/runtime/DefaultAgent.java index ca230856f..3220e910f 100644 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/runtime/DefaultAgent.java +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/runtime/DefaultAgent.java @@ -22,8 +22,10 @@ import java.util.List; import java.util.UUID; import org.argeo.slc.SlcException; +import org.argeo.slc.core.execution.ProcessThread; import org.argeo.slc.execution.ExecutionModuleDescriptor; import org.argeo.slc.execution.ExecutionModulesManager; +import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.process.SlcExecution; import org.argeo.slc.runtime.SlcAgent; import org.argeo.slc.runtime.SlcAgentDescriptor; @@ -61,8 +63,25 @@ public class DefaultAgent implements SlcAgent { /* * SLC AGENT */ - public void runSlcExecution(final SlcExecution slcExecution) { - modulesManager.process(slcExecution); + public void runSlcExecution(SlcExecution slcExecution) { + process(slcExecution); + } + + public void process(ExecutionProcess process) { + ProcessThread processThread = createProcessThread(modulesManager, + process); + processThread.start(); + } + + /** Creates the thread which will coordinate the execution for this agent. */ + protected ProcessThread createProcessThread( + ExecutionModulesManager modulesManager, ExecutionProcess process) { + if (!(process instanceof SlcExecution)) + throw new SlcException("Unsupported process type " + + process.getClass()); + ProcessThread processThread = new ProcessThread(modulesManager, + (SlcExecution) process); + return processThread; } public ExecutionModuleDescriptor getExecutionModuleDescriptor( diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/SlcExecutionServiceAdapter.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/SlcExecutionServiceAdapter.java index a007e6ce5..b1abbeef1 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/SlcExecutionServiceAdapter.java +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/SlcExecutionServiceAdapter.java @@ -18,39 +18,43 @@ package org.argeo.slc.services.impl; import java.util.List; -import org.argeo.slc.UnsupportedException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.msg.process.SlcExecutionStatusRequest; import org.argeo.slc.msg.process.SlcExecutionStepsRequest; -import org.argeo.slc.process.SlcExecution; import org.argeo.slc.process.SlcExecutionNotifier; import org.argeo.slc.process.SlcExecutionStep; import org.argeo.slc.services.SlcExecutionService; /** In memory bridge between SLC execution notifier and service. */ +@SuppressWarnings("deprecation") public class SlcExecutionServiceAdapter implements SlcExecutionNotifier { + private final static Log log = LogFactory + .getLog(SlcExecutionServiceAdapter.class); + private SlcExecutionService slcExecutionService; - public void updateStatus(SlcExecution slcExecution, String oldStatus, + public void updateStatus(ExecutionProcess slcExecution, String oldStatus, String newStatus) { SlcExecutionStatusRequest req = new SlcExecutionStatusRequest( slcExecution.getUuid(), newStatus); - slcExecutionService.updateStatus(req); + try { + slcExecutionService.updateStatus(req); + } catch (Exception e) { + log.trace("Cannot update process status " + e); + } } - public void addSteps(SlcExecution slcExecution, + public void addSteps(ExecutionProcess slcExecution, List additionalSteps) { SlcExecutionStepsRequest req = new SlcExecutionStepsRequest( slcExecution.getUuid(), additionalSteps); - slcExecutionService.addSteps(req); - } - - public void newExecution(SlcExecution slcExecution) { - throw new UnsupportedException(); - //slcExecutionService.newExecution(slcExecution); - } - - public void updateExecution(SlcExecution slcExecution) { - throw new UnsupportedException(); + try { + slcExecutionService.addSteps(req); + } catch (Exception e) { + log.trace("Cannot add steps " + e); + } } public void setSlcExecutionService(SlcExecutionService slcExecutionService) { diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/SlcExecutionServiceImpl.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/SlcExecutionServiceImpl.java index 56ad0ac21..89ef92e93 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/SlcExecutionServiceImpl.java +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/SlcExecutionServiceImpl.java @@ -68,7 +68,7 @@ public class SlcExecutionServiceImpl implements SlcExecutionService { slcExecution.setStatus(msg.getNewStatus()); - if (msg.getNewStatus().equals(SlcExecution.STATUS_FINISHED)) { + if (msg.getNewStatus().equals(SlcExecution.COMPLETED)) { List steps = new ArrayList(); steps.add(new SlcExecutionStep(SlcExecutionStep.END, "Process finished.")); diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/controllers/ProcessController.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/controllers/ProcessController.java index bd5fd7b73..8db565c45 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/controllers/ProcessController.java +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/controllers/ProcessController.java @@ -145,7 +145,7 @@ public class ProcessController { || slcExecution.getUuid().length() < 8) slcExecution.setUuid(UUID.randomUUID().toString()); - slcExecution.setStatus(SlcExecution.STATUS_SCHEDULED); + slcExecution.setStatus(SlcExecution.SCHEDULED); slcExecution.getSteps().add( new SlcExecutionStep(SlcExecutionStep.START, "Process started from the Web UI")); diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionModulesManager.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionModulesManager.java index 26890ad05..4400a18f2 100644 --- a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionModulesManager.java +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionModulesManager.java @@ -20,7 +20,6 @@ import java.util.List; import org.argeo.slc.deploy.ModulesManager; import org.argeo.slc.process.RealizedFlow; -import org.argeo.slc.process.SlcExecution; import org.argeo.slc.process.SlcExecutionStep; /** Provides access to the execution modules */ @@ -35,19 +34,16 @@ public interface ExecutionModulesManager extends ModulesManager { */ public List listExecutionModules(); - /** Asynchronously prepares and executes an {@link SlcExecution} */ - public void process(SlcExecution slcExecution); - /** The thread group to which all process threads will belong. */ public ThreadGroup getProcessesThreadGroup(); /** Synchronously finds and executes an {@link ExecutionFlow}. */ public void execute(RealizedFlow realizedFlow); - /** Notify of a status update status of the {@link SlcExecution} */ - public void dispatchUpdateStatus(SlcExecution slcExecution, + /** Notify of a status update status of the {@link ExecutionProcess} */ + public void dispatchUpdateStatus(ExecutionProcess process, String oldStatus, String newStatus); - /** Notify that a step was added in an {@link SlcExecution} */ - public void dispatchAddStep(SlcExecution slcExecution, SlcExecutionStep step); + /** Notify that a step was added in an {@link ExecutionProcess} */ + public void dispatchAddStep(ExecutionProcess process, SlcExecutionStep step); } diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcess.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcess.java new file mode 100644 index 000000000..58393dd90 --- /dev/null +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcess.java @@ -0,0 +1,37 @@ +package org.argeo.slc.execution; + +/** + * A process is the functional representation of a combination of executions. + * While an execution is the actual java code running, a process exists before, + * during and after the execution actually took place, providing an entry point + * for the definition of executions, their monitoring (e.g. logging) and + * tracking. A process can be distributed or parallelized. + */ +public interface ExecutionProcess { + /** The process is not yet usable. */ + public final static String UNINITIALIZED = "UNINITIALIZED"; + /** The process is usable but not yet scheduled to run. */ + public final static String INITIALIZED = "INITIALIZED"; + /** The process is usable and scheduled to run, but not yet running. */ + public final static String SCHEDULED = "SCHEDULED"; + /** The process is currently running. */ + public final static String RUNNING = "RUNNING"; + /** The process has properly completed. */ + public final static String COMPLETED = "COMPLETED"; + /** The process failed because of an unexpected error. */ + public final static String ERROR = "ERROR"; + /** + * Only a reference to the process has been kept, all monitoring data such + * as logs have been purged. + */ + public final static String PURGED = "PURGED"; + + /** The UUID of this process. */ + public String getUuid(); + + /** The current status of this process. */ + public String getStatus(); + + /** Sets the current status of this process */ + public void setStatus(String status); +} diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcessNotifier.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcessNotifier.java new file mode 100644 index 000000000..9bfdaf98f --- /dev/null +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcessNotifier.java @@ -0,0 +1,14 @@ +package org.argeo.slc.execution; + +import java.util.List; + +import org.argeo.slc.process.SlcExecutionStep; + +public interface ExecutionProcessNotifier { + public void addSteps(ExecutionProcess process, + List additionalSteps); + + public void updateStatus(ExecutionProcess process, String oldStatus, + String newStatus); + +} diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java index 18d02a3bc..37b647ad3 100644 --- a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java @@ -23,14 +23,10 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; -public class SlcExecution implements Serializable { +import org.argeo.slc.execution.ExecutionProcess; + +public class SlcExecution implements ExecutionProcess, Serializable { private static final long serialVersionUID = -7607457971382118466L; - public final static String STATUS_NONE = "DEFAULT"; - public final static String STATUS_SCHEDULED = "SCHEDULED"; - public final static String STATUS_RUNNING = "RUNNING"; - public final static String STATUS_FINISHED = "FINISHED"; - public final static String STATUS_ERROR = "ERROR"; - public final static String STATUS_CLEANED = "CLEANED"; public final static String UNKOWN_HOST = "UNKOWN_HOST"; @@ -38,7 +34,7 @@ public class SlcExecution implements Serializable { private String host; private String user; private String type; - private String status = STATUS_NONE; + private String status = UNINITIALIZED; private Map attributes = new TreeMap(); /** TODO: Synchronize */ @@ -152,7 +148,7 @@ public class SlcExecution implements Serializable { } public Date getEndDate() { - if (!status.equals(STATUS_FINISHED) && !status.equals(STATUS_ERROR)) + if (!status.equals(COMPLETED) && !status.equals(ERROR)) return null; synchronized (steps) { diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecutionNotifier.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecutionNotifier.java index ca6809680..52386d935 100644 --- a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecutionNotifier.java +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecutionNotifier.java @@ -16,18 +16,12 @@ package org.argeo.slc.process; -import java.util.List; +import org.argeo.slc.execution.ExecutionProcessNotifier; -public interface SlcExecutionNotifier { - @Deprecated - public void newExecution(SlcExecution slcExecution); - - public void addSteps(SlcExecution slcExecution, - List additionalSteps); - - @Deprecated - public void updateExecution(SlcExecution slcExecution); - - public void updateStatus(SlcExecution slcExecution, String oldStatus, - String newStatus); +/** + * Notifies of changes in the current process + * + * @deprecated use {@link ExecutionProcessNotifier} instead. + */ +public interface SlcExecutionNotifier extends ExecutionProcessNotifier { } diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/runtime/SlcAgent.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/runtime/SlcAgent.java index 70c8f9c2f..d295f20b6 100644 --- a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/runtime/SlcAgent.java +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/runtime/SlcAgent.java @@ -19,6 +19,7 @@ package org.argeo.slc.runtime; import java.util.List; import org.argeo.slc.execution.ExecutionModuleDescriptor; +import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.process.SlcExecution; /** A local agent, able to run SLC Execution locally. */ @@ -31,8 +32,11 @@ public interface SlcAgent { public List listExecutionModuleDescriptors(); + /** @deprecated Use {@link #process(ExecutionProcess)} instead. */ public void runSlcExecution(SlcExecution slcExecution); + public void process(ExecutionProcess process); + /** @return true if still alive. */ public boolean ping(); } diff --git a/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsAgentProxy.java b/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsAgentProxy.java index 2230cb876..d3027c93d 100644 --- a/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsAgentProxy.java +++ b/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsAgentProxy.java @@ -29,6 +29,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; import org.argeo.slc.execution.ExecutionModuleDescriptor; +import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.msg.ExecutionAnswer; import org.argeo.slc.msg.MsgConstants; import org.argeo.slc.process.SlcExecution; @@ -74,7 +75,15 @@ public class JmsAgentProxy implements SlcAgent { } public void runSlcExecution(SlcExecution slcExecution) { - sendReceive(new AgentMC("runSlcExecution", slcExecution)); + process(slcExecution); + } + + public void process(ExecutionProcess executionProcess) { + if (!(executionProcess instanceof SlcExecution)) + throw new SlcException("Unsupported process type " + + executionProcess.getClass()); + sendReceive(new AgentMC("runSlcExecution", + (SlcExecution) executionProcess)); } public boolean ping() { @@ -198,9 +207,7 @@ public class JmsAgentProxy implements SlcAgent { msg = session.createTextMessage(); else msg = toMessage(body, session); - msg - .setStringProperty(MsgConstants.PROPERTY_SLC_AGENT_ID, - agentUuid); + msg.setStringProperty(MsgConstants.PROPERTY_SLC_AGENT_ID, agentUuid); msg.setStringProperty(JmsAgent.PROPERTY_QUERY, query); msg.setJMSCorrelationID(correlationId); setArguments(msg); diff --git a/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcExecutionNotifier.java b/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcExecutionNotifier.java index 45db072b9..8a13f5d7d 100644 --- a/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcExecutionNotifier.java +++ b/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcExecutionNotifier.java @@ -23,6 +23,7 @@ import javax.jms.Destination; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.UnsupportedException; +import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.msg.process.SlcExecutionStatusRequest; import org.argeo.slc.msg.process.SlcExecutionStepsRequest; import org.argeo.slc.process.SlcExecution; @@ -31,6 +32,7 @@ import org.argeo.slc.process.SlcExecutionStep; import org.springframework.jms.JmsException; import org.springframework.jms.core.JmsTemplate; +@SuppressWarnings("deprecation") public class JmsSlcExecutionNotifier implements SlcExecutionNotifier { private final static Log log = LogFactory .getLog(JmsSlcExecutionNotifier.class); @@ -41,14 +43,14 @@ public class JmsSlcExecutionNotifier implements SlcExecutionNotifier { // private Destination updateStatusDestination; - public void updateStatus(SlcExecution slcExecution, String oldStatus, + public void updateStatus(ExecutionProcess slcExecution, String oldStatus, String newStatus) { SlcExecutionStatusRequest req = new SlcExecutionStatusRequest( slcExecution.getUuid(), newStatus); convertAndSend(req); } - public void addSteps(SlcExecution slcExecution, + public void addSteps(ExecutionProcess slcExecution, List additionalSteps) { SlcExecutionStepsRequest req = new SlcExecutionStepsRequest( slcExecution.getUuid(), additionalSteps); diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/xml/process/FileSlcExecutionNotifier.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/xml/process/FileSlcExecutionNotifier.java index fdc373e65..93cde8ddf 100644 --- a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/xml/process/FileSlcExecutionNotifier.java +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/xml/process/FileSlcExecutionNotifier.java @@ -18,8 +18,6 @@ package org.argeo.slc.xml.process; import java.io.File; import java.io.FileWriter; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -28,46 +26,37 @@ import javax.xml.transform.stream.StreamResult; import org.apache.commons.io.IOUtils; import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.process.SlcExecution; import org.argeo.slc.process.SlcExecutionNotifier; import org.argeo.slc.process.SlcExecutionStep; import org.springframework.oxm.Marshaller; +/** @deprecated Probably not even working anymore */ public class FileSlcExecutionNotifier implements SlcExecutionNotifier { - private final static SimpleDateFormat sdf = new SimpleDateFormat( - "yyyyMMdd-HHmmss"); - - private String basePath; +// private final static SimpleDateFormat sdf = new SimpleDateFormat( +// "yyyyMMdd-HHmmss"); +// +// private String basePath; private Marshaller marshaller; private Map uuidToDir = new HashMap(); - public void addSteps(SlcExecution slcExecution, + public void addSteps(ExecutionProcess slcExecution, List additionalSteps) { writeSlcExecution(slcExecution); } - public void newExecution(SlcExecution slcExecution) { - String dirPath = basePath + File.separator + sdf.format(new Date()) - + '-' + slcExecution.getUuid(); - File dir = new File(dirPath); - dir.mkdirs(); - - uuidToDir.put(slcExecution.getUuid(), dirPath); - - writeSlcExecution(slcExecution); - } - - public void updateExecution(SlcExecution slcExecution) { - writeSlcExecution(slcExecution); - } - - public void updateStatus(SlcExecution slcExecution, String oldStatus, + public void updateStatus(ExecutionProcess slcExecution, String oldStatus, String newStatus) { writeSlcExecution(slcExecution); } - protected void writeSlcExecution(SlcExecution slcExecution) { + protected void writeSlcExecution(ExecutionProcess process) { + if (!(process instanceof SlcExecution)) + throw new SlcException("Unsupported process type " + + process.getClass()); + SlcExecution slcExecution = (SlcExecution) process; FileWriter out = null; try { out = new FileWriter(getFilePath(slcExecution)); @@ -91,7 +80,7 @@ public class FileSlcExecutionNotifier implements SlcExecutionNotifier { } public void setBasePath(String basePath) { - this.basePath = basePath; + //this.basePath = basePath; } public void setMarshaller(Marshaller marshaller) { diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrConstants.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrConstants.java index eb8b13521..eb1cf46e0 100644 --- a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrConstants.java +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrConstants.java @@ -1,6 +1,8 @@ package org.argeo.slc.jcr; public interface SlcJcrConstants { + public final static String PROPERTY_PATH = "argeo.slc.jcr.path"; + public final static String PROCESSES_BASE_PATH = "/slc/processes"; public final static String AGENTS_BASE_PATH = "/slc/agents"; public final static String VM_AGENT_FACTORY_PATH = AGENTS_BASE_PATH + "/vm"; } diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrUtils.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrUtils.java new file mode 100644 index 000000000..0cda5a86d --- /dev/null +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrUtils.java @@ -0,0 +1,54 @@ +package org.argeo.slc.jcr; + +/** Utilities around the SLC JCR model. Note that it relies on fixed base paths. */ +public class SlcJcrUtils { + public final static Integer AGENT_FACTORY_DEPTH = 3; + public final static Integer EXECUTION_MODULES_DEPTH = AGENT_FACTORY_DEPTH + 2; + public final static Integer EXECUTION_FLOWS_DEPTH = EXECUTION_MODULES_DEPTH + 3; + + /** Extracts the path of a flow relative to its execution module */ + public static String flowRelativePath(String fullFlowPath) { + String[] tokens = fullFlowPath.split("/"); + StringBuffer buf = new StringBuffer(fullFlowPath.length()); + for (int i = EXECUTION_FLOWS_DEPTH; i < tokens.length; i++) { + buf.append('/').append(tokens[i]); + } + return buf.toString(); + } + + /** Extracts the execution module name of a flow */ + public static String flowExecutionModuleName(String fullFlowPath) { + String[] tokens = fullFlowPath.split("/"); + return tokens[EXECUTION_MODULES_DEPTH + 1]; + } + + /** Extracts the execution module version of a flow */ + public static String flowExecutionModuleVersion(String fullFlowPath) { + String[] tokens = fullFlowPath.split("/"); + return tokens[EXECUTION_MODULES_DEPTH + 2]; + } + + /** Extracts the agent factory of a flow */ + public static String flowAgentFactoryPath(String fullFlowPath) { + String[] tokens = fullFlowPath.split("/"); + StringBuffer buf = new StringBuffer(fullFlowPath.length()); + // first token is always empty + for (int i = 1; i < AGENT_FACTORY_DEPTH + 1; i++) { + buf.append('/').append(tokens[i]); + } + return buf.toString(); + } + + /** Prevents instantiation */ + private SlcJcrUtils() { + + } + + // public static void main(String[] args) { + // String path = + // "/slc/agents/vm/54654654654/executionModules/org.argeo/1.2.3/myFlow"; + // System.out.println(flowRelativePath(path)); + // System.out.println(flowExecutionModuleName(path)); + // System.out.println(flowAgentFactoryPath(path)); + // } +} diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcNames.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcNames.java index 728d576a5..68579cbae 100644 --- a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcNames.java +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcNames.java @@ -3,9 +3,13 @@ package org.argeo.slc.jcr; /** JCR names used by SLC */ public interface SlcNames { + public final static String SLC_UUID = "slc:uuid"; + public final static String SLC_STATUS = "slc:status"; public final static String SLC_NAME = "slc:name"; public final static String SLC_VERSION = "slc:version"; - public final static String SLC_FLOWS = "slc:flows"; + public final static String SLC_ADDRESS = "slc:address"; + + public final static String SLC_FLOW = "slc:flow"; public final static String SLC_EXECUTION_MODULES = "slc:executionModules"; } diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcTypes.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcTypes.java index d0a45662c..42a941958 100644 --- a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcTypes.java +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcTypes.java @@ -7,5 +7,7 @@ public interface SlcTypes { //public final static String SLC_AGENT = "slc:agent"; public final static String SLC_MODULE = "slc:module"; public final static String SLC_EXECUTION_FLOW = "slc:executionFlow"; + public final static String SLC_PROCESS = "slc:process"; + public final static String SLC_REALIZED_FLOW = "slc:realizedFlow"; } diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrAgent.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrAgent.java index d5b1be19b..b75b04a08 100644 --- a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrAgent.java +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrAgent.java @@ -9,7 +9,10 @@ import javax.jcr.Session; import org.argeo.jcr.JcrUtils; import org.argeo.slc.SlcException; +import org.argeo.slc.core.execution.ProcessThread; import org.argeo.slc.core.runtime.DefaultAgent; +import org.argeo.slc.execution.ExecutionModulesManager; +import org.argeo.slc.execution.ExecutionProcess; import org.argeo.slc.jcr.SlcJcrConstants; import org.argeo.slc.jcr.SlcTypes; import org.argeo.slc.runtime.SlcAgent; @@ -41,6 +44,13 @@ public class JcrAgent extends DefaultAgent implements SlcAgentFactory { } } + @Override + protected ProcessThread createProcessThread( + ExecutionModulesManager modulesManager, ExecutionProcess process) { + return new JcrProcessThread(modulesManager, + (JcrExecutionProcess) process); + } + public void dispose() { } diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionProcess.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionProcess.java new file mode 100644 index 000000000..998027e8e --- /dev/null +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionProcess.java @@ -0,0 +1,53 @@ +package org.argeo.slc.jcr.execution; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.jcr.JcrUtils; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionProcess; +import org.argeo.slc.jcr.SlcNames; + +/** Execution process implementation based on a JCR node. */ +public class JcrExecutionProcess implements ExecutionProcess { + private final Node node; + + public JcrExecutionProcess(Node node) { + this.node = node; + } + + public String getUuid() { + try { + return node.getProperty(SlcNames.SLC_UUID).getString(); + } catch (RepositoryException e) { + throw new SlcException("Cannot get uuid for " + node, e); + } + } + + public String getStatus() { + try { + return node.getProperty(SlcNames.SLC_STATUS).getString(); + } catch (RepositoryException e) { + throw new SlcException("Cannot get uuid for " + node, e); + } + } + + public void setStatus(String status) { + try { + node.setProperty(SlcNames.SLC_STATUS, status); + node.getSession().save(); + } catch (RepositoryException e) { + try { + JcrUtils.discardQuietly(node.getSession()); + } catch (RepositoryException e1) { + // silent + } + throw new SlcException("Cannot get uuid for " + node, e); + } + } + + public Node getNode() { + return node; + } + +} diff --git a/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrProcessThread.java b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrProcessThread.java new file mode 100644 index 000000000..34685fff0 --- /dev/null +++ b/runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrProcessThread.java @@ -0,0 +1,66 @@ +package org.argeo.slc.jcr.execution; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.argeo.slc.core.execution.ProcessThread; +import org.argeo.slc.execution.ExecutionFlowDescriptor; +import org.argeo.slc.execution.ExecutionModulesManager; +import org.argeo.slc.jcr.SlcJcrUtils; +import org.argeo.slc.jcr.SlcNames; +import org.argeo.slc.process.RealizedFlow; + +public class JcrProcessThread extends ProcessThread implements SlcNames { + + public JcrProcessThread(ExecutionModulesManager executionModulesManager, + JcrExecutionProcess process) { + super(executionModulesManager, process); + } + + @Override + protected void process() { + try { + Node realizedFlowNode = getNode().getNode(SLC_FLOW); + // we just manage one level for the time being + NodeIterator nit = realizedFlowNode.getNodes(SLC_FLOW); + while (nit.hasNext()) { + process(nit.nextNode()); + } + } catch (RepositoryException e) { + throw new ArgeoException("Cannot process " + getNode(), e); + } + } + + protected void process(Node realizedFlowNode) throws RepositoryException { + if (realizedFlowNode.hasNode(SLC_ADDRESS)) { + String flowPath = realizedFlowNode.getNode(SLC_ADDRESS) + .getProperty(Property.JCR_PATH).getString(); + // TODO: convert to local path if remote + + Node flowNode = realizedFlowNode.getSession().getNode(flowPath); + String flowName = flowNode.getProperty(SLC_NAME).getString(); + + String executionModuleName = SlcJcrUtils + .flowExecutionModuleName(flowPath); + String executionModuleVersion = SlcJcrUtils + .flowExecutionModuleVersion(flowPath); + + RealizedFlow realizedFlow = new RealizedFlow(); + realizedFlow.setModuleName(executionModuleName); + realizedFlow.setModuleVersion(executionModuleVersion); + + ExecutionFlowDescriptor efd = new ExecutionFlowDescriptor(flowName, + null, null); + realizedFlow.setFlowDescriptor(efd); + + execute(realizedFlow, true); + } + } + + protected Node getNode() { + return ((JcrExecutionProcess) getProcess()).getNode(); + } +} diff --git a/runtime/org.argeo.slc.support.jcr/src/main/resources/org/argeo/slc/jcr/slc.cnd b/runtime/org.argeo.slc.support.jcr/src/main/resources/org/argeo/slc/jcr/slc.cnd index e82799fe1..62c469bc4 100644 --- a/runtime/org.argeo.slc.support.jcr/src/main/resources/org/argeo/slc/jcr/slc.cnd +++ b/runtime/org.argeo.slc.support.jcr/src/main/resources/org/argeo/slc/jcr/slc.cnd @@ -15,5 +15,16 @@ mixin mixin - slc:name (STRING) m +[slc:process] > nt:unstructured, mix:created, mix:lastModified +- slc:uuid (STRING) m +- slc:status (STRING) m ++ slc:flow (slc:realizedFlow) + +[slc:realizedFlow] > nt:base +mixin +- slc:started (DATE) +- slc:completed (DATE) ++ slc:address (nt:address) ++ slc:flow (slc:realizedFlow) *