--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="XEMELIOS-re-patch-tables" default="usage" basedir=".">
+ <import file="../../common-tasks.xml"/>
+ <description>Builds, tests, and runs the project XEMELIOS xemelios-core</description>
+ <property file="${user.home}/.ant.properties"/>
+ <property name="compile.debug" value="true"/>
+ <xmlproperty file="component-definition-properties.xml"/>
+
+ <target name="usage">
+ <echo> Using ${ant.version} These are targets supported by this ANT build script: compile -
+ compile all .java files, except thoses in ./tmp folder. clean - deletes all compiled and
+ generated files and resources. jars - build jar files. Do not call this script directly,
+ use the one located at root of projet (in ../..) instead. </echo>
+ </target>
+
+ <target name="compile" depends="mk-output-dirs,define-compile-debug,prepare">
+ <javac srcdir="java" destdir="build/classes" debug="${compile.debug}" encoding="ISO-8859-1">
+ <classpath>
+ <pathelement path="../starter/build/classes"/>
+ <pathelement path="../xml-marshall/build/classes"/>
+ <pathelement path="../core/build/classes"/>
+ <pathelement path="../mysql-persistence/build/classes"/>
+ <pathelement path="../xemelios-core/build/classes"/>
+ </classpath>
+ </javac>
+ <copy todir="build/classes">
+ <fileset dir="java">
+ <include name="**/*"/>
+ <exclude name="**/*.java"/>
+ <exclude name="**/CVS/*"/>
+ <exclude name="**/*.form"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="jars" depends="prepare">
+ <copy file="manifest/manifest.txt" tofile="build/manifest.txt">
+ <filterset>
+ <filter token="version" value="${component.release}"/>
+ <filter token="name" value="${component.name}"/>
+ </filterset>
+ </copy>
+ <jar destfile="build/jars/${component.name}.jar" basedir="build/classes"
+ manifest="build/manifest.txt"/>
+ </target>
+
+ <target name="clean">
+ <delete dir="build"/>
+ </target>
+
+
+ <target name="mk-output-dirs">
+ <mkdir dir="build/classes"/>
+ <mkdir dir="build/jars"/>
+ </target>
+
+ <target name="config" description="Genere l'arborescence de mise a jour"
+ depends="get-configuration,prepare">
+ <property name="component.dir"
+ value="build/config/source/${component.name}/${component.release}"/>
+ <copy file="component-definition-properties.xml"
+ tofile="build/config/source/component-definition-properties.xml"/>
+ <mkdir dir="${component.dir}"/>
+ <copy todir="${component.dir}">
+ <fileset dir="lib" includes="*.jar"/>
+ <fileset dir="build/jars" includes="*.jar"/>
+ </copy>
+ <antcall target="generate-update"/>
+ </target>
+
+ <target name="setup">
+ <copy todir="../../build/setup/root/lib">
+ <fileset dir="build/jars" includes="*.jar"/>
+ </copy>
+ <copy todir="../../build/setup/root/lib">
+ <fileset dir="lib" includes="*.jar"/>
+ </copy>
+ </target>
+
+</project>
--- /dev/null
+/*
+ * Copyright
+ * 2011 axYus - http://www.axyus.com
+ * 2011 C.Marchand - christophe.marchand@axyus.com
+ *
+ * This file is part of XEMELIOS_NB.
+ *
+ * XEMELIOS_NB is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * XEMELIOS_NB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with XEMELIOS_NB; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+package org.xemelios.patches.tables;
+
+import fr.gouv.finances.cp.utils.PropertiesExpansion;
+import fr.gouv.finances.cp.utils.StartUrl;
+import fr.gouv.finances.cp.xemelios.data.impl.MySqlDataLayer;
+import fr.gouv.finances.dgfip.xemelios.auth.XemeliosUser;
+import fr.gouv.finances.dgfip.xemelios.common.Constants;
+import fr.gouv.finances.dgfip.xemelios.common.config.DocumentModel;
+import fr.gouv.finances.dgfip.xemelios.common.config.DocumentsModel;
+import fr.gouv.finances.dgfip.xemelios.common.config.Loader;
+import fr.gouv.finances.dgfip.xemelios.data.DataLayerManager;
+import fr.gouv.finances.dgfip.xemelios.data.impl.pool.PoolManager;
+import fr.gouv.finances.dgfip.xemelios.data.impl.sqlconfig.TDocument;
+import fr.gouv.finances.dgfip.xemelios.data.impl.sqlconfig.TEtat;
+import fr.gouv.finances.dgfip.xemelios.data.impl.sqlconfig.TLayer;
+import fr.gouv.finances.dgfip.xemelios.data.impl.sqlconfig.TPersistenceConfig;
+import fr.gouv.finances.dgfip.xemelios.data.impl.sqlconfig.TTable;
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URLEncoder;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+/**
+ * Contrôle que les tables ont la bonne structure, et corrige si nécessaire
+ * @author cmarchand
+ */
+public class Patcher {
+ public static final transient String ADDR = "bugs.xemelios@axyus.com";
+ private StringBuilder job;
+ private PrintWriter errors;
+ private StringWriter sw;
+ private String CRLF = null;
+
+ public static void main(String args[]) {
+ new Patcher();
+ }
+
+ protected Patcher() {
+ job = new StringBuilder();
+ errors = new PrintWriter(sw=new StringWriter());
+ CRLF = System.getProperty("line.separator");
+ PropertiesExpansion applicationProperties = new PropertiesExpansion();
+ String fileName = System.getProperty("xemelios.properties");
+ if(fileName==null) fileName = "./xemelios.properties";
+ File f = new File(fileName);
+ if(!f.exists()) {
+ System.err.println("Impossible de trouver "+fileName);
+ errors.println("Impossible de trouver "+fileName);
+ System.exit(1);
+ }
+// System.out.println("xemelios.properties="+f.getAbsolutePath());
+ Connection con = null;
+ try {
+ applicationProperties.load(new FileInputStream(f));
+// System.out.println(MySqlDataLayer.PROP_CONFIG_FILE_NAME+"="+applicationProperties.getProperty(MySqlDataLayer.PROP_CONFIG_FILE_NAME));
+ DocumentsModel documentsModel = Loader.getDocumentsInfos(applicationProperties.getProperty(Constants.SYS_PROP_DOC_DEF_DIR));
+ DataLayerManager.setApplicationProperties(applicationProperties);
+ DataLayerManager.regiterDataImpl(MySqlDataLayer.LAYER_NAME, MySqlDataLayer.class);
+ DataLayerManager.setDataImpl(MySqlDataLayer.LAYER_NAME);
+ MySqlDataLayer dataImpl = (MySqlDataLayer)DataLayerManager.getImplementation();
+ con = PoolManager.getInstance().getConnection();
+ XemeliosUser user = new XemeliosUser() {
+ @Override
+ public String getId() {
+ return "patcher";
+ }
+ @Override
+ public String getDisplayName() {
+ return getId();
+ }
+ @Override
+ public boolean hasRole(String role) {
+ return true;
+ }
+ @Override
+ public boolean hasDocument(String document) {
+ return true;
+ }
+ @Override
+ public boolean hasCollectivite(String collectivite, DocumentModel dm) {
+ return true;
+ }
+ };
+ for(DocumentModel docModel: documentsModel.getDocuments()) {
+// System.out.println("trying "+docModel.getId());
+ TPersistenceConfig tpc = dataImpl.getPersistenceConfig(docModel, user);
+ TLayer tLayer= tpc.getLayer(dataImpl.getLayerName());
+ TDocument tDocument = tLayer.getDocument(docModel.getId());
+ checkTable(tDocument.getListBcTable(),con);
+ checkTable(tDocument.getSpecialKeyTable(),con);
+ for(TEtat tEtat:tDocument.getEtats()) {
+ checkTable(tEtat.getDocumentTable(),con);
+ for(TTable ixTable:tEtat.getIndexTables())
+ checkTable(ixTable,con);
+ }
+ }
+ } catch(Exception ex) {
+ ex.printStackTrace(errors);
+ ex.printStackTrace();
+ exit(1);
+ } finally {
+ if(con!=null)
+ PoolManager.getInstance().releaseConnection(con);
+ }
+ exit(0);
+ }
+
+ private void checkTable(TTable table, Connection con) {
+ if(table==null) return;
+ String tableName = table.getBaseName();
+// System.out.println("checking "+tableName);
+ try {
+ ResultSet rs = con.createStatement().executeQuery("DESC "+tableName);
+ boolean initialDocNameExists=false, archiveNameExists=false;
+ while(rs.next()) {
+ String colName = rs.getString(1).toUpperCase();
+ if("INITIAL_DOC_NAME".equals(colName))
+ initialDocNameExists = true;
+ else if("ARCHIVE_NAME".equals(colName))
+ archiveNameExists = true;
+ }
+ rs.close();
+ if(archiveNameExists && initialDocNameExists) return;
+ else {
+ StringBuilder req = new StringBuilder();
+ req.append("ALTER TABLE ").append(tableName).append(" ");
+ if(!initialDocNameExists)
+ req.append(" ADD INITIAL_DOC_NAME VARCHAR(100), ADD INDEX ").append(tableName).append("_IDN (INITIAL_DOC_NAME),");
+ if(!archiveNameExists)
+ req.append(" ADD ARCHIVE_NAME VARCHAR(100), ADD INDEX ").append(tableName).append("_AN (ARCHIVE_NAME),");
+ req.deleteCharAt(req.length()-1);
+ job.append(req.toString()).append(";").append(CRLF);
+ Statement st = con.createStatement();
+ st.execute(req.toString());
+ st.close();
+ }
+ } catch(SQLException ex) {
+ if("42S02".equals(ex.getSQLState())) {
+ // la table n'existe pas, ce n'est pas grave
+// System.out.println(tableName+" does not exist");
+ } else {
+ errors.append("while patching ").append(tableName).append(":").append(CRLF);
+ errors.append("\tsqlState=").append(ex.getSQLState()).append("\t errorCode=").append(Integer.toString(ex.getErrorCode())).append(CRLF);
+ ex.printStackTrace(errors);
+ errors.append(CRLF);
+ }
+ }
+ }
+
+
+ private void exit(int code) {
+ StringBuffer errorBuffer = sw.getBuffer();
+ errors.flush();
+ System.err.println(errorBuffer);
+ if(errorBuffer.length()>0) {
+ StringBuilder url = new StringBuilder();
+ try {
+ url.append("mailto:").append(ADDR).append("?subject=Re-Patch base&body=").append(URLEncoder.encode(errorBuffer.toString(),"UTF-8"));
+ StartUrl.startUrl(url.toString());
+ } catch(Throwable t) {
+ System.err.println("Impossible d'envoyer le compte-rendu d'anomalies:");
+ System.err.println("Vous pouvez envoyer le texte suivant par mail à cette adresse : "+ADDR);
+ System.err.println(errorBuffer.toString());
+ }
+ }
+ System.out.println("Pour information, les travaux suivants ont été efféctués: "+code);
+ System.out.println(job.toString());
+ System.out.println("Appuyez sur <ENTREE> pour terminer.");
+ try {
+ new BufferedReader(new InputStreamReader(System.in)).readLine();
+ } catch(Throwable t) {}
+ System.exit(code);
+ }
+
+}