001: /**
002: * EasyBeans
003: * Copyright (C) 2006 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: ClientEnhancer.java 2057 2007-11-21 15:35:32Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.ow2.easybeans.client;
025:
026: import static org.ow2.easybeans.enhancer.injection.InjectionClassAdapter.JAVA_LANG_OBJECT;
027:
028: import java.io.IOException;
029: import java.io.InputStream;
030: import java.util.List;
031: import java.util.Map;
032:
033: import org.ow2.easybeans.asm.ClassReader;
034: import org.ow2.easybeans.asm.ClassWriter;
035: import org.ow2.easybeans.deployment.annotations.analyzer.ScanClassVisitor;
036: import org.ow2.easybeans.deployment.annotations.metadata.ClassAnnotationMetadata;
037: import org.ow2.easybeans.deployment.annotations.metadata.EjbJarAnnotationMetadata;
038: import org.ow2.easybeans.enhancer.Enhancer;
039: import org.ow2.easybeans.enhancer.EnhancerException;
040: import org.ow2.easybeans.enhancer.client.ClientLifeCycleAdapter;
041: import org.ow2.easybeans.enhancer.injection.InjectionClassAdapter;
042: import org.ow2.easybeans.loader.EasyBeansClassLoader;
043: import org.ow2.util.log.Log;
044: import org.ow2.util.log.LogFactory;
045:
046: /**
047: * /**
048: * This enhancer is used by the client container to enhance client classes.
049: * For example, it will allow to use @EJB annotations, etc.
050: * @author Florent Benoit
051: */
052: public class ClientEnhancer extends Enhancer {
053:
054: /**
055: * Logger.
056: */
057: private static Log logger = LogFactory.getLog(ClientEnhancer.class);
058:
059: /**
060: * Creates an new enhancer.
061: * @param loader classloader where to define enhanced classes.
062: * @param ejbJarAnnotationMetadata object with references to the metadata.
063: * @param map a map allowing to give some objects to the enhancer.
064: */
065: public ClientEnhancer(final ClassLoader loader,
066: final EjbJarAnnotationMetadata ejbJarAnnotationMetadata,
067: final Map<String, Object> map) {
068: super (loader, ejbJarAnnotationMetadata, map);
069: }
070:
071: /**
072: * Allow to enhance a given set of classes.
073: * @param loader the classloader that will be used to load the classes.
074: * @param classesToEnhance the set of classes to enhance
075: * @param map a map allowing to give some objects to the enhancer.
076: * @throws EnhancerException if enhancer fails
077: */
078: public static void enhance(final ClassLoader loader,
079: final List<String> classesToEnhance,
080: final Map<String, Object> map) throws EnhancerException {
081: EjbJarAnnotationMetadata ejbJarAnnotationMetadata = new EjbJarAnnotationMetadata();
082: ScanClassVisitor scanVisitor = new ScanClassVisitor(
083: ejbJarAnnotationMetadata);
084: logger.info("ClassLoader used = {0}", loader);
085: for (String clazz : classesToEnhance) {
086: read(clazz, loader, scanVisitor, ejbJarAnnotationMetadata);
087: }
088:
089: ClientEnhancer clientEnhancer = new ClientEnhancer(loader,
090: ejbJarAnnotationMetadata, map);
091: clientEnhancer.enhance();
092: }
093:
094: /**
095: * Visits the given class and all available parent classes.
096: * @param className the class to visit.
097: * @param loader the classloader to use.
098: * @param scanVisitor the ASM visitor.
099: * @param ejbJarAnnotationMetadata the structure containing class metadata
100: * @throws EnhancerException if class can't be analyzed.
101: */
102: private static void read(final String className,
103: final ClassLoader loader,
104: final ScanClassVisitor scanVisitor,
105: final EjbJarAnnotationMetadata ejbJarAnnotationMetadata)
106: throws EnhancerException {
107: String readingClass = className;
108: if (!className.toLowerCase().endsWith(".class")) {
109: readingClass = className + ".class";
110: }
111:
112: InputStream is = loader.getResourceAsStream(readingClass);
113:
114: logger.info("Visiting class {0}", className);
115: try {
116: new ClassReader(is).accept(scanVisitor, 0);
117: } catch (IOException e) {
118: throw new EnhancerException("Cannot read the given class '"
119: + className + "'.", e);
120: }
121:
122: // get the class parsed
123: ClassAnnotationMetadata classMetadata = ejbJarAnnotationMetadata
124: .getClassAnnotationMetadata(className);
125: String super ClassName = classMetadata.getSuperName();
126: if (!super ClassName.equals(JAVA_LANG_OBJECT)) {
127: read(super ClassName, loader, scanVisitor,
128: ejbJarAnnotationMetadata);
129: }
130: try {
131: is.close();
132: } catch (IOException e) {
133: throw new EnhancerException(
134: "Cannot close the input stream for class '"
135: + className + "'.", e);
136: }
137:
138: }
139:
140: /**
141: * Override the super class method by using only the injection adapter.
142: * @throws EnhancerException if the class can't be enhanced.
143: */
144: @Override
145: public void enhance() throws EnhancerException {
146: for (ClassAnnotationMetadata classAnnotationMetadata : getEjbJarAnnotationMetadata()
147: .getClassAnnotationMetadataCollection()) {
148: ClassReader cr = getClassReader(classAnnotationMetadata);
149: ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
150: InjectionClassAdapter injectionClassAdapter = new InjectionClassAdapter(
151: classAnnotationMetadata, cw, getMap(), true);
152: ClientLifeCycleAdapter clientLifeCycleAdapter = new ClientLifeCycleAdapter(
153: classAnnotationMetadata, injectionClassAdapter);
154: cr.accept(clientLifeCycleAdapter, 0);
155:
156: ((EasyBeansClassLoader) getClassLoader())
157: .addClassDefinition(classAnnotationMetadata
158: .getClassName().replace("/", "."), cw
159: .toByteArray());
160: }
161: }
162:
163: }
|