xref: /AOO41X/test/testcommon/source/org/openoffice/test/OpenOffice.java (revision 44cf02803b51681da4056cdf9500cc33ee29bd2f)
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 
22 package org.openoffice.test;
23 
24 import java.io.File;
25 import java.io.IOException;
26 import java.net.MalformedURLException;
27 import java.net.URL;
28 import java.text.SimpleDateFormat;
29 import java.util.ArrayList;
30 import java.util.Date;
31 import java.util.HashMap;
32 import java.util.Map.Entry;
33 import java.util.Properties;
34 import java.util.Set;
35 import java.util.UUID;
36 import java.util.logging.Logger;
37 
38 import org.openoffice.test.common.FileUtil;
39 import org.openoffice.test.common.SystemUtil;
40 
41 /**
42  * It represents one OpenOffice instance.
43  * By default, the instance will be started with automation and socket UNO connection enabled.
44  *
45  */
46 public class OpenOffice {
47 
48     private static Logger LOG = Logger.getLogger(OpenOffice.class.getName());
49 
50     private static final String[] DEFAULT_HOME = new String[] {
51         "C:/Program Files/OpenOffice.org 3",
52         "C:/Program Files (x86)/OpenOffice.org 3",
53         "/Applications/OpenOffice.org.app/Contents",
54         "/opt/openoffice.org3",
55     };
56 
57     private static final String USERHOME = System.getProperty("user.home");
58     private static final String BIN = SystemUtil.isWindows() ? "program/soffice.exe" : SystemUtil.isMac() ? "MacOS/soffice": "program/soffice";
59     private static final String SYSUSERCONFIG = SystemUtil.isWindows()? System.getenv("APPDATA") : SystemUtil.isMac() ?  USERHOME + "/Library/Application Support" : USERHOME;
60     public static final String DEFAULT_UNO_URL = "socket,host=127.0.0.1,port=2002;urp";
61     public static final int DEFAULT_AUTOMATION_PORT = 12479;
62 
63     private static OpenOffice defaultInstance = null;
64 
65     private File userInstallation = null;
66 
67     private File defaultUserInstallation = null;
68 
69     private File home = null;
70 
71     private File bin = null;
72 
73     private String binPath = null;
74 
75     private ArrayList<String> args = new ArrayList<String>();
76 
77     private ArrayList<String> registryModifications = new ArrayList<String>();
78 
79     private int automationPort = 0;
80 
81     private Process process = null;
82 
83     private String unoUrl = null;
84 
85     private Properties versionProps = null;
86 
87     private String id = UUID.randomUUID().toString().replace("-", "");
88 
89     private String processPattern = SystemUtil.isMac() ? ".*soffice .*" + id + ".*" : ".*soffice\\.bin.*" + id + ".*|.*soffice\\.exe.*" + id + ".*-env.*";
90 
OpenOffice()91     public OpenOffice() {
92         this(null);
93     }
94 
95     /**
96      * Construct Process with the home path of OpenOffice.
97      *
98      * @param appHome
99      */
OpenOffice(String appHome)100     public OpenOffice(String appHome) {
101         if (appHome == null)
102             appHome = System.getProperty("openoffice.home");
103         if (appHome == null)
104             appHome = System.getenv("OPENOFFICE_HOME");
105         if (appHome == null) {
106             // Search in the classpath
107             try {
108                 URL url = getClass().getClassLoader().getResource(BIN);
109                 File file = new File(url.toURI());
110                 if (file.exists())
111                     appHome = file.getParentFile().getParentFile().getAbsolutePath();
112             } catch (Exception e) {
113                 // ignore
114             }
115         }
116 
117         if (appHome == null) {
118             for (int i = 0; i < DEFAULT_HOME.length; i++)
119                 if (new File(DEFAULT_HOME[i]).exists())
120                     appHome = DEFAULT_HOME[i];
121         }
122 
123         home = new File(appHome);
124         bin = new File(appHome, BIN);
125         try {
126             binPath = bin.getCanonicalPath();
127         } catch (IOException e1) {
128         }
129         File binParent = bin.getParentFile();
130         File bootstrapFile = new File(binParent, "bootstraprc");
131         if (!bootstrapFile.exists())
132             bootstrapFile = new File(binParent, "bootstrap.ini");
133         if (!bootstrapFile.exists())
134             throw new Error("OpenOffice can not be found or it's broken. Testing can not be performed. " +
135                     "Use system property openoffice.home to specify the correct location of OpenOffice.");
136 
137         Properties props = FileUtil.loadProperties(bootstrapFile);
138         String defaultUserInstallationPath = props.getProperty("UserInstallation").replace("$ORIGIN", binParent.getAbsolutePath()).replace("$SYSUSERCONFIG", SYSUSERCONFIG);
139         defaultUserInstallation = new File(defaultUserInstallationPath);
140 
141         File versionFile = new File(binParent, "versionrc");
142         if (!versionFile.exists())
143             versionFile = new File(binParent, "version.ini");
144         versionProps = FileUtil.loadProperties(versionFile);
145         Set<Entry<Object, Object>> entries = versionProps.entrySet();
146         for (Entry<Object, Object> e : entries) {
147             System.setProperty("info.app." + e.getKey(), (String)e.getValue());
148         }
149         //
150         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
151         System.setProperty("info.app.date", dateFormat.format(new Date(versionFile.lastModified())));
152         addArgs("-" + id);
153     }
154 
getDefault()155     public static OpenOffice getDefault() {
156         if (defaultInstance == null) {
157             defaultInstance = new OpenOffice();
158             defaultInstance.setAutomationPort(DEFAULT_AUTOMATION_PORT);
159             defaultInstance.setUnoUrl(DEFAULT_UNO_URL);
160             defaultInstance.addArgs("-nofirststartwizard", "-norestore", "-quickstart=no");
161             defaultInstance.addRegistryModifications("<item oor:path=\"/org.openoffice.Office.Common/Misc\"><prop oor:name=\"UseSystemFileDialog\" oor:op=\"fuse\"><value>false</value></prop></item>",
162                     "<item oor:path=\"/org.openoffice.Office.Common/Security/Scripting\"><prop oor:name=\"MacroSecurityLevel\" oor:op=\"fuse\"><value>0</value></prop></item>");
163         }
164 
165         return defaultInstance;
166     }
167 
restoreDefault()168     public static void restoreDefault() {
169         if (defaultInstance != null) {
170 
171         }
172     }
173 
getVersionProps()174     public Properties getVersionProps() {
175         return versionProps;
176     }
177 
178     /**
179      * Set UserInstallation directory. When openoffice is launched, the argument
180      * "-env:UserInstallation" will be enabled.
181      *
182      * @param dir
183      *            user installation directory. If null is given, the default
184      *            will be used.
185      */
setUserInstallation(File dir)186     public void setUserInstallation(File dir) {
187         userInstallation = dir;
188     }
189 
190     /**
191      * Get UserInstallation directory
192      *
193      * @return
194      */
getUserInstallation()195     public File getUserInstallation() {
196         return userInstallation == null ? defaultUserInstallation : userInstallation;
197     }
198 
199     /**
200      * Get default UserInstallation directory
201      *
202      * @return
203      */
getDefaultUserInstallation()204     public File getDefaultUserInstallation() {
205         return defaultUserInstallation;
206     }
207 
208     /**
209      * Clean the user installation
210      */
cleanUserInstallation()211     public void cleanUserInstallation() {
212         FileUtil.deleteFile(getUserInstallation());
213     }
214 
215     /**
216      * Get installation directory of OpenOffice.
217      *
218      * @return
219      */
getHome()220     public File getHome() {
221         return home;
222     }
223 
224     /**
225      * Set other command line arguments
226      *
227      * @param args
228      */
addArgs(String... arguments)229     public void addArgs(String... arguments) {
230         for (String a : arguments)
231             args.add(a);
232     }
233 
addRegistryModifications(String... items)234     public void addRegistryModifications(String... items) {
235         for (String i : items)
236             registryModifications.add(i);
237     }
238 
getAutomationPort()239     public int getAutomationPort() {
240         return automationPort;
241     }
242 
243     /**
244      * Set automation server listening port
245      * @param automationPort If 0, automation server will be disabled.
246      */
setAutomationPort(int automationPort)247     public void setAutomationPort(int automationPort) {
248         this.automationPort = automationPort;
249     }
250 
getUnoUrl()251     public String getUnoUrl() {
252         return unoUrl;
253     }
254 
255     /**
256      * Set UNO connection listening url
257      * @param unoUrl If null, UNO connection will be disabled.
258      */
setUnoUrl(String unoUrl)259     public void setUnoUrl(String unoUrl) {
260         this.unoUrl = unoUrl;
261     }
262 
263     /**
264      * destroy OpenOffice
265      */
kill()266     public void kill() {
267         SystemUtil.killProcess(".*soffice.*" + id + ".*");
268         SystemUtil.sleep(1);
269         process = null;
270     }
271 
272     /**
273      * Kill all openoffice instances
274      */
killAll()275     public static void killAll() {
276         SystemUtil.killProcess(".*soffice.*");
277         SystemUtil.sleep(1);
278     }
279 
isRunning()280     public boolean isRunning() {
281         if (process == null)
282             return false;
283 
284         try {
285             process.exitValue();
286         } catch (Exception e1) {
287             return true;
288         }
289 
290         return false;
291     }
292 
293     /**
294      * Start OpenOffice
295      *
296      * @return return true when the process is created.
297      */
298     @SuppressWarnings("all")
start()299     public boolean start() {
300         if (isRunning())
301             return false;
302 
303         ArrayList<String> cmds = new ArrayList<String>();
304         cmds.add(binPath);
305         if (automationPort > 0) {
306             cmds.add("-automationport=" + automationPort);
307             cmds.add("-enableautomation");
308         }
309 
310         if (unoUrl != null)
311             cmds.add("-accept=" + unoUrl);
312 
313         if (userInstallation != null) {
314             try {
315                 String url = userInstallation.toURL().toString();
316                 url = url.replace("file:/", "file:///");
317                 cmds.add("-env:UserInstallation=" + url);
318             } catch (MalformedURLException e) {
319                 // ignore never to occur
320             }
321         }
322 
323         if (args != null)
324             cmds.addAll(args);
325 
326         if (registryModifications.size() > 0) {
327             File registry = new File(getUserInstallation(), "user/registrymodifications.xcu");
328             String content = FileUtil.readFileAsString(registry);
329             String newContent = "";
330             for (String item : registryModifications) {
331                 if (!content.contains(item)) {
332                     newContent += item;
333                 }
334             }
335             content = content.replace("</oor:items>", "");
336             if (content.length() == 0)
337                 content += "<?xml version=\"1.0\" encoding=\"UTF-8\"?><oor:items xmlns:oor=\"http://openoffice.org/2001/registry\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">";
338             content += newContent + "</oor:items>";
339             FileUtil.writeStringToFile(registry.getAbsolutePath(), content);
340         }
341 
342         process = SystemUtil.backgroundExec(cmds.toArray(new String[]{}), null, null, null, null);
343 
344         String cmdLine="";
345         for (String s : cmds)
346             cmdLine += "\""+ s + "\" ";
347 
348         LOG.info(cmdLine);
349         if (process == null)
350             throw new RuntimeException("OpenOffice can't be started!");
351         return true;
352     }
353 
getPerfData()354     public HashMap<String, Object> getPerfData() {
355         HashMap<String, Object> proccessInfo = SystemUtil.findProcess(processPattern);
356         String pid = (String) proccessInfo.get("pid");
357         if (pid == null)
358             throw new RuntimeException("Can not find performance data");
359         return SystemUtil.getProcessPerfData(pid);
360     }
361 }
362