001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.jaxws.annotations;
018    
019    import java.lang.annotation.Annotation;
020    import java.lang.reflect.Field;
021    import java.lang.reflect.InvocationTargetException;
022    import java.lang.reflect.Method;
023    
024    // TODO: Check for static methods and fields. They are only allowed for client apps.
025    public abstract class InjectingAnnotationHandler implements AnnotationHandler {
026    
027        abstract public Object getAnnotationValue(Annotation annotation,
028                                                  String name,
029                                                  Class<?> type)
030                throws InjectionException;
031    
032        public void processClassAnnotation(Object instance,
033                                           Class clazz,
034                                           Annotation annotation) {
035            // injection is not done for annotations at class level
036        }
037    
038        public String getJNDIName(Object instance, String name, Field field) {
039            if (name != null && name.length() > 0) {
040                return name;
041            } else {
042                return instance.getClass().getName() + "/" + field.getName();
043            }
044        }
045    
046        public String getJNDIName(Object instance, String name, Method method) {
047            if (name != null && name.length() > 0) {
048                return name;
049            } else {
050                String propName = method.getName();
051                propName = propName.substring(3);
052                propName = Character.toLowerCase(propName.charAt(0))
053                        + propName.substring(1);
054                return instance.getClass().getName() + "/" + propName;
055            }
056        }
057    
058        public Class<?> getType(Class<?> type, Field field) {
059            return (type == null || Object.class == type) ? field.getType() : type;
060        }
061    
062        public Class<?> getType(Class<?> type, Method method) {
063            return (type == null || Object.class == type) ? method
064                    .getParameterTypes()[0] : type;
065        }
066    
067        protected void injectField(Object instance,
068                                   Field field,
069                                   Annotation annotation,
070                                   String name,
071                                   Class<?> type) throws InjectionException {
072    
073            String jndiName = getJNDIName(instance, name, field);
074    
075            Object lookedupResource = getAnnotationValue(annotation, jndiName,
076                    getType(type, field));
077    
078            boolean accessibility = field.isAccessible();
079            try {
080                field.setAccessible(true);
081                field.set(instance, lookedupResource);
082            } catch (IllegalArgumentException e) {
083                throw new InjectionException("Field injection failed", e);
084            } catch (IllegalAccessException e) {
085                throw new InjectionException("Field injection failed", e);
086            } finally {
087                field.setAccessible(accessibility);
088            }
089        }
090    
091        protected void injectMethod(Object instance,
092                                    Method method,
093                                    Annotation annotation,
094                                    String name,
095                                    Class<?> type) throws InjectionException {
096    
097            if (!method.getName().startsWith("set")
098                    || method.getParameterTypes().length != 1
099                    || !method.getReturnType().equals(Void.class)) {
100                throw new IllegalArgumentException(
101                        "Invalid method resource injection annotation");
102            }
103    
104            String jndiName = getJNDIName(instance, name, method);
105    
106            Object lookedupResource = getAnnotationValue(annotation, jndiName,
107                    getType(type, method));
108    
109            boolean accessibility = method.isAccessible();
110            try {
111                method.setAccessible(true);
112                method.invoke(instance, lookedupResource);
113            } catch (IllegalArgumentException e) {
114                throw new InjectionException("Method injection failed", e);
115            } catch (IllegalAccessException e) {
116                throw new InjectionException("Method injection failed", e);
117            } catch (InvocationTargetException e) {
118                throw new InjectionException("Method injection failed", e);
119            } finally {
120                method.setAccessible(accessibility);
121            }
122        }
123    
124    }