![JAR search and dependency download from the Maven repository](/logo.png)
org.eclipse.jetty.start.Module Maven / Gradle / Ivy
//
// ========================================================================
// Copyright (c) 1995-2016 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.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
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.Locale;
import java.util.Set;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* Represents a Module metadata, as defined in Jetty.
*
* A module consists of:
*
* - A set of jar files, directories and/or jar file patterns to be added to the classpath
* - A list of XML configuration files
* - Properties set either directly or via a file of properties
* - A set of modules names (or capability names) that this module depends on.
* - A set of capability names that this module provides (including it's own name).
* - Licence details for using the module
*
* Modules are discovered in the ${jetty.home}/modules
and
* ${jetty.home}/modules
directories. A module may refer to
* non-discovered dynamic module in a subdirectory, using a property as part or
* all of the name.
* A module may be enabled, either directly by name or transiently via a dependency
* from another module by name or provided capability.
*/
public class Module
{
private static final String VERSION_UNSPECIFIED = "9.2";
private static Pattern MOD_NAME = Pattern.compile("^(.*)\\.mod",Pattern.CASE_INSENSITIVE);
/** The file of the module */
private final Path _path;
/** The name of the module */
private final String _name;
/** Is the module dynamic - ie referenced rather than discovered */
private final boolean _dynamic;
/** The version of Jetty the module supports */
private Version version;
/** The module description */
private final List _description=new ArrayList<>();
/** List of xml configurations for this Module */
private final List _xmls=new ArrayList<>();
/** List of ini template lines */
private final List _iniTemplate=new ArrayList<>();
/** List of default config */
private final List _defaultConfig=new ArrayList<>();
/** List of library options for this Module */
private final List _libs=new ArrayList<>();
/** List of files for this Module */
private final List _files=new ArrayList<>();
/** List of selections for this Module */
private final Set _enables=new HashSet<>();
/** List of provides for this Module */
private final Set _provides=new HashSet<>();
/** Boolean true if directly enabled, false if all selections are transitive */
private boolean _notTransitive;
/** Skip File Validation (default: false) */
private boolean _skipFilesValidation = false;
/** List of jvm Args */
private final List _jvmArgs=new ArrayList<>();
/** License lines */
private final List _license=new ArrayList<>();
/** Dependencies */
private final Set _depends=new HashSet<>();
/** Optional */
private final Set _optional=new HashSet<>();
public Module(BaseHome basehome, Path path) throws FileNotFoundException, IOException
{
super();
_path = path;
// Module name is the / separated path below the modules directory
int m=-1;
for (int i=path.getNameCount();i-->0;)
{
if ("modules".equals(path.getName(i).toString()))
{
m=i;
break;
}
}
if (m<0)
throw new IllegalArgumentException("Module not contained within modules directory: "+basehome.toShortForm(path));
String n=path.getName(m+1).toString();
for (int i=m+2;i expander = d->{return props.expand(d);};
Set tmp=_depends.stream().map(expander).collect(Collectors.toSet());
_depends.clear();
_depends.addAll(tmp);
tmp=_optional.stream().map(expander).collect(Collectors.toSet());
_optional.clear();
_optional.addAll(tmp);
}
public List getDefaultConfig()
{
return _defaultConfig;
}
public List getIniTemplate()
{
return _iniTemplate;
}
public List getFiles()
{
return _files;
}
public boolean isSkipFilesValidation()
{
return _skipFilesValidation;
}
public List getJvmArgs()
{
return _jvmArgs;
}
public List getLibs()
{
return _libs;
}
public List getLicense()
{
return _license;
}
public List getXmls()
{
return _xmls;
}
public Version getVersion()
{
return version;
}
public boolean hasDefaultConfig()
{
return !_defaultConfig.isEmpty();
}
public boolean hasIniTemplate()
{
return !_iniTemplate.isEmpty();
}
@Override
public int hashCode()
{
return _name.hashCode();
}
public boolean hasLicense()
{
return (_license != null) && (_license.size() > 0);
}
/**
* Indicates a module that is dynamic in nature
*
* @return a module where the name is not in the top level of the modules directory
*/
public boolean isDynamic()
{
return _dynamic;
}
public boolean hasFiles(BaseHome baseHome, Props props)
{
for (String ref : getFiles())
{
FileArg farg = new FileArg(this,props.expand(ref));
Path refPath = baseHome.getBasePath(farg.location);
if (!Files.exists(refPath))
{
return false;
}
}
return true;
}
public void process(BaseHome basehome) throws FileNotFoundException, IOException
{
Pattern section = Pattern.compile("\\s*\\[([^]]*)\\]\\s*");
if (!FS.canReadFile(_path))
{
StartLog.debug("Skipping read of missing file: %s",basehome.toShortForm(_path));
return;
}
try (BufferedReader buf = Files.newBufferedReader(_path,StandardCharsets.UTF_8))
{
String sectionType = "";
String line;
while ((line = buf.readLine()) != null)
{
line = line.trim();
Matcher sectionMatcher = section.matcher(line);
if (sectionMatcher.matches())
{
sectionType = sectionMatcher.group(1).trim().toUpperCase(Locale.ENGLISH);
}
else
{
// blank lines and comments are valid for ini-template section
if ((line.length() == 0) || line.startsWith("#"))
{
// Remember ini comments and whitespace (empty lines)
// for the [ini-template] section
if ("INI-TEMPLATE".equals(sectionType))
{
_iniTemplate.add(line);
}
}
else
{
switch (sectionType)
{
case "":
// ignore (this would be entries before first section)
break;
case "DESCRIPTION":
_description.add(line);
break;
case "DEPEND":
case "DEPENDS":
_depends.add(line);
break;
case "FILE":
case "FILES":
_files.add(line);
break;
case "DEFAULTS": // old name introduced in 9.2.x
case "INI": // new name for 9.3+
_defaultConfig.add(line);
break;
case "INI-TEMPLATE":
_iniTemplate.add(line);
break;
case "LIB":
case "LIBS":
_libs.add(line);
break;
case "LICENSE":
case "LICENSES":
case "LICENCE":
case "LICENCES":
_license.add(line);
break;
case "NAME":
StartLog.warn("Deprecated [Name] used in %s",basehome.toShortForm(_path));
_provides.add(line);
break;
case "PROVIDE":
case "PROVIDES":
_provides.add(line);
break;
case "OPTIONAL":
_optional.add(line);
break;
case "EXEC":
_jvmArgs.add(line);
break;
case "VERSION":
if (version != null)
{
throw new IOException("[version] already specified");
}
version = new Version(line);
break;
case "XML":
_xmls.add(line);
break;
default:
throw new IOException("Unrecognized Module section: [" + sectionType + "]");
}
}
}
}
}
if (version == null)
{
version = new Version(VERSION_UNSPECIFIED);
}
}
public boolean clearTransitiveEnable()
{
if (_notTransitive)
throw new IllegalStateException("Not Transitive");
if (isEnabled())
{
_enables.clear();
return true;
}
return false;
}
public void setSkipFilesValidation(boolean skipFilesValidation)
{
this._skipFilesValidation = skipFilesValidation;
}
@Override
public String toString()
{
StringBuilder str = new StringBuilder();
str.append("Module[").append(getName());
if (isEnabled())
{
str.append(",enabled");
}
if (isTransitive())
{
str.append(",transitive");
}
str.append(']');
return str.toString();
}
public Set getDepends()
{
return new HashSet<>(_depends);
}
public Set getProvides()
{
return new HashSet<>(_provides);
}
public Set getOptional()
{
return new HashSet<>(_optional);
}
public List getDescription()
{
return _description;
}
public boolean isEnabled()
{
return !_enables.isEmpty();
}
public Set getEnableSources()
{
return new HashSet<>(_enables);
}
/**
* @param source
* @param transitive
* @return True if the module was not previously enabled
*/
public boolean enable(String source,boolean transitive)
{
boolean updated=_enables.isEmpty();
if (transitive)
{
// Ignore transitive selections if explicitly enabled
if (!_notTransitive)
_enables.add(source);
}
else
{
if (!_notTransitive)
{
// Ignore transitive selections if explicitly enabled
updated=true;
_enables.clear(); // clear any transitive enabling
}
_notTransitive=true;
_enables.add(source);
}
return updated;
}
public boolean isTransitive()
{
return isEnabled() && !_notTransitive;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy