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
<!-- Build jar -->\r
<mx:jar destfile="${go.release.dir}/gitblit.jar" includeresources="true">\r
<mainclass name="com.gitblit.GitBlitServer" />\r
- <launcher paths="ext" />\r
</mx:jar>\r
\r
<!-- Generate the docs for the GO build -->\r
#!/bin/bash
-java -cp gitblit.jar com.gitblit.authority.Launcher --baseFolder data
+java -cp gitblit.jar:ext/* com.gitblit.authority.GitblitAuthority --baseFolder data
#!/bin/bash
-java -jar gitblit.jar --baseFolder data --stop
+java -cp "gitblit.jar:ext/*" com.gitblit.GitBlitServer --baseFolder data --stop
#!/bin/bash
-java -jar gitblit.jar --baseFolder data
+java -cp "gitblit.jar:ext/*" com.gitblit.GitBlitServer --baseFolder data
-@java -cp gitblit.jar com.gitblit.authority.Launcher --baseFolder data %*\r
+@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.authority.GitblitAuthority --baseFolder data %*\r
-@java -jar gitblit.jar --stop --baseFolder data %*\r
+@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --stop --baseFolder data %*\r
-@java -jar gitblit.jar --baseFolder data %*\r
+@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --baseFolder data %*\r
--StdOutput=auto ^\r
--StdError=auto ^\r
--StartPath="%CD%" ^\r
- --StartClass=org.moxie.MxLauncher ^\r
+ --StartClass=com.gitblit.GitBlitServer ^\r
--StartMethod=main ^\r
--StartParams="--storePassword;gitblit;--baseFolder;%CD%\data" ^\r
--StartMode=jvm ^\r
--StopPath="%CD%" ^\r
- --StopClass=org.moxie.MxLauncher ^\r
+ --StopClass=com.gitblit.GitBlitServer ^\r
--StopMethod=main ^\r
--StopParams="--stop;--baseFolder;%CD%\data" ^\r
--StopMode=jvm ^\r
- --Classpath="%CD%\gitblit.jar" ^\r
+ --Classpath="%CD%\gitblit.jar;%CD%\ext\*" ^\r
--Jvm=auto ^\r
--JvmMx=1024\r
\ No newline at end of file
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);
}
+++ /dev/null
-/*
- * 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<File> jars = new ArrayList<File>();
- for (String folder : folders) {
- if (folder == null) {
- continue;
- }
- File libFolder = new File(folder);
- if (!libFolder.exists()) {
- continue;
- }
- List<File> 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<File> findJars(File folder) {
- List<File> jars = new ArrayList<File>();
- 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);
- }
- }
-}
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);
}
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);
}
+++ /dev/null
-/*\r
- * Copyright 2012 gitblit.com.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package com.gitblit.authority;\r
-\r
-import java.awt.Color;\r
-import java.awt.EventQueue;\r
-import java.awt.FontMetrics;\r
-import java.awt.Graphics2D;\r
-import java.awt.SplashScreen;\r
-import java.io.File;\r
-import java.io.FileFilter;\r
-import java.io.IOException;\r
-import java.lang.reflect.Method;\r
-import java.net.URL;\r
-import java.net.URLClassLoader;\r
-import java.text.MessageFormat;\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.Collections;\r
-import java.util.List;\r
-\r
-import com.gitblit.Constants;\r
-import com.gitblit.client.Translation;\r
-\r
-/**\r
- * Downloads dependencies and launches Gitblit Authority.\r
- *\r
- * @author James Moger\r
- *\r
- */\r
-public class Launcher {\r
-\r
- public static final boolean DEBUG = false;\r
-\r
- /**\r
- * Parameters of the method to add an URL to the System classes.\r
- */\r
- private static final Class<?>[] PARAMETERS = new Class[] { URL.class };\r
-\r
-\r
- public static void main(String[] args) {\r
- final SplashScreen splash = SplashScreen.getSplashScreen();\r
-\r
- File libFolder = new File("ext");\r
- List<File> jars = findJars(libFolder.getAbsoluteFile());\r
-\r
- // sort the jars by name and then reverse the order so the newer version\r
- // of the library gets loaded in the event that this is an upgrade\r
- Collections.sort(jars);\r
- Collections.reverse(jars);\r
- for (File jar : jars) {\r
- try {\r
- updateSplash(splash, Translation.get("gb.loading") + " " + jar.getName() + "...");\r
- addJarFile(jar);\r
- } catch (IOException e) {\r
-\r
- }\r
- }\r
-\r
- updateSplash(splash, Translation.get("gb.starting") + " Gitblit Authority...");\r
- GitblitAuthority.main(args);\r
- }\r
-\r
- private static void updateSplash(final SplashScreen splash, final String string) {\r
- if (splash == null) {\r
- return;\r
- }\r
- try {\r
- EventQueue.invokeAndWait(new Runnable() {\r
- @Override\r
- public void run() {\r
- Graphics2D g = splash.createGraphics();\r
- if (g != null) {\r
- // Splash is 320x120\r
- FontMetrics fm = g.getFontMetrics();\r
-\r
- // paint startup status\r
- g.setColor(Color.darkGray);\r
- int h = fm.getHeight() + fm.getMaxDescent();\r
- int x = 5;\r
- int y = 115;\r
- int w = 320 - 2 * x;\r
- g.fillRect(x, y - h, w, h);\r
- g.setColor(Color.lightGray);\r
- g.drawRect(x, y - h, w, h);\r
- g.setColor(Color.WHITE);\r
- int xw = fm.stringWidth(string);\r
- g.drawString(string, x + ((w - xw) / 2), y - 5);\r
-\r
- // paint version\r
- String ver = "v" + Constants.getVersion();\r
- int vw = g.getFontMetrics().stringWidth(ver);\r
- g.drawString(ver, 320 - vw - 5, 34);\r
- g.dispose();\r
- splash.update();\r
- }\r
- }\r
- });\r
- } catch (Throwable t) {\r
- t.printStackTrace();\r
- }\r
- }\r
-\r
- public static List<File> findJars(File folder) {\r
- List<File> jars = new ArrayList<File>();\r
- if (folder.exists()) {\r
- File[] libs = folder.listFiles(new FileFilter() {\r
- @Override\r
- public boolean accept(File file) {\r
- return !file.isDirectory() && file.getName().toLowerCase().endsWith(".jar");\r
- }\r
- });\r
- if (libs != null && libs.length > 0) {\r
- jars.addAll(Arrays.asList(libs));\r
- if (DEBUG) {\r
- for (File jar : jars) {\r
- System.out.println("found " + jar);\r
- }\r
- }\r
- }\r
- }\r
-\r
- return jars;\r
- }\r
-\r
- /**\r
- * Adds a file to the classpath\r
- *\r
- * @param f\r
- * the file to be added\r
- * @throws IOException\r
- */\r
- public static void addJarFile(File f) throws IOException {\r
- if (f.getName().indexOf("-sources") > -1 || f.getName().indexOf("-javadoc") > -1) {\r
- // don't add source or javadoc jars to runtime classpath\r
- return;\r
- }\r
- URL u = f.toURI().toURL();\r
- if (DEBUG) {\r
- System.out.println("load=" + u.toExternalForm());\r
- }\r
- URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();\r
- Class<?> sysclass = URLClassLoader.class;\r
- try {\r
- Method method = sysclass.getDeclaredMethod("addURL", PARAMETERS);\r
- method.setAccessible(true);\r
- method.invoke(sysloader, new Object[] { u });\r
- } catch (Throwable t) {\r
- throw new IOException(MessageFormat.format(\r
- "Error, could not add {0} to system classloader", f.getPath()), t);\r
- }\r
- }\r
-}\r
- *server.storePassword* (do not enter *#* characters)\r
**https** is strongly recommended because passwords are insecurely transmitted form your browser/git client using Basic authentication!\r
- *git.packedGitLimit* (set larger than the size of your largest repository)\r
-3. Execute `authority.cmd` or `java -cp gitblit.jar com.gitblit.authority.Launcher --baseFolder data` from a command-line\r
-**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.\r
+3. Windows: Execute `authority.cmd` or `java -cp "gitblit.jar;%CD%\ext\*" com.gitblit.authority.GitblitAuthority --baseFolder data` from a command-line. \r
+ Linux/OSX: Execute `authority.sh` or `java -cp "gitblit.jar:ext/*" com.gitblit.authority.GitblitAuthority --baseFolder data` from a command-line. \r
+ **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.\r
1. fill out the fields in the *new certificate defaults* dialog\r
2. enter the store password used in *server.storePassword* when prompted. This generates an SSL certificate for **localhost**.\r
3. you may want to generate an SSL certificate for the hostname or ip address hostnames you are serving from\r
**NOTE:** You can only have **one** SSL certificate specified for a port.\r
- 5. exit the authority app\r
-4. Execute `gitblit.cmd` or `java -jar gitblit.jar --baseFolder data` from a command-line\r
+ 4. exit the authority app\r
+4. Windows: Execute `gitblit.cmd` or `java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --baseFolder data` from a command-line\r
+ Linux/OSX: Execute `gitblit.sh` or `java -cp gitblit.jar;ext/* com.gitblit.GitBlitServer --baseFolder data` from a command-line\r
5. Open your browser to <http://localhost:8080> or <https://localhost:8443> depending on your chosen configuration.\r
6. Enter the default administrator credentials: **admin / admin** and click the *Login* button \r
**NOTE:** Make sure to change the administrator username and/or password!! \r
\r
**NOTE:** The Gitblit Authority is a GUI tool and will require X11 forwarding on headless UNIX boxes.\r
\r
-1. `authority.cmd` or `java -jar authority.jar --baseFolder data`\r
+1. Windows: `authority.cmd` or `java -cp "gitblit.jar;%CD%\ext\*" com.gitblit.authority.GitblitAuthority --baseFolder data` \r
+ Linux/OSX: `authority.sh` or `java -cp "gitblit.jar:ext/*" com.gitblit.authority.GitblitAuthority --baseFolder data`\r
2. Click the *new ssl certificate* button (red rosette in the toolbar in upper left of window)\r
3. Enter the hostname or ip address\r
4. Make sure the checkbox *serve https with this certificate* is checked\r
\r
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.\r
\r
-1. `authority.cmd` or `java -jar authority.jar --baseFolder data`\r
+1. Windows: `authority.cmd` or `java -cp "gitblit.jar;%CD%\ext\*" com.gitblit.authority.GitblitAuthority --baseFolder data` \r
+ Linux/OSX: `authority.sh` or `java -cp "gitblit.jar:ext/*" com.gitblit.authority.GitblitAuthority --baseFolder data`\r
2. Select the user for which to generate the certificate\r
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.\r
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.\r
\r
**Example**\r
\r
- java -jar gitblit.jar --userService c:/myrealm.config --storePassword something --baseFolder c:/data\r
+ java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --userService c:/myrealm.config --storePassword something --baseFolder c:/data\r
\r
#### Overriding Gitblit GO's Log4j Configuration\r
\r
You can override Gitblit GO's default Log4j configuration with a command-line parameter to the JVM.\r
\r
- java -Dlog4j.configuration=file:///home/james/log4j.properties -jar gitblit.jar <optional_gitblit_args>\r
+ java -Dlog4j.configuration=file:///home/james/log4j.properties -cp gitblit.jar:"ext/*" com.gitblit.GitBlitServer <optional_gitblit_args>\r
\r
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. \r
\r