package act.util; /*- * #%L * ACT Framework * %% * Copyright (C) 2014 - 2017 ActFramework * %% * 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. * #L% */ import act.app.App; import act.app.AppByteCodeScanner; import act.app.AppByteCodeScannerBase; import act.app.AppSourceCodeScanner; import org.osgl.$; import org.osgl.util.C; import org.osgl.util.E; import java.lang.annotation.Annotation; import java.util.Map; import java.util.Set; public abstract class AnnotatedTypeFinder extends AppCodeScannerPluginBase { private $.Func2<App, String, Map<Class<? extends AppByteCodeScanner>, Set<String>>> foundHandler; private Class<? extends Annotation> annoType; private boolean noAbstract; private boolean publicOnly; private App app; protected Set<String> foundClasses = C.newSet(); protected AnnotatedTypeFinder(boolean publicOnly, boolean noAbstract, Class<? extends Annotation> annoType, $.Func2<App, String, Map<Class<? extends AppByteCodeScanner>, Set<String>>> foundHandler) { E.NPE(annoType); this.annoType = annoType; this.foundHandler = foundHandler; this.noAbstract = noAbstract; this.publicOnly = publicOnly; } protected AnnotatedTypeFinder(Class<? extends Annotation> annoType, $.Func2<App, String, Map<Class<? extends AppByteCodeScanner>, Set<String>>> foundHandler) { this(true, true, annoType, foundHandler); } protected AnnotatedTypeFinder(Class<? extends Annotation> annoType) { this(true, true, annoType, null); } protected App app() { return app; } @Override public AppSourceCodeScanner createAppSourceCodeScanner(App app) { return null; } @Override public AppByteCodeScanner createAppByteCodeScanner(App app) { this.app = app; return new ByteCodeSensor(); } @Override public boolean load() { return true; } private class ByteCodeSensor extends AppByteCodeScannerBase { private ClassDetector detector; private $.Func2<App, String, Map<Class<? extends AppByteCodeScanner>, Set<String>>> foundHandler = AnnotatedTypeFinder.this.foundHandler; @Override protected void reset(String className) { super.reset(className); detector = ClassDetector.of(new AnnotatedClassFilter(publicOnly, noAbstract, annoType) { @Override public void found(Class clazz) { } }); } @Override public ByteCodeVisitor byteCodeVisitor() { return detector; } @Override public void scanFinished(String className) { if (detector.found()) { foundClasses.add(className); Map<Class<? extends AppByteCodeScanner>, Set<String>> dependencies = null == foundHandler ? null : foundHandler.apply(app(), className); if (null != dependencies && !dependencies.isEmpty()) { for (Class<? extends AppByteCodeScanner> c : dependencies.keySet()) { addDependencyClassToScanner(c, dependencies.get(c)); } } } } @Override protected boolean shouldScan(String className) { return true; } @Override public int hashCode() { return $.hc(detector, ByteCodeSensor.class); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj instanceof ByteCodeSensor) { ByteCodeSensor that = (ByteCodeSensor)obj; return $.eq(that.detector, this.detector) && $.eq(that.foundHandler, this.foundHandler); } return false; } } }