001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.amber.cfg;
031:
032: import com.caucho.amber.manager.AmberContainer;
033: import com.caucho.amber.manager.AmberPersistenceUnit;
034: import com.caucho.bytecode.JClass;
035: import com.caucho.config.*;
036: import com.caucho.loader.*;
037: import com.caucho.util.*;
038: import com.caucho.vfs.*;
039:
040: import javax.sql.DataSource;
041: import javax.persistence.spi.*;
042: import java.lang.instrument.*;
043: import java.security.*;
044: import java.net.URL;
045: import java.util.*;
046:
047: /**
048: * <persistence-unit> tag in the persistence.xml
049: */
050: public class PersistenceUnitConfig implements PersistenceUnitInfo {
051: private static final L10N L = new L10N(PersistenceUnitConfig.class);
052: private String _name;
053: private Class _provider;
054: private DataSource _jtaDataSource;
055: private DataSource _nonJtaDataSource;
056: private boolean _isExcludeUnlistedClasses;
057:
058: private URL _rootUrl;
059: private DynamicClassLoader _loader;
060:
061: private PersistenceUnitTransactionType _transactionType = PersistenceUnitTransactionType.JTA;
062:
063: private Properties _properties = new Properties();
064:
065: // className -> type
066: private HashMap<String, JClass> _classMap = new HashMap<String, JClass>();
067:
068: private ArrayList<String> _mappingFiles = new ArrayList<String>();
069:
070: private ArrayList<String> _jarFiles = new ArrayList<String>();
071:
072: private ArrayList<URL> _jarFileUrls = new ArrayList<URL>();
073:
074: public PersistenceUnitConfig(URL rootUrl) {
075: Thread thread = Thread.currentThread();
076:
077: _loader = (DynamicClassLoader) thread.getContextClassLoader();
078:
079: _rootUrl = rootUrl;
080: }
081:
082: /**
083: * Returns the unit name.
084: */
085: public String getName() {
086: return _name;
087: }
088:
089: /**
090: * Sets the unit name.
091: */
092: public void setName(String name) {
093: _name = name;
094: }
095:
096: /**
097: * Sets the transaction type.
098: */
099: public void setTransactionType(String type) {
100: if ("JTA".equals(type))
101: _transactionType = PersistenceUnitTransactionType.JTA;
102: else if ("RESOURCE_LOCAL".equals(type))
103: _transactionType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
104: else
105: throw new ConfigException(L.l(
106: "'{0}' is an unknown JPA transaction-type.", type));
107: }
108:
109: /**
110: * Sets the description.
111: */
112: public void setDescription(String description) {
113: }
114:
115: /**
116: * Sets the provider class name.
117: */
118: public void setProvider(Class provider) {
119: _provider = provider;
120:
121: Config.validate(provider, PersistenceProvider.class);
122: }
123:
124: /**
125: * Sets the provider class name.
126: */
127: public Class getProvider() {
128: return _provider;
129: }
130:
131: /**
132: * Sets the provider class name.
133: */
134: public String getPersistenceProviderClassName() {
135: if (_provider != null)
136: return _provider.getName();
137: else
138: return null;
139: }
140:
141: /**
142: * Sets the transactional data source.
143: */
144: public void setJtaDataSource(DataSource ds) {
145: _jtaDataSource = ds;
146: }
147:
148: /**
149: * Gets the transactional data source.
150: */
151: public DataSource getJtaDataSource() {
152: return _jtaDataSource;
153: }
154:
155: /**
156: * Sets the non-transactional data source.
157: */
158: public void setNonJtaDataSource(DataSource ds) {
159: _nonJtaDataSource = ds;
160: }
161:
162: /**
163: * Sets the non-transactional data source.
164: */
165: public DataSource getNonJtaDataSource() {
166: return _nonJtaDataSource;
167: }
168:
169: /**
170: * Sets the mapping file.
171: */
172: public void addMappingFile(String fileName) {
173: _mappingFiles.add(fileName);
174: }
175:
176: /**
177: * Returns the mapping files.
178: */
179: public ArrayList<String> getMappingFiles() {
180: return _mappingFiles;
181: }
182:
183: /**
184: * Sets the jars with classes.
185: */
186: public void addJarFile(String fileName) {
187: _jarFiles.add(fileName);
188: try {
189: URL url = new URL(Vfs.lookup(fileName).getURL());
190:
191: _jarFileUrls.add(url);
192: } catch (Exception e) {
193: throw ConfigException.create(e);
194: }
195: }
196:
197: /**
198: * Returns the jars with classes.
199: */
200: public ArrayList<String> getJarFiles() {
201: return _jarFiles;
202: }
203:
204: /**
205: * Adds a configured class.
206: */
207: public void addClass(String cl) {
208: // null means the class is not yet verified as:
209: // Entity | Embeddable | MappedSuperclass
210:
211: _classMap.put(cl, null);
212: }
213:
214: /**
215: * Adds a map of configured classes.
216: */
217: public void addAllClasses(Map<String, JClass> classMap) {
218: for (Map.Entry<String, JClass> entry : classMap.entrySet()) {
219: String k = entry.getKey();
220: JClass v = entry.getValue();
221:
222: if (!_classMap.containsKey(k))
223: _classMap.put(k, v);
224: }
225: }
226:
227: /**
228: * Returns true if only listed classes should be used.
229: */
230: public boolean isExcludeUnlistedClasses() {
231: return _isExcludeUnlistedClasses;
232: }
233:
234: /**
235: * Sets true if only listed classes should be used.
236: */
237: public void setExcludeUnlistedClasses(boolean isExclude) {
238: _isExcludeUnlistedClasses = isExclude;
239: }
240:
241: /**
242: * Adds the properties.
243: */
244: public PropertiesConfig createProperties() {
245: return new PropertiesConfig();
246: }
247:
248: public AmberPersistenceUnit init(AmberContainer container,
249: ArrayList<EntityMappingsConfig> entityMappings)
250: throws Exception {
251: AmberPersistenceUnit unit = new AmberPersistenceUnit(container,
252: _name);
253:
254: unit.setJPA(true);
255:
256: if (_jtaDataSource != null)
257: unit.setJtaDataSource(_jtaDataSource);
258: if (_nonJtaDataSource != null)
259: unit.setNonJtaDataSource(_nonJtaDataSource);
260:
261: unit.setEntityMappingsList(entityMappings);
262:
263: unit.init();
264:
265: for (Map.Entry<String, JClass> entry : _classMap.entrySet()) {
266: String className = entry.getKey();
267: JClass type = entry.getValue();
268:
269: unit.addEntityClass(className, type);
270: }
271:
272: unit.generate();
273:
274: return unit;
275: }
276:
277: //
278: // PersistenceUnitInfo api
279: //
280:
281: /**
282: * Returns the name.
283: */
284: public String getPersistenceUnitName() {
285: return getName();
286: }
287:
288: /**
289: * Returns the transaction handling.
290: */
291: public PersistenceUnitTransactionType getTransactionType() {
292: return _transactionType;
293: }
294:
295: /**
296: * Returns the mapping file names. The files are resource-loadable
297: * from the classpath.
298: */
299: public List<String> getMappingFileNames() {
300: return _mappingFiles;
301: }
302:
303: /**
304: * Returns the list of jars for the managed classes.
305: */
306: public List<URL> getJarFileUrls() {
307: return _jarFileUrls;
308: }
309:
310: /**
311: * Returns the root persistence unit.
312: */
313: public URL getPersistenceUnitRootUrl() {
314: return _rootUrl;
315: }
316:
317: /**
318: * Returns the list of managed classes.
319: */
320: public List<String> getManagedClassNames() {
321: ArrayList<String> names = new ArrayList<String>();
322: names.addAll(_classMap.keySet());
323:
324: return names;
325: }
326:
327: /**
328: * Returns true if only listed classes are allowed.
329: */
330: public boolean excludeUnlistedClasses() {
331: return _isExcludeUnlistedClasses;
332: }
333:
334: /**
335: * Returns a properties object.
336: */
337: public Properties getProperties() {
338: return _properties;
339: }
340:
341: /**
342: * Returns the classloader the provider should use to load classes,
343: * resources or URLs.
344: */
345: public ClassLoader getClassLoader() {
346: return _loader;
347: }
348:
349: /**
350: * Adds a class transformer.
351: */
352: public void addTransformer(ClassTransformer transformer) {
353: _loader.addTransformer(new TransformerAdapter(transformer));
354: }
355:
356: /**
357: * Returns a temporary class loader.
358: */
359: public ClassLoader getNewTempClassLoader() {
360: return _loader.getNewTempClassLoader();
361: }
362:
363: public String toString() {
364: return "PersistenceUnitConfig[" + _name + "]";
365: }
366:
367: public class PropertiesConfig {
368: public void addProperty(PropertyConfig prop) {
369: _properties.put(prop.getName(), prop.getValue());
370: }
371: }
372:
373: public static class PropertyConfig {
374: private String _name;
375: private String _value;
376:
377: public void setName(String name) {
378: _name = name;
379: }
380:
381: public String getName() {
382: return _name;
383: }
384:
385: public void setValue(String value) {
386: _value = value;
387: }
388:
389: public String getValue() {
390: return _value;
391: }
392: }
393:
394: public static class TransformerAdapter implements
395: ClassFileTransformer {
396: private ClassTransformer _transformer;
397:
398: TransformerAdapter(ClassTransformer transformer) {
399: _transformer = transformer;
400: }
401:
402: public byte[] transform(ClassLoader loader, String className,
403: Class redefineClass, ProtectionDomain domain,
404: byte[] classFileBuffer)
405: throws IllegalClassFormatException {
406: return _transformer.transform(loader, className,
407: redefineClass, domain, classFileBuffer);
408: }
409: }
410: }
|