/* * codjo.net * * Common Apache License 2.0 */ package net.codjo.control.common; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.apache.log4j.Logger; /** * Etape dans un plan d'int�gration. * * @author $Author: nadaud $ * @version $Revision: 1.12 $ */ public class Step implements Cloneable { public static final String ERROR_CODE = "error_code"; public static final String ERROR_MESSAGE = "error_message"; public static final String FOR_ALL = "all"; public static final String FOR_BATCH = "batch"; public static final String FOR_USER = "user"; public static final String FOR_USER_ADD = "user.add"; public static final String FOR_USER_UPDATE = "user.update"; private static final Logger APP = Logger.getLogger(Step.class); private SqlStepHelper sqlControler = new SqlStepHelper(); private String controlClass; private String description; private int errorCode; private String errorMessage; private String id; private Control javaControler; private MassControl javaMassControler; private Set<Parameter> parameters; private int priority; private Query query; private String stepFor; private String test; private String type; private List<String> tableToSpooled; /** * Dictionnaire attach� � ce Step. */ private Dictionary dictionary = new Dictionary(); public Step() { } @Override public Object clone() { Step newStep = new Step(); if (this.controlClass != null) { try { newStep.setControlClass(this.getControlClass()); } catch (Exception ex) { throw new RuntimeException( "An exception occured while trying to clone a Step: " + ex.getClass().getName() + ": " + ex.getMessage()); } } newStep.description = this.description; newStep.errorCode = this.errorCode; newStep.errorMessage = this.errorMessage; newStep.id = this.id; if (this.parameters != null) { newStep.setParameters(this.parameters); } newStep.priority = this.priority; if (this.query != null) { newStep.setQuery((Query)this.getQuery().clone()); } newStep.stepFor = this.stepFor; newStep.test = this.test; newStep.type = this.type; if (this.tableToSpooled != null) { newStep.tableToSpooled = new ArrayList<String>(tableToSpooled); } if (this.getDictionary() != null) { newStep.setDictionary((Dictionary)this.getDictionary().clone()); } return newStep; } public void addTableToSpooledForDebug(String tableName) { if (tableToSpooled == null) { tableToSpooled = new ArrayList<String>(); } tableToSpooled.add(tableName); } public void setControlClass(String controlClass) throws Exception { this.controlClass = controlClass; Object obj = Class.forName(controlClass).newInstance(); if (obj instanceof Control) { javaControler = (Control)Class.forName(controlClass).newInstance(); } else { javaMassControler = (MassControl)Class.forName(controlClass).newInstance(); } } public void setDescription(String description) { this.description = description; } public void setErrorCode(int errorCode) { this.errorCode = errorCode; } public Dictionary getDictionary() { return dictionary; } public void setDictionary(Dictionary dictionary) { this.dictionary.addDictionary(dictionary); } public String getErrorMessage() { return errorMessage; } public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; } public void setId(String id) { this.id = id; } public void setParameters(Collection<Parameter> parameters) { this.parameters = new TreeSet<Parameter>(parameters); } public void setPriority(int priority) { this.priority = priority; } public void setQuery(Query query) { this.query = query; } public void setQuery(String temporaryTable, String ignoreWarningCode, String sql) { Query tmp = new Query(sql); tmp.setIgnoreWarningCode(ignoreWarningCode); tmp.setTemporaryTable(temporaryTable); this.setQuery(tmp); } public void setStepFor(String stepFor) { if (stepFor != null) { this.stepFor = stepFor.toLowerCase(); } else { this.stepFor = null; } } public void setTest(String test) { this.test = test; } public void setType(String type) { this.type = type; } public String getControlClass() { return controlClass; } public String getDescription() { return description; } public int getErrorCode() { return errorCode; } public String getId() { return id; } public Collection<Parameter> getParameters() { return parameters; } public int getPriority() { return priority; } public Query getQuery() { return query; } public String getStepFor() { return stepFor; } public boolean isStepFor(String stepForId) { if (stepFor == null || stepForId == null || FOR_ALL.equals(stepFor)) { return true; } if (FOR_USER.equals(stepFor)) { return isPathOfRequestContains(stepForId, FOR_USER) || isPathOfRequestContains(stepForId, FOR_USER_ADD) || isPathOfRequestContains(stepForId, FOR_USER_UPDATE); } if (FOR_USER_ADD.equals(stepFor)) { return isPathOfRequestContains(stepForId, FOR_USER) || isPathOfRequestContains(stepForId, FOR_USER_ADD); } if (FOR_USER_UPDATE.equals(stepFor)) { return isPathOfRequestContains(stepForId, FOR_USER) || isPathOfRequestContains(stepForId, FOR_USER_UPDATE); } return isPathOfRequestContains(stepForId, stepFor); } private boolean isPathOfRequestContains(String pathOfRequest, String toLookFor) { if (!pathOfRequest.startsWith("/")) { pathOfRequest = "/" + pathOfRequest; } if (!pathOfRequest.endsWith("/")) { pathOfRequest = pathOfRequest + "/"; } return pathOfRequest.contains("/" + toLookFor + "/"); } public String getTest() { return test; } public String getType() { return type; } public void addParameter(Parameter param) { if (parameters == null) { parameters = new TreeSet<Parameter>(); } parameters.add(param); } public void addParameter(Integer index, String parameterType, String parameterValue) { if (parameters == null) { parameters = new TreeSet<Parameter>(); } parameters.add(new Parameter(index, parameterType, parameterValue)); } public void execute(Object obj, Dictionary dico, ControlContext context) throws ControlException { dico.addVariable(ERROR_CODE, Integer.toString(getErrorCode())); dico.addVariable(ERROR_MESSAGE, getErrorMessage()); this.dictionary.setParent(dico); javaControler.setErrorCode(getErrorCode()); javaControler.setContext(context); long start = System.currentTimeMillis(); javaControler.control(obj, dictionary); if (APP.isDebugEnabled()) { long end = System.currentTimeMillis(); APP.debug("\nEtape java (" + getPriority() + ")" + getId() + " - " + getType() + "\n" + getControlClass() + "\nen " + ((end - start) / 1000) + " s"); } } public void execute(Connection con, Dictionary dico, String controlTableName, boolean mass, ControlContext context) throws SQLException, ControlException { dico.addVariable(ERROR_CODE, Integer.toString(getErrorCode())); dico.addVariable(ERROR_MESSAGE, getErrorMessage()); this.dictionary.setParent(dico); if (getQuery() != null && getControlClass() == null) { // Step SQL sqlControler.execute(con, dictionary); if (tableToSpooled != null && APP.isDebugEnabled()) { for (String tableName : tableToSpooled) { spoolTable(con, tableName); } } } else if (mass) { javaMassControler.setContext(context); javaMassControler.setControlTable(controlTableName); javaMassControler.control(con, dictionary); } } @Override public String toString() { return "control( \n" + getId() + "\n" + getParameters() + "\n" + getQuery() + ")"; } /** * Cette methode est ajoute pour faciliter le DEBUG des tests release. * * @param con connection SQL * @param tableName nom de la table * * @throws SQLException Erreur de lecture de la BD */ private static void spoolTable(Connection con, String tableName) throws SQLException { Statement stmt = con.createStatement(); APP.debug("******************** SPOOL de " + tableName + "********************"); try { StringBuffer reportBuffer = new StringBuffer(); ResultSet rs = stmt.executeQuery("select * from " + tableName); ResultSetMetaData rsmd = rs.getMetaData(); // Spool Header int colmumnCount = rsmd.getColumnCount(); for (int i = 1; i <= colmumnCount; i++) { reportBuffer.append("\t").append(rsmd.getColumnName(i)); } reportBuffer.append("\n"); for (int i = 1; i <= colmumnCount; i++) { reportBuffer.append("\t").append(rsmd.getColumnTypeName(i)); } reportBuffer.append("\n"); // Spool Content while (rs.next()) { for (int i = 1; i <= colmumnCount; i++) { reportBuffer.append("\t").append(rs.getObject(i)); } reportBuffer.append("\n"); } APP.debug(reportBuffer); } finally { stmt.close(); } } /** * Classe Helper pour une execution d'une Step en mode SQL. * * @author $Author: nadaud $ * @version $Revision: 1.12 $ */ private class SqlStepHelper { public void execute(Connection con, Dictionary dico) throws SQLException { long start = System.currentTimeMillis(); PreparedStatement stmt = con.prepareStatement(dico.replaceVariables(getQuery().getSql())); int result = -1; try { if (hasParameter()) { setStatementParameters(stmt, dico); } result = stmt.executeUpdate(); SQLWarning warnings = stmt.getWarnings(); String ignoreWarning = getQuery().getIgnoreWarningCode(); if (warnings != null) { if (ignoreWarning == null || !ignoreWarning.contains(warnings.getSQLState())) { throw warnings; } } } finally { if (getQuery().useTemporaryTable()) { dropTable(con, getQuery().getTemporaryTable()); } if (APP.isDebugEnabled()) { long end = System.currentTimeMillis(); APP.debug("\nEtape SQL (" + getPriority() + ")" + getId() + " - " + getType() + "\n" + dico.replaceVariables(getQuery().getSql()) + "\n" + "nb lignes maj = " + result + "\nen " + ((end - start) / 1000) + " s"); } stmt.close(); } } private void setStatementParameters(PreparedStatement stmt, Dictionary dico) throws SQLException { for (Parameter parameter : getParameters()) { parameter.initStatement(stmt, dico); } } private void dropTable(Connection con, String tableName) { try { Statement stmt = con.createStatement(); try { stmt.executeUpdate("drop table " + tableName); } finally { stmt.close(); } } catch (Exception error) { APP.debug("Step (" + getPriority() + ") drop table " + tableName, error); } } private boolean hasParameter() { return parameters != null && parameters.size() > 0; } } }