Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   *
   * Copyright (c) 2010-2011 Oracle and/or its affiliates. All rights reserved.
   *
   * 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://glassfish.java.net/public/CDDL+GPL_1_1.html
  * or packager/legal/LICENSE.txt.  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 and include the License file at packager/legal/LICENSE.txt.
  *
  * GPL Classpath Exception:
  * Oracle designates this particular file as subject to the "Classpath"
  * exception as provided by Oracle in the GPL Version 2 section of the License
  * file that accompanied this code.
  *
  * Modifications:
  * If applicable, add the following below the License Header, with the fields
  * enclosed by brackets [] replaced by your own identifying information:
  * "Portions Copyright [year] [name of copyright owner]"
  *
  * Contributor(s):
  * 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 don't 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 com.sun.jersey.server.impl.modelapi.annotation;
 
 import java.util.Map;

Author(s):
japod
 
 public class IntrospectionModeller {
 
     private static final Logger LOGGER = Logger.getLogger(IntrospectionModeller.class.getName());
 
     public static AbstractResource createResource(Class<?> resourceClass) {
         final Class<?> annotatedResourceClass = getAnnotatedResourceClass(resourceClass);
         final Path rPathAnnotation = annotatedResourceClass.getAnnotation(Path.class);
         final boolean isRootResourceClass = (null != rPathAnnotation);
 
         final boolean isEncodedAnotOnClass = 
                (null != annotatedResourceClass.getAnnotation(Encoded.class));
        AbstractResource resource;
        if (isRootResourceClass) {
            resource = new AbstractResource(resourceClass,
                    new PathValue(rPathAnnotation.value()));
        } else { // just a subresource class
            resource = new AbstractResource(resourceClass);
        }
        workOutConstructorsList(resourceresourceClass.getConstructors(), 
                isEncodedAnotOnClass);
        workOutFieldsList(resourceisEncodedAnotOnClass);
        
        final MethodList methodList = new MethodList(resourceClass);
        workOutSetterMethodsList(resourcemethodListisEncodedAnotOnClass);
        
        final Consumes classScopeConsumesAnnotation = 
                annotatedResourceClass.getAnnotation(Consumes.class);
        final Produces classScopeProducesAnnotation = 
                annotatedResourceClass.getAnnotation(Produces.class);
        workOutResourceMethodsList(resourcemethodListisEncodedAnotOnClass
                classScopeConsumesAnnotationclassScopeProducesAnnotation);
        workOutSubResourceMethodsList(resourcemethodListisEncodedAnotOnClass
                classScopeConsumesAnnotationclassScopeProducesAnnotation);
        workOutSubResourceLocatorsList(resourcemethodListisEncodedAnotOnClass);
        workOutPostConstructPreDestroy(resource);
        if (.isLoggable(.)) {
            .finest(ImplMessages.NEW_AR_CREATED_BY_INTROSPECTION_MODELER(
                    resource.toString()));
        }
        return resource;
    }
    
    private static Class getAnnotatedResourceClass(Class rc) {
        if (rc.isAnnotationPresent(Path.class)) return rc;
        for (Class i : rc.getInterfaces())
            if (i.isAnnotationPresent(Path.class)) return i;
        return rc;
    }
    
    private static void addConsumes(
            AnnotatedMethod am,            
            AbstractResourceMethod resourceMethod
            Consumes consumeMimeAnnotation) {
        // Override annotation is present in method
        if (am.isAnnotationPresent(Consumes.class))
            consumeMimeAnnotation = am.getAnnotation(Consumes.class);
        
        resourceMethod.setAreInputTypesDeclared(consumeMimeAnnotation != null);
        resourceMethod.getSupportedInputTypes().addAll(
                MediaTypes.createMediaTypes(consumeMimeAnnotation));
    }
    private static void addProduces(
            AnnotatedMethod am,
            AbstractResourceMethod resourceMethod
            Produces produceMimeAnnotation) {
        // Override annotation is present in method
        if (am.isAnnotationPresent(Produces.class))
            produceMimeAnnotation = am.getAnnotation(Produces.class);
        
        resourceMethod.setAreOutputTypesDeclared(produceMimeAnnotation != null);
        resourceMethod.getSupportedOutputTypes().addAll(
                MediaTypes.createQualitySourceMediaTypes(produceMimeAnnotation));
    }
    private static void workOutConstructorsList(
            AbstractResource resource
            Constructor[] ctorArray
            boolean isEncoded) {
        if (null != ctorArray) {
            for (Constructor ctor : ctorArray) {
                final AbstractResourceConstructor aCtor = 
                        new AbstractResourceConstructor(ctor);
                processParameters(
                        resource.getResourceClass(),
                        ctor.getDeclaringClass(),
                        aCtor,
                        ctor,
                        isEncoded);
                resource.getConstructors().add(aCtor);
            }
        }
    }
    private static void workOutFieldsList(
            AbstractResource resource
            boolean isEncoded) {        
        Class c = resource.getResourceClass();
        if (c.isInterface())
            return;
        
        while (c != Object.class) {
             for (final Field f : c.getDeclaredFields()) {
                if (f.getDeclaredAnnotations().length > 0) {
                    final AbstractField af = new AbstractField(f);
                    Parameter p = createParameter(
                            resource.getResourceClass(),
                            f.getDeclaringClass(),
                            isEncoded,
                            f.getType(),
                            f.getGenericType(),
                            f.getAnnotations());
                    if (null != p) {
                        af.getParameters().add(p);
                        resource.getFields().add(af);
                    }
                }
             }
             c = c.getSuperclass();
        }
    }
    private static void workOutPostConstructPreDestroy(AbstractResource resource) {
        Class postConstruct = ReflectionHelper.classForName("javax.annotation.PostConstruct");
        if (postConstruct == null)
            return;
        Class preDestroy = ReflectionHelper.classForName("javax.annotation.PreDestroy");
        final MethodList methodList = new MethodList(resource.getResourceClass(), true);
        HashSet<Stringnames = new HashSet<String>();
        for (AnnotatedMethod m : methodList.
                hasAnnotation(postConstruct).
                hasNumParams(0).
                hasReturnType(void.class)) {
            Method method = m.getMethod();
            // only add method if not hidden/overridden
            if (names.add(method.getName())) {
                ReflectionHelper.setAccessibleMethod(method);
                resource.getPostConstructMethods().add(0, method);
            }
        }
        names = new HashSet<String>();
        for (AnnotatedMethod m : methodList.
                hasAnnotation(preDestroy).
                hasNumParams(0).
                hasReturnType(void.class)) {
            Method method = m.getMethod();
            // only add method if not hidden/overridden
            if (names.add(method.getName())) {
                ReflectionHelper.setAccessibleMethod(method);
                resource.getPreDestroyMethods().add(method);
            }
        }
    }
    private static void workOutSetterMethodsList(
            AbstractResource resource
            MethodList methodList,
            boolean isEncoded) {
        for (AnnotatedMethod m : methodList.
                hasNotMetaAnnotation(HttpMethod.class).
                hasNotAnnotation(Path.class).
                hasNumParams(1).
                hasReturnType(void.class).
                nameStartsWith("set")) {
            
            final AbstractSetterMethod asm = new AbstractSetterMethod(resourcem.getMethod(), m.getAnnotations());
            Parameter p = createParameter(
                    resource.getResourceClass(),
                    m.getMethod().getDeclaringClass(),
                    isEncoded,
                    m.getParameterTypes()[0],
                    m.getGenericParameterTypes()[0],
                    m.getAnnotations());
            if (null != p) {
                asm.getParameters().add(p);
                resource.getSetterMethods().add(asm);
            }
        }        
    }
    
    private static void workOutResourceMethodsList(
            AbstractResource resource
            MethodList methodList
            boolean isEncoded,
            Consumes classScopeConsumesAnnotation
            Produces classScopeProducesAnnotation) {
        for (AnnotatedMethod m : methodList.hasMetaAnnotation(HttpMethod.class).
                hasNotAnnotation(Path.class)) {
            final ReflectionHelper.ClassTypePair ct = getGenericReturnType(resource.getResourceClass(), m.getMethod());
            final AbstractResourceMethod resourceMethod = new AbstractResourceMethod(
                    resource,
                    m.getMethod(),
                    ct.cct.t,
                    m.getMetaMethodAnnotations(HttpMethod.class).get(0).value(),
                    m.getAnnotations());
            addConsumes(mresourceMethodclassScopeConsumesAnnotation);
            addProduces(mresourceMethodclassScopeProducesAnnotation);
            processParameters(
                    resourceMethod.getResource().getResourceClass(),
                    resourceMethod.getMethod().getDeclaringClass(),
                    resourceMethodmisEncoded);
            resource.getResourceMethods().add(resourceMethod);
        }
    }
            Class concreteClass,
            Method m) {
        return getGenericType(concreteClassm.getDeclaringClass(), m.getReturnType(), m.getGenericReturnType());
    }
    
    private static void workOutSubResourceMethodsList(
            AbstractResource resource
            MethodList methodList
            boolean isEncoded,
            Consumes classScopeConsumesAnnotation
            Produces classScopeProducesAnnotation) {
        for (AnnotatedMethod m : methodList.hasMetaAnnotation(HttpMethod.class).hasAnnotation(Path.class)) {
            final Path mPathAnnotation = m.getAnnotation(Path.class);
            final PathValue pv = new PathValue(mPathAnnotation.value());
            final boolean emptySegmentCase =  "/".equals(pv.getValue()) || "".equals(pv.getValue());
            
            if (!emptySegmentCase) {
                final ReflectionHelper.ClassTypePair ct = getGenericReturnType(resource.getResourceClass(), m.getMethod());
                final AbstractSubResourceMethod abstractSubResourceMethod = new AbstractSubResourceMethod(
                        resource,
                        m.getMethod(),
                        ct.cct.t,
                        pv,
                        m.getMetaMethodAnnotations(HttpMethod.class).get(0).value(),
                        m.getAnnotations());
                addConsumes(mabstractSubResourceMethodclassScopeConsumesAnnotation);
                addProduces(mabstractSubResourceMethodclassScopeProducesAnnotation);
                processParameters(
                        abstractSubResourceMethod.getResource().getResourceClass(),
                        abstractSubResourceMethod.getMethod().getDeclaringClass(),
                        abstractSubResourceMethodmisEncoded);
                resource.getSubResourceMethods().add(abstractSubResourceMethod);
            } else { // treat the sub-resource method as a resource method
                final ReflectionHelper.ClassTypePair ct = getGenericReturnType(resource.getResourceClass(), m.getMethod());
                final AbstractResourceMethod abstractResourceMethod = new AbstractResourceMethod(
                        resource,
                        m.getMethod(),
                        ct.cct.t,
                        m.getMetaMethodAnnotations(HttpMethod.class).get(0).value(),
                        m.getAnnotations());
                addConsumes(mabstractResourceMethodclassScopeConsumesAnnotation);
                addProduces(mabstractResourceMethodclassScopeProducesAnnotation);
                processParameters(
                        abstractResourceMethod.getResource().getResourceClass(),
                        abstractResourceMethod.getMethod().getDeclaringClass(),
                        abstractResourceMethodmisEncoded);
                resource.getResourceMethods().add(abstractResourceMethod);
            }
        }
    }
    
    private static void workOutSubResourceLocatorsList(
            AbstractResource resource
            MethodList methodList
            boolean isEncoded) {
        for (AnnotatedMethod m : methodList.hasNotMetaAnnotation(HttpMethod.class).
                hasAnnotation(Path.class)) {
            final Path mPathAnnotation = m.getAnnotation(Path.class);
            final AbstractSubResourceLocator subResourceLocator = new AbstractSubResourceLocator(
                    resource,
                    m.getMethod(),
                    new PathValue(
                        mPathAnnotation.value()),
                    m.getAnnotations());
            processParameters(
                    subResourceLocator.getResource().getResourceClass(),
                    subResourceLocator.getMethod().getDeclaringClass(),
                    subResourceLocatormisEncoded);
            resource.getSubResourceLocators().add(subResourceLocator);
        }
    }
    private static void processParameters(
            Class concreteClass,
            Class declaringClass,
            Parameterized parametrized
            Constructor ctor
            boolean isEncoded) {
        Class[] parameterTypes = ctor.getParameterTypes();
        Type[] genericParameterTypes = ctor.getGenericParameterTypes();
        // Workaround bug http://bugs.sun.com/view_bug.do?bug_id=5087240
        if (parameterTypes.length != genericParameterTypes.length) {
            Type[] _genericParameterTypes = new Type[parameterTypes.length];
            _genericParameterTypes[0] = parameterTypes[0];
            System.arraycopy(genericParameterTypes, 0, _genericParameterTypes, 1, genericParameterTypes.length);
            genericParameterTypes = _genericParameterTypes;
        }
        processParameters(
                concreteClassdeclaringClass,
                parametrized,
                ((null != ctor.getAnnotation(Encoded.class)) || isEncoded),
                parameterTypes,
                genericParameterTypes,
                ctor.getParameterAnnotations());
    }
    private static void processParameters(
            Class concreteClass,
            Class declaringClass,
            Parameterized parametrized
            AnnotatedMethod method
            boolean isEncoded) {
        processParameters(
                concreteClassdeclaringClass,
                parametrized,
                ((null != method.getAnnotation(Encoded.class)) || isEncoded),
                method.getParameterTypes(), 
                method.getGenericParameterTypes(), 
                method.getParameterAnnotations());
    }
    private static void processParameters(
            Class concreteClass,
            Class declaringClass,
            Parameterized parametrized,
            boolean isEncoded,
            Class[] parameterTypes,
            Type[] genericParameterTypes,
            Annotation[][] parameterAnnotations) {
        for (int i = 0; i < parameterTypes.lengthi++) {
            Parameter parameter = createParameter(
                    concreteClassdeclaringClass,
                    isEncodedparameterTypes[i], 
                    genericParameterTypes[i], 
                    parameterAnnotations[i]);
            if (null != parameter) {
                parametrized.getParameters().add(parameter);
            } else {
                // clean up the parameters
                parametrized.getParameters().removeAll(parametrized.getParameters());
                break;
            }
        }
    }
    private static interface ParamAnnotationHelper<T extends Annotation> {
        public String getValueOf(T a);
        public Parameter.Source getSource();
    }
        m.put(Context.classnew ParamAnnotationHelper<Context>() {
            @Override
            public String getValueOf(Context a) {
                return null;
            }
            @Override
            public Parameter.Source getSource() {
                return ..;
            }
        });
        m.put(HeaderParam.classnew ParamAnnotationHelper<HeaderParam>() {
            @Override
            public String getValueOf(HeaderParam a) {
                return a.value();
            }
            @Override
            public Parameter.Source getSource() {
                return ..;
            }
        });
        m.put(CookieParam.classnew ParamAnnotationHelper<CookieParam>() {
            @Override
            public String getValueOf(CookieParam a) {
                return a.value();
            }
            @Override
            public Parameter.Source getSource() {
                return ..;
            }
        });
        m.put(MatrixParam.classnew ParamAnnotationHelper<MatrixParam>() {
            @Override
            public String getValueOf(MatrixParam a) {
                return a.value();
            }
            @Override
            public Parameter.Source getSource() {
                return ..;
            }
        });
        m.put(QueryParam.classnew ParamAnnotationHelper<QueryParam>() {
            @Override
            public String getValueOf(QueryParam a) {
                return a.value();
            }
            @Override
            public Parameter.Source getSource() {
                return ..;
            }
        });
        m.put(PathParam.classnew ParamAnnotationHelper<PathParam>() {
            @Override
            public String getValueOf(PathParam a) {
                return a.value();
            }
            @Override
            public Parameter.Source getSource() {
                return ..;
            }
        });
        m.put(FormParam.classnew ParamAnnotationHelper<FormParam>() {
            @Override
            public String getValueOf(FormParam a) {
                return a.value();
            }
            @Override
            public Parameter.Source getSource() {
                return ..;
            }
        });
        return Collections.unmodifiableMap(m);
    }
    private final static Map<ClassParamAnnotationHelperANOT_HELPER_MAP = 
            createParamAnotHelperMap();
    @SuppressWarnings("unchecked")
    private static Parameter createParameter(
            Class concreteClass,
            Class declaringClass,
            boolean isEncoded
            Class<?> paramClass
            Type paramType
            Annotation[] annotations) {
        if (null == annotations) {
            return null;
        }
        Annotation paramAnnotation = null;
        Parameter.Source paramSource = null;
        String paramName = null;
        boolean paramEncoded = isEncoded;
        String paramDefault = null;
        
        
Create a parameter from the list of annotations. Unknown annotated parameters are also supported, and in such a cases the last unrecognized annotation is taken to be that associated with the parameter.
        for (Annotation annotation : annotations) {
            if (.containsKey(annotation.annotationType())) {
                ParamAnnotationHelper helper = .get(annotation.annotationType());
                paramAnnotation = annotation;
                paramSource = helper.getSource();
                paramName = helper.getValueOf(annotation);
            } else if (Encoded.class == annotation.annotationType()) {
                paramEncoded = true;
            } else if (DefaultValue.class == annotation.annotationType()) {
                paramDefault = ((DefaultValueannotation).value();
            } else {
                // lets only clear things down if we've not found a ANOT_HELPER_MAP annotation already
                if (paramAnnotation == null) {
                    paramAnnotation = annotation;
                    paramSource = .;
                    paramName = getValue(annotation);
                }
            }
        }
        if (paramAnnotation == null) {
            paramSource = ..;
        }
        ReflectionHelper.ClassTypePair ct = getGenericType(concreteClassdeclaringClassparamClassparamType);
        paramType = ct.t;
        paramClass = ct.c;
        return new Parameter(
                annotationsparamAnnotation,
                paramSource,
                paramNameparamTypeparamClass,
                paramEncodedparamDefault);
    }
    private static String getValue(Annotation a) {
        try {
            Method m = a.annotationType().getMethod("value");
            if (m.getReturnType() != String.class)
                return null;
            return (String)m.invoke(a);
        } catch (Exception ex) {
        }
        return null;
    }
            final Class concreteClass,
            final Class declaringClass,
            final Class c,
            final Type t) {
        if (t instanceof TypeVariable) {
            ReflectionHelper.ClassTypePair ct = ReflectionHelper.resolveTypeVariable(
                    concreteClass,
                    declaringClass,
                    (TypeVariable)t);
            if (ct != null) {
                return ct;
            }
        } else if (t instanceof ParameterizedType) {
            final ParameterizedType pt = (ParameterizedType)t;
            final Type[] ptts = pt.getActualTypeArguments();
            boolean modified =  false;
            for (int i = 0; i < ptts.lengthi++) {
                ReflectionHelper.ClassTypePair ct =
                        getGenericType(concreteClassdeclaringClass, (Class)pt.getRawType(), ptts[i]);
                if (ct.t != ptts[i]) {
                    ptts[i] = ct.t;
                    modified = true;
                }
            }
            if (modified) {
                ParameterizedType rpt = new ParameterizedType() {
                    @Override
                    public Type[] getActualTypeArguments() {
                        return ptts.clone();
                    }
                    @Override
                    public Type getRawType() {
                        return pt.getRawType();
                    }
                    @Override
                    public Type getOwnerType() {
                        return pt.getOwnerType();
                    }
                };
                return new ReflectionHelper.ClassTypePair((Class)pt.getRawType(), rpt);
            }
        } else if (t instanceof GenericArrayType) {
            GenericArrayType gat = (GenericArrayType)t;
            final ReflectionHelper.ClassTypePair ct =
                    getGenericType(concreteClassdeclaringClassnullgat.getGenericComponentType());
            if (gat.getGenericComponentType() != ct.t) {
                try {
                    Class ac = ReflectionHelper.getArrayClass(ct.c);
                    return new ReflectionHelper.ClassTypePair(acac);
                } catch (Exception e) {
                }
            }
        }
        return new ReflectionHelper.ClassTypePair(ct);
    }
New to GrepCode? Check out our FAQ X