1 /**
2 * Copyright 2005-2006 the original author or authors.
3 *
4 * Licensed under the Gnu General Pubic License, Version 2.0 (the
5 * "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/gpl-license.php
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the Gnu General Public License for more details.
14 */
15 package org.figure8.join.core.setup;
16
17 import org.figure8.join.util.LogUtil;
18 import org.figure8.join.core.ContainerContextHandler;
19
20 import org.apache.commons.logging.Log;
21 import net.sf.hibernate.MappingException;
22 import net.sf.hibernate.cfg.Configuration;
23 import net.sf.hibernate.tool.hbm2ddl.SchemaUpdate;
24
25 import java.util.List;
26 import java.util.Properties;
27 import java.util.Enumeration;
28 /**
29 * Helper object for configuring Hibernate and its SessionFactory
30 * @author <a href="mailto:laurent.broudoux@free.fr">Laurent Broudoux</a>
31 * @version $Revision: 1.2 $
32 */
33 public class HibernateConfigurator{
34
35
36
37 /** Get a commons logger. */
38 protected static Log log = LogUtil.getLog(HibernateConfigurator.class);
39
40 /** Prefix of application properties related to hibernate. */
41 protected final static String HBN_PROPERTIES_PREFIX = "hibernate.";
42 /** Name of application property telling if Hibernate has been setup */
43 public final static String HBN_SETUP_PROPERTY = HBN_PROPERTIES_PREFIX + "setup";
44
45
46
47
48 /** Hibernate mapping files resources. */
49 private List mappingResources = null;
50 /** Hibernate configuration wrapper. */
51 private Configuration hbnConfig = null;
52 /** Application configuration wrapper. */
53 private ApplicationConfig appConfig = null;
54
55
56
57
58 /** Creates a new instance of HibernateConfigurator */
59 public HibernateConfigurator(){
60 }
61
62
63
64
65 /** @param config <code>ApplicationConfig</code> instance */
66 public void setApplicationConfig(ApplicationConfig config){
67 this.appConfig = config;
68 }
69 /** @return The <code>ApplicationConfig</code> instance used. */
70 public ApplicationConfig getApplicationConfig(){
71 return appConfig;
72 }
73
74 /**
75 * Extract hibernate related properties from ApplicationConfig.
76 * @return A set of hibernate properties already present into ApplicationConfig
77 */
78 public Properties getHibernateProperties(){
79 log.debug("Extracting Hibernate properties from application config...");
80 Properties properties = new Properties();
81
82 Enumeration keys = appConfig.getProperties().keys();
83 while (keys != null && keys.hasMoreElements()){
84 String key = (String)keys.nextElement();
85 if (key.startsWith(HBN_PROPERTIES_PREFIX))
86 properties.setProperty(key, appConfig.getProperty(key));
87 }
88 log.debug("Found " + properties.size() + " Hibernate related properties.");
89
90 return properties;
91 }
92
93 /**
94 * Configure Hibernate according to the given database details
95 * @param details Wrapper object for database connection details
96 * @param embedded Boolean telling if database to use is embedded (HSQLDB)
97 * @throws BootstrapException if application config cannot be updated
98 */
99 public synchronized void configureDatabase(DatabaseDetails details, boolean embedded) throws BootstrapException{
100 if (embedded){
101
102 String databasePath = BootstrapUtil.getBootstrapManager().getJoinHome() + "/database/joindb";
103 details.setDatabaseUrl("jdbc:hsqldb:" + databasePath);
104 log.debug("Database is embedded. Setting its Url to: " + details.getDatabaseUrl());
105 }
106
107 Properties properties = new Properties();
108 properties.setProperty("hibernate.connection.driver_class", details.getDriverClassname());
109 properties.setProperty("hibernate.connection.url", details.getDatabaseUrl());
110 properties.setProperty("hibernate.connection.username", details.getUsername());
111 properties.setProperty("hibernate.connection.password", details.getPassword());
112 properties.setProperty("hibernate.dialect", details.getDialect());
113 properties.setProperty("hibernate.c3p0.max_size", "" + details.getPoolSize());
114 properties.setProperty("hibernate.c3p0.min_size", "0");
115 properties.setProperty("hibernate.c3p0.timeout", "30");
116 properties.setProperty("hibernate.c3p0.max_statements", "0");
117
118
119 configureHibernate(properties);
120 }
121
122 /**
123 * Configure Hibernate according to the given datasource JNDI name.
124 * @param datasourceName JNDI name of the datasource to use for connections
125 * @param dialect SQL dialect implementation of the database behind datasource
126 * @throws BootstrapException if application config cannot be updated
127 */
128 public synchronized void configureDatasource(String datasourceName, String dialect) throws BootstrapException{
129
130 Properties properties = new Properties();
131 properties.setProperty("hibernate.connection.datasource", datasourceName);
132 properties.setProperty("hibernate.dialect", dialect);
133
134
135 configureHibernate(properties);
136 }
137
138
139
140
141 /**
142 * Do the real job by filling application with Hibernate properties
143 * and creating the database schema if needed.
144 * @param properties Hibernate specific properties (starting with "hibernate.")
145 * @throws BootstrapException if configuration backup or schema update fails
146 */
147 protected void configureHibernate(Properties properties) throws BootstrapException{
148 if (log.isInfoEnabled())
149 log.info("Configuring Hibernate & Application with properties: " + properties);
150
151
152 Enumeration keys = properties.keys();
153 while (keys != null && keys.hasMoreElements()){
154 String key = (String)keys.nextElement();
155 appConfig.setProperty(key, properties.getProperty(key));
156 }
157 try{
158
159 log.info("Now saving configuration before updating database schema...");
160 appConfig.save();
161 ContainerContextHandler.getInstance().refresh();
162
163 log.info("Configuration backup is ok. Updating database schema...");
164 SchemaUpdate update = new SchemaUpdate(getHibernateConfiguration());
165 update.execute(true, true);
166
167 appConfig.setProperty(HBN_SETUP_PROPERTY, "true");
168 }
169 catch (Exception e){
170 log.error("Execution of configuration backup & database schema update fails...");
171 log.error("Here's the error message: " + e.getMessage());
172 throw new BootstrapException("Configuration of Hibernate fails !", e);
173 }
174 }
175
176
177
178
179 /**
180 * Get an Hibernate configuration object with correct properties
181 * and resource mappings.
182 * @throws MappingException if resource mappings are wrong
183 * @return An Hibernate configuration wrapper
184 */
185 private Configuration getHibernateConfiguration() throws MappingException{
186 if (hbnConfig == null){
187 try{
188
189 mappingResources = (List)ContainerContextHandler.getInstance().getComponent("mappingResources");
190 }
191 catch (Exception e){
192 log.error("mappingResources component cannot be found: " + e.getMessage());
193 throw new MappingException("mappingResources component cannot be found !", e);
194 }
195
196 hbnConfig = new Configuration().setProperties(getHibernateProperties());
197
198 if (mappingResources != null && mappingResources.size() > 0){
199 for (int i=0; i<mappingResources.size(); i++)
200 hbnConfig.addResource((String)mappingResources.get(i), Thread.currentThread().getContextClassLoader());
201 }
202 }
203 return hbnConfig;
204 }
205 }