1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with this 4 * work for additional information regarding copyright ownership. The ASF 5 * licenses this file to You under the Apache License, Version 2.0 (the 6 * "License"); you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law 9 * or agreed to in writing, software distributed under the License is 10 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language 12 * governing permissions and limitations under the License. 13 */ 14 package org.apache.webbeans.decorator; 15 16 import java.lang.annotation.Annotation; 17 import java.lang.reflect.Field; 18 import java.lang.reflect.Method; 19 import java.lang.reflect.Type; 20 import java.util.HashSet; 21 import java.util.Iterator; 22 import java.util.List; 23 import java.util.Set; 24 25 import javax.decorator.Decorates; 26 import javax.enterprise.inject.spi.Decorator; 27 28 import org.apache.webbeans.component.ManagedBean; 29 import org.apache.webbeans.container.BeanManagerImpl; 30 import org.apache.webbeans.exception.WebBeansConfigurationException; 31 import org.apache.webbeans.exception.WebBeansException; 32 import org.apache.webbeans.logger.WebBeansLogger; 33 import org.apache.webbeans.util.AnnotationUtil; 34 import org.apache.webbeans.util.Asserts; 35 import org.apache.webbeans.util.ClassUtil; 36 37 /** 38 * Decorator related utility class. 39 * 40 * @version $Rev$ $Date$ 41 * 42 */ 43 public final class DecoratorUtil 44 { 45 //Logger instance 46 private static final WebBeansLogger logger = WebBeansLogger.getLogger(DecoratorUtil.class); 47 48 //Non-instantiate 49 private DecoratorUtil() 50 { 51 //Empty 52 } 53 54 /** 55 * Check decorator conditions. 56 * @param decoratorClazz decorator class 57 */ 58 public static void checkDecoratorConditions(Class<?> decoratorClazz) 59 { 60 Set<Type> decoratorSet = new HashSet<Type>(); 61 ClassUtil.setInterfaceTypeHierarchy(decoratorSet, decoratorClazz); 62 63 //No-Decorates found, check from super class 64 if(!checkInternalDecoratorConditions(decoratorClazz, decoratorSet)) 65 { 66 boolean found = checkInternalDecoratorConditionsRecursivley(decoratorClazz,decoratorSet); 67 68 if(!found) 69 { 70 throw new WebBeansConfigurationException("Decorator delegate attribute for decorator class : " + decoratorClazz.getName() + " can not be found!"); 71 } 72 } 73 } 74 75 private static boolean checkInternalDecoratorConditionsRecursivley(Class<?> decoratorClazz,Set<Type> decoratorSet) 76 { 77 Class<?> superClazz = decoratorClazz.getSuperclass(); 78 if(!superClazz.equals(Object.class)) 79 { 80 boolean found = checkInternalDecoratorConditions(superClazz, decoratorSet); 81 if(!found) 82 { 83 return checkInternalDecoratorConditionsRecursivley(superClazz, decoratorSet); 84 } 85 else 86 { 87 return true; 88 } 89 } 90 91 return false; 92 } 93 94 private static boolean checkInternalDecoratorConditions(Class<?> decoratorClazz,Set<Type> decoratorSet) 95 { 96 Field[] fields = decoratorClazz.getDeclaredFields(); 97 boolean found = false; 98 for (Field field : fields) 99 { 100 if (AnnotationUtil.isAnnotationExist(field.getDeclaredAnnotations(), Decorates.class)) 101 { 102 if (found) 103 { 104 throw new WebBeansConfigurationException("Decorator class : " + decoratorClazz.getName() + " can only contain one delegate attribute but find more than one!."); 105 } 106 else 107 { 108 Class<?> fieldType = field.getType(); 109 if (!ClassUtil.isInterface(fieldType.getModifiers())) 110 { 111 throw new WebBeansConfigurationException("Decorator class : " + decoratorClazz.getName() + " delegate attribute type must be interface"); 112 } 113 114 for (Type decType : decoratorSet) 115 { 116 if (!fieldType.isAssignableFrom((Class<?>)decType)) 117 { 118 throw new WebBeansConfigurationException("Decorator class : " + decoratorClazz.getName() + " delegate attribute must implement all of the decorator decorated types."); 119 } 120 } 121 122 found = true; 123 } 124 } 125 } 126 127 return found; 128 129 } 130 131 public static void checkManagedBeanDecoratorConditions(ManagedBean<?> component) 132 { 133 Asserts.assertNotNull("component", "component parameter can not be null"); 134 135 Set<Annotation> annSet = component.getQualifiers(); 136 Annotation[] anns = new Annotation[annSet.size()]; 137 anns = annSet.toArray(anns); 138 139 List<Decorator<?>> decoratorList = BeanManagerImpl.getManager().resolveDecorators(component.getTypes(), anns); 140 if (!decoratorList.isEmpty()) 141 { 142 Class<?> clazz = component.getReturnType(); 143 if (ClassUtil.isFinal(clazz.getModifiers())) 144 { 145 throw new WebBeansConfigurationException("Managed Bean : " + component.getReturnType().getName() + " can not be declared final, because it has one or more decorators"); 146 } 147 148 Method[] methods = clazz.getDeclaredMethods(); 149 for (Method method : methods) 150 { 151 int modifiers = method.getModifiers(); 152 if (!ClassUtil.isStatic(modifiers) && !ClassUtil.isPrivate(modifiers) && ClassUtil.isFinal(modifiers)) 153 { 154 // Check decorator implements this 155 Iterator<Decorator<?>> itDecorator = decoratorList.iterator(); 156 while (itDecorator.hasNext()) 157 { 158 WebBeansDecorator<?> decorator = (WebBeansDecorator<?>) itDecorator.next(); 159 Class<?> decClazz = decorator.getClazz(); 160 161 try 162 { 163 if (decClazz.getMethod(method.getName(), method.getParameterTypes()) != null) 164 { 165 throw new WebBeansConfigurationException("Managed Bean : " + component.getReturnType().getName() + " can not define non-private, non-static, final method : " + method.getName() + ", because one of its decorators implements this method"); 166 167 } 168 169 } 170 catch (SecurityException e) 171 { 172 logger.error("Security exception, can not access decorator class : " + decClazz.getName() + " method : " + method.getName(), e); 173 throw new WebBeansException(e); 174 175 } 176 catch (NoSuchMethodException e) 177 { 178 continue; 179 } 180 181 } 182 } 183 } 184 } 185 } 186 187 }