1 /* 2 Launch4j (http://launch4j.sourceforge.net/) 3 Cross-platform Java application wrapper for creating Windows native executables. 4 5 Copyright (c) 2004, 2015 Grzegorz Kowal 6 All rights reserved. 7 8 Redistribution and use in source and binary forms, with or without modification, 9 are permitted provided that the following conditions are met: 10 11 1. Redistributions of source code must retain the above copyright notice, 12 this list of conditions and the following disclaimer. 13 14 2. Redistributions in binary form must reproduce the above copyright notice, 15 this list of conditions and the following disclaimer in the documentation 16 and/or other materials provided with the distribution. 17 18 3. Neither the name of the copyright holder nor the names of its contributors 19 may be used to endorse or promote products derived from this software without 20 specific prior written permission. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 24 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Created on Apr 22, 2005 36 */ 37 package net.sf.launch4j.config; 38 39 import java.io.BufferedWriter; 40 import java.io.File; 41 import java.io.FileInputStream; 42 import java.io.FileOutputStream; 43 import java.io.IOException; 44 import java.io.OutputStreamWriter; 45 import java.util.ArrayList; 46 import java.util.List; 47 import java.util.Properties; 48 49 import javax.xml.parsers.DocumentBuilder; 50 import javax.xml.parsers.DocumentBuilderFactory; 51 52 import org.w3c.dom.Document; 53 import org.w3c.dom.ls.DOMImplementationLS; 54 import org.w3c.dom.ls.LSSerializer; 55 56 import net.sf.launch4j.Util; 57 58 import com.thoughtworks.xstream.XStream; 59 import com.thoughtworks.xstream.io.xml.DomDriver; 60 61 /** 62 * @author Copyright (C) 2014 Grzegorz Kowal 63 */ 64 public class ConfigPersister { 65 66 private static final ConfigPersister _instance = new ConfigPersister(); 67 68 private final XStream _xstream; 69 private Config _config; 70 private File _configPath; 71 ConfigPersister()72 private ConfigPersister() { 73 _xstream = new XStream(new DomDriver()); 74 _xstream.alias("launch4jConfig", Config.class); 75 _xstream.alias("classPath", ClassPath.class); 76 _xstream.alias("jre", Jre.class); 77 _xstream.alias("splash", Splash.class); 78 _xstream.alias("versionInfo", VersionInfo.class); 79 80 _xstream.addImplicitCollection(Config.class, "headerObjects", "obj", 81 String.class); 82 _xstream.addImplicitCollection(Config.class, "libs", "lib", String.class); 83 _xstream.addImplicitCollection(Config.class, "variables", "var", String.class); 84 _xstream.addImplicitCollection(ClassPath.class, "paths", "cp", String.class); 85 _xstream.addImplicitCollection(Jre.class, "options", "opt", String.class); 86 } 87 getInstance()88 public static ConfigPersister getInstance() { 89 return _instance; 90 } 91 getConfig()92 public Config getConfig() { 93 return _config; 94 } 95 getConfigPath()96 public File getConfigPath() { 97 return _configPath; 98 } 99 getOutputPath()100 public File getOutputPath() throws IOException { 101 if (_config.getOutfile().isAbsolute()) { 102 return _config.getOutfile().getParentFile(); 103 } 104 File parent = _config.getOutfile().getParentFile(); 105 return (parent != null) ? new File(_configPath, parent.getPath()) : _configPath; 106 } 107 getOutputFile()108 public File getOutputFile() throws IOException { 109 return _config.getOutfile().isAbsolute() 110 ? _config.getOutfile() 111 : new File(getOutputPath(), _config.getOutfile().getName()); 112 } 113 createBlank()114 public void createBlank() { 115 _config = new Config(); 116 _config.setJre(new Jre()); 117 _configPath = null; 118 } 119 setAntConfig(Config c, File basedir)120 public void setAntConfig(Config c, File basedir) { 121 _config = c; 122 _configPath = basedir; 123 } 124 load(File f)125 public void load(File f) throws ConfigPersisterException { 126 try { 127 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 128 DocumentBuilder builder = factory.newDocumentBuilder(); 129 Document doc = builder.parse(f); 130 131 DOMImplementationLS domImplementation = (DOMImplementationLS) doc.getImplementation(); 132 LSSerializer lsSerializer = domImplementation.createLSSerializer(); 133 String configString = lsSerializer.writeToString(doc); 134 135 _config = (Config) _xstream.fromXML(convertToCurrent(configString)); 136 setConfigPath(f); 137 } catch (Exception e) { 138 throw new ConfigPersisterException(e); 139 } 140 } 141 142 /** 143 * Imports launch4j 1.x.x config file. 144 */ loadVersion1(File f)145 public void loadVersion1(File f) throws ConfigPersisterException { 146 try { 147 Props props = new Props(f); 148 _config = new Config(); 149 String header = props.getProperty(Config.HEADER); 150 _config.setHeaderType(header == null 151 || header.toLowerCase().equals("guihead.bin") ? Config.GUI_HEADER 152 : Config.CONSOLE_HEADER); 153 _config.setJar(props.getFile(Config.JAR)); 154 _config.setOutfile(props.getFile(Config.OUTFILE)); 155 _config.setJre(new Jre()); 156 _config.getJre().setPath(props.getProperty(Jre.PATH)); 157 _config.getJre().setMinVersion(props.getProperty(Jre.MIN_VERSION)); 158 _config.getJre().setMaxVersion(props.getProperty(Jre.MAX_VERSION)); 159 160 String args = props.getProperty(Jre.ARGS); 161 162 if (args != null) { 163 List<String> jreOptions = new ArrayList<String>(); 164 jreOptions.add(args); 165 _config.getJre().setOptions(jreOptions); 166 } 167 168 _config.setCmdLine(props.getProperty(Config.JAR_ARGS)); 169 _config.setChdir("true".equals(props.getProperty(Config.CHDIR)) 170 ? "." : null); 171 _config.setStayAlive("true".equals(props.getProperty(Config.STAY_ALIVE))); 172 _config.setErrTitle(props.getProperty(Config.ERR_TITLE)); 173 _config.setIcon(props.getFile(Config.ICON)); 174 175 File splashFile = props.getFile(Splash.SPLASH_FILE); 176 177 if (splashFile != null) { 178 _config.setSplash(new Splash()); 179 _config.getSplash().setFile(splashFile); 180 String waitfor = props.getProperty("waitfor"); // 1.x 181 _config.getSplash().setWaitForWindow(waitfor != null 182 && !waitfor.equals("")); 183 String splashTimeout = props.getProperty(Splash.TIMEOUT); 184 if (splashTimeout != null) { 185 _config.getSplash().setTimeout(Integer.parseInt(splashTimeout)); 186 } 187 _config.getSplash().setTimeoutErr("true".equals( 188 props.getProperty(Splash.TIMEOUT_ERR))); 189 } else { 190 _config.setSplash(null); 191 } 192 setConfigPath(f); 193 } catch (IOException e) { 194 throw new ConfigPersisterException(e); 195 } 196 } 197 save(File f)198 public void save(File f) throws ConfigPersisterException { 199 try { 200 BufferedWriter w = new BufferedWriter( 201 new OutputStreamWriter(new FileOutputStream(f), "UTF-8")); 202 w.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); 203 _xstream.toXML(_config, w); 204 w.close(); 205 setConfigPath(f); 206 } catch (Exception e) { 207 throw new ConfigPersisterException(e); 208 } 209 } 210 211 /** 212 * Converts 2.x config to current format. 213 */ convertToCurrent(String configString)214 private String convertToCurrent(String configString) { 215 return configString 216 .replaceAll("<headerType>0<", "<headerType>gui<") 217 .replaceAll("<headerType>1<", "<headerType>console<") 218 .replaceAll("jarArgs>", "cmdLine>") 219 .replaceAll("<jarArgs[ ]*/>", "<cmdLine/>") 220 .replaceAll("args>", "opt>") 221 .replaceAll("<args[ ]*/>", "<opt/>") 222 .replaceAll("<dontUsePrivateJres>false</dontUsePrivateJres>", 223 "<jdkPreference>" + Jre.JDK_PREFERENCE_PREFER_JRE + "</jdkPreference>") 224 .replaceAll("<dontUsePrivateJres>true</dontUsePrivateJres>", 225 "<jdkPreference>" + Jre.JDK_PREFERENCE_JRE_ONLY + "</jdkPreference>") 226 .replaceAll("<initialHeapSize>0</initialHeapSize>", "") 227 .replaceAll("<maxHeapSize>0</maxHeapSize>", "") 228 .replaceAll("<customProcName>.*</customProcName>", ""); 229 } 230 setConfigPath(File configFile)231 private void setConfigPath(File configFile) { 232 _configPath = configFile.getAbsoluteFile().getParentFile(); 233 } 234 235 private class Props { 236 final Properties _properties = new Properties(); 237 Props(File f)238 public Props(File f) throws IOException { 239 FileInputStream is = null; 240 try { 241 is = new FileInputStream(f); 242 _properties.load(is); 243 } finally { 244 Util.close(is); 245 } 246 } 247 248 /** 249 * Get property and remove trailing # comments. 250 */ getProperty(String key)251 public String getProperty(String key) { 252 String p = _properties.getProperty(key); 253 254 if (p == null) { 255 return null; 256 } 257 258 int x = p.indexOf('#'); 259 260 if (x == -1) { 261 return p; 262 } 263 264 do { 265 x--; 266 } while (x > 0 && (p.charAt(x) == ' ' || p.charAt(x) == '\t')); 267 268 return (x == 0) ? "" : p.substring(0, x + 1); 269 } 270 getFile(String key)271 public File getFile(String key) { 272 String value = getProperty(key); 273 return value != null ? new File(value) : null; 274 } 275 } 276 } 277