001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.ejb.cfg21;
031:
032: import com.caucho.ejb.cfg.*;
033: import com.caucho.bytecode.JClass;
034: import com.caucho.bytecode.JMethod;
035: import com.caucho.config.ConfigException;
036: import com.caucho.ejb.gen21.BeanAssembler;
037: import com.caucho.ejb.gen21.ViewClass;
038: import com.caucho.java.gen.CallChain;
039: import com.caucho.log.Log;
040: import com.caucho.util.L10N;
041:
042: import java.rmi.RemoteException;
043: import java.util.ArrayList;
044: import java.util.HashMap;
045: import java.util.logging.Logger;
046:
047: /**
048: * Configuration for a particular view.
049: */
050: public class EjbView {
051: private static final Logger log = Log.open(EjbView.class);
052: private static final L10N L = new L10N(EjbView.class);
053:
054: private EjbBean _bean;
055:
056: private ArrayList<ApiClass> _apiList;
057:
058: private String _prefix;
059: private String _suffix;
060:
061: private HashMap<String, EjbMethod> _methodMap = new HashMap<String, EjbMethod>();
062:
063: /**
064: * Creates a new entity bean configuration.
065: */
066: public EjbView(EjbBean bean, ApiClass apiClass, String prefix,
067: String suffix) throws ConfigException {
068: _bean = bean;
069: _apiList = new ArrayList<ApiClass>();
070: _apiList.add(apiClass);
071: _prefix = prefix;
072: _suffix = suffix;
073: }
074:
075: /**
076: * Creates a new entity bean configuration.
077: */
078: public EjbView(EjbBean bean, ArrayList<ApiClass> apiList,
079: String prefix, String suffix) throws ConfigException {
080: _bean = bean;
081: _apiList = apiList;
082: _prefix = prefix;
083: _suffix = suffix;
084: }
085:
086: /**
087: * Returns the bean.
088: */
089: public EjbBean getBean() {
090: return _bean;
091: }
092:
093: protected ApiClass getApiClass() {
094: return _apiList.get(0);
095: }
096:
097: /**
098: * Returns the api class for the view.
099: */
100: protected ArrayList<ApiClass> getApiList() {
101: return _apiList;
102: }
103:
104: /**
105: * Returns the implementation class for the view.
106: */
107: public ApiClass getImplClass() {
108: return _bean.getEJBClassWrapper();
109: }
110:
111: /**
112: * Returns the prefix.
113: */
114: public String getPrefix() {
115: return _prefix;
116: }
117:
118: /**
119: * Returns the suffix.
120: */
121: protected String getSuffix() {
122: return _suffix;
123: }
124:
125: /**
126: * Returns true for a local view.
127: */
128: protected boolean isLocal() {
129: return "Local".equals(_prefix);
130: }
131:
132: /**
133: * Returns the list of methods.
134: */
135: public ArrayList<EjbMethod> getMethods() {
136: ArrayList<EjbMethod> methods = new ArrayList<EjbMethod>();
137:
138: methods.addAll(_methodMap.values());
139:
140: return methods;
141: }
142:
143: /**
144: * Introspects the bean's methods.
145: */
146: protected void introspect() throws ConfigException {
147: // find API methods matching an implementation method
148: for (ApiMethod method : getImplClass().getMethods()) {
149: EjbMethod ejbMethod = null;
150:
151: String name = method.getName();
152:
153: if (ApiClass.OBJECT.getMethod(name, method
154: .getParameterTypes()) != null
155: && !name.equals("toString")) {
156: } else if (name.startsWith("ejb"))
157: ejbMethod = introspectEJBMethod(method);
158: else
159: ejbMethod = introspectBusinessMethod(method);
160:
161: if (ejbMethod != null) {
162: _methodMap.put(getFullMethodName(ejbMethod
163: .getApiMethod()), ejbMethod);
164: }
165: }
166:
167: // find API methods with no matching implementation method
168: for (ApiMethod method : EjbBean.getMethods(_apiList)) {
169: if (method.getDeclaringClass().getName().startsWith(
170: "javax.ejb"))
171: continue;
172: else if (ApiClass.OBJECT.getMethod(method.getName(), method
173: .getParameterTypes()) != null) {
174: continue;
175: }
176:
177: EjbMethod ejbMethod = _methodMap
178: .get(getFullMethodName(method));
179:
180: if (ejbMethod != null)
181: continue;
182:
183: ejbMethod = introspectApiMethod(method);
184:
185: if (ejbMethod != null) {
186: _methodMap.put(getFullMethodName(ejbMethod
187: .getApiMethod()), ejbMethod);
188:
189: validateApiMethod(ejbMethod.getApiMethod());
190: }
191: }
192: }
193:
194: /**
195: * Introspects an ejb method.
196: */
197: protected EjbMethod introspectEJBMethod(ApiMethod method)
198: throws ConfigException {
199: return null;
200: }
201:
202: /**
203: * Introspects a business method.
204: */
205: protected EjbMethod introspectBusinessMethod(ApiMethod implMethod)
206: throws ConfigException {
207: ApiMethod apiMethod = EjbBean.getMethod(_apiList, implMethod
208: .getName(), implMethod.getParameterTypes());
209:
210: if (apiMethod == null)
211: return null;
212:
213: return createBusinessMethod(apiMethod, implMethod);
214: }
215:
216: /**
217: * Creates a new business method.
218: */
219: protected EjbMethod createBusinessMethod(ApiMethod apiMethod,
220: ApiMethod implMethod) throws ConfigException {
221: validateImplMethod(implMethod);
222:
223: return new EjbMethod(this , apiMethod, implMethod);
224: }
225:
226: /**
227: * Validate impl method.
228: */
229: protected void validateImplMethod(ApiMethod implMethod)
230: throws ConfigException {
231: if (!implMethod.isPublic()) {
232: throw error(L
233: .l(
234: "{0}: '{1}' must be public. Business method implementations must be public.",
235: implMethod.getDeclaringClass().getName(),
236: getFullMethodName(implMethod)));
237: }
238:
239: if (implMethod.isStatic()) {
240: throw error(L
241: .l(
242: "{0}: '{1}' must not be static. Business method implementations must not be static.",
243: implMethod.getDeclaringClass().getName(),
244: getFullMethodName(implMethod)));
245: }
246:
247: if (implMethod.isAbstract()) {
248: throw error(L
249: .l(
250: "{0}: '{1}' must not be abstract. Business methods must be implemented.",
251: implMethod.getDeclaringClass().getName(),
252: getFullMethodName(implMethod)));
253: }
254: }
255:
256: /**
257: * Introspects a method in the view api which does not exist in
258: * implementation bean.
259: */
260: protected EjbMethod introspectApiMethod(ApiMethod apiMethod)
261: throws ConfigException {
262: /*
263: if (apiMethod.getName().startsWith("ejbPostCreate")) {
264: // XXX: properly checked?
265: return null;
266: }
267: else
268: */
269: if (apiMethod.getName().startsWith("ejb")) {
270: throw error(L
271: .l(
272: "{0}: '{1}' must not start with 'ejb'. The EJB spec reserves all methods starting with ejb.",
273: apiMethod.getDeclaringClass().getName(),
274: getFullMethodName(apiMethod)));
275: } else
276: throw errorMissingMethod(getImplClass(), apiMethod
277: .getName(), apiMethod);
278: }
279:
280: /**
281: * Validates an API method.
282: */
283: protected void validateApiMethod(ApiMethod apiMethod)
284: throws ConfigException {
285: if ("Remote".equals(_prefix))
286: validateException(apiMethod, RemoteException.class);
287: }
288:
289: protected ConfigException errorMissingMethod(
290: ApiClass expectedClass, String expectedName,
291: ApiMethod matchMethod) {
292: return error(L.l(
293: "{0}: missing '{1}' method needed to match {2}.{3}",
294: expectedClass.getName(), getFullMethodName(
295: expectedName, matchMethod.getParameterTypes()),
296: matchMethod.getDeclaringClass().getSimpleName(),
297: getFullMethodName(matchMethod)));
298: }
299:
300: /**
301: * Assembles the generator.
302: */
303: protected void assembleView(BeanAssembler assembler,
304: String fullClassName) throws ConfigException {
305: }
306:
307: /**
308: * Assembles the generator methods.
309: */
310: protected void assembleMethods(BeanAssembler assembler,
311: ViewClass viewClass, String fullClassName)
312: throws ConfigException {
313: ArrayList<EjbMethod> methods = getMethods();
314:
315: for (int i = 0; i < methods.size(); i++) {
316: EjbMethod method = methods.get(i);
317:
318: method.assembleBean(assembler, fullClassName);
319:
320: viewClass.addMethod(method.assemble(viewClass,
321: fullClassName));
322: }
323: }
324:
325: /**
326: * Finds the matching method pattern.
327: */
328: protected EjbMethodPattern findMethodPattern(ApiMethod apiMethod,
329: String prefix) {
330: return _bean.getMethodPattern(apiMethod, prefix);
331: }
332:
333: /**
334: * Returns the transaction chain.
335: */
336: public CallChain getTransactionChain(CallChain callChain,
337: ApiMethod apiMethod, ApiMethod implMethod, String prefix) {
338: return _bean.getTransactionChain(callChain, apiMethod,
339: implMethod, prefix);
340: }
341:
342: /**
343: * Returns the transaction chain.
344: */
345: public CallChain getSecurityChain(CallChain callChain,
346: ApiMethod apiMethod, String prefix) {
347: return _bean.getSecurityChain(callChain, apiMethod, prefix);
348: }
349:
350: /**
351: * Validate the exceptions.
352: */
353: protected void validateException(ApiMethod method, Class exn)
354: throws ConfigException {
355: _bean.validateException(method, exn);
356: }
357:
358: /**
359: * Validate the exceptions.
360: */
361: protected void validateExceptions(ApiMethod method, Class[] exn)
362: throws ConfigException {
363: _bean.validateExceptions(method, exn);
364: }
365:
366: /**
367: * Returns a printable class name.
368: */
369: public static String getClassName(Class cl) {
370: if (cl != null)
371: return cl.getName();
372: else
373: return null;
374: }
375:
376: public static String getFullMethodName(ApiMethod method) {
377: return EjbBean.getFullMethodName(method);
378: }
379:
380: public static String getFullMethodName(String methodName,
381: Class[] paramTypes) {
382: return EjbBean.getFullMethodName(methodName, paramTypes);
383: }
384:
385: public static String getShortClassName(ApiClass cl) {
386: return cl.getJavaClass().getSimpleName();
387: }
388:
389: /**
390: * Returns an error.
391: */
392: public ConfigException error(String msg) {
393: return new ConfigException(msg);
394: }
395: }
|