use of org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor in project drill by apache.
the class TestClassPathScanner method test.
@Test
public void test() throws Exception {
ScanResult result = ClassPathScanner.fromPrescan(DrillConfig.create());
// if the build has run properly. BuildTimeScan.REGISTRY_FILE was created with a prescan
// assertListEqualsUnordered(result.getPrescannedPackages(),
// "org.apache.drill.common.logical",
// "org.apache.drill.exec.expr",
// "org.apache.drill.exec.physical.base",
// "org.apache.drill.exec.expr.fn.impl",
// "org.apache.drill.exec.physical.impl",
// "org.apache.drill.exec.rpc.user.security",
// "org.apache.drill.exec.store",
// "org.apache.drill.exec.store.mock",
// "org.apache.drill.exec.physical.config",
// "org.apache.drill.storage"
// );
// // this is added in the unit test folder that was not scanned so far
// assertListEqualsUnordered(result.getScannedPackages(),
// "org.apache.drill.exec.testing",
// "org.apache.drill.exec.fn.impl.testing",
// "org.apache.drill.exec.rpc.user.security.testing"
// );
List<AnnotatedClassDescriptor> functions = result.getAnnotatedClasses();
Set<String> scanned = new HashSet<>();
AnnotatedClassDescriptor functionRandomBigIntGauss = null;
for (AnnotatedClassDescriptor function : functions) {
assertTrue(function.getClassName() + " scanned twice", scanned.add(function.getClassName()));
if (function.getClassName().equals(RandomBigIntGauss.class.getName())) {
functionRandomBigIntGauss = function;
}
}
if (functionRandomBigIntGauss == null) {
Assert.fail("functionRandomBigIntGauss not found");
}
// TODO: use Andrew's randomized test framework to verify a subset of the functions
for (AnnotatedClassDescriptor function : functions) {
Class<?> c = Class.forName(function.getClassName(), false, this.getClass().getClassLoader());
Field[] fields = c.getDeclaredFields();
assertEquals("fields count for " + function, fields.length, function.getFields().size());
for (int i = 0; i < fields.length; i++) {
FieldDescriptor fieldDescriptor = function.getFields().get(i);
Field field = fields[i];
assertEquals("Class fields:\n" + Arrays.toString(fields) + "\n != \nDescriptor fields:\n" + function.getFields(), field.getName(), fieldDescriptor.getName());
verifyAnnotations(field.getDeclaredAnnotations(), fieldDescriptor.getAnnotations());
assertEquals(field.getType(), fieldDescriptor.getFieldClass());
}
Annotation[] annotations = c.getDeclaredAnnotations();
List<AnnotationDescriptor> scannedAnnotations = function.getAnnotations();
verifyAnnotations(annotations, scannedAnnotations);
FunctionTemplate bytecodeAnnotation = function.getAnnotationProxy(FunctionTemplate.class);
FunctionTemplate reflectionAnnotation = c.getAnnotation(FunctionTemplate.class);
assertEquals(reflectionAnnotation.name(), bytecodeAnnotation.name());
assertArrayEquals(reflectionAnnotation.names(), bytecodeAnnotation.names());
assertEquals(reflectionAnnotation.scope(), bytecodeAnnotation.scope());
assertEquals(reflectionAnnotation.nulls(), bytecodeAnnotation.nulls());
assertEquals(reflectionAnnotation.isBinaryCommutative(), bytecodeAnnotation.isBinaryCommutative());
assertEquals(reflectionAnnotation.desc(), bytecodeAnnotation.desc());
assertEquals(reflectionAnnotation.costCategory(), bytecodeAnnotation.costCategory());
}
for (String baseType : result.getScannedClasses()) {
validateType(result, baseType);
}
assertTrue(result.getImplementations(PhysicalOperator.class).size() > 0);
assertTrue(result.getImplementations(DrillFunc.class).size() > 0);
}
use of org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor in project drill by apache.
the class ClassPathScanner method scan.
/**
*
* @param pathsToScan the locations to scan for .class files
* @param packagePrefixes the whitelist of package prefixes to scan
* @param parentResult if there was a prescan, its result
* @return the merged scan
*/
static ScanResult scan(Collection<URL> pathsToScan, Collection<String> packagePrefixes, Collection<String> scannedClasses, Collection<String> scannedAnnotations, ScanResult parentResult) {
Stopwatch watch = Stopwatch.createStarted();
try {
AnnotationScanner annotationScanner = new AnnotationScanner(scannedAnnotations);
SubTypesScanner subTypesScanner = new SubTypesScanner(parentResult.getImplementations());
if (packagePrefixes.size() > 0) {
final FilterBuilder filter = new FilterBuilder();
for (String prefix : packagePrefixes) {
filter.include(FilterBuilder.prefix(prefix));
}
ConfigurationBuilder conf = new ConfigurationBuilder().setUrls(pathsToScan).setMetadataAdapter(// Scanners depend on this
METADATA_ADAPTER).filterInputsBy(filter).setScanners(annotationScanner, subTypesScanner);
// scans stuff, but don't use the funky storage layer
new Reflections(conf);
}
List<ParentClassDescriptor> implementations = new ArrayList<>();
for (String baseTypeName : scannedClasses) {
implementations.add(new ParentClassDescriptor(baseTypeName, new ArrayList<>(subTypesScanner.getChildrenOf(baseTypeName))));
}
List<AnnotatedClassDescriptor> annotated = annotationScanner.getAnnotatedClasses();
verifyClassUnicity(annotated, pathsToScan);
return new ScanResult(packagePrefixes, scannedClasses, scannedAnnotations, annotated, implementations);
} finally {
logger.info(format("Scanning packages %s in locations %s took %dms", packagePrefixes, pathsToScan, watch.elapsed(MILLISECONDS)));
}
}
use of org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor in project drill by apache.
the class LocalFunctionRegistry method validate.
/**
* Validates all functions, present in jars.
* Will throw {@link FunctionValidationException} if:
* <ol>
* <li>Jar with the same name has been already registered.</li>
* <li>Conflicting function with the similar signature is found.</li>
* <li>Aggregating function is not deterministic.</li>
*</ol>
* @param jarName jar name to be validated
* @param scanResult scan of all classes present in jar
* @return list of validated function signatures
*/
public List<String> validate(String jarName, ScanResult scanResult) {
List<String> functions = Lists.newArrayList();
FunctionConverter converter = new FunctionConverter();
List<AnnotatedClassDescriptor> providerClasses = scanResult.getAnnotatedClasses();
if (registryHolder.containsJar(jarName)) {
throw new JarValidationException(String.format("Jar with %s name has been already registered", jarName));
}
final ListMultimap<String, String> allFuncWithSignatures = registryHolder.getAllFunctionsWithSignatures();
for (AnnotatedClassDescriptor func : providerClasses) {
DrillFuncHolder holder = converter.getHolder(func, ClassLoader.getSystemClassLoader());
if (holder != null) {
String functionInput = holder.getInputParameters();
String[] names = holder.getRegisteredNames();
for (String name : names) {
String functionName = name.toLowerCase();
String functionSignature = String.format(functionSignaturePattern, functionName, functionInput);
if (allFuncWithSignatures.get(functionName).contains(functionSignature)) {
throw new FunctionValidationException(String.format("Found duplicated function in %s: %s", registryHolder.getJarNameByFunctionSignature(functionName, functionSignature), functionSignature));
} else if (holder.isAggregating() && !holder.isDeterministic()) {
throw new FunctionValidationException(String.format("Aggregate functions must be deterministic: %s", func.getClassName()));
} else {
functions.add(functionSignature);
allFuncWithSignatures.put(functionName, functionSignature);
}
}
} else {
logger.warn("Unable to initialize function for class {}", func.getClassName());
}
}
return functions;
}
use of org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor in project drill by apache.
the class LocalFunctionRegistry method register.
/**
* Registers all functions present in jar and updates registry version.
* If jar name is already registered, all jar related functions will be overridden.
* To prevent classpath collisions during loading and unloading jars,
* each jar is shipped with its own class loader.
*
* @param jars list of jars to be registered
* @param version remote function registry version number with which local function registry is synced
*/
public void register(List<JarScan> jars, long version) {
Map<String, List<FunctionHolder>> newJars = Maps.newHashMap();
for (JarScan jarScan : jars) {
FunctionConverter converter = new FunctionConverter();
List<AnnotatedClassDescriptor> providerClasses = jarScan.getScanResult().getAnnotatedClasses();
List<FunctionHolder> functions = Lists.newArrayList();
newJars.put(jarScan.getJarName(), functions);
for (AnnotatedClassDescriptor func : providerClasses) {
DrillFuncHolder holder = converter.getHolder(func, jarScan.getClassLoader());
if (holder != null) {
String functionInput = holder.getInputParameters();
String[] names = holder.getRegisteredNames();
for (String name : names) {
String functionName = name.toLowerCase();
String functionSignature = String.format(functionSignaturePattern, functionName, functionInput);
functions.add(new FunctionHolder(functionName, functionSignature, holder));
}
}
}
}
registryHolder.addJars(newJars, version);
}
Aggregations