
org.jboss.classloading.spi.dependency.Domain Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source.
* Copyright 2007, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.classloading.spi.dependency;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.jboss.classloading.plugins.metadata.ModuleRequirement;
import org.jboss.classloading.plugins.metadata.PackageCapability;
import org.jboss.classloading.plugins.metadata.PackageRequirement;
import org.jboss.classloading.spi.metadata.Capability;
import org.jboss.classloading.spi.metadata.Requirement;
import org.jboss.classloading.spi.version.VersionRange;
import org.jboss.logging.Logger;
/**
* Domain.
*
* @author Adrian Brock
* @author Ales Justin
* @author [email protected]
* @version $Revision: 1.1 $
*/
public class Domain implements ClassLoadingAdmin
{
/** The log */
private static final Logger log = Logger.getLogger(Domain.class);
/** The domain name */
private String name;
/** The classloading */
private ClassLoading classLoading;
/** The parent domain name */
private String parentDomainName;
/** Whether we are parent first */
private boolean parentFirst;
/** The registered modules in registration order */
private List modules = new CopyOnWriteArrayList();
/** The registered modules by name */
private Map modulesByName = new ConcurrentHashMap();
/**
* Create a new Domain.
*
* @param classLoading the classloading
* @param name the name
* @param parentDomainName the parent domain name
* @param parentFirst whether to check the parent first
* @throws IllegalArgumentException for a null domain or classloading
*/
public Domain(ClassLoading classLoading, String name, String parentDomainName, boolean parentFirst)
{
if (name == null)
throw new IllegalArgumentException("Null name");
if (classLoading == null)
throw new IllegalArgumentException("Null classLoading");
this.classLoading = classLoading;
this.name = name;
this.parentDomainName = parentDomainName;
this.parentFirst = parentFirst;
}
/**
* Get the name.
*
* @return the name.
*/
public String getName()
{
return name;
}
/**
* Get ClassLoading.
*
* @return the classloading
*/
public ClassLoading getClassLoading()
{
return classLoading;
}
/**
* Get the parentDomainName.
*
* @return the parentDomainName.
*/
public String getParentDomainName()
{
return parentDomainName;
}
public Domain getParentDomain()
{
if (parentDomainName != null)
return classLoading.getDomain(parentDomainName);
return null;
}
/**
* Get the parentFirst.
*
* @return the parentFirst.
*/
public boolean isParentFirst()
{
return parentFirst;
}
/**
* Add a module
*
* @param module the module
* @throws IllegalStateException if the module is already registered
* @throws IllegalArgumentException for a null parameter
*/
public synchronized void addModule(Module module)
{
if (module == null)
throw new IllegalArgumentException("Null module");
Domain domain = module.getDomain();
if (domain != null)
throw new IllegalArgumentException("The module is already registered with the domain " + domain.getName());
String contextName = module.getContextName();
if (modulesByName.containsKey(contextName))
throw new IllegalArgumentException("The context " + contextName + " is already registered in domain " + getName());
log.debug(this + " add module " + module);
module.setDomain(this);
modulesByName.put(contextName, module);
modules.add(module);
try
{
module.createDependencies();
// Skip the classloader space checking when it is import all
if (module.isImportAll() == false)
{
ClassLoadingSpace space = new ClassLoadingSpace();
space.join(module);
}
}
catch (Throwable t)
{
removeModule(module);
if (t instanceof RuntimeException)
throw (RuntimeException)t;
else if (t instanceof Error)
throw (Error)t;
else
throw new RuntimeException("Error adding module " + module, t);
}
}
/**
* Remove a deployment
*
* @param module the module
* @throws IllegalArgumentException for a null parameter
*/
protected synchronized void removeModule(Module module)
{
if (module == null)
throw new IllegalArgumentException("Null module");
log.debug(this + " remove module " + module);
ClassLoadingSpace space = module.getClassLoadingSpace();
if (space != null)
space.split(module);
module.removeDependencies();
modules.remove(module);
modulesByName.remove(module.getContextName());
module.setDomain(null);
}
/**
* Get a module for a context name
*
* @param name the context name
* @return the module
*/
public Module getModule(String name)
{
if (name == null)
throw new IllegalArgumentException("Null module name");
Module module = modulesByName.get(name);
if (module != null)
return module;
Domain parent = getParentDomain();
if (parent != null)
return parent.getModule(name);
return null;
}
/**
* Merges the capabilities provided by our global capabilities provider with the passed in capabilities.
*
* @param capabilities the capabilities list into which we want to add the global capabilities
* @return the passed in capabilities with the global capabilities merged in
*/
List mergeGlobalCapabilities(List capabilities)
{
return classLoading.mergeGlobalCapabilities(capabilities);
}
/**
* Resolve a requirement to a module
*
* @param module the module
* @param requirement the requirement
* @return the resolved name or null if not resolved
*/
protected Module resolveModule(Module module, Requirement requirement)
{
// Try to resolve the module
Module result = doResolveModule(module, requirement);
if (result == null)
{
// If we have resolvers, try again if they find it
if (classLoading.resolve(new ResolutionContext(this, module, requirement)))
result = doResolveModule(module, requirement);
}
// If there is a result, check to see whether we need to resolve it
if (result != null)
{
LifeCycle lifeCycle = result.getLifeCycle();
if (lifeCycle != null && lifeCycle.isLazyResolve() && lifeCycle.isResolved() == false)
{
try
{
lifeCycle.resolve();
}
catch (Throwable t)
{
log.warn("Error in resolve for " + result, t);
}
}
}
return result;
}
/**
* Resolve a requirement to a module
*
* @param module the module
* @param requirement the requirement
* @return the resolved name or null if not resolved
*/
protected Module doResolveModule(Module module, Requirement requirement)
{
// First check the parent domain has been setup
Domain parentDomain = null;
if (parentDomainName != null)
{
parentDomain = getParentDomain();
if (parentDomain == null)
return null;
}
// Check the parent first when required
if (parentDomain != null && parentFirst == true)
{
Module result = parentDomain.resolveModule(module, requirement);
if (result != null)
return result;
}
for (Module other : modules)
{
List capabilities = other.getCapabilities();
if (capabilities != null)
{
for (Capability capability : capabilities)
{
if (capability.resolves(module, requirement))
{
if (log.isTraceEnabled())
log.trace("Requirement " + requirement + " resolves against " + capability);
return other;
}
}
}
}
// Check the parent afterwards when required
if (parentDomain != null && parentFirst == false)
return parentDomain.resolveModule(module, requirement);
return null;
}
public Module getModuleForClass(Class> clazz)
{
return Module.getModuleForClass(clazz);
}
public Collection getModules(String name, VersionRange range)
{
if (name == null)
throw new IllegalArgumentException("Null name");
Collection result = new HashSet();
getModulesInternal(name, range, result);
return result;
}
/**
* Get the modules matching the name and range
*
* @param name the name
* @param range the range
* @param result the matching modules
*/
void getModulesInternal(String name, VersionRange range, Collection result)
{
if (range == null)
range = VersionRange.ALL_VERSIONS;
for (Module module : modules)
{
List capabilities = module.getCapabilitiesRaw();
if (capabilities != null && capabilities.isEmpty() == false)
{
ModuleRequirement requirement = new ModuleRequirement(name, range);
for (Capability capability : capabilities)
{
if (capability.resolves(module, requirement))
{
result.add(module);
break;
}
}
}
else
{
if (name.equals(module.getName()) && range.isInRange(module.getVersion()))
{
result.add(module);
return;
}
}
}
}
public Collection getImportedModules(String name, VersionRange range)
{
Collection result = new HashSet();
getImportingModulesInternal(name, range, result);
return result;
}
/**
* Get the importing modules matching the name and range
*
* @param name the name
* @param range the range
* @param result the matching modules
*/
void getImportingModulesInternal(String name, VersionRange range, Collection result)
{
if (range == null)
range = VersionRange.ALL_VERSIONS;
for (Module module : modules)
{
List requirementDependencyItems = module.getDependencies();
if (requirementDependencyItems != null && requirementDependencyItems.isEmpty() == false)
{
for (RequirementDependencyItem dependencyItem : requirementDependencyItems)
{
Requirement requirement = dependencyItem.getRequirement();
if (requirement instanceof ModuleRequirement && dependencyItem.isResolved())
{
ModuleRequirement moduleRequirement = (ModuleRequirement)requirement;
if (name == null || name.equals(moduleRequirement.getName()))
{
if (range.isConsistent(moduleRequirement.getVersionRange()))
{
Module other = module.resolveModule(dependencyItem, true);
ImportModule importModule = new ImportModule(other);
result.add(importModule);
}
}
}
}
}
}
}
public Collection getExportedPackages(Module module)
{
if (module == null)
throw new IllegalArgumentException("Null module");
return module.getExportedPackages();
}
public Collection getExportedPackages(String name, VersionRange range)
{
if (name == null)
throw new IllegalArgumentException("Null name");
Collection result = new HashSet();
getExportedPackagesInternal(name, range, result);
return result;
}
/**
* Get the exported packages matching the name and range
*
* @param name the name
* @param range the range
* @param result the matching modules
*/
void getExportedPackagesInternal(String name, VersionRange range, Collection result)
{
if (range == null)
range = VersionRange.ALL_VERSIONS;
for (Module module : modules)
{
List capabilities = module.getCapabilitiesRaw();
if (capabilities != null && capabilities.isEmpty() == false)
{
PackageRequirement requirement = new PackageRequirement(name, range);
for (Capability capability : capabilities)
{
if (capability instanceof PackageCapability && capability.resolves(module, requirement))
{
ExportPackage exportPackage = new ExportPackage(module, (PackageCapability)capability);
result.add(exportPackage);
break;
}
}
}
}
}
public void refreshModules(Module... modules) throws Exception
{
Module.refreshModules(modules);
}
public boolean resolveModules(Module... modules) throws Exception
{
return Module.resolveModules(modules);
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append(super.toString());
builder.append('{').append(getName()).append('}');
return builder.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy