001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb.plugins.keygenerator.hilo;
023:
024: import org.jboss.system.ServiceMBeanSupport;
025: import org.jboss.ejb.plugins.keygenerator.KeyGeneratorFactory;
026: import org.jboss.ejb.plugins.keygenerator.KeyGenerator;
027: import org.jboss.ejb.plugins.cmp.jdbc.JDBCUtil;
028: import org.jboss.ejb.plugins.cmp.jdbc.SQLUtil;
029: import org.jboss.naming.Util;
030: import org.jboss.deployment.DeploymentException;
031: import org.jboss.tm.TransactionManagerLocator;
032: import org.jboss.mx.util.MBeanServerLocator;
033:
034: import javax.management.ObjectName;
035: import javax.naming.InitialContext;
036: import javax.naming.Context;
037: import javax.naming.NamingException;
038: import javax.sql.DataSource;
039: import javax.transaction.TransactionManager;
040: import java.io.Serializable;
041: import java.io.ObjectInputStream;
042: import java.io.IOException;
043: import java.sql.SQLException;
044: import java.sql.Connection;
045: import java.sql.Statement;
046: import java.sql.ResultSet;
047:
048: /**
049: * @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
050: * @version <tt>$Revision: 61988 $</tt>
051: * @jmx.mbean name="jboss.system:service=KeyGeneratorFactory,type=HiLo"
052: * extends="org.jboss.system.ServiceMBean"
053: */
054: public class HiLoKeyGeneratorFactory extends ServiceMBeanSupport
055: implements KeyGeneratorFactory, HiLoKeyGeneratorFactoryMBean,
056: Serializable {
057: static final long serialVersionUID = -8086895827613378739L;
058:
059: private ObjectName dataSource;
060: private transient DataSource ds;
061: private transient TransactionManager tm;
062:
063: private String jndiName;
064: private String tableName;
065: private String sequenceColumn;
066: private String sequenceName;
067: private String idColumnName;
068: private String createTableDdl;
069: private String selectHiSql;
070: private long blockSize;
071:
072: private boolean createTable = true;
073: private boolean dropTable;
074:
075: /**
076: * @jmx.managed-attribute
077: */
078: public void setFactoryName(String factoryName) {
079: this .jndiName = factoryName;
080: }
081:
082: /**
083: * @jmx.managed-attribute
084: */
085: public String getFactoryName() {
086: return jndiName;
087: }
088:
089: /**
090: * @jmx.managed-attribute
091: */
092: public void setDataSource(ObjectName dataSource) throws Exception {
093: if (getState() == STARTED
094: && !dataSource.equals(this .dataSource)) {
095: ds = lookupDataSource(dataSource);
096: }
097: this .dataSource = dataSource;
098: }
099:
100: /**
101: * @jmx.managed-attribute
102: */
103: public ObjectName getDataSource() {
104: return dataSource;
105: }
106:
107: /**
108: * @jmx.managed-operation
109: */
110: public String getTableName() {
111: return tableName;
112: }
113:
114: /**
115: * @jmx.managed-operation
116: */
117: public void setTableName(String tableName) throws Exception {
118: if (getState() == STARTED && !tableName.equals(this .tableName)) {
119: initSequence(tableName, sequenceColumn, sequenceName,
120: idColumnName);
121: }
122: this .tableName = tableName;
123: }
124:
125: /**
126: * @jmx.managed-attribute
127: */
128: public String getSequenceColumn() {
129: return sequenceColumn;
130: }
131:
132: /**
133: * @jmx.managed-attribute
134: */
135: public void setSequenceColumn(String sequenceColumn) {
136: this .sequenceColumn = sequenceColumn;
137: }
138:
139: /**
140: * @jmx.managed-attribute
141: */
142: public String getSequenceName() {
143: return sequenceName;
144: }
145:
146: /**
147: * @jmx.managed-attribute
148: */
149: public void setSequenceName(String sequenceName) {
150: this .sequenceName = sequenceName;
151: }
152:
153: /**
154: * @jmx.managed-attribute
155: */
156: public String getIdColumnName() {
157: return idColumnName;
158: }
159:
160: /**
161: * @jmx.managed-attribute
162: */
163: public void setIdColumnName(String idColumnName) {
164: this .idColumnName = idColumnName;
165: }
166:
167: /**
168: * @jmx.managed-attribute
169: */
170: public String getCreateTableDdl() {
171: return createTableDdl;
172: }
173:
174: /**
175: * @jmx.managed-attribute
176: */
177: public void setCreateTableDdl(String createTableDdl) {
178: this .createTableDdl = createTableDdl;
179: }
180:
181: /**
182: * @jmx.managed-attribute
183: */
184: public String getSelectHiSql() {
185: return selectHiSql;
186: }
187:
188: /**
189: * @jmx.managed-attribute
190: */
191: public void setSelectHiSql(String selectHiSql) {
192: this .selectHiSql = selectHiSql;
193: }
194:
195: /**
196: * @jmx.managed-attribute
197: */
198: public long getBlockSize() {
199: return blockSize;
200: }
201:
202: /**
203: * @jmx.managed-attribute
204: */
205: public void setBlockSize(long blockSize) {
206: this .blockSize = blockSize;
207: }
208:
209: /**
210: * @jmx.managed-attribute
211: */
212: public boolean isCreateTable() {
213: return createTable;
214: }
215:
216: /**
217: * @jmx.managed-attribute
218: */
219: public void setCreateTable(boolean createTable) {
220: this .createTable = createTable;
221: }
222:
223: /**
224: * @jmx.managed-attribute
225: */
226: public boolean isDropTable() {
227: return dropTable;
228: }
229:
230: /**
231: * @jmx.managed-attribute
232: */
233: public void setDropTable(boolean dropTable) {
234: this .dropTable = dropTable;
235: }
236:
237: // KeyGeneratorFactory implementation
238:
239: public KeyGenerator getKeyGenerator() throws Exception {
240: return new HiLoKeyGenerator(ds, tableName, sequenceColumn,
241: sequenceName, idColumnName, selectHiSql, blockSize, tm);
242: }
243:
244: // ServiceMBeanSupport overrides
245:
246: public void startService() throws Exception {
247: Context ctx = new InitialContext();
248:
249: // bind the factory
250: Util.rebind(ctx, getFactoryName(), this );
251:
252: tm = TransactionManagerLocator.getInstance().locate();
253:
254: ds = lookupDataSource(dataSource);
255: initSequence(tableName, sequenceColumn, sequenceName,
256: idColumnName);
257: }
258:
259: public void stopService() throws Exception {
260: if (dropTable) {
261: dropTableIfExists(tableName);
262: }
263:
264: ds = null;
265: tm = null;
266:
267: // unbind the factory
268: Context ctx = new InitialContext();
269: Util.unbind(ctx, getFactoryName());
270: }
271:
272: // Private
273:
274: private void initSequence(String tableName, String sequenceColumn,
275: String sequenceName, String idColumnName)
276: throws SQLException, DeploymentException {
277: if (createTable) {
278: createTableIfNotExists(tableName);
279: }
280:
281: Connection con = null;
282: Statement st = null;
283: ResultSet rs = null;
284: try {
285: String sql = "select " + idColumnName + " from "
286: + tableName + " where " + sequenceColumn + "='"
287: + sequenceName + "'";
288: log.debug("Executing SQL: " + sql);
289:
290: con = ds.getConnection();
291: st = con.createStatement();
292: rs = st.executeQuery(sql);
293: if (!rs.next()) {
294: sql = "insert into " + tableName + "(" + sequenceColumn
295: + ", " + idColumnName + ") values ('"
296: + sequenceName + "', 0)";
297: log.debug("Executing SQL: " + sql);
298:
299: final Statement insertSt = con.createStatement();
300: try {
301: final int i = insertSt.executeUpdate(sql);
302: if (i != 1) {
303: throw new SQLException(
304: "Expected one updated row but got: "
305: + i);
306: }
307: } finally {
308: JDBCUtil.safeClose(insertSt);
309: }
310: } else {
311: HiLoKeyGenerator.setHighestHi(rs.getLong(1));
312: }
313: } finally {
314: JDBCUtil.safeClose(rs);
315: JDBCUtil.safeClose(st);
316: JDBCUtil.safeClose(con);
317: }
318: }
319:
320: private void createTableIfNotExists(String tableName)
321: throws SQLException, DeploymentException {
322: Connection con = null;
323: Statement st = null;
324: try {
325: if (!SQLUtil.tableExists(tableName, ds)) {
326: log.debug("Executing DDL: " + createTableDdl);
327:
328: con = ds.getConnection();
329: st = con.createStatement();
330: st.executeUpdate(createTableDdl);
331: }
332: } finally {
333: JDBCUtil.safeClose(st);
334: JDBCUtil.safeClose(con);
335: }
336: }
337:
338: private void dropTableIfExists(String tableName)
339: throws SQLException, DeploymentException {
340: Connection con = null;
341: Statement st = null;
342: try {
343: if (SQLUtil.tableExists(tableName, ds)) {
344: final String ddl = "drop table " + tableName;
345: log.debug("Executing DDL: " + ddl);
346:
347: con = ds.getConnection();
348: st = con.createStatement();
349: st.executeUpdate(ddl);
350: }
351: } finally {
352: JDBCUtil.safeClose(st);
353: JDBCUtil.safeClose(con);
354: }
355: }
356:
357: private DataSource lookupDataSource(ObjectName dataSource)
358: throws Exception {
359: try {
360: String dsJndi = (String) server.getAttribute(dataSource,
361: "BindName");
362: return (DataSource) new InitialContext().lookup(dsJndi);
363: } catch (NamingException e) {
364: throw new Exception("Failed to lookup data source: "
365: + dataSource);
366: }
367: }
368:
369: private void readObject(ObjectInputStream ois) throws IOException,
370: ClassNotFoundException {
371: ObjectInputStream.GetField getField = ois.readFields();
372:
373: dataSource = (ObjectName) getField.get("dataSource", null);
374: jndiName = (String) getField.get("jndiName", null);
375: tableName = (String) getField.get("tableName", null);
376: sequenceColumn = (String) getField.get("sequenceColumn", null);
377: sequenceName = (String) getField.get("sequenceName", null);
378: idColumnName = (String) getField.get("idColumnName", null);
379: createTableDdl = (String) getField.get("createTableDdl", null);
380: selectHiSql = (String) getField.get("selectHiSql", null);
381: blockSize = getField.get("blockSize", (long) 0);
382:
383: createTable = getField.get("createTable", true);
384: dropTable = getField.get("dropTable", false);
385:
386: server = MBeanServerLocator.locateJBoss();
387: tm = TransactionManagerLocator.getInstance().locate();
388: try {
389: ds = lookupDataSource(dataSource);
390: } catch (Exception e) {
391: throw new IllegalStateException(
392: "Failed to lookup the DataSource " + dataSource, e);
393: }
394: }
395: }
|