]> git.argeo.org Git - gpl/argeo-slc.git/commitdiff
Improve logging
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 5 Jul 2011 13:33:06 +0000 (13:33 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 5 Jul 2011 13:33:06 +0000 (13:33 +0000)
Logging in UI

git-svn-id: https://svn.argeo.org/slc/trunk@4666 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

18 files changed:
eclipse/plugins/org.argeo.slc.client.rcp/src/main/java/org/argeo/slc/client/rcp/SlcSecureClientApplication.java
eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/controllers.xml
eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/editors.xml
eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/jcr.xml
eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/listeners.xml [deleted file]
eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/views.xml
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/controllers/ProcessController.java
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessBuilderPage.java
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditor.java
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessLogPage.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionThread.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThreadGroup.java
runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionModulesManager.java
runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcessNotifier.java
runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionStep.java [new file with mode: 0644]
runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecutionStep.java
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/log4j/SlcExecutionAppender.java

index e56eadbdad90f8f44aa90b30c866e7f506e5868a..e2b054219ed09a7d40f084be5105973fe5cf9732 100644 (file)
@@ -1,6 +1,8 @@
 package org.argeo.slc.client.rcp;
 
 import org.argeo.security.ui.rcp.SecureRcp;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.window.Window.IExceptionHandler;
 import org.eclipse.ui.application.WorkbenchAdvisor;
 
 /**
@@ -10,6 +12,14 @@ public class SlcSecureClientApplication extends SecureRcp {
 
        @Override
        protected WorkbenchAdvisor createWorkbenchAdvisor(String username) {
+               Window.setExceptionHandler(new IExceptionHandler() {
+
+                       public void handleException(Throwable t) {
+                               System.err.println("Unexpected SLC UI exception: " + t);
+
+                       }
+               });
+
                return new SlcSecureWorkbenchAdvisor(username);
        }
 
index 866c7f4736703a613c0fc617420dab327f31ef56..229d6d1ab0972bb5db5fe99307035b3efcd9cf9e 100644 (file)
@@ -5,6 +5,5 @@
         http://www.springframework.org/schema/beans/spring-beans.xsd">
 
        <bean id="processController" class="org.argeo.slc.client.ui.controllers.ProcessController">
-<!--           <property name="slcExecutionService" ref="slcExecutionService" /> -->
        </bean>
 </beans>
index 2ddbd7f10287f195d4638a8cbf8db022944fca96..31267a15abac370850b3e3db52e38a54e2749feb 100644 (file)
@@ -7,6 +7,7 @@
        <bean id="processEditor" class="org.argeo.slc.client.ui.editors.ProcessEditor"
                scope="prototype">
                <property name="processController" ref="processController" />
+               <property name="modulesManager" ref="modulesManager" />
                <property name="session">
                        <bean factory-bean="repository" factory-method="login" />
                </property>
index c463e7b57a7347d47b830d6f7a72c56fdd0bfa8b..b2043e29b648beac0b6f1b172126d4b920ff8399 100644 (file)
@@ -4,23 +4,6 @@
        xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd">
 
-       <!-- Views -->
-       <bean id="jcrExecutionModulesView" class="org.argeo.slc.client.ui.views.JcrExecutionModulesView"
-               scope="prototype">
-               <property name="session" ref="session" />
-               <property name="modulesManager" ref="modulesManager"/>
-       </bean>
-
-       <bean id="jcrProcessListView" class="org.argeo.slc.client.ui.views.JcrProcessListView"
-               scope="prototype">
-               <property name="session" ref="session" />
-       </bean>
-
-       <bean id="jcrResultListView" class="org.argeo.slc.client.ui.views.JcrResultListView"
-               scope="prototype">
-               <property name="session" ref="session" />
-       </bean>
-
        <bean id="session" class="org.argeo.jcr.spring.ThreadBoundSession">
                <property name="repository" ref="repository" />
        </bean>
diff --git a/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/listeners.xml b/eclipse/plugins/org.argeo.slc.client.ui/META-INF/spring/listeners.xml
deleted file mode 100644 (file)
index 42ed140..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans
-        http://www.springframework.org/schema/beans/spring-beans.xsd">
-
-<!--   <bean id="testManagerServiceAdapter" -->
-<!--           class="org.argeo.slc.client.ui.listeners.TestManagerServiceAdapter"> -->
-<!--           <property name="testManagerService" ref="testManagerService" /> -->
-<!--   </bean> -->
-
-<!--   <bean id="slcExecutionServiceAdapter" class="org.argeo.slc.services.impl.SlcExecutionServiceAdapter"> -->
-<!--           <property name="slcExecutionService" ref="slcExecutionService" /> -->
-<!--   </bean> -->
-
-</beans>
index 8fb16bda3135fbb3a55c093f1badde34126afeaa..9c4b4a90851ec5916ff06102d2d2a39e42aef022 100644 (file)
@@ -4,52 +4,20 @@
        xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd">
 
-       <!-- Views -->
-<!--   <bean id="executionModulesView" class="org.argeo.slc.client.ui.views.ExecutionModulesView" -->
-<!--           scope="prototype"> -->
-<!--           <property name="contentProvider" ref="executionModulesContentProvider" /> -->
-<!--           <property name="processController" ref="processController" /> -->
-<!--           <property name="oxmBean" ref="oxmBean" /> -->
-<!--   </bean> -->
+       <bean id="jcrExecutionModulesView" class="org.argeo.slc.client.ui.views.JcrExecutionModulesView"
+               scope="prototype">
+               <property name="session" ref="session" />
+               <property name="modulesManager" ref="modulesManager" />
+       </bean>
 
-<!--   <bean id="resultListView" class="org.argeo.slc.client.ui.views.ResultListView" -->
-<!--           scope="prototype"> -->
-<!--           <property name="testResultCollectionDao" ref="testResultCollectionDao" /> -->
-<!--   </bean> -->
+       <bean id="jcrProcessListView" class="org.argeo.slc.client.ui.views.JcrProcessListView"
+               scope="prototype">
+               <property name="session" ref="session" />
+       </bean>
 
-<!--   <bean id="resultDetailView" class="org.argeo.slc.client.ui.views.ResultDetailView" -->
-<!--           scope="prototype"> -->
-<!--           <property name="treeTestResultDao" ref="treeTestResultDao" /> -->
-<!--           <property name="contentProvider" ref="resultDetailContentProvider" /> -->
-<!--           <property name="labelProvider" ref="resultDetailLabelProvider" /> -->
-<!--   </bean> -->
-<!--   <bean id="processListView" class="org.argeo.slc.client.ui.views.ProcessListView" -->
-<!--           scope="prototype"> -->
-<!--           <property name="slcExecutionDao" ref="slcExecutionDao" /> -->
-<!--           <property name="structuredContentProvider" ref="processListStructuredContentProvider" /> -->
-<!--           <property name="tableLabelProvider" ref="processListTableLabelProvider" /> -->
-<!--   </bean> -->
+       <bean id="jcrResultListView" class="org.argeo.slc.client.ui.views.JcrResultListView"
+               scope="prototype">
+               <property name="session" ref="session" />
+       </bean>
 
-<!--   <bean id="processDetailView" class="org.argeo.slc.client.ui.views.ProcessDetailView" -->
-<!--           scope="prototype"> -->
-<!--           <property name="slcExecutionDao" ref="slcExecutionDao" /> -->
-<!--           <property name="contentProvider" ref="processDetailContentProvider" /> -->
-<!--   </bean> -->
-
-<!--   <bean id="processBuilderView" class="org.argeo.slc.client.ui.views.ProcessBuilderView" -->
-<!--           scope="prototype"> -->
-<!--           <property name="processController" ref="processController" /> -->
-<!--           <property name="oxmBean" ref="oxmBean" /> -->
-<!--           <property name="slcAgents" ref="slcAgents" /> -->
-<!--   </bean> -->
-
-<!--   <bean id="processParametersView" class="org.argeo.slc.client.ui.views.ProcessParametersView" -->
-<!--           scope="prototype"> -->
-<!--   </bean> -->
-
-       <!-- Providers. -->
-<!--   <bean id="executionModulesContentProvider" -->
-<!--           class="org.argeo.slc.client.ui.providers.ExecutionModulesContentProvider"> -->
-<!--           <property name="slcAgents" ref="slcAgents" /> -->
-<!--   </bean> -->
 </beans>
index 7d0a76ad552d40c05ac539935481e0a1961d2ce3..328282c54921bb094d29b7671c4954fc6cc6fb3b 100644 (file)
@@ -26,7 +26,7 @@ public class ProcessController {
        private final static Log log = LogFactory.getLog(ProcessController.class);
        private Map<String, SlcAgentFactory> agentFactories = new HashMap<String, SlcAgentFactory>();
 
-       public void process(Node processNode) {
+       public ExecutionProcess process(Node processNode) {
                JcrExecutionProcess process = new JcrExecutionProcess(processNode);
                try {
                        // we currently only deal with single agents
@@ -57,6 +57,7 @@ public class ProcessController {
                                SlcAgent slcAgent = agentFactory.getAgent(agentUuid);
                                slcAgent.process(process);
                        }
+                       return process;
                } catch (Exception e) {
                        if (!process.getStatus().equals(ExecutionProcess.ERROR))
                                process.setStatus(ExecutionProcess.ERROR);
index a5d8676de2a5d479ff16e5600e0f1884b57fa5a9..fc0e4f1c8624fcb26f07eef0b15edfd160020472 100644 (file)
@@ -71,6 +71,7 @@ import org.eclipse.ui.forms.editor.FormPage;
 import org.eclipse.ui.forms.widgets.FormToolkit;
 import org.eclipse.ui.forms.widgets.ScrolledForm;
 
+/** Definition of the process. */
 public class ProcessBuilderPage extends FormPage implements SlcNames {
        public final static String ID = "processBuilderPage";
        // private final static Log log =
index b6df3548e129a9419e728b66da03aaa12f101885..b00b41298f3b545f290307beb4488ad7fcb8f06f 100644 (file)
@@ -1,5 +1,8 @@
 package org.argeo.slc.client.ui.editors;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 
 import javax.jcr.Node;
@@ -11,7 +14,10 @@ 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.ExecutionModulesManager;
 import org.argeo.slc.execution.ExecutionProcess;
+import org.argeo.slc.execution.ExecutionProcessNotifier;
+import org.argeo.slc.execution.ExecutionStep;
 import org.argeo.slc.jcr.SlcJcrUtils;
 import org.argeo.slc.jcr.SlcNames;
 import org.argeo.slc.jcr.SlcTypes;
@@ -21,7 +27,8 @@ 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 class ProcessEditor extends FormEditor implements
+               ExecutionProcessNotifier, SlcTypes, SlcNames {
        public final static String ID = ClientUiPlugin.ID + ".processEditor";
 
        private Session session;
@@ -31,6 +38,8 @@ public class ProcessEditor extends FormEditor implements SlcTypes, SlcNames {
        private ProcessBuilderPage builderPage;
        private ProcessLogPage logPage;
 
+       private ExecutionModulesManager modulesManager;
+
        @Override
        public void init(IEditorSite site, IEditorInput input)
                        throws PartInitException {
@@ -96,7 +105,11 @@ public class ProcessEditor extends FormEditor implements SlcTypes, SlcNames {
                }
                doSave(null);
                try {
-                       processController.process(processNode);
+                       ExecutionProcess process = processController.process(processNode);
+                       Map<String, String> properties = new HashMap<String, String>();
+                       properties.put(ExecutionModulesManager.SLC_PROCESS_ID,
+                                       process.getUuid());
+                       modulesManager.registerProcessNotifier(this, properties);
                } catch (Exception e) {
                        Error.show("Execution of " + processNode + " failed", e);
                }
@@ -142,6 +155,14 @@ public class ProcessEditor extends FormEditor implements SlcTypes, SlcNames {
                return false;
        }
 
+       public void updateStatus(ExecutionProcess process, String oldStatus,
+                       String newStatus) {
+       }
+
+       public void addSteps(ExecutionProcess process, List<ExecutionStep> steps) {
+               logPage.addSteps(steps);
+       }
+
        /** Expects one session per editor. */
        public void setSession(Session session) {
                this.session = session;
@@ -151,4 +172,8 @@ public class ProcessEditor extends FormEditor implements SlcTypes, SlcNames {
                this.processController = processController;
        }
 
+       public void setModulesManager(ExecutionModulesManager modulesManager) {
+               this.modulesManager = modulesManager;
+       }
+
 }
index f50b5b99f988bb2b37224c2ee805fb9535a53b3e..00ad3e48ed43493b791ba1c4109b5842fbe71250 100644 (file)
 package org.argeo.slc.client.ui.editors;
 
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.List;
+
+import org.argeo.slc.execution.ExecutionStep;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.forms.editor.FormEditor;
 import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.FormToolkit;
 
 public class ProcessLogPage extends FormPage {
-       public final static String ID = "processLogrPage";
+       public final static String ID = "processLogPage";
+
+       private DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
+
+       /** Where the log is displayed. */
+       private Text text;
+       /**
+        * Stores logs received before the text was shown. TODO : rather store in in
+        * JCR and reads it from there.
+        */
+       private StringBuffer beforeTextInit = new StringBuffer("");
 
        public ProcessLogPage(FormEditor editor) {
                super(editor, ID, "Log");
        }
 
+       @Override
+       public synchronized void createPartControl(Composite parent) {
+               // bypass createFormContent
+               FormToolkit tk = getEditor().getToolkit();
+               // parent.setLayout(new FillLayout());
+               text = tk.createText(parent, "", SWT.MULTI | SWT.H_SCROLL
+                               | SWT.V_SCROLL);
+               text.setEditable(false);
+               
+               // transfer the existing buffer the first time
+               if (beforeTextInit.length() > 0) {
+                       text.append(beforeTextInit.toString());
+                       // clear buffer
+                       beforeTextInit.setLength(0);
+               }
+
+       }
+
+//     @Override
+//     protected synchronized void createFormContent(IManagedForm mf) {
+//             ScrolledForm form = mf.getForm();
+//             form.setExpandHorizontal(true);
+//             form.setExpandVertical(true);
+//             // form.setText("Log");
+//             FillLayout mainLayout = new FillLayout();
+//             form.getBody().setLayout(mainLayout);
+//
+//             FormToolkit tk = getManagedForm().getToolkit();
+//             text = tk.createText(form.getBody(), "", SWT.MULTI | SWT.H_SCROLL
+//                             | SWT.V_SCROLL);
+//             text.setEditable(false);
+//             // transfer the existing buffer the first time
+//             if (beforeTextInit.length() > 0) {
+//                     text.append(beforeTextInit.toString());
+//                     // clear buffer
+//                     beforeTextInit.setLength(0);
+//             }
+//     }
+
+       public synchronized void addSteps(List<ExecutionStep> steps) {
+               final StringBuffer buf = new StringBuffer("");
+               for (ExecutionStep step : steps) {
+                       buf.append(dateFormat.format(step.getTimestamp()));
+                       buf.append(' ');
+                       if (step.getType().equals(ExecutionStep.PHASE_START)) {
+                               buf.append("## START ").append(step.getLog());
+                               buf.append('\n');
+                       } else if (step.getType().equals(ExecutionStep.PHASE_END)) {
+                               buf.append("## END   ").append(step.getLog());
+                               buf.append("\n");
+                       } else {
+                               buf.append(step.getLog());
+                       }
+               }
+
+               if (text != null) {
+                       Display.getDefault().asyncExec(new Runnable() {
+                               public void run() {
+                                       text.append(buf.toString());
+                               }
+                       });
+               } else
+                       beforeTextInit.append(buf);
+       }
+
+       @Override
+       public Control getPartControl() {
+               return text;
+       }
+
+       @Override
+       public void setFocus() {
+               if (text != null)
+                       text.setFocus();
+       }
+
 }
index 06c05248b2f3c82ec3c25fa89c17ac719937e6d8..3b561392115a27d2e156493383e3d7121adacd36 100644 (file)
@@ -17,6 +17,7 @@
 package org.argeo.slc.core.execution;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -28,9 +29,10 @@ 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.execution.ExecutionProcessNotifier;
+import org.argeo.slc.execution.ExecutionStep;
 import org.argeo.slc.process.RealizedFlow;
 import org.argeo.slc.process.SlcExecutionNotifier;
-import org.argeo.slc.process.SlcExecutionStep;
 
 /** Provides the base feature of an execution module manager. */
 @SuppressWarnings("deprecation")
@@ -41,7 +43,10 @@ public abstract class AbstractExecutionModulesManager implements
 
        private List<SlcExecutionNotifier> slcExecutionNotifiers = new ArrayList<SlcExecutionNotifier>();
 
-       private ThreadGroup processesThreadGroup = new ThreadGroup("Processes");
+       private List<FilteredNotifier> filteredNotifiers = Collections
+                       .synchronizedList(new ArrayList<FilteredNotifier>());
+
+       private ThreadGroup processesThreadGroup = new ThreadGroup("SLC Processes");
 
        protected abstract ExecutionFlow findExecutionFlow(String moduleName,
                        String moduleVersion, String flowName);
@@ -79,30 +84,50 @@ public abstract class AbstractExecutionModulesManager implements
                //
        }
 
-       public void dispatchUpdateStatus(ExecutionProcess slcExecution,
+       public void dispatchUpdateStatus(ExecutionProcess process,
                        String oldStatus, String newStatus) {
+               // generic notifiers (notified of everything)
                for (Iterator<SlcExecutionNotifier> it = getSlcExecutionNotifiers()
                                .iterator(); it.hasNext();) {
-                       it.next().updateStatus(slcExecution, oldStatus, newStatus);
+                       it.next().updateStatus(process, oldStatus, newStatus);
+               }
+
+               // filtered notifiers
+               for (Iterator<FilteredNotifier> it = filteredNotifiers.iterator(); it
+                               .hasNext();) {
+                       FilteredNotifier filteredNotifier = it.next();
+                       if (filteredNotifier.receiveFrom(process))
+                               filteredNotifier.getNotifier().updateStatus(process, oldStatus,
+                                               newStatus);
                }
        }
 
-       public void dispatchAddStep(ExecutionProcess slcExecution,
-                       SlcExecutionStep step) {
-               List<SlcExecutionStep> steps = new ArrayList<SlcExecutionStep>();
-               steps.add(step);
+       public void dispatchAddSteps(ExecutionProcess process,
+                       List<ExecutionStep> steps) {
                for (Iterator<SlcExecutionNotifier> it = getSlcExecutionNotifiers()
                                .iterator(); it.hasNext();) {
-                       it.next().addSteps(slcExecution, steps);
+                       it.next().addSteps(process, steps);
+               }
+
+               for (Iterator<FilteredNotifier> it = filteredNotifiers.iterator(); it
+                               .hasNext();) {
+                       FilteredNotifier filteredNotifier = it.next();
+                       if (filteredNotifier.receiveFrom(process))
+                               filteredNotifier.getNotifier().addSteps(process, steps);
                }
        }
 
+       public void registerProcessNotifier(ExecutionProcessNotifier notifier,
+                       Map<String, String> properties) {
+               filteredNotifiers.add(new FilteredNotifier(notifier, properties));
+       }
+
        public void setSlcExecutionNotifiers(
                        List<SlcExecutionNotifier> slcExecutionNotifiers) {
                this.slcExecutionNotifiers = slcExecutionNotifiers;
        }
 
-       public List<SlcExecutionNotifier> getSlcExecutionNotifiers() {
+       private List<SlcExecutionNotifier> getSlcExecutionNotifiers() {
                return slcExecutionNotifiers;
        }
 
@@ -110,4 +135,45 @@ public abstract class AbstractExecutionModulesManager implements
                return processesThreadGroup;
        }
 
+       protected class FilteredNotifier {
+               private final ExecutionProcessNotifier notifier;
+               private final String processId;
+
+               public FilteredNotifier(ExecutionProcessNotifier notifier,
+                               Map<String, String> properties) {
+                       super();
+                       this.notifier = notifier;
+                       if (properties.containsKey(SLC_PROCESS_ID))
+                               processId = properties.get(SLC_PROCESS_ID);
+                       else
+                               processId = null;
+               }
+
+               /**
+                * Whether event from this process should be received by this listener.
+                */
+               public Boolean receiveFrom(ExecutionProcess process) {
+                       if (processId != null)
+                               if (process.getUuid().equals(processId))
+                                       return true;
+                               else
+                                       return false;
+                       return true;
+               }
+
+               @Override
+               public int hashCode() {
+                       return notifier.hashCode();
+               }
+
+               @Override
+               public boolean equals(Object obj) {
+                       return notifier.equals(obj);
+               }
+
+               public ExecutionProcessNotifier getNotifier() {
+                       return notifier;
+               }
+
+       }
 }
index 52040fd50707a5e604b38ddf86f392d95ae0cb31..b42726dd44d553d27a35bf1222a1680bd3ed0c5d 100644 (file)
@@ -19,8 +19,8 @@ package org.argeo.slc.core.execution;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.slc.execution.ExecutionFlowDescriptor;
+import org.argeo.slc.execution.ExecutionStep;
 import org.argeo.slc.process.RealizedFlow;
-import org.argeo.slc.process.SlcExecutionStep;
 
 /** Thread of a single execution */
 public class ExecutionThread extends Thread {
@@ -51,8 +51,8 @@ public class ExecutionThread extends Thread {
                                .getFlowDescriptor();
                String flowName = executionFlowDescriptor.getName();
 
-               dispatchAddStep(new SlcExecutionStep(SlcExecutionStep.PHASE_START,
-                               "Flow " + flowName));
+               dispatchAddStep(new ExecutionStep(ExecutionStep.PHASE_START, "Flow "
+                               + flowName));
 
                try {
                        String autoUpgrade = System
@@ -68,17 +68,17 @@ public class ExecutionThread extends Thread {
                        // TODO: re-throw exception ?
                        String msg = "Execution of flow " + flowName + " failed.";
                        log.error(msg, e);
-                       dispatchAddStep(new SlcExecutionStep(SlcExecutionStep.ERROR, msg
-                                       + " " + e.getMessage()));
+                       dispatchAddStep(new ExecutionStep(ExecutionStep.ERROR, msg + " "
+                                       + e.getMessage()));
                        processThread.notifyError();
                } finally {
                        processThread.flowCompleted();
-                       dispatchAddStep(new SlcExecutionStep(SlcExecutionStep.PHASE_END,
-                                       "Flow " + flowName));
+                       dispatchAddStep(new ExecutionStep(ExecutionStep.PHASE_END, "Flow "
+                                       + flowName));
                }
        }
 
-       private void dispatchAddStep(SlcExecutionStep step) {
+       private void dispatchAddStep(ExecutionStep step) {
                processThread.getProcessThreadGroup().dispatchAddStep(step);
        }
 
index 61e8c2f2a063c6630cf39aa7f399b65399d0751b..6f0143f0fcca651847610471a71ab0945e0d1b74 100644 (file)
 
 package org.argeo.slc.core.execution;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.argeo.slc.execution.ExecutionModulesManager;
 import org.argeo.slc.execution.ExecutionProcess;
+import org.argeo.slc.execution.ExecutionStep;
 import org.argeo.slc.process.SlcExecution;
 import org.argeo.slc.process.SlcExecutionStep;
 
@@ -38,11 +42,20 @@ public class ProcessThreadGroup extends ThreadGroup {
        // return processThread.getSlcProcess();
        // }
 
-       public void dispatchAddStep(SlcExecutionStep step) {
+       public void dispatchAddStep(ExecutionStep step) {
+               // legacy
                ExecutionProcess slcProcess = processThread.getProcess();
                if (slcProcess instanceof SlcExecution)
-                       ((SlcExecution) slcProcess).getSteps().add(step);
-               executionModulesManager.dispatchAddStep(slcProcess, step);
+                       ((SlcExecution) slcProcess).getSteps().add((SlcExecutionStep) step);
+
+               List<ExecutionStep> steps = new ArrayList<ExecutionStep>();
+               steps.add(step);
+               dispatchAddSteps(steps);
+       }
+
+       public void dispatchAddSteps(List<ExecutionStep> steps) {
+               ExecutionProcess slcProcess = processThread.getProcess();
+               executionModulesManager.dispatchAddSteps(slcProcess, steps);
        }
 
 }
index 4400a18f2fe62000aa796afa7966aabb56618359..88a8b2bfec6d8f55a574415b3976ac63ebba8d1b 100644 (file)
@@ -17,6 +17,7 @@
 package org.argeo.slc.execution;
 
 import java.util.List;
+import java.util.Map;
 
 import org.argeo.slc.deploy.ModulesManager;
 import org.argeo.slc.process.RealizedFlow;
@@ -24,6 +25,9 @@ import org.argeo.slc.process.SlcExecutionStep;
 
 /** Provides access to the execution modules */
 public interface ExecutionModulesManager extends ModulesManager {
+       /** Used to filter event notified to an execution notifier. */
+       public static String SLC_PROCESS_ID = "slc.process.id";
+
        /** @return a full fledged module descriptor. */
        public ExecutionModuleDescriptor getExecutionModuleDescriptor(
                        String moduleName, String version);
@@ -45,5 +49,13 @@ public interface ExecutionModulesManager extends ModulesManager {
                        String oldStatus, String newStatus);
 
        /** Notify that a step was added in an {@link ExecutionProcess} */
-       public void dispatchAddStep(ExecutionProcess process, SlcExecutionStep step);
+       public void dispatchAddSteps(ExecutionProcess process,
+                       List<ExecutionStep> steps);
+
+       /**
+        * Register a notifier which will be notified based on the provided
+        * properties.
+        */
+       public void registerProcessNotifier(ExecutionProcessNotifier notifier,
+                       Map<String, String> properties);
 }
index 9bfdaf98fed5bd16d1b1561f3a1995e83b18fffb..e2466ec81f114e957ba309a7da1053f62dfe7aa3 100644 (file)
@@ -2,13 +2,19 @@ package org.argeo.slc.execution;
 
 import java.util.List;
 
-import org.argeo.slc.process.SlcExecutionStep;
-
+/**
+ * Implementations of this interface can be notified of events related to
+ * process execution.
+ */
 public interface ExecutionProcessNotifier {
-       public void addSteps(ExecutionProcess process,
-                       List<SlcExecutionStep> additionalSteps);
-
+       /**
+        * Notify a status change, see {@link ExecutionProcess} for the list of
+        * vaailable statuses.
+        */
        public void updateStatus(ExecutionProcess process, String oldStatus,
                        String newStatus);
 
+       /** Notifiy of new execution steps. */
+       public void addSteps(ExecutionProcess process, List<ExecutionStep> steps);
+
 }
diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionStep.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionStep.java
new file mode 100644 (file)
index 0000000..df2d805
--- /dev/null
@@ -0,0 +1,103 @@
+/*\r
+ * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package org.argeo.slc.execution;\r
+\r
+import java.io.Serializable;\r
+import java.util.Date;\r
+\r
+/**\r
+ * An atomic step to be notified in during an {@link ExecutionProcess}. Can be a\r
+ * log or the start/end of a phase, etc.\r
+ */\r
+public class ExecutionStep implements Serializable {\r
+       private static final long serialVersionUID = 798640526532912161L;\r
+\r
+       // public final static String START = "START";\r
+       // public final static String END = "END";\r
+       public final static String PHASE_START = "PHASE_START";\r
+       public final static String PHASE_END = "PHASE_END";\r
+       public final static String ERROR = "ERROR";\r
+       public final static String WARNING = "WARNING";\r
+       public final static String INFO = "INFO";\r
+       public final static String DEBUG = "DEBUG";\r
+       public final static String TRACE = "TRACE";\r
+\r
+       // TODO make the fields final and private when we don't need POJO support\r
+       // anymore (that\r
+       // is when SlcExecutionStep is removed)\r
+       protected String type;\r
+       protected String thread;\r
+       protected Date timestamp;\r
+       protected String log;\r
+\r
+       /** Empty constructor */\r
+       public ExecutionStep() {\r
+               thread = Thread.currentThread().getName();\r
+       }\r
+\r
+       /** Creates a step at the current date of type INFO */\r
+       public ExecutionStep(String log) {\r
+               this(new Date(), INFO, log);\r
+       }\r
+\r
+       /** Creates a step at the current date */\r
+       public ExecutionStep(String type, String log) {\r
+               this(new Date(), type, log);\r
+       }\r
+\r
+       /** Creates a step of the given type. */\r
+       public ExecutionStep(Date timestamp, String type, String log) {\r
+               this(timestamp, type, log, Thread.currentThread().getName());\r
+       }\r
+\r
+       public ExecutionStep(Date timestamp, String type, String log, String thread) {\r
+               this.type = type;\r
+               this.timestamp = timestamp;\r
+               this.thread = thread;\r
+               this.log = addLog(log);\r
+       }\r
+\r
+       public String getType() {\r
+               return type;\r
+       }\r
+\r
+       public Date getTimestamp() {\r
+               return timestamp;\r
+       }\r
+\r
+       public String getThread() {\r
+               return thread;\r
+       }\r
+\r
+       /**\r
+        * Return the string that should be stored in the log field. Can be null if\r
+        * another mechanism is used to store log lines.\r
+        */\r
+       protected String addLog(String log) {\r
+               return log;\r
+       }\r
+\r
+       public String getLog() {\r
+               return log;\r
+       }\r
+\r
+       @Override\r
+       public String toString() {\r
+               return "Execution step, thread=" + thread + ", type=" + type;\r
+       }\r
+\r
+}\r
index 58f9d01a072d63f3f7ed378d418e99c893a0f2d5..cc1dc7f2d6bbca134185db92116d5a51019727d9 100644 (file)
 \r
 package org.argeo.slc.process;\r
 \r
-import java.io.Serializable;\r
 import java.util.ArrayList;\r
 import java.util.Date;\r
 import java.util.List;\r
 import java.util.StringTokenizer;\r
 import java.util.UUID;\r
 \r
+import org.argeo.slc.execution.ExecutionStep;\r
+\r
 /**\r
  * An atomic step to be notified in during an {@link SlcExecution}. Can be a log\r
  * or the start/end of a phase, etc.\r
+ * \r
+ * @deprecated use {@link ExecutionStep} instead\r
  */\r
-public class SlcExecutionStep implements Serializable {\r
+public class SlcExecutionStep extends ExecutionStep {\r
        private static final long serialVersionUID = -7308643628104726471L;\r
 \r
-       public final static String START = "START";\r
-       public final static String END = "END";\r
-       public final static String PHASE_START = "PHASE_START";\r
-       public final static String PHASE_END = "PHASE_END";\r
-       public final static String ERROR = "ERROR";\r
-       public final static String WARNING = "WARNING";\r
-       public final static String INFO = "INFO";\r
-       public final static String DEBUG = "DEBUG";\r
-       public final static String TRACE = "TRACE";\r
-\r
        private String uuid = UUID.randomUUID().toString();\r
-       private String type;\r
-       private String thread;\r
-       private Date timestamp = new Date();\r
        private List<String> logLines = new ArrayList<String>();\r
 \r
        /** Empty constructor */\r
        public SlcExecutionStep() {\r
-               thread = Thread.currentThread().getName();\r
        }\r
 \r
        /** Creates a step at the current date of type INFO */\r
@@ -68,10 +57,7 @@ public class SlcExecutionStep implements Serializable {
 \r
        public SlcExecutionStep(Date timestamp, String type, String log,\r
                        String thread) {\r
-               this.type = type;\r
-               this.timestamp = timestamp;\r
-               this.thread = thread;\r
-               addLog(log);\r
+               super(timestamp, type, log, thread);\r
        }\r
 \r
        public String getUuid() {\r
@@ -82,26 +68,14 @@ public class SlcExecutionStep implements Serializable {
                this.uuid = uuid;\r
        }\r
 \r
-       public String getType() {\r
-               return type;\r
-       }\r
-\r
        public void setType(String type) {\r
                this.type = type;\r
        }\r
 \r
-       public Date getTimestamp() {\r
-               return timestamp;\r
-       }\r
-\r
        public void setTimestamp(Date begin) {\r
                this.timestamp = begin;\r
        }\r
 \r
-       public String getThread() {\r
-               return thread;\r
-       }\r
-\r
        public void setThread(String thread) {\r
                this.thread = thread;\r
        }\r
@@ -114,13 +88,17 @@ public class SlcExecutionStep implements Serializable {
                this.logLines = logLines;\r
        }\r
 \r
-       public void addLog(String log) {\r
+       protected String addLog(String log) {\r
+               if (logLines == null)\r
+                       logLines = new ArrayList<String>();\r
+\r
                if (log == null)\r
-                       return;\r
+                       return null;\r
 \r
                StringTokenizer st = new StringTokenizer(log, "\n");\r
                while (st.hasMoreTokens())\r
                        logLines.add(removeNonXmlChars(st.nextToken()));\r
+               return null;\r
        }\r
 \r
        /**\r
index a40c98e5ac29cc2320e9b78a068f54bc139847b9..880aefef1f51b27e3a4a7100e6407629495bc018 100644 (file)
@@ -26,7 +26,7 @@ import org.apache.log4j.PatternLayout;
 import org.apache.log4j.spi.LoggingEvent;
 import org.argeo.slc.core.execution.ExecutionThread;
 import org.argeo.slc.core.execution.ProcessThreadGroup;
-import org.argeo.slc.process.SlcExecutionStep;
+import org.argeo.slc.execution.ExecutionStep;
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.beans.factory.InitializingBean;
 
@@ -96,20 +96,20 @@ public class SlcExecutionAppender extends AppenderSkeleton implements
                        final String type;
                        if (event.getLevel().equals(Level.ERROR)
                                        || event.getLevel().equals(Level.FATAL))
-                               type = SlcExecutionStep.ERROR;
+                               type = ExecutionStep.ERROR;
                        else if (event.getLevel().equals(Level.WARN))
-                               type = SlcExecutionStep.WARNING;
+                               type = ExecutionStep.WARNING;
                        else if (event.getLevel().equals(Level.INFO))
-                               type = SlcExecutionStep.INFO;
+                               type = ExecutionStep.INFO;
                        else if (event.getLevel().equals(Level.DEBUG))
-                               type = SlcExecutionStep.DEBUG;
+                               type = ExecutionStep.DEBUG;
                        else if (event.getLevel().equals(Level.TRACE))
-                               type = SlcExecutionStep.TRACE;
+                               type = ExecutionStep.TRACE;
                        else
-                               type = SlcExecutionStep.INFO;
+                               type = ExecutionStep.INFO;
 
-                       SlcExecutionStep step = new SlcExecutionStep(new Date(event
-                                       .getTimeStamp()), type, layout.format(event));
+                       ExecutionStep step = new ExecutionStep(new Date(
+                                       event.getTimeStamp()), type, layout.format(event));
 
                        try {
                                dispatching.set(true);