diff options
author | Joakim Erdfelt | 2014-11-13 21:23:26 +0000 |
---|---|---|
committer | Joakim Erdfelt | 2014-11-13 21:23:26 +0000 |
commit | 15bf5b02f8946c02901ba16a6dd9f02221013c69 (patch) | |
tree | a863801789bae8fa2c037e527a2f62bb79626178 /jetty-start | |
parent | a308c087edae79917b40dbc8e1b5f0c0b3b15b12 (diff) | |
download | org.eclipse.jetty.project-15bf5b02f8946c02901ba16a6dd9f02221013c69.tar.gz org.eclipse.jetty.project-15bf5b02f8946c02901ba16a6dd9f02221013c69.tar.xz org.eclipse.jetty.project-15bf5b02f8946c02901ba16a6dd9f02221013c69.zip |
Updating Main.initFiles() to be extensible
Diffstat (limited to 'jetty-start')
10 files changed, 783 insertions, 139 deletions
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 new file mode 100644 index 0000000000..905915cc4b --- /dev/null +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/FileInitializer.java @@ -0,0 +1,43 @@ +// +// ======================================================================== +// 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.Path; + +/** + * Interface for initializing a file resource. + */ +public interface FileInitializer +{ + /** + * Initialize a file resource + * + * @param uri + * 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. + * @throws IOException + * if there was an attempt to initialize, but an error occurred. + */ + public boolean init(URI uri, Path file) throws IOException; +} 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 eca1f7929f..c0ffd6cb34 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 @@ -35,7 +35,7 @@ import java.net.ConnectException; import java.net.InetAddress; import java.net.Socket; import java.net.SocketTimeoutException; -import java.net.URL; +import java.net.URI; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -50,6 +50,9 @@ 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. @@ -172,76 +175,6 @@ public class Main }).start(); } - private void initFile(StartArgs args, FileArg farg) - { - try - { - Path file = baseHome.getBasePath(farg.location); - - StartLog.debug("[init-file] %s module specified file %s",file.toAbsolutePath(),(FS.exists(file)?"[Exists!]":"")); - if (FS.exists(file)) - { - // file already initialized / downloaded, skip it - return; - } - - if (farg.uri!=null) - { - URL url = new URL(farg.uri); - - StartLog.log("DOWNLOAD", "%s to %s", url, farg.location); - - FS.ensureDirectoryExists(file.getParent()); - - if (args.isTestingModeEnabled()) - { - StartLog.log("TESTING MODE", "Skipping download of " + url); - return; - } - - byte[] buf = new byte[8192]; - try (InputStream in = url.openStream(); - OutputStream out = Files.newOutputStream(file,StandardOpenOption.CREATE_NEW,StandardOpenOption.WRITE)) - { - while (true) - { - int len = in.read(buf); - - if (len > 0) - { - out.write(buf,0,len); - } - if (len < 0) - { - break; - } - } - } - } - else if (farg.location.endsWith("/")) - { - StartLog.log("MKDIR",baseHome.toShortForm(file)); - FS.ensureDirectoryExists(file); - } - else - { - String shortRef = baseHome.toShortForm(file); - if (args.isTestingModeEnabled()) - { - StartLog.log("TESTING MODE","Skipping required file check on: %s",shortRef); - return; - } - StartLog.warn("MISSING: Required file %s",shortRef); - } - } - catch (Exception e) - { - StartLog.warn("ERROR: processing %s%n%s",farg,e); - StartLog.warn(e); - usageExit(EXIT_USAGE); - } - } - private void dumpClasspathWithVersions(Classpath classpath) { StartLog.endStartLog(); @@ -366,6 +299,7 @@ public class Main * 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 @@ -373,7 +307,7 @@ public class Main * false to create a <code>${jetty.base}/start.d/${name}.ini</code> entry instead. * @throws IOException */ - private void buildIni(StartArgs args, String name, boolean topLevel, boolean appendStartIni) 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"); @@ -512,10 +446,12 @@ public class Main } // Do downloads now + List<FileArg> files = new ArrayList<FileArg>(); for (String file : module.getFiles()) { - initFile(args, new FileArg(module,file)); + files.add(new FileArg(module,file)); } + processFileResources(fileInitializers,args,files); // Process dependencies module.expandProperties(args.getProperties()); @@ -547,7 +483,7 @@ public class Main if (!done.contains(m.getName())) { complete=false; - buildIni(args,m.getName(),false,appendStartIni); + buildIni(fileInitializers,args,m.getName(),false,appendStartIni); done.add(m.getName()); } } @@ -636,7 +572,140 @@ 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); @@ -692,19 +761,33 @@ public class Main doStop(args); } + // Establish FileInitializers + List<FileInitializer> fileInitializers = new ArrayList<FileInitializer>(); + if (args.isTestingModeEnabled()) + { + // No downloads performed + fileInitializers.add(new TestFileInitializer()); + } + else + { + // Downloads performed + fileInitializers.add(new MavenLocalRepoFileInitializer()); + fileInitializers.add(new UriFileInitializer()); + } + boolean rebuildGraph = false; // Initialize start.ini for (String module : args.getAddToStartIni()) { - buildIni(args,module,true,true); + buildIni(fileInitializers,args,module,true,true); rebuildGraph = true; } // Initialize start.d for (String module : args.getAddToStartdIni()) { - buildIni(args,module,true,false); + buildIni(fileInitializers,args,module,true,false); rebuildGraph = true; } @@ -719,6 +802,7 @@ public class Main { if (!args.isApproveAllLicenses()) { + StartLog.debug("Requesting License Acknowledgement"); for (Module module : args.getAllModules().resolveEnabled()) { if (!module.acknowledgeLicense()) @@ -730,46 +814,7 @@ public class Main } } - // Check ini files for download possibilities - for (FileArg arg : args.getFiles()) - { - Path file = baseHome.getBasePath(arg.location); - if (!FS.exists(file) && args.isDownload()) - { - initFile(args, arg); - } - - if (!FS.exists(file)) - { - boolean isDir = arg.location.endsWith("/"); - if (isDir) - { - StartLog.log("MKDIR", baseHome.toShortForm(file)); - FS.ensureDirectoryExists(file); - /* Startup should not fail to run on missing directories. - * See Bug #427204 - */ - // args.setRun(false); - } - else - { - String shortRef = baseHome.toShortForm(file); - if (args.isTestingModeEnabled()) - { - StartLog.log("TESTING MODE","Skipping required file check on: %s",shortRef); - return; - } - - 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"); - } - } - } - } + processFileResources(fileInitializers, args); // Informational command line, don't run jetty if (!args.isRun()) @@ -822,6 +867,8 @@ 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/StartArgs.java b/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java index 8f553f8682..2077f2d677 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 @@ -112,7 +112,11 @@ public class StartArgs private Modules allModules; /** Should the server be run? */ private boolean run = true; + + /** Download related args */ private boolean download = false; + private boolean testingMode = false; + private boolean help = false; private boolean stopCommand = false; private boolean listModules = false; @@ -123,7 +127,6 @@ public class StartArgs private boolean exec = false; private boolean approveAllLicenses = false; - private boolean testingMode = false; public StartArgs() { @@ -135,6 +138,10 @@ public class StartArgs FileArg arg = new FileArg(module, uriLocation); if (!files.contains(arg)) { + if (arg.uri != null) + { + this.download = true; + } files.add(arg); } } diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Utils.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Utils.java new file mode 100644 index 0000000000..3e7ffa80b7 --- /dev/null +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Utils.java @@ -0,0 +1,72 @@ +// +// ======================================================================== +// 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; + +public final class Utils +{ + /** + * Is String null, empty, or consisting of only whitespace. + * + * @param value + * the value to test + * @return true if null, empty, or consisting of only whitespace + */ + public static boolean isBlank(String value) + { + if (value == null) + { + return true; + } + int len = value.length(); + for (int i = 0; i < len; i++) + { + int c = value.codePointAt(i); + if (!Character.isWhitespace(c)) + { + return false; + } + } + return true; + } + + /** + * Is String valid and has something other than whitespace + * + * @param value + * the value to test + * @return true if String has something other than whitespace + */ + public static boolean isNotBlank(String value) + { + if (value == null) + { + return false; + } + int len = value.length(); + for (int i = 0; i < len; i++) + { + int c = value.codePointAt(i); + if (!Character.isWhitespace(c)) + { + return true; + } + } + return false; + } +} diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/config/CommandLineConfigSource.java b/jetty-start/src/main/java/org/eclipse/jetty/start/config/CommandLineConfigSource.java index 934158f1ac..af3c54fa9d 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/config/CommandLineConfigSource.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/config/CommandLineConfigSource.java @@ -32,6 +32,7 @@ import org.eclipse.jetty.start.Props; import org.eclipse.jetty.start.Props.Prop; import org.eclipse.jetty.start.RawArgs; import org.eclipse.jetty.start.UsageException; +import org.eclipse.jetty.start.Utils; /** * Configuration Source representing the Command Line arguments. @@ -69,14 +70,14 @@ public class CommandLineConfigSource implements ConfigSource { // If a jetty property is defined, use it Prop prop = this.props.getProp(BaseHome.JETTY_BASE,false); - if (prop != null && !isEmpty(prop.value)) + if (prop != null && !Utils.isBlank(prop.value)) { return FS.toPath(prop.value); } // If a system property is defined, use it String val = System.getProperty(BaseHome.JETTY_BASE); - if (!isEmpty(val)) + if (!Utils.isBlank(val)) { return FS.toPath(val); } @@ -91,14 +92,14 @@ public class CommandLineConfigSource implements ConfigSource { // If a jetty property is defined, use it Prop prop = this.props.getProp(BaseHome.JETTY_HOME,false); - if (prop != null && !isEmpty(prop.value)) + if (prop != null && !Utils.isBlank(prop.value)) { return FS.toPath(prop.value); } // If a system property is defined, use it String val = System.getProperty(BaseHome.JETTY_HOME); - if (!isEmpty(val)) + if (!Utils.isBlank(val)) { return FS.toPath(val); } @@ -130,24 +131,6 @@ public class CommandLineConfigSource implements ConfigSource return home; } - private boolean isEmpty(String value) - { - if (value == null) - { - return true; - } - int len = value.length(); - for (int i = 0; i < len; i++) - { - int c = value.codePointAt(i); - if (!Character.isWhitespace(c)) - { - return false; - } - } - return true; - } - @Override public boolean equals(Object obj) { 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 new file mode 100644 index 0000000000..6aca80597e --- /dev/null +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializer.java @@ -0,0 +1,191 @@ +// +// ======================================================================== +// 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.fileinits; + +import java.io.IOException; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.eclipse.jetty.start.FS; +import org.eclipse.jetty.start.FileInitializer; +import org.eclipse.jetty.start.StartLog; +import org.eclipse.jetty.start.Utils; + +/** + * Attempt to download a <code>maven://</code> URI, by first attempting to find + * the resource in the maven repository system (starting with local, then + * central) + * <p> + * Valid URI Formats: + * <dl> + * <dt><code>maven://<groupId>/<artifactId>/<version></code></dt> + * <dd>minimum requirement (type defaults to <code>jar</code>, with no + * classifier)</dd> + * <dt><code>maven://<groupId>/<artifactId>/<version>/<type></code></dt> + * <dd>optional type requirement</dd> + * <dt> + * <code>maven://<groupId>/<artifactId>/<version>/<type>/<classifier></code> + * </dt> + * <dd>optional type and classifier requirement</dd> + * </dl> + */ +public class MavenLocalRepoFileInitializer extends UriFileInitializer implements FileInitializer +{ + public static class Coordinates + { + public String groupId; + public String artifactId; + public String version; + public String type; + public String classifier; + + public String toPath() + { + StringBuilder pathlike = new StringBuilder(); + pathlike.append(groupId.replace('.','/')); + pathlike.append('/').append(artifactId); + pathlike.append('/').append(version); + pathlike.append('/').append(artifactId); + pathlike.append('-').append(version); + if (classifier != null) + { + pathlike.append('-').append(classifier); + } + pathlike.append('.').append(type); + return pathlike.toString(); + } + + public URI toCentralURI() + { + return URI.create("http://central.maven.org/maven2/" + toPath()); + } + } + + private Path localRepositoryDir; + + public MavenLocalRepoFileInitializer() + { + this(null); + } + + public MavenLocalRepoFileInitializer(Path localRepoDir) + { + this.localRepositoryDir = localRepoDir; + } + + @Override + public boolean init(URI uri, Path file) throws IOException + { + Coordinates coords = getCoordinates(uri); + if (coords == null) + { + // Skip, not a maven:// URI + return false; + } + + if (isFilePresent(file)) + { + // All done + return true; + } + + // If using local repository + if (this.localRepositoryDir != null) + { + // Grab copy from local repository (download if needed to local + // repository) + Path localRepoFile = getLocalRepoFile(coords); + Files.copy(localRepoFile,file); + } + else + { + // normal non-local repo version + download(coords.toCentralURI(),file); + } + return true; + } + + private Path getLocalRepoFile(Coordinates coords) throws IOException + { + Path localFile = localRepositoryDir.resolve(coords.toPath()); + if (FS.canReadFile(localFile)) + { + return localFile; + } + + // Download, if needed + download(coords.toCentralURI(),localFile); + return localFile; + } + + public Coordinates getCoordinates(URI uri) + { + if (!"maven".equalsIgnoreCase(uri.getScheme())) + { + return null; + } + + String ssp = uri.getSchemeSpecificPart(); + + if (ssp.startsWith("//")) + { + ssp = ssp.substring(2); + } + + String parts[] = ssp.split("/"); + + if (StartLog.isDebugEnabled()) + { + StartLog.debug("ssp = %s",ssp); + StartLog.debug("parts = %d",parts.length); + for (int i = 0; i < parts.length; i++) + { + StartLog.debug(" part[%2d]: [%s]",i,parts[i]); + } + } + + if (parts.length < 3) + { + throw new RuntimeException("Not a valid maven:// uri - " + uri); + } + + Coordinates coords = new Coordinates(); + coords.groupId = parts[0]; + coords.artifactId = parts[1]; + coords.version = parts[2]; + coords.type = "jar"; + coords.classifier = null; + + if (parts.length >= 4) + { + if (Utils.isNotBlank(parts[3])) + { + coords.type = parts[3]; + } + + if ((parts.length == 5) && (Utils.isNotBlank(parts[4]))) + { + coords.classifier = parts[4]; + } + } + + return coords; + } +} diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/TestFileInitializer.java b/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/TestFileInitializer.java new file mode 100644 index 0000000000..dc9fd474be --- /dev/null +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/TestFileInitializer.java @@ -0,0 +1,44 @@ +// +// ======================================================================== +// 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.fileinits; + +import java.io.IOException; +import java.net.URI; +import java.nio.file.Path; + +import org.eclipse.jetty.start.FS; +import org.eclipse.jetty.start.FileInitializer; +import org.eclipse.jetty.start.StartLog; + +/** + * In a start testing scenario, it is often not important to actually download + * or initialize a file, this implementation is merely a no-op for the + * {@link FileInitializer} + */ +public class TestFileInitializer implements FileInitializer +{ + @Override + public boolean init(URI uri, Path file) throws IOException + { + FS.ensureDirectoryExists(file.getParent()); + + StartLog.log("TESTING MODE","Skipping download of " + uri); + return true; + } +} 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 new file mode 100644 index 0000000000..785e40ec70 --- /dev/null +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/fileinits/UriFileInitializer.java @@ -0,0 +1,130 @@ +// +// ======================================================================== +// 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.fileinits; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; + +import org.eclipse.jetty.start.FS; +import org.eclipse.jetty.start.FileInitializer; +import org.eclipse.jetty.start.StartLog; + +public class UriFileInitializer implements FileInitializer +{ + private final static String[] SUPPORTED_SCHEMES = { "http", "https" }; + + @Override + public boolean init(URI uri, Path file) throws IOException + { + if (!isSupportedScheme(uri)) + { + // Not a supported scheme. + return false; + } + + if(isFilePresent(file)) + { + // All done + return true; + } + + download(uri,file); + + return true; + } + + protected void download(URI uri, Path file) throws IOException + { + StartLog.log("DOWNLOAD","%s to %s",uri,file); + + FS.ensureDirectoryExists(file.getParent()); + + HttpURLConnection http = (HttpURLConnection)uri.toURL().openConnection(); + http.setInstanceFollowRedirects(true); + http.setAllowUserInteraction(false); + + int status = http.getResponseCode(); + + if(status != HttpURLConnection.HTTP_OK) + { + throw new IOException("URL GET Failure [" + status + "/" + http.getResponseMessage() + "] on " + uri); + } + + byte[] buf = new byte[8192]; + try (InputStream in = http.getInputStream(); OutputStream out = Files.newOutputStream(file,StandardOpenOption.CREATE_NEW,StandardOpenOption.WRITE)) + { + while (true) + { + int len = in.read(buf); + + if (len > 0) + { + out.write(buf,0,len); + } + if (len < 0) + { + break; + } + } + } + } + + protected boolean isFilePresent(Path file) throws IOException + { + if (Files.exists(file)) + { + if (Files.isDirectory(file)) + { + throw new IOException("Directory in the way: " + file.toAbsolutePath()); + } + + if (Files.isReadable(file)) + { + throw new IOException("File not readable: " + file.toAbsolutePath()); + } + + return true; + } + + return false; + } + + private boolean isSupportedScheme(URI uri) + { + String scheme = uri.getScheme(); + if (scheme == null) + { + return false; + } + for (String supported : SUPPORTED_SCHEMES) + { + if (supported.equalsIgnoreCase(scheme)) + { + return true; + } + } + return false; + } +} diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/LicenseTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/LicenseTest.java index c6d040fa64..a7a7ebdd9f 100644 --- a/jetty-start/src/test/java/org/eclipse/jetty/start/LicenseTest.java +++ b/jetty-start/src/test/java/org/eclipse/jetty/start/LicenseTest.java @@ -123,6 +123,7 @@ public class LicenseTest List<String> cmds = getBaseCommandLine(basePath); cmds.add("-Dorg.eclipse.jetty.start.ack.license.protonego-impl=true"); + cmds.add("--dry-run"); StringReader startIni = new StringReader("--module=spdy\n"); try (FileWriter writer = new FileWriter(new File(basePath,"start.ini"))) 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 new file mode 100644 index 0000000000..871eb6d6fc --- /dev/null +++ b/jetty-start/src/test/java/org/eclipse/jetty/start/fileinits/MavenLocalRepoFileInitializerTest.java @@ -0,0 +1,126 @@ +// +// ======================================================================== +// 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.fileinits; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.net.URI; + +import org.eclipse.jetty.start.fileinits.MavenLocalRepoFileInitializer.Coordinates; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class MavenLocalRepoFileInitializerTest +{ + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void testGetCoordinate_NotMaven() + { + MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer(); + String ref = "http://www.eclipse.org/jetty"; + Coordinates coords = repo.getCoordinates(URI.create(ref)); + assertThat("Coords",coords,nullValue()); + } + + @Test + public void testGetCoordinate_InvalidMaven() + { + MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer(); + String ref = "maven://www.eclipse.org/jetty"; + expectedException.expect(RuntimeException.class); + expectedException.expectMessage(containsString("Not a valid maven:// uri")); + repo.getCoordinates(URI.create(ref)); + } + + @Test + public void testGetCoordinate_Normal() + { + MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer(); + String ref = "maven://org.eclipse.jetty/jetty-start/9.3.x"; + Coordinates coords = repo.getCoordinates(URI.create(ref)); + assertThat("Coordinates",coords,notNullValue()); + + assertThat("coords.groupId",coords.groupId,is("org.eclipse.jetty")); + assertThat("coords.artifactId",coords.artifactId,is("jetty-start")); + assertThat("coords.version",coords.version,is("9.3.x")); + assertThat("coords.type",coords.type,is("jar")); + assertThat("coords.classifier",coords.classifier,nullValue()); + + assertThat("coords.toCentralURI", coords.toCentralURI().toASCIIString(), + is("http://central.maven.org/maven2/org/eclipse/jetty/jetty-start/9.3.x/jetty-start-9.3.x.jar")); + } + + @Test + public void testGetCoordinate_Zip() + { + MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer(); + String ref = "maven://org.eclipse.jetty/jetty-distribution/9.3.x/zip"; + Coordinates coords = repo.getCoordinates(URI.create(ref)); + assertThat("Coordinates",coords,notNullValue()); + + assertThat("coords.groupId",coords.groupId,is("org.eclipse.jetty")); + assertThat("coords.artifactId",coords.artifactId,is("jetty-distribution")); + assertThat("coords.version",coords.version,is("9.3.x")); + assertThat("coords.type",coords.type,is("zip")); + assertThat("coords.classifier",coords.classifier,nullValue()); + + assertThat("coords.toCentralURI", coords.toCentralURI().toASCIIString(), + is("http://central.maven.org/maven2/org/eclipse/jetty/jetty-distribution/9.3.x/jetty-distribution-9.3.x.zip")); + } + + @Test + public void testGetCoordinate_TestJar() + { + MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer(); + String ref = "maven://org.eclipse.jetty/jetty-http/9.3.x/jar/tests"; + Coordinates coords = repo.getCoordinates(URI.create(ref)); + assertThat("Coordinates",coords,notNullValue()); + + assertThat("coords.groupId",coords.groupId,is("org.eclipse.jetty")); + assertThat("coords.artifactId",coords.artifactId,is("jetty-http")); + assertThat("coords.version",coords.version,is("9.3.x")); + assertThat("coords.type",coords.type,is("jar")); + assertThat("coords.classifier",coords.classifier,is("tests")); + + assertThat("coords.toCentralURI", coords.toCentralURI().toASCIIString(), + is("http://central.maven.org/maven2/org/eclipse/jetty/jetty-http/9.3.x/jetty-http-9.3.x-tests.jar")); + } + + @Test + public void testGetCoordinate_Test_UnspecifiedType() + { + MavenLocalRepoFileInitializer repo = new MavenLocalRepoFileInitializer(); + String ref = "maven://org.eclipse.jetty/jetty-http/9.3.x//tests"; + Coordinates coords = repo.getCoordinates(URI.create(ref)); + assertThat("Coordinates",coords,notNullValue()); + + assertThat("coords.groupId",coords.groupId,is("org.eclipse.jetty")); + assertThat("coords.artifactId",coords.artifactId,is("jetty-http")); + assertThat("coords.version",coords.version,is("9.3.x")); + assertThat("coords.type",coords.type,is("jar")); + assertThat("coords.classifier",coords.classifier,is("tests")); + + assertThat("coords.toCentralURI", coords.toCentralURI().toASCIIString(), + is("http://central.maven.org/maven2/org/eclipse/jetty/jetty-http/9.3.x/jetty-http-9.3.x-tests.jar")); + } +} |