1 22 package org.jboss.ejb.txtimer; 23 24 26 import java.io.ByteArrayInputStream ; 27 import java.io.ByteArrayOutputStream ; 28 import java.io.IOException ; 29 import java.io.InputStream ; 30 import java.io.ObjectInputStream ; 31 import java.io.ObjectOutputStream ; 32 import java.io.Serializable ; 33 import java.sql.Connection ; 34 import java.sql.PreparedStatement ; 35 import java.sql.ResultSet ; 36 import java.sql.SQLException ; 37 import java.sql.Statement ; 38 import java.sql.Timestamp ; 39 import java.util.ArrayList ; 40 import java.util.Date ; 41 import java.util.List ; 42 43 import javax.management.MBeanServer ; 44 import javax.management.ObjectName ; 45 import javax.naming.InitialContext ; 46 import javax.sql.DataSource ; 47 48 import org.jboss.ejb.plugins.cmp.jdbc.JDBCUtil; 49 import org.jboss.ejb.plugins.cmp.jdbc.SQLUtil; 50 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCFunctionMappingMetaData; 51 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCTypeMappingMetaData; 52 import org.jboss.invocation.MarshalledValueInputStream; 53 import org.jboss.logging.Logger; 54 import org.jboss.mx.util.ObjectNameFactory; 55 56 65 public class GeneralPurposeDatabasePersistencePlugin implements DatabasePersistencePlugin 66 { 67 private static Logger log = Logger.getLogger(GeneralPurposeDatabasePersistencePlugin.class); 69 70 protected ObjectName dataSourceName; 72 73 protected MBeanServer server; 75 protected DataSource ds; 77 protected ObjectName metaDataName; 79 80 81 public void init(MBeanServer server, ObjectName dataSourceName) throws SQLException 82 { 83 this.server = server; 84 this.dataSourceName = dataSourceName; 85 86 try 88 { 89 String dsJndiTx = (String )server.getAttribute(dataSourceName, "BindName"); 90 ds = (DataSource )new InitialContext ().lookup(dsJndiTx); 91 } 92 catch (Exception e) 93 { 94 throw new SQLException ("Failed to lookup data source: " + dataSourceName); 95 } 96 97 String dsName = dataSourceName.getKeyProperty("name"); 99 metaDataName = ObjectNameFactory.create("jboss.jdbc:datasource=" + dsName + ",service=metadata"); 100 if (this.server.isRegistered(metaDataName) == false) 101 throw new IllegalStateException ("Cannot find datasource meta data: " + metaDataName); 102 } 103 104 105 public void createTableIfNotExists() 106 throws SQLException 107 { 108 Connection con = null; 109 Statement st = null; 110 try 111 { 112 if (!SQLUtil.tableExists(getTableName(), ds)) 113 { 114 con = ds.getConnection(); 115 JDBCTypeMappingMetaData typeMapping = (JDBCTypeMappingMetaData)server.getAttribute(metaDataName, "TypeMappingMetaData"); 116 if (typeMapping == null) 117 throw new IllegalStateException ("Cannot obtain type mapping from: " + metaDataName); 118 119 String dateType = typeMapping.getTypeMappingMetaData(Timestamp .class).getSqlType(); 120 String objectType = typeMapping.getTypeMappingMetaData(Object .class).getSqlType(); 121 String longType = typeMapping.getTypeMappingMetaData(Long .class).getSqlType(); 122 123 StringBuffer createTableDDL = new StringBuffer ("create table " + getTableName() + " (" + 125 " " + getColumnTimerID() + " varchar(80) not null," + 126 " " + getColumnTargetID() + " varchar(250) not null," + 127 " " + getColumnInitialDate() + " " + dateType + " not null," + 128 " " + getColumnTimerInterval() + " " + longType + "," + 129 " " + getColumnInstancePK() + " " + objectType + "," + 130 " " + getColumnInfo() + " " + objectType + ", "); 131 132 JDBCFunctionMappingMetaData pkConstraint = typeMapping.getPkConstraintTemplate(); 134 String [] templateParams = new String [] { 135 getTableName() + "_PK", 136 getColumnTimerID() + ", " + getColumnTargetID() 137 }; 138 pkConstraint.getFunctionSql(templateParams, createTableDDL); 139 140 createTableDDL.append(" )"); 142 143 log.debug("Executing DDL: " + createTableDDL); 144 145 st = con.createStatement(); 146 st.executeUpdate(createTableDDL.toString()); 147 } 148 } 149 catch (SQLException e) 150 { 151 throw e; 152 } 153 catch (Exception e) 154 { 155 log.error("Cannot create timer table", e); 156 } 157 finally 158 { 159 JDBCUtil.safeClose(st); 160 JDBCUtil.safeClose(con); 161 } 162 } 163 164 165 public void insertTimer(String timerId, TimedObjectId timedObjectId, Date initialExpiration, long intervalDuration, Serializable info) 166 throws SQLException 167 { 168 Connection con = null; 169 PreparedStatement st = null; 170 try 171 { 172 con = ds.getConnection(); 173 174 String sql = "insert into " + getTableName() + " " + 175 "(" + getColumnTimerID() + "," + getColumnTargetID() + "," + getColumnInitialDate() + "," + getColumnTimerInterval() + "," + getColumnInstancePK() + "," + getColumnInfo() + ") " + 176 "values (?,?,?,?,?,?)"; 177 st = con.prepareStatement(sql); 178 179 st.setString(1, timerId); 180 st.setString(2, timedObjectId.toString()); 181 st.setTimestamp(3, new Timestamp (initialExpiration.getTime())); 182 st.setLong(4, intervalDuration); 183 st.setBytes(5, serialize(timedObjectId.getInstancePk())); 184 st.setBytes(6, serialize(info)); 185 186 int rows = st.executeUpdate(); 187 if (rows != 1) 188 log.error("Unable to insert timer for: " + timedObjectId); 189 } 190 finally 191 { 192 JDBCUtil.safeClose(st); 193 JDBCUtil.safeClose(con); 194 } 195 } 196 197 200 public List selectTimers(ObjectName containerId) throws SQLException 201 { 202 Connection con = null; 203 Statement st = null; 204 ResultSet rs = null; 205 try 206 { 207 con = ds.getConnection(); 208 209 List list = new ArrayList (); 210 211 st = con.createStatement(); 212 rs = st.executeQuery("select * from " + getTableName()); 213 while (rs.next()) 214 { 215 String timerId = rs.getString(getColumnTimerID()); 216 TimedObjectId targetId = TimedObjectId.parse(rs.getString(getColumnTargetID())); 217 218 if (containerId == null || containerId.equals(targetId.getContainerId())) 221 { 222 Date initialDate = rs.getTimestamp(getColumnInitialDate()); 223 long interval = rs.getLong(getColumnTimerInterval()); 224 Serializable pKey = (Serializable )deserialize(rs.getBytes(getColumnInstancePK())); 225 Serializable info = null; 226 try 227 { 228 info = (Serializable )deserialize(rs.getBytes(getColumnInfo())); 229 } 230 catch (Exception e) 231 { 232 log.warn("Cannot deserialize custom info object", e); 236 } 237 targetId = new TimedObjectId(targetId.getContainerId(), pKey); 239 TimerHandleImpl handle = new TimerHandleImpl(timerId, targetId, initialDate, interval, info); 240 list.add(handle); 241 } 242 } 243 244 return list; 245 } 246 finally 247 { 248 JDBCUtil.safeClose(rs); 249 JDBCUtil.safeClose(st); 250 JDBCUtil.safeClose(con); 251 } 252 } 253 254 255 public void deleteTimer(String timerId, TimedObjectId timedObjectId) 256 throws SQLException 257 { 258 Connection con = null; 259 PreparedStatement st = null; 260 ResultSet rs = null; 261 262 try 263 { 264 con = ds.getConnection(); 265 266 String sql = "delete from " + getTableName() + " where " + getColumnTimerID() + "=? and " + getColumnTargetID() + "=?"; 267 st = con.prepareStatement(sql); 268 269 st.setString(1, timerId); 270 st.setString(2, timedObjectId.toString()); 271 272 int rows = st.executeUpdate(); 273 274 if (rows != 1) 279 { 280 log.debug("Unable to remove timer for: " + timerId); 281 } 282 } 283 finally 284 { 285 JDBCUtil.safeClose(rs); 286 JDBCUtil.safeClose(st); 287 JDBCUtil.safeClose(con); 288 } 289 } 290 291 292 public void clearTimers() 293 throws SQLException 294 { 295 Connection con = null; 296 PreparedStatement st = null; 297 ResultSet rs = null; 298 try 299 { 300 con = ds.getConnection(); 301 st = con.prepareStatement("delete from " + getTableName()); 302 st.executeUpdate(); 303 } 304 finally 305 { 306 JDBCUtil.safeClose(rs); 307 JDBCUtil.safeClose(st); 308 JDBCUtil.safeClose(con); 309 } 310 } 311 312 313 public String getTableName() 314 { 315 return "TIMERS"; 316 } 317 318 319 public String getColumnTimerID() 320 { 321 return "TIMERID"; 322 } 323 324 325 public String getColumnTargetID() 326 { 327 return "TARGETID"; 328 } 329 330 331 public String getColumnInitialDate() 332 { 333 return "INITIALDATE"; 334 } 335 336 337 public String getColumnTimerInterval() 338 { 339 return "TIMERINTERVAL"; 341 } 342 343 344 public String getColumnInstancePK() 345 { 346 return "INSTANCEPK"; 347 } 348 349 350 public String getColumnInfo() 351 { 352 return "INFO"; 353 } 354 355 356 protected byte[] serialize(Object obj) 357 { 358 if (obj == null) 359 return null; 360 361 ByteArrayOutputStream baos = new ByteArrayOutputStream (1024); 362 try 363 { 364 ObjectOutputStream oos = new ObjectOutputStream (baos); 365 oos.writeObject(obj); 366 oos.close(); 367 } 368 catch (IOException e) 369 { 370 log.error("Cannot serialize: " + obj, e); 371 } 372 return baos.toByteArray(); 373 } 374 375 376 protected Object deserialize(byte[] bytes) 377 { 378 if (bytes == null) 379 return null; 380 381 ByteArrayInputStream bais = new ByteArrayInputStream (bytes); 382 try 383 { 384 ObjectInputStream oos = new MarshalledValueInputStream(bais); 387 return oos.readObject(); 388 } 389 catch (Exception e) 390 { 391 log.error("Cannot deserialize", e); 392 return null; 393 } 394 } 395 396 397 protected Object deserialize(InputStream input) 398 { 399 400 if (input == null) 401 return null; 402 403 byte[] barr = new byte[1024]; 404 ByteArrayOutputStream baos = new ByteArrayOutputStream (1024); 405 try 406 { 407 for (int b = 0; (b = input.read(barr)) > 0;) 408 { 409 baos.write(barr, 0, b); 410 } 411 return deserialize(baos.toByteArray()); 412 } 413 catch (Exception e) 414 { 415 log.error("Cannot deserialize", e); 416 return null; 417 } 418 } 419 } 420 421 | Popular Tags |