1 5 package com.opensymphony.workflow.loader; 6 7 import com.opensymphony.module.propertyset.PropertySet; 8 9 import com.opensymphony.workflow.FactoryException; 10 import com.opensymphony.workflow.FunctionProvider; 11 12 import org.apache.commons.logging.Log; 13 import org.apache.commons.logging.LogFactory; 14 15 import org.xml.sax.SAXException ; 16 17 import java.io.*; 18 19 import java.sql.*; 20 21 import java.util.HashMap ; 22 import java.util.Iterator ; 23 import java.util.Map ; 24 25 import javax.naming.InitialContext ; 26 import javax.naming.NamingException ; 27 28 import javax.sql.DataSource ; 29 30 31 47 public class JDBCWorkflowFactory extends XMLWorkflowFactory implements FunctionProvider { 48 50 private static final Log log = LogFactory.getLog(JDBCWorkflowFactory.class); 51 final static String wfTable = "OS_WORKFLOWDEFS"; 52 final static String wfName = "WF_NAME"; 53 final static String wfDefinition = "WF_DEFINITION"; 54 55 57 protected DataSource ds; 58 protected Map workflows; 59 protected boolean reload; 60 61 63 public WorkflowDescriptor getWorkflow(String name) throws FactoryException { 64 WfConfig c = (WfConfig) workflows.get(name); 65 66 if (c == null) { 67 throw new RuntimeException ("Unknown workflow name \"" + name + "\""); 68 } 69 70 if (log.isDebugEnabled()) { 71 log.debug("getWorkflow " + name + " descriptor=" + c.descriptor); 72 } 73 74 if (c.descriptor != null) { 75 if (reload) { 76 try { 78 c.descriptor = load(c.wfName); 79 } catch (FactoryException e) { 80 throw e; 81 } catch (Exception e) { 82 throw new FactoryException("Error reloading workflow", e); 83 } 84 } 85 } else { 86 if (log.isDebugEnabled()) { 87 try { 88 c.descriptor = load(c.wfName); 89 } catch (FactoryException e) { 90 throw e; 91 } catch (Exception e) { 92 throw new FactoryException("Error loading workflow", e); 93 } 94 } 95 } 96 97 return c.descriptor; 98 } 99 100 public String [] getWorkflowNames() { 101 int i = 0; 102 String [] res = new String [workflows.keySet().size()]; 103 Iterator it = workflows.keySet().iterator(); 104 105 while (it.hasNext()) { 106 res[i++] = (String ) it.next(); 107 } 108 109 return res; 110 } 111 112 public void execute(Map transientVars, Map args, PropertySet ps) { 113 String name = (String ) args.get("name"); 114 WorkflowDescriptor wfds = (WorkflowDescriptor) transientVars.get("descriptor"); 115 116 try { 117 saveWorkflow(name, wfds, false); 118 } catch (Exception e) { 119 } 120 } 121 122 public void initDone() throws FactoryException { 123 Connection conn = null; 124 125 try { 126 init(); 127 reload = getProperties().getProperty("reload", "false").equalsIgnoreCase("true"); 128 129 conn = ds.getConnection(); 130 131 PreparedStatement ps = conn.prepareStatement("SELECT " + wfName + "," + wfDefinition + " FROM " + wfTable); 132 ResultSet rs = ps.executeQuery(); 133 134 while (rs.next()) { 135 String name = rs.getString(1); 136 WfConfig config = new WfConfig(name); 137 workflows.put(rs.getString(1), config); 138 } 139 140 rs.close(); 141 ps.close(); 142 } catch (Exception e) { 143 throw new FactoryException("Could not read workflow names from datasource", e); 144 } finally { 145 try { 146 conn.close(); 147 } catch (Exception ex) { 148 } 149 } 150 } 151 152 public byte[] read(String workflowname) throws SQLException { 153 byte[] wf = new byte[0]; 154 155 Connection conn = null; 156 157 try { 158 conn = ds.getConnection(); 159 160 PreparedStatement ps = conn.prepareStatement("SELECT " + wfDefinition + " FROM " + wfTable + " WHERE " + wfName + " = ?"); 161 ps.setString(1, workflowname); 162 163 ResultSet rs = ps.executeQuery(); 164 165 if (rs.next()) { 166 wf = rs.getBytes(1); 167 } 168 169 rs.close(); 170 ps.close(); 171 } finally { 172 try { 173 conn.close(); 174 } catch (Exception ex) { 175 } 176 } 177 178 return wf; 179 } 180 181 public boolean removeWorkflow(String name) throws FactoryException { 182 boolean removed = false; 183 184 try { 185 Connection conn = ds.getConnection(); 186 PreparedStatement ps = conn.prepareStatement("DELETE FROM " + wfTable + " WHERE " + wfName + " = ?"); 187 ps.setString(1, name); 188 189 int rows = ps.executeUpdate(); 190 191 if (rows == 1) { 192 removed = true; 193 workflows.remove(name); 194 } 195 196 ps.close(); 197 conn.close(); 198 } catch (SQLException e) { 199 throw new FactoryException("Unable to remove workflow: " + e.toString(), e); 200 } 201 202 return removed; 203 } 204 205 public boolean saveWorkflow(String name, WorkflowDescriptor descriptor, boolean replace) throws FactoryException { 206 WfConfig c = (WfConfig) workflows.get(name); 207 208 if ((c != null) && !replace) { 209 return false; 210 } 211 212 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 213 Writer out = new OutputStreamWriter(bout); 214 215 PrintWriter writer = new PrintWriter(out); 216 writer.println(WorkflowDescriptor.XML_HEADER); 217 writer.println(WorkflowDescriptor.DOCTYPE_DECL); 218 descriptor.writeXML(writer, 0); 219 writer.flush(); 220 writer.close(); 221 222 try { 224 return write(name, bout.toByteArray()); 225 } catch (SQLException e) { 226 throw new FactoryException("Unable to save workflow: " + e.toString(), e); 227 } finally { 228 WfConfig config = new WfConfig(name); 229 workflows.put(name, config); 230 } 231 } 232 233 public boolean write(String workflowname, byte[] wf) throws SQLException { 234 boolean written = false; 235 Connection conn = null; 236 237 try { 238 conn = ds.getConnection(); 239 240 PreparedStatement ps; 241 242 if (exists(workflowname, conn)) { 243 ps = conn.prepareStatement("UPDATE " + wfTable + " SET " + wfDefinition + " = ?" + "WHERE " + wfName + "= ?"); 244 245 try { 246 ps.setBytes(1, wf); 247 } catch (Exception e) { 248 } 249 250 ps.setString(2, workflowname); 251 } else { 252 ps = conn.prepareStatement("INSERT INTO " + wfTable + " (" + wfName + ", " + wfDefinition + ") VALUES (?, ?)"); 253 ps.setString(1, workflowname); 254 255 try { 256 ps.setBytes(2, wf); 257 } catch (Exception e) { 258 } 259 } 260 261 ps.executeUpdate(); 262 ps.close(); 263 conn.close(); 264 written = true; 265 } finally { 266 try { 267 conn.close(); 268 } catch (Exception e) { 269 } 270 } 271 272 return written; 273 } 274 275 private boolean exists(String workflowname, Connection conn) { 276 boolean exists = false; 277 278 try { 279 PreparedStatement ps = conn.prepareStatement("SELECT " + wfName + " FROM " + wfTable + " WHERE " + wfName + " = ?"); 280 ps.setString(1, workflowname); 281 282 ResultSet rs = ps.executeQuery(); 283 284 if (rs.next()) { 285 exists = true; 286 } 287 288 rs.close(); 289 ps.close(); 290 } catch (SQLException e) { 291 log.fatal("Could not check if [" + workflowname + "] exists", e); 292 } 293 294 return exists; 295 } 296 297 private void init() throws NamingException { 298 workflows = new HashMap (); 299 300 ds = (DataSource ) new InitialContext ().lookup(getProperties().getProperty("datasource")); 301 } 302 303 private WorkflowDescriptor load(final String wfName) throws IOException, SAXException , FactoryException { 304 byte[] wf = new byte[0]; 305 306 try { 307 wf = read(wfName); 308 } catch (SQLException e) { 309 throw new FactoryException("Error loading workflow:" + e, e); 310 } 311 312 ByteArrayInputStream is = new ByteArrayInputStream(wf); 313 314 return WorkflowLoader.load(is); 315 } 316 317 319 class WfConfig { 320 String wfName; 321 WorkflowDescriptor descriptor; 322 long lastModified; 323 324 public WfConfig(String name) { 325 wfName = name; 326 } 327 } 328 } 329 | Popular Tags |