diff options
Diffstat (limited to 'src/libs/xpcom18a4/java/src/org/mozilla/xpcom/Mozilla.java')
-rw-r--r-- | src/libs/xpcom18a4/java/src/org/mozilla/xpcom/Mozilla.java | 1079 |
1 files changed, 1079 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/Mozilla.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/Mozilla.java new file mode 100644 index 00000000..05314c90 --- /dev/null +++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/Mozilla.java @@ -0,0 +1,1079 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Java XPCOM Bindings. + * + * The Initial Developer of the Original Code is IBM Corporation. + * Portions created by the Initial Developer are Copyright (C) 2006 + * IBM Corporation. All Rights Reserved. + * + * Contributor(s): + * Javier Pedemonte (jhpedemonte@gmail.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.xpcom; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Properties; + +import org.mozilla.interfaces.nsIComponentManager; +import org.mozilla.interfaces.nsIComponentRegistrar; +import org.mozilla.interfaces.nsILocalFile; +import org.mozilla.interfaces.nsIServiceManager; +import org.mozilla.interfaces.nsISupports; + + +/** + * A singleton class which provides access to the Mozilla browser. Requires + * that XULRunner be installed on the user's system. + * <p> + * You would use to class to find a XULRunner installation, setup a profile (if + * necessary), and initialize embedding. A typical scenario would look like + * this: + * </p><pre> + * Mozilla mozilla = Mozilla.getInstance(); + * GREVersionRange[] range = new GREVersionRange[1]; + * range[0] = new GREVersionRange("1.8.0.*", false, "1.8.1.*", true); + * try { + * File grePath = Mozilla.getGREPathWithProperties(range, null); + * mozilla.initialize(grePath); + * profLock = mozilla.lockProfileDirectory(profileDir); + * // LocationProvider is a user class that implements IAppFileLocProvider + * LocationProvider locProvider = new LocationProvider(grePath, profileDir); + * mozilla.initEmbedding(grePath, grePath, locProvider); + * mozilla.notifyProfile(); + * } catch (XPCOMInitializationException xie) { + * // handle exception + * } catch (XPCOMException xe) { + * // handle exception + * } + * </pre> + * + * @see http://www.mozilla.org/projects/embedding/GRE.html + */ +public class Mozilla implements IMozilla, IGRE, IXPCOM, IJavaXPCOMUtils,XPCOMError { + + private static Mozilla mozillaInstance = new Mozilla(); + + private static final String JAVAXPCOM_JAR = "vboxjxpcom.jar"; + + private IMozilla mozilla = null; + private IGRE gre = null; + private IXPCOM xpcom = null; + private IJavaXPCOMUtils jxutils = null; + + /** + * @return + */ + public static Mozilla getInstance() { + return mozillaInstance; + } + + /** + * + */ + private Mozilla() { + } + + /** + * Locates the path of a GRE with the specified properties. This method + * will only return GREs that support Java embedding (looks for the + * presence of "javaxpcom.jar"). + * <p> + * Currently this uses a "first-fit" algorithm, it does not select + * the newest available GRE. + * + * @param aVersions An array of version ranges: if any version range + * matches, the GRE is considered acceptable. + * @param aProperties A list of GRE property/value pairs which must + * all be satisfied. This parameter is ignored on + * Macintosh, because of the manner in which the + * XUL frameworks are installed. + * + * @return A file object of the appropriate path. If + * the "local" GRE is specified (via the USE_LOCAL_GRE + * environment variable, for example), returns + * <code>null</code>. + * + * @throws FileNotFoundException if an appropriate GRE could not be found + */ + public static File getGREPathWithProperties(GREVersionRange[] aVersions, + Properties aProperties) throws FileNotFoundException { + File grePath = null; + + // if GRE_HOME is in the environment, use that GRE + String env = System.getProperty("GRE_HOME"); + if (env != null) { + try { + grePath = new File(env).getCanonicalFile(); + } catch (IOException e) { + throw new FileNotFoundException("cannot access GRE_HOME"); + } + if (!grePath.exists()) { + throw new FileNotFoundException("GRE_HOME doesn't exist"); + } + return grePath; + } + + // the Gecko bits that sit next to the application or in the PATH + env = System.getProperty("USE_LOCAL_GRE"); + if (env != null) { + return null; + } + + // Search for GRE in platform specific locations. We want a GRE that + // supports Java, so we look for the "javaxpcom" property by default. + if (aProperties == null) { + aProperties = new Properties(); + } + aProperties.setProperty("javaxpcom", "1"); + + String osName = System.getProperty("os.name").toLowerCase(); + if (osName.startsWith("mac os x")) { + grePath = getGREPathMacOSX(aVersions); + } else if (osName.startsWith("windows")) { + grePath = getGREPathWindows(aVersions, aProperties); + } else { + // assume everything else is Unix/Linux + grePath = getGREPathUnix(aVersions, aProperties); + } + + if (grePath == null) { + throw new FileNotFoundException("GRE not found"); + } + + return grePath; + } + + /** + * @param aVersions + * @return + */ + private static File getGREPathMacOSX(GREVersionRange[] aVersions) { + /* + * Check the application bundle first, for + * <bundle>/Contents/Frameworks/XUL.framework/libxpcom.dylib. + */ + File grePath = findGREBundleFramework(); + if (grePath != null) { + return grePath; + } + + // Check ~/Library/Frameworks/XUL.framework/Versions/<version>/libxpcom.dylib + String home = System.getProperty("user.home"); + if (home != null) { + grePath = findGREFramework(home, aVersions); + if (grePath != null) { + return grePath; + } + } + + // Check /Library/Frameworks/XUL.framework/Versions/<version>/libxpcom.dylib + return findGREFramework("", aVersions); + } + + /** + * @return + */ + private static File findGREBundleFramework() { + /* + * Use reflection to get Apple's NSBundle class, which can be used + * to get the bundle's "Frameworks" directory. + */ + try { + URL[] urls = new URL[1]; + urls[0] = new File("/System/Library/Java/").toURI().toURL(); + ClassLoader loader = new URLClassLoader(urls); + Class<?> bundleClass = Class.forName("com.apple.cocoa.foundation.NSBundle", + true, loader); + + // Get the bundle for this app. If this is not executing from + // a bundle, this will return null. + Method mainBundleMethod = bundleClass.getMethod("mainBundle", (java.lang.Class[])null); + Object bundle = mainBundleMethod.invoke(null, (java.lang.Object[])null); + + if (bundle != null) { + // Get the path to the bundle's "Frameworks" directory + Method fwPathMethod = bundleClass.getMethod("privateFrameworksPath", + (java.lang.Class[])null); + String path = (String) fwPathMethod.invoke(bundle, (java.lang.Object[])null); + + // look for libxpcom.dylib + if (path.length() != 0) { + File xulDir = new File(path, "XUL.framework"); + if (xulDir.isDirectory()) { + File xpcomLib = new File(xulDir, "libxpcom.dylib"); + if (xpcomLib.canRead()) { + File grePath = xpcomLib.getCanonicalFile().getParentFile(); + + // Since GRE Properties aren't supported on Mac OS X, we check + // for the existence of the "javaxpcom.jar" file in the GRE. + File jar = new File(grePath, JAVAXPCOM_JAR); + if (jar.canRead()) { + // found GRE + return grePath; + } + } + } + } + } + } catch (Exception e) { } + + return null; + } + + /** + * @param aRootPath + * @param aVersions + * @return + */ + private static File findGREFramework(String aRootPath, + GREVersionRange[] aVersions) { + File frameworkDir = new File(aRootPath + + "/Library/Frameworks/XUL.framework/Versions"); + if (!frameworkDir.exists()) + return null; + + File[] files = frameworkDir.listFiles(); + for (int i = 0; i < files.length; i++) { + if (checkVersion(files[i].getName(), aVersions)) { + File xpcomLib = new File(files[i], "libxpcom.dylib"); + + // Since GRE Properties aren't supported on Mac OS X, we check + // for the existence of the "javaxpcom.jar" file in the GRE. + File jar = new File(files[i], JAVAXPCOM_JAR); + if (xpcomLib.canRead() && jar.canRead()) { + return files[i]; + } + } + } + + return null; + } + + /** + * @param aVersions + * @param aProperties + * @return + */ + private static File getGREPathWindows(GREVersionRange[] aVersions, + Properties aProperties) { + /* + * Note the usage of the "Software\\mozilla.org\\GRE" subkey - this allows + * us to have multiple versions of GREs on the same machine by having + * subkeys such as 1.0, 1.1, 2.0 etc. under it. + * + * Please see http://www.mozilla.org/projects/embedding/GRE.html for + * more info. + */ + + final String greKey = "Software\\mozilla.org\\GRE"; + + // See if there is a GRE registered for the current user. + // If not, look for one on the system. + String key = "HKEY_CURRENT_USER" + "\\" + greKey; + File grePath = getGREPathFromRegKey(key, aVersions, aProperties); + if (grePath == null) { + key = "HKEY_LOCAL_MACHINE" + "\\" + greKey; + grePath = getGREPathFromRegKey(key, aVersions, aProperties); + } + + return grePath; + } + + /** + * @param aRegKey + * @param aVersions + * @param aProperties + * @return + */ + private static File getGREPathFromRegKey(String aRegKey, + GREVersionRange[] aVersions, Properties aProperties) { + // create a temp file for the registry export + File tempFile; + try { + tempFile = File.createTempFile("jx_registry", null); + } catch (IOException e) { + // failed to create temp file. ABORT + return null; + } + + Process proc; + try { + proc = Runtime.getRuntime().exec("regedit /e " + "\"" + tempFile.getPath() + + "\" \"" + aRegKey + "\""); + proc.waitFor(); + } catch (Exception e) { + // Failed to run regedit.exe. Length of temp file is zero, and that's + // handled next. + } + + // If there is a key by that name in the registry, then the file length + // will not be zero. + File grePath = null; + if (tempFile.length() != 0) { + grePath = getGREPathFromRegistryFile(tempFile.getPath(), + aRegKey, aVersions, aProperties); + } + + tempFile.delete(); + return grePath; + } + + /** + * @param aFileName + * @param aCharset + * @param aKeyName + * @param aVersions + * @param aProperties + * @return + */ + private static File getGREPathFromRegistryFile(String aFileName, + String aKeyName, GREVersionRange[] aVersions, + Properties aProperties) { + INIParser parser; + try { + parser = new INIParser(aFileName, Charset.forName("UTF-16")); + } catch (Exception e) { + // Problem reading from file. Bail out. + return null; + } + + Iterator sectionsIter = parser.getSections(); + while (sectionsIter.hasNext()) { + // get 'section' name, which will be a registry key name + String section = (String) sectionsIter.next(); + + // Skip over GRE key ("<root>\Software\mozilla.org\GRE") + int gre_len = aKeyName.length(); + if (section.length() <= gre_len) { + continue; + } + + // Get the GRE subkey; that is, everything after + // "<root>\Software\mozilla.org\GRE\" + String subkeyName = section.substring(gre_len + 1); + + // We are only interested in _immediate_ subkeys. We want + // "<root>\Software\mozilla.org\GRE\<version>" but not + // "<root>\Software\mozilla.org\GRE\<version>\<moretext>". + if (subkeyName.indexOf('\\') != -1) { + continue; + } + + // See if this registry key has a "Version" value, and if so, compare + // it to our desired versions. + String version = parser.getString(section, "\"Version\""); + if (version == null) { + continue; + } + // remove quotes around string + version = version.substring(1, version.length() - 1); + if (!checkVersion(version, aVersions)) { + continue; + } + + // All properties must match, keeping in mind that the propery/value + // pairs returned by regedit.exe have quotes around them. + if (aProperties != null) { + boolean ok = true; + Enumeration e = aProperties.propertyNames(); + while (ok && e.hasMoreElements()) { + String prop = (String) e.nextElement(); + String greValue = parser.getString(section, "\"" + prop + "\""); + if (greValue == null) { + // No such property is set for this GRE. Go on to next GRE. + ok = false; + } else { + // See if the value of the property for the GRE matches + // the given value. + String value = aProperties.getProperty(prop); + if (!greValue.equals("\"" + value + "\"")) { + ok = false; + } + } + } + if (!ok) { + continue; + } + } + + String pathStr = parser.getString(section, "\"GreHome\""); + if (pathStr != null) { + // remove quotes around string + pathStr = pathStr.substring(1, pathStr.length() - 1); + File grePath = new File(pathStr); + if (grePath.exists()) { + File xpcomLib = new File(grePath, "xpcom.dll"); + if (xpcomLib.canRead()) { + // found a good GRE + return grePath; + } + } + } + } + + return null; + } + + /** + * @param aVersions + * @param aProperties + * @return + */ + private static File getGREPathUnix(GREVersionRange[] aVersions, + Properties aProperties) { + File grePath = null; + + String env = System.getProperty("MOZ_GRE_CONF"); + if (env != null) { + grePath = getPathFromConfigFile(env, aVersions, aProperties); + if (grePath != null) { + return grePath; + } + } + + final String greUserConfFile = ".gre.config"; + final String greUserConfDir = ".gre.d"; + final String greConfPath = "/etc/gre.conf"; + final String greConfDir = "/etc/gre.d"; + + env = System.getProperty("user.home"); + if (env != null) { + // Look in ~/.gre.config + grePath = getPathFromConfigFile(env + File.separator + greUserConfFile, + aVersions, aProperties); + if (grePath != null) { + return grePath; + } + + // Look in ~/.gre.d/*.conf + grePath = getPathFromConfigDir(env + File.separator + greUserConfDir, + aVersions, aProperties); + if (grePath != null) { + return grePath; + } + } + + // Look for a global /etc/gre.conf file + grePath = getPathFromConfigFile(greConfPath, aVersions, aProperties); + if (grePath != null) { + return grePath; + } + + // Look for a group of config files in /etc/gre.d/ + grePath = getPathFromConfigDir(greConfDir, aVersions, aProperties); + return grePath; + } + + /** + * @param aFileName + * @param aVersions + * @param aProperties + * @return + */ + private static File getPathFromConfigFile(String aFileName, + GREVersionRange[] aVersions, Properties aProperties) { + INIParser parser; + try { + parser = new INIParser(aFileName); + } catch (Exception e) { + // Problem reading from file. Bail out. + return null; + } + + Iterator sectionsIter = parser.getSections(); + while (sectionsIter.hasNext()) { + // get 'section' name, which will be a version string + String section = (String) sectionsIter.next(); + + // if this isn't one of the versions we are looking for, move + // on to next section + if (!checkVersion(section, aVersions)) { + continue; + } + + // all properties must match + if (aProperties != null) { + boolean ok = true; + Enumeration e = aProperties.propertyNames(); + while (ok && e.hasMoreElements()) { + String prop = (String) e.nextElement(); + String greValue = parser.getString(section, prop); + if (greValue == null) { + // No such property is set for this GRE. Go on to next GRE. + ok = false; + } else { + // See if the value of the property for the GRE matches + // the given value. + if (!greValue.equals(aProperties.getProperty(prop))) { + ok = false; + } + } + } + if (!ok) { + continue; + } + } + + String pathStr = parser.getString(section, "GRE_PATH"); + if (pathStr != null) { + File grePath = new File(pathStr); + if (grePath.exists()) { + File xpcomLib = new File(grePath, "libxpcom.so"); + if (xpcomLib.canRead()) { + // found a good GRE + return grePath; + } + } + } + } + + return null; + } + + /** + * @param aDirName + * @param aVersions + * @param aProperties + * @return + */ + private static File getPathFromConfigDir(String aDirName, + GREVersionRange[] aVersions, Properties aProperties) { + /* + * Open the directory provided and try to read any files in that + * directory that end with .conf. We look for an entry that might + * point to the GRE that we're interested in. + */ + + File dir = new File(aDirName); + if (!dir.isDirectory()) { + return null; + } + + File grePath = null; + File[] files = dir.listFiles(); + for (int i = 0; i < files.length && grePath == null; i++) { + // only look for files that end in '.conf' + if (!files[i].getName().endsWith(".conf")) { + continue; + } + + grePath = getPathFromConfigFile(files[i].getPath(), aVersions, + aProperties); + } + + return grePath; + } + + /** + * @param aVersionToCheck + * @param aVersions + * @return + */ + private static boolean checkVersion(String aVersionToCheck, + GREVersionRange[] aVersions) { + for (int i = 0; i < aVersions.length; i++) { + if (aVersions[i].check(aVersionToCheck)) { + return true; + } + } + return false; + } + + /** + * Initialize the Mozilla object with the given XULRunner path. All + * subsequent Mozilla method invocations be done against the given XULRunner + * version. + * + * @param aLibXULDirectory path of XULRunner build to use + * + * @throws XPCOMInitializationException if failure occurred during + * initialization + */ + public void initialize(File aLibXULDirectory) + throws XPCOMInitializationException { + File jar = new File(aLibXULDirectory, JAVAXPCOM_JAR); + if (!jar.exists()) { + jar = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath()); + if (!jar.exists()) + throw new XPCOMInitializationException("Could not find " + JAVAXPCOM_JAR + + " in " + aLibXULDirectory); + } + + URL[] urls = new URL[1]; + try { + urls[0] = jar.toURI().toURL(); + } catch (MalformedURLException e) { + throw new XPCOMInitializationException(e); + } + ClassLoader loader = new URLClassLoader(urls, + this.getClass().getClassLoader()); + + try { + Class mozillaClass = Class.forName("org.mozilla.xpcom.internal.MozillaImpl", + true, loader); + mozilla = (IMozilla) mozillaClass.newInstance(); + + Class greClass = Class.forName("org.mozilla.xpcom.internal.GREImpl", + true, loader); + gre = (IGRE) greClass.newInstance(); + + Class xpcomClass = Class.forName("org.mozilla.xpcom.internal.XPCOMImpl", + true, loader); + xpcom = (IXPCOM) xpcomClass.newInstance(); + + Class javaXPCOMClass = + Class.forName("org.mozilla.xpcom.internal.JavaXPCOMMethods", + true, loader); + jxutils = (IJavaXPCOMUtils) javaXPCOMClass.newInstance(); + } catch (Exception e) { + throw new XPCOMInitializationException("Could not load " + + "org.mozilla.xpcom.internal.* classes", e); + } + + mozilla.initialize(aLibXULDirectory); + } + + /** + * Initializes libXUL for embedding purposes. + * <p> + * NOTE: This function must be called from the "main" thread. + * <p> + * NOTE: At the present time, this function may only be called once in + * a given process. Use <code>termEmbedding</code> to clean up and free + * resources allocated by <code>initEmbedding</code>. + * + * @param aLibXULDirectory The directory in which the libXUL shared library + * was found. + * @param aAppDirectory The directory in which the application components + * and resources can be found. This will map to + * the "resource:app" directory service key. + * @param aAppDirProvider A directory provider for the application. This + * provider will be aggregated by a libXUL provider + * which will provide the base required GRE keys. + * + * @throws XPCOMException if a failure occurred during initialization + * @throws XPCOMInitializationException if Mozilla was not properly + * initialized + */ + public void initEmbedding(File aLibXULDirectory, File aAppDirectory, + IAppFileLocProvider aAppDirProvider) throws XPCOMException { + try { + gre.initEmbedding(aLibXULDirectory, aAppDirectory, aAppDirProvider); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } + } + + /** + * Terminates libXUL embedding. + * <p> + * NOTE: Release any references to XPCOM objects that you may be holding + * before calling this function. + * + * @throws XPCOMInitializationException if Mozilla was not properly + * initialized + */ + public void termEmbedding() { + try { + gre.termEmbedding(); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } finally { + mozilla = null; + gre = null; + xpcom = null; + } + } + + /** + * Lock a profile directory using platform-specific semantics. + * + * @param aDirectory The profile directory to lock. + * + * @return A lock object. The directory will remain locked until the lock is + * released by invoking the <code>release</code> method, or by the + * termination of the JVM, whichever comes first. + * + * @throws XPCOMException if profile is already locked (with + * <code>errorcode</code> == <code>NS_ERROR_FILE_ACCESS_DENIED</code>); + * or if a failure occurred + * @throws XPCOMInitializationException if Mozilla was not properly + * initialized + */ + public ProfileLock lockProfileDirectory(File aDirectory) + throws XPCOMException { + try { + return gre.lockProfileDirectory(aDirectory); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } + } + + /** + * Fire notifications to inform the toolkit about a new profile. This + * method should be called after <code>initEmbedding</code> if the + * embedder wishes to run with a profile. + * <p> + * Normally the embedder should call <code>lockProfileDirectory</code> + * to lock the directory before calling this method. + * <p> + * NOTE: There are two possibilities for selecting a profile: + * <ul> + * <li> + * Select the profile before calling <code>initEmbedding</code>. + * The aAppDirProvider object passed to <code>initEmbedding</code> + * should provide the NS_APP_USER_PROFILE_50_DIR key, and + * may also provide the following keys: + * <ul> + * <li>NS_APP_USER_PROFILE_LOCAL_50_DIR + * <li>NS_APP_PROFILE_DIR_STARTUP + * <li>NS_APP_PROFILE_LOCAL_DIR_STARTUP + * </ul> + * In this scenario <code>notifyProfile</code> should be called + * immediately after <code>initEmbedding</code>. Component + * registration information will be stored in the profile and + * JS components may be stored in the fastload cache. + * </li> + * <li> + * Select a profile some time after calling <code>initEmbedding</code>. + * In this case the embedder must install a directory service + * provider which provides NS_APP_USER_PROFILE_50_DIR and optionally + * NS_APP_USER_PROFILE_LOCAL_50_DIR. Component registration information + * will be stored in the application directory and JS components will not + * fastload. + * </li> + * </ul> + * + * @throws XPCOMInitializationException if Mozilla was not properly + * initialized + */ + public void notifyProfile() { + try { + gre.notifyProfile(); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } + } + + /** + * Initializes XPCOM. You must call this method before proceeding + * to use XPCOM. + * + * @param aMozBinDirectory The directory containing the component + * registry and runtime libraries; + * or use <code>null</code> to use the working + * directory. + * + * @param aAppFileLocProvider The object to be used by Gecko that specifies + * to Gecko where to find profiles, the component + * registry preferences and so on; or use + * <code>null</code> for the default behaviour. + * + * @return the service manager + * + * @throws XPCOMException <ul> + * <li> NS_ERROR_NOT_INITIALIZED - if static globals were not initialied, + * which can happen if XPCOM is reloaded, but did not completly + * shutdown. </li> + * <li> Other error codes indicate a failure during initialisation. </li> + * </ul> + * @throws XPCOMInitializationException if Mozilla was not properly + * initialized + */ + public nsIServiceManager initXPCOM(File aMozBinDirectory, + IAppFileLocProvider aAppFileLocProvider) throws XPCOMException { + try { + return xpcom.initXPCOM(aMozBinDirectory, aAppFileLocProvider); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } + } + + /** + * Shutdown XPCOM. You must call this method after you are finished + * using xpcom. + * + * @param aServMgr The service manager which was returned by initXPCOM. + * This will release servMgr. + * + * @throws XPCOMException if a failure occurred during termination + * @throws XPCOMInitializationException if Mozilla was not properly + * initialized + */ + public void shutdownXPCOM(nsIServiceManager aServMgr) throws XPCOMException { + try { + xpcom.shutdownXPCOM(aServMgr); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } finally { + mozilla = null; + gre = null; + xpcom = null; + } + } + + /** + * Public Method to access to the service manager. + * + * @return the service manager + * + * @throws XPCOMException if a failure occurred + * @throws XPCOMInitializationException if Mozilla was not properly + * initialized + */ + public nsIServiceManager getServiceManager() throws XPCOMException { + try { + return xpcom.getServiceManager(); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } + } + + /** + * Public Method to access to the component manager. + * + * @return the component manager + * + * @throws XPCOMException if a failure occurred + * @throws XPCOMInitializationException if Mozilla was not properly + * initialized + */ + public nsIComponentManager getComponentManager() throws XPCOMException { + try { + return xpcom.getComponentManager(); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } + } + + /** + * Public Method to access to the component registration manager. + * + * @return the component registration manager + * + * @throws XPCOMException if a failure occurred + * @throws XPCOMInitializationException if Mozilla was not properly + * initialized + */ + public nsIComponentRegistrar getComponentRegistrar() throws XPCOMException { + try { + return xpcom.getComponentRegistrar(); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } + } + + // #ifdef VBOX + public int waitForEvents(long tmo) throws XPCOMException { + try { + return xpcom.waitForEvents(tmo); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } + } + // #endif // VBOX + + /** + * Public Method to create an instance of a nsILocalFile. + * + * @param aPath A string which specifies a full file path to a + * location. Relative paths will be treated as an + * error (NS_ERROR_FILE_UNRECOGNIZED_PATH). + * @param aFollowLinks This attribute will determine if the nsLocalFile will + * auto resolve symbolic links. By default, this value + * will be false on all non unix systems. On unix, this + * attribute is effectively a noop. + * + * @return an instance of an nsILocalFile that points to given path + * + * @throws XPCOMException <ul> + * <li> NS_ERROR_FILE_UNRECOGNIZED_PATH - raised for unrecognized paths + * or relative paths (must supply full file path) </li> + * </ul> + * @throws XPCOMInitializationException if Mozilla was not properly + * initialized + */ + public nsILocalFile newLocalFile(String aPath, boolean aFollowLinks) + throws XPCOMException { + try { + return xpcom.newLocalFile(aPath, aFollowLinks); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } + } + + /** + * If you create a class that implements nsISupports, you will need to provide + * an implementation of the <code>queryInterface</code> method. This helper + * function provides a simple implementation. Therefore, if your class does + * not need to do anything special with <code>queryInterface</code>, your + * implementation would look like: + * <pre> + * public nsISupports queryInterface(String aIID) { + * return XPCOM.queryInterface(this, aIID); + * } + * </pre> + * + * @param aObject object to query + * @param aIID requested interface IID + * + * @return <code>aObject</code> if the given object supports that + * interface; + * <code>null</code> otherwise. + */ + public static nsISupports queryInterface(nsISupports aObject, String aIID) { + ArrayList<Class> classes = new ArrayList<Class>(); + classes.add(aObject.getClass()); + + while (!classes.isEmpty()) { + Class clazz = classes.remove(0); + + // Skip over any class/interface in the "java.*" and "javax.*" domains. + String className = clazz.getName(); + if (className.startsWith("java.") || className.startsWith("javax.")) { + continue; + } + + // If given IID matches that of the current interface, then we + // know that aObject implements the interface specified by the given IID. + if (clazz.isInterface() && className.startsWith("org.mozilla")) { + String iid = Mozilla.getInterfaceIID(clazz); + if (iid != null && aIID.equals(iid)) { + return aObject; + } + } + + // clazz didn't match, so add the interfaces it implements + Class[] interfaces = clazz.getInterfaces(); + for (int i = 0; i < interfaces.length; i++ ) { + classes.add(interfaces[i]); + } + + // Also add its superclass + Class superclass = clazz.getSuperclass(); + if (superclass != null) { + classes.add(superclass); + } + } + + return null; + } + + /** + * Gets the interface IID for a particular Java interface. This is similar + * to NS_GET_IID in the C++ Mozilla files. + * + * @param aInterface interface which has defined an IID + * + * @return IID for given interface + */ + public static String getInterfaceIID(Class aInterface) { + // Get short class name (i.e. "bar", not "org.blah.foo.bar") + StringBuffer iidName = new StringBuffer(); + String fullClassName = aInterface.getName(); + int index = fullClassName.lastIndexOf("."); + String className = index > 0 ? fullClassName.substring(index + 1) + : fullClassName; + + // Create iid field name + if (className.startsWith("ns")) { + iidName.append("NS_"); + iidName.append(className.substring(2).toUpperCase()); + } else { + iidName.append(className.toUpperCase()); + } + iidName.append("_IID"); + + String iid; + try { + Field iidField = aInterface.getDeclaredField(iidName.toString()); + iid = (String) iidField.get(null); + } catch (NoSuchFieldException e) { + // Class may implement non-Mozilla interfaces, which would not have an + // IID method. In that case, just null. + iid = null; + } catch (IllegalAccessException e) { + // Not allowed to access that field for some reason. Write out an + // error message, but don't fail. + System.err.println("ERROR: Could not get field " + iidName.toString()); + iid = null; + } + + return iid; + } + + public long getNativeHandleFromAWT(Object widget) { + try { + return mozilla.getNativeHandleFromAWT(widget); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } + } + + public long wrapJavaObject(Object aJavaObject, String aIID) { + try { + return jxutils.wrapJavaObject(aJavaObject, aIID); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } + } + + public Object wrapXPCOMObject(long aXPCOMObject, String aIID) { + try { + return jxutils.wrapXPCOMObject(aXPCOMObject, aIID); + } catch (NullPointerException e) { + throw new XPCOMInitializationException("Must call " + + "Mozilla.getInstance().initialize() before using this method", e); + } + } + +} |