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: */package org.apache.openejb.assembler.classic;
017:
018: import org.apache.openejb.core.CoreDeploymentInfo;
019:
020: import static java.util.Arrays.asList;
021: import java.util.Comparator;
022: import java.util.List;
023: import java.util.ArrayList;
024: import java.util.Collections;
025: import java.util.Map;
026: import java.util.HashMap;
027: import java.lang.reflect.Method;
028:
029: /**
030: * @version $Rev$ $Date$
031: */
032: public class MethodInfoUtil {
033:
034: public static List<Method> matchingMethods(MethodInfo mi,
035: Class clazz) {
036:
037: Level level = level(mi);
038:
039: switch (level) {
040: case BEAN:
041: case PACKAGE: {
042: return asList(clazz.getMethods());
043: }
044: case CLASS: {
045: return filterByClass(clazz.getMethods(), mi.className);
046: }
047: case OVERLOADED_METHOD_BEAN: {
048: return filterByName(clazz.getMethods(), mi.methodName);
049: }
050: case OVERLOADED_METHOD_CLASS: {
051: return filterByNameAndClass(clazz.getMethods(),
052: mi.className, mi.methodName);
053: }
054: case EXACT_METHOD: {
055: Method method = getMethod(clazz, mi);
056: if (method != null)
057: return asList(method);
058: }
059: }
060:
061: return Collections.EMPTY_LIST;
062: }
063:
064: public static Method getMethod(Class clazz, MethodInfo info) {
065: ClassLoader cl = clazz.getClassLoader();
066:
067: List<Class> params = new ArrayList<Class>();
068: for (String methodParam : info.methodParams) {
069: try {
070: params.add(getClassForParam(methodParam, cl));
071: } catch (ClassNotFoundException cnfe) {
072:
073: }
074: }
075: Method method = null;
076: try {
077: method = clazz.getMethod(info.methodName, params
078: .toArray(new Class[params.size()]));
079: } catch (NoSuchMethodException e) {
080: return null;
081: }
082:
083: if (!info.className.equals("*")
084: && !method.getDeclaringClass().getName().equals(
085: info.className)) {
086: return null;
087: }
088:
089: return method;
090: }
091:
092: private static List<Method> filterByClass(Method[] methods,
093: String className) {
094: List<Method> list = new ArrayList<Method>();
095: for (Method method : methods) {
096: if (method.getDeclaringClass().getName().equals(className)) {
097: list.add(method);
098: }
099: }
100: return list;
101: }
102:
103: private static List<Method> filterByName(Method[] methods,
104: String methodName) {
105: List<Method> list = new ArrayList<Method>();
106: for (Method method : methods) {
107: if (method.getName().equals(methodName)) {
108: list.add(method);
109: }
110: }
111: return list;
112: }
113:
114: private static List<Method> filterByNameAndClass(Method[] methods,
115: String className, String methodName) {
116: List<Method> list = new ArrayList<Method>();
117: for (Method method : methods) {
118: if (method.getName().equals(methodName)
119: && method.getDeclaringClass().getName().equals(
120: className)) {
121: list.add(method);
122: }
123: }
124: return list;
125: }
126:
127: /**
128: * This method splits the MethodPermissionInfo objects so that there is
129: * exactly one MethodInfo per MethodPermissionInfo. A single MethodPermissionInfo
130: * with three MethodInfos would be expanded into three MethodPermissionInfo with
131: * one MethodInfo each.
132: *
133: * The MethodPermissionInfo list is then sorted from least to most specific.
134: *
135: * @param infos
136: * @return a normalized list of new MethodPermissionInfo objects
137: */
138: public static List<MethodPermissionInfo> normalizeMethodPermissionInfos(
139: List<MethodPermissionInfo> infos) {
140: List<MethodPermissionInfo> normalized = new ArrayList<MethodPermissionInfo>();
141: for (MethodPermissionInfo oldInfo : infos) {
142: for (MethodInfo methodInfo : oldInfo.methods) {
143: MethodPermissionInfo newInfo = new MethodPermissionInfo();
144: newInfo.description = oldInfo.description;
145: newInfo.methods.add(methodInfo);
146: newInfo.roleNames.addAll(oldInfo.roleNames);
147: newInfo.unchecked = oldInfo.unchecked;
148:
149: normalized.add(newInfo);
150: }
151: }
152:
153: Collections.sort(normalized, new MethodPermissionComparator());
154:
155: return normalized;
156: }
157:
158: public static Level level(MethodInfo methodInfo) {
159: if (methodInfo.ejbName.equals("*"))
160: return Level.PACKAGE;
161: if (methodInfo.methodName.equals("*")) {
162: if (methodInfo.className.equals("*"))
163: return Level.BEAN;
164: else
165: return Level.CLASS;
166: }
167: if (methodInfo.methodParams == null) {
168: if (methodInfo.className.equals("*"))
169: return Level.OVERLOADED_METHOD_BEAN;
170: else
171: return Level.OVERLOADED_METHOD_CLASS;
172: }
173: return Level.EXACT_METHOD;
174: }
175:
176: private static Class getClassForParam(String className,
177: ClassLoader cl) throws ClassNotFoundException {
178: if (cl == null) {
179: cl = ClassLoader.getSystemClassLoader();
180: }
181:
182: if (className.equals("int")) {
183: return Integer.TYPE;
184: } else if (className.equals("double")) {
185: return Double.TYPE;
186: } else if (className.equals("long")) {
187: return Long.TYPE;
188: } else if (className.equals("boolean")) {
189: return Boolean.TYPE;
190: } else if (className.equals("float")) {
191: return Float.TYPE;
192: } else if (className.equals("char")) {
193: return Character.TYPE;
194: } else if (className.equals("short")) {
195: return Short.TYPE;
196: } else if (className.equals("byte")) {
197: return Byte.TYPE;
198: } else
199: return cl.loadClass(className);
200:
201: }
202:
203: public static Map<Method, MethodAttributeInfo> resolveAttributes(
204: List<? extends MethodAttributeInfo> infos,
205: CoreDeploymentInfo deploymentInfo) {
206: Map<Method, MethodAttributeInfo> attributes = new HashMap<Method, MethodAttributeInfo>();
207:
208: for (MethodAttributeInfo attributeInfo : infos) {
209: for (MethodInfo methodInfo : attributeInfo.methods) {
210:
211: if (methodInfo.ejbDeploymentId == null
212: || methodInfo.ejbDeploymentId
213: .equals(deploymentInfo
214: .getDeploymentID())) {
215: if (!deploymentInfo.isBeanManagedTransaction()) {
216:
217: List<Method> methods = new ArrayList<Method>();
218:
219: if (methodInfo.methodIntf == null) {
220:
221: methods.addAll(matchingMethods(methodInfo,
222: deploymentInfo.getBeanClass()));
223:
224: if (deploymentInfo.getRemoteInterface() != null) {
225: methods.addAll(matchingMethods(
226: methodInfo, deploymentInfo
227: .getRemoteInterface()));
228: }
229: if (deploymentInfo.getHomeInterface() != null) {
230: methods.addAll(matchingMethods(
231: methodInfo, deploymentInfo
232: .getHomeInterface()));
233: }
234: if (deploymentInfo.getLocalInterface() != null) {
235: methods.addAll(matchingMethods(
236: methodInfo, deploymentInfo
237: .getLocalInterface()));
238: }
239: if (deploymentInfo.getLocalHomeInterface() != null) {
240: methods
241: .addAll(matchingMethods(
242: methodInfo,
243: deploymentInfo
244: .getLocalHomeInterface()));
245: }
246: if (deploymentInfo.getMdbInterface() != null) {
247: methods.addAll(matchingMethods(
248: methodInfo, deploymentInfo
249: .getMdbInterface()));
250: }
251: if (deploymentInfo
252: .getServiceEndpointInterface() != null) {
253: methods
254: .addAll(matchingMethods(
255: methodInfo,
256: deploymentInfo
257: .getServiceEndpointInterface()));
258: }
259: for (Class intf : deploymentInfo
260: .getBusinessRemoteInterfaces()) {
261: methods.addAll(matchingMethods(
262: methodInfo, intf));
263: }
264: for (Class intf : deploymentInfo
265: .getBusinessLocalInterfaces()) {
266: methods.addAll(matchingMethods(
267: methodInfo, intf));
268: }
269: } else if (methodInfo.methodIntf.equals("Home")) {
270: methods.addAll(matchingMethods(methodInfo,
271: deploymentInfo.getHomeInterface()));
272: } else if (methodInfo.methodIntf
273: .equals("Remote")) {
274: methods
275: .addAll(matchingMethods(
276: methodInfo,
277: deploymentInfo
278: .getRemoteInterface()));
279: for (Class intf : deploymentInfo
280: .getBusinessRemoteInterfaces()) {
281: methods.addAll(matchingMethods(
282: methodInfo, intf));
283: }
284: } else if (methodInfo.methodIntf
285: .equals("LocalHome")) {
286: methods.addAll(matchingMethods(methodInfo,
287: deploymentInfo
288: .getLocalHomeInterface()));
289: } else if (methodInfo.methodIntf
290: .equals("Local")) {
291: methods
292: .addAll(matchingMethods(
293: methodInfo,
294: deploymentInfo
295: .getLocalInterface()));
296: for (Class intf : deploymentInfo
297: .getBusinessRemoteInterfaces()) {
298: methods.addAll(matchingMethods(
299: methodInfo, intf));
300: }
301: } else if (methodInfo.methodIntf
302: .equals("ServiceEndpoint")) {
303: methods
304: .addAll(matchingMethods(
305: methodInfo,
306: deploymentInfo
307: .getServiceEndpointInterface()));
308: }
309:
310: for (Method method : methods) {
311: if ((method.getDeclaringClass() == javax.ejb.EJBObject.class || method
312: .getDeclaringClass() == javax.ejb.EJBHome.class)
313: && !method.getName().equals(
314: "remove")) {
315: continue;
316: }
317:
318: attributes.put(method, attributeInfo);
319: }
320: }
321: }
322: }
323: }
324: return attributes;
325: }
326:
327: public static enum Level {
328: PACKAGE, CLASS, BEAN, OVERLOADED_METHOD_CLASS, OVERLOADED_METHOD_BEAN, EXACT_METHOD
329: }
330:
331: public static class MethodPermissionComparator extends
332: BaseComparator<MethodPermissionInfo> {
333: public int compare(MethodPermissionInfo a,
334: MethodPermissionInfo b) {
335: return compare(a.methods.get(0), b.methods.get(0));
336: }
337: }
338:
339: public static abstract class BaseComparator<T> implements
340: Comparator<T> {
341: public int compare(MethodInfo am, MethodInfo bm) {
342: Level levelA = level(am);
343: Level levelB = level(bm);
344:
345: return levelA.ordinal() - levelB.ordinal();
346: }
347: }
348:
349: }
|