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: * $Header:$
018: */
019: package org.apache.beehive.controls.system.ejb;
020:
021: import java.lang.reflect.Method;
022: import java.util.HashMap;
023: import java.util.Vector;
024: import javax.ejb.EJBLocalHome;
025: import javax.ejb.FinderException;
026:
027: import org.apache.beehive.controls.api.ControlException;
028:
029: /**
030: * The EJBInfo class is a support class that derives EJB information by
031: * reflecting on an EJB control interface. This is implemented by a
032: * static inner class to make this functionality accesible in both static
033: * and non-static contexts
034: */
035: public class EJBInfo {
036:
037: /**
038: * @deprecated Use the JavaBean getter / setter instead
039: */
040: public String _refName;
041:
042: /**
043: * @deprecated Use the JavaBean getter / setter instead
044: */
045: public Class _homeInterface;
046:
047: /**
048: * @deprecated Use the JavaBean getter / setter instead
049: */
050: public Class _beanInterface;
051:
052: /**
053: * @deprecated Use the JavaBean getter / setter instead
054: */
055: public String _beanType;
056:
057: /**
058: * @deprecated Use the JavaBean getter / setter instead
059: */
060: public boolean _isLocal;
061:
062: /**
063: * Derives bean attributes from the control interface
064: */
065: public EJBInfo(Class controlInterface) {
066: _refName = getEJBRefName(controlInterface);
067:
068: Class localHome = null;
069: Class localBean = null;
070: Class remoteHome = null;
071: Class remoteBean = null;
072:
073: //
074: // To identify the identify home and bean interfaces, we
075: // must reflect the interface hierarchy of the provided
076: // class.
077: //
078: Vector checkList = new Vector();
079: Class[] subintfs = controlInterface.getInterfaces();
080: for (int i = 0; i < subintfs.length; i++)
081: checkList.add(subintfs[i]);
082:
083: HashMap derivesFrom = new HashMap();
084: for (int i = 0; i < checkList.size(); i++) {
085: Class intf = (Class) checkList.elementAt(i);
086:
087: if (javax.ejb.EJBHome.class.isAssignableFrom(intf))
088: remoteHome = intf;
089: else if (javax.ejb.EJBLocalHome.class
090: .isAssignableFrom(intf))
091: localHome = intf;
092: else if (javax.ejb.EJBObject.class.isAssignableFrom(intf))
093: remoteBean = intf;
094: else if (javax.ejb.EJBLocalObject.class
095: .isAssignableFrom(intf))
096: localBean = intf;
097: else {
098: //
099: // If none of the above, add any new subinterfaces to
100: // the search list.
101: //
102: subintfs = intf.getInterfaces();
103: for (int j = 0; j < subintfs.length; j++) {
104: if (!checkList.contains(subintfs[j])) {
105: checkList.add(subintfs[j]);
106: derivesFrom.put(subintfs[j], intf);
107: }
108: }
109: }
110: }
111:
112: //
113: // From the located methods, identify the home/bean interfaces.
114: //
115: if (remoteHome != null) {
116: if (localHome != null)
117: throw new ControlException(controlInterface
118: + " extends multiple EJB home interfaces.");
119: _homeInterface = getRoot(remoteHome, derivesFrom);
120: } else if (localHome != null)
121: _homeInterface = getRoot(localHome, derivesFrom);
122: else
123: throw new ControlException(
124: controlInterface
125: + " does not extend the EJBHome or EJBLocalHome interfaces");
126:
127: if (remoteBean != null) {
128: if (localBean != null)
129: throw new ControlException("Interface "
130: + controlInterface
131: + " extends multiple EJB object interfaces.");
132: _beanInterface = getRoot(remoteBean, derivesFrom);
133: } else if (localBean != null)
134: _beanInterface = getRoot(localBean, derivesFrom);
135: else
136: throw new ControlException(
137: "Interface "
138: + controlInterface
139: + " does not extend the EJBObject or EJBLocalObject interfaces");
140:
141: // Identify the bean type via bean interface reflection
142: _beanType = "Session";
143: Method[] homeMethods = _homeInterface.getMethods();
144: for (int i = 0; i < homeMethods.length; i++) {
145: if (isFinderMethod(homeMethods[i])) {
146: _beanType = "Entity";
147: break;
148: }
149: }
150:
151: _isLocal = (EJBLocalHome.class.isAssignableFrom(_homeInterface));
152: }
153:
154: /**
155: * Unwinds the results of reflecting through the interface inheritance
156: * hierachy to find the original root class from a derived class
157: */
158: public Class getRoot(Class clazz, HashMap derivesFrom) {
159: while (derivesFrom.containsKey(clazz))
160: clazz = (Class) derivesFrom.get(clazz);
161: return clazz;
162: }
163:
164: /**
165: * Computes a unique local ejb ref name based upon the JCX class name
166: */
167: public static String getEJBRefName(Class jcxClass) {
168: return jcxClass.getName() + ".jcx";
169: }
170:
171: public String getRefName() {
172: return _refName;
173: }
174:
175: public void setRefName(String refName) {
176: _refName = refName;
177: }
178:
179: public Class getHomeInterface() {
180: return _homeInterface;
181: }
182:
183: public void setHomeInterface(Class homeInterface) {
184: _homeInterface = homeInterface;
185: }
186:
187: public Class getBeanInterface() {
188: return _beanInterface;
189: }
190:
191: public void setBeanInterface(Class beanInterface) {
192: _beanInterface = beanInterface;
193: }
194:
195: public String getBeanType() {
196: return _beanType;
197: }
198:
199: public void setBeanType(String beanType) {
200: _beanType = beanType;
201: }
202:
203: public boolean isLocal() {
204: return _isLocal;
205: }
206:
207: public void setLocal(boolean local) {
208: _isLocal = local;
209: }
210:
211: public String toString() {
212: return "{refname=" + _refName + " home="
213: + _homeInterface.getName() + " remote="
214: + _beanInterface.getName() + " type=" + _beanType
215: + " local=" + _isLocal + "}";
216: }
217:
218: protected static boolean isFinderMethod(Method m) {
219: if (!m.getName().startsWith("find")) // EJB enforced pattern
220: return false;
221: return methodThrows(m, FinderException.class);
222: }
223:
224: protected static boolean methodThrows(Method m, Class exceptionClass) {
225: Class[] exceptions = m.getExceptionTypes();
226: for (int j = 0; j < exceptions.length; j++)
227: if (exceptionClass.isAssignableFrom(exceptions[j]))
228: return true;
229: return false;
230: }
231: }
|