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.gen;
031:
032: import com.caucho.ejb.cfg.*;
033: import com.caucho.java.JavaWriter;
034: import com.caucho.util.L10N;
035:
036: import java.io.*;
037: import java.lang.reflect.*;
038: import java.util.*;
039: import javax.annotation.security.*;
040: import javax.ejb.*;
041: import javax.interceptor.*;
042:
043: /**
044: * Represents a business method
045: */
046: public class BusinessMethodGenerator implements EjbCallChain {
047: private static final L10N L = new L10N(
048: BusinessMethodGenerator.class);
049:
050: private final View _view;
051:
052: private final ApiMethod _apiMethod;
053: private final Method _implMethod;
054:
055: private String _uniqueName;
056:
057: private boolean _isEnhanced = true;
058:
059: private String[] _roles;
060: private String _roleVar;
061:
062: private String _runAs;
063:
064: private XaCallChain _xa;
065: private SecurityCallChain _security;
066: private InterceptorCallChain _interceptor;
067:
068: public BusinessMethodGenerator(View view, ApiMethod apiMethod,
069: Method implMethod, int index) {
070: _view = view;
071:
072: _apiMethod = apiMethod;
073: _implMethod = implMethod;
074:
075: _uniqueName = "_" + _apiMethod.getName() + "_" + index;
076:
077: _interceptor = new InterceptorCallChain(this , view);
078: _xa = createXa(_interceptor);
079: _security = new SecurityCallChain(this , _xa);
080: }
081:
082: protected XaCallChain createXa(EjbCallChain next) {
083: return new XaCallChain(this , next);
084: }
085:
086: /**
087: * Returns the owning view.
088: */
089: public View getView() {
090: return _view;
091: }
092:
093: /**
094: * Returns the api method
095: */
096: public Method getApiMethod() {
097: return _apiMethod.getMethod();
098: }
099:
100: /**
101: * Returns the implementation method
102: */
103: public Method getImplMethod() {
104: return _implMethod;
105: }
106:
107: /**
108: * Returns true if the business method has any active XA annotation.
109: */
110: public boolean hasXA() {
111: return _xa.isEnhanced();
112: }
113:
114: /**
115: * Returns the xa call chain
116: */
117: public XaCallChain getXa() {
118: return _xa;
119: }
120:
121: /**
122: * Returns the security call chain
123: */
124: public SecurityCallChain getSecurity() {
125: return _security;
126: }
127:
128: /**
129: * Returns the interceptor call chain
130: */
131: public InterceptorCallChain getInterceptor() {
132: return _interceptor;
133: }
134:
135: /**
136: * Returns true if any interceptors enhance the business method
137: */
138: public boolean isEnhanced() {
139: if (_security.isEnhanced())
140: return true;
141: else if (_xa.isEnhanced())
142: return true;
143: else if (_interceptor.isEnhanced())
144: return true;
145:
146: return false;
147: }
148:
149: public void introspect(Method apiMethod, Method implMethod) {
150: _security.introspect(apiMethod, implMethod);
151: _xa.introspect(apiMethod, implMethod);
152: _interceptor.introspect(apiMethod, implMethod);
153: }
154:
155: public final void generatePrologueTop(JavaWriter out,
156: HashMap prologueMap) throws IOException {
157: if (!isEnhanced())
158: return;
159:
160: _security.generatePrologue(out, prologueMap);
161: }
162:
163: public final void generateConstructorTop(JavaWriter out,
164: HashMap prologueMap) throws IOException {
165: if (!isEnhanced())
166: return;
167:
168: _security.generateConstructor(out, prologueMap);
169: }
170:
171: public final void generate(JavaWriter out, HashMap prologueMap)
172: throws IOException {
173: if (!isEnhanced())
174: return;
175:
176: generateHeader(out);
177:
178: out.println("{");
179: out.pushDepth();
180:
181: generateContent(out);
182:
183: out.popDepth();
184: out.println("}");
185:
186: if (_interceptor.isEnhanced()) {
187: out.println();
188: out.print("private ");
189: out.printClass(_implMethod.getReturnType());
190: out.print(" __caucho_");
191: out.print(_apiMethod.getName());
192: out.print("(");
193:
194: Class[] types = _implMethod.getParameterTypes();
195: for (int i = 0; i < types.length; i++) {
196: Class type = types[i];
197:
198: if (i != 0)
199: out.print(", ");
200:
201: out.printClass(type);
202: out.print(" a" + i);
203: }
204:
205: out.println(")");
206: generateThrows(out, _implMethod.getExceptionTypes());
207: out.println();
208: out.println("{");
209: out.pushDepth();
210:
211: generateCall(out);
212:
213: out.popDepth();
214: out.println("}");
215: }
216: }
217:
218: public void generateHeader(JavaWriter out) throws IOException {
219: out.println();
220: if (_apiMethod.isPublic())
221: out.print("public ");
222: else if (_apiMethod.isProtected())
223: out.print("protected ");
224: else
225: throw new IllegalStateException(_apiMethod.toString()
226: + " must be public or protected");
227:
228: out.printClass(_apiMethod.getReturnType());
229: out.print(" ");
230: out.print(_apiMethod.getName());
231: out.print("(");
232:
233: Class[] types = _apiMethod.getParameterTypes();
234: for (int i = 0; i < types.length; i++) {
235: Class type = types[i];
236:
237: if (i != 0)
238: out.print(", ");
239:
240: if (i == types.length - 1 && type.isArray()
241: && _apiMethod.isVarArgs()) {
242: out.printClass(type.getComponentType());
243: out.print("...");
244: } else
245: out.printClass(type);
246:
247: out.print(" a" + i);
248: }
249:
250: out.println(")");
251: if (_implMethod != null)
252: generateThrows(out, _implMethod.getExceptionTypes());
253: else
254: generateThrows(out, _apiMethod.getExceptionTypes());
255: }
256:
257: protected void generateContent(JavaWriter out) throws IOException {
258: _security.generateCall(out);
259: }
260:
261: /**
262: * Generates any additional configuration in the constructor
263: */
264: public void generateConstructor(JavaWriter out, HashMap map)
265: throws IOException {
266: }
267:
268: public void generatePrologue(JavaWriter out, HashMap map)
269: throws IOException {
270: }
271:
272: protected void generateThrows(JavaWriter out, Class[] exnCls)
273: throws IOException {
274: if (exnCls.length == 0)
275: return;
276:
277: out.print(" throws ");
278:
279: for (int i = 0; i < exnCls.length; i++) {
280: if (i != 0)
281: out.print(", ");
282:
283: out.printClass(exnCls[i]);
284: }
285: out.println();
286: }
287:
288: public void generateCall(JavaWriter out) throws IOException {
289: if (!void.class.equals(_implMethod.getReturnType())) {
290: out.printClass(_implMethod.getReturnType());
291: out.println(" result;");
292: }
293:
294: generatePreCall(out);
295:
296: if (!void.class.equals(_implMethod.getReturnType()))
297: out.print("result = ");
298:
299: generateSuper(out);
300: out.print("." + _implMethod.getName() + "(");
301:
302: Class[] types = _implMethod.getParameterTypes();
303: for (int i = 0; i < types.length; i++) {
304: if (i != 0)
305: out.print(", ");
306:
307: out.print(" a" + i);
308: }
309:
310: out.println(");");
311:
312: generatePostCall(out);
313:
314: if (!void.class.equals(_implMethod.getReturnType()))
315: out.println("return result;");
316: }
317:
318: /**
319: * Generates the underlying bean instance
320: */
321: protected void generatePreCall(JavaWriter out) throws IOException {
322: }
323:
324: /**
325: * Generates the underlying bean instance
326: */
327: protected void generateSuper(JavaWriter out) throws IOException {
328: out.print("super");
329: }
330:
331: /**
332: * Generates the underlying bean instance
333: */
334: protected void generateThis(JavaWriter out) throws IOException {
335: out.print("this");
336: }
337:
338: /**
339: * Generates the underlying bean instance
340: */
341: protected void generatePostCall(JavaWriter out) throws IOException {
342: }
343:
344: boolean matches(String name, Class[] parameterTypes) {
345: if (!_apiMethod.getName().equals(name))
346: return false;
347:
348: Class[] methodTypes = _apiMethod.getParameterTypes();
349: if (methodTypes.length != parameterTypes.length)
350: return false;
351:
352: for (int i = 0; i < parameterTypes.length; i++) {
353: if (!methodTypes[i].equals(parameterTypes[i]))
354: return false;
355: }
356:
357: return true;
358: }
359:
360: public String toString() {
361: return getClass().getSimpleName() + "[" + _apiMethod + "]";
362: }
363: }
|