Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 7th, 2012  |  syntax: None  |  size: 6.26 KB  |  hits: 14  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /**
  2.  *  Copyright 2009, 2010 The Regents of the University of California
  3.  *  Licensed under the Educational Community License, Version 2.0
  4.  *  (the "License"); you may not use this file except in compliance
  5.  *  with the License. You may obtain a copy of the License at
  6.  *
  7.  *  http://www.osedu.org/licenses/ECL-2.0
  8.  *
  9.  *  Unless required by applicable law or agreed to in writing,
  10.  *  software distributed under the License is distributed on an "AS IS"
  11.  *  BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  12.  *  or implied. See the License for the specific language governing
  13.  *  permissions and limitations under the License.
  14.  *
  15.  */
  16. package org.opencastproject.workflow.handler;
  17.  
  18. import org.opencastproject.mediapackage.MediaPackage;
  19. import org.opencastproject.workflow.api.WorkflowBuilder;
  20. import org.opencastproject.workflow.api.WorkflowInstance;
  21. import org.opencastproject.workflow.api.WorkflowOperationException;
  22. import org.opencastproject.workflow.api.WorkflowOperationHandler;
  23. import org.opencastproject.workflow.api.WorkflowOperationInstance;
  24. import org.opencastproject.workflow.api.WorkflowOperationResult;
  25. import org.opencastproject.workflow.api.WorkflowOperationResult.Action;
  26. import org.opencastproject.workspace.api.Workspace;
  27.  
  28. import org.slf4j.Logger;
  29. import org.slf4j.LoggerFactory;
  30.  
  31. import java.io.IOException;
  32. import java.io.InputStream;
  33. import java.util.Arrays;
  34. import java.util.LinkedList;
  35. import java.util.List;
  36. import java.util.SortedMap;
  37. import java.util.TreeMap;
  38.  
  39. /**
  40.  *
  41.  */
  42. // TODO: Change the throwing of workflowoperationexceptions to throwing some suitable subclass so
  43. // the caller can switch on errors as appropriate.
  44. public class CLIWorkflowOperationHandler implements WorkflowOperationHandler {
  45.  
  46.   /** The logging facility */
  47.   private static final Logger logger = LoggerFactory.getLogger(CLIWorkflowOperationHandler.class);
  48.  
  49.   /** The local workspace */
  50.   private Workspace workspace = null;
  51.  
  52.   /** The configuration options for this handler */
  53.   private static final SortedMap<String, String> CONFIG_OPTIONS;
  54.  
  55.   static {
  56.     CONFIG_OPTIONS = new TreeMap<String, String>();
  57.     CONFIG_OPTIONS.put("exec", "The full path the executable to run");
  58.     CONFIG_OPTIONS.put("params", "Space separated list of command line parameters to pass to the executable')");
  59.   }
  60.  
  61.   /**
  62.    * Callback for declarative services configuration that will introduce us to the local workspace service.
  63.    * Implementation assumes that the reference is configured as being static.
  64.    *
  65.    * @param workspace
  66.    *          an instance of the workspace
  67.    */
  68.   public void setWorkspace(Workspace workspace) {
  69.     this.workspace = workspace;
  70.   }
  71.  
  72.   /**
  73.    * {@inheritDoc}
  74.    *
  75.    * @see org.opencastproject.workflow.api.WorkflowOperationHandler#start(org.opencastproject.workflow.api.WorkflowInstance)
  76.    */
  77.   @Override
  78.   public WorkflowOperationResult start(WorkflowInstance workflowInstance) throws WorkflowOperationException {
  79.  
  80.     WorkflowOperationInstance operation = workflowInstance.getCurrentOperation();
  81.  
  82.     // MediaPackage from previous workflow operations
  83.     MediaPackage srcPackage = (MediaPackage) workflowInstance.getMediaPackage().clone();
  84.     // Modified media package from our operation, if any
  85.     MediaPackage resultPackage = null;
  86.     // Executable attempting to be invoked
  87.     String exec = operation.getConfiguration("exec");
  88.     // Parameters, like argv[]
  89.     String params = operation.getConfiguration("params");
  90.  
  91.     // Verify that the executable is not null
  92.     if ((exec == null) || (exec == "")) {
  93.       logger.info("Executable parameter from workflow document is either null or empty: " + exec);
  94.       throw new WorkflowOperationException("Invalid exec param: " + exec);
  95.     }
  96.  
  97.     // Start the external process
  98.     List<String> args = new LinkedList<String>();
  99.     args.add(exec);
  100.     args.addAll(Arrays.asList(" "));
  101.  
  102.     Process p = null;
  103.     try {
  104.       p = Runtime.getRuntime().exec(args.toArray(new String[0]));
  105.     } catch (IOException e) {
  106.       // Only log the first argument, the executable, as other arguments may contain sensative values
  107.       // e.g. MySQL password/user, paths, etc. that should not be shown to caller
  108.       logger.error("Could not start subprocess {}", args.get(0));
  109.       throw new WorkflowOperationException("Could not start subprocess: " + args.get(0));
  110.     }
  111.     // Attempt to read the output of the command and parse it as a media package
  112.     try {
  113.       InputStream in = p.getInputStream();
  114.       StringBuffer sb = new StringBuffer();
  115.       int c;
  116.       while ((c = in.read()) != -1) {
  117.         sb.append(c);
  118.       }
  119.       in.close();
  120.  
  121.       // If the response is a media package set the response to it
  122.       // TODO
  123.  
  124.     } catch (IOException e) {
  125.       logger.debug("Unable to read output from subprocess.", e);
  126.     }
  127.  
  128.     // On error return code throw to caller
  129.     int returnCode = 0;
  130.     try {
  131.       returnCode = p.waitFor();
  132.     } catch (InterruptedException e) {
  133.       throw new WorkflowOperationException("Workflow handler thread interrupted before external process ended.");
  134.     }
  135.     if (returnCode != 0) {
  136.       logger.warn("Non-zero return code from external process");
  137.       throw new WorkflowOperationException("Non-zero return code from external process: " + String.valueOf(returnCode));
  138.     }
  139.  
  140.     // If there is no resultant mediapackage, pass back the one that was provided to us
  141.     if (resultPackage == null) {
  142.       return WorkflowBuilder.getInstance().buildWorkflowOperationResult(srcPackage, Action.CONTINUE);
  143.     }
  144.     return WorkflowBuilder.getInstance().buildWorkflowOperationResult(resultPackage, Action.CONTINUE);
  145.   }
  146.  
  147.   @Override
  148.   public String getId() {
  149.     return "cli";
  150.   }
  151.  
  152.   @Override
  153.   public String getDescription() {
  154.     return "Executes command line workflow operations";
  155.   }
  156.  
  157.   @Override
  158.   public void destroy(WorkflowInstance workflowInstance) throws WorkflowOperationException {
  159.     // Do nothing (nothing to clean up, the command line program should do this itself)
  160.   }
  161.  
  162.   /**
  163.    * {@inheritDoc}
  164.    *
  165.    * @see org.opencastproject.workflow.api.WorkflowOperationHandler#getConfigurationOptions()
  166.    */
  167.   @Override
  168.   public SortedMap<String, String> getConfigurationOptions() {
  169.     return CONFIG_OPTIONS;
  170.   }
  171.  
  172. }