KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > versant > core > jdo > query > mem > MemQueryCompiler


1
2 /*
3  * Copyright (c) 1998 - 2005 Versant Corporation
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  * Versant Corporation - initial API and implementation
11  */

12 package com.versant.core.jdo.query.mem;
13
14
15 import com.versant.lib.bcel.Constants;
16 import com.versant.lib.bcel.classfile.JavaClass;
17 import com.versant.lib.bcel.generic.ClassGen;
18 import com.versant.lib.bcel.generic.InstructionFactory;
19
20 import com.versant.core.metadata.ClassMetaData;
21 import com.versant.core.metadata.ModelMetaData;
22 import com.versant.core.jdo.*;
23 import com.versant.core.jdo.query.ParamNode;
24 import com.versant.core.jdo.query.ParseException;
25
26 import java.util.HashMap JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.lang.reflect.Method JavaDoc;
29 import java.lang.reflect.InvocationTargetException JavaDoc;
30 import java.io.File JavaDoc;
31 import java.io.FileOutputStream JavaDoc;
32 import java.io.IOException JavaDoc;
33
34 import com.versant.core.common.BindingSupportImpl;
35
36 /**
37  * Compiler for in memory queries. This maintains a cache of precompiled
38  * queries.
39  */

40 public class MemQueryCompiler {
41
42     private final ModelMetaData jmd;
43     private final ClassLoader JavaDoc loader;
44     private Map JavaDoc compiledQueryMap = new HashMap JavaDoc();
45     private long clsCounter;
46     private Method JavaDoc defineClass;
47
48     public MemQueryCompiler(ModelMetaData jmd, ClassLoader JavaDoc loader) {
49         this.jmd = jmd;
50         this.loader = loader;
51
52         try {
53             defineClass = ClassLoader JavaDoc.class.getDeclaredMethod("defineClass",
54                     new Class JavaDoc[]{String JavaDoc.class, byte[].class, Integer.TYPE,
55                                 Integer.TYPE});
56         } catch (NoSuchMethodException JavaDoc e) {
57             // not possible really
58
throw BindingSupportImpl.getInstance().internal(e.toString(), e);
59         }
60         defineClass.setAccessible(true);
61
62     }
63
64     public synchronized BCodeQuery compile(QueryDetails queryParams, Object JavaDoc[] params) {
65         BCodeQuery bCodeQuery = (BCodeQuery)compiledQueryMap.get(queryParams);
66         if (bCodeQuery != null) return bCodeQuery;
67
68
69         boolean toFilter = true;
70         if (queryParams.getFilter() == null || queryParams.getFilter().equals(
71                 "true")) {
72             toFilter = false;
73         } else {
74             toFilter = true;
75         }
76
77         ClassMetaData classMetaData = jmd.getClassMetaData(
78                 queryParams.getCandidateClass());
79         String JavaDoc name = getQClsName();
80         ClassGen classGen = new ClassGen(name, BCodeQuery.class.getName(),
81                 "<generated>", Constants.ACC_PUBLIC | Constants.ACC_SUPER,
82                 null);
83         InstructionFactory factory = new InstructionFactory(classGen);
84         classGen.addEmptyConstructor(Constants.ACC_PUBLIC);
85
86         CompiledMemQuery compiledMemQuery = new CompiledMemQuery(jmd);
87         try {
88             compiledMemQuery.compile(queryParams);
89         } catch (ParseException e) {
90             throw BindingSupportImpl.getInstance().exception(e.getMessage());
91         }
92
93         if (toFilter) {
94             ByteCodeQVisitor byteCodeQVisitor =
95                     new ByteCodeQVisitor(classGen, factory, name,
96                     classMetaData, compiledMemQuery);
97             byteCodeQVisitor.setParamMap(
98                     createParamMap(params, compiledMemQuery));
99             compiledMemQuery.filter.visit(byteCodeQVisitor, null);
100             byteCodeQVisitor.finish();
101         }
102
103         if (queryParams.getOrdering() != null) {
104             ByteCodeQCompareVisitor byteCodeQCompareVisitor = new ByteCodeQCompareVisitor(
105                     classGen, factory, name, classMetaData);
106             for (int i = 0; i < compiledMemQuery.orders.length; i++) {
107                 compiledMemQuery.orders[i].visit(byteCodeQCompareVisitor, null);
108             }
109             byteCodeQCompareVisitor.finish();
110         }
111
112         JavaClass javaClass = classGen.getJavaClass();
113         try {
114             bCodeQuery = (BCodeQuery)defineClass(javaClass.getBytes(), null).newInstance();
115             compiledQueryMap.put(queryParams, bCodeQuery);
116         } catch (Exception JavaDoc e) {
117             if (BindingSupportImpl.getInstance().isOwnException(e)) {
118                 throw (RuntimeException JavaDoc)e;
119             }
120             throw BindingSupportImpl.getInstance().internal(e.getMessage(), e);
121         }
122
123         return bCodeQuery;
124     }
125
126     private Map JavaDoc createParamMap(Object JavaDoc[] params,
127             CompiledMemQuery compiledMemQuery) {
128         Map JavaDoc m = new HashMap JavaDoc();
129         if (compiledMemQuery.params == null) {
130             return m;
131         }
132         for (int i = 0; i < compiledMemQuery.params.length; i++) {
133             ParamNode param = compiledMemQuery.params[i];
134             m.put(param.getIdentifier(), params[i]);
135         }
136         return m;
137     }
138
139     private Class JavaDoc defineClass(byte[] bytecode, File JavaDoc dir) {
140         try {
141             Class JavaDoc cls = (Class JavaDoc)defineClass.invoke(loader, new Object JavaDoc[]{null,
142                     bytecode, new Integer JavaDoc(0), new Integer JavaDoc(bytecode.length)});
143             if (dir != null) {
144                 File JavaDoc f = new File JavaDoc(dir, cls.getName() + ".class");
145                 try {
146                     FileOutputStream JavaDoc o = new FileOutputStream JavaDoc(f);
147                     o.write(bytecode, 0, bytecode.length);
148                     o.close();
149                 } catch (IOException JavaDoc x) {
150                     throw BindingSupportImpl.getInstance().runtime(
151                             "Error writing to " + f + ": " + x, x);
152                 }
153             }
154             return cls;
155         } catch (InvocationTargetException JavaDoc e) {
156             Throwable JavaDoc t = e.getTargetException();
157             throw BindingSupportImpl.getInstance().internal(t.toString(), t);
158         } catch (Exception JavaDoc x) {
159             throw BindingSupportImpl.getInstance().internal(x.toString(), x);
160         }
161     }
162
163     private synchronized String JavaDoc getQClsName() {
164         return "VOA_QUERY_" + clsCounter++;
165     }
166
167 }
168
Popular Tags