org.eclipse.jetty.start.BaseBuilder Maven / Gradle / Ivy
//
// ========================================================================
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// 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.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.start.builders.StartDirBuilder;
import org.eclipse.jetty.start.builders.StartIniBuilder;
import org.eclipse.jetty.start.fileinits.BaseHomeFileInitializer;
import org.eclipse.jetty.start.fileinits.LocalFileInitializer;
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 ${jetty.base}
, including
* ini files, directories, and libs. Also handles License management.
*/
public class BaseBuilder
{
public interface Config
{
/**
* Add a module to the start environment in ${jetty.base}
*
* @param module the module to add
* @param props The properties to substitute into a template
* @return The ini file if module was added, null if module was not added.
* @throws IOException if unable to add the module
*/
String addModule(Module module, Props props) throws IOException;
}
private static final String EXITING_LICENSE_NOT_ACKNOWLEDGED = "Exiting: license not acknowledged!";
private final BaseHome baseHome;
private final List 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())
{
// Copy from basehome
fileInitializers.add(new BaseHomeFileInitializer(baseHome));
// Handle local directories
fileInitializers.add(new LocalFileInitializer(baseHome));
// No downloads performed
fileInitializers.add(new TestFileInitializer(baseHome));
}
else if (args.isCreateFiles())
{
// Handle local directories
fileInitializers.add(new LocalFileInitializer(baseHome));
// Downloads are allowed to be performed
// Setup Maven Local Repo
Path localRepoDir = args.findMavenLocalRepoDir();
if (localRepoDir != null)
{
// Use provided local repo directory
fileInitializers.add(new MavenLocalRepoFileInitializer(baseHome, localRepoDir,
args.getMavenLocalRepoDir() == null,
startArgs.getMavenBaseUri()));
}
else
{
// No no local repo directory (direct downloads)
fileInitializers.add(new MavenLocalRepoFileInitializer(baseHome));
}
// Copy from basehome
fileInitializers.add(new BaseHomeFileInitializer(baseHome));
// Normal URL downloads
fileInitializers.add(new UriFileInitializer(baseHome));
}
}
/**
* Build out the Base directory (if needed)
*
* @return true if base directory was changed, false if left unchanged.
* @throws IOException if unable to build
*/
public boolean build() throws IOException
{
Modules modules = startArgs.getAllModules();
// Select all the added modules to determine which ones are newly enabled
Set newlyAdded = new HashSet<>();
if (!startArgs.getStartModules().isEmpty())
{
for (String name : startArgs.getStartModules())
{
newlyAdded.addAll(modules.enable(name, "--add-to-start"));
if (!newlyAdded.contains(name))
{
Set sources = modules.get(name).getEnableSources();
sources.remove("--add-to-start");
StartLog.info("%s already enabled by %s", name, sources);
}
}
}
if (StartLog.isDebugEnabled())
StartLog.debug("added=%s", newlyAdded);
// Check the licenses
if (startArgs.isLicenseCheckRequired())
{
Licensing licensing = new Licensing();
for (String name : newlyAdded)
{
licensing.addModule(modules.get(name));
}
if (licensing.hasLicenses())
{
if (startArgs.isApproveAllLicenses())
{
StartLog.info("All Licenses Approved via Command Line Option");
}
else if (!licensing.acknowledgeLicenses())
{
StartLog.warn(EXITING_LICENSE_NOT_ACKNOWLEDGED);
System.exit(1);
}
}
}
// generate the files
List files = new ArrayList();
AtomicReference builder = new AtomicReference<>();
AtomicBoolean modified = new AtomicBoolean();
Path startd = getBaseHome().getBasePath("start.d");
Path startini = getBaseHome().getBasePath("start.ini");
if (startArgs.isCreateStartd() && !Files.exists(startd))
{
if (FS.ensureDirectoryExists(startd))
{
StartLog.log("MKDIR", baseHome.toShortForm(startd));
modified.set(true);
}
if (Files.exists(startini))
{
int ini = 0;
Path startdStartini = startd.resolve("start.ini");
while (Files.exists(startdStartini))
{
ini++;
startdStartini = startd.resolve("start" + ini + ".ini");
}
Files.move(startini, startdStartini);
modified.set(true);
}
}
if (!newlyAdded.isEmpty())
{
if (Files.exists(startini) && Files.exists(startd))
StartLog.warn("Use both %s and %s is deprecated", getBaseHome().toShortForm(startd), getBaseHome().toShortForm(startini));
boolean useStartD = Files.exists(startd);
builder.set(useStartD ? new StartDirBuilder(this) : new StartIniBuilder(this));
newlyAdded.stream().map(n -> modules.get(n)).forEach(module ->
{
String ini = null;
try
{
if (module.isSkipFilesValidation())
{
StartLog.debug("Skipping [files] validation on %s", module.getName());
}
else
{
// if (explicitly added and ini file modified)
if (startArgs.getStartModules().contains(module.getName()))
{
ini = builder.get().addModule(module, startArgs.getProperties());
if (ini != null)
modified.set(true);
}
for (String file : module.getFiles())
{
files.add(new FileArg(module, startArgs.getProperties().expand(file)));
}
}
}
catch (Exception e)
{
throw new RuntimeException(e);
}
if (module.isDynamic())
{
for (String s : module.getEnableSources())
{
StartLog.info("%-15s %s", module.getName(), s);
}
}
else if (module.isTransitive())
{
if (module.hasIniTemplate())
StartLog.info("%-15s transitively enabled, ini template available with --add-to-start=%s",
module.getName(),
module.getName());
else
StartLog.info("%-15s transitively enabled", module.getName());
}
else
StartLog.info("%-15s initialized in %s",
module.getName(),
ini);
});
}
files.addAll(startArgs.getFiles());
if (!files.isEmpty() && processFileResources(files))
modified.set(true);
return modified.get();
}
public BaseHome getBaseHome()
{
return baseHome;
}
public StartArgs getStartArgs()
{
return startArgs;
}
/**
* Process a specific file resource
*
* @param arg the fileArg 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) throws IOException
{
URI uri = arg.uri == null ? null : URI.create(arg.uri);
if (startArgs.isCreateFiles())
{
for (FileInitializer finit : fileInitializers)
{
if (finit.isApplicable(uri))
return finit.create(uri, arg.location);
}
throw new IOException(String.format("Unable to create %s", arg));
}
for (FileInitializer finit : fileInitializers)
{
if (finit.isApplicable(uri))
if (!finit.check(uri, arg.location))
startArgs.setRun(false);
}
return false;
}
/**
* 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 files) throws IOException
{
if ((files == null) || (files.isEmpty()))
{
return false;
}
boolean dirty = false;
List failures = new ArrayList<>();
for (FileArg arg : files)
{
try
{
boolean processed = processFileResource(arg);
dirty |= processed;
}
catch (Throwable t)
{
StartLog.warn(t);
failures.add(String.format("[%s] %s - %s", t.getClass().getSimpleName(), t.getMessage(), arg.location));
}
}
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;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy