public Map act(Redirector redirector, SourceResolver resolver, Map objectModel,
String source, Parameters param) throws Exception {
DataSourceComponent datasource = null;
Connection conn = null;
Map results = new HashMap();
int rows = 0;
boolean failed = false;
// read global parameter settings
boolean reloadable = DESCRIPTOR_RELOADABLE_DEFAULT;
// call specific default modes apart from output mode are not supported
// set request attribute
String outputMode = param.getParameter("output", (String) defaultModeNames.get(MODE_OUTPUT));
if (this.settings.containsKey("reloadable")) {
reloadable = Boolean.valueOf((String) this.settings.get("reloadable")).booleanValue();
}
// read local parameter settings
try {
Configuration conf =
this.getConfiguration(param.getParameter("descriptor", (String) this.settings.get("descriptor")),
resolver,
param.getParameterAsBoolean("reloadable",reloadable));
// get database connection and try to turn off autocommit
datasource = this.getDataSource(conf, param);
conn = datasource.getConnection();
if (conn.getAutoCommit() == true) {
try {
conn.setAutoCommit(false);
} catch (Exception ex) {
String tmp = param.getParameter("use-transactions",(String) this.settings.get("use-transactions",null));
if (tmp != null && (tmp.equalsIgnoreCase("no") || tmp.equalsIgnoreCase("false") || tmp.equalsIgnoreCase("0"))) {
if (getLogger().isErrorEnabled())
getLogger().error("This DB connection does not support transactions. If you want to risk your data's integrity by continuing nonetheless set parameter \"use-transactions\" to \"no\".");
throw ex;
}
}
}
// find tables to work with
Configuration[] tables = conf.getChildren("table");
String tablesetname = param.getParameter("table-set", (String) this.settings.get("table-set"));
Map modeTypes = null;
if (tablesetname == null) {
modeTypes = new HashMap(6);
modeTypes.put( MODE_AUTOINCR, "autoincr" );
modeTypes.put( MODE_OTHERS, "others" );
modeTypes.put( MODE_OUTPUT, outputMode );
for (int i = 0; i < tables.length; i++) {
rows += processTable(tables[i], conn, objectModel, results, modeTypes);
}
} else {
// new set based behaviour
// create index for table names / aliases
Map tableIndex = new HashMap(2*tables.length);
String tableName = null;
Object result = null;
for (int i=0; i<tables.length; i++) {
tableName = tables[i].getAttribute("alias",tables[i].getAttribute("name",""));
result = tableIndex.put(tableName,new Integer(i));
if (result != null) {
throw new IOException("Duplicate table entry for "+tableName+" at positions "+result+" and "+i);
}
}
Configuration[] tablesets = conf.getChildren("table-set");
String setname = null;
boolean found = false;
// find tables contained in tableset
int j = 0;
for (j = 0; j < tablesets.length; j++) {
setname = tablesets[j].getAttribute ("name", "");
if (tablesetname.trim().equals (setname.trim ())) {
found = true;
break;
}
}
if (!found) {
throw new IOException(" given set " + tablesetname + " does not exists in a description file.");
}
Configuration[] set = tablesets[j].getChildren("table");
for (int i = 0; i < set.length; i++) {
// look for alternative mode types
modeTypes = new HashMap(6);
modeTypes.put( MODE_AUTOINCR, set[i].getAttribute( "autoincr-mode", "autoincr" ) );
modeTypes.put( MODE_OTHERS, set[i].getAttribute( "others-mode", "others" ) );
modeTypes.put( MODE_OUTPUT, outputMode );
tableName=set[i].getAttribute("name","");
if (tableIndex.containsKey(tableName)) {
j = ((Integer)tableIndex.get(tableName)).intValue();
rows += processTable( tables[j], conn, objectModel, results, modeTypes );
} else {
throw new IOException(" given table " + tableName + " does not exists in a description file.");
}
}
}
if (conn.getAutoCommit() == false) {
conn.commit();
}
// obtain output mode module and rollback output
ServiceSelector outputSelector = null;
OutputModule output = null;
try {
outputSelector = (ServiceSelector) this.manager.lookup(OUTPUT_MODULE_SELECTOR);
if (outputMode != null && outputSelector != null && outputSelector.isSelectable(outputMode)){
output = (OutputModule) outputSelector.select(outputMode);
}
if (output != null) {
output.commit(null, objectModel);
} else if (getLogger().isWarnEnabled()) {
getLogger().warn("Could not select output mode " + outputMode);
}
} catch (ServiceException e) {
if (getLogger().isWarnEnabled()) {
getLogger().warn("Could not select output mode " + outputMode + ":" + e.getMessage());
}
} finally {
if (outputSelector != null) {
if (output != null) {
outputSelector.release(output);
}
this.manager.release(outputSelector);
}
}
} catch (Exception e) {
failed = true;
if ( conn != null ) {
try {
if (getLogger().isDebugEnabled()) {
getLogger().debug( "Rolling back transaction. Caused by " + e.getMessage() );
e.printStackTrace();
}
conn.rollback();
results = null;
// obtain output mode module and commit output
ServiceSelector outputSelector = null;
OutputModule output = null;
try {
outputSelector = (ServiceSelector) this.manager.lookup(OUTPUT_MODULE_SELECTOR);
if (outputMode != null && outputSelector != null && outputSelector.isSelectable(outputMode)){
output = (OutputModule) outputSelector.select(outputMode);
}
if (output != null) {
output.rollback( null, objectModel, e);
} else if (getLogger().isWarnEnabled()) {
getLogger().warn("Could not select output mode " + outputMode);
}
} catch (ServiceException e2) {
if (getLogger().isWarnEnabled()) {
getLogger().warn("Could not select output mode " + outputMode + ":" + e2.getMessage());
}
} finally {
if (outputSelector != null) {
if (output != null) {
outputSelector.release(output);
}
this.manager.release(outputSelector);
}
}
} catch (SQLException se) {
if (getLogger().isDebugEnabled())
getLogger().debug("There was an error rolling back the transaction", se);
}
}
//throw new ProcessingException("Could not add record :position = " + currentIndex, e);
// don't throw an exception, an error has been signalled, that should suffice
String throwException = (String) this.settings.get( "throw-exception",
param.getParameter( "throw-exception", null ) );
if ( throwException != null && BooleanUtils.toBoolean(throwException)) {
throw new ProcessingException("Cannot process the requested SQL statement ",e);
}
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException sqe) {
getLogger().warn("There was an error closing the datasource", sqe);
}
}
if (datasource != null)
this.dbselector.release(datasource);
}
if (results != null) {
if (rows>0 || (!failed && !this.failOnEmpty)) {
results.put("row-count",new Integer(rows));
} else {
results = null;
}
} else {
if (rows>0) {
results = new HashMap(1);
results.put("row-count",new Integer(rows));
}
}
return results; // (results == null? results : Collections.unmodifiableMap(results));