This is an automated email from the ASF dual-hosted git repository. rmannibucau pushed a commit to branch rmannibucau/scan-mojo in repository https://gitbox.apache.org/repos/asf/openwebbeans.git
commit 6863edf69a3743b42b381a8e288d5141ab437f94 Author: Romain Manni-Bucau <rmannibu...@gmail.com> AuthorDate: Sat Dec 5 21:12:25 2020 +0100 basic scan mojo --- pom.xml | 2 + .../webbeans/config/OpenWebBeansConfiguration.java | 7 + .../corespi/scanner/AbstractMetaDataDiscovery.java | 3 +- .../webbeans/corespi/scanner/xbean/CdiArchive.java | 49 ++- .../InterceptorAnnotatedDiscoveryTest.java | 4 +- webbeans-maven-plugin/pom.xml | 118 ++++++ .../org/apache/openwebbeans/maven/ScanMojo.java | 457 +++++++++++++++++++++ .../src/main/resources/META-INF/MANIFEST.MF | 1 + .../apache/webbeans/web/tests/WebBeansTest.java | 4 +- 9 files changed, 640 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 3d672d1..c37574a 100644 --- a/pom.xml +++ b/pom.xml @@ -504,6 +504,7 @@ </execution> </executions> <configuration> + <excludes>**/HelpMojo.java</excludes> <configLocation>openwebbeans/owb-checks-default.xml</configLocation> <headerLocation>openwebbeans/owb-header.txt</headerLocation> <consoleOutput>true</consoleOutput> @@ -649,6 +650,7 @@ <module>webbeans-se</module> <module>webbeans-junit5</module> <module>webbeans-slf4j</module> + <module>webbeans-maven-plugin</module> </modules> <dependencyManagement> diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/config/OpenWebBeansConfiguration.java b/webbeans-impl/src/main/java/org/apache/webbeans/config/OpenWebBeansConfiguration.java index 7eab234..82486a5 100644 --- a/webbeans-impl/src/main/java/org/apache/webbeans/config/OpenWebBeansConfiguration.java +++ b/webbeans-impl/src/main/java/org/apache/webbeans/config/OpenWebBeansConfiguration.java @@ -556,4 +556,11 @@ public class OpenWebBeansConfiguration return generatorJavaVersion; } + + public void cleanBuiltTimeScanning() + { + configProperties.stringPropertyNames().stream() + .filter(it -> it.startsWith("openwebbeans.buildtime.scanning.")) + .forEach(configProperties::remove); + } } diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/corespi/scanner/AbstractMetaDataDiscovery.java b/webbeans-impl/src/main/java/org/apache/webbeans/corespi/scanner/AbstractMetaDataDiscovery.java index 210556e..797f093 100644 --- a/webbeans-impl/src/main/java/org/apache/webbeans/corespi/scanner/AbstractMetaDataDiscovery.java +++ b/webbeans-impl/src/main/java/org/apache/webbeans/corespi/scanner/AbstractMetaDataDiscovery.java @@ -129,7 +129,8 @@ public abstract class AbstractMetaDataDiscovery implements BdaScannerService } archive = new CdiArchive( beanArchiveService, WebBeansUtil.getCurrentClassLoader(), - beanDeploymentUrls, userFilter, getAdditionalArchive()); + beanDeploymentUrls, userFilter, getAdditionalArchive(), + webBeansContext.getOpenWebBeansConfiguration()); finder = new OwbAnnotationFinder(archive); return finder; diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/corespi/scanner/xbean/CdiArchive.java b/webbeans-impl/src/main/java/org/apache/webbeans/corespi/scanner/xbean/CdiArchive.java index b77aaf0..1b7c199 100644 --- a/webbeans-impl/src/main/java/org/apache/webbeans/corespi/scanner/xbean/CdiArchive.java +++ b/webbeans-impl/src/main/java/org/apache/webbeans/corespi/scanner/xbean/CdiArchive.java @@ -18,14 +18,18 @@ */ package org.apache.webbeans.corespi.scanner.xbean; +import org.apache.webbeans.config.OpenWebBeansConfiguration; import org.apache.webbeans.spi.BeanArchiveService; import org.apache.webbeans.spi.BeanArchiveService.BeanArchiveInformation; import org.apache.xbean.finder.archive.Archive; +import org.apache.xbean.finder.archive.ClassesArchive; import org.apache.xbean.finder.archive.ClasspathArchive; import org.apache.xbean.finder.archive.CompositeArchive; import org.apache.xbean.finder.archive.FilteredArchive; import org.apache.xbean.finder.filter.Filter; +import org.apache.xbean.finder.util.Files; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -35,6 +39,10 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.toList; /** * this delegate pattern is interesting @@ -53,7 +61,7 @@ public class CdiArchive implements Archive private final Archive delegate; public CdiArchive(BeanArchiveService beanArchiveService, ClassLoader loader, Map<String, URL> urls, - Filter userFilter, Archive customArchive) + Filter userFilter, Archive customArchive, OpenWebBeansConfiguration config) { Collection<Archive> archives = new ArrayList<>(); boolean customAdded = false; @@ -64,7 +72,9 @@ public class CdiArchive implements Archive BeanArchiveInformation beanArchiveInfo = beanArchiveService.getBeanArchiveInformation(url); final boolean custom = "openwebbeans".equals(url.getProtocol()); Archive archive = new FilteredArchive( - custom ? customArchive : ClasspathArchive.archive(loader, url), + custom ? + customArchive : + createArchive(loader, url, config), new BeanArchiveFilter(beanArchiveInfo, urlClasses, userFilter)); if (!customAdded && custom) { @@ -78,9 +88,44 @@ public class CdiArchive implements Archive { archives.add(userFilter != null ? new FilteredArchive(customArchive, userFilter) : customArchive); } + if (config != null) + { + config.cleanBuiltTimeScanning(); + } delegate = new CompositeArchive(archives); } + private Archive createArchive(final ClassLoader loader, final URL url, final OpenWebBeansConfiguration config) + { + if (config != null) + { + final File file = Files.toFile(url); + if (!file.isDirectory()) // see ScanMojo + { + final String classes = config.getProperty( + "openwebbeans.buildtime.scanning." + file.getName() + ".classes"); + if (classes != null) + { + return new ClassesArchive(Stream.of(classes.split(",")) + .map(it -> + { + try + { + return loader.loadClass(it); + } + catch (final ClassNotFoundException e) + { + return null; + } + }) + .filter(Objects::nonNull) + .collect(toList())); + } + } + } + return ClasspathArchive.archive(loader, url); + } + public Map<String, FoundClasses> classesByUrl() { return classesByUrl; diff --git a/webbeans-impl/src/test/java/org/apache/webbeans/test/discovery/InterceptorAnnotatedDiscoveryTest.java b/webbeans-impl/src/test/java/org/apache/webbeans/test/discovery/InterceptorAnnotatedDiscoveryTest.java index e3f9602..a8f79cc 100644 --- a/webbeans-impl/src/test/java/org/apache/webbeans/test/discovery/InterceptorAnnotatedDiscoveryTest.java +++ b/webbeans-impl/src/test/java/org/apache/webbeans/test/discovery/InterceptorAnnotatedDiscoveryTest.java @@ -75,7 +75,9 @@ public class InterceptorAnnotatedDiscoveryTest extends AbstractUnitTest } super.initFinder(); - archive = new CdiArchive(webBeansContext().getBeanArchiveService(), WebBeansUtil.getCurrentClassLoader(), emptyMap(), null, null) + archive = new CdiArchive( + webBeansContext().getBeanArchiveService(), WebBeansUtil.getCurrentClassLoader(), emptyMap(), + null, null, null) { @Override public Map<String, FoundClasses> classesByUrl() diff --git a/webbeans-maven-plugin/pom.xml b/webbeans-maven-plugin/pom.xml new file mode 100644 index 0000000..f0e7104 --- /dev/null +++ b/webbeans-maven-plugin/pom.xml @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>openwebbeans</artifactId> + <groupId>org.apache.openwebbeans</groupId> + <version>2.0.21-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>openwebbeans-maven-plugin</artifactId> + <name>Maven Plugin</name> + <packaging>maven-plugin</packaging> + <description>Apache OpenWebBeans Maven Plugin</description> + + <properties> + <mvn.version>3.6.3</mvn.version> + <meecrowave.build.name>${project.groupId}.maven</meecrowave.build.name> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <version>${mvn.version}</version> + <exclusions> + <exclusion> + <groupId>javax.enterprise</groupId> + <artifactId>cdi-api</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <version>${mvn.version}</version> + <exclusions> + <exclusion> + <groupId>javax.inject</groupId> + <artifactId>javax.inject</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.maven.plugin-tools</groupId> + <artifactId>maven-plugin-annotations</artifactId> + <version>3.3</version> + </dependency> + <dependency> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-dependency-tree</artifactId> + <version>3.0.1</version> + </dependency> + <dependency> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-artifact-resolver</artifactId> + <version>1.0</version> + </dependency> + <dependency> + <groupId>org.apache.xbean</groupId> + <artifactId>xbean-finder-shaded</artifactId> + <version>${xbean.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <version>3.6.0</version> + <executions> + <execution> + <id>mojo-descriptor</id> + <goals> + <goal>descriptor</goal> + <goal>helpmojo</goal> + </goals> + </execution> + </executions> + <configuration> + <goalPrefix>openwebbeans</goalPrefix> + <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound> + </configuration> + </plugin> + </plugins> + </build> + + <reporting> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <version>3.6.0</version> + </plugin> + </plugins> + </reporting> + +</project> \ No newline at end of file diff --git a/webbeans-maven-plugin/src/main/java/org/apache/openwebbeans/maven/ScanMojo.java b/webbeans-maven-plugin/src/main/java/org/apache/openwebbeans/maven/ScanMojo.java new file mode 100644 index 0000000..e62d10a --- /dev/null +++ b/webbeans-maven-plugin/src/main/java/org/apache/openwebbeans/maven/ScanMojo.java @@ -0,0 +1,457 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openwebbeans.maven; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.DefaultArtifact; +import org.apache.maven.artifact.handler.DefaultArtifactHandler; +import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; +import org.apache.maven.artifact.resolver.ArtifactResolutionResult; +import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.DefaultDependencyResolutionRequest; +import org.apache.maven.project.DependencyResolutionException; +import org.apache.maven.project.DependencyResolutionRequest; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.MavenProjectHelper; +import org.apache.maven.project.ProjectDependenciesResolver; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder; +import org.apache.xbean.finder.AnnotationFinder; +import org.apache.xbean.finder.archive.Archive; +import org.apache.xbean.finder.archive.ClasspathArchive; +import org.apache.xbean.finder.util.Files; +import org.eclipse.aether.graph.DependencyVisitor; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.lang.reflect.Modifier; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.regex.Pattern; + +import static java.util.Arrays.asList; +import static java.util.Comparator.comparing; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; +import static org.apache.maven.plugins.annotations.ResolutionScope.RUNTIME_PLUS_SYSTEM; + +/** + * Scan at build time the beans and generate an OWB configuration to use it. + */ +@Mojo(name = "scan", requiresDependencyResolution = RUNTIME_PLUS_SYSTEM) +public class ScanMojo extends AbstractMojo +{ + private static final String DEFAULT_DEP_EXCLUDES = "org.apache.johnzon:johnzon-," + + "org.apache.xbean:," + + "org.apache.openwebbeans:," + + "org.apache.tomcat:tomcat-," + + "org.apache.openjpa:openjpa," + + "org.apache.geronimo.specs:," + + "org.apache.commons:commons-," + + "commons-.+:commons-.+," + + "javax\\..+:.+," + + "org.postgresql:," + + "com.h2database:h2," + + "org.checkerframework:," + + "serp," + + "slf4j-"; + + @Parameter(property = "openwebbeans.skip", defaultValue = "false") + private boolean skip; + + @Parameter(property = "openwebbeans.scanFolders", defaultValue = "false") // can move more than jars + private boolean scanFolders; + + @Parameter(property = "openwebbeans.scopes", defaultValue = "compile,runtime") + private Collection<String> scopes; + + @Parameter(property = "openwebbeans.libs") + private Collection<String> libs; + + @Parameter(property = "openwebbeans.dependencies.includes") + private Collection<String> dependenciesIncludes; + + @Parameter(property = "openwebbeans.dependencies.excludes", defaultValue = DEFAULT_DEP_EXCLUDES) + private Collection<String> dependenciesExcludes; + + @Parameter(property = "openwebbeans.classes.excludes") + private Collection<String> classesExcludes; + + @Parameter(defaultValue = "${project.build.outputDirectory}") + private File outputDirectory; + + @Component + private MavenProjectHelper projectHelper; + + @Component + private RepositorySystem repositorySystem; + + @Component + private ProjectDependenciesResolver dependenciesResolver; + + @Component + private DependencyGraphBuilder graphBuilder; + + @Parameter(defaultValue = "${project}", readonly = true) + private MavenProject project; + + /** + * Used to extend properties set by default. + */ + @Parameter + private Map<String, String> openwebbeansProperties; + + @Parameter(defaultValue = "CLASSES") + private ScanMode mode; + + private Map<String, Pattern> patterns = new HashMap<>(); + + @Override + public void execute() throws MojoExecutionException + { + if (skip) + { + getLog().warn(getClass().getSimpleName() + " skipped"); + return; + } + + final Collection<Path> files = new ArrayList<>(); + if (dependenciesExcludes.contains("{defaults}")) + { + dependenciesExcludes.remove("{defaults}"); + dependenciesExcludes.addAll(asList(DEFAULT_DEP_EXCLUDES.split(","))); + } + + collectClasspath(files); + if (!scanFolders) + { + files.removeIf(it -> java.nio.file.Files.isDirectory(it)); + } + + final List<URL> urls = files.stream().map(it -> + { + try + { + return it.toUri().toURL(); + } + catch (final MalformedURLException e) + { + throw new IllegalStateException(e); + } + }).collect(toList()); + + final Thread thread = Thread.currentThread(); + final ClassLoader oldLoader = thread.getContextClassLoader(); + final List<Scanned> scanned; + try (final URLClassLoader loader = new URLClassLoader(urls.toArray(new URL[0]))) + { + thread.setContextClassLoader(loader); + scanned = urls.stream() + .map(url -> doScan(url, loader)) + .collect(toList()); + } + catch (final Exception e) + { + throw new MojoExecutionException(e.getMessage(), e); + } + finally + { + thread.setContextClassLoader(oldLoader); + } + + final Properties properties = new Properties() + { + @Override // deterministic write, not elegant but simple, avoids to recode java.util.Properties.saveConvert + public synchronized Enumeration<Object> keys() + { + final List<String> keys = new ArrayList<String>(List.class.cast(Collections.list(super.keys()))); + Collections.sort(keys); + return Collections.enumeration(new ArrayList<>(keys)); + } + + @Override // same for java 11 and not 8 + public Set<Map.Entry<Object, Object>> entrySet() + { + return new LinkedHashSet<>(super.entrySet().stream() + .sorted(comparing(it -> String.valueOf(it.getKey()))) + .collect(toList())); + } + }; + // meecrowave uses 1000 so let's override it + // for now we don't override scanner since built-in ones are able to read these meta but later we could + properties.setProperty("configuration.ordinal", "2000"); + switch (mode == null ? ScanMode.CLASSES : mode) + { + case CLASSES: + if (!scanned.isEmpty()) + { + scanned.forEach(meta -> properties.setProperty( + "openwebbeans.buildtime.scanning." + meta.name + ".classes", + String.join(",", meta.classes))); + } + break; + default: + getLog().error("Unsupported scan mode: " + mode); + } + + if (openwebbeansProperties != null) // easy way to customize a docker image or so let's support it + { + openwebbeansProperties.forEach(properties::setProperty); + } + + final Path output = outputDirectory.toPath().resolve("META-INF/openwebbeans/openwebbeans.properties"); + try + { + java.nio.file.Files.createDirectories(output.getParent()); + try (final Writer writer = new BufferedWriter(java.nio.file.Files.newBufferedWriter(output)) + { + @Override + public void write(final String str) throws IOException + { + if (!str.startsWith("#")) // skip date comment (and we don't care of other comments btw) + { + super.write(str); + } + } + }) + { + // don't use store() to ensure it is reproducible (no date) + properties.store(writer, ""); + } + } + catch (final IOException ioe) + { + throw new IllegalStateException(ioe); + } + } + + private Scanned doScan(final URL url, final ClassLoader loader) + { + final File file = Files.toFile(url); + final Archive archive = ClasspathArchive.archive(loader, url); + final Collection<String> classes = new AnnotationFinder(archive, false) + .getAnnotatedClassNames().stream() + .filter(it -> + { + try + { + final Class<?> aClass = loader.loadClass(it); + return !aClass.isAnonymousClass() && + !Modifier.isPrivate(aClass.getModifiers()); + } + catch (final ClassNotFoundException | NoClassDefFoundError err) + { + return false; + } + }) + .filter(it -> classesExcludes == null || classesExcludes.stream().noneMatch(it::startsWith)) + .sorted() + .collect(toList()); + return new Scanned(file.getName(), classes); + } + + protected void collectClasspath(final Collection<Path> files) + { + final Collection<String> includedArtifacts = project.getArtifacts().stream() + .filter(this::isIncluded) + .map(a -> + { + files.add(a.getFile().toPath()); + return a.getArtifactId(); + }).collect(toSet()); + libs.forEach(l -> + { + final boolean transitive = l.endsWith("?transitive"); + final String coords = transitive ? l.substring(0, l.length() - "?transitive".length()) : l; + final String[] c = coords.split(":"); + if (c.length < 3 || c.length > 5) + { + throw new IllegalArgumentException("libs syntax is groupId:artifactId:version[:classifier][:type[?transitive]]"); + } + if (!transitive) + { + files.add(resolve(c[0], c[1], c[2], c.length == 4 ? c[3] : "")); + } + else + { + addTransitiveDependencies(files, includedArtifacts, new Dependency() + {{ + setGroupId(c[0]); + setArtifactId(c[1]); + setVersion(c[2]); + if (c.length == 4 && !"-".equals(c[3])) + { + setClassifier(c[3]); + } + if (c.length == 5) + { + setType(c[4]); + } + }}); + } + }); + } + + private void addTransitiveDependencies(final Collection<Path> aggregator, + final Collection<String> includedArtifacts, final Dependency dependency) + { + final DependencyResolutionRequest request = new DefaultDependencyResolutionRequest(); + request.setMavenProject(new MavenProject() + {{ + getDependencies().add(dependency); + }}); + try + { + dependenciesResolver + .resolve(request) + .getDependencyGraph() + .accept(new DependencyVisitor() + { + @Override + public boolean visitEnter(final org.eclipse.aether.graph.DependencyNode node) + { + return true; + } + + @Override + public boolean visitLeave(final org.eclipse.aether.graph.DependencyNode node) + { + final org.eclipse.aether.artifact.Artifact artifact = node.getArtifact(); + if (artifact != null && includedArtifacts.add(artifact.getArtifactId())) + { + aggregator.add(artifact.getFile().toPath()); + } + return true; + } + }); + } + catch (final DependencyResolutionException e) + { + throw new IllegalStateException(e.getMessage(), e); + } + } + + private Path resolve(final String group, final String artifact, final String version, final String classifier) + { + final DefaultArtifact art = new DefaultArtifact( + group, artifact, version, "compile", "jar", classifier, new DefaultArtifactHandler()); + final ArtifactResolutionRequest artifactRequest = new ArtifactResolutionRequest() + .setArtifact(art); + final ArtifactResolutionResult result = repositorySystem.resolve(artifactRequest); + if (!result.isSuccess()) + { + throw new IllegalStateException("Can't find " + art + ", please add it to the pom."); + } + return result.getArtifacts().iterator().next().getFile().toPath(); + } + + + private boolean isIncluded(final Artifact a) + { + return (!((scopes == null && + !(Artifact.SCOPE_COMPILE.equals(a.getScope()) || Artifact.SCOPE_RUNTIME.equals(a.getScope()))) + || (scopes != null && !scopes.contains(a.getScope())))) && + isExplicitlyIncluded(a); + } + + private boolean isExplicitlyIncluded(final Artifact art) + { + if (dependenciesExcludes.isEmpty() && dependenciesIncludes.isEmpty()) + { + return true; + } + final String coord = art.getGroupId() + ':' + art.getArtifactId(); + final String artOnly = art.getArtifactId(); + if (!dependenciesIncludes.isEmpty() && dependenciesExcludes.isEmpty()) + { + return dependenciesIncludes.stream() + .anyMatch(it -> compare(coord, artOnly, it)); + } + if (dependenciesIncludes.isEmpty() && !dependenciesExcludes.isEmpty()) + { + return dependenciesExcludes.stream() + .noneMatch(it -> compare(coord, artOnly, it)); + } + final boolean forced = dependenciesIncludes.stream() + .anyMatch(it -> compare(coord, artOnly, it)); + if (forced) + { + return true; + } + final boolean notExcluded = dependenciesExcludes.stream() + .noneMatch(it -> compare(coord, artOnly, it)); + return notExcluded; + } + + private boolean compare(final String coord, final String artOnly, final String conf) + { + return coord.startsWith(conf) || artOnly.startsWith(conf) || patterns.computeIfAbsent(conf, k -> + { + try + { + return Pattern.compile(k); + } + catch (final Exception e) + { + // whatever, ignore pattern + return Pattern.compile("/\\\\"); + } + }).matcher(coord).matches(); + } + + private static class Scanned + { + private final String name; + private final Collection<String> classes; + + private Scanned(final String name, final Collection<String> classes) + { + this.name = name; + this.classes = classes; + } + } + + // this will be used to add new mode like "FULLY_PRE_SCANNED" + // where we wouldn't use the classloader but only the meta to scan + public enum ScanMode + { + // means we map the list of classes per jar, + // it enables to speed up scanning and keep extensibility of CDI + CLASSES + } +} diff --git a/webbeans-maven-plugin/src/main/resources/META-INF/MANIFEST.MF b/webbeans-maven-plugin/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000..9d885be --- /dev/null +++ b/webbeans-maven-plugin/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Manifest-Version: 1.0 diff --git a/webbeans-web/src/test/java/org/apache/webbeans/web/tests/WebBeansTest.java b/webbeans-web/src/test/java/org/apache/webbeans/web/tests/WebBeansTest.java index 82d1828..cbbb1f0 100644 --- a/webbeans-web/src/test/java/org/apache/webbeans/web/tests/WebBeansTest.java +++ b/webbeans-web/src/test/java/org/apache/webbeans/web/tests/WebBeansTest.java @@ -79,7 +79,9 @@ public class WebBeansTest { @Override public void scan() { - archive = new CdiArchive(new DefaultBeanArchiveService(), Thread.currentThread().getContextClassLoader(), new HashMap<String, URL>(), null, null); + archive = new CdiArchive( + new DefaultBeanArchiveService(), Thread.currentThread().getContextClassLoader(), + new HashMap<String, URL>(), null, null, null); finder = new OwbAnnotationFinder(new ClassesArchive()); } }