/*
* Copyright 2013 Chris Pheby
*
* 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.jadira.scanner;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jadira.scanner.classpath.ClasspathResolver;
import org.jadira.scanner.classpath.filter.JElementTypeFilter;
import org.jadira.scanner.classpath.filter.JTypeAnnotatedWithFilter;
import org.jadira.scanner.classpath.filter.JTypeSubTypeOfFilter;
import org.jadira.scanner.classpath.projector.ClasspathProjector;
import org.jadira.scanner.classpath.types.JElement;
import org.jadira.scanner.classpath.types.JType;
import org.jadira.scanner.core.api.Filter;
import org.jadira.scanner.core.api.Locator;
public class Scanner {
protected final transient Configuration configuration;
private ClasspathResolver classpathResolver;
public Scanner(final Configuration configuration) {
this.configuration = configuration;
List<URL> urls = new ArrayList<URL>();
if (configuration.getUrls() != null) {
urls.addAll(configuration.getUrls());
}
if (configuration.getLocators() != null) {
for (Locator<URL> next : configuration.getLocators()) {
urls.addAll(next.locate());
}
}
if (configuration.getClassLoaders() == null) {
classpathResolver = new ClasspathResolver(urls);
} else {
classpathResolver = new ClasspathResolver(urls, configuration.getClassLoaders());
}
}
public Scanner(final String prefix, final Filter<?>...s) {
this((Object) prefix,s);
}
public Scanner(final Object... params) {
this(ConfigurationBuilder.build(params));
}
public Scanner() {
this(new ConfigurationBuilder());
}
public <T> Class<? extends T>[] findSubTypesOf(final Class<T> type) {
@SuppressWarnings("unchecked")
Class<? extends T>[] result = (Class<? extends T>[]) jtypeToClass(classpathResolver.resolveAll(null, ClasspathProjector.SINGLETON, assembleFilters(new JElementTypeFilter(JType.class), new JTypeSubTypeOfFilter(type))));
return result;
}
public Class<?>[] findTypesAnnotatedWith(final Class<? extends Annotation> annotation) {
return jtypeToClass(classpathResolver.resolveAll(null, ClasspathProjector.SINGLETON, assembleFilters(new JElementTypeFilter(JType.class), new JTypeAnnotatedWithFilter(annotation))));
}
public Configuration getConfiguration() {
return configuration;
}
private static Class<?>[] jtypeToClass(Collection<? extends JElement> jclasses) {
List<JType> elements = new ArrayList<JType>(jclasses.size());
for (JElement next : jclasses) {
if (!(next instanceof JType)) {
throw new IllegalStateException("Only JType can be converted to classes");
} else {
elements.add((JType)next);
}
}
return jtypeToClass(elements.toArray(new JType[]{}));
}
private static Class<?>[] jtypeToClass(JType... jclasses) {
Class<?>[] classes = new Class[jclasses.length];
for (int i=0; i<jclasses.length; i++) {
Class<?> actualClass = (Class<?>) jclasses[i].getActualClass();
classes[i] = actualClass;
}
return classes;
}
private Filter<?>[] assembleFilters(Filter<?>... searchFilters) {
Filter<?>[] filters = new Filter<?>[configuration.getFilters().size() + searchFilters.length];
for (int i = 0; i < configuration.getFilters().size(); i++) {
filters[i] = configuration.getFilters().get(0);
}
for (int i = 0; i < searchFilters.length; i++) {
filters[configuration.getFilters().size() + i] = searchFilters[i];
}
return filters;
}
}