data) {
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(type.getClassLoader().loadClass(a.name).asSubclass(Annotation.class), a.values);
} else if (o instanceof SerTypeConst) {
return type.getClassLoader().loadClass(((SerTypeConst) o).name);
} else if (o instanceof SerEnumConst) {
SerEnumConst e = (SerEnumConst) o;
return type.getClassLoader().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-1.9/sezpoz/src/main/java/net/java/sezpoz/Indexable.java 0000664 0000000 0000000 00000005457 11572157770 0024531 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. Portions Copyright 2006-2010 Sun
* Microsystems, Inc. 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-1.9/sezpoz/src/main/java/net/java/sezpoz/impl/ 0000775 0000000 0000000 00000000000 11572157770 0022721 5 ustar 00root root 0000000 0000000 sezpoz-1.9/sezpoz/src/main/java/net/java/sezpoz/impl/Indexer5.java 0000664 0000000 0000000 00000022703 11572157770 0025253 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. Portions Copyright 2006-2010 Sun
* Microsystems, Inc. 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 com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.apt.Filer;
import com.sun.mirror.declaration.AnnotationMirror;
import com.sun.mirror.declaration.AnnotationTypeDeclaration;
import com.sun.mirror.declaration.AnnotationTypeElementDeclaration;
import com.sun.mirror.declaration.AnnotationValue;
import com.sun.mirror.declaration.Declaration;
import com.sun.mirror.declaration.EnumConstantDeclaration;
import com.sun.mirror.declaration.FieldDeclaration;
import com.sun.mirror.declaration.MethodDeclaration;
import com.sun.mirror.declaration.TypeDeclaration;
import com.sun.mirror.type.DeclaredType;
import com.sun.mirror.type.TypeMirror;
import java.io.File;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
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 net.java.sezpoz.Indexable;
/**
* Processor for indexable annotations.
*/
class Indexer5 implements AnnotationProcessor {
private final AnnotationProcessorEnvironment env;
/** map from indexable annotation names, to actual uses */
private final Map> output;
public Indexer5(Set ignore, AnnotationProcessorEnvironment env) {
this.env = env;
output = new HashMap>();
}
public void process() {
// XXX how does getSpecifiedTypeDeclarations differ?
for (TypeDeclaration decl : env.getTypeDeclarations()) {
analyze(decl);
for (MethodDeclaration m : decl.getMethods()) {
analyze(m);
}
for (FieldDeclaration f : decl.getFields()) {
analyze(f);
}
}
for (Map.Entry> outputEntry : output.entrySet()) {
String annName = outputEntry.getKey();
try {
OutputStream os = env.getFiler().createBinaryFile(Filer.Location.CLASS_TREE, "",
new File("META-INF" + File.separator + "annotations" + File.separator + annName));
try {
ObjectOutputStream oos = new ObjectOutputStream(os);
for (SerAnnotatedElement el : outputEntry.getValue()) {
oos.writeObject(el);
}
oos.writeObject(null);
oos.flush();
} finally {
os.close();
}
} catch (IOException x) {
env.getMessager().printError(x.toString());
}
}
}
private void analyze(Declaration decl) {
for (AnnotationMirror ann : decl.getAnnotationMirrors()) {
// First check to see if it is an @Indexable annotation.
boolean indexable = false;
TypeMirror objType = null; // upper type bound on annotated elements, or null for Object.class
for (AnnotationMirror metaAnn : ann.getAnnotationType().getDeclaration().getAnnotationMirrors()) {
if (getQualifiedNameUsingShell(metaAnn.getAnnotationType().getDeclaration()).equals(Indexable.class.getName())) {
// Yes it is. Now just find the type=... if there is one:
Map values = metaAnn.getElementValues();
if (!values.isEmpty()) {
AnnotationValue val = values.values().iterator().next();
objType = (TypeMirror) val.getValue();
}
indexable = true;
break;
}
}
if (!indexable) {
continue;
}
// XXX check that it is not @Inherited, and that it has the right @Target
// XXX check that decl is public
// XXX check that decl is static if a method, etc.
// XXX check that decl is assignable to objType if that is not null
String annName = getQualifiedNameUsingShell(ann.getAnnotationType().getDeclaration());
List existingOutput = output.get(annName);
if (existingOutput == null) {
existingOutput = new ArrayList();
output.put(annName, existingOutput);
}
existingOutput.add(makeSerAnnotatedElement(decl, ann.getElementValues()));
}
}
/**
* Similar to {@link TypeDeclaration#getQualifiedName} but uses p.O$I rather than p.O.I.
* In JDK 6 could use Elements.getBinaryName.
*/
static String getQualifiedNameUsingShell(TypeDeclaration decl) {
TypeDeclaration outer = decl.getDeclaringType();
if (outer != null) {
return getQualifiedNameUsingShell(outer) + '$' + decl.getSimpleName();
} else {
return decl.getQualifiedName();
}
}
private SerAnnotatedElement makeSerAnnotatedElement(Declaration decl, Map annvalues) {
String className, memberName;
boolean isMethod;
if (decl instanceof TypeDeclaration) {
className = getQualifiedNameUsingShell((TypeDeclaration) decl);
memberName = null;
isMethod = false;
} else if (decl instanceof MethodDeclaration) {
MethodDeclaration _decl = (MethodDeclaration) decl;
className = getQualifiedNameUsingShell(_decl.getDeclaringType());
memberName = _decl.getSimpleName();
isMethod = true;
} else {
FieldDeclaration _decl = (FieldDeclaration) decl;
className = getQualifiedNameUsingShell(_decl.getDeclaringType());
memberName = _decl.getSimpleName();
isMethod = false;
}
return new SerAnnotatedElement(className, memberName, isMethod, translate(annvalues));
}
private static TreeMap translate(Map annvalues) {
TreeMap values = new TreeMap();
for (Map.Entry entry : annvalues.entrySet()) {
String key = entry.getKey().getSimpleName();
AnnotationValue val = entry.getValue();
values.put(key, translate(val.getValue()));
}
return values;
}
private static Object translate(Object annval) {
if (annval instanceof Collection) {
@SuppressWarnings("unchecked")
Collection annvals = (Collection) annval;
List