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: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.jms.jdbc;
030:
031: import com.caucho.config.ConfigException;
032: import com.caucho.config.types.Period;
033: import com.caucho.jdbc.JdbcMetaData;
034: import com.caucho.util.L10N;
035: import com.caucho.util.Log;
036:
037: import javax.sql.DataSource;
038: import javax.annotation.PostConstruct;
039: import java.sql.Connection;
040: import java.sql.ResultSet;
041: import java.sql.SQLException;
042: import java.sql.Statement;
043: import java.util.logging.Logger;
044:
045: /**
046: * Manages the JDBC configuration.
047: */
048: public class JdbcManager {
049: static final Logger log = Log.open(JdbcManager.class);
050: static final L10N L = new L10N(JdbcManager.class);
051:
052: private DataSource _dataSource;
053:
054: private String _messageTable = "resin_jms_message";
055:
056: private String _destinationTable = "resin_jms_destination";
057: private String _destinationSequence;
058:
059: private String _consumerTable = "resin_jms_consumer";
060: private String _consumerSequence;
061:
062: private String _blob;
063: private String _longType;
064:
065: private String _tablespace; // oracle tablespace for blobs
066:
067: private boolean _isTruncateBlob;
068:
069: private long _purgeInterval = 60000L;
070: private long _pollInterval = -1;
071:
072: private JdbcMessage _jdbcMessage;
073:
074: private volatile boolean _isInit;
075:
076: public JdbcManager() {
077: }
078:
079: /**
080: * Sets the data source.
081: */
082: public void setDataSource(DataSource dataSource) {
083: _dataSource = dataSource;
084: }
085:
086: /**
087: * Gets the data source.
088: */
089: public DataSource getDataSource() {
090: return _dataSource;
091: }
092:
093: /**
094: * Returns the message table
095: */
096: public String getMessageTable() {
097: return _messageTable;
098: }
099:
100: /**
101: * Sets the message table
102: */
103: public void setMessageTable(String tableName) {
104: _messageTable = tableName;
105: }
106:
107: /**
108: * Returns the destination table
109: */
110: public String getDestinationTable() {
111: return _destinationTable;
112: }
113:
114: /**
115: * Sets the destination table
116: */
117: public void setDestinationTable(String tableName) {
118: _destinationTable = tableName;
119: }
120:
121: /**
122: * Returns the destination sequence
123: */
124: public String getDestinationSequence() {
125: return _destinationSequence;
126: }
127:
128: /**
129: * Returns the consumer table
130: */
131: public String getConsumerTable() {
132: return _consumerTable;
133: }
134:
135: /**
136: * Sets the consumer table
137: */
138: public void setConsumerTable(String tableName) {
139: _consumerTable = tableName;
140: }
141:
142: /**
143: * Returns the consumer sequence
144: */
145: public String getConsumerSequence() {
146: return _consumerSequence;
147: }
148:
149: /**
150: * Returns the meta-data.
151: */
152: public JdbcMetaData getMetaData() {
153: return JdbcMetaData.create(_dataSource);
154: }
155:
156: /**
157: * Returns the blob type.
158: */
159: public String getBlob() {
160: if (_blob == null)
161: _blob = getMetaData().getBlobType();
162:
163: return _blob;
164: }
165:
166: /**
167: * Sets the oracle tablespace.
168: */
169: public void setTablespace(String tablespace) {
170: _tablespace = tablespace;
171: }
172:
173: /**
174: * Gets the oracle tablespace
175: */
176: public String getTablespace() {
177: return _tablespace;
178: }
179:
180: /**
181: * Returns the blob type.
182: */
183: public String getLongType() {
184: if (_longType == null)
185: _longType = getMetaData().getLongType();
186:
187: return _longType;
188: }
189:
190: /**
191: * Sets the purge interval.
192: */
193: public void setPurgeInterval(Period period) {
194: _purgeInterval = period.getPeriod();
195: }
196:
197: /**
198: * Gets the purge interval.
199: */
200: public long getPurgeInterval() {
201: return _purgeInterval;
202: }
203:
204: /**
205: * Sets the poll interval for destinations that have a listener, default
206: * is to do no polling.
207: */
208: public void setPollInterval(Period pollInterval) {
209: _pollInterval = pollInterval.getPeriod();
210: }
211:
212: /**
213: * Returns the poll interval.
214: */
215: public long getPollInterval() {
216: return _pollInterval;
217: }
218:
219: /**
220: * Returns the JDBC message manager.
221: */
222: public JdbcMessage getJdbcMessage() {
223: return _jdbcMessage;
224: }
225:
226: /**
227: * Return true if blobs need to be truncated before deletion.
228: */
229: public boolean isTruncateBlob() {
230: return _isTruncateBlob;
231: }
232:
233: /**
234: * Initializes the JdbcManager
235: */
236: @PostConstruct
237: public void init() throws ConfigException, SQLException {
238: if (_isInit)
239: return;
240: _isInit = true;
241:
242: if (_dataSource == null)
243: throw new ConfigException(L
244: .l("JdbcManager requires a <data-source> element."));
245:
246: _jdbcMessage = new JdbcMessage(this );
247:
248: _jdbcMessage.init();
249:
250: initDestinationTable();
251: initConsumerTable();
252:
253: _isTruncateBlob = getMetaData().isTruncateBlobBeforeDelete();
254: }
255:
256: /**
257: * Initializes the destination table.
258: */
259: protected void initDestinationTable() throws SQLException {
260: Connection conn = _dataSource.getConnection();
261:
262: if (!getMetaData().supportsIdentity()) {
263: if (!getMetaData().supportsSequences())
264: throw new ConfigException(
265: L
266: .l("JdbcManager requires a datasource that supports either identity or sequences"));
267:
268: _destinationSequence = _destinationTable + "_cseq";
269: }
270:
271: try {
272: Statement stmt = conn.createStatement();
273: String sql = "SELECT 1 FROM " + _destinationTable
274: + " WHERE 1=0";
275:
276: try {
277: ResultSet rs = stmt.executeQuery(sql);
278: rs.next();
279: rs.close();
280: stmt.close();
281:
282: return;
283: } catch (SQLException e) {
284: log.finest(e.toString());
285: }
286:
287: log.info(L.l("creating JMS destination table {0}",
288: _destinationTable));
289:
290: String longType = getLongType();
291: String identity = longType + " PRIMARY KEY";
292:
293: if (getMetaData().supportsIdentity())
294: identity = getMetaData().createIdentitySQL(identity);
295:
296: sql = ("CREATE TABLE " + _destinationTable + " (" + " id "
297: + identity + "," + " name VARCHAR(255),"
298: + " is_topic INTEGER" + ")");
299:
300: stmt.executeUpdate(sql);
301:
302: if (!getMetaData().supportsIdentity()) {
303: _destinationSequence = _destinationTable + "_cseq";
304:
305: stmt.executeUpdate(getMetaData().createSequenceSQL(
306: _destinationSequence, 1));
307: }
308: } finally {
309: conn.close();
310: }
311: }
312:
313: /**
314: * Initializes the consumer table.
315: */
316: protected void initConsumerTable() throws SQLException {
317: if (!getMetaData().supportsIdentity())
318: _consumerSequence = _consumerTable + "_cseq";
319:
320: Connection conn = _dataSource.getConnection();
321: try {
322: Statement stmt = conn.createStatement();
323: String sql = "SELECT 1 FROM " + _consumerTable
324: + " WHERE 1=0";
325:
326: try {
327: ResultSet rs = stmt.executeQuery(sql);
328: rs.next();
329: rs.close();
330: stmt.close();
331:
332: return;
333: } catch (SQLException e) {
334: log.finest(e.toString());
335: }
336:
337: log.info(L.l("creating JMS consumer table {0}",
338: _consumerTable));
339:
340: String longType = getLongType();
341: String identity = longType + " PRIMARY KEY";
342:
343: if (getMetaData().supportsIdentity())
344: identity = getMetaData().createIdentitySQL(identity);
345:
346: sql = ("CREATE TABLE " + _consumerTable + " (" + " s_id "
347: + identity + "," + " queue " + longType + ","
348: + " client VARCHAR(255)," + " name VARCHAR(255),"
349: + " expire " + longType + "," + " read_id "
350: + longType + "," + " ack_id " + longType + ")");
351:
352: stmt.executeUpdate(sql);
353:
354: if (_consumerSequence != null)
355: stmt.executeUpdate(getMetaData().createSequenceSQL(
356: _consumerSequence, 1));
357: } finally {
358: conn.close();
359: }
360: }
361:
362: /**
363: * Returns a hash code.
364: */
365: public int hashCode() {
366: if (_dataSource == null)
367: return 0;
368: else
369: return _dataSource.hashCode();
370: }
371:
372: /**
373: * Test for equality.
374: */
375: public boolean equals(Object o) {
376: if (this == o)
377: return true;
378: else if (!(o instanceof JdbcManager))
379: return false;
380:
381: JdbcManager manager = (JdbcManager) o;
382:
383: return _dataSource != null
384: && _dataSource.equals(manager._dataSource);
385: }
386: }
|