Re-organize the Launcher code a bit
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.boot.loader;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.security.CodeSource;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Base class for launchers that can start an application with a fully configured
|
||||
* classpath.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public abstract class AbstractLauncher implements ArchiveFilter {
|
||||
|
||||
private Logger logger = Logger.getLogger(AbstractLauncher.class.getName());
|
||||
|
||||
private LaunchHelper helper = new LaunchHelper();
|
||||
|
||||
/**
|
||||
* Launch the application. This method is the initial entry point that should be
|
||||
* called by a subclass {@code public static void main(String[] args)} method.
|
||||
* @param args the incoming arguments
|
||||
*/
|
||||
public void launch(String[] args) {
|
||||
try {
|
||||
launch(args, getClass().getProtectionDomain());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the application given the protection domain.
|
||||
* @param args the incoming arguments
|
||||
* @param protectionDomain the protection domain
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void launch(String[] args, ProtectionDomain protectionDomain)
|
||||
throws Exception {
|
||||
CodeSource codeSource = protectionDomain.getCodeSource();
|
||||
URI location = (codeSource == null ? null : codeSource.getLocation().toURI());
|
||||
String path = (location == null ? null : location.getPath());
|
||||
if (path == null) {
|
||||
throw new IllegalStateException("Unable to determine code source archive");
|
||||
}
|
||||
File root = new File(path);
|
||||
if (!root.exists()) {
|
||||
throw new IllegalStateException(
|
||||
"Unable to determine code source archive from " + root);
|
||||
}
|
||||
Archive archive = (root.isDirectory() ? new ExplodedArchive(root)
|
||||
: new JarFileArchive(root));
|
||||
launch(args, archive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the application given the archive file
|
||||
* @param args the incoming arguments
|
||||
* @param archive the underlying (zip/war/jar) archive
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void launch(String[] args, Archive archive) throws Exception {
|
||||
List<Archive> lib = new ArrayList<Archive>();
|
||||
lib.addAll(this.helper.findNestedArchives(archive, this));
|
||||
this.logger.fine("Added " + lib.size() + " entries");
|
||||
postProcessLib(archive, lib);
|
||||
String mainClass = this.helper.getMainClass(archive);
|
||||
this.helper.launch(args, mainClass, lib);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to post-process lib entries before they are used. Implementations can add
|
||||
* and remove entries.
|
||||
* @param archive the archive
|
||||
* @param lib the existing lib
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void postProcessLib(Archive archive, List<Archive> lib) throws Exception {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import java.net.URL;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
/**
|
||||
* An archive that can be launched by the {@link Launcher}.
|
||||
* An archive that can be launched by the {@link AbstractLauncher}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see JarFileArchive
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.boot.loader;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface ArchiveFilter {
|
||||
|
||||
public boolean isArchive(Archive.Entry entry);
|
||||
|
||||
}
|
||||
@@ -19,15 +19,19 @@ package org.springframework.boot.loader;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link Launcher} for JAR based archives. This launcher assumes that dependency jars are
|
||||
* included inside a {@code /lib} directory.
|
||||
* {@link AbstractLauncher} for JAR based archives. This launcher assumes that dependency
|
||||
* jars are included inside a {@code /lib} directory.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JarLauncher extends Launcher {
|
||||
public class JarLauncher extends AbstractLauncher {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new JarLauncher().launch(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isNestedArchive(Archive.Entry entry) {
|
||||
public boolean isArchive(Archive.Entry entry) {
|
||||
return !entry.isDirectory() && entry.getName().startsWith("lib/");
|
||||
}
|
||||
|
||||
@@ -36,8 +40,4 @@ public class JarLauncher extends Launcher {
|
||||
lib.add(0, archive);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new JarLauncher().launch(args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,110 +16,71 @@
|
||||
|
||||
package org.springframework.boot.loader;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.security.CodeSource;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Base class for launchers that can start an application with a fully configured
|
||||
* classpath.
|
||||
* Common convenience methods shared by launcher implementations.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public abstract class Launcher {
|
||||
public class LaunchHelper {
|
||||
|
||||
private Logger logger = Logger.getLogger(Launcher.class.getName());
|
||||
private Logger logger = Logger.getLogger(LaunchHelper.class.getName());
|
||||
|
||||
/**
|
||||
* The main runner class. This must be loaded by the created ClassLoader so cannot be
|
||||
* directly referenced.
|
||||
*/
|
||||
private static final String RUNNER_CLASS = Launcher.class.getPackage().getName()
|
||||
+ ".MainMethodRunner";
|
||||
private static final String RUNNER_CLASS = AbstractLauncher.class.getPackage()
|
||||
.getName() + ".MainMethodRunner";
|
||||
|
||||
/**
|
||||
* Launch the application. This method is the initial entry point that should be
|
||||
* called by a subclass {@code public static void main(String[] args)} method.
|
||||
* @param args the incoming arguments
|
||||
*/
|
||||
public void launch(String[] args) {
|
||||
try {
|
||||
launch(args, getClass().getProtectionDomain());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the application given the protection domain.
|
||||
* @param args the incoming arguments
|
||||
* @param protectionDomain the protection domain
|
||||
* @param mainClass the main class
|
||||
* @param lib a collection of archives (zip/jar/war or directory)
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void launch(String[] args, ProtectionDomain protectionDomain)
|
||||
public void launch(String[] args, String mainClass, List<Archive> lib)
|
||||
throws Exception {
|
||||
CodeSource codeSource = protectionDomain.getCodeSource();
|
||||
URI location = (codeSource == null ? null : codeSource.getLocation().toURI());
|
||||
String path = (location == null ? null : location.getPath());
|
||||
if (path == null) {
|
||||
throw new IllegalStateException("Unable to determine code source archive");
|
||||
}
|
||||
File root = new File(path);
|
||||
if (!root.exists()) {
|
||||
throw new IllegalStateException(
|
||||
"Unable to determine code source archive from " + root);
|
||||
}
|
||||
Archive archive = (root.isDirectory() ? new ExplodedArchive(root)
|
||||
: new JarFileArchive(root));
|
||||
launch(args, archive);
|
||||
ClassLoader classLoader = createClassLoader(lib);
|
||||
launch(args, mainClass, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the application given the archive file
|
||||
* @param args the incoming arguments
|
||||
* @param archive the underlying (zip/war/jar) archive
|
||||
* @param archive the archive to search
|
||||
* @return an accumulation of nested archives
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void launch(String[] args, Archive archive) throws Exception {
|
||||
public List<Archive> findNestedArchives(Archive archive, ArchiveFilter filter)
|
||||
throws Exception {
|
||||
List<Archive> lib = new ArrayList<Archive>();
|
||||
for (Archive.Entry entry : archive.getEntries()) {
|
||||
if (isNestedArchive(entry)) {
|
||||
if (filter.isArchive(entry)) {
|
||||
this.logger.fine("Adding: " + entry.getName());
|
||||
lib.add(archive.getNestedArchive(entry));
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.fine("Added " + lib.size() + " entries");
|
||||
postProcessLib(archive, lib);
|
||||
ClassLoader classLoader = createClassLoader(lib);
|
||||
launch(args, archive, classLoader);
|
||||
return lib;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the specified {@link JarEntry} is a nested item that should be added
|
||||
* to the classpath. The method is called once for each entry.
|
||||
* @param jarEntry the jar entry
|
||||
* @return {@code true} if the entry is a nested item (jar or folder)
|
||||
*/
|
||||
protected abstract boolean isNestedArchive(Archive.Entry jarEntry);
|
||||
|
||||
/**
|
||||
* Called to post-process lib entries before they are used. Implementations can add
|
||||
* and remove entries.
|
||||
* Obtain the main class that should be used to launch the application. By default
|
||||
* this method uses a {@code Start-Class} manifest entry.
|
||||
* @param archive the archive
|
||||
* @param lib the existing lib
|
||||
* @return the main class
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void postProcessLib(Archive archive, List<Archive> lib) throws Exception {
|
||||
public String getMainClass(Archive archive) throws Exception {
|
||||
String mainClass = archive.getManifest().getMainAttributes()
|
||||
.getValue("Start-Class");
|
||||
if (mainClass == null) {
|
||||
throw new IllegalStateException("No 'Start-Class' manifest entry specified");
|
||||
}
|
||||
return mainClass;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,26 +97,15 @@ public abstract class Launcher {
|
||||
return createClassLoader(urls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a classloader for the specified URLs
|
||||
* @param urls the URLs
|
||||
* @return the classloader
|
||||
* @throws Exception
|
||||
*/
|
||||
protected ClassLoader createClassLoader(URL[] urls) throws Exception {
|
||||
return new LaunchedURLClassLoader(urls, getClass().getClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the application given the archive file and a fully configured classloader.
|
||||
* @param args the incoming arguments
|
||||
* @param archive the archive
|
||||
* @param mainClass the main class to run
|
||||
* @param classLoader the classloader
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void launch(String[] args, Archive archive, ClassLoader classLoader)
|
||||
protected void launch(String[] args, String mainClass, ClassLoader classLoader)
|
||||
throws Exception {
|
||||
String mainClass = getMainClass(archive);
|
||||
Runnable runner = createMainMethodRunner(mainClass, args, classLoader);
|
||||
Thread runnerThread = new Thread(runner);
|
||||
runnerThread.setContextClassLoader(classLoader);
|
||||
@@ -164,19 +114,13 @@ public abstract class Launcher {
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the main class that should be used to launch the application. By default
|
||||
* this method uses a {@code Start-Class} manifest entry.
|
||||
* @param archive the archive
|
||||
* @return the main class
|
||||
* Create a classloader for the specified URLs
|
||||
* @param urls the URLs
|
||||
* @return the classloader
|
||||
* @throws Exception
|
||||
*/
|
||||
protected String getMainClass(Archive archive) throws Exception {
|
||||
String mainClass = archive.getManifest().getMainAttributes()
|
||||
.getValue("Start-Class");
|
||||
if (mainClass == null) {
|
||||
throw new IllegalStateException("No 'Start-Class' manifest entry specified");
|
||||
}
|
||||
return mainClass;
|
||||
protected ClassLoader createClassLoader(URL[] urls) throws Exception {
|
||||
return new LaunchedURLClassLoader(urls, getClass().getClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -25,7 +25,7 @@ import java.security.PrivilegedExceptionAction;
|
||||
import org.springframework.boot.loader.jar.RandomAccessJarFile;
|
||||
|
||||
/**
|
||||
* {@link ClassLoader} used by the {@link Launcher}.
|
||||
* {@link ClassLoader} used by the {@link AbstractLauncher}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.springframework.boot.loader;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Utility class that used by {@link Launcher}s to call a main method. This class allows
|
||||
* Utility class that used by {@link AbstractLauncher}s to call a main method. This class allows
|
||||
* methods to be executed within a thread configured with a specific context classloader.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
|
||||
@@ -23,7 +23,6 @@ import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -33,8 +32,8 @@ import java.util.logging.Logger;
|
||||
import org.springframework.boot.loader.util.SystemPropertyUtils;
|
||||
|
||||
/**
|
||||
* {@link Launcher} for archives with user-configured classpath and main class via a
|
||||
* properties file. This model is often more flexible and more amenable to creating
|
||||
* {@link AbstractLauncher} for archives with user-configured classpath and main class via
|
||||
* a properties file. This model is often more flexible and more amenable to creating
|
||||
* well-behaved OS-level services than a model based on executable jars.
|
||||
*
|
||||
* <p>
|
||||
@@ -49,19 +48,20 @@ import org.springframework.boot.loader.util.SystemPropertyUtils;
|
||||
* System properties in case the file doesn't exist):
|
||||
*
|
||||
* <ul>
|
||||
* <li><code>loader.path</code>: a comma-separated list of classpath directories
|
||||
* (containing file resources and/or archives in *.jar or *.zip). Defaults to
|
||||
* <code>lib</code> (i.e. a directory in the current working directory)</li>
|
||||
* <li><code>loader.path</code>: a comma-separated list of directories to append to the
|
||||
* classpath (containing file resources and/or nested archives in *.jar or *.zip).
|
||||
* Defaults to <code>lib</code> (i.e. a directory in the current working directory)</li>
|
||||
* <li><code>loader.main</code>: the main method to delegate execution to once the class
|
||||
* loader is set up. No default, but will fall back to looking in a
|
||||
* <code>MANIFEST.MF</code> if there is one.</li>
|
||||
* loader is set up. No default, but will fall back to looking for a
|
||||
* <code>Start-Class</code> in a <code>MANIFEST.MF</code>, if there is one in
|
||||
* <code>${loader.home}/META-INF</code>.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class PropertiesLauncher extends Launcher {
|
||||
public class PropertiesLauncher implements ArchiveFilter {
|
||||
|
||||
private Logger logger = Logger.getLogger(Launcher.class.getName());
|
||||
private Logger logger = Logger.getLogger(AbstractLauncher.class.getName());
|
||||
|
||||
/**
|
||||
* Properties key for main class
|
||||
@@ -85,10 +85,32 @@ public class PropertiesLauncher extends Launcher {
|
||||
|
||||
private Properties properties = new Properties();
|
||||
|
||||
private LaunchHelper helper = new LaunchHelper();
|
||||
|
||||
public static void main(String[] args) {
|
||||
new PropertiesLauncher().launch(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the application. This method is the initial entry point that should be
|
||||
* called by a subclass {@code public static void main(String[] args)} method.
|
||||
* @param args the incoming arguments
|
||||
*/
|
||||
public void launch(String[] args) {
|
||||
try {
|
||||
File home = getHomeDirectory();
|
||||
initialize(home);
|
||||
this.helper.launch(args, getMainClass(home), getLibrary(home, this.paths));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void launch(String[] args, ProtectionDomain protectionDomain)
|
||||
throws Exception {
|
||||
launch(args, new ExplodedArchive(getHomeDirectory()));
|
||||
public boolean isArchive(Archive.Entry entry) {
|
||||
return entry.isDirectory() || isArchive(entry.getName());
|
||||
}
|
||||
|
||||
protected File getHomeDirectory() {
|
||||
@@ -96,28 +118,62 @@ public class PropertiesLauncher extends Launcher {
|
||||
"${user.dir}")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Look in various places for a properties file to extract loader settings. Default to
|
||||
* <code>application.properties</code> either on the current classpath or in the
|
||||
* current working directory.
|
||||
* @see org.springframework.boot.loader.Launcher#launch(java.lang.String[],
|
||||
* org.springframework.boot.loader.Archive)
|
||||
*/
|
||||
@Override
|
||||
protected void launch(String[] args, Archive archive) throws Exception {
|
||||
initialize();
|
||||
super.launch(args, archive);
|
||||
protected String getMainClass(File home) throws Exception {
|
||||
if (System.getProperty(MAIN) != null) {
|
||||
return SystemPropertyUtils.resolvePlaceholders(System.getProperty(MAIN));
|
||||
}
|
||||
if (this.properties.containsKey(MAIN)) {
|
||||
return SystemPropertyUtils.resolvePlaceholders(this.properties
|
||||
.getProperty(MAIN));
|
||||
}
|
||||
return this.helper.getMainClass(new ExplodedArchive(home));
|
||||
}
|
||||
|
||||
protected void initialize() throws Exception {
|
||||
initializeProperties();
|
||||
protected void initialize(File home) throws Exception {
|
||||
initializeProperties(home);
|
||||
initializePaths();
|
||||
}
|
||||
|
||||
private void initializeProperties() throws Exception, IOException {
|
||||
private boolean isArchive(String name) {
|
||||
return name.endsWith(".jar") || name.endsWith(".zip");
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the configured paths and look for nested archives.
|
||||
*
|
||||
* @param home the home directory for this launch
|
||||
* @param paths the directory roots for classpath entries
|
||||
* @return a library of archives that can be used as a classpath
|
||||
* @throws Exception
|
||||
*/
|
||||
private List<Archive> getLibrary(File home, List<String> paths) throws Exception {
|
||||
List<Archive> lib = new ArrayList<Archive>();
|
||||
for (String path : paths) {
|
||||
String root = cleanupPath(stripFileUrlPrefix(path));
|
||||
File file = new File(root);
|
||||
if (!root.startsWith("/")) {
|
||||
file = new File(home, root);
|
||||
}
|
||||
if (file.isDirectory()) {
|
||||
this.logger.info("Adding classpath entries from " + path);
|
||||
Archive archive = new ExplodedArchive(file);
|
||||
lib.addAll(this.helper.findNestedArchives(archive, this));
|
||||
lib.add(0, archive);
|
||||
}
|
||||
else {
|
||||
this.logger.info("No directory found at " + path);
|
||||
}
|
||||
}
|
||||
return lib;
|
||||
}
|
||||
|
||||
private void initializeProperties(File home) throws Exception, IOException {
|
||||
String config = SystemPropertyUtils.resolvePlaceholders(System.getProperty(
|
||||
CONFIG_NAME, "application")) + ".properties";
|
||||
InputStream resource = getClasspathResource(config);
|
||||
if (resource == null) {
|
||||
resource = getResource(new File(home, config).getAbsolutePath());
|
||||
}
|
||||
if (resource == null) {
|
||||
config = SystemPropertyUtils.resolvePlaceholders(System.getProperty(
|
||||
CONFIG_LOCATION, config));
|
||||
@@ -262,43 +318,4 @@ public class PropertiesLauncher extends Launcher {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isNestedArchive(Archive.Entry entry) {
|
||||
String name = entry.getName();
|
||||
for (String path : this.paths) {
|
||||
if (path.length() > 0) {
|
||||
if ((entry.isDirectory() && name.equals(path))
|
||||
|| (!entry.isDirectory() && name.startsWith(path) && isArchive(name))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isArchive(String name) {
|
||||
return name.endsWith(".jar") || name.endsWith(".zip");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postProcessLib(Archive archive, List<Archive> lib) throws Exception {
|
||||
lib.add(0, archive);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMainClass(Archive archive) throws Exception {
|
||||
if (System.getProperty(MAIN) != null) {
|
||||
return SystemPropertyUtils.resolvePlaceholders(System.getProperty(MAIN));
|
||||
}
|
||||
if (this.properties.containsKey(MAIN)) {
|
||||
return SystemPropertyUtils.resolvePlaceholders(this.properties
|
||||
.getProperty(MAIN));
|
||||
}
|
||||
return super.getMainClass(archive);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new PropertiesLauncher().launch(args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,16 +20,20 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link Launcher} for WAR based archives. This launcher for standard WAR archives.
|
||||
* Supports dependencies in {@code WEB-INF/lib} as well as {@code WEB-INF/lib-provided},
|
||||
* classes are loaded from {@code WEB-INF/classes}.
|
||||
* {@link AbstractLauncher} for WAR based archives. This launcher for standard WAR
|
||||
* archives. Supports dependencies in {@code WEB-INF/lib} as well as
|
||||
* {@code WEB-INF/lib-provided}, classes are loaded from {@code WEB-INF/classes}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class WarLauncher extends Launcher {
|
||||
public class WarLauncher extends AbstractLauncher {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new WarLauncher().launch(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isNestedArchive(Archive.Entry entry) {
|
||||
public boolean isArchive(Archive.Entry entry) {
|
||||
if (entry.isDirectory()) {
|
||||
return entry.getName().equals("WEB-INF/classes/");
|
||||
}
|
||||
@@ -64,8 +68,4 @@ public class WarLauncher extends Launcher {
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new WarLauncher().launch(args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,14 +48,14 @@ public class PropertiesLauncherTests {
|
||||
|
||||
@Test
|
||||
public void testUserSpecifiedMain() throws Exception {
|
||||
this.launcher.initialize();
|
||||
this.launcher.initialize(new File("."));
|
||||
assertEquals("demo.Application", this.launcher.getMainClass(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserSpecifiedConfigName() throws Exception {
|
||||
System.setProperty("loader.config.name", "foo");
|
||||
this.launcher.initialize();
|
||||
this.launcher.initialize(new File("."));
|
||||
assertEquals("my.Application", this.launcher.getMainClass(null));
|
||||
assertEquals("[etc/]", ReflectionTestUtils.getField(this.launcher, "paths")
|
||||
.toString());
|
||||
@@ -64,7 +64,7 @@ public class PropertiesLauncherTests {
|
||||
@Test
|
||||
public void testSystemPropertySpecifiedMain() throws Exception {
|
||||
System.setProperty("loader.main", "foo.Bar");
|
||||
this.launcher.initialize();
|
||||
this.launcher.initialize(new File("."));
|
||||
assertEquals("foo.Bar", this.launcher.getMainClass(null));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user