From d3a931ab36d0ed7fc8d0dc04e56e6fd4acc18514 Mon Sep 17 00:00:00 2001 From: nathan Date: Sun, 28 Jun 2015 00:07:01 +0200 Subject: [PATCH] Added intellij support. Compiled as java6 --- Annotations.iml | 4 +- .../util/annotation/AnnotationDefaults.java | 27 +- .../util/annotation/AnnotationDetector.java | 270 ++++++++++-------- src/dorkbox/util/annotation/Builder.java | 15 +- .../util/annotation/ClassFileBuffer.java | 98 ++++--- .../util/annotation/ClassFileIterator.java | 55 ++-- .../util/annotation/ClassIterator.java | 7 +- src/dorkbox/util/annotation/Cursor.java | 3 +- .../annotation/CustomClassloaderIterator.java | 27 +- src/dorkbox/util/annotation/FileIterator.java | 22 +- src/dorkbox/util/annotation/Reporter.java | 9 +- .../util/annotation/ReporterFunction.java | 6 +- .../util/annotation/ZipFileIterator.java | 20 +- 13 files changed, 319 insertions(+), 244 deletions(-) diff --git a/Annotations.iml b/Annotations.iml index 11aa443..73b7023 100644 --- a/Annotations.iml +++ b/Annotations.iml @@ -7,13 +7,13 @@ - + - + diff --git a/src/dorkbox/util/annotation/AnnotationDefaults.java b/src/dorkbox/util/annotation/AnnotationDefaults.java index 5a5c713..ad2dc15 100644 --- a/src/dorkbox/util/annotation/AnnotationDefaults.java +++ b/src/dorkbox/util/annotation/AnnotationDefaults.java @@ -24,52 +24,61 @@ import java.lang.reflect.Method; /** * for specifying the default report methods, without constantly creating new objects */ -public class AnnotationDefaults { +public +class AnnotationDefaults { public static final ReporterFunction getTypeName = new ReporterFunction() { @Override - public String report(Cursor cursor) { + public + String report(Cursor cursor) { return cursor.getTypeName(); } }; public static final ReporterFunction> getAnnotationType = new ReporterFunction>() { @Override - public Class report(Cursor cursor) { + public + Class report(Cursor cursor) { return cursor.getAnnotationType(); } }; public static final ReporterFunction getElementType = new ReporterFunction() { @Override - public ElementType report(Cursor cursor) { + public + ElementType report(Cursor cursor) { return cursor.getElementType(); } }; public static final ReporterFunction getMemberName = new ReporterFunction() { @Override - public String report(Cursor cursor) { + public + String report(Cursor cursor) { return cursor.getMemberName(); } }; public static final ReporterFunction> getType = new ReporterFunction>() { @Override - public Class report(Cursor cursor) { + public + Class report(Cursor cursor) { return cursor.getType(); } }; public static final ReporterFunction> getConstructor = new ReporterFunction>() { @Override - public Constructor report(Cursor cursor) { + public + Constructor report(Cursor cursor) { return cursor.getConstructor(); } }; public static final ReporterFunction getField = new ReporterFunction() { @Override - public Field report(Cursor cursor) { + public + Field report(Cursor cursor) { return cursor.getField(); } }; public static final ReporterFunction getMethod = new ReporterFunction() { @Override - public Method report(Cursor cursor) { + public + Method report(Cursor cursor) { return cursor.getMethod(); } }; diff --git a/src/dorkbox/util/annotation/AnnotationDetector.java b/src/dorkbox/util/annotation/AnnotationDetector.java index 8509331..e326926 100644 --- a/src/dorkbox/util/annotation/AnnotationDetector.java +++ b/src/dorkbox/util/annotation/AnnotationDetector.java @@ -21,11 +21,9 @@ */ package dorkbox.util.annotation; -import java.io.DataInput; -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; +import org.slf4j.LoggerFactory; + +import java.io.*; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.reflect.AnnotatedElement; @@ -35,29 +33,18 @@ import java.lang.reflect.Method; import java.net.JarURLConnection; import java.net.URISyntaxException; import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.EnumSet; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.slf4j.LoggerFactory; +import java.util.*; /** * {@code AnnotationDetector} reads Java Class Files ("*.class") and reports the * found annotations via a simple, developer friendly API. - *

+ *

* A Java Class File consists of a stream of 8-bit bytes. All 16-bit, 32-bit, and 64-bit * quantities are constructed by reading in two, four, and eight consecutive 8-bit * bytes, respectively. Multi byte data items are always stored in big-endian order, * where the high bytes come first. In the Java platforms, this format is * supported by interfaces {@link java.io.DataInput} and {@link java.io.DataOutput}. - *

+ *

* A class file consists of a single ClassFile structure: *

  * ClassFile {
@@ -97,7 +84,7 @@ import org.slf4j.LoggerFactory;
  * 
  • scanning java annotations at * runtime. * - *

    + *

    * Similar projects / libraries: *

      *
    • JBoss MC Scanning lib; @@ -108,18 +95,19 @@ import org.slf4j.LoggerFactory; * Available from maven: {@code tv.cntt:annovention:1.2}; *
    • If using the Spring Framework, use {@code ClassPathScanningCandidateComponentProvider} *
    - *

    + *

    * All above mentioned projects make use of a byte code manipulation library (like BCEL, * ASM or Javassist). * * @author Ronald K. Muller * @since annotation-detector 3.0.0 */ -public final class AnnotationDetector implements Builder, Cursor { +public final +class AnnotationDetector implements Builder, Cursor { private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(AnnotationDetector.class); - // Constant Pool type tags + // Constant Pool type ta gs private static final int CP_UTF8 = 1; private static final int CP_INTEGER = 3; private static final int CP_FLOAT = 4; @@ -180,18 +168,20 @@ public final class AnnotationDetector implements Builder, Cursor { // "(Ljava/lang/String;II)I" String, int, int as arguments, return type int private String methodDescriptor; - private AnnotationDetector(ClassLoader loader, final File[] filesOrDirectories, ClassIterator iterator, final String[] pkgNameFilter) { + private + AnnotationDetector(ClassLoader loader, final File[] filesOrDirectories, ClassIterator iterator, final String[] pkgNameFilter) { this.loader = loader; if (iterator == null) { this.cfIterator = new ClassFileIterator(filesOrDirectories, pkgNameFilter); if (filesOrDirectories.length == 0) { LOG.warn("No files or directories to scan!"); - } else if (LOG.isTraceEnabled()) { - LOG.trace("Files and root directories scanned:\n{}", - Arrays.toString(filesOrDirectories).replace(", ", "\n")); } - } else { + else if (LOG.isTraceEnabled()) { + LOG.trace("Files and root directories scanned:\n{}", Arrays.toString(filesOrDirectories).replace(", ", "\n")); + } + } + else { this.cfIterator = iterator; if (LOG.isTraceEnabled()) { @@ -206,8 +196,8 @@ public final class AnnotationDetector implements Builder, Cursor { * Only scan Class Files in the specified packages. If nothing is specified, all classes * on the class path are scanned. */ - public static Builder scanClassPath(final String... packageNames) - throws IOException { + public static + Builder scanClassPath(final String... packageNames) throws IOException { final ClassLoader loader = Thread.currentThread().getContextClassLoader(); return scanClassPath(loader, packageNames); @@ -218,8 +208,8 @@ public final class AnnotationDetector implements Builder, Cursor { * Only scan Class Files in the specified packages. If nothing is specified, all classes * on the class path are scanned. */ - public static Builder scanClassPath(ClassLoader loader, final String... packageNames) - throws IOException { + public static + Builder scanClassPath(ClassLoader loader, final String... packageNames) throws IOException { final String[] pkgNameFilter; @@ -259,7 +249,8 @@ public final class AnnotationDetector implements Builder, Cursor { } return new AnnotationDetector(loader, null, new CustomClassloaderIterator(fileNames, packageNames), pkgNameFilter); - } else { + } + else { final Set files = new HashSet(); if (packageNames.length == 0) { @@ -268,7 +259,8 @@ public final class AnnotationDetector implements Builder, Cursor { for (int i = 0; i < fileNames.length; ++i) { files.add(new File(fileNames[i])); } - } else { + } + else { pkgNameFilter = new String[packageNames.length]; for (int i = 0; i < pkgNameFilter.length; ++i) { pkgNameFilter[i] = packageNames[i].replace('.', '/'); @@ -288,7 +280,8 @@ public final class AnnotationDetector implements Builder, Cursor { * Factory method, starting point for the fluent interface. * Scan all files specified by the classFileIterator. */ - public static Builder scan(ClassLoader loader, final ClassIterator iterator) { + public static + Builder scan(ClassLoader loader, final ClassIterator iterator) { return new AnnotationDetector(loader, null, iterator, null); } @@ -296,7 +289,8 @@ public final class AnnotationDetector implements Builder, Cursor { * Factory method, starting point for the fluent interface. * Scan all files in the specified jar files and directories. */ - public static Builder scanFiles(ClassLoader loader, final File... filesOrDirectories) { + public static + Builder scanFiles(ClassLoader loader, final File... filesOrDirectories) { return new AnnotationDetector(loader, filesOrDirectories, null, null); } @@ -304,7 +298,8 @@ public final class AnnotationDetector implements Builder, Cursor { * Factory method, starting point for the fluent interface. * Scan all files in the specified jar files and directories. */ - public static Builder scanFiles(final File... filesOrDirectories) { + public static + Builder scanFiles(final File... filesOrDirectories) { return new AnnotationDetector(Thread.currentThread().getContextClassLoader(), filesOrDirectories, null, null); } @@ -312,7 +307,8 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Builder#forAnnotations(java.lang.Class...) }. */ @Override - public Builder forAnnotations(final Class annotation) { + public + Builder forAnnotations(final Class annotation) { this.annotations = new HashMap>(1); // map "raw" type names to Class object this.annotations.put("L" + annotation.getName().replace('.', '/') + ";", annotation); @@ -324,7 +320,8 @@ public final class AnnotationDetector implements Builder, Cursor { */ @SuppressWarnings("unchecked") @Override - public Builder forAnnotations(final Class... annotations) { + public + Builder forAnnotations(final Class... annotations) { this.annotations = new HashMap>(annotations.length); // map "raw" type names to Class object for (int i = 0; i < annotations.length; ++i) { @@ -337,7 +334,8 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Builder#on(java.lang.annotation.ElementType...) }. */ @Override - public Builder on(final ElementType type) { + public + Builder on(final ElementType type) { if (type == null) { throw new IllegalArgumentException("At least one Element Type must be specified"); } @@ -359,7 +357,8 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Builder#on(java.lang.annotation.ElementType...) }. */ @Override - public Builder on(final ElementType... types) { + public + Builder on(final ElementType... types) { if (types.length == 0) { throw new IllegalArgumentException("At least one Element Type must be specified"); } @@ -383,7 +382,8 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Builder#filter(java.io.FilenameFilter) }. */ @Override - public Builder filter(final FilenameFilter filter) { + public + Builder filter(final FilenameFilter filter) { if (filter == null) { throw new NullPointerException("'filter' may not be null"); } @@ -395,7 +395,8 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Builder#report(dorkbox.util.annotation.AnnotationDetector.Reporter) }. */ @Override - public void report(final Reporter reporter) throws IOException { + public + void report(final Reporter reporter) throws IOException { this.reporter = reporter; detect(this.cfIterator); } @@ -404,12 +405,14 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Builder#collect(dorkbox.util.annotation.AnnotationDetector.ReporterFunction) }. */ @Override - public List collect(final ReporterFunction reporter) throws IOException { + public + List collect(final ReporterFunction reporter) throws IOException { final List list = new ArrayList(); this.reporter = new Reporter() { @Override - public void report(Cursor cursor) { + public + void report(Cursor cursor) { list.add(reporter.report(cursor)); } @@ -422,7 +425,8 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Cursor#getTypeName() }. */ @Override - public String getTypeName() { + public + String getTypeName() { return this.typeName.replace('/', '.'); } @@ -430,7 +434,8 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Cursor#getAnnotationType() }. */ @Override - public Class getAnnotationType() { + public + Class getAnnotationType() { return this.annotationType; } @@ -438,7 +443,8 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Cursor#getElementType() }. */ @Override - public ElementType getElementType() { + public + ElementType getElementType() { return this.elementType; } @@ -446,7 +452,8 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Cursor#getMemberName() }. */ @Override - public String getMemberName() { + public + String getMemberName() { return this.memberName; } @@ -454,7 +461,8 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Cursor#getType() }. */ @Override - public Class getType() { + public + Class getType() { return loadClass(this.loader, getTypeName()); } @@ -462,16 +470,15 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Cursor#getField() }. */ @Override - public Field getField() { + public + Field getField() { if (this.elementType != ElementType.FIELD) { - throw new IllegalStateException( - "Illegal to call getField() when " + this.elementType + " is reported"); + throw new IllegalStateException("Illegal to call getField() when " + this.elementType + " is reported"); } try { return getType().getDeclaredField(this.memberName); } catch (NoSuchFieldException ex) { - throw assertionError( - "Cannot find Field '%s' for type %s", this.memberName, getTypeName()); + throw assertionError("Cannot find Field '%s' for type %s", this.memberName, getTypeName()); } } @@ -479,17 +486,16 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Cursor#getConstructor() }. */ @Override - public Constructor getConstructor() { + public + Constructor getConstructor() { if (this.elementType != ElementType.CONSTRUCTOR) { - throw new IllegalStateException( - "Illegal to call getMethod() when " + this.elementType + " is reported"); + throw new IllegalStateException("Illegal to call getMethod() when " + this.elementType + " is reported"); } try { final Class[] parameterTypes = parseArguments(this.methodDescriptor); return getType().getConstructor(parameterTypes); } catch (NoSuchMethodException ex) { - throw assertionError( - "Cannot find Contructor '%s(...)' for type %s", this.memberName, getTypeName()); + throw assertionError("Cannot find Contructor '%s(...)' for type %s", this.memberName, getTypeName()); } } @@ -497,17 +503,16 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Cursor#getMethod() }. */ @Override - public Method getMethod() { + public + Method getMethod() { if (this.elementType != ElementType.METHOD) { - throw new IllegalStateException( - "Illegal to call getMethod() when " + this.elementType + " is reported"); + throw new IllegalStateException("Illegal to call getMethod() when " + this.elementType + " is reported"); } try { final Class[] parameterTypes = parseArguments(this.methodDescriptor); return getType().getDeclaredMethod(this.memberName, parameterTypes); } catch (NoSuchMethodException ex) { - throw assertionError( - "Cannot find Method '%s(...)' for type %s", this.memberName, getTypeName()); + throw assertionError("Cannot find Method '%s(...)' for type %s", this.memberName, getTypeName()); } } @@ -515,10 +520,11 @@ public final class AnnotationDetector implements Builder, Cursor { * See {@link Cursor#getAnnotation(java.lang.Class) }. */ @Override - public T getAnnotation(final Class annotationClass) { + public + T getAnnotation(final Class annotationClass) { if (!annotationClass.equals(this.annotationType)) { throw new IllegalStateException("Illegal to call getAnnotation() when " + - this.annotationType.getName() + " is reported"); + this.annotationType.getName() + " is reported"); } final AnnotatedElement ae; switch (this.elementType) { @@ -539,8 +545,8 @@ public final class AnnotationDetector implements Builder, Cursor { // private - private static void addFiles(ClassLoader loader, String resourceName, Set files) - throws IOException { + private static + void addFiles(ClassLoader loader, String resourceName, Set files) throws IOException { final Enumeration resourceEnum = loader.getResources(resourceName); while (resourceEnum.hasMoreElements()) { @@ -557,7 +563,8 @@ public final class AnnotationDetector implements Builder, Cursor { final File dir = toFile(url); if (dir.isDirectory()) { files.add(dir); - } else if (isVfs) { + } + else if (isVfs) { //Jar file via JBoss VFS protocol - strip package name String jarPath = dir.getPath(); final int idx = jarPath.indexOf(".jar"); @@ -568,23 +575,26 @@ public final class AnnotationDetector implements Builder, Cursor { files.add(jarFile); } } - } else { + } + else { throw assertionError("Not a recognized file URL: %s", url); } - } else { + } + else { // Resource in Jar File - final File jarFile = - toFile(((JarURLConnection)url.openConnection()).getJarFileURL()); + final File jarFile = toFile(((JarURLConnection) url.openConnection()).getJarFileURL()); if (jarFile.isFile()) { files.add(jarFile); - } else { + } + else { throw assertionError("Not a File: %s", jarFile); } } } } - private static File toFile(final URL url) throws IOException { + private static + File toFile(final URL url) throws IOException { // only correct way to convert the URL to a File object, also see issue #16 // Do not use URLDecoder try { @@ -594,7 +604,8 @@ public final class AnnotationDetector implements Builder, Cursor { } } - private void detect(final ClassIterator iterator) throws IOException { + private + void detect(final ClassIterator iterator) throws IOException { InputStream stream; boolean mustEndInClass = iterator instanceof ClassFileIterator; while ((stream = iterator.next(this.filter)) != null) { @@ -620,14 +631,16 @@ public final class AnnotationDetector implements Builder, Cursor { } } - private boolean hasCafebabe(final ClassFileBuffer buffer) throws IOException { - return buffer.size() > 4 && buffer.readInt() == 0xCAFEBABE; + private + boolean hasCafebabe(final ClassFileBuffer buffer) throws IOException { + return buffer.size() > 4 && buffer.readInt() == 0xCAFEBABE; } /** * Inspect the given (Java) class file in streaming mode. */ - private void read(final DataInput di) throws IOException { + private + void read(final DataInput di) throws IOException { readVersion(di); readConstantPoolEntries(di); readAccessFlags(di); @@ -639,18 +652,21 @@ public final class AnnotationDetector implements Builder, Cursor { readAttributes(di, ElementType.TYPE); } - private void readVersion(final DataInput di) throws IOException { + private + void readVersion(final DataInput di) throws IOException { // sequence: minor version, major version (argument_index is 1-based) if (LOG.isTraceEnabled()) { int minor = di.readUnsignedShort(); int maj = di.readUnsignedShort(); LOG.trace("Java Class version {}.{}", maj, minor); - } else { + } + else { di.skipBytes(4); } } - private void readConstantPoolEntries(final DataInput di) throws IOException { + private + void readConstantPoolEntries(final DataInput di) throws IOException { final int count = di.readUnsignedShort(); this.constantPool = new Object[count]; for (int i = 1; i < count; ++i) { @@ -664,8 +680,8 @@ public final class AnnotationDetector implements Builder, Cursor { /** * Return {@code true} if a double slot is read (in case of Double or Long constant). */ - private boolean readConstantPoolEntry(final DataInput di, final int index) - throws IOException { + private + boolean readConstantPoolEntry(final DataInput di, final int index) throws IOException { final int tag = di.readUnsignedByte(); switch (tag) { @@ -697,29 +713,33 @@ public final class AnnotationDetector implements Builder, Cursor { this.constantPool[index] = di.readUnsignedShort(); return false; default: - throw new ClassFormatError( - "Unkown tag value for constant pool entry: " + tag); + throw new ClassFormatError("Unkown tag value for constant pool entry: " + tag); } } - private void readAccessFlags(final DataInput di) throws IOException { + private + void readAccessFlags(final DataInput di) throws IOException { di.skipBytes(2); // u2 } - private void readThisClass(final DataInput di) throws IOException { + private + void readThisClass(final DataInput di) throws IOException { this.typeName = resolveUtf8(di); } - private void readSuperClass(final DataInput di) throws IOException { + private + void readSuperClass(final DataInput di) throws IOException { di.skipBytes(2); // u2 } - private void readInterfaces(final DataInput di) throws IOException { + private + void readInterfaces(final DataInput di) throws IOException { final int count = di.readUnsignedShort(); di.skipBytes(count * 2); // count * u2 } - private void readFields(final DataInput di) throws IOException { + private + void readFields(final DataInput di) throws IOException { final int count = di.readUnsignedShort(); for (int i = 0; i < count; ++i) { readAccessFlags(di); @@ -732,7 +752,8 @@ public final class AnnotationDetector implements Builder, Cursor { } } - private void readMethods(final DataInput di) throws IOException { + private + void readMethods(final DataInput di) throws IOException { final int count = di.readUnsignedShort(); for (int i = 0; i < count; ++i) { readAccessFlags(di); @@ -743,28 +764,28 @@ public final class AnnotationDetector implements Builder, Cursor { } } - private void readAttributes(final DataInput di, final ElementType reporterType) - throws IOException { + private + void readAttributes(final DataInput di, final ElementType reporterType) throws IOException { final int count = di.readUnsignedShort(); for (int i = 0; i < count; ++i) { final String name = resolveUtf8(di); // in bytes, use this to skip the attribute info block final int length = di.readInt(); - if (this.elementTypes.contains(reporterType) && - ("RuntimeVisibleAnnotations".equals(name) || - "RuntimeInvisibleAnnotations".equals(name))) { + if (this.elementTypes.contains(reporterType) && ("RuntimeVisibleAnnotations".equals(name) || + "RuntimeInvisibleAnnotations".equals(name))) { LOG.trace("Attribute: {}", name); readAnnotations(di, reporterType); - } else { + } + else { LOG.trace("Attribute: {} (ignored)", name); di.skipBytes(length); } } } - private void readAnnotations(final DataInput di, final ElementType elementType) - throws IOException { + private + void readAnnotations(final DataInput di, final ElementType elementType) throws IOException { // the number of Runtime(In)VisibleAnnotations final int count = di.readUnsignedShort(); @@ -775,21 +796,23 @@ public final class AnnotationDetector implements Builder, Cursor { LOG.trace("Annotation: {} (ignored)", rawTypeName); continue; } - LOG.trace("Annotation: ''{}'' on type ''{}'', member ''{}'' (reported)", - this.annotationType.getName(), getTypeName(), getMemberName()); + LOG.trace("Annotation: ''{}'' on type ''{}'', member ''{}'' (reported)", this.annotationType.getName(), getTypeName(), + getMemberName()); this.elementType = elementType; this.reporter.report(this); } } - private String readAnnotation(final DataInput di) throws IOException { + private + String readAnnotation(final DataInput di) throws IOException { final String rawTypeName = resolveUtf8(di); // num_element_value_pairs final int count = di.readUnsignedShort(); for (int i = 0; i < count; ++i) { if (LOG.isTraceEnabled()) { LOG.trace("Anntotation Element: {}", resolveUtf8(di)); - } else { + } + else { di.skipBytes(2); } readAnnotationElementValue(di); @@ -797,7 +820,8 @@ public final class AnnotationDetector implements Builder, Cursor { return rawTypeName; } - private void readAnnotationElementValue(final DataInput di) throws IOException { + private + void readAnnotationElementValue(final DataInput di) throws IOException { final int tag = di.readUnsignedByte(); switch (tag) { case BYTE: @@ -827,8 +851,7 @@ public final class AnnotationDetector implements Builder, Cursor { } break; default: - throw new ClassFormatError("Not a valid annotation element type tag: 0x" + - Integer.toHexString(tag)); + throw new ClassFormatError("Not a valid annotation element type tag: 0x" + Integer.toHexString(tag)); } } @@ -836,14 +859,16 @@ public final class AnnotationDetector implements Builder, Cursor { * Look up the String value, identified by the u2 index value from constant pool * (direct or indirect). */ - private String resolveUtf8(final DataInput di) throws IOException { + private + String resolveUtf8(final DataInput di) throws IOException { final int index = di.readUnsignedShort(); final Object value = this.constantPool[index]; final String s; if (value instanceof Integer) { - s = (String)this.constantPool[(Integer)value]; - } else { - s = (String)value; + s = (String) this.constantPool[(Integer) value]; + } + else { + s = (String) value; } return s; } @@ -854,7 +879,8 @@ public final class AnnotationDetector implements Builder, Cursor { */ // incorrect detection of dereferencing possible null pointer // TODO: https://github.com/checkstyle/checkstyle/issues/14 fixed in 5.8? - private Class[] parseArguments(final String descriptor) { + private + Class[] parseArguments(final String descriptor) { final int n = descriptor.length(); // "minimal" descriptor: no arguments: "()V", first character is always '(' if (n < 3 || descriptor.charAt(0) != '(') { @@ -866,7 +892,8 @@ public final class AnnotationDetector implements Builder, Cursor { if (i == 1) { if (c == ')') { return new Class[0]; - } else { + } + else { args = new LinkedList>(); } } @@ -929,25 +956,26 @@ public final class AnnotationDetector implements Builder, Cursor { /** * Load the class, but do not initialize it. */ - private static Class loadClass(ClassLoader loader, final String rawClassName) { + private static + Class loadClass(ClassLoader loader, final String rawClassName) { final String typeName = rawClassName.replace('/', '.'); try { return Class.forName(typeName, false, loader); } catch (ClassNotFoundException ex) { - throw assertionError( - "Cannot load type '%s', scanned file not on class path? (%s)", typeName, ex); + throw assertionError("Cannot load type '%s', scanned file not on class path? (%s)", typeName, ex); } } /** * The method descriptor must always be parseable, so if not an AssertionError is thrown. */ - private static AssertionError unparseable(final String descriptor, final String cause) { - return assertionError( - "Unparseble method descriptor: '%s' (cause: %s)", descriptor, cause); + private static + AssertionError unparseable(final String descriptor, final String cause) { + return assertionError("Unparseble method descriptor: '%s' (cause: %s)", descriptor, cause); } - private static AssertionError assertionError(String message, Object... args) { + private static + AssertionError assertionError(String message, Object... args) { return new AssertionError(String.format(message, args)); } diff --git a/src/dorkbox/util/annotation/Builder.java b/src/dorkbox/util/annotation/Builder.java index 32e4ef3..9d3a7d1 100644 --- a/src/dorkbox/util/annotation/Builder.java +++ b/src/dorkbox/util/annotation/Builder.java @@ -34,7 +34,8 @@ import java.util.List; * @author Ronald K. Muller * @since annotation-detector 3.1.0 */ -public interface Builder { +public +interface Builder { /** * Specify the annotation types to report. @@ -51,7 +52,7 @@ public interface Builder { /** * Specify the Element Types to scan. If this method is not called, * {@link ElementType#TYPE} is used as default. - *

    + *

    * Valid types are: *

      *
    • {@link ElementType#TYPE} @@ -66,7 +67,7 @@ public interface Builder { /** * Specify the Element Types to scan. If this method is not called, * {@link ElementType#TYPE} is used as default. - *

      + *

      * Valid types are: *

        *
      • {@link ElementType#TYPE} @@ -81,18 +82,18 @@ public interface Builder { /** * Filter the scanned Class Files based on its name and the directory or jar file it is * stored. - *

        + *

        * If the Class File is stored as a single file in the file system the {@code File} * argument in {@link FilenameFilter#accept(java.io.File, java.lang.String) } is the * absolute path to the root directory scanned. - *

        + *

        * If the Class File is stored in a jar file the {@code File} argument in * {@link FilenameFilter#accept(java.io.File, java.lang.String)} is the absolute path of * the jar file. - *

        + *

        * The {@code String} argument is the full name of the ClassFile in native format, * including package name, like {@code eu/infomas/annotation/AnnotationDetector$1.class}. - *

        + *

        * Note that all non-Class Files are already filtered and not seen by the filter. * * @param filter The filter, never {@code null} diff --git a/src/dorkbox/util/annotation/ClassFileBuffer.java b/src/dorkbox/util/annotation/ClassFileBuffer.java index a678a17..b2b6bef 100644 --- a/src/dorkbox/util/annotation/ClassFileBuffer.java +++ b/src/dorkbox/util/annotation/ClassFileBuffer.java @@ -21,24 +21,21 @@ */ package dorkbox.util.annotation; -import java.io.DataInput; -import java.io.DataInputStream; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; /** * {@code ClassFileBuffer} is used by {@link AnnotationDetector} to efficiently read Java * ClassFile files from an {@link InputStream} and parse the content via the {@link DataInput} * interface. - *

        + *

        * Note that Java ClassFile files can grow really big, * {@code com.sun.corba.se.impl.logging.ORBUtilSystemException} is 128.2 kb! * * @author Ronald K. Muller * @since annotation-detector 3.0.0 */ -final class ClassFileBuffer implements DataInput { +final +class ClassFileBuffer implements DataInput { private byte[] buffer; private int size; // the number of significant bytes read @@ -70,7 +67,8 @@ final class ClassFileBuffer implements DataInput { * supplied byte stream. * The read pointer is reset to the start of the byte array. */ - public void readFrom(final InputStream in) throws IOException { + public + void readFrom(final InputStream in) throws IOException { this.pointer = 0; this.size = 0; int n; @@ -87,7 +85,8 @@ final class ClassFileBuffer implements DataInput { * Sets the file-pointer offset, measured from the beginning of this file, * at which the next read or write occurs. */ - public void seek(final int position) throws IOException { + public + void seek(final int position) throws IOException { if (position < 0) { throw new IllegalArgumentException("position < 0: " + position); } @@ -100,20 +99,22 @@ final class ClassFileBuffer implements DataInput { /** * Return the size (in bytes) of this Java ClassFile file. */ - public int size() { + public + int size() { return this.size; } // DataInput @Override - public void readFully(final byte[] bytes) throws IOException { + public + void readFully(final byte[] bytes) throws IOException { readFully(bytes, 0, bytes.length); } @Override - public void readFully(final byte[] bytes, final int offset, final int length) - throws IOException { + public + void readFully(final byte[] bytes, final int offset, final int length) throws IOException { if (length < 0 || offset < 0 || offset + length > bytes.length) { throw new IndexOutOfBoundsException(); @@ -126,13 +127,15 @@ final class ClassFileBuffer implements DataInput { } @Override - public int skipBytes(final int n) throws IOException { + public + int skipBytes(final int n) throws IOException { seek(this.pointer + n); return n; } @Override - public byte readByte() throws IOException { + public + byte readByte() throws IOException { if (this.pointer >= this.size) { throw new EOFException(); } @@ -140,12 +143,14 @@ final class ClassFileBuffer implements DataInput { } @Override - public boolean readBoolean() throws IOException { + public + boolean readBoolean() throws IOException { return readByte() != 0; } @Override - public int readUnsignedByte() throws IOException { + public + int readUnsignedByte() throws IOException { if (this.pointer >= this.size) { throw new EOFException(); } @@ -153,7 +158,8 @@ final class ClassFileBuffer implements DataInput { } @Override - public int readUnsignedShort() throws IOException { + public + int readUnsignedShort() throws IOException { if (this.pointer + 2 > this.size) { throw new EOFException(); } @@ -161,48 +167,54 @@ final class ClassFileBuffer implements DataInput { } @Override - public short readShort() throws IOException { - return (short)readUnsignedShort(); + public + short readShort() throws IOException { + return (short) readUnsignedShort(); } @Override - public char readChar() throws IOException { - return (char)readUnsignedShort(); + public + char readChar() throws IOException { + return (char) readUnsignedShort(); } @Override - public int readInt() throws IOException { + public + int readInt() throws IOException { if (this.pointer + 4 > this.size) { throw new EOFException(); } return (read() << 24) + - (read() << 16) + - (read() << 8) + - read(); + (read() << 16) + + (read() << 8) + + read(); } @Override - public long readLong() throws IOException { + public + long readLong() throws IOException { if (this.pointer + 8 > this.size) { throw new EOFException(); } - return ((long)read() << 56) + - ((long)read() << 48) + - ((long)read() << 40) + - ((long)read() << 32) + - (read() << 24) + - (read() << 16) + - (read() << 8) + - read(); + return ((long) read() << 56) + + ((long) read() << 48) + + ((long) read() << 40) + + ((long) read() << 32) + + (read() << 24) + + (read() << 16) + + (read() << 8) + + read(); } @Override - public float readFloat() throws IOException { + public + float readFloat() throws IOException { return Float.intBitsToFloat(readInt()); } @Override - public double readDouble() throws IOException { + public + double readDouble() throws IOException { return Double.longBitsToDouble(readLong()); } @@ -214,22 +226,26 @@ final class ClassFileBuffer implements DataInput { */ @Override @Deprecated - public String readLine() throws IOException { + public + String readLine() throws IOException { throw new UnsupportedOperationException("readLine() is deprecated and not supported"); } @Override - public String readUTF() throws IOException { + public + String readUTF() throws IOException { return DataInputStream.readUTF(this); } // private - private int read() { + private + int read() { return this.buffer[this.pointer++] & 0xff; } - private void resizeIfNeeded() { + private + void resizeIfNeeded() { if (this.size >= this.buffer.length) { final byte[] newBuffer = new byte[this.buffer.length * 2]; System.arraycopy(this.buffer, 0, newBuffer, 0, this.buffer.length); diff --git a/src/dorkbox/util/annotation/ClassFileIterator.java b/src/dorkbox/util/annotation/ClassFileIterator.java index 5f2641b..24fc147 100644 --- a/src/dorkbox/util/annotation/ClassFileIterator.java +++ b/src/dorkbox/util/annotation/ClassFileIterator.java @@ -21,22 +21,19 @@ */ package dorkbox.util.annotation; -import java.io.File; -import java.io.FileInputStream; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; /** * {@code ClassFileIterator} is used to iterate over all Java ClassFile files available within * a specific context. - *

        + *

        * For every Java ClassFile ({@code .class}) an {@link InputStream} is returned. * * @author Ronald K. Muller * @since annotation-detector 3.0.0 */ -public class ClassFileIterator implements ClassIterator { +public +class ClassFileIterator implements ClassIterator { private FileIterator fileIter; protected final String[] pkgNameFilter; @@ -47,24 +44,26 @@ public class ClassFileIterator implements ClassIterator { /** * Create a new {@code ClassFileIterator} returning all Java ClassFile files available * from the specified files and/or directories, including sub directories. - *

        + *

        * If the (optional) package filter is defined, only class files staring with one of the * defined package names are returned. * NOTE: package names must be defined in the native format (using '/' instead of '.'). */ - protected ClassFileIterator(final String[] pkgNameFilter) { + protected + ClassFileIterator(final String[] pkgNameFilter) { this.pkgNameFilter = pkgNameFilter; } /** * Create a new {@code ClassFileIterator} returning all Java ClassFile files available * from the specified files and/or directories, including sub directories. - *

        + *

        * If the (optional) package filter is defined, only class files staring with one of the * defined package names are returned. * NOTE: package names must be defined in the native format (using '/' instead of '.'). */ - protected ClassFileIterator(final File[] filesOrDirectories, final String[] pkgNameFilter) { + protected + ClassFileIterator(final File[] filesOrDirectories, final String[] pkgNameFilter) { this.fileIter = new FileIterator(filesOrDirectories); this.pkgNameFilter = pkgNameFilter; } @@ -74,11 +73,10 @@ public class ClassFileIterator implements ClassIterator { * The name is either the path name of a file or the name of an ZIP/JAR file entry. */ @Override - public String getName() { + public + String getName() { // Both getPath() and getName() are very light weight method calls - return this.zipIter == null ? - this.fileIter.getFile().getPath() : - this.zipIter.getEntry().getName(); + return this.zipIter == null ? this.fileIter.getFile().getPath() : this.zipIter.getEntry().getName(); } /** @@ -88,37 +86,43 @@ public class ClassFileIterator implements ClassIterator { * ZIP File Entry. */ @Override - public boolean isFile() { + public + boolean isFile() { return this.isFile; } /** * Return the next Java ClassFile as an {@code InputStream}. - *

        + *

        * NOTICE: Client code MUST close the returned {@code InputStream}! */ @Override - public InputStream next(final FilenameFilter filter) throws IOException { + public + InputStream next(final FilenameFilter filter) throws IOException { while (true) { if (this.zipIter == null) { final File file = this.fileIter.next(); if (file == null) { return null; - } else { + } + else { final String path = file.getPath(); - if (path.endsWith(".class") && (filter == null || - filter.accept(this.fileIter.getRootFile(), this.fileIter.relativize(path)))) { + if (path.endsWith(".class") && (filter == null || filter.accept(this.fileIter.getRootFile(), this.fileIter.relativize( + path)))) { this.isFile = true; return new FileInputStream(file); - } else if (this.fileIter.isRootFile() && endsWithIgnoreCase(path, ".jar")) { + } + else if (this.fileIter.isRootFile() && endsWithIgnoreCase(path, ".jar")) { this.zipIter = new ZipFileIterator(file, this.pkgNameFilter); } // else just ignore } - } else { + } + else { final InputStream is = this.zipIter.next(filter); if (is == null) { this.zipIter = null; - } else { + } + else { this.isFile = false; return is; } @@ -128,7 +132,8 @@ public class ClassFileIterator implements ClassIterator { // private - private static boolean endsWithIgnoreCase(final String value, final String suffix) { + private static + boolean endsWithIgnoreCase(final String value, final String suffix) { final int n = suffix.length(); return value.regionMatches(true, value.length() - n, suffix, 0, n); } diff --git a/src/dorkbox/util/annotation/ClassIterator.java b/src/dorkbox/util/annotation/ClassIterator.java index 36aea69..ae18eb3 100644 --- a/src/dorkbox/util/annotation/ClassIterator.java +++ b/src/dorkbox/util/annotation/ClassIterator.java @@ -31,13 +31,14 @@ import java.io.InputStream; /** * {@code ClassFileIterator} is used to iterate over all Java ClassFile files available within * a specific context. - *

        + *

        * For every Java ClassFile ({@code .class}) an {@link InputStream} is returned. * * @author Ronald K. Muller * @since annotation-detector 3.0.0 */ -public interface ClassIterator { +public +interface ClassIterator { /** * Return the name of the Java ClassFile returned from the last call to {@link #next()}. @@ -55,7 +56,7 @@ public interface ClassIterator { /** * Return the next Java ClassFile as an {@code InputStream}. - *

        + *

        * NOTICE: Client code MUST close the returned {@code InputStream}! */ InputStream next(final FilenameFilter filter) throws IOException; diff --git a/src/dorkbox/util/annotation/Cursor.java b/src/dorkbox/util/annotation/Cursor.java index acaa969..48606fb 100644 --- a/src/dorkbox/util/annotation/Cursor.java +++ b/src/dorkbox/util/annotation/Cursor.java @@ -33,7 +33,8 @@ import java.lang.reflect.Method; * @author Ronald K. Muller * @since annotation-detector 3.1.0 */ -public interface Cursor { +public +interface Cursor { /** * Return the type name of the currently reported Java Class File. diff --git a/src/dorkbox/util/annotation/CustomClassloaderIterator.java b/src/dorkbox/util/annotation/CustomClassloaderIterator.java index af54ca1..e60d338 100644 --- a/src/dorkbox/util/annotation/CustomClassloaderIterator.java +++ b/src/dorkbox/util/annotation/CustomClassloaderIterator.java @@ -15,6 +15,8 @@ */ package dorkbox.util.annotation; +import dorkbox.util.FileUtil; + import java.io.File; import java.io.FilenameFilter; import java.io.IOException; @@ -26,17 +28,17 @@ import java.util.Iterator; import java.util.List; import java.util.Set; -import dorkbox.util.FileUtil; +public +class CustomClassloaderIterator implements ClassIterator { -public class CustomClassloaderIterator implements ClassIterator { - - private volatile Iterator loaderFilesIterator; + private final Iterator loaderFilesIterator; private ClassFileIterator classFileIterator; // have to support // 1 - scanning the classpath // 2 - scanning a specific package - public CustomClassloaderIterator(List fileNames, String[] packageNames) throws IOException { + public + CustomClassloaderIterator(List fileNames, String[] packageNames) throws IOException { // if ANY of our filenames DO NOT start with "box", we have to add it as a file, so our iterator picks it up (and if dir, it's childred) Set files = new HashSet(); @@ -56,7 +58,8 @@ public class CustomClassloaderIterator implements ClassIterator { if (files.isEmpty()) { this.classFileIterator = null; - } else { + } + else { this.classFileIterator = new ClassFileIterator(files.toArray(new File[0]), packageNames); } @@ -65,13 +68,15 @@ public class CustomClassloaderIterator implements ClassIterator { } @Override - public String getName() { + public + String getName() { // not needed return null; } @Override - public boolean isFile() { + public + boolean isFile() { if (this.classFileIterator != null) { return this.classFileIterator.isFile(); } @@ -80,13 +85,15 @@ public class CustomClassloaderIterator implements ClassIterator { } @Override - public InputStream next(FilenameFilter filter) throws IOException { + public + InputStream next(FilenameFilter filter) throws IOException { if (this.classFileIterator != null) { while (true) { InputStream next = this.classFileIterator.next(filter); if (next == null) { this.classFileIterator = null; - } else { + } + else { String name = this.classFileIterator.getName(); if (name.endsWith(".class")) { return next; diff --git a/src/dorkbox/util/annotation/FileIterator.java b/src/dorkbox/util/annotation/FileIterator.java index 5b5668b..380a810 100644 --- a/src/dorkbox/util/annotation/FileIterator.java +++ b/src/dorkbox/util/annotation/FileIterator.java @@ -29,7 +29,7 @@ import java.util.NoSuchElementException; /** * {@code FileIterator} enables iteration over all files in a directory and all its sub * directories. - *

        + *

        * Usage: *

          * FileIterator iter = new FileIterator(new File("./src"));
        @@ -43,7 +43,8 @@ import java.util.NoSuchElementException;
          * @author Ronald K. Muller
          * @since annotation-detector 3.0.0
          */
        -final class FileIterator {
        +final
        +class FileIterator {
         
             private final Deque stack = new LinkedList();
             private int rootCount;
        @@ -52,13 +53,13 @@ final class FileIterator {
         
             /**
              * Create a new {@code FileIterator} using the specified 'filesOrDirectories' as root.
        -     * 

        + *

        * If 'filesOrDirectories' contains a file, the iterator just returns that single file. * If 'filesOrDirectories' contains a directory, all files in that directory * and its sub directories are returned (depth first). * * @param filesOrDirectories Zero or more {@link File} objects, which are iterated - * in the specified order (depth first) + * in the specified order (depth first) */ FileIterator(final File... filesOrDirectories) { addReverse(filesOrDirectories); @@ -80,12 +81,12 @@ final class FileIterator { /** * Relativize the absolute full (file) 'path' against the current root file. - *

        + *

        * Example:
        * Let current root be "/path/to/dir". * Then {@code relativize("/path/to/dir/with/file.ext")} equals "with/file.ext" (without * leading '/'). - *

        + *

        * Note: the paths are not canonicalized! */ String relativize(final String path) { @@ -115,7 +116,8 @@ final class FileIterator { if (this.stack.isEmpty()) { this.current = null; return null; - } else { + } + else { this.current = this.stack.removeLast(); if (this.current.isDirectory()) { if (this.stack.size() < this.rootCount) { @@ -124,7 +126,8 @@ final class FileIterator { } addReverse(this.current.listFiles()); return next(); - } else { + } + else { return this.current; } } @@ -135,7 +138,8 @@ final class FileIterator { /** * Add the specified files in reverse order. */ - private void addReverse(final File[] files) { + private + void addReverse(final File[] files) { for (int i = files.length - 1; i >= 0; --i) { this.stack.add(files[i]); } diff --git a/src/dorkbox/util/annotation/Reporter.java b/src/dorkbox/util/annotation/Reporter.java index a737b74..e7715de 100644 --- a/src/dorkbox/util/annotation/Reporter.java +++ b/src/dorkbox/util/annotation/Reporter.java @@ -24,22 +24,21 @@ package dorkbox.util.annotation; /** * {@code Reporter} is used to report the detected annotations. - *

        + *

        * This interface is a so called "Single Abstract Method" (SAM) or "Functional Interface", so * can be used as a Lambda in Java 8 (see examples). * - * @see Builder#report(dorkbox.util.annotation.Reporter) - * * @author Ronald K. Muller + * @see Builder#report(dorkbox.util.annotation.Reporter) * @since annotation-detector 3.1.0 */ -public interface Reporter { +public +interface Reporter { /** * This method is called when an {@code Annotation} is detected. Invoke methods on the * provided {@code Cursor} reference to get more specific information about the * {@code Annotation}. - * */ void report(Cursor cursor); diff --git a/src/dorkbox/util/annotation/ReporterFunction.java b/src/dorkbox/util/annotation/ReporterFunction.java index 5261fdc..de41955 100644 --- a/src/dorkbox/util/annotation/ReporterFunction.java +++ b/src/dorkbox/util/annotation/ReporterFunction.java @@ -24,12 +24,12 @@ package dorkbox.util.annotation; /** * {@code ReporterFunction} is used to report the detected annotations. * - * @see Builder#collect(dorkbox.util.annotation.ReporterFunction) - * * @author Ronald K. Muller + * @see Builder#collect(dorkbox.util.annotation.ReporterFunction) * @since annotation-detector 3.1.0 */ -public interface ReporterFunction { +public +interface ReporterFunction { /** * This method is called when an {@code Annotation} is detected. diff --git a/src/dorkbox/util/annotation/ZipFileIterator.java b/src/dorkbox/util/annotation/ZipFileIterator.java index 98eccbc..9bb355e 100644 --- a/src/dorkbox/util/annotation/ZipFileIterator.java +++ b/src/dorkbox/util/annotation/ZipFileIterator.java @@ -32,15 +32,16 @@ import java.util.zip.ZipFile; /** * {@code ZipFileIterator} is used to iterate over all entries in a given {@code zip} or * {@code jar} file and returning the {@link InputStream} of these entries. - *

        + *

        * It is possible to specify an (optional) entry name filter. - *

        + *

        * The most efficient way of iterating is used, see benchmark in test classes. * * @author Ronald K. Muller * @since annotation-detector 3.0.0 */ -final class ZipFileIterator { +final +class ZipFileIterator { private final File file; private final ZipFile zipFile; @@ -52,9 +53,9 @@ final class ZipFileIterator { /** * Create a new {@code ZipFileIterator} instance. * - * @param zipFile The ZIP file used to iterate over all entries + * @param zipFile The ZIP file used to iterate over all entries * @param entryNameFilter (optional) file name filter. Only entry names starting with - * one of the specified names in the filter are returned + * one of the specified names in the filter are returned */ ZipFileIterator(final File file, final String[] entryNameFilter) throws IOException { this.file = file; @@ -64,11 +65,13 @@ final class ZipFileIterator { this.entries = this.zipFile.entries(); } - public ZipEntry getEntry() { + public + ZipEntry getEntry() { return this.current; } - public InputStream next(final FilenameFilter filter) throws IOException { + public + InputStream next(final FilenameFilter filter) throws IOException { while (this.entries.hasMoreElements()) { this.current = this.entries.nextElement(); if (filter == null || accept(this.current, filter)) { @@ -85,7 +88,8 @@ final class ZipFileIterator { return null; } - private boolean accept(final ZipEntry entry, final FilenameFilter filter) { + private + boolean accept(final ZipEntry entry, final FilenameFilter filter) { if (entry.isDirectory()) { return false; }