Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoakim Erdfelt2014-11-17 20:21:01 +0000
committerJoakim Erdfelt2014-11-17 20:21:01 +0000
commitdbf6f2e6446479ca7ac766f85ee77fc5a579c99f (patch)
treef0fdd5e70a154b0458f307cd6ea7c25092cb0831 /jetty-start
parent61e480c2c1f38e3eb0ba5a876933618ed4188f22 (diff)
downloadorg.eclipse.jetty.project-dbf6f2e6446479ca7ac766f85ee77fc5a579c99f.tar.gz
org.eclipse.jetty.project-dbf6f2e6446479ca7ac766f85ee77fc5a579c99f.tar.xz
org.eclipse.jetty.project-dbf6f2e6446479ca7ac766f85ee77fc5a579c99f.zip
451973 - Ambiguous module init location when mixing --add-to-start & --add-to-startd in the same exec
+ Cleaning up entire base buildout into BaseBuilder class + The management of the configuration is maintained in - StartDirBuilder - StartIniBuilder + The buildout of the directories from the [files] section is now maintained by the BaseBuilder itself. + Using new FileInitializer system as well + Using new Licensing system as well
Diffstat (limited to 'jetty-start')
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/BaseBuilder.java365
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/FS.java5
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/FileInitializer.java4
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/Main.java440
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/Module.java31
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java262
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/README.TXT48
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java13
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/builders/StartDirBuilder.java86
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/builders/StartIniBuilder.java127
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializer.java8
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/UriFileInitializer.java9
-rw-r--r--jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java177
-rw-r--r--jetty-start/src/test/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializerTest.java37
14 files changed, 1025 insertions, 587 deletions
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/BaseBuilder.java b/jetty-start/src/main/java/org/eclipse/jetty/start/BaseBuilder.java
new file mode 100644
index 0000000000..0e7604cc04
--- /dev/null
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/BaseBuilder.java
@@ -0,0 +1,365 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.start;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jetty.start.Modules.AndMatcher;
+import org.eclipse.jetty.start.Modules.EnabledMatcher;
+import org.eclipse.jetty.start.Modules.Matcher;
+import org.eclipse.jetty.start.Modules.SourceSetMatcher;
+import org.eclipse.jetty.start.Modules.UniqueSourceMatcher;
+import org.eclipse.jetty.start.builders.StartDirBuilder;
+import org.eclipse.jetty.start.builders.StartIniBuilder;
+import org.eclipse.jetty.start.fileinits.MavenLocalRepoFileInitializer;
+import org.eclipse.jetty.start.fileinits.TestFileInitializer;
+import org.eclipse.jetty.start.fileinits.UriFileInitializer;
+
+/**
+ * Build a start configuration in <code>${jetty.base}</code>, including
+ * ini files, directories, and libs. Also handles License management.
+ */
+public class BaseBuilder
+{
+ public static interface Config
+ {
+ /**
+ * Add a module to the start environment in <code>${jetty.base}</code>
+ *
+ * @param module
+ * the module to add
+ * @return true if module was added, false if module was not added
+ * (because that module already exists)
+ * @throws IOException
+ */
+ public boolean addModule(Module module) throws IOException;
+ }
+
+ private static final String EXITING_LICENSE_NOT_ACKNOWLEDGED = "Exiting: license not acknowledged!";
+
+ private final BaseHome baseHome;
+ private final List<FileInitializer> fileInitializers;
+ private final StartArgs startArgs;
+
+ public BaseBuilder(BaseHome baseHome, StartArgs args)
+ {
+ this.baseHome = baseHome;
+ this.startArgs = args;
+ this.fileInitializers = new ArrayList<>();
+
+ // Establish FileInitializers
+ if (args.isTestingModeEnabled())
+ {
+ // No downloads performed
+ fileInitializers.add(new TestFileInitializer());
+ }
+ else if (args.isDownload())
+ {
+ // Downloads are allowed to be performed
+ // Setup Maven Local Repo
+ Path localRepoDir = args.getMavenLocalRepoDir();
+ if (localRepoDir != null)
+ {
+ // Use provided local repo directory
+ fileInitializers.add(new MavenLocalRepoFileInitializer(baseHome,localRepoDir));
+ }
+ else
+ {
+ // No no local repo directory (direct downloads)
+ fileInitializers.add(new MavenLocalRepoFileInitializer(baseHome));
+ }
+
+ // Normal URL downloads
+ fileInitializers.add(new UriFileInitializer(baseHome));
+ }
+ }
+
+ private void ackLicenses() throws IOException
+ {
+ if (startArgs.isLicenseCheckRequired())
+ {
+ if (startArgs.isApproveAllLicenses())
+ {
+ StartLog.info("All Licenses Approved via Command Line Option");
+ }
+ else
+ {
+ Licensing licensing = new Licensing();
+ for (Module module : startArgs.getAllModules().getEnabled())
+ {
+ licensing.addModule(module);
+ }
+
+ if (licensing.hasLicenses())
+ {
+ StartLog.debug("Requesting License Acknowledgement");
+ if (!licensing.acknowledgeLicenses())
+ {
+ StartLog.warn(EXITING_LICENSE_NOT_ACKNOWLEDGED);
+ System.exit(1);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Build out the Base directory (if needed)
+ *
+ * @return true if base directory was changed, false if left unchanged.
+ * @throws IOException
+ */
+ public boolean build() throws IOException
+ {
+ Modules modules = startArgs.getAllModules();
+ boolean dirty = false;
+
+ String dirSource = "<add-to-startd>";
+ String iniSource = "<add-to-start-ini>";
+
+ int count = 0;
+ count += modules.enableAll(startArgs.getAddToStartdIni(),dirSource);
+ count += modules.enableAll(startArgs.getAddToStartIni(),iniSource);
+
+ Matcher startDMatcher = new AndMatcher(new EnabledMatcher(),new UniqueSourceMatcher(dirSource));
+ Matcher startIniMatcher = new AndMatcher(new EnabledMatcher(),new UniqueSourceMatcher(iniSource));
+
+ // look for ambiguous declaration in 2 places
+ Matcher ambiguousMatcher = new AndMatcher(new EnabledMatcher(),new SourceSetMatcher(dirSource,iniSource));
+ List<Module> ambiguous = modules.getMatching(ambiguousMatcher);
+
+ if (ambiguous.size() > 0)
+ {
+ StringBuilder err = new StringBuilder();
+ err.append("Unable to add ");
+ err.append(ambiguous.size());
+ err.append(" module");
+ if (ambiguous.size() > 1)
+ {
+ err.append('s');
+ }
+ err.append(" (found declared via both --add-to-start and --add-to-startd): [");
+ for (int i = 0; i < ambiguous.size(); i++)
+ {
+ if (i > 0)
+ {
+ err.append(", ");
+ }
+ err.append(ambiguous.get(i).getName());
+ }
+ err.append(']');
+ throw new RuntimeException(err.toString());
+ }
+
+ StartLog.debug("Adding %s new module(s)",count);
+
+ // Acknowledge Licenses
+ ackLicenses();
+
+ // Collect specific modules to enable
+ List<Module> startDModules = modules.getMatching(startDMatcher);
+ List<Module> startIniModules = modules.getMatching(startIniMatcher);
+
+ List<FileArg> files = new ArrayList<FileArg>();
+
+ if (!startDModules.isEmpty())
+ {
+ StartDirBuilder builder = new StartDirBuilder(this);
+ for (Module mod : startDModules)
+ {
+ dirty |= builder.addModule(mod);
+ for (String file : mod.getFiles())
+ {
+ files.add(new FileArg(mod,file));
+ }
+ }
+ }
+
+ if (!startIniModules.isEmpty())
+ {
+ StartIniBuilder builder = new StartIniBuilder(this);
+ for (Module mod : startIniModules)
+ {
+ dirty |= builder.addModule(mod);
+ for (String file : mod.getFiles())
+ {
+ files.add(new FileArg(mod,file));
+ }
+ }
+ }
+
+ // Process files
+ files.addAll(startArgs.getFiles());
+ dirty |= processFileResources(files);
+
+ return dirty;
+ }
+
+ public BaseHome getBaseHome()
+ {
+ return baseHome;
+ }
+
+ public StartArgs getStartArgs()
+ {
+ return startArgs;
+ }
+
+ /**
+ * Process a specific file resource
+ *
+ * @param arg
+ * the fileArg to work with
+ * @param file
+ * the resolved file reference to work with
+ * @return true if change was made as a result of the file, false if no change made.
+ * @throws IOException
+ * if there was an issue in processing this file
+ */
+ private boolean processFileResource(FileArg arg, Path file) throws IOException
+ {
+ if (startArgs.isDownload() && (arg.uri != null))
+ {
+ URI uri = URI.create(arg.uri);
+
+ // Process via initializers
+ for (FileInitializer finit : fileInitializers)
+ {
+ if (finit.init(uri,file))
+ {
+ // Completed successfully
+ return true;
+ }
+ }
+
+ return false;
+ }
+ else
+ {
+ // Process directly
+ boolean isDir = arg.location.endsWith("/");
+
+ if (FS.exists(file))
+ {
+ // Validate existence
+ if (isDir)
+ {
+ if (!Files.isDirectory(file))
+ {
+ throw new IOException("Invalid: path should be a directory (but isn't): " + file);
+ }
+ if (!FS.canReadDirectory(file))
+ {
+ throw new IOException("Unable to read directory: " + file);
+ }
+ }
+ else
+ {
+ if (!FS.canReadFile(file))
+ {
+ throw new IOException("Unable to read file: " + file);
+ }
+ }
+
+ return false;
+ }
+
+ if (isDir)
+ {
+ // Create directory
+ StartLog.log("MKDIR",baseHome.toShortForm(file));
+ return FS.ensureDirectoryExists(file);
+ }
+ else
+ {
+ // Warn on missing file (this has to be resolved manually by user)
+ String shortRef = baseHome.toShortForm(file);
+ if (startArgs.isTestingModeEnabled())
+ {
+ StartLog.log("TESTING MODE","Skipping required file check on: %s",shortRef);
+ return true;
+ }
+
+ StartLog.warn("Missing Required File: %s",baseHome.toShortForm(file));
+ startArgs.setRun(false);
+ if (arg.uri != null)
+ {
+ StartLog.warn(" Can be downloaded From: %s",arg.uri);
+ StartLog.warn(" Run start.jar --create-files to download");
+ }
+
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Process the {@link FileArg} for startup, assume that all licenses have
+ * been acknowledged at this stage.
+ *
+ * @param files
+ * the list of {@link FileArg}s to process
+ * @return true if base directory modified, false if left untouched
+ */
+ private boolean processFileResources(List<FileArg> files) throws IOException
+ {
+ if ((files == null) || (files.isEmpty()))
+ {
+ return false;
+ }
+
+ boolean dirty = false;
+
+ List<String> failures = new ArrayList<String>();
+
+ for (FileArg arg : files)
+ {
+ Path file = baseHome.getBasePath(arg.location);
+ try
+ {
+ dirty |= processFileResource(arg,file);
+ }
+ catch (Throwable t)
+ {
+ StartLog.warn(t);
+ failures.add(String.format("[%s] %s - %s",t.getClass().getSimpleName(),t.getMessage(),file.toAbsolutePath().toString()));
+ }
+ }
+
+ if (!failures.isEmpty())
+ {
+ StringBuilder err = new StringBuilder();
+ err.append("Failed to process all file resources.");
+ for (String failure : failures)
+ {
+ err.append(System.lineSeparator()).append(" - ").append(failure);
+ }
+ StartLog.warn(err.toString());
+
+ throw new RuntimeException(err.toString());
+ }
+
+ return dirty;
+ }
+}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java b/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java
index 69a7344baf..cc5e181080 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/FS.java
@@ -67,14 +67,15 @@ public class FS
return Files.exists(ret);
}
- public static void ensureDirectoryExists(Path dir) throws IOException
+ public static boolean ensureDirectoryExists(Path dir) throws IOException
{
if (exists(dir))
{
// exists already, nothing to do
- return;
+ return false;
}
Files.createDirectories(dir);
+ return true;
}
public static void ensureDirectoryWritable(Path dir) throws IOException
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/FileInitializer.java b/jetty-start/src/main/java/org/eclipse/jetty/start/FileInitializer.java
index 905915cc4b..24c10d29fe 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/FileInitializer.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/FileInitializer.java
@@ -34,8 +34,8 @@ public interface FileInitializer
* the remote URI of the resource acting as its source
* @param file
* the local file resource to initialize
- * @return true if local file is initialized, false if this
- * {@link FileInitializer} skipped this attempt.
+ * @return true if local file is initialized (resulted in a change on disk), false if this
+ * {@link FileInitializer} did nothing.
* @throws IOException
* if there was an attempt to initialize, but an error occurred.
*/
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
index 33ee63035b..87887ff8b5 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
@@ -21,37 +21,23 @@ package org.eclipse.jetty.start;
import static org.eclipse.jetty.start.UsageException.*;
import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
-import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
-import java.net.URI;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Locale;
-import java.util.Set;
-import java.util.regex.Pattern;
import org.eclipse.jetty.start.config.CommandLineConfigSource;
-import org.eclipse.jetty.start.fileinits.MavenLocalRepoFileInitializer;
-import org.eclipse.jetty.start.fileinits.TestFileInitializer;
-import org.eclipse.jetty.start.fileinits.UriFileInitializer;
/**
* Main start class.
@@ -82,7 +68,6 @@ import org.eclipse.jetty.start.fileinits.UriFileInitializer;
*/
public class Main
{
- private static final String EXITING_LICENSE_NOT_ACKNOWLEDGED = "Exiting: license not acknowledged!";
private static final int EXIT_USAGE = 1;
public static void main(String[] args)
@@ -273,222 +258,6 @@ public class Main
}
/**
- * Build out INI file.
- * <p>
- * This applies equally for either <code>${jetty.base}/start.ini</code> or
- * <code>${jetty.base}/start.d/${name}.ini</code>
- *
- * @param fileInitializers the configured initializers
- * @param args the arguments of what modules are enabled
- * @param name the name of the module to based the build of the ini
- * @param topLevel
- * @param appendStartIni true to append to <code>${jetty.base}/start.ini</code>,
- * false to create a <code>${jetty.base}/start.d/${name}.ini</code> entry instead.
- * @throws IOException
- */
- private void buildIni(List<FileInitializer> fileInitializers, StartArgs args, String name, boolean topLevel, boolean appendStartIni) throws IOException
- {
- // Find the start.d relative to the base directory only.
- Path start_d = baseHome.getBasePath("start.d");
-
- // Is this a module?
- Modules modules = args.getAllModules();
- Module module = modules.get(name);
- if (module == null)
- {
- StartLog.warn("ERROR: No known module for %s",name);
- return;
- }
-
- boolean transitive = module.isEnabled() && (module.getSources().size() == 0);
-
- // Find any named ini file and check it follows the convention
- Path start_ini = baseHome.getBasePath("start.ini");
- String short_start_ini = baseHome.toShortForm(start_ini);
- Path startd_ini = start_d.resolve(name + ".ini");
- String short_startd_ini = baseHome.toShortForm(startd_ini);
- StartIni module_ini = null;
- if (FS.exists(startd_ini))
- {
- module_ini = new StartIni(startd_ini);
- if (module_ini.getLineMatches(Pattern.compile("--module=(.*, *)*" + name)).size() == 0)
- {
- StartLog.warn("ERROR: %s is not enabled in %s!",name,short_startd_ini);
- return;
- }
- }
-
- if (!args.isApproveAllLicenses())
- {
- if (!module.acknowledgeLicense())
- {
- StartLog.warn(EXITING_LICENSE_NOT_ACKNOWLEDGED);
- System.exit(1);
- }
- }
-
- boolean buildIni=false;
- if (module.isEnabled())
- {
- // is it an explicit request to create an ini file?
- if (topLevel && !FS.exists(startd_ini) && !appendStartIni)
- {
- buildIni=true;
- }
- // else is it transitive
- else if (transitive)
- {
- if (module.hasDefaultConfig())
- {
- buildIni = true;
- StartLog.info("%-15s initialised transitively",name);
- }
- }
- // else must be initialized explicitly
- else
- {
- for (String source : module.getSources())
- {
- StartLog.info("%-15s initialised in %s",name,baseHome.toShortForm(source));
- }
- }
- }
- else
- {
- buildIni=true;
- }
-
- String source = "<transitive>";
-
- // If we need an ini
- if (buildIni)
- {
- // File BufferedWriter
- BufferedWriter writer = null;
- PrintWriter out = null;
- try
- {
- if (appendStartIni)
- {
- source = short_start_ini;
- StartLog.info("%-15s initialised in %s (appended)",name,source);
- writer = Files.newBufferedWriter(start_ini,StandardCharsets.UTF_8,StandardOpenOption.CREATE,StandardOpenOption.APPEND);
- out = new PrintWriter(writer);
- }
- else
- {
- // Create the directory if needed
- FS.ensureDirectoryExists(start_d);
- FS.ensureDirectoryWritable(start_d);
- source = short_startd_ini;
- StartLog.info("%-15s initialised in %s (created)",name,source);
- writer = Files.newBufferedWriter(startd_ini,StandardCharsets.UTF_8,StandardOpenOption.CREATE_NEW,StandardOpenOption.WRITE);
- out = new PrintWriter(writer);
- }
-
- if (appendStartIni)
- {
- out.println();
- }
- out.println("# --------------------------------------- ");
- out.println("# Module: " + name);
-
- out.println("--module=" + name);
-
- args.parse("--module=" + name,source);
- args.parseModule(module);
-
- for (String line : module.getDefaultConfig())
- {
- out.println(line);
- }
- }
- finally
- {
- if (out != null)
- {
- out.close();
- }
- }
- }
-
- modules.enable(name,Collections.singletonList(source));
-
- // Also list other places this module is enabled
- for (String src : module.getSources())
- {
- StartLog.debug("also enabled in: %s",src);
- if (!short_start_ini.equals(src))
- {
- StartLog.info("%-15s enabled in %s",name,baseHome.toShortForm(src));
- }
- }
-
- // Do downloads now
- List<FileArg> files = new ArrayList<FileArg>();
- for (String file : module.getFiles())
- {
- files.add(new FileArg(module,file));
- }
- processFileResources(fileInitializers,args,files);
-
- // Process dependencies
- module.expandProperties(args.getProperties());
- modules.registerParentsIfMissing(module);
- modules.buildGraph();
-
- // process new ini modules
- if (topLevel)
- {
- List<Module> depends = new ArrayList<>();
- for (String depend : modules.resolveParentModulesOf(name))
- {
- if (!name.equals(depend))
- {
- Module m = modules.get(depend);
- m.setEnabled(true);
- depends.add(m);
- }
- }
- Collections.sort(depends,Collections.reverseOrder(new Module.DepthComparator()));
-
- Set<String> done = new HashSet<>(0);
- while (true)
- {
- // initialize known dependencies
- boolean complete=true;
- for (Module m : depends)
- {
- if (!done.contains(m.getName()))
- {
- complete=false;
- buildIni(fileInitializers,args,m.getName(),false,appendStartIni);
- done.add(m.getName());
- }
- }
-
- if (complete)
- {
- break;
- }
-
- // look for any new ones resolved via expansion
- depends.clear();
- for (String depend : modules.resolveParentModulesOf(name))
- {
- if (!name.equals(depend))
- {
- Module m = modules.get(depend);
- m.setEnabled(true);
- depends.add(m);
- }
- }
- Collections.sort(depends,Collections.reverseOrder(new Module.DepthComparator()));
- }
- }
- }
-
- /**
* Convenience for <code>processCommandLine(cmdLine.toArray(new String[cmdLine.size()]))</code>
*/
public StartArgs processCommandLine(List<String> cmdLine) throws Exception
@@ -534,7 +303,8 @@ public class Main
modules.buildGraph();
args.setAllModules(modules);
- List<Module> activeModules = modules.resolveEnabled();
+ List<Module> activeModules = modules.getEnabled();
+ modules.assertModulesValid(activeModules);
// ------------------------------------------------------------
// 5) Lib & XML Expansion / Resolution
@@ -552,139 +322,6 @@ public class Main
return args;
}
- /**
- * Process the {@link FileArg} for startup, assume that all licenses have
- * been acknowledged at this stage.
- *
- * @param fileInitializers the file initializer mechanisms.
- * @param args the start arguments
- */
- private void processFileResources(List<FileInitializer> fileInitializers, StartArgs args) throws IOException
- {
- processFileResources(fileInitializers,args,args.getFiles());
- }
-
- /**
- * Process the {@link FileArg} for startup, assume that all licenses have
- * been acknowledged at this stage.
- *
- * @param fileInitializers the file initializer mechanisms.
- * @param args the start arguments
- * @param files the list of {@link FileArg}s to process
- */
- private void processFileResources(List<FileInitializer> fileInitializers, StartArgs args, List<FileArg> files) throws IOException
- {
- List<String> failures = new ArrayList<String>();
-
- for (FileArg arg : files)
- {
- Path file = baseHome.getBasePath(arg.location);
- try
- {
- if (!processFileResource(fileInitializers,args,arg,file))
- {
- failures.add(String.format("[GenericError] %s",file.toAbsolutePath().toString()));
- }
- }
- catch (Throwable t)
- {
- StartLog.warn(t);
- failures.add(String.format("[%s] %s - %s",t.getClass().getSimpleName(),t.getMessage(),file.toAbsolutePath().toString()));
- }
- }
-
- if (failures.isEmpty())
- {
- return;
- }
-
- StartLog.warn("Failed to process all file resources.");
- for (String failure : failures)
- {
- StartLog.warn(" - %s",failure);
- }
- }
-
- private boolean processFileResource(List<FileInitializer> fileInitializers, StartArgs args, FileArg arg, Path file) throws IOException
- {
- if (args.isDownload() && arg.uri != null)
- {
- URI uri = URI.create(arg.uri);
-
- // Process via initializers
- for (FileInitializer finit : fileInitializers)
- {
- if (finit.init(uri,file))
- {
- // Completed successfully
- return true;
- }
- }
-
- return false;
- }
- else
- {
- // Process directly
- boolean isDir = arg.location.endsWith("/");
-
- if (FS.exists(file))
- {
- // Validate existence
- if (isDir)
- {
- if (!Files.isDirectory(file))
- {
- throw new IOException("Invalid: path should be a directory (but isn't): " + file);
- }
- if (!FS.canReadDirectory(file))
- {
- throw new IOException("Unable to read directory: " + file);
- }
- }
- else
- {
- if (!FS.canReadFile(file))
- {
- throw new IOException("Unable to read file: " + file);
- }
- }
-
- return true;
- }
-
- if (isDir)
- {
- // Create directory
- StartLog.log("MKDIR",baseHome.toShortForm(file));
- FS.ensureDirectoryExists(file);
-
- return true;
- }
- else
- {
- // Warn on missing file (this has to be resolved manually by
- // user)
- String shortRef = baseHome.toShortForm(file);
- if (args.isTestingModeEnabled())
- {
- StartLog.log("TESTING MODE","Skipping required file check on: %s",shortRef);
- return true;
- }
-
- StartLog.warn("Missing Required File: %s",baseHome.toShortForm(file));
- args.setRun(false);
- if (arg.uri != null)
- {
- StartLog.warn(" Can be downloaded From: %s",arg.uri);
- StartLog.warn(" Run start.jar --create-files to download");
- }
-
- return false;
- }
- }
- }
-
public void start(StartArgs args) throws IOException, InterruptedException
{
StartLog.debug("StartArgs: %s",args);
@@ -740,74 +377,13 @@ public class Main
doStop(args);
}
- // Establish FileInitializers
- List<FileInitializer> fileInitializers = new ArrayList<FileInitializer>();
- if (args.isTestingModeEnabled())
+ BaseBuilder baseBuilder = new BaseBuilder(baseHome,args);
+ if(baseBuilder.build())
{
- // No downloads performed
- fileInitializers.add(new TestFileInitializer());
- }
- else
- {
- // Downloads are allowed to be performed
-
- // Setup Maven Local Repo
- Path localRepoDir = args.getMavenLocalRepoDir();
- if (localRepoDir != null)
- {
- // Use provided local repo directory
- fileInitializers.add(new MavenLocalRepoFileInitializer(localRepoDir));
- }
- else
- {
- // No no local repo directory (direct downloads)
- fileInitializers.add(new MavenLocalRepoFileInitializer());
- }
-
- // Normal URL downloads
- fileInitializers.add(new UriFileInitializer());
- }
-
- boolean rebuildGraph = false;
-
- // Initialize start.ini
- for (String module : args.getAddToStartIni())
- {
- buildIni(fileInitializers,args,module,true,true);
- rebuildGraph = true;
- }
-
- // Initialize start.d
- for (String module : args.getAddToStartdIni())
- {
- buildIni(fileInitializers,args,module,true,false);
- rebuildGraph = true;
- }
-
- if (rebuildGraph)
- {
- args.getAllModules().clearMissing();
- args.getAllModules().buildGraph();
- }
-
- // If in --create-files, check licenses
- if(args.isDownload())
- {
- if (!args.isApproveAllLicenses())
- {
- StartLog.debug("Requesting License Acknowledgement");
- for (Module module : args.getAllModules().resolveEnabled())
- {
- if (!module.acknowledgeLicense())
- {
- StartLog.warn(EXITING_LICENSE_NOT_ACKNOWLEDGED);
- System.exit(1);
- }
- }
- }
+ // base directory changed.
+ StartLog.info("Base directory was modified");
+ return;
}
-
- processFileResources(fileInitializers, args);
// Informational command line, don't run jetty
if (!args.isRun())
@@ -860,8 +436,6 @@ public class Main
}
}
-
-
private void doStop(StartArgs args)
{
int stopPort = Integer.parseInt(args.getProperties().getString("STOP.PORT"));
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java
index 59189ca807..98e9d120e9 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Module.java
@@ -108,7 +108,7 @@ public class Module
/** License lines */
private List<String> license;
- /** Is this Module enabled via start.jar command line, start.ini, or start.d/*.ini ? */
+ /** Is this Module enabled via start.jar command line, start.ini, or start.d/*.ini */
private boolean enabled = false;
/** List of sources that enabled this module */
private final Set<String> sources = new HashSet<>();
@@ -272,6 +272,29 @@ public class Module
{
return license != null && license.size() > 0;
}
+
+
+ public boolean hasSource(String regex)
+ {
+ for (String source : sources)
+ {
+ if (source.matches(regex))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasUniqueSource(String regex)
+ {
+ if (sources.size() != 1)
+ {
+ return false;
+ }
+
+ return sources.iterator().next().matches(regex);
+ }
public boolean acknowledgeLicense() throws IOException
{
@@ -361,6 +384,11 @@ public class Module
return enabled;
}
+ public boolean isVirtual()
+ {
+ return !logicalName.equals(fileRef);
+ }
+
public void process(BaseHome basehome) throws FileNotFoundException, IOException
{
Pattern section = Pattern.compile("\\s*\\[([^]]*)\\]\\s*");
@@ -477,5 +505,4 @@ public class Module
str.append(']');
return str.toString();
}
-
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java
index 1958cfa155..4d95fc1bc5 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Modules.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -38,6 +39,134 @@ import java.util.regex.Pattern;
*/
public class Modules implements Iterable<Module>
{
+ public static interface Matcher
+ {
+ public boolean match(Module module);
+ }
+
+ public static class AllMatcher implements Matcher
+ {
+ @Override
+ public boolean match(Module module)
+ {
+ return true;
+ }
+ }
+
+ public static class AndMatcher implements Matcher
+ {
+ private final Matcher matchers[];
+
+ public AndMatcher(Matcher ... matchers)
+ {
+ this.matchers = matchers;
+ }
+
+ @Override
+ public boolean match(Module module)
+ {
+ for (Matcher matcher : this.matchers)
+ {
+ if (!matcher.match(module))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ public static class EnabledMatcher implements Matcher
+ {
+ @Override
+ public boolean match(Module module)
+ {
+ return module.isEnabled();
+ }
+ }
+
+ public static class RegexNameMatcher implements Matcher
+ {
+ private final Pattern pat;
+
+ public RegexNameMatcher(String regex)
+ {
+ this.pat = Pattern.compile(regex);
+ }
+
+ @Override
+ public boolean match(Module module)
+ {
+ return pat.matcher(module.getName()).matches();
+ }
+ }
+
+ public static class UniqueSourceMatcher implements Matcher
+ {
+ private final Pattern pat;
+
+ public UniqueSourceMatcher(String sourceRegex)
+ {
+ this.pat = Pattern.compile(sourceRegex);
+ }
+
+ @Override
+ public boolean match(Module module)
+ {
+ if (module.getSources().size() != 1)
+ {
+ // Not unique
+ return false;
+ }
+
+ String sourceId = module.getSources().iterator().next();
+ return pat.matcher(sourceId).matches();
+ }
+ }
+
+ public static class SourceSetMatcher implements Matcher
+ {
+ private final Set<String> nameSet;
+
+ public SourceSetMatcher(String... names)
+ {
+ this.nameSet = new HashSet<>();
+
+ for (String name : names)
+ {
+ this.nameSet.add(name);
+ }
+ }
+
+ @Override
+ public boolean match(Module module)
+ {
+ Set<String> sources = module.getSources();
+ if (sources == null)
+ {
+ // empty sources list
+ return false;
+ }
+
+ if (sources.size() != nameSet.size())
+ {
+ // non-equal sized set
+ return false;
+ }
+
+ for (String source : module.getSources())
+ {
+ if (!this.nameSet.contains(source))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ }
+
private final BaseHome baseHome;
private final StartArgs args;
@@ -194,7 +323,7 @@ public class Modules implements Iterable<Module>
ordered.addAll(modules.values());
Collections.sort(ordered,new Module.NameComparator());
- List<Module> active = resolveEnabled();
+ List<Module> active = getEnabled();
for (Module module : ordered)
{
@@ -275,37 +404,40 @@ public class Modules implements Iterable<Module>
List<String> empty = Collections.emptyList();
enable(name,empty);
}
+
- public void enable(String name, List<String> sources) throws IOException
+ public int enableAll(List<String> names, String source) throws IOException
{
+ if ((names == null) || (names.isEmpty()))
+ {
+ // nothing to do
+ return 0;
+ }
+
+ List<String> sources = Collections.singletonList(source);
+
+ int count = 0;
+ for (String name : names)
+ {
+ count += enable(name,sources);
+ }
+ return count;
+ }
+
+ public int enable(String name, List<String> sources) throws IOException
+ {
+ int count = 0;
+
if (name.contains("*"))
{
// A regex!
- Pattern pat = Pattern.compile(name);
- List<Module> matching = new ArrayList<>();
- do
- {
- matching.clear();
-
- // find matching entries that are not enabled
- for (Map.Entry<String, Module> entry : modules.entrySet())
- {
- if (pat.matcher(entry.getKey()).matches())
- {
- if (!entry.getValue().isEnabled())
- {
- matching.add(entry.getValue());
- }
- }
- }
-
- // enable them
- for (Module module : matching)
- {
- enableModule(module,sources);
- }
+ List<Module> matching = getMatching(new RegexNameMatcher(name));
+
+ // enable them
+ for (Module module : matching)
+ {
+ count += enableModule(module,sources);
}
- while (!matching.isEmpty());
}
else
{
@@ -313,32 +445,36 @@ public class Modules implements Iterable<Module>
if (module == null)
{
System.err.printf("WARNING: Cannot enable requested module [%s]: not a valid module name.%n",name);
- return;
+ return count;
}
- enableModule(module,sources);
+ count += enableModule(module,sources);
}
+ return count;
}
- private void enableModule(Module module, List<String> sources) throws IOException
+ private int enableModule(Module module, List<String> sources) throws IOException
{
- String via = "<transitive>";
-
- // Always add the sources
- if (sources != null)
+ int count = 0;
+ if(sources == null)
{
- module.addSources(sources);
- via = Utils.join(sources, ", ");
+ // We use source for tagging how a node was selected, it should
+ // always be required
+ throw new RuntimeException("sources should never be empty");
}
+ module.addSources(sources);
+ String via = Utils.join(sources, ", ");
+
// If already enabled, nothing else to do
if (module.isEnabled())
{
StartLog.debug("Enabled module: %s (via %s)",module.getName(),via);
- return;
+ return count;
}
StartLog.debug("Enabling module: %s (via %s)",module.getName(),via);
module.setEnabled(true);
+ count++;
args.parseModule(module);
module.expandProperties(args.getProperties());
@@ -370,9 +506,10 @@ public class Modules implements Iterable<Module>
}
if (parent != null)
{
- enableModule(parent,null);
+ count += enableModule(parent,sources);
}
}
+ return count;
}
private void findChildren(Module module, Set<Module> ret)
@@ -560,12 +697,40 @@ public class Modules implements Iterable<Module>
findChildren(module,ret);
return asNameSet(ret);
}
+
+ public List<Module> getEnabled()
+ {
+ return getMatching(new EnabledMatcher());
+ }
+
+ /**
+ * Get the modules from the tree that match the provided matcher.
+ *
+ * @param matcher the matcher to use for matches
+ * @return the list of matching modules in execution order.
+ */
+ public List<Module> getMatching(Matcher matcher)
+ {
+ List<Module> selected = new ArrayList<Module>();
+
+ for (Module module : modules.values())
+ {
+ if (matcher.match(module))
+ {
+ selected.add(module);
+ }
+ }
+
+ Collections.sort(selected,new Module.DepthComparator());
+ return selected;
+ }
/**
- * Resolve the execution order of the enabled modules, and all dependant modules, based on depth first transitive reduction.
+ * Resolve the execution order of the enabled modules, and all dependent modules, based on depth first transitive reduction.
*
- * @return the list of active modules (plus dependant modules), in execution order.
+ * @return the list of active modules (plus dependent modules), in execution order.
*/
+ @Deprecated
public List<Module> resolveEnabled()
{
Map<String, Module> active = new HashMap<String, Module>();
@@ -578,6 +743,16 @@ public class Modules implements Iterable<Module>
}
}
+ assertModulesValid(active.values());
+
+ List<Module> ordered = new ArrayList<>();
+ ordered.addAll(active.values());
+ Collections.sort(ordered,new Module.DepthComparator());
+ return ordered;
+ }
+
+ public void assertModulesValid(Collection<Module> active)
+ {
/*
* check against the missing modules
*
@@ -585,9 +760,9 @@ public class Modules implements Iterable<Module>
*/
for (String missing : missingModules)
{
- for (String activeModule : active.keySet())
+ for (Module module : active)
{
- if (missing.startsWith(activeModule))
+ if (missing.startsWith(module.getName()))
{
StartLog.warn("** Unable to continue, required dependency missing. [%s]",missing);
StartLog.warn("** As configured, Jetty is unable to start due to a missing enabled module dependency.");
@@ -596,11 +771,6 @@ public class Modules implements Iterable<Module>
}
}
}
-
- List<Module> ordered = new ArrayList<>();
- ordered.addAll(active.values());
- Collections.sort(ordered,new Module.DepthComparator());
- return ordered;
}
public Set<String> resolveParentModulesOf(String moduleName)
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/README.TXT b/jetty-start/src/main/java/org/eclipse/jetty/start/README.TXT
deleted file mode 100644
index fc569bc44a..0000000000
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/README.TXT
+++ /dev/null
@@ -1,48 +0,0 @@
-Jetty start
------------
-
-The run directory is either the top-level of a distribution
-or jetty-distribution/target/distribution directory when built from
-source.
-
-Jetty start.jar provides a cross platform replacement for startup scripts.
-It makes use of executable JAR that builds the classpath and then executes
-jetty.
-
-To run with the demo:
-
- java -jar start.jar --enable=demo
- java -jar start.jar
-
-To run with the default modules:
-
- java -jar start.jar
-
-The default options may be specified in the start.ini file, or if
-that is not present, they are defined in the start.config file that
-is within the start.jar.
-
-To run with specific configuration file(s)
-
- java -jar start.jar etc/jetty.xml
-
-To see the available options
-
- java -jar start.jar --help
-
-To run with JSP support (if available)
-
- java -jar start.jar --module=jsp
-
-To run with JMX support
-
- java -jar start.jar --module=jmx
-
-To run with JSP & JMX support
-
- java -jar start.jar --module=jsp,jmx
-
-Note that JSP requires the jasper jars to be within $JETTY/lib/jsp These
-are currently not distributed with the eclipse release and must be
-obtained from a jetty-hightide release from codehaus.
-
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java b/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
index 41ac0e7ad9..25a44818f1 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
@@ -116,6 +116,7 @@ public class StartArgs
/** Download related args */
private boolean download = false;
+ private boolean licenseCheckRequired = false;
private boolean testingMode = false;
private boolean help = false;
@@ -139,10 +140,6 @@ public class StartArgs
FileArg arg = new FileArg(module, uriLocation);
if (!files.contains(arg))
{
- if (arg.uri != null)
- {
- this.download = true;
- }
files.add(arg);
}
}
@@ -656,6 +653,11 @@ public class StartArgs
return exec;
}
+ public boolean isLicenseCheckRequired()
+ {
+ return licenseCheckRequired;
+ }
+
public boolean isNormalMainClass()
{
return SERVER_MAIN.equals(getMainClassname());
@@ -792,6 +794,7 @@ public class StartArgs
{
run = false;
download = true;
+ licenseCheckRequired = true;
return;
}
@@ -861,6 +864,7 @@ public class StartArgs
addToStartdIni.addAll(moduleNames);
run = false;
download = true;
+ licenseCheckRequired = true;
return;
}
@@ -871,6 +875,7 @@ public class StartArgs
addToStartIni.addAll(moduleNames);
run = false;
download = true;
+ licenseCheckRequired = true;
return;
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/builders/StartDirBuilder.java b/jetty-start/src/main/java/org/eclipse/jetty/start/builders/StartDirBuilder.java
new file mode 100644
index 0000000000..bfa4334f2e
--- /dev/null
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/builders/StartDirBuilder.java
@@ -0,0 +1,86 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.start.builders;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+
+import org.eclipse.jetty.start.BaseBuilder;
+import org.eclipse.jetty.start.FS;
+import org.eclipse.jetty.start.Module;
+
+/**
+ * Management of the <code>${jetty.base}/start.d/</code> based configuration.
+ * <p>
+ * Implementation of the <code>--add-to-startd=[name]</code> command line behavior
+ */
+public class StartDirBuilder implements BaseBuilder.Config
+{
+ private final Path startDir;
+
+ public StartDirBuilder(BaseBuilder baseBuilder) throws IOException
+ {
+ this.startDir = baseBuilder.getBaseHome().getBasePath("start.d");
+ FS.ensureDirectoryExists(startDir);
+ }
+
+ @Override
+ public boolean addModule(Module module) throws IOException
+ {
+ if (module.isVirtual())
+ {
+ // skip, no need to reference
+ return false;
+ }
+
+ // Create start.d/{name}.ini
+
+ Path ini = startDir.resolve(module.getName() + ".ini");
+
+ try (BufferedWriter writer = Files.newBufferedWriter(ini,StandardCharsets.UTF_8,StandardOpenOption.CREATE,StandardOpenOption.TRUNCATE_EXISTING))
+ {
+ writeModuleSection(writer,module);
+ }
+
+ return true;
+ }
+
+ protected void writeModuleSection(BufferedWriter writer, Module module)
+ {
+ PrintWriter out = new PrintWriter(writer);
+
+ out.println("# --------------------------------------- ");
+ out.println("# Module: " + module.getName());
+
+ out.println("--module=" + module.getName());
+
+ for (String line : module.getDefaultConfig())
+ {
+ out.println(line);
+ }
+
+ out.println();
+ out.flush();
+ }
+}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/builders/StartIniBuilder.java b/jetty-start/src/main/java/org/eclipse/jetty/start/builders/StartIniBuilder.java
new file mode 100644
index 0000000000..d57957afba
--- /dev/null
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/builders/StartIniBuilder.java
@@ -0,0 +1,127 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.start.builders;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jetty.start.BaseBuilder;
+import org.eclipse.jetty.start.Module;
+import org.eclipse.jetty.start.Props;
+
+/**
+ * Management of the <code>${jetty.base}/start.ini</code> based configuration.
+ * <p>
+ * Implementation of the <code>--add-to-start=[name]</code> command line
+ * behavior
+ */
+public class StartIniBuilder implements BaseBuilder.Config
+{
+ private final Path startIni;
+
+ /* List of modules already present in start.ini */
+ private Set<String> modulesPresent = new HashSet<>();
+
+ /* List of properties (keys only) already present in start.ini */
+ private Set<String> propsPresent = new HashSet<>();
+
+ public StartIniBuilder(BaseBuilder baseBuilder) throws IOException
+ {
+ this.startIni = baseBuilder.getBaseHome().getBasePath("start.ini");
+
+ if (Files.exists(startIni))
+ {
+ parseIni();
+ }
+ }
+
+ private void parseIni() throws IOException
+ {
+ try (BufferedReader reader = Files.newBufferedReader(startIni,StandardCharsets.UTF_8))
+ {
+ String line;
+ while ((line = reader.readLine()) != null)
+ {
+ line = line.trim();
+ if (line.startsWith("--module="))
+ {
+ List<String> moduleNames = Props.getValues(line);
+ this.modulesPresent.addAll(moduleNames);
+ }
+ else if (!line.startsWith("-") && line.contains("-"))
+ {
+ String key = line.substring(0,line.indexOf('='));
+ this.propsPresent.add(key);
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean addModule(Module module) throws IOException
+ {
+ if (modulesPresent.contains(module.getName()))
+ {
+ // skip, already present
+ return false;
+ }
+
+ if (module.isVirtual())
+ {
+ // skip, no need to reference
+ return false;
+ }
+
+ // Append to start.ini
+ try (BufferedWriter writer = Files.newBufferedWriter(startIni,StandardCharsets.UTF_8,StandardOpenOption.APPEND,StandardOpenOption.CREATE))
+ {
+ writeModuleSection(writer,module);
+ }
+
+ return true;
+ }
+
+ protected void writeModuleSection(BufferedWriter writer, Module module)
+ {
+ PrintWriter out = new PrintWriter(writer);
+
+ out.println("# --------------------------------------- ");
+ out.println("# Module: " + module.getName());
+
+ out.println("--module=" + module.getName());
+
+ for (String line : module.getDefaultConfig())
+ {
+ // TODO: validate property keys
+ out.println(line);
+ }
+
+ out.println();
+ out.flush();
+ }
+}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializer.java b/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializer.java
index f48b3777fd..42b3d70c5d 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializer.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializer.java
@@ -23,6 +23,7 @@ import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
+import org.eclipse.jetty.start.BaseHome;
import org.eclipse.jetty.start.FS;
import org.eclipse.jetty.start.FileInitializer;
import org.eclipse.jetty.start.StartLog;
@@ -80,13 +81,14 @@ public class MavenLocalRepoFileInitializer extends UriFileInitializer implements
private Path localRepositoryDir;
- public MavenLocalRepoFileInitializer()
+ public MavenLocalRepoFileInitializer(BaseHome baseHome)
{
- this(null);
+ this(baseHome,null);
}
- public MavenLocalRepoFileInitializer(Path localRepoDir)
+ public MavenLocalRepoFileInitializer(BaseHome baseHome, Path localRepoDir)
{
+ super(baseHome);
this.localRepositoryDir = localRepoDir;
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/UriFileInitializer.java b/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/UriFileInitializer.java
index 785e40ec70..8582d5df17 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/UriFileInitializer.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/UriFileInitializer.java
@@ -27,6 +27,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
+import org.eclipse.jetty.start.BaseHome;
import org.eclipse.jetty.start.FS;
import org.eclipse.jetty.start.FileInitializer;
import org.eclipse.jetty.start.StartLog;
@@ -34,6 +35,12 @@ import org.eclipse.jetty.start.StartLog;
public class UriFileInitializer implements FileInitializer
{
private final static String[] SUPPORTED_SCHEMES = { "http", "https" };
+ private final BaseHome baseHome;
+
+ public UriFileInitializer(BaseHome baseHome)
+ {
+ this.baseHome = baseHome;
+ }
@Override
public boolean init(URI uri, Path file) throws IOException
@@ -57,7 +64,7 @@ public class UriFileInitializer implements FileInitializer
protected void download(URI uri, Path file) throws IOException
{
- StartLog.log("DOWNLOAD","%s to %s",uri,file);
+ StartLog.log("DOWNLOAD","%s to %s",uri,baseHome.toShortForm(file));
FS.ensureDirectoryExists(file.getParent());
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java
index 5806df2376..3d85367b65 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/ModulesTest.java
@@ -18,21 +18,25 @@
package org.eclipse.jetty.start;
-import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
+import org.eclipse.jetty.start.Modules.AndMatcher;
+import org.eclipse.jetty.start.Modules.EnabledMatcher;
+import org.eclipse.jetty.start.Modules.UniqueSourceMatcher;
import org.eclipse.jetty.start.config.CommandLineConfigSource;
import org.eclipse.jetty.start.config.ConfigSources;
import org.eclipse.jetty.start.config.JettyBaseConfigSource;
import org.eclipse.jetty.start.config.JettyHomeConfigSource;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.TestingDir;
-import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
@@ -49,18 +53,18 @@ public class ModulesTest
// Test Env
File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
File baseDir = testdir.getEmptyDir();
- String cmdLine[] = new String[] {"jetty.version=TEST"};
-
+ String cmdLine[] = new String[] { "jetty.version=TEST" };
+
// Configuration
CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
ConfigSources config = new ConfigSources();
config.add(cmdLineSource);
config.add(new JettyHomeConfigSource(homeDir.toPath()));
config.add(new JettyBaseConfigSource(baseDir.toPath()));
-
+
// Initialize
BaseHome basehome = new BaseHome(config);
-
+
StartArgs args = new StartArgs();
args.parse(config);
@@ -112,14 +116,14 @@ public class ModulesTest
expected.add("server");
expected.add("annotations");
expected.add("resources");
- expected.add("logging");
-
+ expected.add("logging");
+
ConfigurationAssert.assertContainsUnordered("All Modules",expected,moduleNames);
}
-
+
/**
* Test loading of only shallow modules, not deep references.
- * In other words. ${search-dir}/modules/*.mod should be the only
+ * In other words. ${search-dir}/modules/*.mod should be the only
* valid references, but ${search-dir}/alt/foo/modules/*.mod should
* not be considered valid.
*/
@@ -128,20 +132,21 @@ public class ModulesTest
{
// Test Env
File homeDir = MavenTestingUtils.getTestResourceDir("jetty home with spaces");
- // intentionally setup top level resources dir (as this would have many deep references)
+ // intentionally setup top level resources dir (as this would have many
+ // deep references)
File baseDir = MavenTestingUtils.getTestResourcesDir();
- String cmdLine[] = new String[] {"jetty.version=TEST"};
-
+ String cmdLine[] = new String[] { "jetty.version=TEST" };
+
// Configuration
CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
ConfigSources config = new ConfigSources();
config.add(cmdLineSource);
config.add(new JettyHomeConfigSource(homeDir.toPath()));
config.add(new JettyBaseConfigSource(baseDir.toPath()));
-
+
// Initialize
BaseHome basehome = new BaseHome(config);
-
+
StartArgs args = new StartArgs();
args.parse(config);
@@ -154,10 +159,10 @@ public class ModulesTest
{
moduleNames.add(mod.getName());
}
-
+
List<String> expected = new ArrayList<>();
expected.add("base");
-
+
ConfigurationAssert.assertContainsUnordered("All Modules",expected,moduleNames);
}
@@ -167,18 +172,18 @@ public class ModulesTest
// Test Env
File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
File baseDir = testdir.getEmptyDir();
- String cmdLine[] = new String[] {"jetty.version=TEST", "java.version=1.7.0_60"};
-
+ String cmdLine[] = new String[] { "jetty.version=TEST", "java.version=1.7.0_60" };
+
// Configuration
CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
ConfigSources config = new ConfigSources();
config.add(cmdLineSource);
config.add(new JettyHomeConfigSource(homeDir.toPath()));
config.add(new JettyBaseConfigSource(baseDir.toPath()));
-
+
// Initialize
BaseHome basehome = new BaseHome(config);
-
+
StartArgs args = new StartArgs();
args.parse(config);
@@ -206,9 +211,9 @@ public class ModulesTest
expected.add("protonego-impl");
expected.add("xml");
expected.add("jsp-impl");
-
+
List<String> resolved = new ArrayList<>();
- for (Module module : modules.resolveEnabled())
+ for (Module module : modules.getEnabled())
{
resolved.add(module.getName());
}
@@ -222,23 +227,23 @@ public class ModulesTest
// Test Env
File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
File baseDir = testdir.getEmptyDir();
- String cmdLine[] = new String[] {"jetty.version=TEST"};
-
+ String cmdLine[] = new String[] { "jetty.version=TEST" };
+
// Configuration
CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
ConfigSources config = new ConfigSources();
config.add(cmdLineSource);
config.add(new JettyHomeConfigSource(homeDir.toPath()));
config.add(new JettyBaseConfigSource(baseDir.toPath()));
-
+
// Initialize
BaseHome basehome = new BaseHome(config);
-
+
StartArgs args = new StartArgs();
args.parse(config);
// Test Modules
- Modules modules = new Modules(basehome, args);
+ Modules modules = new Modules(basehome,args);
modules.registerAll();
// Enable 2 modules
@@ -248,7 +253,7 @@ public class ModulesTest
modules.buildGraph();
// Collect active module list
- List<Module> active = modules.resolveEnabled();
+ List<Module> active = modules.getEnabled();
// Assert names are correct, and in the right order
List<String> expectedNames = new ArrayList<>();
@@ -263,7 +268,7 @@ public class ModulesTest
actualNames.add(actual.getName());
}
- Assert.assertThat("Resolved Names: " + actualNames,actualNames,contains(expectedNames.toArray()));
+ assertThat("Resolved Names: " + actualNames,actualNames,contains(expectedNames.toArray()));
// Assert Library List
List<String> expectedLibs = new ArrayList<>();
@@ -277,7 +282,7 @@ public class ModulesTest
expectedLibs.add("lib/jetty-server-${jetty.version}.jar");
List<String> actualLibs = modules.normalizeLibs(active);
- Assert.assertThat("Resolved Libs: " + actualLibs,actualLibs,contains(expectedLibs.toArray()));
+ assertThat("Resolved Libs: " + actualLibs,actualLibs,contains(expectedLibs.toArray()));
// Assert XML List
List<String> expectedXmls = new ArrayList<>();
@@ -285,7 +290,7 @@ public class ModulesTest
expectedXmls.add("etc/jetty-http.xml");
List<String> actualXmls = modules.normalizeXmls(active);
- Assert.assertThat("Resolved XMLs: " + actualXmls,actualXmls,contains(expectedXmls.toArray()));
+ assertThat("Resolved XMLs: " + actualXmls,actualXmls,contains(expectedXmls.toArray()));
}
@Test
@@ -294,18 +299,18 @@ public class ModulesTest
// Test Env
File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
File baseDir = testdir.getEmptyDir();
- String cmdLine[] = new String[] {"jetty.version=TEST"};
-
+ String cmdLine[] = new String[] { "jetty.version=TEST" };
+
// Configuration
CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
ConfigSources config = new ConfigSources();
config.add(cmdLineSource);
config.add(new JettyHomeConfigSource(homeDir.toPath()));
config.add(new JettyBaseConfigSource(baseDir.toPath()));
-
+
// Initialize
BaseHome basehome = new BaseHome(config);
-
+
StartArgs args = new StartArgs();
args.parse(config);
@@ -321,7 +326,7 @@ public class ModulesTest
// modules.dump();
// Collect active module list
- List<Module> active = modules.resolveEnabled();
+ List<Module> active = modules.getEnabled();
// Assert names are correct, and in the right order
List<String> expectedNames = new ArrayList<>();
@@ -341,7 +346,7 @@ public class ModulesTest
actualNames.add(actual.getName());
}
- Assert.assertThat("Resolved Names: " + actualNames,actualNames,contains(expectedNames.toArray()));
+ assertThat("Resolved Names: " + actualNames,actualNames,contains(expectedNames.toArray()));
// Assert Library List
List<String> expectedLibs = new ArrayList<>();
@@ -362,7 +367,7 @@ public class ModulesTest
expectedLibs.add("lib/websocket/*.jar");
List<String> actualLibs = modules.normalizeLibs(active);
- Assert.assertThat("Resolved Libs: " + actualLibs,actualLibs,contains(expectedLibs.toArray()));
+ assertThat("Resolved Libs: " + actualLibs,actualLibs,contains(expectedLibs.toArray()));
// Assert XML List
List<String> expectedXmls = new ArrayList<>();
@@ -373,6 +378,98 @@ public class ModulesTest
expectedXmls.add("etc/jetty-websockets.xml");
List<String> actualXmls = modules.normalizeXmls(active);
- Assert.assertThat("Resolved XMLs: " + actualXmls,actualXmls,contains(expectedXmls.toArray()));
+ assertThat("Resolved XMLs: " + actualXmls,actualXmls,contains(expectedXmls.toArray()));
+ }
+
+ @Test
+ public void testResolve_Alt() throws IOException
+ {
+ // Test Env
+ File homeDir = MavenTestingUtils.getTestResourceDir("usecases/home");
+ File baseDir = testdir.getEmptyDir();
+ String cmdLine[] = new String[] { "jetty.version=TEST" };
+
+ // Configuration
+ CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
+ ConfigSources config = new ConfigSources();
+ config.add(cmdLineSource);
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
+ config.add(new JettyBaseConfigSource(baseDir.toPath()));
+
+ // Initialize
+ BaseHome basehome = new BaseHome(config);
+
+ StartArgs args = new StartArgs();
+ args.parse(config);
+
+ // Test Modules
+ Modules modules = new Modules(basehome,args);
+ modules.registerAll();
+
+ // Enable test modules
+ modules.enable("http",TEST_SOURCE);
+ modules.enable("annotations",TEST_SOURCE);
+ modules.enable("deploy",TEST_SOURCE);
+ // Enable alternate modules
+ String alt = "<alt>";
+ modules.enable("websocket",Collections.singletonList(alt));
+ modules.enable("jsp",Collections.singletonList(alt));
+
+ modules.buildGraph();
+ // modules.dump();
+
+ // Collect active module list
+ List<Module> active = modules.getEnabled();
+
+ // Assert names are correct, and in the right order
+ List<String> expectedNames = new ArrayList<>();
+ expectedNames.add("base");
+ expectedNames.add("jsp-impl");
+ expectedNames.add("xml");
+ expectedNames.add("server");
+ expectedNames.add("http");
+ expectedNames.add("jndi");
+ expectedNames.add("security");
+ expectedNames.add("servlet");
+ expectedNames.add("jsp");
+ expectedNames.add("plus");
+ expectedNames.add("webapp");
+ expectedNames.add("annotations");
+ expectedNames.add("deploy");
+ expectedNames.add("websocket");
+
+ List<String> actualNames = new ArrayList<>();
+ for (Module actual : active)
+ {
+ actualNames.add(actual.getName());
+ }
+
+ assertThat("Resolved Names: " + actualNames,actualNames,contains(expectedNames.toArray()));
+
+ // Now work with the 'alt' selected
+ List<String> expectedAlts = new ArrayList<>();
+ expectedAlts.add("jsp-impl");
+ expectedAlts.add("jsp");
+ expectedAlts.add("websocket");
+
+ for (String expectedAlt : expectedAlts)
+ {
+ Module altMod = modules.get(expectedAlt);
+ assertThat("Alt.mod[" + expectedAlt + "].enabled",altMod.isEnabled(),is(true));
+ Set<String> sources = altMod.getSources();
+ assertThat("Alt.mod[" + expectedAlt + "].sources: [" + Utils.join(sources,", ") + "]",sources,contains(alt));
+ }
+
+ // Now collect the unique source list
+ List<Module> alts = modules.getMatching(new AndMatcher(new EnabledMatcher(),new UniqueSourceMatcher(alt)));
+
+ // Assert names are correct, and in the right order
+ actualNames = new ArrayList<>();
+ for (Module actual : alts)
+ {
+ actualNames.add(actual.getName());
+ }
+
+ assertThat("Resolved Alt (Sources) Names: " + actualNames,actualNames,contains(expectedAlts.toArray()));
}
}
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializerTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializerTest.java
index 871eb6d6fc..c964796d0e 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializerTest.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializerTest.java
@@ -21,9 +21,17 @@ package org.eclipse.jetty.start.fileinits;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
+import java.io.File;
+import java.io.IOException;
import java.net.URI;
+import org.eclipse.jetty.start.BaseHome;
+import org.eclipse.jetty.start.config.ConfigSources;
+import org.eclipse.jetty.start.config.JettyBaseConfigSource;
+import org.eclipse.jetty.start.config.JettyHomeConfigSource;
import org.eclipse.jetty.start.fileinits.MavenLocalRepoFileInitializer.Coordinates;
+import org.eclipse.jetty.toolchain.test.TestingDir;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -32,11 +40,28 @@ public class MavenLocalRepoFileInitializerTest
{
@Rule
public ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public TestingDir testdir = new TestingDir();
+
+ private BaseHome baseHome;
+
+ @Before
+ public void setupBaseHome() throws IOException
+ {
+ File homeDir = testdir.getEmptyDir();
+
+ ConfigSources config = new ConfigSources();
+ config.add(new JettyHomeConfigSource(homeDir.toPath()));
+ config.add(new JettyBaseConfigSource(homeDir.toPath()));
+
+ this.baseHome = new BaseHome(config);
+ }
@Test
public void testGetCoordinate_NotMaven()
{
- MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer();
+ MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer(baseHome);
String ref = "http://www.eclipse.org/jetty";
Coordinates coords = repo.getCoordinates(URI.create(ref));
assertThat("Coords",coords,nullValue());
@@ -45,7 +70,7 @@ public class MavenLocalRepoFileInitializerTest
@Test
public void testGetCoordinate_InvalidMaven()
{
- MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer();
+ MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer(baseHome);
String ref = "maven://www.eclipse.org/jetty";
expectedException.expect(RuntimeException.class);
expectedException.expectMessage(containsString("Not a valid maven:// uri"));
@@ -55,7 +80,7 @@ public class MavenLocalRepoFileInitializerTest
@Test
public void testGetCoordinate_Normal()
{
- MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer();
+ MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer(baseHome);
String ref = "maven://org.eclipse.jetty/jetty-start/9.3.x";
Coordinates coords = repo.getCoordinates(URI.create(ref));
assertThat("Coordinates",coords,notNullValue());
@@ -73,7 +98,7 @@ public class MavenLocalRepoFileInitializerTest
@Test
public void testGetCoordinate_Zip()
{
- MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer();
+ MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer(baseHome);
String ref = "maven://org.eclipse.jetty/jetty-distribution/9.3.x/zip";
Coordinates coords = repo.getCoordinates(URI.create(ref));
assertThat("Coordinates",coords,notNullValue());
@@ -91,7 +116,7 @@ public class MavenLocalRepoFileInitializerTest
@Test
public void testGetCoordinate_TestJar()
{
- MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer();
+ MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer(baseHome);
String ref = "maven://org.eclipse.jetty/jetty-http/9.3.x/jar/tests";
Coordinates coords = repo.getCoordinates(URI.create(ref));
assertThat("Coordinates",coords,notNullValue());
@@ -109,7 +134,7 @@ public class MavenLocalRepoFileInitializerTest
@Test
public void testGetCoordinate_Test_UnspecifiedType()
{
- MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer();
+ MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer(baseHome);
String ref = "maven://org.eclipse.jetty/jetty-http/9.3.x//tests";
Coordinates coords = repo.getCoordinates(URI.create(ref));
assertThat("Coordinates",coords,notNullValue());

Back to the top