org.jopendocument.link.OOInstallation Maven / Gradle / Ivy
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2008 jOpenDocument, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU
* General Public License Version 3 only ("GPL").
* You may not use this file except in compliance with the License.
* You can obtain a copy of the License at http://www.gnu.org/licenses/gpl-3.0.html
* See the License for the specific language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*
*/
package org.jopendocument.link;
import org.jopendocument.util.DesktopEnvironment;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This class finds out where OpenOffice.org is installed.
*
* @author Sylvain CUAZ
* @see #getInstance()
*/
public class OOInstallation {
private static OOInstallation instance;
/**
* Return the installation for this machine.
*
* @return the installation for this machine, null if not installed.
* @throws IOException if an error occurs while searching.
*/
public static OOInstallation getInstance() throws IOException {
// since null means never detected or not installed, this will keep searching when not
// installed
if (instance == null) {
instance = detectInstall();
}
return instance;
}
/**
* Forget the current installation to pick up a change (e.g. updated version).
*/
public static void reset() {
instance = null;
}
// UREINSTALLLOCATION REG_SZ C:\Program Files\OpenOffice.org 3\URE\
// \1 is the name, \2 the value
// cannot use \p{} since some names/values can be non-ASCII
private static final Pattern stringValuePattern = Pattern.compile("^\\s*(.+?)\\s+REG_SZ\\s+(.+?)$", Pattern.MULTILINE);
private static final String LOBundleID = "org.libreoffice.script";
private static final String OOBundleID = "org.openoffice.script";
// return the standard out (not the standard error)
private static String cmdSubstitution(String... args) throws IOException {
final ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(false);
return DesktopEnvironment.cmdSubstitution(pb.start());
}
static final URL toURL(final File f) {
try {
return f.toURI().toURL();
} catch (MalformedURLException e) {
// shouldn't happen since constructed from a file
throw new IllegalStateException("Couldn't transform to URL " + f, e);
}
}
// handle windows x64
private static String findRootPath() {
final String[] rootPaths = { "HKEY_LOCAL_MACHINE\\SOFTWARE\\LibreOffice", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LibreOffice", "HKEY_LOCAL_MACHINE\\SOFTWARE\\OpenOffice.org",
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\OpenOffice.org" };
for (final String p : rootPaths) {
if (DesktopEnvironment.test("reg", "query", p))
return p;
}
return null;
}
private static String findBundleURL() throws IOException {
for (final String bundleID : new String[] { LOBundleID, OOBundleID }) {
// if not found prints nothing to out and a cryptic error to the standard error stream
final String url = cmdSubstitution("osascript", "-e", "tell application id \"com.apple.Finder\" to URL of application file id \"" + bundleID + "\"").trim();
if (url.length() > 0)
return url;
}
return null;
}
// all string values for the passed registry path
private static Map getStringValues(final String path, final String option) throws IOException {
final Map values = new HashMap();
final String out = DesktopEnvironment.cmdSubstitution(Runtime.getRuntime().exec(new String[] { "reg", "query", path, option }));
final Matcher matcher = stringValuePattern.matcher(out);
while (matcher.find()) {
values.put(matcher.group(1), matcher.group(2));
}
return values;
}
// add jar directories for OpenOffice 2 or 3
private static final void addPaths(final List cp, final File progDir, final String basisDir, final String ureDir) throws IOException {
// oo2
// all in C:\Program Files\OpenOffice.org 2.4\program\classes
add(cp, new File(progDir, "classes"));
// oo3
// some in C:\Program Files\OpenOffice.org 3\URE\java
// the rest in C:\Program Files\OpenOffice.org 3\Basis\program\classes
if (ureDir != null) {
// Windows
add(cp, ureDir + File.separator + "java");
// MacOS and Linux
add(cp, ureDir + File.separator + "share" + File.separator + "java");
}
if (basisDir != null)
add(cp, basisDir + File.separator + "program" + File.separator + "classes");
}
private static final void addUnixPaths(final List cp, final File progDir) throws IOException {
final File baseDir = progDir.getParentFile();
final String basisDir = baseDir.getPath() + File.separator + "basis-link";
final String ureDir = basisDir + File.separator + "ure-link";
addPaths(cp, progDir, basisDir, ureDir);
}
private static void add(final List res, final File f) {
if (f != null && f.isDirectory()) {
res.add(f);
}
}
private static void add(final List res, final String f) {
if (f != null)
add(res, new File(f));
}
private static OOInstallation detectInstall() throws IOException {
final File exe;
final List cp = new ArrayList(3);
final String os = System.getProperty("os.name");
if (os.startsWith("Windows")) {
final String rootPath = findRootPath();
// not installed
if (rootPath == null)
return null;
final boolean libreOffice = rootPath.contains("LibreOffice");
// Only the default value so pass '/ve'
final Map unoValues = getStringValues(rootPath + "\\UNO\\InstallPath", "/ve");
if (unoValues.size() != 1)
throw new IOException("No UNO install path: " + unoValues);
// e.g. C:\Program Files\OpenOffice.org 2.4\program
final File unoPath = new File(unoValues.values().iterator().next());
if (!unoPath.isDirectory())
throw new IOException(unoPath + " is not a directory");
exe = new File(unoPath, "soffice.exe");
// '/s' since variables are one level (the version) deeper
final Map layersValues = getStringValues(rootPath + (libreOffice ? "\\Layers_\\LibreOffice" : "\\Layers\\OpenOffice.org"), "/s");
addPaths(cp, unoPath, layersValues.get("BASISINSTALLLOCATION"), layersValues.get("UREINSTALLLOCATION"));
} else if (os.startsWith("Mac OS")) {
final String url = findBundleURL();
if (url == null)
return null;
try {
final File appPkg = new File(new URI(url).getPath());
// need to call soffice from the MacOS directory otherwise it fails
exe = new File(appPkg, "Contents/MacOS/soffice");
addUnixPaths(cp, new File(appPkg, "Contents/program"));
} catch (URISyntaxException e) {
throw new IOException(e);
}
} else if (os.startsWith("Linux")) {
// soffice is usually a symlink in /usr/bin
// if not found prints nothing at all
final String binPath = cmdSubstitution("which", "soffice").trim();
if (binPath.length() != 0) {
exe = new File(binPath).getCanonicalFile();
} else {
// e.g. Ubuntu 6.06
final File defaultInstall = new File("/usr/lib/openoffice/program/soffice");
exe = defaultInstall.canExecute() ? defaultInstall : null;
}
if (exe != null)
addUnixPaths(cp, exe.getParentFile());
} else
exe = null;
return exe == null ? null : new OOInstallation(exe, cp);
}
private final File executable;
private final List classpath;
// TODO parse program/version.ini
private OOInstallation(File executable, List classpath) throws IOException {
super();
if (!executable.isFile())
throw new IOException("executable not found at " + executable);
this.executable = executable;
this.classpath = Collections.unmodifiableList(new ArrayList(classpath));
}
public final File getExecutable() {
return this.executable;
}
public final List getClasspath() {
return this.classpath;
}
public final List getURLs(final Set jars) {
final int stop = this.getClasspath().size();
final List res = new ArrayList();
for (int i = 0; i < stop; i++) {
final File[] foundJars = this.getClasspath().get(i).listFiles(new FileFilter() {
@Override
public boolean accept(File f) {
return jars.contains(f.getName());
}
});
for (final File foundJar : foundJars) {
res.add(toURL(foundJar));
}
}
return res;
}
@Override
public String toString() {
return this.getClass().getSimpleName() + " exe: " + this.getExecutable() + " classpath: " + this.getClasspath();
}
public static void main(String[] args) {
try {
final OOInstallation i = getInstance();
System.out.println(i == null ? "Not installed" : i);
} catch (IOException e) {
System.out.println("Couldn't detect OpenOffice.org: " + e.getLocalizedMessage());
e.printStackTrace();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy