From: Florian Zschocke Date: Thu, 7 Nov 2019 19:00:17 +0000 (+0100) Subject: For Java 9+ define the classpath instead of using a Launcher. X-Git-Tag: r1.9.0~31 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b902e6949ea283e9e553b5b9288bb1da13193db7;p=gitblit.git For Java 9+ define the classpath instead of using a Launcher. The (moxie and other) Launcher do not work with Java 9 and later anymore. It used to dynamically extend the classpath, misusing an internal interface of the `URLClassLoader`. This is no longer possible since Java 9, which closed that path and does not offer any way to dynamically extend the classpath during runtime. So the choice is between providing one large Jar with everything in it, providing a Jar that has the Jars in `ext` listed explicitly in its manifest, and specifying the classpath on the command line where the `ext` directory can be added and all contained jar files will be put on the classpath. The motivation for the Launcher class was to be able to simply drop new jar files into a directory and they will be picked up at the application start, without having to specify a classpath. We opt for solution three here. This way jar files can still be dropped into the ext directory, albeit the directory needs to be added to the classpath on the command line. Unfortunately using a wildcard is not possible in the manifest file. We change the calls in the script files accordingly. This seems like a good compromise, since no one will run the application manually typing the whole commandline anyway. This also does away with the splash screen, by the way. Again, doesn't seem like a big loss, as I don't think it was ever shown for the Authority. Personally, I am not convinced that it is the best way, because I don't really think that the use case of dropping whatever jar files into the `ext` directory is a valid one that happened a lot. This does not yet fix the client programs, which still use a Launcher. Maybe for them a all-in-one Jar is a better solution. Fixes #1262 Fixes #1294 --- diff --git a/build.xml b/build.xml index 8787623b..c8bace50 100644 --- a/build.xml +++ b/build.xml @@ -205,7 +205,6 @@ - diff --git a/src/main/distrib/linux/authority.sh b/src/main/distrib/linux/authority.sh index ce5c2377..740f51a8 100644 --- a/src/main/distrib/linux/authority.sh +++ b/src/main/distrib/linux/authority.sh @@ -1,2 +1,2 @@ #!/bin/bash -java -cp gitblit.jar com.gitblit.authority.Launcher --baseFolder data +java -cp gitblit.jar:ext/* com.gitblit.authority.GitblitAuthority --baseFolder data diff --git a/src/main/distrib/linux/gitblit-stop.sh b/src/main/distrib/linux/gitblit-stop.sh index 2fef2034..2a774644 100644 --- a/src/main/distrib/linux/gitblit-stop.sh +++ b/src/main/distrib/linux/gitblit-stop.sh @@ -1,2 +1,2 @@ #!/bin/bash -java -jar gitblit.jar --baseFolder data --stop +java -cp "gitblit.jar:ext/*" com.gitblit.GitBlitServer --baseFolder data --stop diff --git a/src/main/distrib/linux/gitblit.sh b/src/main/distrib/linux/gitblit.sh index 7d631e72..2a52e24e 100644 --- a/src/main/distrib/linux/gitblit.sh +++ b/src/main/distrib/linux/gitblit.sh @@ -1,2 +1,2 @@ #!/bin/bash -java -jar gitblit.jar --baseFolder data +java -cp "gitblit.jar:ext/*" com.gitblit.GitBlitServer --baseFolder data diff --git a/src/main/distrib/win/authority.cmd b/src/main/distrib/win/authority.cmd index f9a18640..3a27c8a9 100644 --- a/src/main/distrib/win/authority.cmd +++ b/src/main/distrib/win/authority.cmd @@ -1 +1 @@ -@java -cp gitblit.jar com.gitblit.authority.Launcher --baseFolder data %* +@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.authority.GitblitAuthority --baseFolder data %* diff --git a/src/main/distrib/win/gitblit-stop.cmd b/src/main/distrib/win/gitblit-stop.cmd index 34f0f4be..b6bebd8a 100644 --- a/src/main/distrib/win/gitblit-stop.cmd +++ b/src/main/distrib/win/gitblit-stop.cmd @@ -1 +1 @@ -@java -jar gitblit.jar --stop --baseFolder data %* +@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --stop --baseFolder data %* diff --git a/src/main/distrib/win/gitblit.cmd b/src/main/distrib/win/gitblit.cmd index 1a6d7e09..6cd193dd 100644 --- a/src/main/distrib/win/gitblit.cmd +++ b/src/main/distrib/win/gitblit.cmd @@ -1 +1 @@ -@java -jar gitblit.jar --baseFolder data %* +@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --baseFolder data %* diff --git a/src/main/distrib/win/installService.cmd b/src/main/distrib/win/installService.cmd index a684ab21..ef2ba2d0 100644 --- a/src/main/distrib/win/installService.cmd +++ b/src/main/distrib/win/installService.cmd @@ -23,16 +23,16 @@ SET ARCH=amd64 --StdOutput=auto ^ --StdError=auto ^ --StartPath="%CD%" ^ - --StartClass=org.moxie.MxLauncher ^ + --StartClass=com.gitblit.GitBlitServer ^ --StartMethod=main ^ --StartParams="--storePassword;gitblit;--baseFolder;%CD%\data" ^ --StartMode=jvm ^ --StopPath="%CD%" ^ - --StopClass=org.moxie.MxLauncher ^ + --StopClass=com.gitblit.GitBlitServer ^ --StopMethod=main ^ --StopParams="--stop;--baseFolder;%CD%\data" ^ --StopMode=jvm ^ - --Classpath="%CD%\gitblit.jar" ^ + --Classpath="%CD%\gitblit.jar;%CD%\ext\*" ^ --Jvm=auto ^ --JvmMx=1024 \ No newline at end of file diff --git a/src/main/java/com/gitblit/GitBlitServer.java b/src/main/java/com/gitblit/GitBlitServer.java index e006e2c8..06000f53 100644 --- a/src/main/java/com/gitblit/GitBlitServer.java +++ b/src/main/java/com/gitblit/GitBlitServer.java @@ -143,7 +143,7 @@ public class GitBlitServer { if (parser != null) { parser.printUsage(System.out); System.out - .println("\nExample:\n java -server -Xmx1024M -jar gitblit.jar --repositoriesFolder c:\\git --httpPort 80 --httpsPort 443"); + .println("\nExample:\n java -server -Xmx1024M -cp gitblit.jar:ext/* com.gitblit.GitBlitServer --repositoriesFolder /srv/git --httpPort 80 --httpsPort 443"); } System.exit(0); } diff --git a/src/main/java/com/gitblit/Launcher.java b/src/main/java/com/gitblit/Launcher.java deleted file mode 100644 index 68a9dbf9..00000000 --- a/src/main/java/com/gitblit/Launcher.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2011 gitblit.com. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.gitblit; - -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLClassLoader; -import java.security.ProtectionDomain; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * Launch helper class that adds all jars found in the local "lib" & "ext" - * folders and then calls the application main. Using this technique we do not - * have to specify a classpath and we can dynamically add jars to the - * distribution. - * - * @author James Moger - * - */ -public class Launcher { - - public static final boolean DEBUG = false; - - /** - * Parameters of the method to add an URL to the System classes. - */ - private static final Class[] PARAMETERS = new Class[] { URL.class }; - - public static void main(String[] args) { - if (DEBUG) { - System.out.println("jcp=" + System.getProperty("java.class.path")); - ProtectionDomain protectionDomain = Launcher.class.getProtectionDomain(); - System.out.println("launcher=" - + protectionDomain.getCodeSource().getLocation().toExternalForm()); - } - - // Load the JARs in the lib and ext folder - String[] folders = new String[] { "lib", "ext" }; - List jars = new ArrayList(); - for (String folder : folders) { - if (folder == null) { - continue; - } - File libFolder = new File(folder); - if (!libFolder.exists()) { - continue; - } - List found = findJars(libFolder.getAbsoluteFile()); - jars.addAll(found); - } - // sort the jars by name and then reverse the order so the newer version - // of the library gets loaded in the event that this is an upgrade - Collections.sort(jars); - Collections.reverse(jars); - - if (jars.size() == 0) { - for (String folder : folders) { - File libFolder = new File(folder); - // this is a test of adding a comment - // more really interesting things - System.err.println("Failed to find any JARs in " + libFolder.getPath()); - } - System.exit(-1); - } else { - for (File jar : jars) { - try { - jar.canRead(); - addJarFile(jar); - } catch (Throwable t) { - t.printStackTrace(); - } - } - } - - // Start Server - GitBlitServer.main(args); - } - - public static List findJars(File folder) { - List jars = new ArrayList(); - if (folder.exists()) { - File[] libs = folder.listFiles(new FileFilter() { - @Override - public boolean accept(File file) { - return !file.isDirectory() && file.getName().toLowerCase().endsWith(".jar"); - } - }); - if (libs != null && libs.length > 0) { - jars.addAll(Arrays.asList(libs)); - if (DEBUG) { - for (File jar : jars) { - System.out.println("found " + jar); - } - } - } - } - - return jars; - } - - /** - * Adds a file to the classpath - * - * @param f - * the file to be added - * @throws IOException - */ - public static void addJarFile(File f) throws IOException { - if (f.getName().indexOf("-sources") > -1 || f.getName().indexOf("-javadoc") > -1) { - // don't add source or javadoc jars to runtime classpath - return; - } - URL u = f.toURI().toURL(); - if (DEBUG) { - System.out.println("load=" + u.toExternalForm()); - } - URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader(); - Class sysclass = URLClassLoader.class; - try { - Method method = sysclass.getDeclaredMethod("addURL", PARAMETERS); - method.setAccessible(true); - method.invoke(sysloader, new Object[] { u }); - } catch (Throwable t) { - throw new IOException(MessageFormat.format( - "Error, could not add {0} to system classloader", f.getPath()), t); - } - } -} diff --git a/src/main/java/com/gitblit/MigrateTickets.java b/src/main/java/com/gitblit/MigrateTickets.java index b08228ef..52287c45 100644 --- a/src/main/java/com/gitblit/MigrateTickets.java +++ b/src/main/java/com/gitblit/MigrateTickets.java @@ -116,7 +116,7 @@ public class MigrateTickets { if (parser != null) { parser.printUsage(System.out); System.out - .println("\nExample:\n java -gitblit.jar com.gitblit.MigrateTickets com.gitblit.tickets.RedisTicketService --baseFolder c:\\gitblit-data"); + .println("\nExample:\n java -cp gitblit.jar;\"%CD%/ext/*\" com.gitblit.MigrateTickets com.gitblit.tickets.RedisTicketService --baseFolder c:\\gitblit-data"); } System.exit(0); } diff --git a/src/main/java/com/gitblit/ReindexTickets.java b/src/main/java/com/gitblit/ReindexTickets.java index 858436af..12936db0 100644 --- a/src/main/java/com/gitblit/ReindexTickets.java +++ b/src/main/java/com/gitblit/ReindexTickets.java @@ -111,7 +111,7 @@ public class ReindexTickets { if (parser != null) { parser.printUsage(System.out); System.out - .println("\nExample:\n java -gitblit.jar com.gitblit.ReindexTickets --baseFolder c:\\gitblit-data"); + .println("\nExample:\n java -cp gitblit.jar;\"%CD%/ext/*\" com.gitblit.ReindexTickets --baseFolder c:\\gitblit-data"); } System.exit(0); } diff --git a/src/main/java/com/gitblit/authority/Launcher.java b/src/main/java/com/gitblit/authority/Launcher.java deleted file mode 100644 index bffeb68e..00000000 --- a/src/main/java/com/gitblit/authority/Launcher.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2012 gitblit.com. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.gitblit.authority; - -import java.awt.Color; -import java.awt.EventQueue; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.SplashScreen; -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLClassLoader; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import com.gitblit.Constants; -import com.gitblit.client.Translation; - -/** - * Downloads dependencies and launches Gitblit Authority. - * - * @author James Moger - * - */ -public class Launcher { - - public static final boolean DEBUG = false; - - /** - * Parameters of the method to add an URL to the System classes. - */ - private static final Class[] PARAMETERS = new Class[] { URL.class }; - - - public static void main(String[] args) { - final SplashScreen splash = SplashScreen.getSplashScreen(); - - File libFolder = new File("ext"); - List jars = findJars(libFolder.getAbsoluteFile()); - - // sort the jars by name and then reverse the order so the newer version - // of the library gets loaded in the event that this is an upgrade - Collections.sort(jars); - Collections.reverse(jars); - for (File jar : jars) { - try { - updateSplash(splash, Translation.get("gb.loading") + " " + jar.getName() + "..."); - addJarFile(jar); - } catch (IOException e) { - - } - } - - updateSplash(splash, Translation.get("gb.starting") + " Gitblit Authority..."); - GitblitAuthority.main(args); - } - - private static void updateSplash(final SplashScreen splash, final String string) { - if (splash == null) { - return; - } - try { - EventQueue.invokeAndWait(new Runnable() { - @Override - public void run() { - Graphics2D g = splash.createGraphics(); - if (g != null) { - // Splash is 320x120 - FontMetrics fm = g.getFontMetrics(); - - // paint startup status - g.setColor(Color.darkGray); - int h = fm.getHeight() + fm.getMaxDescent(); - int x = 5; - int y = 115; - int w = 320 - 2 * x; - g.fillRect(x, y - h, w, h); - g.setColor(Color.lightGray); - g.drawRect(x, y - h, w, h); - g.setColor(Color.WHITE); - int xw = fm.stringWidth(string); - g.drawString(string, x + ((w - xw) / 2), y - 5); - - // paint version - String ver = "v" + Constants.getVersion(); - int vw = g.getFontMetrics().stringWidth(ver); - g.drawString(ver, 320 - vw - 5, 34); - g.dispose(); - splash.update(); - } - } - }); - } catch (Throwable t) { - t.printStackTrace(); - } - } - - public static List findJars(File folder) { - List jars = new ArrayList(); - if (folder.exists()) { - File[] libs = folder.listFiles(new FileFilter() { - @Override - public boolean accept(File file) { - return !file.isDirectory() && file.getName().toLowerCase().endsWith(".jar"); - } - }); - if (libs != null && libs.length > 0) { - jars.addAll(Arrays.asList(libs)); - if (DEBUG) { - for (File jar : jars) { - System.out.println("found " + jar); - } - } - } - } - - return jars; - } - - /** - * Adds a file to the classpath - * - * @param f - * the file to be added - * @throws IOException - */ - public static void addJarFile(File f) throws IOException { - if (f.getName().indexOf("-sources") > -1 || f.getName().indexOf("-javadoc") > -1) { - // don't add source or javadoc jars to runtime classpath - return; - } - URL u = f.toURI().toURL(); - if (DEBUG) { - System.out.println("load=" + u.toExternalForm()); - } - URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader(); - Class sysclass = URLClassLoader.class; - try { - Method method = sysclass.getDeclaredMethod("addURL", PARAMETERS); - method.setAccessible(true); - method.invoke(sysloader, new Object[] { u }); - } catch (Throwable t) { - throw new IOException(MessageFormat.format( - "Error, could not add {0} to system classloader", f.getPath()), t); - } - } -} diff --git a/src/site/setup_go.mkd b/src/site/setup_go.mkd index c46e04ba..20b4ba48 100644 --- a/src/site/setup_go.mkd +++ b/src/site/setup_go.mkd @@ -8,14 +8,16 @@ Open `data/gitblit.properties` in your favorite text editor and make sure to rev - *server.storePassword* (do not enter *#* characters) **https** is strongly recommended because passwords are insecurely transmitted form your browser/git client using Basic authentication! - *git.packedGitLimit* (set larger than the size of your largest repository) -3. Execute `authority.cmd` or `java -cp gitblit.jar com.gitblit.authority.Launcher --baseFolder data` from a command-line -**NOTE:** The Authority is a Swing GUI application. Use of this tool is not required as Gitblit GO will startup and create SSL certificates itself, BUT use of this tool allows you to control the identification metadata used in the generated self-signed certificates. Skipping this step will result in certificates with default metadata. +3. Windows: Execute `authority.cmd` or `java -cp "gitblit.jar;%CD%\ext\*" com.gitblit.authority.GitblitAuthority --baseFolder data` from a command-line. + Linux/OSX: Execute `authority.sh` or `java -cp "gitblit.jar:ext/*" com.gitblit.authority.GitblitAuthority --baseFolder data` from a command-line. + **NOTE:** The Authority is a Swing GUI application. Use of this tool is not required as Gitblit GO will startup and create SSL certificates itself, BUT use of this tool allows you to control the identification metadata used in the generated self-signed certificates. Skipping this step will result in certificates with default metadata. 1. fill out the fields in the *new certificate defaults* dialog 2. enter the store password used in *server.storePassword* when prompted. This generates an SSL certificate for **localhost**. 3. you may want to generate an SSL certificate for the hostname or ip address hostnames you are serving from **NOTE:** You can only have **one** SSL certificate specified for a port. - 5. exit the authority app -4. Execute `gitblit.cmd` or `java -jar gitblit.jar --baseFolder data` from a command-line + 4. exit the authority app +4. Windows: Execute `gitblit.cmd` or `java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --baseFolder data` from a command-line + Linux/OSX: Execute `gitblit.sh` or `java -cp gitblit.jar;ext/* com.gitblit.GitBlitServer --baseFolder data` from a command-line 5. Open your browser to or depending on your chosen configuration. 6. Enter the default administrator credentials: **admin / admin** and click the *Login* button **NOTE:** Make sure to change the administrator username and/or password!! @@ -49,7 +51,8 @@ If you want to serve your repositories to another machine over https then you wi **NOTE:** The Gitblit Authority is a GUI tool and will require X11 forwarding on headless UNIX boxes. -1. `authority.cmd` or `java -jar authority.jar --baseFolder data` +1. Windows: `authority.cmd` or `java -cp "gitblit.jar;%CD%\ext\*" com.gitblit.authority.GitblitAuthority --baseFolder data` + Linux/OSX: `authority.sh` or `java -cp "gitblit.jar:ext/*" com.gitblit.authority.GitblitAuthority --baseFolder data` 2. Click the *new ssl certificate* button (red rosette in the toolbar in upper left of window) 3. Enter the hostname or ip address 4. Make sure the checkbox *serve https with this certificate* is checked @@ -88,7 +91,8 @@ Alternatively, Gitblit GO is designed to facilitate use of client certificate au When you generate a new client certificate, a zip file bundle is created which includes a P12 keystore for browsers and a PEM keystore for Git. Both of these are password-protected. Additionally, a personalized README file is generated with setup instructions for popular browsers and Git. The README is generated from `data\certs\instructions.tmpl` and can be modified to suit your needs. -1. `authority.cmd` or `java -jar authority.jar --baseFolder data` +1. Windows: `authority.cmd` or `java -cp "gitblit.jar;%CD%\ext\*" com.gitblit.authority.GitblitAuthority --baseFolder data` + Linux/OSX: `authority.sh` or `java -cp "gitblit.jar:ext/*" com.gitblit.authority.GitblitAuthority --baseFolder data` 2. Select the user for which to generate the certificate 3. Click the *new certificate* button and enter the expiration date of the certificate. You must also enter a password for the generated keystore. This password is *not* the same as the user's login password. This password is used to protect the privatekey and public certificate you will generate for the selected user. You must also enter a password hint for the user. 4. If your mail server settings are properly configured you will have a *send email* checkbox which you can use to immediately send the generated certificate bundle to the user. @@ -139,13 +143,13 @@ Command-Line parameters override the values in `gitblit.properties` at runtime. **Example** - java -jar gitblit.jar --userService c:/myrealm.config --storePassword something --baseFolder c:/data + java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --userService c:/myrealm.config --storePassword something --baseFolder c:/data #### Overriding Gitblit GO's Log4j Configuration You can override Gitblit GO's default Log4j configuration with a command-line parameter to the JVM. - java -Dlog4j.configuration=file:///home/james/log4j.properties -jar gitblit.jar + java -Dlog4j.configuration=file:///home/james/log4j.properties -cp gitblit.jar:"ext/*" com.gitblit.GitBlitServer You can not use override the default log4j configuration *AND* specify the `--dailyLogFile` parameter. For reference, here is [Gitblit's default Log4j configuration](https://github.com/gitblit/gitblit/blob/master/src/log4j.properties). It includes some file appenders that are disabled by default.