001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 1999-2004 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: MethodDesc.java 6407 2005-03-11 12:34:28Z joaninh $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas_ejb.deployment.api;
025:
026: import java.lang.reflect.Method;
027: import java.util.HashSet;
028: import java.util.Iterator;
029: import java.util.List;
030:
031: import org.objectweb.jonas_ejb.deployment.xml.MethodParams;
032: import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
033:
034: /**
035: * Class to hold meta-information related to bean and home methods.
036: * @author Christophe Ney [cney@batisseurs.com] : Initial developer
037: * @author Helene Joanin: fix a bug about select method select method is a bean's method which name begins with ejbSelect,
038: * (and not home interface method as finder method).
039: */
040: public class MethodDesc {
041:
042: /**
043: * Set of constants for method transaction attribute
044: */
045: public static final int TX_NULL = -1;
046: public static final int TX_NOT_SET = 0;
047: public static final int TX_NOT_SUPPORTED = 1;
048: public static final int TX_REQUIRED = 2;
049: public static final int TX_SUPPORTS = 3;
050: public static final int TX_REQUIRES_NEW = 4;
051: public static final int TX_MANDATORY = 5;
052: public static final int TX_NEVER = 6;
053:
054: private static final String[] ATTR = { "TX_NOT_SET",
055: "TX_NOT_SUPPORTED", "TX_REQUIRED", "TX_SUPPORTS",
056: "TX_REQUIRES_NEW", "TX_MANDATORY", "TX_NEVER" };
057:
058: /**
059: * default value for undefined transaction attribute for sessions and entities
060: */
061: protected static final String TX_STR_DEFAULT_VALUE = "Supports";
062:
063: /**
064: * default value for undefined transaction attribute for message driven beans
065: */
066: protected static final String TX_STR_DEFAULT_VALUE_4_MDB = "NotSupported";
067:
068: /**
069: * value for undefined transaction attribute
070: */
071: private int txAttribute = TX_NOT_SET;
072: private int txAttributeStatus = APPLY_TO_BEAN;
073:
074: // Array of String representing the roles which can execute the method of this MethodDesc
075: private HashSet roleName = new HashSet();
076:
077: public static final int APPLY_TO_NOTHING = 0;
078: public static final int APPLY_TO_BEAN = 1;
079: public static final int APPLY_TO_CLASS = 2;
080: public static final int APPLY_TO_BEAN_METHOD_NAME = 3;
081: public static final int APPLY_TO_CLASS_METHOD_NAME = 4;
082: public static final int APPLY_TO_BEAN_METHOD = 5;
083: public static final int APPLY_TO_CLASS_METHOD = 6;
084:
085: protected static final String[] APPLY_TO = { "APPLY_TO_NOTHING",
086: "APPLY_TO_BEAN", "APPLY_TO_CLASS",
087: "APPLY_TO_BEAN_METHOD_NAME", "APPLY_TO_CLASS_METHOD_NAME",
088: "APPLY_TO_BEAN_METHOD", "APPLY_TO_CLASS_METHOD" };
089:
090: private Method meth;
091: private Class classDef;
092: private int index;
093:
094: protected BeanDesc beanDesc;
095:
096: private boolean isFinder = false;
097: private boolean isEjbSelect = false;
098: private boolean isFindByPrimaryKey = false;
099:
100: /**
101: * This method was marked as excluded in ejb-jar.xml ?
102: */
103: private boolean excluded = false;
104:
105: /**
106: * constructor to be used by parent node
107: */
108: public MethodDesc(BeanDesc beanDesc, Method meth, Class clDef,
109: int index) {
110: this .meth = meth;
111: this .classDef = clDef;
112: this .index = index;
113: this .beanDesc = beanDesc;
114: isFindByPrimaryKey = MethodDesc.isFindByPrimaryKey(meth);
115: isFinder = isFinder(meth);
116: isEjbSelect = isEjbSelect(meth);
117: }
118:
119: /**
120: * get a unique index of the method for the bean
121: */
122: public int getIndex() {
123: return index;
124: }
125:
126: public void setIndex(int idx) {
127: index = idx;
128: }
129:
130: /**
131: * access if the method is a finder
132: * @return true for finder methods
133: */
134: public boolean isFinder() {
135: return isFinder;
136: }
137:
138: /**
139: * access if the method is <code>findByPrimaryKey</code>
140: * @return true for the <code>findByPrimaryKey</code> method
141: */
142: public boolean isFindByPrimaryKey() {
143: return isFindByPrimaryKey;
144: }
145:
146: /**
147: * access if the method is a select
148: * @return true for select methods
149: */
150: public boolean isEjbSelect() {
151: return isEjbSelect;
152: }
153:
154: /**
155: * Overwrite TxAttribute
156: * @param transAttribute new value for txAttribute
157: * @param status applicability of given transAttribute parameter
158: */
159: void overwriteTxAttribute(String transAttribute, int status)
160: throws DeploymentDescException {
161: // overwrite only if numerical value greater than existing one
162: if (status < this .txAttributeStatus) {
163: return;
164: }
165: setTxAttribute(transAttribute);
166: txAttributeStatus = status;
167: }
168:
169: /**
170: * Set TxAttribute with given value
171: */
172: void setTxAttribute(String transAttribute)
173: throws DeploymentDescException {
174: if (transAttribute.equals("NotSupported")) {
175: txAttribute = TX_NOT_SUPPORTED;
176: } else if (transAttribute.equals("Required")) {
177: txAttribute = TX_REQUIRED;
178: } else if (transAttribute.equals("Supports")) {
179: txAttribute = TX_SUPPORTS;
180: } else if (transAttribute.equals("RequiresNew")) {
181: txAttribute = TX_REQUIRES_NEW;
182: } else if (transAttribute.equals("Mandatory")) {
183: txAttribute = TX_MANDATORY;
184: } else if (transAttribute.equals("Never")) {
185: txAttribute = TX_NEVER;
186: } else {
187: throw new DeploymentDescException(transAttribute
188: + " is not a valid trans-attribute value");
189: }
190: }
191:
192: /**
193: * Add a role name to the role names which can execute the method
194: * @param rn role name to add
195: */
196: void addRoleName(String rn) {
197: roleName.add(rn);
198: }
199:
200: /**
201: * Evaluate method pattern maching as defined in the EJB specifications
202: * @return one of the <code>APPLY_TO_*</code> values.
203: */
204: public int matchPattern(Class pclass, String mName,
205: MethodParams patternMethodParams) {
206: return matchPattern(getMethod(), classDef, pclass, mName,
207: patternMethodParams);
208: }
209:
210: /**
211: * Get the status of applicability for a given pattern to a method
212: * @return status of applicability APPLY_TO_NOTHING,APPLY_TO_BEAN,APPLY_TO_CLASS,APPLY_TO_METHOD_NAME,APPLY_TO_METHOD
213: */
214: public static int matchPattern(java.lang.reflect.Method meth,
215: Class classMeth, Class pclass, String mName,
216: MethodParams patternMethodParams) {
217:
218: // If pclass don't match -> APPLY_TO_NOTHING
219: if (pclass != null && !pclass.isAssignableFrom(classMeth)) {
220: return APPLY_TO_NOTHING;
221: }
222:
223: // class is enough
224: if (mName.equals("*")) {
225: return (pclass == null) ? APPLY_TO_BEAN : APPLY_TO_CLASS;
226: }
227:
228: // method name does not match
229: if (!mName.equals(meth.getName())) {
230: return APPLY_TO_NOTHING;
231: }
232:
233: // no params specified (name test is enough)
234: if (patternMethodParams == null) {
235: return (pclass == null) ? APPLY_TO_BEAN_METHOD_NAME
236: : APPLY_TO_CLASS_METHOD_NAME;
237: }
238:
239: Class pars[] = meth.getParameterTypes();
240: List pattPars = patternMethodParams.getMethodParamList();
241: // number of parameters does not match
242: if (pars.length != pattPars.size()) {
243: return APPLY_TO_NOTHING;
244: }
245: Iterator i = pattPars.iterator();
246: for (int ii = 0; ii < pars.length; ii++) {
247: String cName = (String) i.next();
248: if (!getClassName(pars[ii]).equals(cName)) {
249: return APPLY_TO_NOTHING;
250: }
251: }
252: return (pclass == null) ? APPLY_TO_BEAN_METHOD
253: : APPLY_TO_CLASS_METHOD;
254: }
255:
256: /**
257: * Returns common name of a given type <BR>
258: * For example it returns int[] for an array of int
259: * @return String with the name of the given type
260: */
261: private static String getClassName(Class c) {
262: String name;
263: if (c.isArray()) {
264: name = getClassName(c.getComponentType()) + "[]";
265: } else {
266: name = c.getName();
267: }
268: return (name);
269: }
270:
271: /**
272: * Get the container transaction attribute that match the method
273: * @return Constant value within list :
274: * TX_NOT_SUPPORTED,TX_REQUIRED,TX_SUPPORTS,TX_REQUIRES_NEW,TX_MANDATORY,TX_NEVER,TX_NOT_SET
275: */
276: public int getTxAttribute() {
277: return txAttribute;
278: }
279:
280: /**
281: * Get the container transaction attribute that match the method
282: * @return Constant value within list :
283: * APPLY_TO_NOTHING, APPLY_TO_BEAN, APPLY_TO_CLASS, APPLY_TO_BEAN_METHOD_NAME,
284: * APPLY_TO_CLASS_METHOD_NAME, APPLY_TO_BEAN_METHOD, APPLY_TO_CLASS_METHOD
285: */
286: public int getTxAttributeStatus() {
287: return txAttributeStatus;
288: }
289:
290: /**
291: * String representation of the transactionnal attribute
292: * @return String representation of this transactionnal attribute
293: */
294: public static String getTxAttributeName(int value) {
295: if ((value < 0) || (value > ATTR.length)) {
296: throw new Error(value + " is not a valid TxAttribute");
297: }
298: return ATTR[value];
299: }
300:
301: /**
302: * String representation of the transactionnal attribute
303: * @return String representation of this transactionnal attribute
304: */
305: public String getTxAttributeName() {
306: return ATTR[txAttribute];
307: }
308:
309: /**
310: * String representation of the roles which can execute the method
311: * @return Array of String representing the roles which can execute the method
312: */
313: public String[] getRoleName() {
314: if (roleName.isEmpty()) {
315: return new String[0];
316: }
317: Object[] o = roleName.toArray();
318: String[] rn = new String[o.length];
319: for (int i = 0; i < rn.length; i++) {
320: rn[i] = (String) o[i];
321: }
322: return rn;
323: }
324:
325: /**
326: * String representation of the given element <method>
327: * @param m an element <method>
328: * @return String representation of the given element method
329: */
330: public static String methodElementToString(
331: org.objectweb.jonas_ejb.deployment.xml.Method m) {
332: return methodElementToString(m.getMethodIntf(), m
333: .getMethodName(), m.getMethodParams());
334: }
335:
336: /**
337: * get a String representation of a method from it's XML representation
338: */
339: protected static String methodElementToString(String intf,
340: String name, MethodParams params) {
341: String s = new String();
342: if (intf != null) {
343: s = s.concat(intf + ".");
344: }
345: s = s.concat(name);
346: if (params != null) {
347: s = s.concat("(");
348: for (Iterator i = params.getMethodParamList().iterator(); i
349: .hasNext();) {
350: s = s.concat((String) i.next());
351: if (i.hasNext()) {
352: s = s.concat(",");
353: }
354: }
355: s = s.concat(")");
356: }
357: return (s);
358: }
359:
360: /**
361: * get a String representation of a method from the reflection object
362: */
363: public static String toString(Method m) {
364: StringBuffer ret = new StringBuffer();
365: ret.append(m.getDeclaringClass().getName());
366: ret.append('.');
367: ret.append(m.getName());
368: ret.append('(');
369: Class[] params = m.getParameterTypes();
370: for (int i = 0; i < params.length; i++) {
371: ret.append(getClassName(params[i]));
372: if (i == params.length - 1) {
373: break;
374: }
375: ret.append(',');
376: }
377: ret.append(')');
378: return ret.toString();
379: }
380:
381: /**
382: * return the method to which the meta-information applies
383: */
384: public Method getMethod() {
385: return meth;
386: }
387:
388: /**
389: * get the parent node
390: */
391: public BeanDesc getBeanDesc() {
392: return beanDesc;
393: }
394:
395: /**
396: * access if a method is a finder
397: */
398: public static boolean isFinder(Method meth) {
399: return (meth.getName().startsWith("find") && (javax.ejb.EJBHome.class
400: .isAssignableFrom(meth.getDeclaringClass()) || javax.ejb.EJBLocalHome.class
401: .isAssignableFrom(meth.getDeclaringClass())));
402: }
403:
404: /**
405: * access if a method is findByPrimaryKey
406: */
407: public static boolean isFindByPrimaryKey(Method meth) {
408: return (meth.getName().equals("findByPrimaryKey") && (javax.ejb.EJBHome.class
409: .isAssignableFrom(meth.getDeclaringClass()) || javax.ejb.EJBLocalHome.class
410: .isAssignableFrom(meth.getDeclaringClass())));
411: }
412:
413: /**
414: * access if a method is a select
415: */
416: public static boolean isEjbSelect(Method meth) {
417: return (meth.getName().startsWith("ejbSelect") && javax.ejb.EntityBean.class
418: .isAssignableFrom(meth.getDeclaringClass()));
419: }
420:
421: /**
422: * String representation of the object for test purpose
423: * @return String representation of this object
424: */
425: public String toString() {
426: StringBuffer ret = new StringBuffer();
427: ret.append("\ngetTxAttribute() = "
428: + ATTR[getTxAttribute()]);
429: ret.append("\ngetTxAttributeStatus() = "
430: + APPLY_TO[getTxAttributeStatus()]);
431: ret.append("\nMethodIndex = " + index);
432: ret.append("\nmeth = " + toString(meth));
433: ret.append("\nisFinder = " + isFinder);
434: ret.append("\nisEjbSelect = " + isEjbSelect);
435: ret.append("\nisFindByPrimaryKey = " + isFindByPrimaryKey);
436: if (!roleName.isEmpty()) {
437: ret.append("\ngetRoleName() = [");
438: String[] rn = getRoleName();
439: for (int i = 0; i < rn.length - 1; i++) {
440: ret.append(rn[i] + ", ");
441: }
442: ret.append(rn[rn.length - 1] + "]");
443: ret.append("\n");
444: }
445: return ret.toString();
446: }
447:
448: /**
449: * @return true if this method is excluded (in DD), else false
450: */
451: public boolean isExcluded() {
452: return excluded;
453: }
454:
455: /**
456: * Sets the excluded attribute.
457: * @param excluded true of false
458: */
459: public void setExcluded(boolean excluded) {
460: this.excluded = excluded;
461: }
462: }
|