1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 package org.openoffice.test.common;
22 
23 import java.io.File;
24 import java.io.IOException;
25 import java.lang.reflect.Method;
26 import java.net.URL;
27 import java.net.URLClassLoader;
28 import java.text.MessageFormat;
29 import java.util.logging.Level;
30 
31 /**
32  * Install openoffice from installation package before running test
33  *
34  */
35 public class Installer implements Runnable {
36 	private static Logger log = Logger.getLogger(Installer.class);
37 	File downloadDir = Testspace.getFile("download");
38 	File downloadUrl = Testspace.getFile("download/url");
39 	File installDir = Testspace.getFile("install");
40 	File installTempDir = Testspace.getFile("install_temp");
41 
42 	@Override
run()43 	public void run() {
44 		String prop = System.getProperty("singleton");
45 		if ("true".equalsIgnoreCase(prop) || "yes".equalsIgnoreCase(prop)) {
46 			if (SystemUtil.findProcesses(".*org\\.openoffice\\.test\\.common\\.Installer.*").size() > 1) {
47 				throw new RuntimeException("Only allow one running test instance!");
48 			}
49 		}
50 
51 		prop = findOpenofficeHome();
52 		System.setProperty("openoffice.home", prop);
53 		log.log(Level.INFO, MessageFormat.format("OpenOffice in {0} will be tested.", prop));
54 
55 		String[] jars = { "juh.jar", "unoil.jar", "ridl.jar", "jurt.jar" };
56 		for (String jar : jars) {
57 			File file = FileUtil.findFile(prop, jar);
58 
59 			if (file != null)
60 				addToClassPath(file);
61 		}
62 
63 	}
64 
findOpenofficeHome()65 	private String findOpenofficeHome() {
66 		String prop = System.getProperty("openoffice.home");
67 		if (prop != null) {
68 			validateOpenOfficeInstallation(new File(prop));
69 			return prop;
70 		}
71 
72 		if ((prop = System.getProperty("openoffice.pack")) != null) {
73 			String onlyNewProp = System.getProperty("only.new");
74 			File packFile = null;
75 			if (FileUtil.isUrl(prop)) {
76 				log.log(Level.INFO, MessageFormat.format("Try to download {0}...", prop));
77 				String url = FileUtil.readFileAsString(downloadUrl);
78 				if (!prop.equals(url)) {
79 					FileUtil.deleteFile(downloadDir);
80 					downloadDir.mkdirs();
81 					packFile = FileUtil.download(prop, downloadDir);
82 					if (packFile == null)
83 						throw new RuntimeException(MessageFormat.format("{0} can not be downloaded!", prop));
84 					FileUtil.writeStringToFile(downloadUrl, prop);
85 				} else {
86 					boolean[] skipped = { false };
87 					packFile = FileUtil.download(prop, downloadDir, true, skipped);
88 					if (packFile == null)
89 						throw new RuntimeException(MessageFormat.format("{0} can not be downloaded!", prop));
90 					if (("true".equalsIgnoreCase(onlyNewProp) || "yes".equalsIgnoreCase(onlyNewProp)) && skipped[0])
91 						throw new RuntimeException(MessageFormat.format("{0} is old. Test is allowed only on new build.", prop));
92 				}
93 			} else {
94 				packFile = new File(prop);
95 				if (!packFile.isFile())
96 					throw new RuntimeException(MessageFormat.format("{0} does not exists or is not a file!", prop));
97 			}
98 
99 			try {
100 				FileUtil.deleteFile(installDir);
101 				FileUtil.deleteFile(installTempDir);
102 				installTempDir.mkdirs();
103 				if (packFile.getName().endsWith(".gz")) {
104 					StringBuffer output = new StringBuffer();
105 					if (SystemUtil.exec(new String[] { "tar", "-zxpf", packFile.getAbsolutePath(), "-C", installTempDir.getAbsolutePath() }, output) != 0)
106 						throw new RuntimeException(MessageFormat.format("{0} can not be installed! Cause: {1}", packFile, output));
107 				} else {
108 					if (!FileUtil.unzip(packFile, installTempDir))
109 						throw new RuntimeException(MessageFormat.format("{0} can not be installed!", packFile));
110 				}
111 				// On windows, if path is too long, openoffice can not be
112 				// started.
113 				File[] files = installTempDir.listFiles();
114 				if (files != null && files.length == 1 && files[0].isDirectory()) {
115 					files[0].renameTo(installDir);
116 				}
117 				validateOpenOfficeInstallation(installDir);
118 				return installDir.getAbsolutePath();
119 			} finally {
120 				FileUtil.deleteFile(installTempDir);
121 			}
122 		}
123 
124 		// Try look for the output of ./configure --with-package-format="installed"
125 		final String srcRoot = System.getenv("SRC_ROOT");
126 		final String inPath = System.getenv("INPATH");
127 		if (srcRoot == null || inPath == null) {
128 			throw new RuntimeException("Neither openoffice.home nor openoffice.pack were specified, and could not autodetect OpenOffice " +
129 				"from ${SRC_ROOT} and ${INPATH}. Please make sure OpenOffice was built with the --with-package-format=\"installed\" option, " +
130 				"and you ran \"source <platform>.set.sh\"");
131 		}
132 		final File instsetoo_native = new File(srcRoot, "instsetoo_native");
133 		final File buildDir = new File(instsetoo_native, inPath);
134 		final File apacheOpenOffice = new File(buildDir, "Apache_OpenOffice");
135 		final File installed = new File(apacheOpenOffice, "installed");
136 		final File install = new File(installed, "install");
137 		final File enUs = new File(install, "en-US");
138 		// *nix:
139 		File openoffice4 = new File(enUs, "openoffice4");
140 		if (!openoffice4.exists()) {
141 			// Windows:
142 			openoffice4 = new File(enUs, "OpenOffice 4");
143 		}
144 		if (!openoffice4.exists()) {
145 			throw new RuntimeException("Neither openoffice.home nor openoffice.pack were specified, and could not find OpenOffice in " + openoffice4.getAbsolutePath());
146 		}
147 		validateOpenOfficeInstallation(openoffice4);
148 		return openoffice4.getAbsolutePath();
149 	}
150 
validateOpenOfficeInstallation(File directory)151 	private static void validateOpenOfficeInstallation(File directory) {
152 		final File sofficeBin = FileUtil.findFile(directory, "soffice.bin", false);
153 		if (sofficeBin == null) {
154 			throw new RuntimeException(MessageFormat.format(
155 				"No valid OpenOffice found in {0}!", directory.getAbsolutePath()));
156 		}
157 	}
158 
addToClassPath(File file)159 	public static boolean addToClassPath(File file) {
160 		try {
161 			URL url = file.toURI().toURL();
162 			URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
163 			Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
164 			method.setAccessible(true);
165 			method.invoke(classLoader, new Object[] { url });
166 			return true;
167 		} catch (Throwable t) {
168 			t.printStackTrace();
169 		}
170 
171 		return false;
172 	}
173 
main(String... args)174 	public static void main(String... args) {
175 		new Installer().run();
176 	}
177 }
178