1 16 package org.apache.cocoon.acting; 17 18 import java.sql.Connection ; 19 import java.sql.PreparedStatement ; 20 import java.sql.ResultSet ; 21 import java.sql.SQLException ; 22 import java.util.Collections ; 23 import java.util.Enumeration ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import java.util.Map ; 27 import java.util.SortedSet ; 28 import java.util.TreeSet ; 29 30 import org.apache.avalon.excalibur.datasource.DataSourceComponent; 31 import org.apache.avalon.framework.configuration.Configuration; 32 import org.apache.avalon.framework.configuration.ConfigurationException; 33 import org.apache.avalon.framework.parameters.Parameters; 34 import org.apache.avalon.framework.thread.ThreadSafe; 35 import org.apache.cocoon.Constants; 36 import org.apache.cocoon.ProcessingException; 37 import org.apache.cocoon.environment.ObjectModelHelper; 38 import org.apache.cocoon.environment.Redirector; 39 import org.apache.cocoon.environment.Request; 40 import org.apache.cocoon.environment.SourceResolver; 41 import org.apache.commons.lang.StringUtils; 42 43 54 public class DatabaseAddAction extends AbstractDatabaseAction implements ThreadSafe { 55 protected static final Map addStatements = new HashMap (); 56 private static final Map selectStatements = new HashMap (); 57 58 63 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters param) throws Exception { 64 DataSourceComponent datasource = null; 65 Connection conn = null; 66 Map results = new HashMap (); 67 68 boolean reloadable = Constants.DESCRIPTOR_RELOADABLE_DEFAULT; 70 if (this.settings.containsKey("reloadable")) 71 reloadable = Boolean.valueOf((String ) this.settings.get("reloadable")).booleanValue(); 72 try { 74 Configuration conf = 75 this.getConfiguration(param.getParameter("descriptor", (String ) this.settings.get("descriptor")), resolver, 76 param.getParameterAsBoolean("reloadable",reloadable)); 77 78 datasource = this.getDataSource(conf); 79 conn = datasource.getConnection(); 80 Request request = ObjectModelHelper.getRequest(objectModel); 81 82 if (conn.getAutoCommit()) { 83 conn.setAutoCommit(false); 84 } 85 86 Configuration[] tables = conf.getChildren("table"); 87 for (int i=0; i<tables.length; i++) { 88 Configuration table = tables[i]; 89 processTable(table,conn,request,results); 90 } 91 conn.commit(); 92 } catch (Exception e) { 93 if (conn != null) { 94 try { 95 conn.rollback(); 96 } catch (SQLException se) { 97 getLogger().debug("There was an error rolling back the transaction", se); 98 } 99 } 100 101 throw new ProcessingException("Could not add record",e); 103 } finally { 104 if (conn != null) { 105 try { 106 conn.close(); 107 } catch (SQLException sqe) { 108 getLogger().warn("There was an error closing the datasource", sqe); 109 } 110 } 111 112 if (datasource != null) this.dbselector.release(datasource); 113 } 114 115 return Collections.unmodifiableMap(results); 116 } 117 118 126 void processTable(Configuration table, Connection conn, Request request, Map results) throws SQLException ,ConfigurationException,Exception { 127 PreparedStatement statement = null; 128 try { 129 String query = this.getAddQuery(table); 130 getLogger().debug("Add query: "+query); 131 statement = conn.prepareStatement(query); 132 Configuration[] keys = table.getChild("keys").getChildren("key"); 133 Configuration[] values = table.getChild("values").getChildren("value"); 134 int currentIndex = 1; 135 boolean manyrows = false; 136 int wildcardIndex = -1; 137 String wildcardParam = null; 138 for (int i=0; i<keys.length; i++) { 139 wildcardParam = keys[i].getAttribute("param"); 140 if ((wildcardIndex = wildcardParam.indexOf('*')) != -1) { 141 manyrows = true; 142 break; 143 } 144 } 145 if (manyrows) { 146 150 String prefix = wildcardParam.substring(0,wildcardIndex); 151 String suffix = StringUtils.substring(wildcardParam, wildcardIndex + 1); 152 Enumeration names = request.getParameterNames(); 153 SortedSet matchset = new TreeSet (); 154 int prefixLength = prefix.length(); 155 int length = prefixLength + suffix.length(); 156 while (names.hasMoreElements()) { 157 String name = (String )names.nextElement(); 158 if (name.startsWith(prefix) && name.endsWith(suffix)) { 159 String wildcard = StringUtils.mid(name, prefixLength, name.length() - length); 160 matchset.add(wildcard); 161 } 162 } 163 int rowIndex = 1; 164 Iterator iterator = matchset.iterator(); 165 while (iterator.hasNext()) { 166 String wildcard = (String )iterator.next(); 167 currentIndex = 1; 168 for (int j=0; j<keys.length; j++) { 169 String myparam = getActualParam(keys[j].getAttribute("param"),wildcard); 170 currentIndex += setKey(table,keys[j],conn,statement,currentIndex,request,myparam,results); 171 } 172 for (int j=0; j<values.length; j++) { 173 String myparam = getActualParam(values[j].getAttribute("param"),wildcard); 174 this.setColumn(statement,currentIndex,request,values[j],myparam,request.getParameter(myparam),rowIndex); 175 currentIndex++; 176 } 177 statement.execute(); 178 rowIndex++; 179 } 180 } else { 181 185 for (int i = 0; i < keys.length; i++) { 186 currentIndex += setKey(table,keys[i],conn,statement,currentIndex,request,keys[i].getAttribute("param",""),results); 187 } 188 for (int i = 0; i < values.length; i++, currentIndex++) { 189 this.setColumn(statement, currentIndex, request, values[i]); 190 } 191 statement.execute(); 192 193 } 194 } finally { 195 try { 196 if (statement != null) { 197 statement.close(); 198 } 199 } catch (SQLException e) {} 200 } 201 } 202 203 234 int setKey(Configuration table, Configuration key, Connection conn, PreparedStatement statement, int currentIndex, Request request, String param, Map results) throws ConfigurationException, SQLException ,Exception { 235 String mode = key.getAttribute("mode","automatic"); 236 String keyname = new StringBuffer ("key:").append(table.getAttribute("name")) 237 .append(':').append(key.getAttribute("dbcol")).toString(); 238 if ("manual".equals(mode)) { 239 String selectQuery = this.getSelectQuery(key); 241 PreparedStatement select_statement = conn.prepareStatement(selectQuery); 242 ResultSet set = select_statement.executeQuery(); 243 set.next(); 244 int value = set.getInt("maxid") + 1; 245 statement.setInt(currentIndex, value); 246 getLogger().debug("Manually setting key to " + value); 247 setRequestAttribute(request,keyname,new Integer (value)); 248 results.put(key.getAttribute("dbcol"),String.valueOf(value)); 249 set.close(); 250 select_statement.close(); 251 } else if ("form".equals(mode)) { 252 getLogger().debug("Setting key from form"); 254 this.setColumn(statement, currentIndex, request, key, param); 255 } else if ("request-attribute".equals(mode)) { 256 Integer value = (Integer )getRequestAttribute(request,key.getAttribute("request-attribute-name")); 257 getLogger().debug("Setting key from request attribute "+value); 258 statement.setInt(currentIndex,value.intValue()); 259 } else { 260 getLogger().debug("Automatically setting key"); 261 return 0; 263 } 264 return 1; 265 } 266 267 278 String getActualParam(String param, String wildcard) { 279 int index; 280 if ((index = param.indexOf('*')) != -1) { 281 return param.substring(0,index)+wildcard+param.substring(index+1); 282 } else { 283 return param; 284 } 285 } 286 287 295 protected String getAddQuery(Configuration table) throws ConfigurationException { 296 String query = null; 297 synchronized (DatabaseAddAction.addStatements) { 298 query = (String ) DatabaseAddAction.addStatements.get(table); 299 if (query == null) { 300 Configuration[] values = table.getChild("values").getChildren("value"); 301 Configuration[] keys = table.getChild("keys").getChildren("key"); 302 303 StringBuffer queryBuffer = new StringBuffer ("INSERT INTO "); 304 queryBuffer.append(table.getAttribute("name")); 305 queryBuffer.append(" ("); 306 307 int numParams = 0; 308 309 for (int i = 0; i < keys.length; i++) { 310 String mode = keys[i].getAttribute("mode", "automatic"); 311 if ("manual".equals(mode) || "form".equals(mode) || "request-attribute".equals(mode)) { 312 if (numParams > 0) { 313 queryBuffer.append(", "); 314 } 315 queryBuffer.append(keys[i].getAttribute("dbcol")); 316 this.setSelectQuery(table.getAttribute("name"), keys[i]); 317 numParams++; 318 } 319 } 320 queryBuffer.append(buildList(values, numParams)); 321 numParams += values.length; 322 queryBuffer.append(") VALUES ("); 323 if (numParams > 0) { 324 queryBuffer.append("?"); 325 queryBuffer.append(StringUtils.repeat(", ?", numParams - 1)); 326 } 327 queryBuffer.append(")"); 328 query = queryBuffer.toString(); 329 330 DatabaseAddAction.addStatements.put(table, query); 331 } 332 } 333 return query; 334 } 335 336 341 protected final synchronized void setSelectQuery(String tableName, Configuration entry) throws ConfigurationException { 342 StringBuffer queryBuffer = new StringBuffer ("SELECT max("); 343 queryBuffer.append(entry.getAttribute("dbcol")); 344 queryBuffer.append(") AS maxid FROM "); 345 queryBuffer.append(tableName); 346 347 DatabaseAddAction.selectStatements.put(entry, queryBuffer.toString()); 348 } 349 350 protected final synchronized String getSelectQuery(Configuration entry) throws ConfigurationException { 351 return (String ) DatabaseAddAction.selectStatements.get(entry); 352 } 353 } 354 | Popular Tags |