001: /**
002: * EasyBeans
003: * Copyright (C) 2006-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:JPersistenceUnitInfoHelper.java 1537 2007-07-08 15:31:22Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.ow2.easybeans.persistence.xml;
025:
026: import java.io.IOException;
027: import java.net.URL;
028: import java.util.Enumeration;
029: import java.util.HashMap;
030: import java.util.LinkedList;
031: import java.util.Map;
032: import java.util.Properties;
033:
034: import javax.naming.InitialContext;
035: import javax.naming.NamingException;
036: import javax.sql.DataSource;
037:
038: import org.ow2.util.log.Log;
039: import org.ow2.util.log.LogFactory;
040:
041: /**
042: * Class used to fill PersistenceInfo implementation class.
043: * @author Florent Benoit
044: */
045: public final class JPersistenceUnitInfoHelper {
046:
047: /**
048: * Default XML configuration.
049: */
050: private static final String PERSISTENCE_CONFIG = "org/ow2/easybeans/persistence/conf/preconfigured-persistence-providers.xml";
051:
052: /**
053: * Customized XML configuration.
054: */
055: private static final String DEFAULT_PERSISTENCEPROVIDER_CONFIG = "org/ow2/easybeans/persistence/conf/default-persistence-provider.xml";
056:
057: /**
058: * System property to change the default provider.
059: */
060: public static final String DEFAULT_PERSISTENCE_PROVIDER = "org.ow2.easybeans.persistence.default.provider";
061:
062: /**
063: * Logger.
064: */
065: private static Log logger = LogFactory
066: .getLog(JPersistenceUnitInfoHelper.class);
067:
068: /**
069: * Default configuration of persistence.xml (it defines the default
070: * persistence provider and links to external config, one for each provider
071: * class name.
072: */
073: private static JPersistenceUnitInfo defaultPersistenceunitInfo = null;
074:
075: /**
076: * Defines the default configuration (properties) for each persistence
077: * provider.
078: */
079: private static Map<String, JPersistenceUnitInfo> providersInfo = null;
080:
081: /**
082: * Utility class, no public constructor.
083: */
084: private JPersistenceUnitInfoHelper() {
085:
086: }
087:
088: /**
089: * Parses the given XML and complete the PersistenceUnitInfos structure
090: * before returning it.
091: * @param url the URL of the the Reader of the XML file.
092: * @return array of jPersistenceInfo which are implementation of
093: * PersistenceUnitInfo object
094: * @throws JPersistenceUnitInfoException if values are incorrect.
095: */
096: public static JPersistenceUnitInfo[] getPersistenceUnitInfo(
097: final URL url) throws JPersistenceUnitInfoException {
098: // load default values if not already loaded.
099: loadDefaultValues();
100:
101: JPersistenceUnitInfo[] jPersistenceunitInfos = JPersistenceUnitInfoLoader
102: .loadPersistenceUnitInfoImpl(url);
103:
104: for (JPersistenceUnitInfo jPersistenceunitInfo : jPersistenceunitInfos) {
105: // analyze jta datasource
106: String jtaDsName = jPersistenceunitInfo
107: .getJtaDataSourceName();
108:
109: // try to get this datasource (if not null)
110: if (jtaDsName != null && !jtaDsName.equals("")) {
111: DataSource ds = null;
112: try {
113: ds = (DataSource) new InitialContext()
114: .lookup(jtaDsName);
115: } catch (NamingException e) {
116: // TODO: Remove
117: // try with jdbc_1
118: try {
119: logger
120: .warn("Datasource named '"
121: + jtaDsName
122: + "' was not found, use instead the default jndi name jdbc_1");
123: ds = (DataSource) new InitialContext()
124: .lookup("jdbc_1");
125: } catch (NamingException ne) {
126: throw new JPersistenceUnitInfoException(
127: "Cannot get jta DataSource with the JNDI name '"
128: + jtaDsName + "'.", ne);
129: }
130: }
131: jPersistenceunitInfo.setJtaDataSource(ds);
132: }
133:
134: // analyze non jta datasource
135: String nonJtaDsName = jPersistenceunitInfo
136: .getNonJtaDataSourceName();
137: // try to get this datasource (if not null)
138: if (nonJtaDsName != null && !nonJtaDsName.equals("")) {
139: DataSource ds = null;
140: try {
141: ds = (DataSource) new InitialContext()
142: .lookup(nonJtaDsName);
143: } catch (NamingException e) {
144: // TODO: Remove
145: // try with jdbc_1
146: try {
147: logger
148: .warn("Datasource named '"
149: + nonJtaDsName
150: + "' was not found, use instead the default jndi name jdbc_1");
151: ds = (DataSource) new InitialContext()
152: .lookup("jdbc_1");
153: } catch (NamingException ne) {
154: throw new JPersistenceUnitInfoException(
155: "Cannot get non jta DataSource with the JNDI name '"
156: + nonJtaDsName + "'.", ne);
157: }
158: }
159: jPersistenceunitInfo.setNonJtaDataSource(ds);
160: }
161:
162: // Persistence Provider
163: if (jPersistenceunitInfo.getPersistenceProviderClassName() == null
164: || jPersistenceunitInfo
165: .getPersistenceProviderClassName().equals(
166: "")) {
167: logger
168: .info(
169: "No persistence provider was set, set to default value {0}.",
170: defaultPersistenceunitInfo
171: .getPersistenceProviderClassName());
172: jPersistenceunitInfo
173: .setPersistenceProviderClassName(defaultPersistenceunitInfo
174: .getPersistenceProviderClassName());
175: }
176:
177: // add properties for the given persistence provider
178: JPersistenceUnitInfo providerDefaultConf = providersInfo
179: .get(jPersistenceunitInfo
180: .getPersistenceProviderClassName());
181: if (providerDefaultConf == null) {
182: logger
183: .debug(
184: "No default configuration for the persistence provider {0}",
185: jPersistenceunitInfo
186: .getPersistenceProviderClassName());
187: } else {
188: logger
189: .debug(
190: "Found a default configuration for the persistence provider {0}",
191: jPersistenceunitInfo
192: .getPersistenceProviderClassName());
193: Properties defaultProperties = providerDefaultConf
194: .getProperties();
195: Enumeration<?> providerPropertiesEnum = defaultProperties
196: .propertyNames();
197: while (providerPropertiesEnum.hasMoreElements()) {
198: String key = (String) providerPropertiesEnum
199: .nextElement();
200: String value = defaultProperties.getProperty(key);
201: // set the value on the provider info
202: if (jPersistenceunitInfo.getProperties()
203: .getProperty(key) == null) {
204: jPersistenceunitInfo.getProperties()
205: .setProperty(key, value);
206: logger
207: .debug(
208: "Setting the property {0} with value {1}",
209: key, value);
210: }
211: }
212:
213: }
214: }
215: return jPersistenceunitInfos;
216: }
217:
218: /**
219: * Loads the default values (global configuration) and then configuration of
220: * each persistence provider.
221: * @throws JPersistenceUnitInfoException if default configuration is not found
222: */
223: private static synchronized void loadDefaultValues()
224: throws JPersistenceUnitInfoException {
225:
226: // already loaded, return.
227: if (defaultPersistenceunitInfo != null && providersInfo != null) {
228: return;
229: }
230: defaultPersistenceunitInfo = new JPersistenceUnitInfo();
231: providersInfo = new HashMap<String, JPersistenceUnitInfo>();
232:
233: // Load default values for a persistence INFO
234: ClassLoader currentCL = JPersistenceUnitInfo.class
235: .getClassLoader();
236: Enumeration<URL> urlsConfig = null;
237: try {
238: urlsConfig = currentCL.getResources(PERSISTENCE_CONFIG);
239: } catch (IOException e) {
240: throw new JPersistenceUnitInfoException(
241: "Cannot get resources with the name '"
242: + PERSISTENCE_CONFIG
243: + "' in the context classloader '"
244: + currentCL + "'.");
245: }
246:
247: // reverse the list of URLs as we want to override the values
248: LinkedList<URL> lstURLs = new LinkedList<URL>();
249: while (urlsConfig.hasMoreElements()) {
250: lstURLs.addFirst(urlsConfig.nextElement());
251: }
252:
253: // Customization ?
254: URL customizedConfig = currentCL
255: .getResource(DEFAULT_PERSISTENCEPROVIDER_CONFIG);
256: if (customizedConfig != null) {
257: lstURLs.addLast(customizedConfig);
258: }
259:
260: // For each URL, analyze properties (only one persistence unit is
261: // expected by module)
262: for (URL tmpURL : lstURLs) {
263: JPersistenceUnitInfo[] jPersistenceunitInfos = JPersistenceUnitInfoLoader
264: .loadPersistenceUnitInfoImpl(tmpURL);
265: // use first unit name
266: if (jPersistenceunitInfos.length != 1) {
267: throw new JPersistenceUnitInfoException(
268: "Each default config file should have only one persistence unit '"
269: + tmpURL + "'.");
270: }
271: JPersistenceUnitInfo pInfo = jPersistenceunitInfos[0];
272: String persistenceProviderClassName = pInfo
273: .getPersistenceProviderClassName();
274: if (persistenceProviderClassName != null) {
275: defaultPersistenceunitInfo
276: .setPersistenceProviderClassName(persistenceProviderClassName);
277: }
278:
279: // Now extract configuration of each persistence provider
280: Properties providersProperties = pInfo.getProperties();
281: Enumeration<?> providerNames = providersProperties
282: .propertyNames();
283: while (providerNames.hasMoreElements()) {
284: String providerName = (String) providerNames
285: .nextElement();
286:
287: // check if there is an existing provider, else create it
288: JPersistenceUnitInfo existingProviderInfo = providersInfo
289: .get(providerName);
290: if (existingProviderInfo == null) {
291: existingProviderInfo = new JPersistenceUnitInfo();
292: providersInfo.put(providerName,
293: existingProviderInfo);
294: }
295:
296: Enumeration<URL> urlsProviderConf = null;
297: try {
298: urlsProviderConf = currentCL
299: .getResources(providersProperties
300: .getProperty(providerName));
301: } catch (IOException e) {
302: throw new JPersistenceUnitInfoException(
303: "Cannot get resources with the name '"
304: + providerName
305: + "' in the context classloader '"
306: + currentCL + "'.");
307: }
308: // reverse order : used to override values
309: LinkedList<URL> reverseProviderConfURLs = new LinkedList<URL>();
310: while (urlsProviderConf.hasMoreElements()) {
311: reverseProviderConfURLs.addFirst(urlsProviderConf
312: .nextElement());
313: }
314:
315: if (reverseProviderConfURLs.size() == 0) {
316: logger
317: .warn(
318: "No default properties for persistence provider class named {0}",
319: providerName);
320: }
321:
322: // for each info for a provider, set the values
323: for (URL providerURLConf : reverseProviderConfURLs) {
324: JPersistenceUnitInfo[] providerPersistenceunitInfos = JPersistenceUnitInfoLoader
325: .loadPersistenceUnitInfoImpl(providerURLConf);
326: // use first unit name
327: if (providerPersistenceunitInfos.length != 1) {
328: throw new JPersistenceUnitInfoException(
329: "Each default config file should have only one persistence unit '"
330: + providerURLConf + "'.");
331: }
332: JPersistenceUnitInfo providerInfo = providerPersistenceunitInfos[0];
333:
334: // get provider info and set values
335: Properties providerProperties = providerInfo
336: .getProperties();
337: Enumeration<?> providerPropertiesEnum = providerProperties
338: .propertyNames();
339: while (providerPropertiesEnum.hasMoreElements()) {
340: String key = (String) providerPropertiesEnum
341: .nextElement();
342: String value = providerProperties
343: .getProperty(key);
344: // set the value on the provider info
345: existingProviderInfo.getProperties()
346: .setProperty(key, value);
347: }
348:
349: }
350: }
351:
352: }
353:
354: // System property ? change the default persistence provider
355: String sysPropertyPersistenceProvider = System
356: .getProperty(DEFAULT_PERSISTENCE_PROVIDER);
357: if (sysPropertyPersistenceProvider != null) {
358: logger
359: .debug(
360: "System property overriding the persistence provider ''{0}'' with the new value ''{1}''",
361: defaultPersistenceunitInfo
362: .getPersistenceProviderClassName(),
363: sysPropertyPersistenceProvider);
364: defaultPersistenceunitInfo
365: .setPersistenceProviderClassName(sysPropertyPersistenceProvider);
366: }
367:
368: logger.info("Default persistence provider set to value {0}.",
369: defaultPersistenceunitInfo
370: .getPersistenceProviderClassName());
371: }
372:
373: }
|