001: /*--------------------------------------------------------------------------*
002: | Copyright (C) 2006 Christopher Kohlhaas |
003: | |
004: | This program is free software; you can redistribute it and/or modify |
005: | it under the terms of the GNU General Public License as published by the |
006: | Free Software Foundation. A copy of the license has been included with |
007: | these distribution in the COPYING file, if not go to www.fsf.org |
008: | |
009: | As a special exception, you are granted the permissions to link this |
010: | program with every library, which license fulfills the Open Source |
011: | Definition as published by the Open Source Initiative (OSI). |
012: *--------------------------------------------------------------------------*/
013: package org.rapla.storage.dbsql;
014:
015: import java.sql.Connection;
016: import java.sql.PreparedStatement;
017: import java.sql.ResultSet;
018: import java.sql.SQLException;
019: import java.sql.Statement;
020: import java.util.ArrayList;
021: import java.util.Calendar;
022: import java.util.Collection;
023: import java.util.Iterator;
024: import java.util.Locale;
025: import java.util.Map;
026: import java.util.Random;
027: import java.util.StringTokenizer;
028:
029: import org.apache.avalon.framework.logger.Logger;
030: import org.rapla.entities.Category;
031: import org.rapla.entities.EntityNotFoundException;
032: import org.rapla.entities.RaplaType;
033: import org.rapla.entities.dynamictype.DynamicType;
034: import org.rapla.entities.storage.EntityResolver;
035: import org.rapla.entities.storage.RefEntity;
036: import org.rapla.entities.storage.internal.SimpleIdentifier;
037: import org.rapla.framework.RaplaContext;
038: import org.rapla.framework.RaplaContextException;
039: import org.rapla.framework.RaplaException;
040: import org.rapla.framework.RaplaLocale;
041: import org.rapla.storage.LocalCache;
042: import org.rapla.storage.impl.EntityStore;
043: import org.rapla.storage.xml.PreferenceReader;
044: import org.rapla.storage.xml.PreferenceWriter;
045: import org.rapla.storage.xml.RaplaInput;
046: import org.rapla.storage.xml.RaplaXMLReader;
047: import org.rapla.storage.xml.RaplaXMLWriter;
048:
049: abstract class EntityStorage implements Storage {
050: Random random = new Random();
051:
052: String insertSql;
053: String updateSql;
054: String deleteSql;
055: String selectSql;
056: String deleteAllSql;
057: String searchForIdSql;
058:
059: RaplaContext sm;
060: LocalCache cache;
061: private EntityStore entityStore;
062: private RaplaLocale raplaLocale;
063:
064: Collection subStores = new ArrayList();
065: Connection con;
066: int lastParameterIndex;
067: /** first paramter is 1 */
068: final String tableName;
069:
070: Logger logger;
071:
072: protected EntityStorage(RaplaContext context, String table,
073: String[] entries) throws RaplaException {
074: this .sm = context;
075: if (context.has(EntityStore.class.getName())) {
076: this .entityStore = (EntityStore) context
077: .lookup(EntityStore.class.getName());
078: }
079: if (context.has(LocalCache.class.getName())) {
080: this .cache = (LocalCache) context.lookup(LocalCache.class
081: .getName());
082: }
083: this .raplaLocale = (RaplaLocale) sm.lookup(RaplaLocale.ROLE);
084: logger = (Logger) context.lookup(Logger.class.getName());
085: lastParameterIndex = entries.length;
086: tableName = table;
087: createSQL(table, entries);
088: if (getLogger().isDebugEnabled()) {
089: getLogger().debug(insertSql);
090: getLogger().debug(updateSql);
091: getLogger().debug(deleteSql);
092: getLogger().debug(selectSql);
093: getLogger().debug(deleteAllSql);
094: }
095: }
096:
097: protected Logger getLogger() {
098: return logger;
099: }
100:
101: protected void createSQL(String table, String[] entries) {
102: String idString = entries[0];
103: selectSql = "select " + getEntryList(entries) + " from "
104: + table;
105: deleteSql = "delete from " + table + " where " + idString
106: + "= ?";
107: insertSql = "insert into " + table + " ("
108: + getEntryList(entries) + ") values ("
109: + getMarkerList(entries.length) + ")";
110: updateSql = "update " + table + " set "
111: + getUpdateList(entries) + " where " + idString + "= ?";
112: deleteAllSql = "delete from " + table;
113: searchForIdSql = "select id from " + table + " where id = ?";
114: }
115:
116: protected void addSubStorage(Storage subStore) {
117: subStores.add(subStore);
118: }
119:
120: public void setConnection(Connection con) {
121: this .con = con;
122: Iterator it = subStores.iterator();
123: while (it.hasNext()) {
124: ((Storage) it.next()).setConnection(con);
125: }
126: }
127:
128: public Locale getLocale() {
129: return raplaLocale.getLocale();
130: }
131:
132: public java.sql.Date getSQLDate(Calendar cal) {
133: return new java.sql.Date(cal.getTime().getTime());
134: }
135:
136: public java.sql.Time getSQLTime(Calendar cal) {
137: return new java.sql.Time(cal.getTime().getTime());
138: }
139:
140: private String getEntryList(String[] entries) {
141: StringBuffer buf = new StringBuffer();
142: for (int i = 0; i < entries.length; i++) {
143: buf.append(entries[i]);
144: if (i < entries.length - 1)
145: buf.append(", ");
146: }
147: return buf.toString();
148: }
149:
150: private String getMarkerList(int length) {
151: StringBuffer buf = new StringBuffer();
152: for (int i = 0; i < length; i++) {
153: buf.append('?');
154: if (i < length - 1)
155: buf.append(',');
156: }
157: return buf.toString();
158: }
159:
160: private String getUpdateList(String[] entries) {
161: StringBuffer buf = new StringBuffer();
162: for (int i = 0; i < entries.length; i++) {
163: buf.append(entries[i]);
164: buf.append("=? ");
165: if (i < entries.length - 1)
166: buf.append(", ");
167: }
168: return buf.toString();
169: }
170:
171: public static void executeBatchedStatement(Connection con,
172: String sql) throws SQLException {
173: Statement stmt = null;
174: try {
175: stmt = con.createStatement();
176: StringTokenizer tokenizer = new StringTokenizer(sql, ";");
177: while (tokenizer.hasMoreTokens())
178: stmt.executeUpdate(tokenizer.nextToken());
179: } finally {
180: if (stmt != null)
181: stmt.close();
182: }
183: }
184:
185: String getString(ResultSet rset, int index) throws SQLException {
186: String str = rset.getString(index);
187: return (str != null) ? str : "";
188: }
189:
190: public static int getId(RefEntity entity) {
191: return ((SimpleIdentifier) entity.getId()).getKey();
192: }
193:
194: private boolean isInDatabase(RefEntity entity) throws SQLException {
195: ResultSet rset = null;
196: PreparedStatement stmt = null;
197: try {
198: stmt = con.prepareStatement(searchForIdSql);
199: stmt.setInt(1, getId(entity));
200: rset = stmt.executeQuery();
201: return rset.next();
202: } finally {
203: if (rset != null)
204: rset.close();
205: if (stmt != null)
206: stmt.close();
207: }
208: }
209:
210: public void loadAll() throws SQLException, RaplaException {
211: Statement stmt = null;
212: ResultSet rset = null;
213: try {
214: stmt = con.createStatement();
215: rset = stmt.executeQuery(selectSql);
216: while (rset.next()) {
217: load(rset);
218: }
219: } finally {
220: if (rset != null)
221: rset.close();
222: if (stmt != null)
223: stmt.close();
224: }
225: Iterator it = subStores.iterator();
226: while (it.hasNext()) {
227: ((Storage) it.next()).loadAll();
228: }
229: }
230:
231: public void insert(Collection entities) throws SQLException,
232: RaplaException {
233: Iterator it2 = entities.iterator();
234: while (it2.hasNext()) {
235: RefEntity entity = (RefEntity) it2.next();
236: insert(entity);
237: }
238: }
239:
240: public void insert(RefEntity entity) throws SQLException,
241: RaplaException {
242: Iterator it = subStores.iterator();
243: while (it.hasNext()) {
244: ((Storage) it.next()).insert(entity);
245: }
246: PreparedStatement stmt = null;
247: try {
248: stmt = con.prepareStatement(insertSql);
249: write(stmt, entity);
250: } finally {
251: if (stmt != null)
252: stmt.close();
253: }
254: }
255:
256: public void update(RefEntity entity) throws SQLException,
257: RaplaException {
258: Iterator it = subStores.iterator();
259: while (it.hasNext()) {
260: Storage storage = (Storage) it.next();
261: storage.delete(entity);
262: storage.insert(entity);
263: }
264: PreparedStatement stmt = null;
265: try {
266: stmt = con.prepareStatement(updateSql);
267: int id = getId(entity);
268: stmt.setInt(lastParameterIndex + 1, id);
269: write(stmt, entity);
270: } finally {
271: if (stmt != null)
272: stmt.close();
273: }
274: }
275:
276: public void save(RefEntity entity) throws SQLException,
277: RaplaException {
278: if (isInDatabase(entity)) {
279: update(entity);
280: } else {
281: insert(entity);
282: }
283: }
284:
285: public void delete(RefEntity entity) throws SQLException,
286: RaplaException {
287: Iterator it = subStores.iterator();
288: while (it.hasNext()) {
289: ((Storage) it.next()).delete(entity);
290: }
291:
292: PreparedStatement stmt = null;
293: try {
294: stmt = con.prepareStatement(deleteSql);
295: stmt.setInt(1, getId(entity));
296: stmt.executeUpdate();
297: } finally {
298: if (stmt != null)
299: stmt.close();
300: }
301: }
302:
303: public void deleteAll() throws SQLException {
304: Iterator it = subStores.iterator();
305: while (it.hasNext()) {
306: ((Storage) it.next()).deleteAll();
307: }
308: executeBatchedStatement(con, deleteAllSql);
309: }
310:
311: abstract protected void write(PreparedStatement stmt,
312: RefEntity entity) throws SQLException, RaplaException;
313:
314: abstract protected void load(ResultSet rs) throws SQLException,
315: RaplaException;
316:
317: public RaplaInput getReader() throws RaplaException {
318: return (RaplaInput) lookup(RaplaInput.class.getName());
319:
320: }
321:
322: public RaplaXMLReader getReaderFor(RaplaType type)
323: throws RaplaException {
324: Map readerMap = (Map) lookup(PreferenceReader.READERMAP);
325: return (RaplaXMLReader) readerMap.get(type);
326: }
327:
328: public RaplaXMLWriter getWriterFor(RaplaType type)
329: throws RaplaException {
330: Map writerMap = (Map) lookup(PreferenceWriter.WRITERMAP);
331: return (RaplaXMLWriter) writerMap.get(type);
332: }
333:
334: protected Object lookup(String role) throws RaplaException {
335: try {
336: return sm.lookup(role);
337: } catch (RaplaContextException e) {
338: throw new RaplaException(e);
339: }
340:
341: }
342:
343: protected void put(RefEntity entity) {
344: entityStore.put(entity);
345:
346: }
347:
348: protected EntityResolver getResolver() {
349: return entityStore;
350: }
351:
352: protected void putPassword(Object userId, String password) {
353: entityStore.putPassword(userId, password);
354: }
355:
356: protected DynamicType getDynamicType(String typeKey) {
357: return entityStore.getDynamicType(typeKey);
358: }
359:
360: protected RefEntity resolve(Object id)
361: throws EntityNotFoundException {
362: return entityStore.resolve(id);
363: }
364:
365: protected Category getSuperCategory() {
366: if (cache != null) {
367: return cache.getSuperCategory();
368: }
369: return entityStore.getSuperCategory();
370: }
371:
372: protected RefEntity get(Object id) {
373: return entityStore.get(id);
374: }
375: }
|