001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.config;
018:
019: import org.apache.openejb.OpenEJBException;
020: import org.objectweb.asm.AnnotationVisitor;
021: import org.objectweb.asm.ClassReader;
022: import org.objectweb.asm.FieldVisitor;
023: import org.objectweb.asm.MethodVisitor;
024: import org.objectweb.asm.commons.EmptyVisitor;
025:
026: import javax.persistence.PersistenceContext;
027: import javax.persistence.PersistenceProperty;
028: import java.io.IOException;
029: import java.net.URL;
030: import java.util.HashMap;
031: import java.util.HashSet;
032: import java.util.LinkedHashMap;
033: import java.util.Map;
034: import java.util.Set;
035:
036: public class PersistenceContextAnnFactory {
037: private static boolean useAsm;
038: static {
039: boolean isPersistenceContextAnnotationValid = false;
040: try {
041: // Tomcat persistence context class is missing the properties method
042: Class<?> persistenceContextClass = Class
043: .forName("javax.persistence.PersistenceContext");
044: persistenceContextClass.getMethod("properties",
045: (Class[]) null);
046: isPersistenceContextAnnotationValid = true;
047: } catch (Exception e) {
048: }
049: useAsm = !isPersistenceContextAnnotationValid;
050: }
051:
052: public Map<String, AsmPersistenceContext> contexts = new HashMap<String, AsmPersistenceContext>();
053: private final Set<String> processed = new HashSet<String>();
054:
055: public void addAnnotations(Class c) throws OpenEJBException {
056: if (!useAsm)
057: return;
058: if (processed.contains(c.getName()))
059: return;
060:
061: try {
062: URL u = c.getResource("/" + c.getName().replace('.', '/')
063: + ".class");
064: ClassReader r = new ClassReader(u.openStream());
065: r.accept(new PersistenceContextReader(), true);
066: } catch (IOException e) {
067: throw new OpenEJBException("Unable to read class "
068: + c.getName());
069: }
070:
071: processed.add(c.getName());
072: }
073:
074: public PersistenceContextAnn create(
075: PersistenceContext persistenceContext,
076: AnnotationDeployer.Member member) throws OpenEJBException {
077: if (useAsm) {
078: if (member != null) {
079: addAnnotations(member.getDeclaringClass());
080: }
081:
082: String name = persistenceContext.name();
083: if (name == null || name.equals("")) {
084: name = (member == null) ? null : member
085: .getDeclaringClass().getName()
086: + "/" + member.getName();
087: }
088:
089: AsmPersistenceContext asmPersistenceContext = contexts
090: .get(name);
091: if (asmPersistenceContext == null) {
092: throw new NullPointerException("PersistenceContext "
093: + name + " not found");
094: }
095: return asmPersistenceContext;
096: } else {
097: return new DirectPersistenceContext(persistenceContext);
098: }
099: }
100:
101: private static class DirectPersistenceContext implements
102: PersistenceContextAnn {
103: private final PersistenceContext persistenceContext;
104:
105: public DirectPersistenceContext(
106: PersistenceContext persistenceContext) {
107: if (persistenceContext == null)
108: throw new NullPointerException(
109: "persistenceContext is null");
110: this .persistenceContext = persistenceContext;
111: }
112:
113: public String name() {
114: return persistenceContext.name();
115: }
116:
117: public String unitName() {
118: return persistenceContext.unitName();
119: }
120:
121: public String type() {
122: if (persistenceContext.type() == null)
123: return null;
124: return persistenceContext.type().toString();
125: }
126:
127: public Map<String, String> properties() {
128: Map<String, String> properties = new LinkedHashMap<String, String>();
129: for (PersistenceProperty property : persistenceContext
130: .properties()) {
131: properties.put(property.name(), property.value());
132: }
133: return properties;
134: }
135:
136: public String toString() {
137: return persistenceContext.toString();
138: }
139: }
140:
141: private static class AsmPersistenceContext implements
142: PersistenceContextAnn {
143: public String name;
144: public String unitName;
145: public String type;
146: public final Map<String, String> properties = new LinkedHashMap<String, String>();
147:
148: public String name() {
149: return name;
150: }
151:
152: public String unitName() {
153: return unitName;
154: }
155:
156: public String type() {
157: return type;
158: }
159:
160: public Map<String, String> properties() {
161: return properties;
162: }
163:
164: public String toString() {
165: return "@PersistenceContext(name = \"" + name
166: + "\", unitName = \"" + unitName
167: + "\", type = PersistenceContextType." + type
168: + ", " + properties + ")";
169: }
170: }
171:
172: private class PersistenceContextReader extends EmptyVisitor {
173: private String className;
174: private String currentName;
175:
176: public void visit(int version, int access, String name,
177: String signature, String super Name, String[] interfaces) {
178: className = name.replace("/", ".");
179: super .visit(version, access, name, signature, super Name,
180: interfaces);
181: }
182:
183: public FieldVisitor visitField(int access, String name,
184: String desc, String signature, Object value) {
185: currentName = name;
186: return super .visitField(access, name, desc, signature,
187: value);
188: }
189:
190: public MethodVisitor visitMethod(int access, String name,
191: String desc, String signature, String[] exceptions) {
192: currentName = name;
193:
194: // setFoo -> foo
195: if (currentName.startsWith("set")) {
196: currentName = currentName.substring(3);
197: }
198: if (currentName.length() > 0) {
199: currentName = Character.toLowerCase(currentName
200: .charAt(0))
201: + currentName.substring(1);
202: }
203:
204: return super .visitMethod(access, name, desc, signature,
205: exceptions);
206: }
207:
208: public AnnotationVisitor visitAnnotation(String desc,
209: boolean visible) {
210: return visitAnnotation(null, desc);
211: }
212:
213: public AnnotationVisitor visitAnnotation(String name,
214: String desc) {
215: if ("Ljavax/persistence/PersistenceContext;".equals(desc)) {
216: PersistenceContextVisitor visitor = new PersistenceContextVisitor(
217: className, currentName);
218: return visitor;
219: } else if ("Ljavax/persistence/PersistenceContexts;"
220: .equals(desc)) {
221: return this ;
222: }
223: return new EmptyVisitor();
224: }
225:
226: public AnnotationVisitor visitParameterAnnotation(int i,
227: String string, boolean b) {
228: return new EmptyVisitor();
229: }
230:
231: public AnnotationVisitor visitAnnotationDefault() {
232: return new EmptyVisitor();
233: }
234:
235: public AnnotationVisitor visitArray(String string) {
236: return this ;
237: }
238: }
239:
240: private class PersistenceContextVisitor implements
241: AnnotationVisitor {
242: private AsmPersistenceContext persistenceContext = new AsmPersistenceContext();
243:
244: public PersistenceContextVisitor(String className,
245: String memberName) {
246: persistenceContext.name = className + "/" + memberName;
247: }
248:
249: public void visit(String name, Object value) {
250: setValue(name, value == null ? null : value.toString());
251: }
252:
253: public void visitEnum(String name, String type, String value) {
254: setValue(name, value == null ? null : value.toString());
255: }
256:
257: public AnnotationVisitor visitAnnotation(String name,
258: String desc) {
259: setValue(name, desc);
260: return null;
261: }
262:
263: private void setValue(String name, String value) {
264: if ("name".equals(name)) {
265: persistenceContext.name = value;
266: } else if ("unitName".equals(name)) {
267: persistenceContext.unitName = value;
268: } else if ("type".equals(name)) {
269: persistenceContext.type = value;
270: }
271: }
272:
273: public AnnotationVisitor visitArray(String string) {
274: return new EmptyVisitor() {
275: private String name;
276: private String value;
277:
278: public void visit(String n, Object v) {
279: if ("name".equals(n)) {
280: name = (v == null ? null : v.toString());
281: } else if ("value".equals(n)) {
282: value = (v == null ? null : v.toString());
283: }
284: }
285:
286: public void visitEnd() {
287: persistenceContext.properties.put(name, value);
288: }
289: };
290: }
291:
292: public void visitEnd() {
293: contexts.put(persistenceContext.name, persistenceContext);
294: }
295: }
296: }
|