--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="XEMELIOS-starter" default="usage" basedir=".">
+ <import file="../../common-tasks.xml"/>
+ <description>Builds, tests, and runs the project XEMELIOS starter</description>
+ <property file="${user.home}/.ant.properties"/>
+ <property name="compile.debug" value="true"/>
+
+ <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 roto of the project (../..) 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"/>
+ </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/xemelios.jar" basedir="build/classes" manifest="build/manifest.txt"/>
+ </target>
+
+ <target name="clean">
+ <delete dir="build"/>
+ </target>
+
+ <target name="config" 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="build/jars" includes="*.jar"/>
+ </copy>
+ <antcall target="generate-update"/>
+ </target>
+
+ <target name="setup">
+ <copy todir="../../build/setup/root">
+ <fileset dir="build/jars" includes="*.jar"/>
+ </copy>
+ </target>
+
+ <target name="mk-output-dirs">
+ <mkdir dir="build/classes"/>
+ <mkdir dir="build/jars"/>
+ </target>
+</project>
+
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<component xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../../defs/technical-component-definition.xsd">
+ <name>starter</name>
+ <description>Lanceur Xemelios</description>
+ <release>5.0.0.1</release>
+ <url>http://xemelios.org/updatesV5/starter</url>
+ <type>COMPOSANT</type>
+ <destination>
+ <base>${xemelios.root}</base>
+ </destination>
+ <release-notes>
+ <release v="5.0.0.1">
+ <note>Contrôle de l'unicité de l'exécution de Xemelios</note>
+ </release>
+ </release-notes>
+</component>
--- /dev/null
+/*
+ * Copyright
+ * 2005 axYus - www.axyus.com
+ * 2005 Serguei Eremenko
+ *
+ * This file is part of XEMELIOS.
+ *
+ * XEMELIOS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * XEMELIOS 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XEMELIOS; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package fr.gouv.finances.cp.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.NoSuchElementException;
+import java.util.Properties;
+
+/**
+ * The tag ${} is used to introduce substitutable parameters so it expands
+ * properties with ${} described in a property file; it is possible to have
+ * different sections with the same names as: <br>
+ *
+ * global_name1=z1 <br>
+ * sec_name=v <br>
+ * x1=2 <br>
+ * y1=0 <br>
+ * [section_1] <br>
+ * x1=${x1} <br>
+ * [section2] <br>
+ * x1=zxc <br>
+ * [${sec_name}] <br>
+ * ... <br>
+ *
+ * @author Serguei Eremenko
+ * @version 1.0
+ */
+public class PropertiesExpansion extends Properties {
+ /**
+ * Comment for <code>serialVersionUID</code>
+ */
+ private static final long serialVersionUID = 3258412845963096881L;
+
+ /**
+ * Creates an empty property list with no default values.
+ */
+ public PropertiesExpansion() {
+ super();
+ }
+
+ /**
+ * Creates an empty property list with the specified defaults.
+ *
+ * @param def
+ * the defaults.
+ */
+ public PropertiesExpansion(Properties def) {
+ super(def);
+ }
+
+ /**
+ * Searches for the property with the specified key in this property list
+ * and substitutes any ${} occurrence that may be in the key.
+ *
+ * @param key
+ * the property key.
+ * @return the value in this property list with the specified key value or
+ * null if not found.
+ */
+ @Override
+ public String getProperty(String key) {
+ return replace(super.getProperty(replace(key)));
+ }
+
+ /**
+ * Searches for the property within the specified section and with the
+ * specified key in this property list and substitutes any ${} occurrence
+ * that may be in the key.
+ *
+ * @param section
+ * the property section.
+ * @param key
+ * the property key.
+ * @return the value in this property list within the specified section and
+ * with the specified key value or null if not found.
+ */
+ @Override
+ public String getProperty(String section, String key) {
+ Properties p = (Properties)get(replace(section));
+ if (p == null)
+ return null;
+ return replace(p.getProperty(replace(key)));
+ }
+
+ /**
+ * @param section
+ * the property section.
+ * @param key
+ * the property key.
+ * @param def
+ * the default value.
+ * @return the value in this property list within the specified section and
+ * with the specified key value or this default value.
+ */
+ public String getProperty(String section, String key, String def) {
+ String s = getProperty(section, key);
+ if (s == null)
+ s = def;
+ return replace(s);
+ }
+
+ /**
+ * Casts a found property to its integer value
+ *
+ * @param prop
+ * the Properties to be searched in
+ * @param key
+ * the property key
+ * @param def
+ * the default value
+ * @return the found value cast to integer or the default value
+ * @see #getProperty
+ */
+ public static int getInt(Properties prop, String key, int def) {
+ int out = def;
+ try {
+ out = getInt(prop, key);
+ }
+ catch (RuntimeException e) {}
+ return out;
+ }
+
+ /**
+ * @see #getProperty
+ */
+ public static int getInt(Properties prop, String key) {
+ String s = prop.getProperty(key);
+ if (s == null)
+ throw new NoSuchElementException("No key " + key + " found");
+ return Integer.parseInt(s);
+ }
+
+ public static long getLong(Properties prop, String key, long def) {
+ long out = def;
+ try {
+ out = getLong(prop, key);
+ }
+ catch (RuntimeException e) {}
+ return out;
+ }
+
+ public static long getLong(Properties prop, String key) {
+ String s = prop.getProperty(key);
+ if (s == null)
+ throw new NoSuchElementException("No key " + key + " found");
+ return Long.parseLong(s);
+ }
+
+ public static float getFloat(Properties prop, String key, float def) {
+ float out = def;
+ try {
+ out = getFloat(prop, key);
+ }
+ catch (RuntimeException e) {}
+ return out;
+ }
+
+ public static float getFloat(Properties prop, String key) {
+ String s = prop.getProperty(key);
+ if (s == null)
+ throw new NoSuchElementException("No key " + key + " found");
+ return Float.parseFloat(s);
+ }
+
+ public static double getDouble(Properties prop, String key, double def) {
+ double out = def;
+ try {
+ out = getDouble(prop, key);
+ }
+ catch (RuntimeException e) {}
+ return out;
+ }
+
+ public static double getDouble(Properties prop, String key) {
+ String s = prop.getProperty(key);
+ if (s == null)
+ throw new NoSuchElementException("No key " + key + " found");
+ return Double.parseDouble(s);
+ }
+
+ public static boolean getBoolean(Properties prop, String key, boolean def) {
+ boolean out = def;
+ try {
+ out = getBoolean(prop, key);
+ }
+ catch (RuntimeException e) {}
+ return out;
+ }
+
+ public static boolean getBoolean(Properties prop, String key) {
+ String s = prop.getProperty(key);
+ if (s == null)
+ throw new NoSuchElementException("No key " + key + " found");
+ return new Boolean(s).booleanValue();
+ }
+
+ public int getInt(String key, int def) {
+ int out = def;
+ try {
+ out = getInt(key);
+ }
+ catch (RuntimeException e) {}
+ return out;
+ }
+
+ public int getInt(String key) {
+ String s = getProperty(key);
+ if (s == null)
+ throw new NoSuchElementException("No key " + key + " found");
+ return Integer.parseInt(s);
+ }
+
+ public long getLong(String key, long def) {
+ long out = def;
+ try {
+ out = getLong(key);
+ }
+ catch (RuntimeException e) {}
+ return out;
+ }
+
+ public long getLong(String key) {
+ String s = getProperty(key);
+ if (s == null)
+ throw new NoSuchElementException("No key " + key + " found");
+ return Long.parseLong(s);
+ }
+
+ public float getFloat(String key, float def) {
+ float out = def;
+ try {
+ out = getFloat(key);
+ }
+ catch (RuntimeException e) {}
+ return out;
+ }
+
+ public float getFloat(String key) {
+ String s = getProperty(key);
+ if (s == null)
+ throw new NoSuchElementException("No key " + key + " found");
+ return Float.parseFloat(s);
+ }
+
+ public double getDouble(String key, double def) {
+ double out = def;
+ try {
+ out = getDouble(key);
+ }
+ catch (RuntimeException e) {}
+ return out;
+ }
+
+ public double getDouble(String key) {
+ String s = getProperty(key);
+ if (s == null)
+ throw new NoSuchElementException("No key " + key + " found");
+ return Double.parseDouble(s);
+ }
+
+ public boolean getBoolean(String key, boolean def) {
+ boolean out = def;
+ try {
+ out = getBoolean(key);
+ }
+ catch (RuntimeException e) {}
+ return out;
+ }
+
+ public boolean getBoolean(String key) {
+ String s = getProperty(key);
+ if (s == null)
+ throw new NoSuchElementException("No key " + key + " found");
+ return new Boolean(s).booleanValue();
+ }
+
+ /**
+ * @param key
+ * the key to be placed into this property list.
+ * @param value
+ * the value corresponding to key.
+ * @return the previous value of the specified key in this property list, or
+ * null if it did not have one.
+ */
+ @Override
+ public Object setProperty(String key, String value) {
+ return super.setProperty(replace(key), replace(value));
+ }
+
+ /**
+ * @param section
+ * the section where the key to be placed into this property
+ * list, the section is created if the property list did not have
+ * one.
+ * @param key
+ * the key to be placed into this property list.
+ * @param value
+ * the value corresponding to key.
+ * @return the previous value of the specified key in this property list, or
+ * null if it did not have one.
+ */
+ public Object setProperty(String section, String key, String value) {
+ Properties p = (Properties)get(replace(section));
+ if (p == null) {
+ p = new Properties();
+ put(replace(section), p);
+ }
+ return p.setProperty(key, replace(value));
+ }
+
+ /**
+ * @return an enumeration of the sections in this property list.
+ */
+ public synchronized Enumeration sections() {
+ final int len = keySet().size();
+ final String[] all = keySet().toArray(new String[len]);
+ return new Enumeration() {
+ public boolean hasMoreElements() {
+ next = null;
+ while (i < len) {
+ String key = all[i++];
+ if (get(key) instanceof Properties) {
+ next = key;
+ break;
+ }
+ }
+ return next != null;
+ }
+
+ public Object nextElement() {
+ if (next == null)
+ throw new NoSuchElementException();
+ return next;
+ }
+
+ private Object next = null;
+
+ private int i = 0;
+ };
+ }
+
+ /**
+ * @param section
+ * the section name where to enumerate the keys from.
+ * @return an enumeration of the section keys in this property list or empty
+ * enumeration if there is no such section or the section does not
+ * contain any keys.
+ */
+ public synchronized Enumeration sectionKeys(String section) {
+ Properties p = (Properties)get(replace(section));
+ Enumeration en = null;
+ if (p == null) {
+ en = new Enumeration() {
+ public boolean hasMoreElements() {
+ return false;
+ }
+
+ public Object nextElement() {
+ throw new NoSuchElementException();
+ }
+ };
+ } else {
+ en = p.keys();
+ }
+ return en;
+ }
+
+ /**
+ * Overrides the Hashtable's put method and its use is strongly discouraged.
+ *
+ * @see java.util.Hashtable#put
+ * @see #setProperty
+ */
+ @Override
+ public Object put(Object key, Object val) {
+ if (key == null || val == null)
+ throw new NullPointerException();
+ Object o = null;
+ if (key instanceof String && val instanceof String) {
+ String s = (String)key;
+ int i = s.indexOf(startSecSep);
+ if (i == 0) {
+ curSec = replace(s.substring(i + 1, s.indexOf(endSecSep, i + 2)));
+ Properties p = (Properties)get(curSec);
+ if (p == null) {
+ p = new Properties();
+ o = super.put(curSec, p);
+ }
+ } else {
+ Properties p = (Properties)get(curSec);
+ if (p != null) {
+ o = p.put(key, val);
+ } else {
+ o = super.put(key, val);
+ }
+ }
+ } else {
+ o = super.put(key, val);
+ }
+ return o;
+ }
+
+ /**
+ * Reads a property list (key and element pairs) from the input stream.
+ *
+ * @param is
+ * the input stream.
+ */
+ @Override
+ public synchronized void load(InputStream is) throws IOException {
+ curSec = "";
+ super.load(is);
+ curSec = "";
+ replaceAll(this);
+ }
+
+ /**
+ * Writes this property list (key and element pairs) in this Properties
+ * table to the output stream in a format suitable for loading into a
+ * Properties table using the load method.
+ *
+ * @param os
+ * an output stream.
+ * @param header
+ * a description of the property list.
+ */
+ @Override
+ public synchronized void store(OutputStream os, String header) throws IOException {
+ Properties p = null;
+ for (Enumeration en = keys(); en.hasMoreElements();) {
+ String k = (String)en.nextElement();
+ Object v = get(k);
+ if (v instanceof String) {
+ if (p == null)
+ p = new Properties();
+ p.put(k, v);
+ }
+ }
+ if (p != null)
+ p.store(os, header);
+ for (Enumeration en = keys(); en.hasMoreElements();) {
+ String k = (String)en.nextElement();
+ Object v = get(k);
+ if (v instanceof Properties) {
+ byte[] b = (startSecSep + k + endSecSep + "\r\n").getBytes();
+ os.write(b, 0, b.length);
+ os.flush();
+ ((Properties)v).store(os, null);
+ }
+ }
+ }
+
+ /**
+ * @param in
+ * the string where substitutable parameters ${} will be replaces
+ * with values contained in the hashtable of keys
+ * @param keys
+ * the hashtable of keys
+ * @return the substituted string
+ */
+ public static String replace(String in, Hashtable keys) {
+ if (in == null)
+ return null;
+ if (keys == null)
+ throw new NullPointerException("Keys source is null");
+ StringBuffer out = new StringBuffer();
+ int index = 0;
+ int i = 0;
+ String key = null;
+ while ((index = in.indexOf(startTag, i)) > -1) {
+ key = in.substring(index + 2, in.indexOf(endTag, index + 3));
+ out.append(in.substring(i, index));
+ if (keys.containsKey(key)) {
+ out.append(keys.get(key));
+ } else {
+ out.append(startTag).append(key).append(endTag);
+ }
+ i = index + 3 + key.length();
+ }
+ return out.append(in.substring(i)).toString();
+ }
+
+ /**
+ * @param in the key which string value to be replaced with values from
+ * this property list
+ */
+ public String replace(String in) {
+ if (in == null)
+ return null;
+ StringBuffer out = new StringBuffer();
+ int index = 0;
+ int i = 0;
+ String key = null;
+ while ((index = in.indexOf(startTag, i)) > -1) {
+ key = in.substring(index + 2, in.indexOf(endTag, index + 3));
+ out.append(in.substring(i, index));
+ String val = super.getProperty(key);
+ if (val != null) {
+ // be careful here
+ out.append(replace(val));
+ } else {
+ out.append(startTag).append(key).append(endTag);
+ }
+ i = index + 3 + key.length();
+ }
+ return out.append(in.substring(i)).toString();
+ }
+
+ /**
+ * Replaces all occurrences of the substitution tag in the given Properties.
+ */
+ protected void replaceAll(Properties p) {
+ for (Enumeration en = p.keys(); en.hasMoreElements();) {
+ String k = (String)en.nextElement();
+ Object v = p.get(k);
+ if (v instanceof String) {
+ String nv = replace((String)v);
+ p.put(k, nv);
+ }
+ if (v instanceof Properties)
+ replaceAll((Properties)v);
+ }
+ }
+
+ protected static char startSecSep = '[';
+
+ protected static char endSecSep = ']';
+
+ protected static String startTag = "${";
+
+ protected static String endTag = "}";
+
+ private String curSec = "";
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("{\n");
+ for(String key: stringPropertyNames()) {
+ sb.append("\t(").append(key).append(",").append(getProperty(key)).append(")\n");
+ }
+ sb.append("}\n");
+ return sb.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright
+ * 2005 axYus - www.axyus.com
+ * 2005 L.Meckert - lmeckert@club-internet.fr
+ *
+ * This file is part of XEMELIOS.
+ *
+ * XEMELIOS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * XEMELIOS 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XEMELIOS; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package fr.gouv.finances.cp.xemelios.starter;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import fr.gouv.finances.cp.utils.PropertiesExpansion;
+import fr.gouv.finances.cp.xemelios.updater.starter.Updater;
+import java.lang.reflect.Constructor;
+import java.net.ServerSocket;
+import javax.swing.JOptionPane;
+
+/**
+ * Cette class est le lanceur de Xemelios
+ * @author cmarchand
+ */
+public class Bootstrap {
+ private static final Class[] parameters = new Class[] { URL.class };
+
+ public static void addFile(String s) throws IOException {
+ File f = new File(s);
+ addFile(f);
+ }
+
+ public static void addFile(File f) throws IOException {
+ addURL(f.toURI().toURL());
+ }
+
+ // bitonio trouvé sur le net
+ public static void addURL(URL u) throws IOException {
+ URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
+ Class sysclass = URLClassLoader.class;
+
+ try {
+ Method method = sysclass.getDeclaredMethod("addURL", parameters);
+ method.setAccessible(true); // voyou
+ method.invoke(sysloader, new Object[] { u });
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw new IOException("Error, could not add URL to system classloader");
+ }
+
+ }
+
+ static PropertiesExpansion restoreProperties() {
+ PropertiesExpansion properties = new PropertiesExpansion();
+ String propsFileName = System.getProperty("xemelios.properties");
+ if (propsFileName == null) {
+ propsFileName = "xemelios.properties";
+ } // fichier de ce nom dans rep courant
+ File propsFile = new File(propsFileName);
+ try {
+ if (propsFile.isFile() && propsFile.canRead()) {
+ } else {
+ System.err.println("Impossible d'accéder à " + propsFileName);
+ }
+ }
+ catch (SecurityException se) {
+ System.err.println("Problème d'accès au fichier " + propsFileName);
+ }
+ if (propsFile != null) {
+ try {
+ FileInputStream in = new FileInputStream(propsFile);
+ properties.load(in);
+ } catch (IOException ioe) {
+ System.err.println("Cannot load properties " + ioe);
+ return null;
+ }
+ }
+ // on ajoute toutes les propriétés système
+ for(String propName: System.getProperties().stringPropertyNames())
+ properties.setProperty(propName, System.getProperty(propName));
+ return properties;
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ PropertiesExpansion applicationConfiguration = restoreProperties();
+ // TODO
+ // ouverture d'une socket pour contrôler l'unicité du Xemelios sur le poste
+ try {
+ int port = 8973;
+ String sTmp = applicationConfiguration.getProperty("xemelios.isolation.port");
+ if(sTmp!=null) {
+ try {
+ port = Integer.parseInt(sTmp);
+ } catch(Exception ignorable) {}
+ }
+ ServerSocket ss = new ServerSocket(port);
+ // maintenant, il faut s'assurer que l'on fermera bien cela
+ ServerSocketCloser ssc = new ServerSocketCloser(ss);
+ Runtime.getRuntime().addShutdownHook(ssc);
+ } catch(Exception ex) {
+ JOptionPane.showMessageDialog(null, "Un autre Xemelios est déjà en cours d'execution");
+ System.exit(1);
+ }
+ new Updater(applicationConfiguration);
+
+ String classdirs = applicationConfiguration.getProperty("xemelios.jars.dir");
+ String startClassName = applicationConfiguration.getProperty("xemelios.startclass");
+ String[] classdirsArray = classdirs.split(";");
+
+ for (int dir = 0; dir < classdirsArray.length; ++dir) {
+ try {
+ File jarsdir = new File(classdirsArray[dir]);
+ addURL(new URL("file:" + jarsdir.getAbsolutePath()));
+ File[] listJars = jarsdir.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File pathname) {
+ String s = pathname.getPath();
+ return s.endsWith(".jar");
+ }
+ });
+ for (int i = 0; i < listJars.length; ++i) {
+ addURL(new URL("file:" + listJars[i].getAbsolutePath()));
+ }
+ }
+ catch (NullPointerException n) {
+ System.err.println("Impossible de trouver le repertoire " + classdirsArray[dir]);
+ }
+ }
+
+ Class startClass = Class.forName(startClassName);
+ Constructor cc = startClass.getConstructor(PropertiesExpansion.class,String[].class);
+ cc.newInstance(applicationConfiguration, args);
+ }
+
+ private static class ServerSocketCloser extends Thread {
+ private ServerSocket ss;
+ ServerSocketCloser(ServerSocket socketToClose) {
+ super();
+ this.ss = socketToClose;
+ }
+
+ @Override
+ public void run() {
+ try {
+ ss.close();
+ } catch(Exception ex) {
+ // on ignore
+ }
+ }
+
+ }
+}
--- /dev/null
+Pour demarrer la classe bootstrap en cliquant sur le jar :
+utiliser le fichier manifest.txt qui doit contenir la ligne
+Main-Class: fr.gouv.finances.cp.outil.common.Bootstrap
+
+une fois le jar demat.jar constitué avec les classes de l'appli, il faut lancer
+jar umf manifest.txt demat.jar
--- /dev/null
+/*
+ * Copyright
+ * 2006 axYus - www.axyus.com
+ * 2006 C.Marchand - christophe.marchand@axyus.com
+ *
+ * This file is part of XEMELIOS.
+ *
+ * XEMELIOS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * XEMELIOS 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XEMELIOS; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package fr.gouv.finances.cp.xemelios.updater.starter;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+
+import fr.gouv.finances.cp.utils.PropertiesExpansion;
+
+/**
+ * This class is responsible of patching xemelios installation directory
+ * with previously downloaded files.
+ * If no download is available or if it is incomplete, it destroys
+ * the download directory and advise user he has to update again.
+ * @author chm
+ *
+ */
+public class Updater {
+
+ private PropertiesExpansion props;
+// private static final transient String TMP_ENTRY = "fr.gouv.finances.cp.xemelios.updater.starter.Updater.tmp";
+ private StringBuilder xmlScript;
+ private PrintStream output;
+
+ public Updater(PropertiesExpansion applicationProperties) {
+ super();
+ props = applicationProperties;
+// props = new PropertiesExpansion();
+ xmlScript = new StringBuilder("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<update-script>\n");
+// for(Object s:System.getProperties().keySet()) props.put(s,System.getProperty((String)s));
+ boolean bRet = false;
+ //Properties props = new Properties();
+ File tmpDir = new File(applicationProperties.getProperty("xemelios.dir")+"/tmp-upd");
+ File outputFile = new File(applicationProperties.getProperty("xemelios.dir"),"update.log");
+ //if(outputFile.exists()) outputFile.delete();
+ try {
+ output = new PrintStream(new FileOutputStream(outputFile,false));
+ } catch(FileNotFoundException fnfEx) {
+ output = System.out;
+ try {
+ System.out.println("unable to write to "+outputFile.getCanonicalPath());
+ } catch(Throwable t) {}
+ }
+ if(tmpDir.exists()) {
+ try {
+ File batch = new File(tmpDir,"update-script.xem");
+ if(batch.exists()) {
+ ArrayList<String> lines = new ArrayList<String>();
+ BufferedReader br = new BufferedReader(new FileReader(batch));
+ String line = br.readLine();
+ while(line!=null) {
+ lines.add(line);
+ line=br.readLine();
+ }
+ br.close();
+
+ for(String s:lines) {
+ if(s.startsWith("copy")) checkAvailability(s,tmpDir);
+ }
+
+ for(String s:lines) {
+ if(s.startsWith("copy")) doCopy(s,tmpDir);
+ else if(s.startsWith("delete")) doDelete(s);
+ else if(s.startsWith("install-component")) doInstallComponent(s);
+ else if(s.startsWith("remove-component")) doRemoveComponent(s);
+ else if(s.startsWith("configuration")) doConfiguration(s);
+ }
+
+ xmlScript.append("</update-script>");
+ File f = new File(props.replace("${xemelios.prg}"),"update-script.xml");
+ FileOutputStream fos = new FileOutputStream(f);
+ fos.write(xmlScript.toString().getBytes("ISO-8859-1"));
+ fos.flush(); fos.close();
+ bRet = true;
+ }
+ } catch(IOException ioEx) {
+ bRet = false;
+ ioEx.printStackTrace();
+ } catch(Exception ex) {
+ bRet = false;
+ ex.printStackTrace();
+ }
+ if(!bRet) {
+ JOptionPane.showMessageDialog((JFrame)null,"Il y a eu un problème lors de la mise à jour de Xemelios.\nVous devez recommencer le processus de mise à jour.","Erreur",JOptionPane.ERROR_MESSAGE);
+ } else {
+ JOptionPane.showMessageDialog((JFrame)null,"Xemelios a été correctement mis à jour.","Mise à jour",JOptionPane.INFORMATION_MESSAGE);
+ }
+ // at least, destroy directory
+ for(File f:tmpDir.listFiles()) f.delete();
+ tmpDir.delete();
+ } else {
+ output.println("no update dir found at "+tmpDir.getAbsolutePath());
+ }
+ }
+
+ private void doCopy(String line,File updateDir) throws Exception {
+ String[] args=splittLine(line);
+ File f = new File(updateDir,args[1]);
+ FileInfo fi = new FileInfo(f.getCanonicalPath(),props.replace(args[2]));
+ if(!copyFile(fi)) throw new Exception();
+ output.println("copying from "+fi.tmpFileName+" to "+fi.destFileName);
+ }
+ private void doDelete(String line) throws Exception {
+ String[] args = splittLine(line);
+ File f = new File(props.replace(args[1]));
+ if(f.exists()) f.delete();
+ output.println("deleting "+props.replace(args[1]));
+ }
+ private void doInstallComponent(String line) throws Exception {
+ String[] args = splittLine(line);
+ String id = args[1];
+ String version = args[2];
+ String description = args[3];
+ xmlScript.append(" <component id=\"").append(id).append("\" version=\"").append(version).append("\" description=\"").append(description).append("\"/>\n");
+ output.println("preparing to install component "+id+" - "+version+" - "+description);
+ }
+ private void doRemoveComponent(String line) throws Exception {
+ String[] args = splittLine(line);
+ String id = args[1];
+ //String version = args[2];
+ //String description = args[3];
+ xmlScript.append(" <remove-component id=\"").append(id).append("\"/>\n");
+ output.println("preparing to remove component "+id);
+ }
+ private void doConfiguration(String line) throws Exception {
+ String[] args = splittLine(line);
+ String className = args[1];
+ xmlScript.append(" <configurator class=\"").append(className).append("\"");
+ if(args.length>2) {
+ xmlScript.append(" >\n");
+ for(int i=2;i<args.length;) {
+ xmlScript.append(" <param name=\"").append(args[i++]).append("\">").append(args[i++]).append("</param>\n");
+ }
+ xmlScript.append(" </configurator>\n");
+ } else {
+ xmlScript.append("/>\n");
+ }
+ output.println("preparing configurator "+className);
+ }
+
+ private void checkAvailability(String line,File updateDir) throws Exception {
+ String[] args = splittLine(line);
+ File f = new File(updateDir,args[1]);
+ FileInfo fi = new FileInfo(f.getCanonicalPath(),args[2]);
+ if(!isAvailable(fi)) throw new Exception(fi.tmpFileName+" not available.");
+ }
+
+ private boolean copyFile(FileInfo fi) {
+ try {
+ File dest = new File(fi.destFileName);
+ File dir = dest.getParentFile();
+ if(dir!=null && !dir.exists()) {
+ output.println("trying to create "+dir.getAbsolutePath()+" directory");
+ dir.mkdirs();
+ }
+ if(dest.exists()) dest.delete();
+ FileInputStream fis = new FileInputStream(fi.tmpFileName);
+ FileOutputStream fos = new FileOutputStream(dest);
+ FileChannel inputChannel = fis.getChannel();
+ FileChannel outputChannel = fos.getChannel();
+ outputChannel.transferFrom(inputChannel,0,inputChannel.size());
+ outputChannel.close();
+ inputChannel.close();
+ return true;
+ } catch(IOException ioEx) {
+ output.println("while copying "+fi.tmpFileName+" to "+fi.destFileName+"\n"+ioEx.getMessage());
+ return false;
+ }
+ }
+
+ private static boolean isAvailable(FileInfo fi) {
+ File f = new File (fi.tmpFileName);
+ return f.exists();
+ }
+ private static String[] splittLine(String line) {
+ StringTokenizer st = new StringTokenizer(line,"|");
+ int tokens = st.countTokens();
+ String[] ret = new String[tokens];
+ for(int i=0;i<tokens;i++) ret[i]=st.nextToken();
+ return ret;
+ }
+ private class FileInfo {
+ String tmpFileName, destFileName;
+ public FileInfo(String source, String dest) {
+ super();
+ this.tmpFileName=source;
+ this.destFileName=dest;
+ }
+ }
+}
--- /dev/null
+Manifest-version: 1.0
+Jar-Version: @version@
+Jar-Content: @name@
+Main-Class: fr.gouv.finances.cp.xemelios.starter.Bootstrap
\ No newline at end of file