Skip to content

Commit

Permalink
[SHRINKWRAP-411] Adding "delete" methods to the API, implementation, …
Browse files Browse the repository at this point in the history
…tests
  • Loading branch information
PiotrNowicki authored and ALRubinger committed Jul 27, 2012
1 parent dd241ea commit 1883f1f
Show file tree
Hide file tree
Showing 3 changed files with 705 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,116 @@ public interface ClassContainer<T extends Archive<T>> extends ResourceContainer<
* If no packages were specified
*/
T addPackages(boolean recursive, Filter<ArchivePath> filter, String... packages) throws IllegalArgumentException;

/**
* Deletes the {@link Class}, and all member (inner) {@link Class}es from the {@link Archive}.
*
* @param class The class to be deleted from the Archive
* @return This archive
* @throws IllegalArgumentException If no class was specified
*/
T deleteClass(Class<?> clazz) throws IllegalArgumentException;

/**
* Deletes the {@link Class}, and all member (inner) {@link Class}es, with the specified fully-qualified name, loaded by the
* Thread Context {@link ClassLoader}, from the {@link Archive}.
*
* @param fullyQualifiedClassName The name of the {@link Class} to be deleted
* @return This archive
* @throws IllegalArgumentException If no class name was specified
* @throws IllegalArgumentException If the {@link Class} could not be loaded
*/
T deleteClass(String fullyQualifiedClassName) throws IllegalArgumentException;

/**
* Deletes the {@link Class}es, and all member (inner) {@link Class}es from the {@link Archive}.
*
* @param classes The classes to be removed from the {@link Archive}
* @return This archive
* @throws IllegalArgumentException If no classes were specified
*/
T deleteClasses(Class<?>... classes) throws IllegalArgumentException;

/**
* Deletes all classes in the specified {@link Package} from the {@link Archive}. <br/>
* SubPackages are excluded.
*
* @param pack The {@link Package} to be deleted
* @return This archive
* @throws IllegalArgumentException If no package was specified
* @see #deletePackages(boolean, Package...)
*/
T deletePackage(Package pack) throws IllegalArgumentException;

/**
* Deletes all classes in the specified {@link Package} from the {@link Archive}. <br/>
* SubPackages are excluded.
*
* @param pack Package to be delete represented by a String ("my/package")
* @return This archive
* @throws IllegalArgumentException If no package was specified
* @see #deletePackages(boolean, Package...)
*/
T deletePackage(String pack) throws IllegalArgumentException;

/**
* Deletes all classes in the default {@link Package} from the {@link Archive}. <br/>
* SubPackages are excluded.
*
* @return This archive
*/
T deleteDefaultPackage();

/**
* Deletes all classes in the specified {@link Package}s from the {@link Archive}.
*
* @param recursive Should the sub packages be deleted?
* @param packages All the packages to be deleted
* @return This archive
* @throws IllegalArgumentException If no packages were specified
* @see #deletePackages(boolean, Filter, Package...)
*/
T deletePackages(boolean recursive, Package... packages) throws IllegalArgumentException;

/**
* Delete all classes in the specified {@link Package}s from the {@link Archive}.
*
* @param recursive Should the sub packages be deleted?
* @param packages All the packages to be deleted represented by a String ("my/package")
* @return This archive
* @throws IllegalArgumentException If no packages were specified
* @see #deletePackages(boolean, Filter, Package...)
*/
T deletePackages(boolean recursive, String... packages) throws IllegalArgumentException;

/**
* Deletes all classes accepted by the filter in the specified {@link Package}s from the {@link Archive}. <br/>
*
* The {@link ArchivePath} returned to the filter is the {@link ArchivePath} of the class, not the final location. <br/>
* package.MyClass = /package/MyClass.class <br/>
* <b>not:</b> package.MyClass = /WEB-INF/classes/package/MyClass.class <br/>
*
* @param recursive Should the sub packages be deleted?
* @param filter filter out specific classes
* @param packages All the packages to be deleted
* @return This archive
* @throws IllegalArgumentException If no packages were specified or if no filter was specified
*/
T deletePackages(boolean recursive, Filter<ArchivePath> filter, Package... packages) throws IllegalArgumentException;

/**
* Delete all classes accepted by the filter in the specified {@link Package}s from the {@link Archive}. <br/>
*
* The {@link ArchivePath} returned to the filter is the {@link ArchivePath} of the class, not the final location. <br/>
* package.MyClass = /package/MyClass.class <br/>
* <b>not:</b> package.MyClass = /WEB-INF/classes/package/MyClass.class <br/>
*
* @param recursive Should the sub packages be deleted?
* @param filter filter out specific classes
* @param packages All the packages to be deleted represented by a String ("my/package")
* @return This archive
* @throws IllegalArgumentException If no packages were specified or if no filter was specified
*/
T deletePackages(boolean recursive, Filter<ArchivePath> filter, String... packages) throws IllegalArgumentException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ArchiveEventHandler;
Expand Down Expand Up @@ -1266,9 +1267,8 @@ public T addClass(String fullyQualifiedClassName) throws IllegalArgumentExceptio
Validate.notNullOrEmpty(fullyQualifiedClassName, "Fully-qualified class name must be specified");

// Get this archive's CLs
final Archive<?> archive = this.getArchive();
final Iterable<ClassLoader> cls = ((Configurable) archive).getConfiguration().getClassLoaders();
assert cls != null : "CLs of this archive is not specified:" + archive;
Iterable<ClassLoader> cls = getArchiveClassLoaders();
assert cls != null : "CLs of this archive is not specified:" + this.getArchive();

// Find the class in the configured CLs
final Class<?> classToAdd;
Expand Down Expand Up @@ -1450,8 +1450,7 @@ public T addPackages(boolean recursive, final Filter<ArchivePath> filter, String
Validate.notNull(packageNames, "PackageNames must be specified");

// Get the CLs for this archive
final Iterable<ClassLoader> classLoaders = ((Configurable) this.getArchive()).getConfiguration()
.getClassLoaders();
final Iterable<ClassLoader> classLoaders = getArchiveClassLoaders();

for (String packageName : packageNames) {
for (final ClassLoader classLoader : classLoaders) {
Expand Down Expand Up @@ -1493,6 +1492,192 @@ public void classFound(String className) {
scanner.scanPackage();
}

/*
* (non-Javadoc)
*
* @see org.jboss.shrinkwrap.api.container.ClassContainer#deleteClass(java.lang.Class)
*/
@Override
public T deleteClass(Class<?> clazz) throws IllegalArgumentException {
Validate.notNull(clazz, "Class must be specified");

return deleteClasses(clazz);
}

/*
* (non-Javadoc)
*
* @see org.jboss.shrinkwrap.api.container.ClassContainer#deleteClass(java.lang.String)
*/
@Override
public T deleteClass(String fullyQualifiedClassName) throws IllegalArgumentException {
Validate.notNull(fullyQualifiedClassName, "Class name must be specified");

ArchivePath path = new BasicPath(getClassesPath(), AssetUtil.getFullPathForClassResource(fullyQualifiedClassName));

getArchive().delete(path);

return covarientReturn();
}

/*
* (non-Javadoc)
*
* @see org.jboss.shrinkwrap.api.container.ClassContainer#deleteClasses(java.lang.Class<?>[])
*/
@Override
public T deleteClasses(Class<?>... classes) throws IllegalArgumentException {
Validate.notNullAndNoNullValues(classes, "Classes must be specified and cannot contain null values");

for (Class<?> clazz : classes) {
final ArchivePath path = new BasicPath(getClassesPath(), AssetUtil.getFullPathForClassResource(clazz));

// We need to remove all the inner classes as well (if present).
for (ArchivePath innerPath : getInnerClasses(path)) {
getArchive().delete(innerPath);
}

// Remove the class itself.
getArchive().delete(path);
}

return covarientReturn();
}

private Set<ArchivePath> getInnerClasses(final ArchivePath path) {
Map<ArchivePath, Node> content = getContent(new Filter<ArchivePath>() {
@Override
public boolean include(ArchivePath object) {
String expression = path.get().replace(".class", "\\$.*");
final boolean matches = object.get().matches(expression);

return matches;
}
});

return content.keySet();
}

/*
* (non-Javadoc)
*
* @see org.jboss.shrinkwrap.api.container.ClassContainer#deletePackage(java.lang.Package)
*/
@Override
public T deletePackage(Package pack) throws IllegalArgumentException {
Validate.notNull(pack, "Package name must be specified");

return deletePackages(false, pack);
}

/*
* (non-Javadoc)
*
* @see org.jboss.shrinkwrap.api.container.ClassContainer#deletePackage(java.lang.String)
*/
@Override
public T deletePackage(String pack) throws IllegalArgumentException {
Validate.notNull(pack, "Package name must be specified");

return deletePackages(false, pack);
}

/*
* (non-Javadoc)
*
* @see org.jboss.shrinkwrap.api.container.ClassContainer#deleteDefaultPackage()
*/
@Override
public T deleteDefaultPackage() {
return deletePackage(DEFAULT_PACKAGE_NAME);
}

/*
* (non-Javadoc)
*
* @see org.jboss.shrinkwrap.api.container.ClassContainer#deletePackages(boolean, java.lang.Package[])
*/
@Override
public T deletePackages(boolean recursive, Package... packages) throws IllegalArgumentException {
Validate.notNullAndNoNullValues(packages, "Packages must be specified and must not contain null values");

return deletePackages(recursive, Filters.includeAll(), packages);
}

/*
* (non-Javadoc)
*
* @see org.jboss.shrinkwrap.api.container.ClassContainer#deletePackages(boolean, java.lang.String[])
*/
@Override
public T deletePackages(boolean recursive, String... packages) throws IllegalArgumentException {
Validate.notNullAndNoNullValues(packages, "Packages must be specified and must not contain null values");

return deletePackages(recursive, Filters.includeAll(), packages);
}

/*
* (non-Javadoc)
*
* @see org.jboss.shrinkwrap.api.container.ClassContainer#deletePackages(boolean, org.jboss.shrinkwrap.api.Filter,
* java.lang.Package[])
*/
@Override
public T deletePackages(boolean recursive, Filter<ArchivePath> filter, Package... packages) throws IllegalArgumentException {
Validate.notNullAndNoNullValues(packages, "Packages must be specified and cannot contain null values");
Validate.notNull(filter, "Filter must be specified");

String[] packagesName = new String[packages.length];

for (int i = 0; i < packages.length; i++) {
// Validation for not-nullity was already done
packagesName[i] = packages[i].getName();
}

return deletePackages(recursive, filter, packagesName);
}

/*
* (non-Javadoc)
*
* @see org.jboss.shrinkwrap.api.container.ClassContainer#deletePackages(boolean, org.jboss.shrinkwrap.api.Filter,
* java.lang.String[])
*/
@Override
public T deletePackages(boolean recursive, Filter<ArchivePath> filter, String... packages) throws IllegalArgumentException {
Validate.notNullAndNoNullValues(packages, "Packages must be specified and cannot contain null values");
Validate.notNull(filter, "Filter must be specified");

for (String packageName : packages) {
for (ClassLoader cl : getArchiveClassLoaders()) {
deletePackage(recursive, filter, packageName, cl);
}
}

return covarientReturn();
}

private void deletePackage(boolean recursive, final Filter<ArchivePath> filter, String packageName, ClassLoader classLoader) {
assert filter != null : "Filter cannot be null";

final URLPackageScanner.Callback callback = new URLPackageScanner.Callback() {
@Override
public void classFound(String className) {
ArchivePath classNamePath = AssetUtil.getFullPathForClassResource(className);

if (!filter.include(classNamePath)) {
return;
}

ArchivePath location = new BasicPath(getClassesPath(), classNamePath);
delete(location);
}
};

final URLPackageScanner scanner = URLPackageScanner.newInstance(recursive, classLoader, callback, packageName);
scanner.scanPackage();
}

// -------------------------------------------------------------------------------------||
// Required Implementations - LibraryContainer ----------------------------------------||
// -------------------------------------------------------------------------------------||
Expand Down Expand Up @@ -1799,6 +1984,12 @@ private enum GetTcclAction implements PrivilegedAction<ClassLoader> {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
}

private Iterable<ClassLoader> getArchiveClassLoaders() {
final Archive<?> archive = getArchive();
final Iterable<ClassLoader> cls = ((Configurable) archive).getConfiguration().getClassLoaders();

return cls;
}
}

0 comments on commit 1883f1f

Please sign in to comment.