View Javadoc

1   /**
2    * This file Copyright (c) 2003-2011 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.workflow.flows;
35  
36  import info.magnolia.cms.beans.config.ContentRepository;
37  import info.magnolia.cms.core.Content;
38  import info.magnolia.cms.core.ItemType;
39  import info.magnolia.cms.core.HierarchyManager;
40  import info.magnolia.cms.util.ContentUtil;
41  import info.magnolia.cms.util.NodeDataUtil;
42  import info.magnolia.context.MgnlContext;
43  import info.magnolia.context.WebContextImpl;
44  import info.magnolia.module.workflow.WorkflowConstants;
45  
46  import java.io.IOException;
47  import java.io.InputStream;
48  import java.io.StringReader;
49  import java.net.MalformedURLException;
50  import java.net.URL;
51  import java.net.URLConnection;
52  import java.text.MessageFormat;
53  import java.util.ArrayList;
54  import java.util.Collection;
55  import java.util.Collections;
56  import java.util.Iterator;
57  import java.util.List;
58  
59  import javax.jcr.RepositoryException;
60  import javax.servlet.http.HttpServletRequest;
61  
62  import openwfe.org.engine.workitem.LaunchItem;
63  
64  import org.apache.commons.lang.StringUtils;
65  import org.jdom.Document;
66  import org.jdom.Element;
67  import org.slf4j.Logger;
68  import org.slf4j.LoggerFactory;
69  
70  /**
71   * Read and store flows in the repositories.
72   * @author philipp
73   */
74  public class DefaultFlowDefinitionManager implements FlowDefinitionManager {
75  
76      private static Logger log = LoggerFactory.getLogger(DefaultFlowDefinitionManager.class);
77  
78      private boolean saveWorkflowDefinitionInWorkItem = true;
79  
80      private String flowDefinitionURLPattern;
81  
82      public void configure(LaunchItem launchItem, String workflowName) throws FlowDefinitionException {
83          if(saveWorkflowDefinitionInWorkItem){
84              launchItem.setWorkflowDefinitionUrl(WorkflowConstants.ATTRIBUTE_WORKFLOW_DEFINITION_URL);
85              String flowDef = readDefinition(workflowName);
86              launchItem.getAttributes().puts(WorkflowConstants.ATTRIBUTE_DEFINITION, flowDef);
87          }
88          else{
89              InputStream is = null;
90              String surl = getFlowDefinitionURLPattern();
91              surl = MessageFormat.format(surl, new String[]{workflowName});
92              try {
93                  URL url = new URL(surl);
94                  URLConnection connection = url.openConnection();
95                  connection.connect();
96                  is = connection.getInputStream();
97                  launchItem.setWorkflowDefinitionUrl(surl);
98              }
99              catch (MalformedURLException e) {
100                 throw new FlowDefinitionException("can't use workflow name [" + workflowName + "] because the url[" + surl + "] is not an url", e);
101             }
102             catch (IOException e) {
103                 throw new FlowDefinitionException("can't use workflow name [" + workflowName + "] because the url[" + surl + "] is not accessible", e);
104             }
105             finally {
106                 try {if(is!=null) is.close();} catch(Exception e) {/*just try to close any open stream*/}
107             }
108 
109         }
110     }
111 
112     public String readDefinition(String workflowName) throws FlowDefinitionException {
113         Content node;
114         try {
115             node = getDefinitionNode(workflowName);
116         }
117         catch (RepositoryException e) {
118             throw new FlowDefinitionException("can't read workflow definition [" + workflowName + "]", e);
119         }
120         if (node == null){
121             throw new FlowDefinitionException("can't read workflow definition [" + workflowName + "]") ;
122         }
123         return node.getNodeData("value").getString();
124     }
125 
126     /**
127      * find one flow node by flow name.
128      * @return Content node in JCR store for specified flow definition
129      */
130     public Content getDefinitionNode(String name) throws RepositoryException {
131         if (name == null) {
132             return null;
133         }
134         return ContentUtil.getContent(ContentRepository.CONFIG, WorkflowConstants.ROOT_PATH_FOR_FLOW + "/"+ name);
135     }
136 
137     public void saveDefinition(String definition) throws FlowDefinitionException {
138         saveDefinition(extractWorkflowName(definition), definition);
139     }
140 
141     protected void saveDefinition(String workflowName, String definition) throws FlowDefinitionException {
142         if (definition == null) {
143             return;
144         }
145 
146         try {
147             HierarchyManager hm = MgnlContext.getSystemContext().getHierarchyManager(ContentRepository.CONFIG);
148             Content root = hm.getContent(WorkflowConstants.ROOT_PATH_FOR_FLOW);
149 
150             // check if the node already exist, and if it does update the value of the the NodeData FLOW_VALUE with the
151             // new flow. This is to allow duplication of flow node.
152 
153             final Content wfNode = ContentUtil.getOrCreateContent(root, workflowName, ItemType.CONTENTNODE);
154             NodeDataUtil.getOrCreateAndSet(wfNode, WorkflowConstants.FLOW_VALUE, definition);
155 
156             root.save();
157             log.info("New flow added: " + workflowName);
158         }
159         catch (Exception e) {
160             throw new FlowDefinitionException("can't add flow", e);
161         }
162     }
163 
164     protected String extractWorkflowName(String definition) throws FlowDefinitionException {
165         try {
166             // jdom
167             final org.jdom.input.SAXBuilder builder = new org.jdom.input.SAXBuilder();
168             Document doc = builder.build(new StringReader(definition));
169             Element process_definition = doc.getRootElement();
170             return process_definition.getAttribute("name").getValue();
171         }
172         catch(Exception e){
173             throw new FlowDefinitionException("can't extract name out of the definition", e);
174         }
175     }
176 
177     public List getDefinitionNames(){
178         ArrayList list = new ArrayList();
179 
180         HierarchyManager hm = MgnlContext.getSystemContext().getHierarchyManager(ContentRepository.CONFIG);
181         Content root;
182         try {
183             root = hm.getContent(WorkflowConstants.ROOT_PATH_FOR_FLOW);
184         }
185         catch (RepositoryException e) {
186             log.error("can't read flow definitions", e);
187             return Collections.EMPTY_LIST;
188         }
189         // get the leaves
190         Collection c =  ContentUtil.getAllChildren(root);
191 
192         Iterator it = c.iterator();
193         while (it.hasNext()) {
194             String name = ((Content) (it.next())).getName();
195             if (name != null) {
196                 list.add(name);
197             }
198         }
199 
200         return list;
201     }
202 
203     public String getFlowDefinitionURLPattern() {
204         if (StringUtils.isEmpty(flowDefinitionURLPattern) || flowDefinitionURLPattern.equals("auto")) {
205             WebContextImpl impl = (WebContextImpl) MgnlContext.getInstance();
206             HttpServletRequest request = impl.getRequest();
207 
208             StringBuffer baseurl = new StringBuffer();
209             baseurl.append("http");
210             if(request.isSecure()){
211                 baseurl.append("s");
212             }
213             baseurl.append("://");
214             baseurl.append(request.getServerName());
215             baseurl.append(":");
216             baseurl.append(request.getServerPort());
217             baseurl.append(impl.getContextPath());
218             baseurl.append("/.magnolia/pages/flows.html");
219             baseurl.append("?command=showFlow&flowName=");
220             baseurl.append("{0}");
221             flowDefinitionURLPattern = baseurl.toString();
222         }
223 
224         return this.flowDefinitionURLPattern;
225     }
226 
227 
228     public void setFlowDefinitionURLPattern(String flowDefinitionURLPattern) {
229         this.flowDefinitionURLPattern = flowDefinitionURLPattern;
230     }
231 
232 }