data) {
this.loader = loader;
this.type = type;
this.data = data;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if (name.equals("annotationType") && method.getParameterTypes().length == 0) {
return type;
} else if (name.equals("hashCode") && method.getParameterTypes().length == 0) {
// See Annotation#hashCode for explanation of algorithm.
int x = 0;
for (Method m : type.getDeclaredMethods()) {
Object val = annCall(m);
int valhash = val.hashCode();
Class> arrClazz;
if (val instanceof Object[]) {
arrClazz = Object[].class;
} else {
arrClazz = val.getClass();
}
try {
Method arraysHashCode = Arrays.class.getMethod("hashCode", arrClazz);
valhash = (Integer) arraysHashCode.invoke(null, val);
} catch (NoSuchMethodException nsme) {
// fine, not an array object
}
x += (127 * m.getName().hashCode()) ^ valhash;
}
return x;
} else if (name.equals("equals") && method.getParameterTypes().length == 1 && method.getParameterTypes()[0] == Object.class) {
// All annotation values have to be equal (even if defaulted).
if (!(args[0] instanceof Annotation)) {
return false;
}
Annotation o = (Annotation) args[0];
if (type != o.annotationType()) {
return false;
}
for (Method m : type.getDeclaredMethods()) {
Object myval = annCall(m);
Object other = m.invoke(o);
Class> arrClazz;
if (myval instanceof Object[]) {
arrClazz = Object[].class;
} else {
arrClazz = myval.getClass();
}
try {
Method arraysEquals = Arrays.class.getMethod("equals", arrClazz, arrClazz);
if (!((Boolean) arraysEquals.invoke(null, myval, other))) {
return false;
}
} catch (NoSuchMethodException nsme) {
// fine, not an array object
if (!myval.equals(other)) {
return false;
}
}
}
return true;
} else if (name.equals("toString") && method.getParameterTypes().length == 0) {
// No firm contract, just for debugging.
return "@" + type.getName() + data;
} else {
// Anything else is presumed to be one of the annotation methods.
return annCall(method);
}
}
/**
* Invoke an annotation method.
*/
private Object annCall(Method m) throws Exception {
assert m.getParameterTypes().length == 0;
String name = m.getName();
if (data.containsKey(name)) {
return evaluate(data.get(name), m.getReturnType());
} else {
Object o = m.getDefaultValue();
assert o != null;
return o;
}
}
/**
* Unwrap a value to a live type.
*/
private Object evaluate(Object o, Class> expectedType) throws Exception {
if (o instanceof SerAnnConst) {
SerAnnConst a = (SerAnnConst) o;
return proxy(loader, loader.loadClass(a.name).asSubclass(Annotation.class), a.values);
} else if (o instanceof SerTypeConst) {
return loader.loadClass(((SerTypeConst) o).name);
} else if (o instanceof SerEnumConst) {
SerEnumConst e = (SerEnumConst) o;
return loader.loadClass(e.enumName).getField(e.constName).get(null);
} else if (o instanceof ArrayList>) {
List> l = (List>) o;
Class> compType = expectedType.getComponentType();
int size = l.size();
Object arr = Array.newInstance(compType, size);
for (int i = 0; i < size; i++) {
Array.set(arr, i, evaluate(l.get(i), compType));
}
return arr;
} else {
return o;
}
}
}
}
sezpoz-pom-1.10/sezpoz/src/main/java/net/java/sezpoz/Indexable.java 0000664 0000000 0000000 00000005443 12506606152 0025354 0 ustar 00root root 0000000 0000000 /*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License ("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file. This particular file is subject to the "Classpath"
* exception as provided in the GPL Version 2 section of the License file
* that accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* The Original Software is SezPoz. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Copyright 2006-2011 Oracle
* Corporation. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package net.java.sezpoz;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marker for an annotation type which can be indexed.
* You can then use {@link Index} to find all annotated elements
* together with the annotations without necessarily loading any
* classes.
*
* The annotation may use any {@link java.lang.annotation.RetentionPolicy}
* and must permit targets of type {@link java.lang.annotation.ElementType#TYPE},
* {@link java.lang.annotation.ElementType#METHOD}, or {@link java.lang.annotation.ElementType#FIELD}
* (but no others). It should not be {@link java.lang.annotation.Inherited}.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE})
public @interface Indexable {
/**
* Optional indication of a type to which the resolved instance
* must be assignable.
* @return the type of instance
*/
Class> type() default Object.class;
}
sezpoz-pom-1.10/sezpoz/src/main/java/net/java/sezpoz/impl/ 0000775 0000000 0000000 00000000000 12506606152 0023551 5 ustar 00root root 0000000 0000000 sezpoz-pom-1.10/sezpoz/src/main/java/net/java/sezpoz/impl/Indexer6.java 0000664 0000000 0000000 00000042617 12506606152 0026112 0 ustar 00root root 0000000 0000000 /*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License ("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file. This particular file is subject to the "Classpath"
* exception as provided in the GPL Version 2 section of the License file
* that accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* The Original Software is SezPoz. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Copyright 2006-2011 Oracle
* Corporation. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package net.java.sezpoz.impl;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.tools.Diagnostic.Kind;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import net.java.sezpoz.Indexable;
import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
/**
* Processor for indexable annotations.
*/
@IgnoreJRERequirement
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("*")
@SupportedOptions("sezpoz.quiet")
public class Indexer6 extends AbstractProcessor {
/** public for ServiceLoader */
public Indexer6() {}
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
// TODO we should not write until processingOver
return false;
}
for (Element indexable : roundEnv.getElementsAnnotatedWith(Indexable.class)) {
String error = verifyIndexable(indexable);
if (error != null) {
processingEnv.getMessager().printMessage(Kind.ERROR, error, indexable);
} else {
Retention retention = indexable.getAnnotation(Retention.class);
if (retention == null || retention.value() != RetentionPolicy.SOURCE) {
processingEnv.getMessager().printMessage(Kind.WARNING, "should be marked @Retention(RetentionPolicy.SOURCE)", indexable);
}
}
}
// map from indexable annotation names, to actual uses
Map> output = new HashMap>();
Map> originatingElementsByAnn = new HashMap>();
scan(annotations, originatingElementsByAnn, roundEnv, output);
write(output, originatingElementsByAnn);
return false;
}
private void scan(Set extends TypeElement> annotations, Map> originatingElementsByAnn,
RoundEnvironment roundEnv, Map> output) {
for (TypeElement ann : annotations) {
AnnotationMirror indexable = null;
for (AnnotationMirror _indexable : processingEnv.getElementUtils().getAllAnnotationMirrors(ann)) {
if (processingEnv.getElementUtils().getBinaryName((TypeElement) _indexable.getAnnotationType().asElement()).
contentEquals(Indexable.class.getName())) {
indexable = _indexable;
break;
}
}
if (indexable == null) {
continue;
}
String annName = processingEnv.getElementUtils().getBinaryName(ann).toString();
Collection originatingElements = originatingElementsByAnn.get(annName);
if (originatingElements == null) {
originatingElements = new ArrayList();
originatingElementsByAnn.put(annName, originatingElements);
}
for (Element elt : roundEnv.getElementsAnnotatedWith(ann)) {
AnnotationMirror marked = null;
for (AnnotationMirror _marked : elt.getAnnotationMirrors()) {
if (processingEnv.getElementUtils().getBinaryName((TypeElement) _marked.getAnnotationType().asElement()).contentEquals(annName)) {
marked = _marked;
break;
}
}
if (marked == null) {
continue;
}
String error = verify(elt, indexable);
if (error != null) {
processingEnv.getMessager().printMessage(Kind.ERROR, error, elt, marked);
continue;
}
originatingElements.add(elt);
List existingOutput = output.get(annName);
if (existingOutput == null) {
existingOutput = new ArrayList();
output.put(annName, existingOutput);
}
SerAnnotatedElement ser = makeSerAnnotatedElement(elt, ann);
if (!Boolean.parseBoolean(processingEnv.getOptions().get("sezpoz.quiet"))) {
processingEnv.getMessager().printMessage(Kind.NOTE, ser.className.replace('$', '.') +
(ser.memberName != null ? "." + ser.memberName : "") +
" indexed under " + annName.replace('$', '.'));
}
existingOutput.add(ser);
}
}
}
private void write(Map> output, Map> originatingElementsByAnn) {
for (Map.Entry> outputEntry : output.entrySet()) {
String annName = outputEntry.getKey();
try {
List elements = outputEntry.getValue();
try {
FileObject in = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", "META-INF/annotations/" + annName);
// Read existing annotations, for incremental compilation.
InputStream is = in.openInputStream();
try {
ObjectInputStream ois = new ObjectInputStream(is);
while (true) {
SerAnnotatedElement el;
try {
el = (SerAnnotatedElement) ois.readObject();
} catch (ClassNotFoundException cnfe) {
throw new IOException(cnfe.toString());
}
if (el == null) {
break;
}
elements.add(el);
}
} finally {
is.close();
}
} catch (FileNotFoundException x) {
// OK, created for the first time
}
FileObject out = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT,
"", "META-INF/annotations/" + annName,
originatingElementsByAnn.get(annName).toArray(new Element[0]));
OutputStream os = out.openOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(os);
for (SerAnnotatedElement el : elements) {
oos.writeObject(el);
}
oos.writeObject(null);
oos.flush();
} finally {
os.close();
}
} catch (IOException x) {
processingEnv.getMessager().printMessage(Kind.ERROR, x.toString());
}
}
}
private SerAnnotatedElement makeSerAnnotatedElement(Element elt, TypeElement ann) {
String className, memberName;
boolean isMethod;
switch (elt.getKind()) {
case CLASS:
className = processingEnv.getElementUtils().getBinaryName((TypeElement) elt).toString();
memberName = null;
isMethod = false;
break;
case METHOD:
className = processingEnv.getElementUtils().getBinaryName((TypeElement) elt.getEnclosingElement()).toString();
memberName = elt.getSimpleName().toString();
isMethod = true;
break;
case FIELD:
className = processingEnv.getElementUtils().getBinaryName((TypeElement) elt.getEnclosingElement()).toString();
memberName = elt.getSimpleName().toString();
isMethod = false;
break;
default:
throw new AssertionError(elt.getKind());
}
return new SerAnnotatedElement(className, memberName, isMethod, translate(elt.getAnnotationMirrors(), ann));
}
private TreeMap translate(List extends AnnotationMirror> mirrors, TypeElement ann) {
TreeMap values = new TreeMap();
for (AnnotationMirror mirror : mirrors) {
if (processingEnv.getTypeUtils().isSameType(mirror.getAnnotationType(), ann.asType())) {
for (Map.Entry extends ExecutableElement,? extends AnnotationValue> entry : mirror.getElementValues().entrySet()) {
values.put(entry.getKey().getSimpleName().toString(), translate(entry.getValue().getValue()));
}
}
}
return values;
}
private Object translate(Object annval) {
if (annval instanceof List) {
@SuppressWarnings("unchecked")
List extends AnnotationValue> annvals = (List) annval;
List values = new ArrayList(annvals.size());
for (AnnotationValue v : annvals) {
values.add(translate(v.getValue()));
}
return values;
} else if (annval instanceof TypeMirror) {
return new SerTypeConst(processingEnv.getElementUtils().getBinaryName(
(TypeElement) processingEnv.getTypeUtils().asElement((TypeMirror) annval)).toString());
} else if (annval instanceof VariableElement) {
VariableElement elt = (VariableElement) annval;
return new SerEnumConst(processingEnv.getElementUtils().getBinaryName(
(TypeElement) elt.getEnclosingElement()).toString(), elt.getSimpleName().toString());
} else if (annval instanceof AnnotationMirror) {
AnnotationMirror am = (AnnotationMirror) annval;
TreeMap values = new TreeMap();
for (Map.Entry extends ExecutableElement,? extends AnnotationValue> entry : am.getElementValues().entrySet()) {
values.put(entry.getKey().getSimpleName().toString(), translate(entry.getValue().getValue()));
}
return new SerAnnConst(am.getAnnotationType().toString(), values);// XXX or use asElement?
} else {
return annval;
}
}
/**
* Checks metadata of a proposed registration.
* @param registration a class, method, or field
* @param annotation an indexable annotation applied to {@code registration}
* @param indexable {@link Indexable} annotation on that annotation
* @return an error message, or null if it is valid
*/
private String verify(Element registration, AnnotationMirror indexable) {
if (!registration.getModifiers().contains(Modifier.PUBLIC)) {
return "annotated elements must be public";
}
TypeMirror supertype = processingEnv.getElementUtils().getTypeElement("java.lang.Object").asType();
for (Map.Entry extends ExecutableElement,? extends AnnotationValue> entry : indexable.getElementValues().entrySet()) {
if (!entry.getKey().getSimpleName().contentEquals("type")) {
continue;
}
supertype = (TypeMirror) entry.getValue().getValue();
}
TypeMirror thistype;
switch (registration.getKind()) {
case CLASS:
if (registration.getModifiers().contains(Modifier.ABSTRACT)) {
return "annotated classes must not be abstract";
}
boolean hasDefaultCtor = false;
for (ExecutableElement constructor : ElementFilter.constructorsIn(registration.getEnclosedElements())) {
if (constructor.getModifiers().contains(Modifier.PUBLIC) && constructor.getParameters().isEmpty()) {
hasDefaultCtor = true;
break;
}
}
if (!hasDefaultCtor) {
return "annotated classes must have a public no-argument constructor";
}
Element enclosing = registration.getEnclosingElement();
if (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE && !registration.getModifiers().contains(Modifier.STATIC)) {
return "annotated nested classes must be static";
}
thistype = registration.asType();
break;
case METHOD:
if (!registration.getEnclosingElement().getModifiers().contains(Modifier.PUBLIC)) {
return "annotated methods must be contained in a public class";
}
if (!registration.getModifiers().contains(Modifier.STATIC)) {
return "annotated methods must be static";
}
if (!((ExecutableElement) registration).getParameters().isEmpty()) {
return "annotated methods must take no parameters";
}
thistype = ((ExecutableElement) registration).getReturnType();
break;
case FIELD:
if (!registration.getEnclosingElement().getModifiers().contains(Modifier.PUBLIC)) {
return "annotated fields must be contained in a public class";
}
if (!registration.getModifiers().contains(Modifier.STATIC)) {
return "annotated fields must be static";
}
if (!registration.getModifiers().contains(Modifier.FINAL)) {
return "annotated fields must be final";
}
thistype = ((VariableElement) registration).asType();
break;
default:
return "annotations must be on classes, methods, or fields";
}
if (!processingEnv.getTypeUtils().isAssignable(thistype, supertype)) {
return "not assignable to " + supertype;
}
return null;
}
private String verifyIndexable(Element indexable) {
if (indexable.getAnnotation(Inherited.class) != null) {
return "cannot be @Inherited";
}
Target target = indexable.getAnnotation(Target.class);
if (target == null) {
return "must be marked with @Target";
}
if (target.value().length == 0) {
return "must have at least one element type in @Target";
}
for (ElementType type : target.value()) {
switch (type) {
case TYPE:
case METHOD:
case FIELD:
continue;
default:
return "should not be permitted on element type " + type;
}
}
return null;
}
}
sezpoz-pom-1.10/sezpoz/src/main/java/net/java/sezpoz/impl/SerAnnConst.java 0000664 0000000 0000000 00000005331 12506606152 0026613 0 ustar 00root root 0000000 0000000 /*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License ("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file. This particular file is subject to the "Classpath"
* exception as provided in the GPL Version 2 section of the License file
* that accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* The Original Software is SezPoz. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Copyright 2006-2011 Oracle
* Corporation. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package net.java.sezpoz.impl;
import java.io.Serializable;
import java.util.TreeMap;
/**
* Representation of a nested annotation constant.
*/
public final class SerAnnConst implements Serializable {
private static final long serialVersionUID = 1L;
/** fully qualified name of annotation type */
public final String name;
/** values of annotation attrs, as in {@link #SerAnnotatedElement} */
public final TreeMap values;
SerAnnConst(String name, TreeMap values) {
this.name = name;
this.values = values;
}
public int hashCode() {
return name.hashCode();
}
public boolean equals(Object obj) {
if (!(obj instanceof SerAnnConst)) {
return false;
}
SerAnnConst o = (SerAnnConst) obj;
return name.equals(o.name) && values.equals(o.values);
}
public String toString() {
return "@" + name + values;
}
}
sezpoz-pom-1.10/sezpoz/src/main/java/net/java/sezpoz/impl/SerAnnotatedElement.java 0000664 0000000 0000000 00000007241 12506606152 0030321 0 ustar 00root root 0000000 0000000 /*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License ("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file. This particular file is subject to the "Classpath"
* exception as provided in the GPL Version 2 section of the License file
* that accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* The Original Software is SezPoz. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Copyright 2006-2011 Oracle
* Corporation. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package net.java.sezpoz.impl;
import java.io.Serializable;
import java.util.TreeMap;
/**
* Represents one annotated element (class etc.) with a particular list of values.
* One META-INF/annotations/* file is a sequence of serialized SerAnnotatedElement
* instances, terminated by a null.
*/
public final class SerAnnotatedElement implements Serializable {
private static final long serialVersionUID = 1L;
/** fully qualified name of class */
public final String className;
/** mame of method or field within class, or null for whole class */
public final String memberName;
/** true for method, false for class or field */
public final boolean isMethod;
/** values of annotation, as primitive wrappers, String's, ArrayList's (for arrays), or Ser*Const objects */
public final TreeMap values;
SerAnnotatedElement(String className, String memberName, boolean isMethod, TreeMap values) {
this.className = className;
this.memberName = memberName;
this.isMethod = isMethod;
this.values = values;
}
public int hashCode() {
return className.hashCode();
}
public boolean equals(Object obj) {
if (!(obj instanceof SerAnnotatedElement)) {
return false;
}
SerAnnotatedElement o = (SerAnnotatedElement) obj;
return className.equals(o.className) &&
((memberName == null) ? (o.memberName == null) : memberName.equals(o.memberName)) &&
isMethod == o.isMethod &&
values.equals(o.values);
}
public String toString() {
StringBuffer b = new StringBuffer(className);
if (memberName != null) {
b.append('#');
b.append(memberName);
if (isMethod) {
b.append("()");
}
}
b.append(values);
return b.toString();
}
}
sezpoz-pom-1.10/sezpoz/src/main/java/net/java/sezpoz/impl/SerEnumConst.java 0000664 0000000 0000000 00000005246 12506606152 0027010 0 ustar 00root root 0000000 0000000 /*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License ("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file. This particular file is subject to the "Classpath"
* exception as provided in the GPL Version 2 section of the License file
* that accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* The Original Software is SezPoz. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Copyright 2006-2011 Oracle
* Corporation. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package net.java.sezpoz.impl;
import java.io.Serializable;
/**
* Represents one enum constant value.
*/
public final class SerEnumConst implements Serializable {
private static final long serialVersionUID = 1L;
/** fully qualified name of enumeration type */
public final String enumName;
/** name of enumeration "field" (constant name) */
public final String constName;
SerEnumConst(String enumName, String constName) {
this.enumName = enumName;
this.constName = constName;
}
public int hashCode() {
return enumName.hashCode();
}
public boolean equals(Object obj) {
if (!(obj instanceof SerEnumConst)) {
return false;
}
SerEnumConst o = (SerEnumConst) obj;
return enumName.equals(o.enumName) && constName.equals(o.constName);
}
public String toString() {
return constName;
}
}
sezpoz-pom-1.10/sezpoz/src/main/java/net/java/sezpoz/impl/SerTypeConst.java 0000664 0000000 0000000 00000004602 12506606152 0027020 0 ustar 00root root 0000000 0000000 /*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License ("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file. This particular file is subject to the "Classpath"
* exception as provided in the GPL Version 2 section of the License file
* that accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* The Original Software is SezPoz. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Copyright 2006-2011 Oracle
* Corporation. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package net.java.sezpoz.impl;
import java.io.Serializable;
/**
* Representation of one class constant.
*/
public final class SerTypeConst implements Serializable {
private static final long serialVersionUID = 1L;
/** fully qualified name of class */
public final String name;
SerTypeConst(String name) {
this.name = name;
}
public int hashCode() {
return name.hashCode();
}
public boolean equals(Object obj) {
return obj instanceof SerTypeConst && name.equals(((SerTypeConst) obj).name);
}
public String toString() {
return name;
}
}
sezpoz-pom-1.10/sezpoz/src/main/java/net/java/sezpoz/package-info.java 0000664 0000000 0000000 00000004640 12506606152 0026003 0 ustar 00root root 0000000 0000000 /**
* Support for declaring, creating, and inspecting indices of annotated Java elements.
*
* For example, to permit registration of simple menu items, while
* making it possible to prepare a menu without loading any of them
* until they are actually selected:
*
* {@literal @}Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
* {@literal @}Retention(RetentionPolicy.SOURCE)
* {@literal @}Indexable(type=ActionListener.class)
* public {@literal @}interface MenuItem {
* String menuName();
* String itemName();
* String iconPath() default "";
* }
*
* A concrete registration might look like:
*
* {@literal @}MenuItem(menuName="File", itemName="Print", iconPath=".../print.png")
* public class PrintAction extends AbstractAction {
* public void actionPerformed(ActionEvent e) {...}
* }
*
* Alternatively:
*
* public class Actions {
* {@literal @}MenuItem(menuName="File", itemName="Print")
* public static Action print() {...}
* }
*
* or even:
*
* public class Actions {
* {@literal @}MenuItem(menuName="File", itemName="Print")
* public static final Action PRINT = ...;
* }
*
* To create the index on JDK 6, just compile your sources normally with javac.
* If using JDK 5, simply run apt instead of/in addition to javac.
* (The processor is in the same JAR as this API and should be autodetected.)
*
* Usage is then simple:
*
* for (final {@literal IndexItem} item :
* Index.load(MenuItem.class, ActionListener.class)) {
* JMenu menu = new JMenu(item.annotation().menuName());
* JMenuItem menuitem = new JMenuItem(item.annotation().itemName());
* String icon = item.annotation().iconPath();
* if (!icon.equals("")) {
* menuitem.setIcon(new ImageIcon(icon));
* }
* menuitem.addActionListener(new ActionListener() {
* public void actionPerformed(ActionEvent e) {
* try {
* item.instance().actionPerformed(e);
* } catch (InstantiationException x) {
* x.printStackTrace();
* }
* }
* });
* }
*
* If you want to see what is getting loaded and when,
* configure {@link java.util.logging} so that the logger
* named {@code net.java.sezpoz} is visible at
* {@link java.util.logging.Level#FINER} or above.
*/
package net.java.sezpoz;
sezpoz-pom-1.10/sezpoz/src/main/resources/ 0000775 0000000 0000000 00000000000 12506606152 0020640 5 ustar 00root root 0000000 0000000 sezpoz-pom-1.10/sezpoz/src/main/resources/META-INF/ 0000775 0000000 0000000 00000000000 12506606152 0022000 5 ustar 00root root 0000000 0000000 sezpoz-pom-1.10/sezpoz/src/main/resources/META-INF/services/ 0000775 0000000 0000000 00000000000 12506606152 0023623 5 ustar 00root root 0000000 0000000 sezpoz-pom-1.10/sezpoz/src/main/resources/META-INF/services/javax.annotation.processing.Processor 0000664 0000000 0000000 00000000036 12506606152 0033160 0 ustar 00root root 0000000 0000000 net.java.sezpoz.impl.Indexer6
sezpoz-pom-1.10/sezpoz/src/test/ 0000775 0000000 0000000 00000000000 12506606152 0016661 5 ustar 00root root 0000000 0000000 sezpoz-pom-1.10/sezpoz/src/test/java/ 0000775 0000000 0000000 00000000000 12506606152 0017602 5 ustar 00root root 0000000 0000000 sezpoz-pom-1.10/sezpoz/src/test/java/net/ 0000775 0000000 0000000 00000000000 12506606152 0020370 5 ustar 00root root 0000000 0000000 sezpoz-pom-1.10/sezpoz/src/test/java/net/java/ 0000775 0000000 0000000 00000000000 12506606152 0021311 5 ustar 00root root 0000000 0000000 sezpoz-pom-1.10/sezpoz/src/test/java/net/java/sezpoz/ 0000775 0000000 0000000 00000000000 12506606152 0022643 5 ustar 00root root 0000000 0000000 sezpoz-pom-1.10/sezpoz/src/test/java/net/java/sezpoz/ClassLoaderTest.java 0000664 0000000 0000000 00000011424 12506606152 0026544 0 ustar 00root root 0000000 0000000 /*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License ("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file. This particular file is subject to the "Classpath"
* exception as provided in the GPL Version 2 section of the License file
* that accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* The Original Software is SezPoz. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Copyright 2006-2011 Oracle
* Corporation. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package net.java.sezpoz;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.util.concurrent.Callable;
import net.java.sezpoz.impl.TestUtils;
import org.junit.Before;
import org.junit.Test;
/**
* Check class loader issues.
*
* @author Johannes Schindelin
*/
public class ClassLoaderTest {
private File dir, src1, clz1, src2, clz2;
private ClassLoader loader1, loader2;
@Before public void setUp() throws Exception {
dir = TestUtils.getWorkDir(this);
TestUtils.clearDir(dir);
src1 = new File(dir, "src1");
clz1 = new File(dir, "clz1");
clz1.mkdirs();
loader1 = new URLClassLoader(new URL[] {clz1.toURI().toURL()});
src2 = new File(dir, "src2");
clz2 = new File(dir, "clz2");
clz2.mkdirs();
loader2 = new URLClassLoader(new URL[] {clz2.toURI().toURL()}, loader1);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test public void differentLoaders() throws Exception {
TestUtils.makeSource(src1, "api.MyAnnotation",
"import java.lang.annotation.ElementType;",
"import java.lang.annotation.Retention;",
"import java.lang.annotation.RetentionPolicy;",
"import java.lang.annotation.Target;",
"import java.util.concurrent.Callable;",
"import net.java.sezpoz.Indexable;",
"@Retention(RetentionPolicy.RUNTIME)",
"@Target(ElementType.TYPE)",
"@Indexable(type = Callable.class)",
"public @interface MyAnnotation {",
"Class> myClass();",
"}");
TestUtils.runApt(src1, null, clz1, new File[0], null);
TestUtils.makeSource(src2, "com.example.MyExample",
"import api.MyAnnotation;",
"import java.util.concurrent.Callable;",
"@MyAnnotation(myClass = MyExample.class)",
"public class MyExample implements Callable {",
"public Object call() {",
"return \"Hello, World!\";",
"}",
"}");
TestUtils.runApt(src2, null, clz2, new File[] {clz1}, null);
final Class annotationClass = loader1.loadClass("api.MyAnnotation");
final Class exampleClass = loader2.loadClass("com.example.MyExample");
final Index index = Index.load(annotationClass, Callable.class, loader2);
Iterator it = index.iterator();
assertTrue(it.hasNext());
IndexItem item = it.next();
assertFalse(it.hasNext());
final Object annotation = item.annotation();
final Method myClassMethod = annotation.getClass().getMethod("myClass");
final Object myClass = myClassMethod.invoke(annotation);
assertEquals(myClass, exampleClass);
}
}
sezpoz-pom-1.10/sezpoz/src/test/java/net/java/sezpoz/IndexTest.java 0000664 0000000 0000000 00000046634 12506606152 0025432 0 ustar 00root root 0000000 0000000 /*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License ("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file. This particular file is subject to the "Classpath"
* exception as provided in the GPL Version 2 section of the License file
* that accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* The Original Software is SezPoz. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Copyright 2006-2011 Oracle
* Corporation. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package net.java.sezpoz;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.Arrays;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.swing.Action;
import net.java.sezpoz.impl.TestUtils;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
/**
* Check that loading of an index works.
*/
public class IndexTest {
private File dir, src, clz;
private ClassLoader loader;
@Before public void setUp() throws Exception {
dir = TestUtils.getWorkDir(this);
TestUtils.clearDir(dir);
src = new File(dir, "src");
clz = new File(dir, "clz");
clz.mkdirs();
loader = new URLClassLoader(new URL[] {clz.toURI().toURL()});
}
@SuppressWarnings("unchecked")
@Test public void basicUsage() throws Exception {
TestUtils.makeSource(src, "api.MenuItem",
"import java.lang.annotation.*;",
"@Retention(RetentionPolicy.RUNTIME)",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@net.java.sezpoz.Indexable(type=javax.swing.Action.class)",
"public @interface MenuItem {",
"String menuName();",
"String itemName();",
"String iconPath() default \"\";",
"}");
TestUtils.makeSource(src, "impl.PrintAction",
"@api.MenuItem(menuName=\"File\", itemName=\"Print\", iconPath=\".../print.png\")",
"public class PrintAction extends javax.swing.AbstractAction {",
"public void actionPerformed(java.awt.event.ActionEvent e) {}",
"}");
TestUtils.runApt(src, null, clz, new File[0], null);
Class menuItemClazz = loader.loadClass("api.MenuItem");
Index index = Index.load(menuItemClazz, Action.class, loader);
Iterator it = index.iterator();
assertTrue(it.hasNext());
IndexItem item = it.next();
assertFalse(it.hasNext());
try {
it.next();
fail();
} catch (NoSuchElementException x) {/*OK*/}
Annotation ann = item.annotation();
assertEquals(menuItemClazz, ann.annotationType());
assertEquals("File", menuItemClazz.getMethod("menuName").invoke(ann));
assertEquals("Print", menuItemClazz.getMethod("itemName").invoke(ann));
assertEquals(".../print.png", menuItemClazz.getMethod("iconPath").invoke(ann));
assertEquals("impl.PrintAction", item.className());
assertEquals(null, item.memberName());
assertEquals(ElementType.TYPE, item.kind());
Class implClazz = loader.loadClass("impl.PrintAction");
assertEquals(implClazz, item.element());
Annotation live = implClazz.getAnnotation(menuItemClazz);
assertEquals("live and proxy annotations match", ann, live);
assertEquals("live and proxy annotations match in opposite direction", live, ann);
assertEquals("proxy annotation equal to itself", ann, ann);
assertEquals("live and proxy annotations have same hash code", ann.hashCode(), live.hashCode());
assertNotSame("but live and proxy annotations are not identical", ann, live);
Object o = item.instance();
assertEquals(implClazz, o.getClass());
assertSame("caches instance", o, item.instance());
Index index2 = Index.load(menuItemClazz, Action.class, loader);
it = index2.iterator();
assertTrue(it.hasNext());
IndexItem item2 = it.next();
assertFalse(it.hasNext());
assertEquals("IndexItem.equals works naturally", item, item2);
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Indexable
public @interface Marker {
String stuff();
}
@Marker(stuff="hello")
public static class Marked1 {}
@Marker(stuff="goodbye")
public static class Marked2 {}
@Test public void staticallyKnownAnnotation() throws Exception {
TestUtils.makeSource(src, "impl.C",
"import " + Marker.class.getName().replace('$', '.') + ";",
"@Marker(stuff=\"hello\")",
"public class C {}");
TestUtils.runApt(src, null, clz, new File[] {
new File(URI.create(Marker.class.getProtectionDomain().getCodeSource().getLocation().toExternalForm()))
}, null);
int cnt = 0;
for (IndexItem item : Index.load(Marker.class, Object.class, loader)) {
cnt++;
assertEquals("impl.C", ((Class) item.element()).getName());
assertEquals("impl.C", item.instance().getClass().getName());
Marker proxy = item.annotation();
assertEquals(Marker.class, proxy.annotationType());
assertEquals("hello", proxy.stuff());
Marker real1 = Marked1.class.getAnnotation(Marker.class), real2 = Marked2.class.getAnnotation(Marker.class);
assertEquals(real1, proxy);
assertEquals(proxy, real1);
assertEquals(real1.hashCode(), proxy.hashCode());
assertFalse(real2.equals(proxy));
assertFalse(proxy.equals(real2));
}
assertEquals(1, cnt);
}
@SuppressWarnings("unchecked")
@Test public void methodsAndFields() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@net.java.sezpoz.Indexable",
"public @interface A {}");
TestUtils.makeSource(src, "y.C",
"public class C {",
"@x.A",
"public static final Object F = 1;",
"@x.A",
"public static Object m() {return 2;}",
"}");
TestUtils.runApt(src, null, clz, new File[0], null);
Class extends Annotation> a = loader.loadClass("x.A").asSubclass(Annotation.class);
int cnt = 0;
for (IndexItem item : Index.load(a, Object.class, loader)) {
cnt++;
assertEquals("y.C", item.className());
if (item.kind() == ElementType.FIELD) {
assertEquals("F", item.memberName());
assertEquals(1, item.instance());
} else {
assertEquals(ElementType.METHOD, item.kind());
assertEquals("m", item.memberName());
assertEquals(2, item.instance());
}
}
assertEquals(2, cnt);
}
@Test public void multipleCodeSources() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@net.java.sezpoz.Indexable",
"public @interface A {}");
TestUtils.makeSource(src, "y.C1",
"@x.A",
"public class C1 {}");
TestUtils.runApt(src, null, clz, new File[0], null);
File src2 = new File(dir, "src2");
TestUtils.makeSource(src2, "z.C2",
"@x.A",
"public class C2 {}");
File clz2 = new File(dir, "clz2");
clz2.mkdirs();
TestUtils.runApt(src2, null, clz2, new File[] {clz}, null);
loader = new URLClassLoader(new URL[] {clz.toURI().toURL(), clz2.toURI().toURL()});
Class extends Annotation> a = loader.loadClass("x.A").asSubclass(Annotation.class);
Iterator it = Index.load(a, Object.class, loader).iterator();
assertTrue(it.hasNext());
IndexItem item = (IndexItem) it.next();
assertEquals("y.C1", item.instance().getClass().getName());
assertTrue(it.hasNext());
item = (IndexItem) it.next();
assertEquals("z.C2", item.instance().getClass().getName());
assertFalse(it.hasNext());
try {
it.next();
fail();
} catch (NoSuchElementException x) {/*OK*/}
}
@Test public void codeSourceOverlapping() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@net.java.sezpoz.Indexable",
"public @interface A {",
"int x();",
"}");
TestUtils.makeSource(src, "y.C1",
"@x.A(x=1)",
"public class C1 {}");
TestUtils.runApt(src, null, clz, new File[0], null);
File src2 = new File(dir, "src2");
TestUtils.makeSource(src2, "y.C1",
"@x.A(x=2)",
"public class C1 {}");
File clz2 = new File(dir, "clz2");
clz2.mkdirs();
TestUtils.runApt(src2, null, clz2, new File[] {clz}, null);
loader = new URLClassLoader(new URL[] {clz.toURI().toURL(), clz2.toURI().toURL()});
Class extends Annotation> a = loader.loadClass("x.A").asSubclass(Annotation.class);
Iterator it = Index.load(a, Object.class, loader).iterator();
assertTrue(it.hasNext());
IndexItem item = (IndexItem) it.next();
assertEquals("y.C1", item.instance().getClass().getName());
assertEquals(1, a.getMethod("x").invoke(item.annotation()));
assertFalse("y.C1 only loaded once", it.hasNext());
try {
it.next();
fail();
} catch (NoSuchElementException x) {/*OK*/}
}
@Test public void heavyOverlap() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@net.java.sezpoz.Indexable",
"public @interface A {",
"int x();",
"}");
TestUtils.makeSource(src, "y.C1",
"@x.A(x=1)",
"public class C1 {}");
TestUtils.runApt(src, null, clz, new File[0], null);
URL[] urls = new URL[9]; // too slow to make this really big
for (int i = 0; i < urls.length; i++) {
urls[i] = new URL(new URL("http://" + i + ".nowhere.net/"), "", new URLStreamHandler() {
protected URLConnection openConnection(URL u) throws IOException {
URL u2 = new URL(clz.toURI().toURL(), u.getPath().substring(1));
return u2.openConnection();
}
});
}
loader = new URLClassLoader(urls);
Class extends Annotation> a = loader.loadClass("x.A").asSubclass(Annotation.class);
Iterator it = Index.load(a, Object.class, loader).iterator();
assertTrue(it.hasNext());
IndexItem item = (IndexItem) it.next();
assertEquals("y.C1", item.instance().getClass().getName());
assertEquals(1, a.getMethod("x").invoke(item.annotation()));
assertFalse("y.C1 only loaded once", it.hasNext());
try {
it.next();
fail();
} catch (NoSuchElementException x) {/*OK*/}
}
@Test public void defaultValues() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Retention(RetentionPolicy.RUNTIME)",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@net.java.sezpoz.Indexable",
"public @interface A {",
"int x() default 5;",
"}");
TestUtils.makeSource(src, "y.C",
"import x.A;",
"public class C {",
"@A",
"public static Void m1() {return null;}",
"@A(x=5)",
"public static Void m2() {return null;}",
"@A(x=17)",
"public static Void m3() {return null;}",
"}");
TestUtils.runApt(src, null, clz, new File[0], null);
Class extends Annotation> a = loader.loadClass("x.A").asSubclass(Annotation.class);
int cnt = 0;
Annotation[] proxyAnns = new Annotation[3];
Annotation[] liveAnns = new Annotation[3];
for (IndexItem item : Index.load(a, Object.class, loader)) {
cnt++;
assertEquals("y.C", item.className());
Annotation ann = item.annotation();
Method x = a.getMethod("x");
int index;
if (item.memberName().equals("m1")) {
index = 0;
assertEquals(5, x.invoke(ann));
} else if (item.memberName().equals("m2")) {
index = 1;
assertEquals(5, x.invoke(ann));
} else {
assertEquals("m3", item.memberName());
index = 2;
assertEquals(17, x.invoke(ann));
}
proxyAnns[index] = ann;
liveAnns[index] = item.element().getAnnotation(a);
assertNotNull(liveAnns[index]);
}
assertEquals(3, cnt);
Set all = new HashSet();
all.addAll(Arrays.asList(proxyAnns));
all.addAll(Arrays.asList(liveAnns));
assertEquals("all annotations are either with x=5 or x=17", 2, all.size());
Map all2 = new IdentityHashMap();
for (Annotation ann : proxyAnns) {
all2.put(ann, null);
}
for (Annotation ann : liveAnns) {
all2.put(ann, null);
}
assertEquals(6, all2.size());
}
@SuppressWarnings("unchecked")
@Test public void complexStructure() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Retention(RetentionPolicy.RUNTIME)",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@net.java.sezpoz.Indexable",
"public @interface A {",
"B b();",
"B[] bs();",
"int[] xs();",
"E e();",
"Class c();",
"class Nested {}",
"}");
TestUtils.makeSource(src, "x.B",
"import java.lang.annotation.*;",
"@Retention(RetentionPolicy.RUNTIME)",
"public @interface B {",
"int x();",
"int[] ys() default {1, 2};",
"E[] es() default {};",
"}");
TestUtils.makeSource(src, "x.E",
"public enum E {",
"CHOCOLATE, VANILLA, STRAWBERRY",
"}");
TestUtils.makeSource(src, "y.C",
"import x.*;",
"@A(",
"b=@B(x=1),",
"bs={@B(x=2), @B(x=3, ys=17, es=E.VANILLA)},",
"xs={6, 7},",
"e=E.CHOCOLATE,",
"c=A.Nested.class",
")",
"public class C {}");
TestUtils.runApt(src, null, clz, new File[0], null);
Class extends Annotation> a = loader.loadClass("x.A").asSubclass(Annotation.class);
IndexItem item = Index.load(a, Object.class, loader).iterator().next();
Class> b = loader.loadClass("x.B");
Class e = loader.loadClass("x.E");
Annotation ann = item.annotation();
// Test all structural elements:
Object bb = a.getMethod("b").invoke(ann);
assertTrue(b.isAssignableFrom(bb.getClass()));
assertEquals(1, b.getMethod("x").invoke(bb));
int[] ys = (int[]) b.getMethod("ys").invoke(bb);
assertEquals(2, ys.length);
assertEquals(1, ys[0]);
assertEquals(2, ys[1]);
Object[] es = (Object[]) b.getMethod("es").invoke(bb);
assertEquals(e, es.getClass().getComponentType());
assertEquals(0, es.length);
Object[] bs = (Object[]) a.getMethod("bs").invoke(ann);
assertEquals(b, bs.getClass().getComponentType());
assertEquals(2, bs.length);
bb = bs[0];
assertEquals(2, b.getMethod("x").invoke(bb));
bb = bs[1];
assertEquals(3, b.getMethod("x").invoke(bb));
ys = (int[]) b.getMethod("ys").invoke(bb);
assertEquals(1, ys.length);
assertEquals(17, ys[0]);
es = (Object[]) b.getMethod("es").invoke(bb);
assertEquals(e, es.getClass().getComponentType());
assertEquals(1, es.length);
assertEquals(e.getField("VANILLA").get(null), es[0]);
int[] xs = (int[]) a.getMethod("xs").invoke(ann);
assertEquals(2, xs.length);
assertEquals(6, xs[0]);
assertEquals(7, xs[1]);
assertEquals(e.getField("CHOCOLATE").get(null), a.getMethod("e").invoke(ann));
assertEquals(loader.loadClass("x.A$Nested"), a.getMethod("c").invoke(ann));
// Check also object comparisons:
Annotation live = item.element().getAnnotation(a);
assertEquals(live, ann);
assertEquals(ann, live);
assertEquals(live.hashCode(), ann.hashCode());
}
// XXX need to test:
// - verification that interface is indexable
// - verification that instance type is valid (try with Void also)
// - annotation values incl. newlines, quotes, etc.
// - element() and instance() are truly lazy
// - access permissions
// - Class constants can be loaded from different class loader than annotation
}
sezpoz-pom-1.10/sezpoz/src/test/java/net/java/sezpoz/impl/ 0000775 0000000 0000000 00000000000 12506606152 0023604 5 ustar 00root root 0000000 0000000 sezpoz-pom-1.10/sezpoz/src/test/java/net/java/sezpoz/impl/AptFailedException.java 0000664 0000000 0000000 00000004013 12506606152 0030155 0 ustar 00root root 0000000 0000000 /*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License ("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file. This particular file is subject to the "Classpath"
* exception as provided in the GPL Version 2 section of the License file
* that accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* The Original Software is SezPoz. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Copyright 2006-2011 Oracle
* Corporation. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package net.java.sezpoz.impl;
/**
* Thrown by {@link #runApt} if processing fails.
*/
public final class AptFailedException extends Exception {
AptFailedException(int res) {
super("processing failed with error code " + res);
}
}
sezpoz-pom-1.10/sezpoz/src/test/java/net/java/sezpoz/impl/Indexer6Test.java 0000664 0000000 0000000 00000030754 12506606152 0027004 0 ustar 00root root 0000000 0000000 /*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License ("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file. This particular file is subject to the "Classpath"
* exception as provided in the GPL Version 2 section of the License file
* that accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* The Original Software is SezPoz. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Copyright 2006-2011 Oracle
* Corporation. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package net.java.sezpoz.impl;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.TreeSet;
import static org.junit.Assert.*;
import org.junit.Test;
/**
* Test for JDK 6 (JSR 199) version of indexer.
*/
public class Indexer6Test extends IndexerTestBase {
@Test public void incrementalCompilation() throws Exception {
File src1 = new File(dir, "src1");
TestUtils.makeSource(src1, "Thing",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface Thing {",
"String name();",
"}");
File clz1 = new File(dir, "clz1");
TestUtils.runApt(src1, null, clz1, null, null);
File src2 = new File(dir, "src2");
TestUtils.makeSource(src2, "Impl1",
"@Thing(name=\"one\")",
"public class Impl1 {}");
File clz2 = new File(dir, "clz2");
TestUtils.runApt(src2, null, clz2, new File[] {clz1}, null);
assertEquals(Collections.singletonMap("Thing", Collections.singleton(
"Impl1{name=one}"
)), TestUtils.findMetadata(clz2));
TestUtils.makeSource(src2, "Impl2",
"@Thing(name=\"two\")",
"public class Impl2 {}");
TestUtils.runApt(src2, "Impl2", clz2, new File[] {clz1}, null);
assertEquals(Collections.singletonMap("Thing", new TreeSet(Arrays.asList(
"Impl1{name=one}",
"Impl2{name=two}"
))), TestUtils.findMetadata(clz2));
}
// XXX the following should be moved to IndexerTestBase when Indexer5 implements these things:
@Test public void nonPublic() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface A {}");
TestUtils.makeSource(src, "y.C1", "@x.A public class C1 {}");
TestUtils.makeSource(src, "y.C2", "@x.A class C2 {}");
TestUtils.runApt(src, "A|C1", clz, null, null);
TestUtils.runAptExpectingErrors(src, "A|C2", clz, null, "public");
TestUtils.makeSource(src, "y.M1", "public class M1 {@x.A public static Object m() {return null;}}");
TestUtils.makeSource(src, "y.M2", "public class M2 {@x.A static Object m() {return null;}}");
TestUtils.makeSource(src, "y.M3", "public class M3 {@x.A protected static Object m() {return null;}}");
TestUtils.makeSource(src, "y.M4", "public class M4 {@x.A private static Object m() {return null;}}");
TestUtils.makeSource(src, "y.M5", "class M1 {@x.A public static Object m() {return null;}}");
TestUtils.runApt(src, "A|M1", clz, null, null);
TestUtils.runAptExpectingErrors(src, "A|M2", clz, null, "public");
TestUtils.runAptExpectingErrors(src, "A|M3", clz, null, "public");
TestUtils.runAptExpectingErrors(src, "A|M4", clz, null, "public");
TestUtils.runAptExpectingErrors(src, "A|M5", clz, null, "public");
TestUtils.makeSource(src, "y.F1", "public class F1 {@x.A public static final Object f = null;}");
TestUtils.makeSource(src, "y.F2", "public class F2 {@x.A static final Object f = null;}");
TestUtils.makeSource(src, "y.F3", "public class F3 {@x.A private static final Object f = null;}");
TestUtils.makeSource(src, "y.F4", "class F4 {@x.A public static final Object f = null;}");
TestUtils.runApt(src, "A|F1", clz, null, null);
TestUtils.runAptExpectingErrors(src, "A|F2", clz, null, "public");
TestUtils.runAptExpectingErrors(src, "A|F3", clz, null, "public");
TestUtils.runAptExpectingErrors(src, "A|F4", clz, null, "public");
}
@Test public void inappropriateModifiersOrArgs() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface A {}");
TestUtils.makeSource(src, "y.C1", "@x.A public class C1 {}");
TestUtils.makeSource(src, "y.C2", "@x.A public abstract class C2 {}");
TestUtils.makeSource(src, "y.C3", "@x.A public class C3 {private C3() {}}");
TestUtils.makeSource(src, "y.C4", "@x.A public class C4 {public C4(int x) {}}");
TestUtils.runApt(src, "A|C1", clz, null, null);
TestUtils.runAptExpectingErrors(src, "A|C2", clz, null, "abstract");
TestUtils.runAptExpectingErrors(src, "A|C3", clz, null, "constructor");
TestUtils.runAptExpectingErrors(src, "A|C4", clz, null, "constructor");
TestUtils.makeSource(src, "y.M1", "public class M1 {@x.A public static Object m() {return null;}}");
TestUtils.makeSource(src, "y.M2", "public class M2 {@x.A public Object m() {return null;}}");
TestUtils.makeSource(src, "y.M3", "public class M3 {@x.A public static Object m(int x) {return null;}}");
TestUtils.runApt(src, "A|M1", clz, null, null);
TestUtils.runAptExpectingErrors(src, "A|M2", clz, null, "static");
TestUtils.runAptExpectingErrors(src, "A|M3", clz, null, "parameters");
TestUtils.makeSource(src, "y.F1", "public class F1 {@x.A public static final Object f = null;}");
TestUtils.makeSource(src, "y.F2", "public class F2 {@x.A public final Object f = null;}");
TestUtils.makeSource(src, "y.F3", "public class F3 {@x.A public static Object f = null;}");
TestUtils.runApt(src, "A|F1", clz, null, null);
TestUtils.runAptExpectingErrors(src, "A|F2", clz, null, "static");
TestUtils.runAptExpectingErrors(src, "A|F3", clz, null, "final");
TestUtils.makeSource(src, "y.N1", "public class N1 {@x.A public static class N {}}");
TestUtils.makeSource(src, "y.N2", "public class N2 {@x.A public class N {}}");
TestUtils.runApt(src, "A|N1", clz, null, null);
TestUtils.runAptExpectingErrors(src, "A|N2", clz, null, "static");
/* XXX 269 processors will not even see this:
TestUtils.makeSource(src, "y.N3", "public class N3 {void m() {@x.A class N {}}}");
TestUtils.runAptExpectingErrors(src, "A|N3", clz, null, "static", useJsr199());
*/
}
@Test public void incompatibleType() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable(type=Runnable.class)",
"public @interface A {}");
TestUtils.makeSource(src, "y.C1", "@x.A public class C1 implements Runnable {public void run() {}}");
TestUtils.makeSource(src, "y.C2", "@x.A public class C2 {}");
TestUtils.runApt(src, "A|C1", clz, null, null);
TestUtils.runAptExpectingErrors(src, "A|C2", clz, null, "Runnable");
TestUtils.makeSource(src, "y.M1", "public class M1 {@x.A public static Runnable m() {return null;}}");
TestUtils.makeSource(src, "y.M2", "public class M2 {@x.A public static Object m() {return null;}}");
TestUtils.makeSource(src, "y.M3", "public class M3 implements Runnable {@x.A public static M3 m() {return null;} public void run() {}}");
TestUtils.runApt(src, "A|M1", clz, null, null);
TestUtils.runAptExpectingErrors(src, "A|M2", clz, null, "Runnable");
TestUtils.runApt(src, "A|M3", clz, null, null);
TestUtils.makeSource(src, "y.F1", "public class F1 {@x.A public static final Runnable f = null;}");
TestUtils.makeSource(src, "y.F2", "public class F2 {@x.A public static final Object f = null;}");
TestUtils.makeSource(src, "y.F3", "public class F3 implements Runnable {@x.A public static final F3 f = null; public void run() {}}");
TestUtils.runApt(src, "A|F1", clz, null, null);
TestUtils.runAptExpectingErrors(src, "A|F2", clz, null, "Runnable");
TestUtils.runApt(src, "A|F3", clz, null, null);
}
@Test public void inappropriateIndexable() throws Exception {
TestUtils.makeSource(src, "x.A1",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface A1 {}");
TestUtils.runApt(src, "A1", clz, null, null);
TestUtils.makeSource(src, "x.A2",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@Inherited",
"@net.java.sezpoz.Indexable",
"public @interface A2 {}");
TestUtils.runAptExpectingErrors(src, "A2", clz, null, "@Inherited");
TestUtils.makeSource(src, "x.A3",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface A3 {}");
TestUtils.runAptExpectingErrors(src, "A3", clz, null, "CONSTRUCTOR");
TestUtils.makeSource(src, "x.A4",
"@net.java.sezpoz.Indexable",
"@Retention(RetentionPolicy.SOURCE)",
"public @interface A4 {}");
TestUtils.runAptExpectingErrors(src, "A4", clz, null, "@Target");
TestUtils.makeSource(src, "x.A5",
"import java.lang.annotation.*;",
"@Target({})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface A5 {}");
TestUtils.runAptExpectingErrors(src, "A5", clz, null, "@Target");
TestUtils.makeSource(src, "x.A6",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@net.java.sezpoz.Indexable",
"public @interface A6 {}");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
TestUtils.runApt(src, "A6", clz, null, baos);
baos.flush();
assertTrue("output warns about @Retention: " + baos, baos.toString().contains("@Retention"));
}
}
sezpoz-pom-1.10/sezpoz/src/test/java/net/java/sezpoz/impl/IndexerTestBase.java 0000664 0000000 0000000 00000027112 12506606152 0027503 0 ustar 00root root 0000000 0000000 /*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License ("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file. This particular file is subject to the "Classpath"
* exception as provided in the GPL Version 2 section of the License file
* that accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* The Original Software is SezPoz. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Copyright 2006-2011 Oracle
* Corporation. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package net.java.sezpoz.impl;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
/**
* Tries to run indexer and confirms that it serializes annotations correctly.
*/
public abstract class IndexerTestBase {
protected File dir, src, clz;
@Before public void setUp() throws Exception {
dir = TestUtils.getWorkDir(this);
TestUtils.clearDir(dir);
src = new File(dir, "src");
clz = new File(dir, "clz");
}
@Test public void basicUsage() throws Exception {
File src1 = new File(dir, "src1");
TestUtils.makeSource(src1, "api.MenuItem",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable(type=javax.swing.Action.class)",
"public @interface MenuItem {",
"String menuName();",
"String itemName();",
"String iconPath() default \"\";",
"}");
File clz1 = new File(dir, "clz1");
TestUtils.runApt(src1, null, clz1, null, null);
File src2 = new File(dir, "src2");
TestUtils.makeSource(src2, "impl.PrintAction",
"@api.MenuItem(menuName=\"File\", itemName=\"Print\", iconPath=\".../print.png\")",
"@Deprecated", // make sure this is ignored!
"public class PrintAction extends javax.swing.AbstractAction {",
"public void actionPerformed(java.awt.event.ActionEvent e) {}",
"}");
File clz2 = new File(dir, "clz2");
TestUtils.runApt(src2, null, clz2, new File[] {clz1}, null);
assertEquals(Collections.singletonMap("api.MenuItem", Collections.singleton(
"impl.PrintAction{iconPath=.../print.png, itemName=Print, menuName=File}"
)), TestUtils.findMetadata(clz2));
}
@Test public void strangeAnnStringVals() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface A {",
"String x();",
"}");
TestUtils.makeSource(src, "y.C",
"@x.A(x=\"foo\\\\\\\"\\n\")",
"public class C {}");
TestUtils.runApt(src, null, clz, null, null);
assertEquals(Collections.singletonMap("x.A", Collections.singleton(
"y.C{x=foo\\\"\n}"
)), TestUtils.findMetadata(clz));
}
@Test public void compositeVals() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface A {",
"Other other();",
"Other[] others();",
"int i();",
"boolean b();",
"char c();",
"}");
TestUtils.makeSource(src, "x.Other",
"@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)",
"public @interface Other {",
"int v();",
"}");
TestUtils.makeSource(src, "y.C",
"import x.*;",
"@A(other=@Other(v=1),others=@Other(v=2),i=3,b=true,c='x')",
"public class C {}");
TestUtils.runApt(src, null, clz, null, null);
assertEquals(Collections.singletonMap("x.A", Collections.singleton(
"y.C{b=true, c=x, i=3, other=@x.Other{v=1}, others=[@x.Other{v=2}]}"
)), TestUtils.findMetadata(clz));
}
@Test public void defaultValsNotWritten() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface A {",
"int i() default 0;",
"}");
TestUtils.makeSource(src, "x.B",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface B {",
"A[] as() default {};",
"}");
TestUtils.makeSource(src, "y.C1",
"@x.A(i=33)",
"public class C1 {}");
TestUtils.makeSource(src, "y.C2",
"@x.A()",
"public class C2 {}");
TestUtils.makeSource(src, "y.C3",
"@x.A",
"public class C3 {}");
TestUtils.makeSource(src, "y.C4",
"@x.B",
"public class C4 {}");
TestUtils.makeSource(src, "y.C5",
"import x.*;",
"@B(as={@A, @A(), @A(i=20)})",
"public class C5 {}");
TestUtils.runApt(src, null, clz, null, null);
Map> expected = new HashMap>();
expected.put("x.A", new TreeSet(Arrays.asList(new String[] {
"y.C1{i=33}",
"y.C2{}",
"y.C3{}",
})));
expected.put("x.B", new TreeSet(Arrays.asList(new String[] {
"y.C4{}",
"y.C5{as=[@x.A{}, @x.A{}, @x.A{i=20}]}"
})));
assertEquals(expected, TestUtils.findMetadata(clz));
}
@Test public void serializeExoticConstants() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface A {",
"Class clazz();",
"E[] enoom();",
"}");
TestUtils.makeSource(src, "x.E",
"public enum E {ONE, TWO}");
TestUtils.makeSource(src, "y.C",
"import x.*;",
"@A(clazz=String.class,enoom={E.ONE,E.TWO})",
"public class C {}");
TestUtils.runApt(src, null, clz, null, null);
assertEquals(Collections.singletonMap("x.A", Collections.singleton(
"y.C{clazz=java.lang.String, enoom=[ONE, TWO]}"
)), TestUtils.findMetadata(clz));
}
@Test public void methodsAndFields() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface A {",
"boolean b();",
"}");
TestUtils.makeSource(src, "y.C",
"import x.*;",
"public class C {",
"@A(b=true)",
"public static final Object F = null;",
"@A(b=false)",
"public static Object m() {return null;}",
"}");
TestUtils.runApt(src, null, clz, null, null);
assertEquals(Collections.singletonMap("x.A", new TreeSet(Arrays.asList(new String[] {
"y.C#F{b=true}",
"y.C#m(){b=false}",
}))), TestUtils.findMetadata(clz));
}
@Test public void nestedClasses() throws Exception {
TestUtils.makeSource(src, "x.Outer",
"import java.lang.annotation.*;",
"public class Outer {",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@net.java.sezpoz.Indexable",
"@Retention(RetentionPolicy.SOURCE)",
"public @interface A {",
"Class> type();",
"}",
"}");
TestUtils.makeSource(src, "y.Auter",
"public class Auter {",
"public static class T {}",
"@x.Outer.A(type=T.class)",
"public static class C {}",
"}");
TestUtils.runApt(src, null, clz, null, null);
assertEquals(Collections.singletonMap("x.Outer$A", Collections.singleton(
"y.Auter$C{type=y.Auter$T}"
)), TestUtils.findMetadata(clz));
}
/* Uncompilable anyway: "annotation value must be a class literal"
@Test public void exoticClassConstants() throws Exception {
TestUtils.makeSource(src, "x.A",
"import java.lang.annotation.*;",
"@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})",
"@Retention(RetentionPolicy.SOURCE)",
"@net.java.sezpoz.Indexable",
"public @interface A {",
"Class[] clazz();",
"}");
TestUtils.makeSource(src, "y.C",
"import x.*;",
"@A(clazz={Integer.class, Integer.TYPE})",
"public class C {}");
TestUtils.runApt(src, null, clz, null, null, useJsr199());
assertEquals(Collections.singletonMap("x.A", Collections.singleton(
"y.C{clazz=[java.lang.Integer, int]}"
)), TestUtils.findMetadata(clz));
}
*/
}
sezpoz-pom-1.10/sezpoz/src/test/java/net/java/sezpoz/impl/TestUtils.java 0000664 0000000 0000000 00000021103 12506606152 0026404 0 ustar 00root root 0000000 0000000 /*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License ("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file. This particular file is subject to the "Classpath"
* exception as provided in the GPL Version 2 section of the License file
* that accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* The Original Software is SezPoz. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Copyright 2006-2011 Oracle
* Corporation. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package net.java.sezpoz.impl;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.regex.Pattern;
import javax.tools.ToolProvider;
import net.java.sezpoz.Indexable;
import org.junit.Assert;
/**
* Common utilities used during testing.
*/
public class TestUtils {
private TestUtils() {}
public static void clearDir(File d) throws IOException {
File[] kids = d.listFiles();
if (kids != null) {
for (File kid : kids) {
if (kid.isDirectory()) {
clearDir(kid);
}
if (!kid.delete()) {
throw new IOException(kid.getAbsolutePath());
}
}
}
}
private static Map counts = new HashMap();
public static File getWorkDir(Object test) throws IOException {
File base = new File(System.getProperty("workdir", System.getProperty("java.io.tmpdir")));
String name = test.getClass().getName();
Integer count = counts.get(name);
if (count == null) {
count = 0;
}
counts.put(name, ++count);
File workdir = new File(new File(base, name), "test" + count);
if (!workdir.isDirectory() && !workdir.mkdirs()) {
throw new IOException(workdir.getAbsolutePath());
}
return workdir;
}
/**
* Run annotation processing.
* @param src a source root (runs apt on all *.java it finds)
* @param srcIncludes optional regex to limit class names to compile
* @param dest a dest dir (also compiles classes there)
* @param cp classpath entries for processor (Indexable will always be accessible), or null
* @param stderr output stream to use, or null for test console
* @throws Exception if something unexpected went wrong
*/
public static void runApt(File src, String srcIncludes, File dest, File[] cp, OutputStream stderr) throws Exception {
List args = new ArrayList();
String indexableLoc = new File(URI.create(Indexable.class.getProtectionDomain().getCodeSource().getLocation().toExternalForm())).getAbsolutePath();
args.add("-processorpath");
args.add(indexableLoc);
args.add("-classpath");
StringBuffer b = new StringBuffer(indexableLoc);
if (cp != null) {
for (File entry : cp) {
b.append(File.pathSeparatorChar);
b.append(entry.getAbsolutePath());
}
}
args.add(b.toString());
args.add("-d");
args.add(dest.getAbsolutePath());
dest.mkdirs();
args.add("-Asezpoz.quiet=true");
scan(args, src, srcIncludes);
//System.err.println("running apt with args: " + args);
String[] argsA = args.toArray(new String[args.size()]);
int res = ToolProvider.getSystemJavaCompiler().run(null, null, stderr, argsA);
if (res != 0) {
throw new AptFailedException(res);
}
}
private static void scan(List names, File f, String includes) {
if (f.isDirectory()) {
for (File kid : f.listFiles()) {
scan(names, kid, includes);
}
} else if (f.getName().endsWith(".java") && (includes == null || Pattern.compile(includes).matcher(f.getName()).find())) {
names.add(f.getAbsolutePath());
}
}
/**
* Run annotation processing and expect an error to be issued.
* @param src a source root (runs apt on all *.java it finds)
* @param srcIncludes optional regex to limit class names to compile
* @param dest a dest dir (also compiles classes there)
* @param cp classpath entries for processor (Indexable will always be accessible), or null
* @param error an error you expect to see printed (APT must also fail), else assertion failure
* @throws Exception if something unexpected went wrong
*/
public static void runAptExpectingErrors(File src, String srcIncludes, File dest, File[] cp, String error) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
runApt(src, srcIncludes, dest, cp, baos);
Assert.fail("annotation processing should have failed");
} catch (AptFailedException x) {
String log = baos.toString();
Assert.assertTrue(log, log.contains(error));
}
}
/**
* Create a source file.
* @param dir source root
* @param clazz a class name
* @param content lines of text (skip package decl)
*/
public static void makeSource(File dir, String clazz, String... content) throws IOException {
File f = new File(dir, clazz.replace('.', File.separatorChar) + ".java");
f.getParentFile().mkdirs();
Writer w = new FileWriter(f);
try {
PrintWriter pw = new PrintWriter(w);
String pkg = clazz.replaceFirst("\\.[^.]+$", "");
if (!pkg.equals(clazz)) {
pw.println("package " + pkg + ";");
}
for (String line : content) {
pw.println(line);
}
pw.flush();
} finally {
w.close();
}
}
/**
* Find contents of META-INF/annotations/* in a dest dir.
* @return map from simple file names to set of SerAnnotatedElement.toString()s
*/
public static Map> findMetadata(File dest) throws Exception {
File dir = new File(new File(dest, "META-INF"), "annotations");
if (!dir.isDirectory()) {
return Collections.emptyMap();
}
Map> metadata = new HashMap>();
for (String kid : dir.list()) {
File f = new File(dir, kid);
InputStream is = new FileInputStream(f);
try {
ObjectInputStream ois = new ObjectInputStream(is);
SortedSet entries = new TreeSet();
while (true) {
SerAnnotatedElement el = (SerAnnotatedElement) ois.readObject();
if (el == null) {
break;
}
entries.add(el.toString());
}
metadata.put(kid, entries);
} finally {
is.close();
}
}
return metadata;
}
}