All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cxf.jaxrs.model.AbstractResourceInfo Maven / Gradle / Ivy

There is a newer version: 3.0.0-milestone2
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.cxf.jaxrs.model;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;

import org.apache.cxf.jaxrs.impl.tl.ThreadLocalProxy;
import org.apache.cxf.jaxrs.utils.AnnotationUtils;
import org.apache.cxf.jaxrs.utils.InjectionUtils;

public abstract class AbstractResourceInfo {
    
    private static Map, List> contextFields;
    private static Map, List> resourceFields;
    private static Map, Map, Method>> contextMethods;
    private static Map, Map> fieldProxyMap;
    private static Map, Map> resourceProxyMap;
    private static Map, Map> setterProxyMap;
    
    protected boolean root;
    protected Class resourceClass;
    protected Class serviceClass;
    
    protected AbstractResourceInfo() {
        
    }
    
    protected AbstractResourceInfo(Class resourceClass, Class serviceClass, boolean isRoot) {
        this.serviceClass = serviceClass;
        this.resourceClass = resourceClass;
        root = isRoot;
        if (root && resourceClass != null) {
            findContextFields(serviceClass);
            findContextSetterMethods(serviceClass);
        }
    }
    
    public void setResourceClass(Class rClass) {
        resourceClass = rClass;
        if (serviceClass.isInterface() && resourceClass != null && !resourceClass.isInterface()) {
            findContextFields(resourceClass);
            findContextSetterMethods(resourceClass);
        }
    }
    
    public Class getServiceClass() {
        return serviceClass;
    }
    
    private void findContextFields(Class cls) {
        if (cls == Object.class || cls == null) {
            return;
        }
        for (Field f : cls.getDeclaredFields()) {
            for (Annotation a : f.getAnnotations()) {
                if (a.annotationType() == Context.class) {
                    contextFields = addContextField(contextFields, f);
                    if (f.getType() != Application.class) {
                        fieldProxyMap = getProxyMap(Field.class, fieldProxyMap);
                        addToMap(fieldProxyMap, f, InjectionUtils.createThreadLocalProxy(f.getType()));
                    }
                } else if (a.annotationType() == Resource.class 
                           && AnnotationUtils.isContextClass(f.getType())) {
                    resourceFields = addContextField(resourceFields, f);
                    resourceProxyMap = getProxyMap(Field.class, resourceProxyMap);
                    addToMap(resourceProxyMap, f, InjectionUtils.createThreadLocalProxy(f.getType()));
                }
            }
        }
        findContextFields(cls.getSuperclass());
    }
    
    private  Map, Map> getProxyMap(Class keyClass,
        Map, Map> map) {
        return map == null ? new HashMap, Map>() : map;
    }
    
    private void findContextSetterMethods(Class cls) {
        
        for (Method m : cls.getMethods()) {
        
            if (!m.getName().startsWith("set") || m.getParameterTypes().length != 1) {
                continue;
            }
            for (Annotation a : m.getAnnotations()) {
                if (a.annotationType() == Context.class) {
                    checkContextMethod(m);
                    break;
                }
            }
        }
        Class[] interfaces = cls.getInterfaces();
        for (Class i : interfaces) {
            findContextSetterMethods(i);
        }
    }
    
    private void checkContextMethod(Method m) {
        Class type = m.getParameterTypes()[0];
        if (AnnotationUtils.isContextClass(type)
            && m.getName().equals("set" + type.getSimpleName())) {        
            addContextMethod(type, m);
        }
    }
    
    @SuppressWarnings("unchecked")
    public Map, Method> getContextMethods() {
        Map, Method> methods = contextMethods == null ? null : contextMethods.get(getServiceClass());
        return methods == null ? Collections.EMPTY_MAP 
                                      : Collections.unmodifiableMap(methods);
    }
    
    private void addContextMethod(Class contextClass, Method m) {
        if (contextMethods == null) {
            contextMethods = new HashMap, Map, Method>>();
        }
        addToMap(contextMethods, contextClass, m);
        if (m.getParameterTypes()[0] != Application.class) {
            setterProxyMap = getProxyMap(Method.class, setterProxyMap);
            addToMap(setterProxyMap, m, 
                     InjectionUtils.createThreadLocalProxy(m.getParameterTypes()[0]));
        }
    }
    
    public boolean isRoot() {
        return root;
    }
    
    public Class getResourceClass() {
        return resourceClass;
    }
    
    public List getContextFields() {
        return getList(contextFields);
    }
    
    public List getResourceFields() {
        return getList(resourceFields);
    }
    
    public ThreadLocalProxy getContextFieldProxy(Field f) {
        return getProxy(fieldProxyMap, f);
    }
    
    public ThreadLocalProxy getResourceFieldProxy(Field f) {
        return getProxy(resourceProxyMap, f);
    }
    
    public ThreadLocalProxy getContextSetterProxy(Method m) {
        return getProxy(setterProxyMap, m);
    }
    
    public abstract boolean isSingleton();
    
    public void clearThreadLocalProxies() {
        clearProxies(fieldProxyMap);
        clearProxies(resourceProxyMap);
        clearProxies(setterProxyMap);
    }
    
    private  void clearProxies(Map, Map> tlps) {
        Map proxies = tlps == null ? null : tlps.get(getServiceClass());
        if (proxies == null) {
            return;
        }
        for (ThreadLocalProxy tlp : proxies.values()) {
            if (tlp != null) {
                tlp.remove();
            }
        }
    }
    
    private Map, List> addContextField(Map, List> theFields, Field f) {
        
        theFields = theFields == null ? new HashMap, List>() : theFields;
        
        List fields = theFields.get(serviceClass);
        if (fields == null) {
            fields = new ArrayList();
            theFields.put(serviceClass, fields);
        }
        if (!fields.contains(f)) {
            fields.add(f);
        }
        return theFields;
    }
    
    private  void addToMap(Map, Map> theFields, 
                               T f, V proxy) {
        Map proxies = theFields.get(serviceClass);
        if (proxies == null) {
            proxies = new HashMap();
            theFields.put(serviceClass, proxies);
        }
        if (!proxies.containsKey(f)) {
            proxies.put(f, proxy);
        }
    }

    private List getList(Map, List> fields) {
        List ret = fields == null ? null : fields.get(getServiceClass());
        if (ret != null) {
            ret = Collections.unmodifiableList(ret);
        } else {
            ret = Collections.emptyList();
        }
        return ret;
    }
    
    private  ThreadLocalProxy getProxy(Map, Map> proxies, T key) {
        
        Map theMap = proxies == null ? null : proxies.get(getServiceClass());
        
        return theMap != null ? theMap.get(key) : null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy