1 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 ; 15 16 import java.util.*; 17 18 import javax.xml.parsers.*; 19 20 21 26 public class XMLWorkflowFactory extends AbstractWorkflowFactory { 27 29 protected Map workflows; 30 protected boolean reload; 31 32 34 public WorkflowDescriptor getWorkflow(String 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 [] getWorkflowNames() { 58 int i = 0; 59 String [] res = new String [workflows.keySet().size()]; 60 Iterator it = workflows.keySet().iterator(); 61 62 while (it.hasNext()) { 63 res[i++] = (String ) 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 classLoader = Thread.currentThread().getContextClassLoader(); 73 InputStream is = null; 74 String name = getProperties().getProperty("resource", "workflows.xml"); 75 76 if ((name != null) && (name.indexOf(":/") > -1)) { 77 try { 78 is = new URL (name).openStream(); 79 } catch (Exception e) { 80 } 81 } 82 83 if (is == null) { 84 try { 85 is = classLoader.getResourceAsStream(name); 86 } catch (Exception e) { 87 } 88 } 89 90 if (is == null) { 91 try { 92 is = classLoader.getResourceAsStream("/" + name); 93 } catch (Exception e) { 94 } 95 } 96 97 if (is == null) { 98 try { 99 is = classLoader.getResourceAsStream("META-INF/" + name); 100 } catch (Exception e) { 101 } 102 } 103 104 if (is == null) { 105 try { 106 is = classLoader.getResourceAsStream("/META-INF/" + name); 107 } catch (Exception 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 e) { 136 throw new InvalidWorkflowDescriptorException("Error in workflow config", e); 137 } 138 } 139 140 public boolean removeWorkflow(String name) throws FactoryException { 141 throw new FactoryException("remove workflow not supported"); 142 143 } 151 152 public boolean saveWorkflow(String 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 ("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 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 e) { 214 throw new FactoryException("Error in workflow descriptor: " + c.url, e); 215 } 216 } 217 218 220 class WorkflowConfig { 221 String location; 222 String type; 223 URL url; 224 WorkflowDescriptor descriptor; 225 long lastModified; 226 227 public WorkflowConfig(String type, String location) { 228 if ("URL".equals(type)) { 229 try { 230 url = new URL (location); 231 232 File file = new File(url.getFile()); 233 234 if (file.exists()) { 235 lastModified = file.lastModified(); 236 } 237 } catch (Exception 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 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 |