KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > opensymphony > workflow > loader > XMLWorkflowFactory


1 /*
2  * Copyright (c) 2002-2003 by OpenSymphony
3  * All rights reserved.
4  */

5 package com.opensymphony.workflow.loader;
6
7 import com.opensymphony.workflow.FactoryException;
8 import com.opensymphony.workflow.InvalidWorkflowDescriptorException;
9
10 import org.w3c.dom.*;
11
12 import java.io.*;
13
14 import java.net.URL JavaDoc;
15
16 import java.util.*;
17
18 import javax.xml.parsers.*;
19
20
21 /**
22  * @author Hani Suleiman
23  * Date: May 10, 2002
24  * Time: 11:30:41 AM
25  */

26 public class XMLWorkflowFactory extends AbstractWorkflowFactory {
27     //~ Instance fields ////////////////////////////////////////////////////////
28

29     protected Map workflows;
30     protected boolean reload;
31
32     //~ Methods ////////////////////////////////////////////////////////////////
33

34     public WorkflowDescriptor getWorkflow(String JavaDoc name) throws FactoryException {
35         WorkflowConfig c = (WorkflowConfig) workflows.get(name);
36
37         if (c == null) {
38             throw new FactoryException("Unknown workflow name \"" + name + "\"");
39         }
40
41         if (c.descriptor != null) {
42             if (reload) {
43                 File file = new File(c.url.getFile());
44
45                 if (file.exists() && (file.lastModified() > c.lastModified)) {
46                     c.lastModified = file.lastModified();
47                     loadWorkflow(c);
48                 }
49             }
50         } else {
51             loadWorkflow(c);
52         }
53
54         return c.descriptor;
55     }
56
57     public String JavaDoc[] getWorkflowNames() {
58         int i = 0;
59         String JavaDoc[] res = new String JavaDoc[workflows.keySet().size()];
60         Iterator it = workflows.keySet().iterator();
61
62         while (it.hasNext()) {
63             res[i++] = (String JavaDoc) it.next();
64         }
65
66         return res;
67     }
68
69     public void initDone() throws FactoryException {
70         reload = getProperties().getProperty("reload", "false").equals("true");
71
72         ClassLoader JavaDoc classLoader = Thread.currentThread().getContextClassLoader();
73         InputStream is = null;
74         String JavaDoc name = getProperties().getProperty("resource", "workflows.xml");
75
76         if ((name != null) && (name.indexOf(":/") > -1)) {
77             try {
78                 is = new URL JavaDoc(name).openStream();
79             } catch (Exception JavaDoc e) {
80             }
81         }
82
83         if (is == null) {
84             try {
85                 is = classLoader.getResourceAsStream(name);
86             } catch (Exception JavaDoc e) {
87             }
88         }
89
90         if (is == null) {
91             try {
92                 is = classLoader.getResourceAsStream("/" + name);
93             } catch (Exception JavaDoc e) {
94             }
95         }
96
97         if (is == null) {
98             try {
99                 is = classLoader.getResourceAsStream("META-INF/" + name);
100             } catch (Exception JavaDoc e) {
101             }
102         }
103
104         if (is == null) {
105             try {
106                 is = classLoader.getResourceAsStream("/META-INF/" + name);
107             } catch (Exception JavaDoc e) {
108             }
109         }
110
111         try {
112             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
113             dbf.setNamespaceAware(true);
114
115             DocumentBuilder db = null;
116
117             try {
118                 db = dbf.newDocumentBuilder();
119             } catch (ParserConfigurationException e) {
120                 throw new FactoryException("Error creating document builder", e);
121             }
122
123             Document doc = db.parse(is);
124
125             Element root = (Element) doc.getElementsByTagName("workflows").item(0);
126             workflows = new HashMap();
127
128             List list = XMLUtil.getChildElements(root, "workflow");
129
130             for (int i = 0; i < list.size(); i++) {
131                 Element e = (Element) list.get(i);
132                 WorkflowConfig config = new WorkflowConfig(e.getAttribute("type"), e.getAttribute("location"));
133                 workflows.put(e.getAttribute("name"), config);
134             }
135         } catch (Exception JavaDoc e) {
136             throw new InvalidWorkflowDescriptorException("Error in workflow config", e);
137         }
138     }
139
140     public boolean removeWorkflow(String JavaDoc name) throws FactoryException {
141         throw new FactoryException("remove workflow not supported");
142
143         //WorkflowConfig workflow = (WorkflowConfig)workflows.remove(name);
144
//if(workflow == null) return false;
145
//if(workflow.descriptor != null)
146
//{
147
//
148
//}
149
//return true;
150
}
151
152     public boolean saveWorkflow(String JavaDoc name, WorkflowDescriptor descriptor, boolean replace) throws FactoryException {
153         WorkflowConfig c = (WorkflowConfig) workflows.get(name);
154
155         if ((c != null) && !replace) {
156             return false;
157         }
158
159         if (c == null) {
160             throw new UnsupportedOperationException JavaDoc("Saving of new workflow is not currently supported");
161         }
162
163         Writer out;
164         descriptor.validate();
165
166         try {
167             out = new OutputStreamWriter(new FileOutputStream(c.url.getFile() + ".new"), "utf-8");
168         } catch (FileNotFoundException ex) {
169             throw new FactoryException("Could not create new file to save workflow " + c.url.getFile());
170         } catch (UnsupportedEncodingException ex) {
171             throw new FactoryException("utf-8 encoding not supported, contact your JVM vendor!");
172         }
173
174         writeXML(descriptor, out);
175
176         //write it out to a new file, to ensure we don't end up with a messed up file if we're interrupted halfway for some reason
177
//now lets rename
178
File original = new File(c.url.getFile());
179         File backup = new File(c.url.getFile() + ".bak");
180         File updated = new File(c.url.getFile() + ".new");
181         boolean isOK = !original.exists() || original.renameTo(backup);
182
183         if (!isOK) {
184             throw new FactoryException("Unable to backup original workflow file " + original + " to " + backup + ", aborting save");
185         }
186
187         isOK = updated.renameTo(original);
188
189         if (!isOK) {
190             throw new FactoryException("Unable to rename new workflow file " + updated + " to " + original + ", aborting save");
191         }
192
193         backup.delete();
194
195         return true;
196     }
197
198     protected void save() {
199     }
200
201     protected void writeXML(WorkflowDescriptor descriptor, Writer out) {
202         PrintWriter writer = new PrintWriter(new BufferedWriter(out));
203         writer.println(WorkflowDescriptor.XML_HEADER);
204         writer.println(WorkflowDescriptor.DOCTYPE_DECL);
205         descriptor.writeXML(writer, 0);
206         writer.flush();
207         writer.close();
208     }
209
210     private void loadWorkflow(WorkflowConfig c) throws FactoryException {
211         try {
212             c.descriptor = WorkflowLoader.load(c.url);
213         } catch (Exception JavaDoc e) {
214             throw new FactoryException("Error in workflow descriptor: " + c.url, e);
215         }
216     }
217
218     //~ Inner Classes //////////////////////////////////////////////////////////
219

220     class WorkflowConfig {
221         String JavaDoc location;
222         String JavaDoc type;
223         URL JavaDoc url;
224         WorkflowDescriptor descriptor;
225         long lastModified;
226
227         public WorkflowConfig(String JavaDoc type, String JavaDoc location) {
228             if ("URL".equals(type)) {
229                 try {
230                     url = new URL JavaDoc(location);
231
232                     File file = new File(url.getFile());
233
234                     if (file.exists()) {
235                         lastModified = file.lastModified();
236                     }
237                 } catch (Exception JavaDoc ex) {
238                 }
239             } else if ("file".equals(type)) {
240                 try {
241                     File file = new File(location);
242                     url = file.toURL();
243                     lastModified = file.lastModified();
244                 } catch (Exception JavaDoc ex) {
245                 }
246             } else {
247                 url = Thread.currentThread().getContextClassLoader().getResource(location);
248             }
249
250             this.type = type;
251             this.location = location;
252         }
253     }
254 }
255
Popular Tags