From 535a0addb627b0bd1dc344f394036e2502e37c2d Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 7 Sep 2019 17:40:56 +0200 Subject: [PATCH 01/13] [WIP] Try to fix LibreOffice class loader The problem is that it somehow doesn't load the jars from the LO path, but from our custom module --- .../org/jabref/gui/openoffice/OOBibBase.java | 31 ++++++------------- .../gui/openoffice/OpenOfficePanel.java | 27 ++++++---------- 2 files changed, 20 insertions(+), 38 deletions(-) diff --git a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java index ce72f55294e..7814a52d4e3 100644 --- a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java @@ -7,6 +7,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -131,7 +132,7 @@ class OOBibBase { private final DialogService dialogService; - public OOBibBase(String pathToOO, boolean atEnd, DialogService dialogService) throws IllegalAccessException, InvocationTargetException, BootstrapException, CreationException, IOException { + public OOBibBase(String pathToOO, boolean atEnd, DialogService dialogService) throws IllegalAccessException, InvocationTargetException, BootstrapException, CreationException, IOException, ClassNotFoundException { this.dialogService = dialogService; @@ -147,7 +148,9 @@ public OOBibBase(String pathToOO, boolean atEnd, DialogService dialogService) th yearAuthorTitleComparator = new FieldComparatorStack<>(yearAuthorTitleList); this.atEnd = atEnd; - xDesktop = simpleBootstrap(pathToOO); + + xDesktop = simpleBootstrap(pathToOO); + } @@ -237,26 +240,12 @@ private List getTextDocuments() throws NoSuchElementException, Wr private XDesktop simpleBootstrap(String pathToExecutable) throws IllegalAccessException, InvocationTargetException, BootstrapException, - CreationException, IOException { - - ClassLoader loader = ClassLoader.getSystemClassLoader(); - if (loader instanceof URLClassLoader) { - URLClassLoader cl = (URLClassLoader) loader; - Class sysclass = URLClassLoader.class; - try { - Method method = sysclass.getDeclaredMethod("addURL", URL.class); - method.setAccessible(true); - method.invoke(cl, new File(pathToExecutable).toURI().toURL()); - } catch (SecurityException | NoSuchMethodException | MalformedURLException t) { - LOGGER.error("Error, could not add URL to system classloader", t); - cl.close(); - throw new IOException("Error, could not add URL to system classloader", t); - } - } else { - LOGGER.error("Error occured, URLClassLoader expected but " + loader.getClass() - + " received. Could not continue."); - } + CreationException, IOException, ClassNotFoundException { + + URL[] urls = { Paths.get(pathToExecutable).toUri().toURL()}; + Class clazz = Class.forName("com.sun.star.comp.helper.Bootstrap", true, new URLClassLoader(urls)); + //Get the office component context: XComponentContext xContext = Bootstrap.bootstrap(); //Get the office service manager: diff --git a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java index c56e7606c29..188122d298d 100644 --- a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java @@ -137,21 +137,8 @@ public OpenOfficePanel(JabRefFrame frame, JabRefPreferences jabRefPreferences, O initPanel(); } - private static void addURL(List jarList) throws IOException { - URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader(); - Class sysclass = URLClassLoader.class; - try { - Method method = sysclass.getDeclaredMethod("addURL", URL.class); - method.setAccessible(true); - for (URL anU : jarList) { - method.invoke(sysloader, anU); - } - } catch (SecurityException | NoSuchMethodException | IllegalAccessException | IllegalArgumentException | - InvocationTargetException e) { - LOGGER.error("Could not add URL to system classloader", e); - sysloader.close(); - throw new IOException("Error, could not add URL to system classloader", e); - } + private static void addURL(List jarList) throws IOException, ClassNotFoundException { + Class clazz = Class.forName("com.sun.star.comp.helper.Bootstrap", true, new URLClassLoader( jarList.toArray(new URL[0]) )); } public Node getContent() { @@ -453,12 +440,18 @@ private void loadOpenOfficeJars(Path configurationPath) throws IOException { for (Optional jarPath : filePaths) { jarURLs.add((jarPath.get().toUri().toURL())); } - addURL(jarURLs); + + try { + addURL(jarURLs); + } catch (ClassNotFoundException e) { + LOGGER.error("lo error",e); + } } private OOBibBase createBibBase() throws IOException, InvocationTargetException, IllegalAccessException, - BootstrapException, CreationException { + BootstrapException, CreationException, ClassNotFoundException { // Connect + return new OOBibBase(ooPrefs.getExecutablePath(), true, dialogService); } From e81457a7561d721a006abe07549032147a267ca8 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 7 Sep 2019 18:30:25 +0200 Subject: [PATCH 02/13] refactor and try with custom class loader --- .../org/jabref/gui/openoffice/OOBibBase.java | 19 ++++------- .../gui/openoffice/OpenOfficePanel.java | 23 +++++-------- .../openoffice/ChildFirstClassLoader.java | 33 +++++++++++++++++++ 3 files changed, 49 insertions(+), 26 deletions(-) create mode 100644 src/main/java/org/jabref/logic/openoffice/ChildFirstClassLoader.java diff --git a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java index 7814a52d4e3..a4fa5db2ff7 100644 --- a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java @@ -1,12 +1,8 @@ package org.jabref.gui.openoffice; -import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.MalformedURLException; import java.net.URL; -import java.net.URLClassLoader; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -32,6 +28,7 @@ import org.jabref.logic.bibtex.comparator.FieldComparatorStack; import org.jabref.logic.l10n.Localization; import org.jabref.logic.layout.Layout; +import org.jabref.logic.openoffice.ChildFirstClassLoader; import org.jabref.logic.openoffice.OOBibStyle; import org.jabref.logic.openoffice.OOPreFormatter; import org.jabref.logic.openoffice.OOUtil; @@ -132,7 +129,7 @@ class OOBibBase { private final DialogService dialogService; - public OOBibBase(String pathToOO, boolean atEnd, DialogService dialogService) throws IllegalAccessException, InvocationTargetException, BootstrapException, CreationException, IOException, ClassNotFoundException { + public OOBibBase(List jarUrls, boolean atEnd, DialogService dialogService) throws IllegalAccessException, InvocationTargetException, BootstrapException, CreationException, IOException, ClassNotFoundException { this.dialogService = dialogService; @@ -149,9 +146,7 @@ public OOBibBase(String pathToOO, boolean atEnd, DialogService dialogService) th this.atEnd = atEnd; - xDesktop = simpleBootstrap(pathToOO); - - + xDesktop = simpleBootstrap(jarUrls); } public boolean isConnectedToDocument() { @@ -238,14 +233,14 @@ private List getTextDocuments() throws NoSuchElementException, Wr return result; } - private XDesktop simpleBootstrap(String pathToExecutable) + private XDesktop simpleBootstrap(List jarUrls) throws IllegalAccessException, InvocationTargetException, BootstrapException, CreationException, IOException, ClassNotFoundException { - URL[] urls = { Paths.get(pathToExecutable).toUri().toURL()}; - Class clazz = Class.forName("com.sun.star.comp.helper.Bootstrap", true, new URLClassLoader(urls)); - + URL[] urls = jarUrls.toArray(new URL[3]); + Class clazz = Class.forName("com.sun.star.comp.helper.Bootstrap", true, new ChildFirstClassLoader(urls, null)); + //Get the office component context: XComponentContext xContext = Bootstrap.bootstrap(); //Get the office service manager: diff --git a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java index 188122d298d..2bec311bc4e 100644 --- a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java @@ -3,9 +3,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.net.URL; -import java.net.URLClassLoader; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; @@ -45,6 +43,7 @@ import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternPreferences; import org.jabref.logic.help.HelpFile; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.openoffice.ChildFirstClassLoader; import org.jabref.logic.openoffice.OOBibStyle; import org.jabref.logic.openoffice.OpenOfficePreferences; import org.jabref.logic.openoffice.StyleLoader; @@ -138,7 +137,7 @@ public OpenOfficePanel(JabRefFrame frame, JabRefPreferences jabRefPreferences, O } private static void addURL(List jarList) throws IOException, ClassNotFoundException { - Class clazz = Class.forName("com.sun.star.comp.helper.Bootstrap", true, new URLClassLoader( jarList.toArray(new URL[0]) )); + // Class clazz = Class.forName("com.sun.star.comp.helper.Bootstrap", true, new ChildFirstClassLoader( jarList.toArray(new URL[0]),null )); } public Node getContent() { @@ -373,9 +372,9 @@ private void connect() { @Override protected OOBibBase call() throws Exception { updateProgress(ProgressBar.INDETERMINATE_PROGRESS, ProgressBar.INDETERMINATE_PROGRESS); - loadOpenOfficeJars(Paths.get(ooPrefs.getInstallationPath())); + List jarUrls = loadOpenOfficeJars(Paths.get(ooPrefs.getInstallationPath())); - return createBibBase(); + return createBibBase(jarUrls); } }; @@ -429,7 +428,7 @@ protected OOBibBase call() throws Exception { } - private void loadOpenOfficeJars(Path configurationPath) throws IOException { + private List loadOpenOfficeJars(Path configurationPath) throws IOException { List> filePaths = OpenOfficePreferences.OO_JARS.stream().map(jar -> FileUtil.find(jar, configurationPath)).collect(Collectors.toList()); if (!filePaths.stream().allMatch(Optional::isPresent)) { @@ -440,19 +439,15 @@ private void loadOpenOfficeJars(Path configurationPath) throws IOException { for (Optional jarPath : filePaths) { jarURLs.add((jarPath.get().toUri().toURL())); } - - try { - addURL(jarURLs); - } catch (ClassNotFoundException e) { - LOGGER.error("lo error",e); - } + return jarURLs; + } - private OOBibBase createBibBase() throws IOException, InvocationTargetException, IllegalAccessException, + private OOBibBase createBibBase(List jarUrls) throws IOException, InvocationTargetException, IllegalAccessException, BootstrapException, CreationException, ClassNotFoundException { // Connect - return new OOBibBase(ooPrefs.getExecutablePath(), true, dialogService); + return new OOBibBase(jarUrls,true, dialogService); } private Optional showManualConnectionDialog() { diff --git a/src/main/java/org/jabref/logic/openoffice/ChildFirstClassLoader.java b/src/main/java/org/jabref/logic/openoffice/ChildFirstClassLoader.java new file mode 100644 index 00000000000..a09a53688f2 --- /dev/null +++ b/src/main/java/org/jabref/logic/openoffice/ChildFirstClassLoader.java @@ -0,0 +1,33 @@ +package org.jabref.logic.openoffice; + +import java.net.URL; +import java.net.URLClassLoader; + +public class ChildFirstClassLoader extends URLClassLoader { + + public ChildFirstClassLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); + } + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + // has the class loaded already? + Class loadedClass = findLoadedClass(name); + if (loadedClass == null) { + try { + // find the class from given jar urls + loadedClass = findClass(name); + } catch (ClassNotFoundException e) { + // Hmmm... class does not exist in the given urls. + // Let's try finding it in our parent classloader. + // this'll throw ClassNotFoundException in failure. + loadedClass = super.loadClass(name, resolve); + } + } + + if (resolve) { // marked to resolve + resolveClass(loadedClass); + } + return loadedClass; + } +} \ No newline at end of file From 4fca6a7f2aaad959aaed7fe232701edd26baa388 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sun, 8 Sep 2019 20:01:10 +0200 Subject: [PATCH 03/13] try to init it after loading --- .../java/org/jabref/gui/openoffice/OOBibBase.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java index a4fa5db2ff7..694aac2bf5d 100644 --- a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java @@ -239,10 +239,18 @@ private XDesktop simpleBootstrap(List jarUrls) URL[] urls = jarUrls.toArray(new URL[3]); - Class clazz = Class.forName("com.sun.star.comp.helper.Bootstrap", true, new ChildFirstClassLoader(urls, null)); - + Class clazz = (Class) Class.forName("com.sun.star.comp.helper.Bootstrap", true, new ChildFirstClassLoader(urls, null)); + Bootstrap boot = null; + try { + boot = clazz.getDeclaredConstructor().newInstance(); + } catch (InstantiationException | java.lang.IllegalArgumentException | NoSuchMethodException | SecurityException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + //Get the office component context: - XComponentContext xContext = Bootstrap.bootstrap(); + XComponentContext xContext = boot.bootstrap(); //Get the office service manager: XMultiComponentFactory xServiceManager = xContext.getServiceManager(); //Create the desktop, which is the root frame of the From ecf2ff98b6eaf91472053f80f8a4a512a8d57fd3 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Fri, 13 Sep 2019 14:58:09 +0200 Subject: [PATCH 04/13] fix empty spaces --- .../java/org/jabref/logic/openoffice/ChildFirstClassLoader.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/openoffice/ChildFirstClassLoader.java b/src/main/java/org/jabref/logic/openoffice/ChildFirstClassLoader.java index a09a53688f2..b618a4ac845 100644 --- a/src/main/java/org/jabref/logic/openoffice/ChildFirstClassLoader.java +++ b/src/main/java/org/jabref/logic/openoffice/ChildFirstClassLoader.java @@ -24,7 +24,6 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE loadedClass = super.loadClass(name, resolve); } } - if (resolve) { // marked to resolve resolveClass(loadedClass); } From e60629ecf97d27f846390cb8c23a82fddfafb02b Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 14 Sep 2019 18:10:28 +0200 Subject: [PATCH 05/13] try with a custom implenention of the Boostrap class which accepts a path parameter --- .../org/jabref/gui/openoffice/Bootstrap.java | 436 ++++++++++++++++++ .../org/jabref/gui/openoffice/OOBibBase.java | 17 +- 2 files changed, 441 insertions(+), 12 deletions(-) create mode 100644 src/main/java/org/jabref/gui/openoffice/Bootstrap.java diff --git a/src/main/java/org/jabref/gui/openoffice/Bootstrap.java b/src/main/java/org/jabref/gui/openoffice/Bootstrap.java new file mode 100644 index 00000000000..458da4987ce --- /dev/null +++ b/src/main/java/org/jabref/gui/openoffice/Bootstrap.java @@ -0,0 +1,436 @@ +// -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +package org.jabref.gui.openoffice; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.Random; + +import com.sun.star.bridge.UnoUrlResolver; +import com.sun.star.bridge.XUnoUrlResolver; +import com.sun.star.comp.helper.BootstrapException; +import com.sun.star.comp.helper.ComponentContext; +import com.sun.star.comp.helper.ComponentContextEntry; +import com.sun.star.comp.loader.JavaLoader; +import com.sun.star.comp.servicemanager.ServiceManager; +import com.sun.star.container.XSet; +import com.sun.star.lang.XInitialization; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lib.util.NativeLibraryLoader; +import com.sun.star.loader.XImplementationLoader; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; + +/** Bootstrap offers functionality to obtain a context or simply + a service manager. + The service manager can create a few basic services, whose implementations are: +
    +
  • com.sun.star.comp.loader.JavaLoader
  • +
  • com.sun.star.comp.urlresolver.UrlResolver
  • +
  • com.sun.star.comp.bridgefactory.BridgeFactory
  • +
  • com.sun.star.comp.connections.Connector
  • +
  • com.sun.star.comp.connections.Acceptor
  • +
  • com.sun.star.comp.servicemanager.ServiceManager
  • +
+ + Other services can be inserted into the service manager by + using its XSet interface: +
+        XSet xSet = UnoRuntime.queryInterface( XSet.class, aMultiComponentFactory );
+        // insert the service manager
+        xSet.insert( aSingleComponentFactory );
+    
+*/ +public class Bootstrap { + + private static void insertBasicFactories( + XSet xSet, XImplementationLoader xImpLoader ) + throws Exception + { + // insert the factory of the loader + xSet.insert( xImpLoader.activate( + "com.sun.star.comp.loader.JavaLoader", null, null, null ) ); + + // insert the factory of the URLResolver + xSet.insert( xImpLoader.activate( + "com.sun.star.comp.urlresolver.UrlResolver", null, null, null ) ); + + // insert the bridgefactory + xSet.insert( xImpLoader.activate( + "com.sun.star.comp.bridgefactory.BridgeFactory", null, null, null ) ); + + // insert the connector + xSet.insert( xImpLoader.activate( + "com.sun.star.comp.connections.Connector", null, null, null ) ); + + // insert the acceptor + xSet.insert( xImpLoader.activate( + "com.sun.star.comp.connections.Acceptor", null, null, null ) ); + } + + /** + * Returns an array of default commandline options to start bootstrapped + * instance of soffice with. You may use it in connection with bootstrap + * method for example like this: + *
+     *     List list = Arrays.asList( Bootstrap.getDefaultOptions() );
+     *     list.remove("--nologo");
+     *     list.remove("--nodefault");
+     *     list.add("--invisible");
+     *
+     *     Bootstrap.bootstrap( list.toArray( new String[list.size()] );
+     * 
+ * + * @return an array of default commandline options + * @see #bootstrap( String[] ) + * @since LibreOffice 5.1 + */ + public static final String[] getDefaultOptions() + { + return new String[] + { + "--nologo", + "--nodefault", + "--norestore", + "--nolockcheck" + }; + } + + /** + backwards compatibility stub. + @param context_entries the hash table contains mappings of entry names (type string) to + context entries (type class ComponentContextEntry). + @throws Exception if things go awry. + @return a new context. + */ + public static XComponentContext createInitialComponentContext( Hashtable context_entries ) + throws Exception + { + return createInitialComponentContext((Map) context_entries); + } + /** Bootstraps an initial component context with service manager and basic + jurt components inserted. + @param context_entries the hash table contains mappings of entry names (type string) to + context entries (type class ComponentContextEntry). + @throws Exception if things go awry. + @return a new context. + */ + public static XComponentContext createInitialComponentContext( Map context_entries ) + throws Exception + { + ServiceManager xSMgr = new ServiceManager(); + + XImplementationLoader xImpLoader = UnoRuntime.queryInterface( + XImplementationLoader.class, new JavaLoader() ); + XInitialization xInit = UnoRuntime.queryInterface( + XInitialization.class, xImpLoader ); + Object[] args = new Object [] { xSMgr }; + xInit.initialize( args ); + + // initial component context + if (context_entries == null) + context_entries = new HashMap( 1 ); + // add smgr + context_entries.put( + "/singletons/com.sun.star.lang.theServiceManager", + new ComponentContextEntry( null, xSMgr ) ); + // ... xxx todo: add standard entries + XComponentContext xContext = new ComponentContext( context_entries, null ); + + xSMgr.setDefaultContext(xContext); + + XSet xSet = UnoRuntime.queryInterface( XSet.class, xSMgr ); + // insert basic jurt factories + insertBasicFactories( xSet, xImpLoader ); + + return xContext; + } + + /** + * Bootstraps a servicemanager with the jurt base components registered. + * + * See also UNOIDL com.sun.star.lang.ServiceManager. + * + * @throws Exception if things go awry. + * @return a freshly bootstrapped service manager + */ + public static XMultiServiceFactory createSimpleServiceManager() throws Exception + { + return UnoRuntime.queryInterface( + XMultiServiceFactory.class, createInitialComponentContext( (Map) null ).getServiceManager() ); + } + + + /** Bootstraps the initial component context from a native UNO installation. + + @throws Exception if things go awry. + @return a freshly bootstrapped component context. + + See also + cppuhelper/defaultBootstrap_InitialComponentContext(). + */ + public static final XComponentContext defaultBootstrap_InitialComponentContext() + throws Exception + { + return defaultBootstrap_InitialComponentContext( (String) null, (Map) null ); + } + /** + * Backwards compatibility stub. + * + * @param ini_file + * ini_file (may be null: uno.rc besides cppuhelper lib) + * @param bootstrap_parameters + * bootstrap parameters (maybe null) + * + * @throws Exception if things go awry. + * @return a freshly bootstrapped component context. + */ + public static final XComponentContext defaultBootstrap_InitialComponentContext( + String ini_file, Hashtable bootstrap_parameters ) + throws Exception + { + return defaultBootstrap_InitialComponentContext(ini_file, (Map) bootstrap_parameters); + + } + /** Bootstraps the initial component context from a native UNO installation. + + See also + cppuhelper/defaultBootstrap_InitialComponentContext(). + + @param ini_file + ini_file (may be null: uno.rc besides cppuhelper lib) + @param bootstrap_parameters + bootstrap parameters (maybe null) + + @throws Exception if things go awry. + @return a freshly bootstrapped component context. + */ + public static final XComponentContext defaultBootstrap_InitialComponentContext( + String ini_file, Map bootstrap_parameters ) + throws Exception + { + // jni convenience: easier to iterate over array than calling Hashtable + String pairs [] = null; + if (null != bootstrap_parameters) + { + pairs = new String [ 2 * bootstrap_parameters.size() ]; + int n = 0; + for (Map.Entry bootstrap_parameter : bootstrap_parameters.entrySet()) { + pairs[ n++ ] = bootstrap_parameter.getKey(); + pairs[ n++ ] = bootstrap_parameter.getValue(); + } + } + + if (! m_loaded_juh) + { + if ("The Android Project".equals(System.getProperty("java.vendor"))) + { + // Find out if we are configured with DISABLE_DYNLOADING or + // not. Try to load the lo-bootstrap shared library which + // won't exist in the DISABLE_DYNLOADING case. (And which will + // be already loaded otherwise, so nothing unexpected happens + // that case.) Yeah, this would be simpler if I just could be + // bothered to keep a separate branch for DISABLE_DYNLOADING + // on Android, merging in master periodically, until I know + // for sure whether it is what I want, or not. + + boolean disable_dynloading = false; + try { + System.loadLibrary( "lo-bootstrap" ); + } catch ( UnsatisfiedLinkError e ) { + disable_dynloading = true; + } + + if (!disable_dynloading) + { + NativeLibraryLoader.loadLibrary( Bootstrap.class.getClassLoader(), "juh" ); + } + } + else + { + NativeLibraryLoader.loadLibrary( Bootstrap.class.getClassLoader(), "juh" ); + } + m_loaded_juh = true; + } + return UnoRuntime.queryInterface( + XComponentContext.class, + cppuhelper_bootstrap( + ini_file, pairs, Bootstrap.class.getClassLoader() ) ); + } + + private static boolean m_loaded_juh = false; + private static native Object cppuhelper_bootstrap( + String ini_file, String bootstrap_parameters [], ClassLoader loader ) + throws Exception; + + /** + * Bootstraps the component context from a UNO installation. + * + * @throws BootstrapException if things go awry. + * + * @return a bootstrapped component context. + * + * @since UDK 3.1.0 + */ + public static final XComponentContext bootstrap(String path) + throws BootstrapException { + + String[] defaultArgArray = getDefaultOptions(); + return bootstrap( defaultArgArray, path ); + } + + /** + * Bootstraps the component context from a UNO installation. + * + * @param argArray + * an array of strings - commandline options to start instance of + * soffice with + * @see #getDefaultOptions() + * + * @throws BootstrapException if things go awry. + * + * @return a bootstrapped component context. + * + * @since LibreOffice 5.1 + */ + public static final XComponentContext bootstrap( String[] argArray, String path ) + throws BootstrapException { + + XComponentContext xContext = null; + + try { + // create default local component context + XComponentContext xLocalContext = + createInitialComponentContext( (Map) null ); + if ( xLocalContext == null ) + throw new BootstrapException( "no local component context!" ); + + // find office executable relative to this class's class loader + String sOffice = + System.getProperty( "os.name" ).startsWith( "Windows" ) ? + "soffice.exe" : "soffice"; + + Path fOffice = Paths.get(path).resolve(sOffice).toAbsolutePath(); + /*File fOffice = NativeLibraryLoader.getResource( + Bootstrap.class.getClassLoader(), sOffice );*/ + if ( fOffice == null ) + throw new BootstrapException( "no office executable found!" ); + + // create random pipe name + String sPipeName = "uno" + + Long.toString(randomPipeName.nextLong() & 0x7fffffffffffffffL); + + // create call with arguments + String[] cmdArray = new String[ argArray.length + 2 ]; + cmdArray[0] = fOffice.toString(); + cmdArray[1] = ( "--accept=pipe,name=" + sPipeName + ";urp;" ); + + System.arraycopy( argArray, 0, cmdArray, 2, argArray.length ); + + // start office process + Process p = Runtime.getRuntime().exec( cmdArray ); + pipe( p.getInputStream(), System.out, "CO> " ); + pipe( p.getErrorStream(), System.err, "CE> " ); + + // initial service manager + XMultiComponentFactory xLocalServiceManager = + xLocalContext.getServiceManager(); + if ( xLocalServiceManager == null ) + throw new BootstrapException( "no initial service manager!" ); + + // create a URL resolver + XUnoUrlResolver xUrlResolver = + UnoUrlResolver.create( xLocalContext ); + + // connection string + String sConnect = "uno:pipe,name=" + sPipeName + + ";urp;StarOffice.ComponentContext"; + + // wait until office is started + for (int i = 0;; ++i) { + try { + // try to connect to office + Object context = xUrlResolver.resolve( sConnect ); + xContext = UnoRuntime.queryInterface( + XComponentContext.class, context); + if ( xContext == null ) + throw new BootstrapException( "no component context!" ); + break; + } catch ( com.sun.star.connection.NoConnectException ex ) { + // Wait 500 ms, then try to connect again, but do not wait + // longer than 5 min (= 600 * 500 ms) total: + if (i == 600) { + throw new BootstrapException(ex); + } + Thread.sleep( 500 ); + } + } + } catch ( BootstrapException e ) { + throw e; + } catch ( java.lang.RuntimeException e ) { + throw e; + } catch ( java.lang.Exception e ) { + throw new BootstrapException( e ); + } + + return xContext; + } + + private static final Random randomPipeName = new Random(); + + private static void pipe( + final InputStream in, final PrintStream out, final String prefix ) { + + new Thread( "Pipe: " + prefix) { + @Override + public void run() { + try { + BufferedReader r = new BufferedReader( + new InputStreamReader(in, "UTF-8") ); + + for ( ; ; ) { + String s = r.readLine(); + if ( s == null ) { + break; + } + out.println( prefix + s ); + } + } catch ( UnsupportedEncodingException e ) { + e.printStackTrace( System.err ); + } catch ( java.io.IOException e ) { + e.printStackTrace( System.err ); + } + } + }.start(); + } +} + +// vim:set shiftwidth=4 softtabstop=4 expandtab: diff --git a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java index 694aac2bf5d..e365204d539 100644 --- a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.URL; +import java.net.URLClassLoader; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -237,20 +238,12 @@ private XDesktop simpleBootstrap(List jarUrls) throws IllegalAccessException, InvocationTargetException, BootstrapException, CreationException, IOException, ClassNotFoundException { + String loPath = "C:\\Program Files\\LibreOffice\\program"; - URL[] urls = jarUrls.toArray(new URL[3]); - Class clazz = (Class) Class.forName("com.sun.star.comp.helper.Bootstrap", true, new ChildFirstClassLoader(urls, null)); - Bootstrap boot = null; - try { - boot = clazz.getDeclaredConstructor().newInstance(); - } catch (InstantiationException | java.lang.IllegalArgumentException | NoSuchMethodException | SecurityException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - - + + //Get the office component context: - XComponentContext xContext = boot.bootstrap(); + XComponentContext xContext = org.jabref.gui.openoffice.Bootstrap.bootstrap(loPath); //Get the office service manager: XMultiComponentFactory xServiceManager = xContext.getServiceManager(); //Create the desktop, which is the root frame of the From f5e376c431da3f1fbd2626bf03ba14672a2496e2 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 14 Sep 2019 19:09:26 +0200 Subject: [PATCH 06/13] Hack Boostrap method of OpenOffice to use sockets instead of pipe! --- .../org/jabref/gui/openoffice/Bootstrap.java | 24 ++++++-------- .../org/jabref/gui/openoffice/OOBibBase.java | 19 ++++------- .../gui/openoffice/OpenOfficePanel.java | 1 - .../openoffice/ChildFirstClassLoader.java | 32 ------------------- 4 files changed, 16 insertions(+), 60 deletions(-) delete mode 100644 src/main/java/org/jabref/logic/openoffice/ChildFirstClassLoader.java diff --git a/src/main/java/org/jabref/gui/openoffice/Bootstrap.java b/src/main/java/org/jabref/gui/openoffice/Bootstrap.java index 458da4987ce..a475bf031c3 100644 --- a/src/main/java/org/jabref/gui/openoffice/Bootstrap.java +++ b/src/main/java/org/jabref/gui/openoffice/Bootstrap.java @@ -26,8 +26,7 @@ import java.io.InputStreamReader; import java.io.PrintStream; import java.io.UnsupportedEncodingException; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.net.URLClassLoader; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; @@ -300,11 +299,11 @@ private static native Object cppuhelper_bootstrap( * * @since UDK 3.1.0 */ - public static final XComponentContext bootstrap(String path) + public static final XComponentContext bootstrap(URLClassLoader loader) throws BootstrapException { String[] defaultArgArray = getDefaultOptions(); - return bootstrap( defaultArgArray, path ); + return bootstrap( defaultArgArray, loader); } /** @@ -321,7 +320,7 @@ public static final XComponentContext bootstrap(String path) * * @since LibreOffice 5.1 */ - public static final XComponentContext bootstrap( String[] argArray, String path ) + public static final XComponentContext bootstrap( String[] argArray, URLClassLoader loader ) throws BootstrapException { XComponentContext xContext = null; @@ -338,20 +337,15 @@ public static final XComponentContext bootstrap( String[] argArray, String path System.getProperty( "os.name" ).startsWith( "Windows" ) ? "soffice.exe" : "soffice"; - Path fOffice = Paths.get(path).resolve(sOffice).toAbsolutePath(); - /*File fOffice = NativeLibraryLoader.getResource( - Bootstrap.class.getClassLoader(), sOffice );*/ + File fOffice = NativeLibraryLoader.getResource(loader, sOffice); if ( fOffice == null ) throw new BootstrapException( "no office executable found!" ); - // create random pipe name - String sPipeName = "uno" + - Long.toString(randomPipeName.nextLong() & 0x7fffffffffffffffL); - // create call with arguments + //We need a socket, pipe does not work. https://api.libreoffice.org/examples/examples.html String[] cmdArray = new String[ argArray.length + 2 ]; - cmdArray[0] = fOffice.toString(); - cmdArray[1] = ( "--accept=pipe,name=" + sPipeName + ";urp;" ); + cmdArray[0] = fOffice.getPath(); + cmdArray[1] = ( "--accept=socket,host=localhost,port=2083" + ";urp;" ); System.arraycopy( argArray, 0, cmdArray, 2, argArray.length ); @@ -371,7 +365,7 @@ public static final XComponentContext bootstrap( String[] argArray, String path UnoUrlResolver.create( xLocalContext ); // connection string - String sConnect = "uno:pipe,name=" + sPipeName + + String sConnect = "uno:socket,host=localhost,port=2083"+ ";urp;StarOffice.ComponentContext"; // wait until office is started diff --git a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java index e365204d539..1700f07f722 100644 --- a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java @@ -4,7 +4,6 @@ import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.net.URLClassLoader; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -29,7 +28,6 @@ import org.jabref.logic.bibtex.comparator.FieldComparatorStack; import org.jabref.logic.l10n.Localization; import org.jabref.logic.layout.Layout; -import org.jabref.logic.openoffice.ChildFirstClassLoader; import org.jabref.logic.openoffice.OOBibStyle; import org.jabref.logic.openoffice.OOPreFormatter; import org.jabref.logic.openoffice.OOUtil; @@ -47,7 +45,6 @@ import com.sun.star.beans.UnknownPropertyException; import com.sun.star.beans.XPropertyContainer; import com.sun.star.beans.XPropertySet; -import com.sun.star.comp.helper.Bootstrap; import com.sun.star.comp.helper.BootstrapException; import com.sun.star.container.NoSuchElementException; import com.sun.star.container.XEnumeration; @@ -146,7 +143,7 @@ public OOBibBase(List jarUrls, boolean atEnd, DialogService dialogService) yearAuthorTitleComparator = new FieldComparatorStack<>(yearAuthorTitleList); this.atEnd = atEnd; - + xDesktop = simpleBootstrap(jarUrls); } @@ -230,20 +227,18 @@ private List getTextDocuments() throws NoSuchElementException, Wr if (document != null) { result.add(document); } - } + } return result; } private XDesktop simpleBootstrap(List jarUrls) - throws IllegalAccessException, InvocationTargetException, BootstrapException, - CreationException, IOException, ClassNotFoundException { + throws CreationException, BootstrapException { + + URL[] urls = jarUrls.toArray(new URL[1]); + URLClassLoader loader = new URLClassLoader(urls, null); - String loPath = "C:\\Program Files\\LibreOffice\\program"; - - - //Get the office component context: - XComponentContext xContext = org.jabref.gui.openoffice.Bootstrap.bootstrap(loPath); + XComponentContext xContext = org.jabref.gui.openoffice.Bootstrap.bootstrap(loader); //Get the office service manager: XMultiComponentFactory xServiceManager = xContext.getServiceManager(); //Create the desktop, which is the root frame of the diff --git a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java index 2bec311bc4e..7d6c57128af 100644 --- a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java @@ -43,7 +43,6 @@ import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternPreferences; import org.jabref.logic.help.HelpFile; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.openoffice.ChildFirstClassLoader; import org.jabref.logic.openoffice.OOBibStyle; import org.jabref.logic.openoffice.OpenOfficePreferences; import org.jabref.logic.openoffice.StyleLoader; diff --git a/src/main/java/org/jabref/logic/openoffice/ChildFirstClassLoader.java b/src/main/java/org/jabref/logic/openoffice/ChildFirstClassLoader.java deleted file mode 100644 index b618a4ac845..00000000000 --- a/src/main/java/org/jabref/logic/openoffice/ChildFirstClassLoader.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.jabref.logic.openoffice; - -import java.net.URL; -import java.net.URLClassLoader; - -public class ChildFirstClassLoader extends URLClassLoader { - - public ChildFirstClassLoader(URL[] urls, ClassLoader parent) { - super(urls, parent); - } - - @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - // has the class loaded already? - Class loadedClass = findLoadedClass(name); - if (loadedClass == null) { - try { - // find the class from given jar urls - loadedClass = findClass(name); - } catch (ClassNotFoundException e) { - // Hmmm... class does not exist in the given urls. - // Let's try finding it in our parent classloader. - // this'll throw ClassNotFoundException in failure. - loadedClass = super.loadClass(name, resolve); - } - } - if (resolve) { // marked to resolve - resolveClass(loadedClass); - } - return loadedClass; - } -} \ No newline at end of file From 9e9a94c720531ef7fc946fdc3446aecf294843f8 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 14 Sep 2019 21:09:40 +0200 Subject: [PATCH 07/13] checkstyle --- .../org/jabref/gui/openoffice/Bootstrap.java | 241 +++++++----------- 1 file changed, 95 insertions(+), 146 deletions(-) diff --git a/src/main/java/org/jabref/gui/openoffice/Bootstrap.java b/src/main/java/org/jabref/gui/openoffice/Bootstrap.java index a475bf031c3..76d1815ed79 100644 --- a/src/main/java/org/jabref/gui/openoffice/Bootstrap.java +++ b/src/main/java/org/jabref/gui/openoffice/Bootstrap.java @@ -69,30 +69,23 @@ */ public class Bootstrap { + private static final Random RANDOM_PIPE_NAME = new Random(); - private static void insertBasicFactories( - XSet xSet, XImplementationLoader xImpLoader ) - throws Exception - { + private static void insertBasicFactories(XSet xSet, XImplementationLoader xImpLoader) throws Exception { // insert the factory of the loader - xSet.insert( xImpLoader.activate( - "com.sun.star.comp.loader.JavaLoader", null, null, null ) ); + xSet.insert(xImpLoader.activate("com.sun.star.comp.loader.JavaLoader", null, null, null)); // insert the factory of the URLResolver - xSet.insert( xImpLoader.activate( - "com.sun.star.comp.urlresolver.UrlResolver", null, null, null ) ); + xSet.insert(xImpLoader.activate("com.sun.star.comp.urlresolver.UrlResolver", null, null, null)); // insert the bridgefactory - xSet.insert( xImpLoader.activate( - "com.sun.star.comp.bridgefactory.BridgeFactory", null, null, null ) ); + xSet.insert(xImpLoader.activate("com.sun.star.comp.bridgefactory.BridgeFactory", null, null, null)); // insert the connector - xSet.insert( xImpLoader.activate( - "com.sun.star.comp.connections.Connector", null, null, null ) ); + xSet.insert(xImpLoader.activate("com.sun.star.comp.connections.Connector", null, null, null)); // insert the acceptor - xSet.insert( xImpLoader.activate( - "com.sun.star.comp.connections.Acceptor", null, null, null ) ); + xSet.insert(xImpLoader.activate("com.sun.star.comp.connections.Acceptor", null, null, null)); } /** @@ -112,15 +105,8 @@ private static void insertBasicFactories( * @see #bootstrap( String[] ) * @since LibreOffice 5.1 */ - public static final String[] getDefaultOptions() - { - return new String[] - { - "--nologo", - "--nodefault", - "--norestore", - "--nolockcheck" - }; + public static final String[] getDefaultOptions() { + return new String[] {"--nologo", "--nodefault", "--norestore", "--nolockcheck"}; } /** @@ -130,11 +116,10 @@ context entries (type class ComponentContextEntry). @throws Exception if things go awry. @return a new context. */ - public static XComponentContext createInitialComponentContext( Hashtable context_entries ) - throws Exception - { + public static XComponentContext createInitialComponentContext(Hashtable context_entries) throws Exception { return createInitialComponentContext((Map) context_entries); } + /** Bootstraps an initial component context with service manager and basic jurt components inserted. @param context_entries the hash table contains mappings of entry names (type string) to @@ -142,33 +127,27 @@ context entries (type class ComponentContextEntry). @throws Exception if things go awry. @return a new context. */ - public static XComponentContext createInitialComponentContext( Map context_entries ) - throws Exception - { + public static XComponentContext createInitialComponentContext(Map context_entries) throws Exception { ServiceManager xSMgr = new ServiceManager(); - XImplementationLoader xImpLoader = UnoRuntime.queryInterface( - XImplementationLoader.class, new JavaLoader() ); - XInitialization xInit = UnoRuntime.queryInterface( - XInitialization.class, xImpLoader ); - Object[] args = new Object [] { xSMgr }; - xInit.initialize( args ); + XImplementationLoader xImpLoader = UnoRuntime.queryInterface(XImplementationLoader.class, new JavaLoader()); + XInitialization xInit = UnoRuntime.queryInterface(XInitialization.class, xImpLoader); + Object[] args = new Object[] {xSMgr}; + xInit.initialize(args); // initial component context if (context_entries == null) - context_entries = new HashMap( 1 ); + context_entries = new HashMap(1); // add smgr - context_entries.put( - "/singletons/com.sun.star.lang.theServiceManager", - new ComponentContextEntry( null, xSMgr ) ); + context_entries.put("/singletons/com.sun.star.lang.theServiceManager", new ComponentContextEntry(null, xSMgr)); // ... xxx todo: add standard entries - XComponentContext xContext = new ComponentContext( context_entries, null ); + XComponentContext xContext = new ComponentContext(context_entries, null); xSMgr.setDefaultContext(xContext); - XSet xSet = UnoRuntime.queryInterface( XSet.class, xSMgr ); + XSet xSet = UnoRuntime.queryInterface(XSet.class, xSMgr); // insert basic jurt factories - insertBasicFactories( xSet, xImpLoader ); + insertBasicFactories(xSet, xImpLoader); return xContext; } @@ -181,26 +160,22 @@ public static XComponentContext createInitialComponentContext( Map) null ).getServiceManager() ); + public static XMultiServiceFactory createSimpleServiceManager() throws Exception { + return UnoRuntime.queryInterface(XMultiServiceFactory.class, createInitialComponentContext((Map) null).getServiceManager()); } - /** Bootstraps the initial component context from a native UNO installation. - + @throws Exception if things go awry. @return a freshly bootstrapped component context. - + See also cppuhelper/defaultBootstrap_InitialComponentContext(). */ - public static final XComponentContext defaultBootstrap_InitialComponentContext() - throws Exception - { - return defaultBootstrap_InitialComponentContext( (String) null, (Map) null ); + public static final XComponentContext defaultBootstrap_InitialComponentContext() throws Exception { + return defaultBootstrap_InitialComponentContext((String) null, (Map) null); } + /** * Backwards compatibility stub. * @@ -212,46 +187,37 @@ public static final XComponentContext defaultBootstrap_InitialComponentContext() * @throws Exception if things go awry. * @return a freshly bootstrapped component context. */ - public static final XComponentContext defaultBootstrap_InitialComponentContext( - String ini_file, Hashtable bootstrap_parameters ) - throws Exception - { - return defaultBootstrap_InitialComponentContext(ini_file, (Map) bootstrap_parameters); - + public static final XComponentContext defaultBootstrap_InitialComponentContext(String ini_file, Hashtable bootstrap_parameters) throws Exception { + return defaultBootstrap_InitialComponentContext(ini_file, (Map) bootstrap_parameters); } - /** Bootstraps the initial component context from a native UNO installation. + /** Bootstraps the initial component context from a native UNO installation. + See also cppuhelper/defaultBootstrap_InitialComponentContext(). - + @param ini_file ini_file (may be null: uno.rc besides cppuhelper lib) @param bootstrap_parameters bootstrap parameters (maybe null) - + @throws Exception if things go awry. @return a freshly bootstrapped component context. */ - public static final XComponentContext defaultBootstrap_InitialComponentContext( - String ini_file, Map bootstrap_parameters ) - throws Exception - { + public static final XComponentContext defaultBootstrap_InitialComponentContext(String ini_file, Map bootstrap_parameters) throws Exception { // jni convenience: easier to iterate over array than calling Hashtable - String pairs [] = null; - if (null != bootstrap_parameters) - { - pairs = new String [ 2 * bootstrap_parameters.size() ]; + String pairs[] = null; + if (null != bootstrap_parameters) { + pairs = new String[2 * bootstrap_parameters.size()]; int n = 0; for (Map.Entry bootstrap_parameter : bootstrap_parameters.entrySet()) { - pairs[ n++ ] = bootstrap_parameter.getKey(); - pairs[ n++ ] = bootstrap_parameter.getValue(); + pairs[n++] = bootstrap_parameter.getKey(); + pairs[n++] = bootstrap_parameter.getValue(); } } - if (! m_loaded_juh) - { - if ("The Android Project".equals(System.getProperty("java.vendor"))) - { + if (!m_loaded_juh) { + if ("The Android Project".equals(System.getProperty("java.vendor"))) { // Find out if we are configured with DISABLE_DYNLOADING or // not. Try to load the lo-bootstrap shared library which // won't exist in the DISABLE_DYNLOADING case. (And which will @@ -263,32 +229,25 @@ public static final XComponentContext defaultBootstrap_InitialComponentContext( boolean disable_dynloading = false; try { - System.loadLibrary( "lo-bootstrap" ); - } catch ( UnsatisfiedLinkError e ) { + System.loadLibrary("lo-bootstrap"); + } catch (UnsatisfiedLinkError e) { disable_dynloading = true; } - if (!disable_dynloading) - { - NativeLibraryLoader.loadLibrary( Bootstrap.class.getClassLoader(), "juh" ); - } - } - else - { - NativeLibraryLoader.loadLibrary( Bootstrap.class.getClassLoader(), "juh" ); + if (!disable_dynloading) { + NativeLibraryLoader.loadLibrary(Bootstrap.class.getClassLoader(), "juh"); + } + } else { + NativeLibraryLoader.loadLibrary(Bootstrap.class.getClassLoader(), "juh"); } m_loaded_juh = true; } - return UnoRuntime.queryInterface( - XComponentContext.class, - cppuhelper_bootstrap( - ini_file, pairs, Bootstrap.class.getClassLoader() ) ); + return UnoRuntime.queryInterface(XComponentContext.class, cppuhelper_bootstrap(ini_file, pairs, Bootstrap.class.getClassLoader())); } private static boolean m_loaded_juh = false; - private static native Object cppuhelper_bootstrap( - String ini_file, String bootstrap_parameters [], ClassLoader loader ) - throws Exception; + + private static native Object cppuhelper_bootstrap(String ini_file, String bootstrap_parameters[], ClassLoader loader) throws Exception; /** * Bootstraps the component context from a UNO installation. @@ -299,11 +258,10 @@ private static native Object cppuhelper_bootstrap( * * @since UDK 3.1.0 */ - public static final XComponentContext bootstrap(URLClassLoader loader) - throws BootstrapException { + public static final XComponentContext bootstrap(URLClassLoader loader) throws BootstrapException { String[] defaultArgArray = getDefaultOptions(); - return bootstrap( defaultArgArray, loader); + return bootstrap(defaultArgArray, loader); } /** @@ -320,107 +278,98 @@ public static final XComponentContext bootstrap(URLClassLoader loader) * * @since LibreOffice 5.1 */ - public static final XComponentContext bootstrap( String[] argArray, URLClassLoader loader ) - throws BootstrapException { + public static final XComponentContext bootstrap(String[] argArray, URLClassLoader loader) throws BootstrapException { XComponentContext xContext = null; try { // create default local component context - XComponentContext xLocalContext = - createInitialComponentContext( (Map) null ); - if ( xLocalContext == null ) - throw new BootstrapException( "no local component context!" ); + XComponentContext xLocalContext = createInitialComponentContext((Map) null); + if (xLocalContext == null) + throw new BootstrapException("no local component context!"); // find office executable relative to this class's class loader - String sOffice = - System.getProperty( "os.name" ).startsWith( "Windows" ) ? - "soffice.exe" : "soffice"; - + String sOffice = System.getProperty("os.name").startsWith("Windows") ? "soffice.exe" : "soffice"; + File fOffice = NativeLibraryLoader.getResource(loader, sOffice); - if ( fOffice == null ) - throw new BootstrapException( "no office executable found!" ); + if (fOffice == null) + throw new BootstrapException("no office executable found!"); // create call with arguments //We need a socket, pipe does not work. https://api.libreoffice.org/examples/examples.html - String[] cmdArray = new String[ argArray.length + 2 ]; + String[] cmdArray = new String[argArray.length + 2]; cmdArray[0] = fOffice.getPath(); - cmdArray[1] = ( "--accept=socket,host=localhost,port=2083" + ";urp;" ); + cmdArray[1] = ("--accept=socket,host=localhost,port=2083" + ";urp;"); - System.arraycopy( argArray, 0, cmdArray, 2, argArray.length ); + System.arraycopy(argArray, 0, cmdArray, 2, argArray.length); // start office process - Process p = Runtime.getRuntime().exec( cmdArray ); - pipe( p.getInputStream(), System.out, "CO> " ); - pipe( p.getErrorStream(), System.err, "CE> " ); + Process p = Runtime.getRuntime().exec(cmdArray); + pipe(p.getInputStream(), System.out, "CO> "); + pipe(p.getErrorStream(), System.err, "CE> "); // initial service manager - XMultiComponentFactory xLocalServiceManager = - xLocalContext.getServiceManager(); - if ( xLocalServiceManager == null ) - throw new BootstrapException( "no initial service manager!" ); + XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager(); + if (xLocalServiceManager == null) + throw new BootstrapException("no initial service manager!"); // create a URL resolver - XUnoUrlResolver xUrlResolver = - UnoUrlResolver.create( xLocalContext ); + XUnoUrlResolver xUrlResolver = UnoUrlResolver.create(xLocalContext); // connection string - String sConnect = "uno:socket,host=localhost,port=2083"+ - ";urp;StarOffice.ComponentContext"; + String sConnect = "uno:socket,host=localhost,port=2083" + ";urp;StarOffice.ComponentContext"; // wait until office is started for (int i = 0;; ++i) { try { // try to connect to office - Object context = xUrlResolver.resolve( sConnect ); - xContext = UnoRuntime.queryInterface( - XComponentContext.class, context); - if ( xContext == null ) - throw new BootstrapException( "no component context!" ); + Object context = xUrlResolver.resolve(sConnect); + xContext = UnoRuntime.queryInterface(XComponentContext.class, context); + if (xContext == null) + throw new BootstrapException("no component context!"); break; - } catch ( com.sun.star.connection.NoConnectException ex ) { + } catch (com.sun.star.connection.NoConnectException ex) { // Wait 500 ms, then try to connect again, but do not wait // longer than 5 min (= 600 * 500 ms) total: if (i == 600) { throw new BootstrapException(ex); } - Thread.sleep( 500 ); + Thread.sleep(500); } } - } catch ( BootstrapException e ) { + } catch (BootstrapException e) { throw e; - } catch ( java.lang.RuntimeException e ) { + } catch (java.lang.RuntimeException e) { throw e; - } catch ( java.lang.Exception e ) { - throw new BootstrapException( e ); + } catch (java.lang.Exception e) { + throw new BootstrapException(e); } return xContext; } - private static final Random randomPipeName = new Random(); + + + private static void pipe(final InputStream in, final PrintStream out, final String prefix) { - private static void pipe( - final InputStream in, final PrintStream out, final String prefix ) { + new Thread("Pipe: " + prefix) { - new Thread( "Pipe: " + prefix) { @Override public void run() { try { - BufferedReader r = new BufferedReader( - new InputStreamReader(in, "UTF-8") ); + BufferedReader r = new BufferedReader(new InputStreamReader(in, "UTF-8")); - for ( ; ; ) { + for (;;) { String s = r.readLine(); - if ( s == null ) { + if (s == null) { break; } - out.println( prefix + s ); + out.println(prefix + s); } - } catch ( UnsupportedEncodingException e ) { - e.printStackTrace( System.err ); - } catch ( java.io.IOException e ) { - e.printStackTrace( System.err ); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(System.err); + } catch (java.io.IOException e) { + e.printStackTrace(System.err); } } }.start(); From 442ddec1454c181da58b0ffbc70a3dee707476a5 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 14 Sep 2019 21:12:47 +0200 Subject: [PATCH 08/13] update submodule? --- src/main/resources/csl-styles | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/csl-styles b/src/main/resources/csl-styles index 83603de7a7f..fa125ec03c6 160000 --- a/src/main/resources/csl-styles +++ b/src/main/resources/csl-styles @@ -1 +1 @@ -Subproject commit 83603de7a7f4652f8d1733f18f0c00be8974948e +Subproject commit fa125ec03c6270dea5881ec1623f1b741da6e759 From d93695106283668df8466027b3e1d673ab9fcedf Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 14 Sep 2019 21:16:29 +0200 Subject: [PATCH 09/13] checkstyle rest of the document --- src/main/java/org/jabref/gui/openoffice/Bootstrap.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/gui/openoffice/Bootstrap.java b/src/main/java/org/jabref/gui/openoffice/Bootstrap.java index 76d1815ed79..5872f81b21d 100644 --- a/src/main/java/org/jabref/gui/openoffice/Bootstrap.java +++ b/src/main/java/org/jabref/gui/openoffice/Bootstrap.java @@ -69,6 +69,7 @@ */ public class Bootstrap { + private static final Random RANDOM_PIPE_NAME = new Random(); private static void insertBasicFactories(XSet xSet, XImplementationLoader xImpLoader) throws Exception { @@ -348,8 +349,6 @@ public static final XComponentContext bootstrap(String[] argArray, URLClassLoade return xContext; } - - private static void pipe(final InputStream in, final PrintStream out, final String prefix) { new Thread("Pipe: " + prefix) { From 89d49813b934e00df31a37b2db8e4bf01c924593 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 14 Sep 2019 21:18:46 +0200 Subject: [PATCH 10/13] run cleanup as well to introduce block braces --- .../org/jabref/gui/openoffice/Bootstrap.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/jabref/gui/openoffice/Bootstrap.java b/src/main/java/org/jabref/gui/openoffice/Bootstrap.java index 5872f81b21d..31a5f9bd754 100644 --- a/src/main/java/org/jabref/gui/openoffice/Bootstrap.java +++ b/src/main/java/org/jabref/gui/openoffice/Bootstrap.java @@ -137,8 +137,9 @@ public static XComponentContext createInitialComponentContext(Map(1); + if (context_entries == null) { + context_entries = new HashMap<>(1); + } // add smgr context_entries.put("/singletons/com.sun.star.lang.theServiceManager", new ComponentContextEntry(null, xSMgr)); // ... xxx todo: add standard entries @@ -166,10 +167,10 @@ public static XMultiServiceFactory createSimpleServiceManager() throws Exception } /** Bootstraps the initial component context from a native UNO installation. - + @throws Exception if things go awry. @return a freshly bootstrapped component context. - + See also cppuhelper/defaultBootstrap_InitialComponentContext(). */ @@ -193,15 +194,15 @@ public static final XComponentContext defaultBootstrap_InitialComponentContext(S } /** Bootstraps the initial component context from a native UNO installation. - + See also cppuhelper/defaultBootstrap_InitialComponentContext(). - + @param ini_file ini_file (may be null: uno.rc besides cppuhelper lib) @param bootstrap_parameters bootstrap parameters (maybe null) - + @throws Exception if things go awry. @return a freshly bootstrapped component context. */ @@ -286,15 +287,17 @@ public static final XComponentContext bootstrap(String[] argArray, URLClassLoade try { // create default local component context XComponentContext xLocalContext = createInitialComponentContext((Map) null); - if (xLocalContext == null) + if (xLocalContext == null) { throw new BootstrapException("no local component context!"); + } // find office executable relative to this class's class loader String sOffice = System.getProperty("os.name").startsWith("Windows") ? "soffice.exe" : "soffice"; File fOffice = NativeLibraryLoader.getResource(loader, sOffice); - if (fOffice == null) + if (fOffice == null) { throw new BootstrapException("no office executable found!"); + } // create call with arguments //We need a socket, pipe does not work. https://api.libreoffice.org/examples/examples.html @@ -311,8 +314,9 @@ public static final XComponentContext bootstrap(String[] argArray, URLClassLoade // initial service manager XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager(); - if (xLocalServiceManager == null) + if (xLocalServiceManager == null) { throw new BootstrapException("no initial service manager!"); + } // create a URL resolver XUnoUrlResolver xUrlResolver = UnoUrlResolver.create(xLocalContext); @@ -326,8 +330,9 @@ public static final XComponentContext bootstrap(String[] argArray, URLClassLoade // try to connect to office Object context = xUrlResolver.resolve(sConnect); xContext = UnoRuntime.queryInterface(XComponentContext.class, context); - if (xContext == null) + if (xContext == null) { throw new BootstrapException("no component context!"); + } break; } catch (com.sun.star.connection.NoConnectException ex) { // Wait 500 ms, then try to connect again, but do not wait From 56c2d780521d1923717194f46cfd978d61006b94 Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sat, 14 Sep 2019 21:31:05 +0200 Subject: [PATCH 11/13] move static variable up to fix checkstyle --- src/main/java/org/jabref/gui/openoffice/Bootstrap.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/gui/openoffice/Bootstrap.java b/src/main/java/org/jabref/gui/openoffice/Bootstrap.java index 31a5f9bd754..059e04f1fc0 100644 --- a/src/main/java/org/jabref/gui/openoffice/Bootstrap.java +++ b/src/main/java/org/jabref/gui/openoffice/Bootstrap.java @@ -71,6 +71,7 @@ public class Bootstrap { private static final Random RANDOM_PIPE_NAME = new Random(); + private static boolean M_LOADED_JUH = false; private static void insertBasicFactories(XSet xSet, XImplementationLoader xImpLoader) throws Exception { // insert the factory of the loader @@ -218,7 +219,7 @@ public static final XComponentContext defaultBootstrap_InitialComponentContext(S } } - if (!m_loaded_juh) { + if (!M_LOADED_JUH) { if ("The Android Project".equals(System.getProperty("java.vendor"))) { // Find out if we are configured with DISABLE_DYNLOADING or // not. Try to load the lo-bootstrap shared library which @@ -242,13 +243,11 @@ public static final XComponentContext defaultBootstrap_InitialComponentContext(S } else { NativeLibraryLoader.loadLibrary(Bootstrap.class.getClassLoader(), "juh"); } - m_loaded_juh = true; + M_LOADED_JUH = true; } return UnoRuntime.queryInterface(XComponentContext.class, cppuhelper_bootstrap(ini_file, pairs, Bootstrap.class.getClassLoader())); } - private static boolean m_loaded_juh = false; - private static native Object cppuhelper_bootstrap(String ini_file, String bootstrap_parameters[], ClassLoader loader) throws Exception; /** From d935f254887ce8a037a3db9841daf64bd6e5acfb Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sun, 15 Sep 2019 12:24:42 +0200 Subject: [PATCH 12/13] remove obsolete method fix spacing --- .../org/jabref/gui/openoffice/OpenOfficePanel.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java index 7d6c57128af..e790ce3c4db 100644 --- a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java @@ -135,10 +135,6 @@ public OpenOfficePanel(JabRefFrame frame, JabRefPreferences jabRefPreferences, O initPanel(); } - private static void addURL(List jarList) throws IOException, ClassNotFoundException { - // Class clazz = Class.forName("com.sun.star.comp.helper.Bootstrap", true, new ChildFirstClassLoader( jarList.toArray(new URL[0]),null )); - } - public Node getContent() { return vbox; } @@ -366,12 +362,12 @@ private void connectManually() { private void connect() { ooPrefs = jabRefPreferences.getOpenOfficePreferences(); - Task connectTask = new Task() { + Task connectTask = new Task<>() { @Override protected OOBibBase call() throws Exception { updateProgress(ProgressBar.INDETERMINATE_PROGRESS, ProgressBar.INDETERMINATE_PROGRESS); - List jarUrls = loadOpenOfficeJars(Paths.get(ooPrefs.getInstallationPath())); + List jarUrls = findOpenOfficeJars(Paths.get(ooPrefs.getInstallationPath())); return createBibBase(jarUrls); } @@ -427,7 +423,7 @@ protected OOBibBase call() throws Exception { } - private List loadOpenOfficeJars(Path configurationPath) throws IOException { + private List findOpenOfficeJars(Path configurationPath) throws IOException { List> filePaths = OpenOfficePreferences.OO_JARS.stream().map(jar -> FileUtil.find(jar, configurationPath)).collect(Collectors.toList()); if (!filePaths.stream().allMatch(Optional::isPresent)) { @@ -444,9 +440,7 @@ private List loadOpenOfficeJars(Path configurationPath) throws IOException private OOBibBase createBibBase(List jarUrls) throws IOException, InvocationTargetException, IllegalAccessException, BootstrapException, CreationException, ClassNotFoundException { - // Connect - - return new OOBibBase(jarUrls,true, dialogService); + return new OOBibBase(jarUrls, true, dialogService); } private Optional showManualConnectionDialog() { From e62af1ffca82980442c955255f326aea40e3a27b Mon Sep 17 00:00:00 2001 From: Siedlerchr Date: Sun, 15 Sep 2019 15:19:12 +0200 Subject: [PATCH 13/13] Add changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65c3e9bed6d..c96ac04290c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# ### Fixed - Inherit fields from cross-referenced entries as specified by biblatex [#5045](https://github.com/JabRef/jabref/issues/5045) +- We fixed an issue where it was no longer possible to connect to LibreOffice [#5261](https://github.com/JabRef/jabref/issues/5261) + ### Removed