blob: 0a549b023c9f0739d36a391b25740dbfa5ef3af7 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
package org.openoffice.test;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;
import org.openoffice.test.common.FileUtil;
import org.openoffice.test.common.SystemUtil;
/**
* It represents one OpenOffice instance.
* By default, the instance will be started with automation and socket UNO connection enabled.
*
*/
public class OpenOffice {
private static Logger LOG = Logger.getLogger(OpenOffice.class.getName());
private static final String[] DEFAULT_HOME = new String[] {
"C:/Program Files/OpenOffice.org 3",
"C:/Program Files (x86)/OpenOffice.org 3",
"/Applications/OpenOffice.org.app/Contents",
"/opt/openoffice.org3",
};
private static final String USERHOME = System.getProperty("user.home");
private static final String BIN = SystemUtil.isWindows() ? "program/soffice.exe" : SystemUtil.isMac() ? "MacOS/soffice": "program/soffice";
private static final String SYSUSERCONFIG = SystemUtil.isWindows()? System.getenv("APPDATA") : SystemUtil.isMac() ? USERHOME + "/Library/Application Support" : USERHOME;
public static final String DEFAULT_UNO_URL = "socket,host=127.0.0.1,port=2002;urp";
public static final int DEFAULT_AUTOMATION_PORT = 12479;
private static OpenOffice defaultInstance = null;
private File userInstallation = null;
private File defaultUserInstallation = null;
private File home = null;
private File bin = null;
private String binPath = null;
private ArrayList<String> args = new ArrayList<String>();
private ArrayList<String> registryModifications = new ArrayList<String>();
private int automationPort = 0;
private Process process = null;
private String unoUrl = null;
private Properties versionProps = null;
private String id = UUID.randomUUID().toString().replace("-", "");
private String processPattern = SystemUtil.isMac() ? ".*soffice .*" + id + ".*" : ".*soffice\\.bin.*" + id + ".*|.*soffice\\.exe.*" + id + ".*-env.*";
public OpenOffice() {
this(null);
}
/**
* Construct Process with the home path of OpenOffice.
*
* @param appHome
*/
public OpenOffice(String appHome) {
if (appHome == null)
appHome = System.getProperty("openoffice.home");
if (appHome == null)
appHome = System.getenv("OPENOFFICE_HOME");
if (appHome == null) {
// Search in the classpath
try {
URL url = getClass().getClassLoader().getResource(BIN);
File file = new File(url.toURI());
if (file.exists())
appHome = file.getParentFile().getParentFile().getAbsolutePath();
} catch (Exception e) {
// ignore
}
}
if (appHome == null) {
for (int i = 0; i < DEFAULT_HOME.length; i++)
if (new File(DEFAULT_HOME[i]).exists())
appHome = DEFAULT_HOME[i];
}
home = new File(appHome);
bin = new File(appHome, BIN);
try {
binPath = bin.getCanonicalPath();
} catch (IOException e1) {
}
File binParent = bin.getParentFile();
File bootstrapFile = new File(binParent, "bootstraprc");
if (!bootstrapFile.exists())
bootstrapFile = new File(binParent, "bootstrap.ini");
if (!bootstrapFile.exists())
throw new Error("OpenOffice can not be found or it's broken. Testing can not be performed. " +
"Use system property openoffice.home to specify the correct location of OpenOffice.");
Properties props = FileUtil.loadProperties(bootstrapFile);
String defaultUserInstallationPath = props.getProperty("UserInstallation").replace("$ORIGIN", binParent.getAbsolutePath()).replace("$SYSUSERCONFIG", SYSUSERCONFIG);
defaultUserInstallation = new File(defaultUserInstallationPath);
File versionFile = new File(binParent, "versionrc");
if (!versionFile.exists())
versionFile = new File(binParent, "version.ini");
versionProps = FileUtil.loadProperties(versionFile);
Set<Entry<Object, Object>> entries = versionProps.entrySet();
for (Entry<Object, Object> e : entries) {
System.setProperty("info.app." + e.getKey(), (String)e.getValue());
}
//
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
System.setProperty("info.app.date", dateFormat.format(new Date(versionFile.lastModified())));
addArgs("-" + id);
}
public static OpenOffice getDefault() {
if (defaultInstance == null) {
defaultInstance = new OpenOffice();
defaultInstance.setAutomationPort(DEFAULT_AUTOMATION_PORT);
defaultInstance.setUnoUrl(DEFAULT_UNO_URL);
defaultInstance.addArgs("-nofirststartwizard", "-norestore", "-quickstart=no");
defaultInstance.addRegistryModifications("<item oor:path=\"/org.openoffice.Office.Common/Misc\"><prop oor:name=\"UseSystemFileDialog\" oor:op=\"fuse\"><value>false</value></prop></item>",
"<item oor:path=\"/org.openoffice.Office.Common/Security/Scripting\"><prop oor:name=\"MacroSecurityLevel\" oor:op=\"fuse\"><value>0</value></prop></item>");
}
return defaultInstance;
}
public static void restoreDefault() {
if (defaultInstance != null) {
}
}
public Properties getVersionProps() {
return versionProps;
}
/**
* Set UserInstallation directory. When openoffice is launched, the argument
* "-env:UserInstallation" will be enabled.
*
* @param dir
* user installation directory. If null is given, the default
* will be used.
*/
public void setUserInstallation(File dir) {
userInstallation = dir;
}
/**
* Get UserInstallation directory
*
* @return
*/
public File getUserInstallation() {
return userInstallation == null ? defaultUserInstallation : userInstallation;
}
/**
* Get default UserInstallation directory
*
* @return
*/
public File getDefaultUserInstallation() {
return defaultUserInstallation;
}
/**
* Clean the user installation
*/
public void cleanUserInstallation() {
FileUtil.deleteFile(getUserInstallation());
}
/**
* Get installation directory of OpenOffice.
*
* @return
*/
public File getHome() {
return home;
}
/**
* Set other command line arguments
*
* @param args
*/
public void addArgs(String... arguments) {
for (String a : arguments)
args.add(a);
}
public void addRegistryModifications(String... items) {
for (String i : items)
registryModifications.add(i);
}
public int getAutomationPort() {
return automationPort;
}
/**
* Set automation server listening port
* @param automationPort If 0, automation server will be disabled.
*/
public void setAutomationPort(int automationPort) {
this.automationPort = automationPort;
}
public String getUnoUrl() {
return unoUrl;
}
/**
* Set UNO connection listening url
* @param unoUrl If null, UNO connection will be disabled.
*/
public void setUnoUrl(String unoUrl) {
this.unoUrl = unoUrl;
}
/**
* destroy OpenOffice
*/
public void kill() {
SystemUtil.killProcess(".*soffice.*" + id + ".*");
SystemUtil.sleep(1);
process = null;
}
/**
* Kill all openoffice instances
*/
public static void killAll() {
SystemUtil.killProcess(".*soffice.*");
SystemUtil.sleep(1);
}
public boolean isRunning() {
if (process == null)
return false;
try {
process.exitValue();
} catch (Exception e1) {
return true;
}
return false;
}
/**
* Start OpenOffice
*
* @return return true when the process is created.
*/
@SuppressWarnings("all")
public boolean start() {
if (isRunning())
return false;
ArrayList<String> cmds = new ArrayList<String>();
cmds.add(binPath);
if (automationPort > 0) {
cmds.add("-automationport=" + automationPort);
cmds.add("-enableautomation");
}
if (unoUrl != null)
cmds.add("-accept=" + unoUrl);
if (userInstallation != null) {
try {
String url = userInstallation.toURL().toString();
url = url.replace("file:/", "file:///");
cmds.add("-env:UserInstallation=" + url);
} catch (MalformedURLException e) {
// ignore never to occur
}
}
if (args != null)
cmds.addAll(args);
if (registryModifications.size() > 0) {
File registry = new File(getUserInstallation(), "user/registrymodifications.xcu");
String content = FileUtil.readFileAsString(registry);
String newContent = "";
for (String item : registryModifications) {
if (!content.contains(item)) {
newContent += item;
}
}
content.replace("</oor:items>", "");
if (content.length() == 0)
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\">";
content += newContent + "</oor:items>";
FileUtil.writeStringToFile(registry.getAbsolutePath(), content);
}
process = SystemUtil.backgroundExec(cmds.toArray(new String[]{}), null, null, null, null);
String cmdLine="";
for (String s : cmds)
cmdLine += "\""+ s + "\" ";
LOG.info(cmdLine);
if (process == null)
throw new RuntimeException("OpenOffice can't be started!");
return true;
}
public HashMap<String, Object> getPerfData() {
HashMap<String, Object> proccessInfo = SystemUtil.findProcess(processPattern);
String pid = (String) proccessInfo.get("pid");
if (pid == null)
throw new RuntimeException("Can not find performance data");
return SystemUtil.getProcessPerfData(pid);
}
}