001: /**
002: * EasyBeans
003: * Copyright (C) 2007 Bull S.A.S.
004: * Contact: easybeans@ow2.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: ENCBindingBuilder.java 2067 2007-11-27 10:03:12Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.ow2.easybeans.deployment.enc;
025:
026: import java.util.Arrays;
027: import java.util.List;
028:
029: import org.ow2.easybeans.asm.Type;
030: import org.ow2.easybeans.deployment.annotations.JMethod;
031: import org.ow2.easybeans.deployment.annotations.impl.JAnnotationResource;
032: import org.ow2.easybeans.deployment.annotations.impl.JavaxPersistenceContext;
033: import org.ow2.easybeans.deployment.annotations.impl.JavaxPersistenceUnit;
034: import org.ow2.easybeans.deployment.annotations.metadata.ClassAnnotationMetadata;
035: import org.ow2.easybeans.deployment.annotations.metadata.CommonAnnotationMetadata;
036: import org.ow2.easybeans.deployment.annotations.metadata.EjbJarAnnotationMetadata;
037: import org.ow2.easybeans.deployment.annotations.metadata.FieldAnnotationMetadata;
038: import org.ow2.easybeans.deployment.annotations.metadata.MethodAnnotationMetadata;
039: import org.ow2.easybeans.deployment.api.IJAnnotationResource;
040: import org.ow2.easybeans.deployment.api.IJavaxPersistenceContext;
041: import org.ow2.easybeans.deployment.api.IJavaxPersistenceUnit;
042:
043: /**
044: * Utility class that helps to build the ENC Binding by analyzing metadata.
045: * @author Florent BENOIT
046: */
047: public class ENCBindingBuilder {
048:
049: /**
050: * All class metadata are kept by this object.
051: */
052: private EjbJarAnnotationMetadata ejbJarAnnotationMetadata = null;
053:
054: /**
055: * Binding holder object.
056: */
057: private ENCBindingHolder bindingHolder = null;
058:
059: /**
060: * Replace length to create default JNDI names.
061: */
062: private static final int GETTER_LENGTH = 3;
063:
064: /**
065: * Constructor used only by this class/subclasses.
066: * @param ejbJarAnnotationMetadata the given metadata to analyze.
067: */
068: protected ENCBindingBuilder(
069: final EjbJarAnnotationMetadata ejbJarAnnotationMetadata) {
070: this .ejbJarAnnotationMetadata = ejbJarAnnotationMetadata;
071: this .bindingHolder = new ENCBindingHolder();
072: }
073:
074: /**
075: * Analyze the metadata and populate the binding holder.
076: * @throws ENCBindingException if the analyze is failing.
077: */
078: protected void analyze() throws ENCBindingException {
079:
080: // Analyze each class
081: for (ClassAnnotationMetadata classMetadata : ejbJarAnnotationMetadata
082: .getClassAnnotationMetadataCollection()) {
083: analyzeClassMetadata(classMetadata);
084: }
085: }
086:
087: /**
088: * Analyze the given class metadata.
089: * @param classMetadata the given metadata to analyze.
090: * @throws ENCBindingException if the class has not been analyzed
091: */
092: protected void analyzeClassMetadata(
093: final ClassAnnotationMetadata classMetadata)
094: throws ENCBindingException {
095: // Are there persistence context (only on Class)
096: List<JavaxPersistenceContext> javaxPersistenceContexts = classMetadata
097: .getJavaxPersistencePersistenceContexts();
098: if (javaxPersistenceContexts != null) {
099: for (JavaxPersistenceContext javaxPersistenceContext : javaxPersistenceContexts) {
100: addPersistenceContext(javaxPersistenceContext);
101: }
102: }
103:
104: // Are there persistence unit (only on Class)
105: List<JavaxPersistenceUnit> javaxPersistenceUnits = classMetadata
106: .getJavaxPersistencePersistenceUnits();
107: if (javaxPersistenceUnits != null) {
108: for (JavaxPersistenceUnit javaxPersistenceUnit : javaxPersistenceUnits) {
109: addPersistenceUnit(javaxPersistenceUnit);
110: }
111: }
112:
113: // Are there resource (only on Class)
114: List<JAnnotationResource> jAnnotationResources = classMetadata
115: .getJAnnotationResources();
116: if (jAnnotationResources != null) {
117: for (JAnnotationResource jAnnotationResource : jAnnotationResources) {
118: addResource(jAnnotationResource);
119: }
120: }
121:
122: // Analyze common stuff on the class
123: analyzeCommonMetadata(classMetadata);
124:
125: // Then, analyze each field of the class
126: for (FieldAnnotationMetadata fieldAnnotationMetadata : classMetadata
127: .getFieldAnnotationMetadataCollection()) {
128: analyzeFieldMetadata(fieldAnnotationMetadata);
129: }
130:
131: // And each method of the class
132: for (MethodAnnotationMetadata methodAnnotationMetadata : classMetadata
133: .getMethodAnnotationMetadataCollection()) {
134: analyzeMethodMetadata(methodAnnotationMetadata);
135: }
136:
137: }
138:
139: /**
140: * Analyze the given field metadata.
141: * @param fieldMetadata the given metadata to analyze.
142: * @throws ENCBindingException if the field has not been analyzed
143: */
144: protected void analyzeFieldMetadata(
145: final FieldAnnotationMetadata fieldMetadata)
146: throws ENCBindingException {
147: // Analyze common stuff on the field
148: analyzeCommonMetadata(fieldMetadata);
149: }
150:
151: /**
152: * Analyze the given method metadata.
153: * @param methodAnnotationMetadata the given metadata to analyze.
154: * @throws ENCBindingException if the method has not been analyzed
155: */
156: protected void analyzeMethodMetadata(
157: final MethodAnnotationMetadata methodAnnotationMetadata)
158: throws ENCBindingException {
159: // Analyze common stuff on the method
160: analyzeCommonMetadata(methodAnnotationMetadata);
161: }
162:
163: /**
164: * Analyze the given common metadata.
165: * @param commonAnnotationMetadata the given metadata to analyze.
166: * @throws ENCBindingException if the common metadata has not been analyzed
167: */
168: protected void analyzeCommonMetadata(
169: final CommonAnnotationMetadata commonAnnotationMetadata)
170: throws ENCBindingException {
171: JavaxPersistenceContext javaxPersistenceContext = commonAnnotationMetadata
172: .getJavaxPersistenceContext();
173: if (javaxPersistenceContext != null) {
174: // Set name if null
175: if (isNullOrEmpty(javaxPersistenceContext.getName())) {
176: javaxPersistenceContext.setName(getName(
177: commonAnnotationMetadata,
178: javaxPersistenceContext));
179: }
180: addPersistenceContext(javaxPersistenceContext);
181: }
182:
183: JavaxPersistenceUnit javaxPersistenceUnit = commonAnnotationMetadata
184: .getJavaxPersistenceUnit();
185: if (javaxPersistenceUnit != null) {
186: // Set name if null
187: if (isNullOrEmpty(javaxPersistenceUnit.getName())) {
188: javaxPersistenceUnit
189: .setName(getName(commonAnnotationMetadata,
190: javaxPersistenceUnit));
191: }
192: addPersistenceUnit(javaxPersistenceUnit);
193: }
194:
195: IJAnnotationResource jAnnotationResource = commonAnnotationMetadata
196: .getJAnnotationResource();
197: if (jAnnotationResource != null) {
198: // Set name if null
199: if (isNullOrEmpty(jAnnotationResource.getName())) {
200: jAnnotationResource.setName(getName(
201: commonAnnotationMetadata, jAnnotationResource));
202: }
203: jAnnotationResource.setType(getType(
204: commonAnnotationMetadata, jAnnotationResource));
205: addResource(jAnnotationResource);
206: }
207:
208: }
209:
210: /**
211: * Checks if the given string is empty or null.
212: * @param name the given string to test
213: * @return true if the string is null or empty
214: */
215: private boolean isNullOrEmpty(final String name) {
216: return (name == null) || "".equals(name);
217: }
218:
219: /**
220: * Gets the ENC name for the given metadata.
221: * @param commonAnnotationMetadata the metadata to analyze.
222: * @param o the given object associated to the metadata (used for logging).
223: * @return the given ENC name
224: * @throws ENCBindingException if no name has been defined on the given name
225: * and the metadata is invalid.
226: */
227: private String getName(
228: final CommonAnnotationMetadata commonAnnotationMetadata,
229: final Object o) throws ENCBindingException {
230: if (commonAnnotationMetadata instanceof FieldAnnotationMetadata) {
231: FieldAnnotationMetadata fieldAnnotationMetadata = (FieldAnnotationMetadata) commonAnnotationMetadata;
232: return fieldAnnotationMetadata.getClassAnnotationMetadata()
233: .getClassName().replace("/", ".")
234: + "/" + fieldAnnotationMetadata.getFieldName();
235: }
236:
237: if (commonAnnotationMetadata instanceof MethodAnnotationMetadata) {
238: MethodAnnotationMetadata methodAnnotationMetadata = (MethodAnnotationMetadata) commonAnnotationMetadata;
239:
240: StringBuilder propertyBuilder = new StringBuilder(
241: methodAnnotationMetadata.getMethodName());
242: propertyBuilder.delete(0, GETTER_LENGTH);
243: propertyBuilder.setCharAt(0, Character
244: .toLowerCase(propertyBuilder.charAt(0)));
245: propertyBuilder.insert(0, methodAnnotationMetadata
246: .getClassAnnotationMetadata().getClassName()
247: .replace("/", ".")
248: + "/");
249: return propertyBuilder.toString();
250: }
251:
252: // Last case is the Class case.
253: throw new ENCBindingException(
254: "There is no defined name in the object '" + o
255: + "' that is defined on the class '"
256: + commonAnnotationMetadata + "'.");
257:
258: }
259:
260: /**
261: * Gets the type for the given metadata.
262: * @param commonAnnotationMetadata the metadata to analyze.
263: * @param jAnnotationResource the given annotation resouce object
264: * @return the given type value (interface)
265: * @throws ENCBindingException if no name has been defined on the given name
266: * and the metadata is invalid.
267: */
268: private String getType(
269: final CommonAnnotationMetadata commonAnnotationMetadata,
270: final IJAnnotationResource jAnnotationResource)
271: throws ENCBindingException {
272: if (commonAnnotationMetadata instanceof FieldAnnotationMetadata) {
273: FieldAnnotationMetadata fieldAnnotationMetadata = (FieldAnnotationMetadata) commonAnnotationMetadata;
274: Type typeInterface = Type.getType(fieldAnnotationMetadata
275: .getJField().getDescriptor());
276: return typeInterface.getClassName();
277: } else if (commonAnnotationMetadata instanceof MethodAnnotationMetadata) {
278: MethodAnnotationMetadata methodAnnotationMetadata = (MethodAnnotationMetadata) commonAnnotationMetadata;
279:
280: JMethod jMethod = methodAnnotationMetadata.getJMethod();
281: Type[] args = Type
282: .getArgumentTypes(jMethod.getDescriptor());
283: if (args.length != 1) {
284: throw new ENCBindingException("Method args '"
285: + Arrays.asList(args) + "' for method '"
286: + jMethod
287: + "' are invalid. Length should be of 1.");
288: }
289: Type typeInterface = args[0];
290: return typeInterface.getClassName();
291: }
292:
293: return jAnnotationResource.getType();
294: }
295:
296: /**
297: * Adds the given persistence context to the list of bindings.
298: * @param javaxPersistenceContext the given persistence context.
299: */
300: protected void addPersistenceContext(
301: final IJavaxPersistenceContext javaxPersistenceContext) {
302: bindingHolder
303: .addPersistenceContextBinding(new ENCBinding<IJavaxPersistenceContext>(
304: javaxPersistenceContext.getName(),
305: javaxPersistenceContext));
306: }
307:
308: /**
309: * Adds the given persistence unit to the list of bindings.
310: * @param javaxPersistenceUnit the given persistence unit.
311: */
312: protected void addPersistenceUnit(
313: final IJavaxPersistenceUnit javaxPersistenceUnit) {
314: bindingHolder
315: .addPersistenceUnitBinding(new ENCBinding<IJavaxPersistenceUnit>(
316: javaxPersistenceUnit.getName(),
317: javaxPersistenceUnit));
318: }
319:
320: /**
321: * Adds the given resource to the list of bindings.
322: * @param jAnnotationResource the given resource.
323: */
324: protected void addResource(
325: final IJAnnotationResource jAnnotationResource) {
326: bindingHolder
327: .addResourceBinding(new ENCBinding<IJAnnotationResource>(
328: jAnnotationResource.getName(),
329: jAnnotationResource));
330: }
331:
332: /**
333: * @return the Holder of all ENC bindings.
334: */
335: protected ENCBindingHolder getHolder() {
336: return bindingHolder;
337: }
338:
339: /**
340: * Found all ENC bindings from the given set of metadata.
341: * @param ejbJarAnnotationMetadata the given metadata to analyze.
342: * @return object that contains all bindings found for the given set of
343: * classes.
344: * @throws ENCBindingException if the analyze of the set of the metadata has
345: * failed.
346: */
347: public static ENCBindingHolder analyze(
348: final EjbJarAnnotationMetadata ejbJarAnnotationMetadata)
349: throws ENCBindingException {
350: ENCBindingBuilder bindingBuilder = new ENCBindingBuilder(
351: ejbJarAnnotationMetadata);
352: bindingBuilder.analyze();
353: return bindingBuilder.getHolder();
354: }
355: }
|