View Javadoc

1   /*
2    * Copyright 2004-2006 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.tuigwaa.database;
17  
18  import java.sql.SQLException;
19  import java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Properties;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.dom4j.Document;
29  import org.hibernate.HibernateException;
30  import org.hibernate.MappingException;
31  import org.hibernate.SessionFactory;
32  import org.hibernate.cfg.Configuration;
33  import org.hibernate.cfg.HbmBinder;
34  import org.hibernate.cfg.Mappings;
35  import org.hibernate.dialect.Dialect;
36  import org.hibernate.engine.Mapping;
37  import org.hibernate.mapping.Column;
38  import org.hibernate.mapping.ForeignKey;
39  import org.hibernate.mapping.PersistentClass;
40  import org.hibernate.mapping.Property;
41  import org.hibernate.mapping.Table;
42  import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
43  import org.hibernate.tool.hbm2ddl.TableMetadata;
44  import org.hibernate.type.Type;
45  import org.hibernate.util.CollectionHelper;
46  import org.seasar.framework.util.ResourceUtil;
47  import org.seasar.tuigwaa.model.core.TgwAttribute;
48  import org.seasar.tuigwaa.model.core.TgwEntity;
49  import org.seasar.tuigwaa.model.core.impl.FkAttribute;
50  import org.seasar.tuigwaa.util.TgwResource;
51  import org.seasar.tuigwaa.util.TgwUtils;
52  
53  import com.isenshi.util.extlib.HSQL18Dialect;
54  
55  /***
56   * @author nishioka
57   */
58  public class DynaConfiguration extends Configuration {
59  
60  	private static final long serialVersionUID = 188829885451057673L;
61  
62  	private Log log = LogFactory.getLog(getClass());
63  
64  	private SessionFactory factory_;
65  
66  	private Map managedEntittyMap_ = new HashMap(); //key:entityName value:entity
67  
68  	private static final String DEFAULT_CONFIG_PATH = "hibernate.cfg.xml";
69  
70  	private String dialect;
71  
72  	public DynaConfiguration(String driver) throws HibernateException {
73  		super();
74  		super.configure(ResourceUtil.getResource(DEFAULT_CONFIG_PATH));
75  		this.dialect = TgwResource.getProperty("hibernate." + driver);
76  		build();
77  	}
78  
79  	private Mapping map = new Mapping() {
80  
81  		public Type getIdentifierType(String persistentClass) throws MappingException {
82  			PersistentClass pc = ( (PersistentClass) classes.get( persistentClass ) );
83  			if ( pc == null ) {
84  				throw new MappingException( "persistent class not known: " + persistentClass );
85  			}
86  			return pc.getIdentifier().getType();
87  		}
88  
89  		public String getIdentifierPropertyName(String persistentClass) throws MappingException {
90  			final PersistentClass pc = (PersistentClass) classes.get( persistentClass );
91  			if ( pc == null ) {
92  				throw new MappingException( "persistent class not known: " + persistentClass );
93  			}
94  			if ( !pc.hasIdentifierProperty() ) return null;
95  			return pc.getIdentifierProperty().getName();
96  		}
97  
98  		public Type getReferencedPropertyType(String persistentClass, String propertyName) throws MappingException {
99  			final PersistentClass pc = (PersistentClass) classes.get( persistentClass );
100 			if ( pc == null ) {
101 				throw new MappingException( "persistent class not known: " + persistentClass );
102 			}
103 			Property prop = pc.getReferencedProperty( propertyName );
104 			if ( prop == null ) {
105 				throw new MappingException(
106 						"property not known: " + 
107 						persistentClass + '.' + propertyName
108 					);
109 			}
110 			return prop.getType();
111 
112 		}
113 	};
114 
115 	public synchronized SessionFactory getSessionFactory()
116 			throws HibernateException {
117 		if (factory_ == null) {
118 			build();
119 		}
120 		return factory_;
121 	}
122 
123 	public String getCreateSQLString(Table table) throws HibernateException {
124 		Dialect dialect = Dialect.getDialect(getProperties());
125 		return table.sqlCreateString(dialect, map, null, null);
126 	}
127 
128 	public String getDropSQLString(Table table) throws HibernateException {
129 		Dialect dialect = Dialect.getDialect(getProperties());
130 		return table.sqlDropString(dialect, null, null);
131 	}
132 
133 	public Iterator getAlterSQLString(Table table, DatabaseMetadata dbMetadata,
134 			String schema) throws HibernateException, SQLException {
135 		Dialect dialect = Dialect.getDialect(getProperties());
136 		TableMetadata tableMetadata = dbMetadata.getTableMetadata(table
137 				.getName(), null, null);
138 
139 		return table.sqlAlterStrings(dialect, map, tableMetadata, null, null);
140 	}
141 
142 	public String getCreateSchemaSQLString(String schema) {
143 		Dialect dialect = Dialect.getDialect(getProperties());
144 		if (dialect instanceof HSQL18Dialect) {
145 			return "create schema " + schema + " authorization dba";
146 		} else {
147 			return "create schema " + schema;
148 		}
149 	}
150 
151 	public String getDropSchemaSQLString(String schema) {
152 		// return "drop schema " + schema; for postgre
153 		// return "drop schema " + schema + " authorization dba";
154 		return "drop schema " + schema + " cascade";
155 	}
156 
157 	public String getForeignKeySQLString(ForeignKey fk) {
158 		Dialect dialect = Dialect.getDialect(getProperties());
159 		fk.setCascadeDeleteEnabled(true); //cascade true
160 		return fk.sqlCreateString(dialect, null, null, null);
161 	}
162 
163 	public Table addTable(String schema, TgwEntity entity) throws HibernateException,
164 			ClassNotFoundException {
165 		return addTable(schema, entity, true);
166 	}
167 
168 	public Table addTable(String schema, TgwEntity entity, boolean needRebuild)
169 			throws HibernateException, ClassNotFoundException {
170 		Mappings mappings = createMappings();
171 		Table table = addTable(schema, entity, mappings);
172 		if (needRebuild) {
173 			build();
174 		}
175 		putEntity(entity);
176 		return table;
177 	}
178 
179 	public Table alterTable(String schema, TgwEntity entity) throws Exception {
180 		doDeleteTable(schema, entity.getName(), false);
181 		Table table = addTable(schema, entity, false);
182 		resetConfiguration(schema);
183 		return table;
184 	}
185 
186 	public void deleteTable(String schema, String name) throws Exception {
187 		doDeleteTable(schema, name, true);
188 	}
189 
190 	public void deleteTable(String schema, String[] names) throws Exception {
191 		for (int i = 0; i < names.length; i++) {
192 			doDeleteTable(schema, names[i], false);
193 		}
194 		resetConfiguration(schema);
195 	}
196 
197 	// [Start] ----- Private Method -----
198 
199 	private void resetConfiguration(String schema) throws HibernateException,
200 			ClassNotFoundException {
201 		super.reset();
202 
203 		synchronized (managedEntittyMap_) {
204 			Iterator itr = managedEntittyMap_.values().iterator();
205 			while (itr.hasNext()) {
206 				TgwEntity entitiy = (TgwEntity) itr.next();
207 				addTable(schema, entitiy, false);
208 			}
209 		}
210 		build();
211 	}
212 
213 	private void putEntity(TgwEntity entity) {
214 		String name = entity.getName();
215 		synchronized (managedEntittyMap_) {
216 			managedEntittyMap_.put(name, entity);
217 		}
218 	}
219 
220 	private void removeEntity(String name) {
221 		synchronized (managedEntittyMap_) {
222 			managedEntittyMap_.remove(name);
223 		}
224 	}
225 
226 	public void build() throws HibernateException {
227 		Properties props = getProperties();
228 		props.setProperty("hibernate.dialect", dialect);
229 		setProperties(props);
230 		factory_ = buildSessionFactory();
231 		log.info("Build Session Factory : " + factory_);
232 	}
233 
234 	private Table addTable(String schema, TgwEntity entity, Mappings mappings)
235 			throws ClassNotFoundException, HibernateException {
236 
237 		Document doc = HbmDocumentFactory.create(schema, entity);
238 		HbmBinder.bindRoot(doc, mappings, CollectionHelper.EMPTY_MAP);
239 
240 		Table table = null;
241 
242 		String tableName = TgwUtils.toTableName(entity);
243 
244 		for (Iterator i = getTableMappings(); i.hasNext();) {
245 			Table aTable = (Table) i.next();
246 			String aTableName = aTable.getName();
247 
248 			if (tableName.equalsIgnoreCase(aTableName)) {
249 				table = aTable;
250 				// someda added for to work with foreign key
251 				bindForeignKey(entity, table);
252 				// end
253 				break;
254 			}
255 		}
256 		return table;
257 	}
258 
259 	private void bindForeignKey(TgwEntity entity, Table table) {
260 		Iterator fields = entity.getFieldIterator();
261 		while (fields.hasNext()) {
262 			TgwAttribute field = (TgwAttribute) fields.next();
263 			if (field instanceof FkAttribute) {
264 				FkAttribute fk = (FkAttribute) field;
265 				List list = toColumnList(fk, table);
266 				table.createForeignKey(null, list, fk.getRefEntity()
267 						.getJavaClass().getName());
268 			}
269 		}
270 	}
271 
272 	private List toColumnList(FkAttribute attr, Table table) {
273 		List list = new ArrayList();
274 		Iterator columns = table.getColumnIterator();
275 		while (columns.hasNext()) {
276 			Column col = (Column) columns.next();
277 			if (attr.getName().equalsIgnoreCase(col.getName())) {
278 				list.add(col);
279 				break;
280 			}
281 		}
282 		return list;
283 	}
284 
285 	private void doDeleteTable(String schema, String name, boolean needResetConfiguration)
286 			throws Exception {
287 		removeEntity(name);
288 		if (needResetConfiguration) {
289 			resetConfiguration(schema);
290 		}
291 	}
292 
293 	// [End] ----- Private Method -----
294 }