blob: a8e7ed6e1f72e2ee583c9a3461692f275daefe24 [file] [log] [blame]
/* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xmlbeans.impl.jam.internal.java15;
import org.apache.xmlbeans.impl.jam.internal.reflect.Reflect15Delegate;
import org.apache.xmlbeans.impl.jam.internal.elements.ElementContext;
import org.apache.xmlbeans.impl.jam.mutable.MMember;
import org.apache.xmlbeans.impl.jam.mutable.MConstructor;
import org.apache.xmlbeans.impl.jam.mutable.MField;
import org.apache.xmlbeans.impl.jam.mutable.MClass;
import org.apache.xmlbeans.impl.jam.mutable.MParameter;
import org.apache.xmlbeans.impl.jam.mutable.MAnnotatedElement;
import org.apache.xmlbeans.impl.jam.mutable.MAnnotation;
import org.apache.xmlbeans.impl.jam.JClass;
import org.apache.xmlbeans.impl.jam.provider.JamLogger;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.InvocationTargetException;
import java.lang.annotation.Annotation;
/**
* @author Patrick Calahan <email: pcal-at-bea-dot-com>
*/
public class Reflect15DelegateImpl implements Reflect15Delegate {
// ========================================================================
// Variables
private ElementContext mContext = null;
private JamLogger mLogger = null;
// ========================================================================
// Reflect15Delegate implementation
public void init(ElementContext ctx) {
if (mContext != null) throw new IllegalStateException("init called twice");
mContext = ctx;
mLogger = mContext.getLogger();
}
public void extractAnnotations(MMember dest, Method src) {
Annotation[] anns = src.getDeclaredAnnotations();
if (anns == null) return;
extractAnnotations(dest,anns);
}
public void extractAnnotations(MConstructor dest, Constructor src) {
Annotation[] anns = src.getDeclaredAnnotations();
if (anns == null) return;
extractAnnotations(dest,anns);
}
public void extractAnnotations(MField dest, Field src) {
Annotation[] anns = src.getDeclaredAnnotations();
if (anns == null) return;
extractAnnotations(dest,anns);
}
public void extractAnnotations(MClass dest, Class src) {
Annotation[] anns = src.getDeclaredAnnotations();
if (anns == null) return;
extractAnnotations(dest,anns);
}
public void extractAnnotations(MParameter dest, Method src,
int paramNum) {
Annotation[][] anns;
try {
anns = src.getParameterAnnotations();
} catch(NullPointerException wtf) {
//FIXME workaround, sun code throws an NPE here
if (mLogger.isVerbose(this)) {
mLogger.verbose("ignoring unexpected error while calling Method.getParameterAnnotations():");
mLogger.verbose(wtf);
}
//wtf.printStackTrace();
return;
}
if (anns == null) return;
if (paramNum >= anns.length) {
if (mLogger.isVerbose(this)) {
mLogger.warning("method "+src.getName()+
" has fewer than expected parameter annotations ");
}
return;
}
extractAnnotations(dest,anns[paramNum]);
}
public void extractAnnotations(MParameter dest, Constructor src,
int paramNum) {
Annotation[][] anns;
try {
anns = src.getParameterAnnotations();
} catch(NullPointerException wtf) {
//FIXME workaround, sun code throws an NPE here
if (mLogger.isVerbose(this)) {
mLogger.verbose("ignoring unexpected error while calling Constructor.getParameterAnnotations():");
mLogger.verbose(wtf);
}
//wtf.printStackTrace();
return;
}
if (anns == null) return;
if (paramNum >= anns.length) {
if (mLogger.isVerbose(this)) {
mLogger.warning("constructor "+src.getName()+
" has fewer than expected parameter annotations ");
}
return;
}
extractAnnotations(dest,anns[paramNum]);
}
public boolean isEnum(Class clazz) { return clazz.isEnum(); }
// ========================================================================
// Private methods
private void extractAnnotations(MAnnotatedElement dest,
Annotation[] anns)
{
if (anns == null || anns.length == 0) return;
for(int i=0; i<anns.length; i++) {
MAnnotation destAnn = dest.findOrCreateAnnotation
(anns[i].annotationType().getName());
destAnn.setAnnotationInstance(anns[i]);
populateAnnotation(destAnn,anns[i]);
}
}
private void populateAnnotation(MAnnotation dest, Annotation src) {
boolean isVerbose = mLogger.isVerbose(this);
if (src == null) throw new IllegalArgumentException();
Class annType = src.annotationType();
if (isVerbose) mLogger.verbose("type is "+annType.getName());
//FIXME this is a bit clumsy right now - I think we need to be a little
// more surgical in identifying the annotation member methods
Method[] methods = annType.getMethods();
for(int i=0; i<methods.length; i++) {
if (isVerbose) mLogger.verbose("examining "+methods[i].toString());
int mods = methods[i].getModifiers();
if (Modifier.isStatic(mods)) continue;
if (!Modifier.isPublic(mods)) continue;
if (methods[i].getParameterTypes().length > 0) continue;
{
// try to limit it to real annotation methods.
// FIXME seems like this could be better
Class c = methods[i].getDeclaringClass();
if (Object.class.equals(c) || Annotation.class.equals(c)) {
continue;
}
}
try {
if (isVerbose) mLogger.verbose("invoking "+methods[i].getName()+"()");
Object value = methods[i].invoke(src,(Object[])null);
if (isVerbose) mLogger.verbose("value is "+value);
if (value instanceof Annotation) {
if (isVerbose) mLogger.verbose("it's nested!! creating for "+
methods[i].getName()+" and "+
annType.getName());
MAnnotation nested = dest.createNestedValue(methods[i].getName(),
annType.getName());
nested.setAnnotationInstance(value);
populateAnnotation(nested,(Annotation)value);
} else if (value instanceof Annotation[]) {
Annotation[] anns = (Annotation[])value;
MAnnotation[] nested = dest.createNestedValueArray
(methods[i].getName(),
methods[i].getReturnType().getComponentType().getName(),
anns.length);
for(int j=0; j<anns.length; j++) populateAnnotation(nested[j],anns[j]);
} else {
JClass type = mContext.getClassLoader().
loadClass(methods[i].getReturnType().getName());
dest.setSimpleValue(methods[i].getName(),value,type);
}
} catch (IllegalAccessException e) {
mLogger.warning(e);
} catch (InvocationTargetException e) {
mLogger.warning(e);
}
}
}
}