001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb3.interceptor;
023:
024: import java.lang.reflect.Method;
025: import java.security.AccessController;
026: import java.security.PrivilegedActionException;
027: import java.security.PrivilegedExceptionAction;
028: import java.util.ArrayList;
029:
030: import org.jboss.ejb3.metamodel.Interceptor;
031:
032: /**
033: * We cannot use annotation overrides for the interceptor stuff since they do not have a
034: * container associated with them
035: *
036: * @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
037: * @version $Revision: 60233 $
038: */
039: public class InterceptorInfo {
040: Class clazz;
041: Interceptor xml;
042:
043: //interceptor methods defined by this class
044: protected Method aroundInvoke;
045: protected Method postConstruct;
046: protected Method postActivate;
047: protected Method preDestroy;
048: protected Method prePassivate;
049:
050: //Interceptor methods defined by this class and all superclasses
051: protected Method[] aroundInvokeHierarchy;
052: protected Method[] postConstructHierarchy;
053: protected Method[] postActivateHierarchy;
054: protected Method[] preDestroyHierarchy;
055: protected Method[] prePassivateHierarchy;
056:
057: boolean haveCalculatedHierarchy;
058:
059: protected InterceptorInfo() {
060: }
061:
062: public InterceptorInfo(Class clazz) {
063: this .clazz = clazz;
064: }
065:
066: public InterceptorInfo(InterceptorInfo interceptorInfo) {
067: this .clazz = interceptorInfo.clazz;
068: this .aroundInvoke = interceptorInfo.aroundInvoke;
069: this .postConstruct = interceptorInfo.postConstruct;
070: this .postActivate = interceptorInfo.postActivate;
071: this .preDestroy = interceptorInfo.preDestroy;
072: this .prePassivate = interceptorInfo.prePassivate;
073: this .aroundInvokeHierarchy = interceptorInfo.aroundInvokeHierarchy;
074: this .postConstructHierarchy = interceptorInfo.postConstructHierarchy;
075: this .postActivateHierarchy = interceptorInfo.postActivateHierarchy;
076: this .preDestroyHierarchy = interceptorInfo.preDestroyHierarchy;
077: this .prePassivateHierarchy = interceptorInfo.prePassivateHierarchy;
078: }
079:
080: protected void setXml(Interceptor xml) {
081: this .xml = xml;
082: }
083:
084: public Interceptor getXml() {
085: return xml;
086: }
087:
088: public Method getAroundInvoke() {
089: return aroundInvoke;
090: }
091:
092: protected void setAroundInvoke(Method aroundInvoke) {
093: if (aroundInvoke == null)
094: return;
095:
096: if (this .aroundInvoke != null
097: && !this .aroundInvoke.equals(aroundInvoke)) {
098: throw new RuntimeException(
099: "Interceptors can only have one around-invoke/@AroundInvoke method - "
100: + clazz.getName());
101: }
102: this .aroundInvoke = makeAccessible(aroundInvoke);
103: }
104:
105: public Class getClazz() {
106: return clazz;
107: }
108:
109: public boolean haveCalculatedHierarchy() {
110: return haveCalculatedHierarchy;
111: }
112:
113: public Method getPostActivate() {
114: return postActivate;
115: }
116:
117: protected void setPostActivate(Method postActivate) {
118: if (postActivate == null)
119: return;
120:
121: if (this .postActivate != null
122: && !this .postActivate.equals(postActivate)) {
123: throw new RuntimeException(
124: "Interceptors can only have one post-activate/@PostActivate method - "
125: + clazz.getName());
126: }
127: this .postActivate = makeAccessible(postActivate);
128: }
129:
130: public Method getPostConstruct() {
131: return postConstruct;
132: }
133:
134: protected void setPostConstruct(Method postConstruct) {
135: if (postConstruct == null)
136: return;
137:
138: if (this .postConstruct != null
139: && !this .postConstruct.equals(postConstruct)) {
140: throw new RuntimeException(
141: "Interceptors can only have one post-construct/@PostConstruct method - "
142: + clazz.getName());
143: }
144: this .postConstruct = makeAccessible(postConstruct);
145: }
146:
147: public Method getPreDestroy() {
148: return preDestroy;
149: }
150:
151: protected void setPreDestroy(Method preDestroy) {
152: if (preDestroy == null)
153: return;
154:
155: if (this .preDestroy != null
156: && !this .preDestroy.equals(preDestroy)) {
157: throw new RuntimeException(
158: "Interceptors can only have one pre-destroy/@PreDestroy method - "
159: + clazz.getName());
160: }
161: this .preDestroy = makeAccessible(preDestroy);
162: }
163:
164: public Method getPrePassivate() {
165: return prePassivate;
166: }
167:
168: protected void setPrePassivate(Method prePassivate) {
169: if (prePassivate == null)
170: return;
171:
172: if (this .prePassivate != null
173: && !this .prePassivate.equals(prePassivate)) {
174: throw new RuntimeException(
175: "Interceptors can only have one pre-passivate/@PrePassivate method - "
176: + clazz.getName());
177: }
178: this .prePassivate = makeAccessible(prePassivate);
179: }
180:
181: public Method[] getAroundInvokes() {
182: return aroundInvokeHierarchy;
183: }
184:
185: public Method[] getPostActivates() {
186: return postActivateHierarchy;
187: }
188:
189: public Method[] getPostConstructs() {
190: return postConstructHierarchy;
191: }
192:
193: public Method[] getPreDestroys() {
194: return preDestroyHierarchy;
195: }
196:
197: public Method[] getPrePassivates() {
198: return prePassivateHierarchy;
199: }
200:
201: private Method makeAccessible(final Method method) {
202: try {
203: AccessController
204: .doPrivileged(new PrivilegedExceptionAction() {
205: public Object run() {
206: method.setAccessible(true);
207: return null;
208: }
209: });
210: } catch (PrivilegedActionException e) {
211: throw new RuntimeException(e.getException());
212: }
213:
214: return method;
215: }
216:
217: public String toString() {
218: StringBuffer sb = new StringBuffer("InterceptorInfo{class="
219: + clazz);
220: appendMethods(sb);
221: sb.append("}");
222: return sb.toString();
223: }
224:
225: protected void appendMethods(StringBuffer sb) {
226: appendMethodString(sb, "aroundInvoke", aroundInvoke);
227: appendMethodString(sb, "postConstruct", postConstruct);
228: appendMethodString(sb, "postActivate", postActivate);
229: appendMethodString(sb, "prePassivate", prePassivate);
230: appendMethodString(sb, "preDestroy", preDestroy);
231: }
232:
233: protected void appendMethodString(StringBuffer buf,
234: String methodType, Method m) {
235: if (m != null) {
236: buf.append(", " + methodType + "=" + m.getName());
237: }
238: }
239:
240: public void calculateHierarchy(InterceptorInfo super Info) {
241: if (haveCalculatedHierarchy) {
242: return;
243: }
244:
245: postConstructHierarchy = initaliseMethods(
246: (super Info != null) ? super Info.postConstructHierarchy
247: : null, postConstruct);
248: postActivateHierarchy = initaliseMethods(
249: (super Info != null) ? super Info.postActivateHierarchy
250: : null, postActivate);
251: aroundInvokeHierarchy = initaliseMethods(
252: (super Info != null) ? super Info.aroundInvokeHierarchy
253: : null, aroundInvoke);
254: prePassivateHierarchy = initaliseMethods(
255: (super Info != null) ? super Info.prePassivateHierarchy
256: : null, prePassivate);
257: preDestroyHierarchy = initaliseMethods(
258: (super Info != null) ? super Info.preDestroyHierarchy
259: : null, preDestroy);
260:
261: haveCalculatedHierarchy = true;
262: }
263:
264: private Method[] initaliseMethods(Method[] super Methods,
265: Method myMethod) {
266: if (super Methods == null && myMethod == null) {
267: return null;
268: }
269: ArrayList hierarchy = new ArrayList();
270: if (super Methods != null) {
271: //We only want to add superclass interceptor/lifecycle methods if we do not override them
272: for (int i = 0; i < super Methods.length; ++i) {
273: if (!haveMethod(super Methods[i])) {
274: hierarchy.add(super Methods[i]);
275: }
276: }
277: }
278:
279: if (myMethod != null) {
280: hierarchy.add(myMethod);
281: }
282:
283: return (Method[]) hierarchy
284: .toArray(new Method[hierarchy.size()]);
285: }
286:
287: private boolean haveMethod(Method method) {
288: try {
289: clazz.getDeclaredMethod(method.getName(), method
290: .getParameterTypes());
291: return true;
292: } catch (NoSuchMethodException e) {
293: return false;
294: }
295: }
296:
297: @Override
298: public boolean equals(Object obj) {
299: if (obj instanceof InterceptorInfo) {
300: return clazz.equals(((InterceptorInfo) obj).getClazz());
301: }
302: return false;
303: }
304:
305: @Override
306: public int hashCode() {
307: return clazz.getName().hashCode();
308: }
309:
310: }
|