/*
* JBoss, Home of Professional Open Source
* Copyright 2009, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed 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.jboss.arquillian.container.weld.embedded;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import org.jboss.arquillian.core.spi.Validate;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ArchivePath;
import org.jboss.shrinkwrap.api.Filters;
import org.jboss.shrinkwrap.api.Node;
import org.jboss.shrinkwrap.api.asset.ArchiveAsset;
import org.jboss.weld.bootstrap.spi.BeansXml;
import org.jboss.weld.bootstrap.spi.Filter;
import org.jboss.weld.bootstrap.spi.Metadata;
import org.jboss.weld.metadata.FilterPredicate;
import org.jboss.weld.resources.spi.ResourceLoader;
/**
* BeanUtils
*
* @author <a href="mailto:aslak@redhat.com">Aslak Knutsen</a>
* @version $Revision: $
*/
final class Utils {
private static final String BEANS_XML_REGEX = ".*/beans\\.xml";
private Utils() {
}
@SuppressWarnings("unchecked")
static <T> T getBeanReference(BeanManager manager, Class<T> type) {
Bean<?> bean = manager.resolve(manager.getBeans(type));
return (T) manager.getReference(
bean,
type,
manager.createCreationalContext(null));
}
public static String findArchiveId(Archive<?> archive) {
return archive.getName();
}
public static Collection<URL> findBeansXml(Archive<?> archive) {
Validate.notNull(archive, "Archive must be specified");
List<URL> beansXmls = new ArrayList<URL>();
Map<ArchivePath, Node> nestedArchives = archive.getContent(Filters.include(".*\\.jar|.*\\.war"));
for (final Map.Entry<ArchivePath, Node> nestedArchiveEntry : nestedArchives.entrySet()) {
if (!(nestedArchiveEntry.getValue().getAsset() instanceof ArchiveAsset)) {
continue;
}
ArchiveAsset nestedArchive = (ArchiveAsset) nestedArchiveEntry.getValue().getAsset();
Map<ArchivePath, Node> classes = nestedArchive.getArchive().getContent(Filters.include(BEANS_XML_REGEX));
for (final Map.Entry<ArchivePath, Node> entry : classes.entrySet()) {
try {
beansXmls.add(
new URL(null, "archive://" + nestedArchive.getArchive().getName() + entry.getKey().get(), new URLStreamHandler() {
@Override
protected java.net.URLConnection openConnection(URL u) throws java.io.IOException {
return new URLConnection(u) {
@Override
public void connect() throws IOException {
}
@Override
public InputStream getInputStream()
throws IOException {
return entry.getValue().getAsset().openStream();
}
};
}
;
}));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Map<ArchivePath, Node> classes = archive.getContent(Filters.include(BEANS_XML_REGEX));
for (final Map.Entry<ArchivePath, Node> entry : classes.entrySet()) {
try {
beansXmls.add(
new URL(null, "archive://" + entry.getKey().get(), new URLStreamHandler() {
@Override
protected java.net.URLConnection openConnection(URL u) throws java.io.IOException {
return new URLConnection(u) {
@Override
public void connect() throws IOException {
}
@Override
public InputStream getInputStream()
throws IOException {
return entry.getValue().getAsset().openStream();
}
};
}
;
}));
} catch (Exception e) {
e.printStackTrace();
}
}
return beansXmls;
}
public static Collection<Class<?>> findBeanClasses(Archive<?> archive, ClassLoader classLoader, BeansXml beansXml, ResourceLoader resourceLoader) {
Validate.notNull(archive, "Archive must be specified");
List<Class<?>> beanClasses = new ArrayList<Class<?>>();
try {
Map<ArchivePath, Node> nestedArchives = archive.getContent(Filters.include(".*\\.jar|.*\\.war|.*\\.rar"));
for (final Map.Entry<ArchivePath, Node> nestedArchiveEntry : nestedArchives.entrySet()) {
if (!(nestedArchiveEntry.getValue().getAsset() instanceof ArchiveAsset)) {
continue;
}
ArchiveAsset nestedArchive = (ArchiveAsset) nestedArchiveEntry.getValue().getAsset();
Map<ArchivePath, Node> markerFiles = nestedArchive.getArchive().getContent(Filters.include(BEANS_XML_REGEX));
if (markerFiles.isEmpty()) {
continue;
}
beanClasses.addAll(filterClasses(nestedArchive.getArchive(), classLoader, beansXml, resourceLoader));
}
Map<ArchivePath, Node> markerFiles = archive.getContent(Filters.include(BEANS_XML_REGEX));
if (!markerFiles.isEmpty()) {
beanClasses.addAll(filterClasses(archive, classLoader, beansXml, resourceLoader));
}
} catch (ClassNotFoundException e) {
throw new RuntimeException("Could not load class from archive " + archive.getName(), e);
}
return beanClasses;
}
/*
* input: /org/MyClass.class
* output: org.MyClass
*/
public static String findClassName(ArchivePath path) {
String className = path.get();
className = className.replaceAll("/WEB-INF/classes/", "");
if (className.charAt(0) == '/') {
className = className.substring(1);
}
className = className.replaceAll("\\.class", "");
className = className.replaceAll("/", ".");
return className;
}
private static Collection<Class<?>> filterClasses(Archive<?> archive, ClassLoader classLoader, BeansXml beansXml, ResourceLoader resourceLoader)
throws ClassNotFoundException {
List<Class<?>> beanClasses = new ArrayList<Class<?>>();
Map<ArchivePath, Node> classes = archive.getContent(Filters.include(".*\\.class"));
for (Map.Entry<ArchivePath, Node> classEntry : classes.entrySet()) {
if (beansXml.getScanning().getExcludes().isEmpty()) {
Class<?> loadedClass = classLoader.loadClass(
findClassName(classEntry.getKey()));
beanClasses.add(loadedClass);
} else {
boolean isExcluded = false;
for (Metadata<Filter> filterMetadata : beansXml.getScanning().getExcludes()) {
FilterPredicate excludePredicate = new FilterPredicate(filterMetadata, resourceLoader);
if (excludePredicate.test(findClassName(classEntry.getKey()))) {
isExcluded = true;
break;
}
}
if (!isExcluded) {
Class<?> loadedClass = classLoader.loadClass(findClassName(classEntry.getKey()));
beanClasses.add(loadedClass);
}
}
}
return beanClasses;
}
}