1 23 24 package org.objectweb.speedo.jca; 25 26 import org.objectweb.util.monolog.api.BasicLevel; 27 import org.objectweb.util.monolog.api.Logger; 28 import org.objectweb.util.monolog.api.LoggerFactory; 29 import org.objectweb.util.monolog.api.Loggable; 30 import org.objectweb.util.monolog.Monolog; 31 import org.objectweb.util.monolog.wrapper.printwriter.LoggerImpl; 32 import org.objectweb.speedo.api.Debug; 33 import org.objectweb.speedo.api.SpeedoProperties; 34 import org.objectweb.speedo.api.ExceptionHelper; 35 import org.objectweb.speedo.pm.api.ProxyManagerFactory; 36 import org.objectweb.speedo.Speedo; 37 38 import java.io.PrintWriter ; 39 import java.io.FileInputStream ; 40 import java.io.IOException ; 41 import java.io.File ; 42 import java.io.InputStream ; 43 import java.io.FileNotFoundException ; 44 import java.util.Set ; 45 import java.util.Properties ; 46 import java.util.HashMap ; 47 import java.util.Iterator ; 48 import javax.resource.ResourceException ; 49 import javax.resource.spi.ConnectionManager ; 50 import javax.resource.spi.ConnectionRequestInfo ; 51 import javax.resource.spi.ManagedConnection ; 52 import javax.resource.spi.ManagedConnectionFactory ; 53 import javax.security.auth.Subject ; 54 import javax.jdo.JDOHelper; 55 import javax.jdo.PersistenceManager; 56 import javax.transaction.TransactionManager ; 57 import javax.transaction.xa.Xid ; 58 import javax.transaction.xa.XAException ; 59 import javax.naming.InitialContext ; 60 import javax.naming.NamingException ; 61 62 65 public class JdoManagedConnectionFactory 66 implements ManagedConnectionFactory , 67 JdoAttributeController { 68 69 private final static String [] DEFAULT_JNDI_NAMES = { 70 "javax.transaction.UserTransaction", "javax.transaction.TransactionManager", "java:/TransactionManager", "jta/usertransaction", "java:comp/UserTransaction" }; 76 77 81 private Logger logger; 82 86 protected JdoConnectionFactory connectionFactory; 87 90 private LoggerFactory loggerFactory = null; 91 94 protected ProxyManagerFactory pmf = null; 95 96 100 private String propertiesFileName = null; 101 104 private ConnectionManager connectionManager = null; 105 106 private PrintWriter printWriter = null; 107 108 protected boolean started = false; 109 110 113 private String tmName = null; 114 115 protected TransactionManager tm = null; 116 117 121 private HashMap xid2xac = new HashMap (); 122 123 132 private boolean lookupTM(String name) { 133 InitialContext ictx = null; 134 try { 135 ictx = new InitialContext (); 136 Object o = ictx.lookup(name); 137 if (o == null) { 138 logger.log(BasicLevel.WARN, 139 "JNDI retrieves a null value for the name '" + name + "'."); 140 } 141 if (!(o instanceof TransactionManager )) { 142 logger.log(BasicLevel.WARN, 143 "JNDI retrieves an object which is not a javax.transaction.TransactionManager (JNDI name: " + name + "): " + o); 144 return false; 145 } 146 tm = (TransactionManager ) o; 147 logger.log(BasicLevel.INFO, "The TransactionManager was found in JNDI with the name '" + name + "'."); 148 return true; 149 } catch (Exception e) { 150 logger.log(BasicLevel.WARN, 151 "Error when lookup the transaction manager in JNDI with the name '" 152 + name + "'", e); 153 return false; 154 } finally { 155 if (ictx != null) { 156 try { 157 ictx.close(); 158 } catch (NamingException e) { 159 } 160 } 161 } 162 } 163 164 167 public synchronized void start() throws ResourceException { 168 if (started) { 169 return; 170 } 171 if (loggerFactory == null) { 173 if (Monolog.monologFactory == null) { 174 loggerFactory = Monolog.initialize(); 175 } else { 176 loggerFactory = Monolog.monologFactory; 177 } 178 } 179 if (logger == null) { 180 logger = loggerFactory.getLogger("org.objectweb.speedo.jca"); 181 } 182 183 if (pmf == null) { 185 Properties p = loadProperties(); 186 if (p.get(SpeedoProperties.MANAGED) == null) { 187 p.put(SpeedoProperties.MANAGED, "true"); 189 } 190 logger.log(BasicLevel.DEBUG, "Properties loaded:" + p); 191 findTransactionManager(p); 192 193 String str = p.getProperty(SpeedoProperties.MAPPING_STRUCTURE); 197 if (str == null 198 || !str.equals(SpeedoProperties.MAPPING_STRUCTURE_DN)) { 199 p.put(SpeedoProperties.MAPPING_STRUCTURE, 200 SpeedoProperties.MAPPING_STRUCTURE_DN); 201 logger.log(BasicLevel.WARN, "The mapping structure cannot be" + 202 " managed by Speedo into a managed environnement " + 203 "(XA transaction): " 204 + SpeedoProperties.MAPPING_STRUCTURE + " is forced to " 205 + SpeedoProperties.MAPPING_STRUCTURE_DN); 206 } 207 byte txMode = getByteTxMode(p.getProperty(SpeedoProperties.TRANSACTION_MODE)); 209 connectionFactory = new JdoConnectionFactory(logger, this, connectionManager, txMode); 210 logger.log(BasicLevel.INFO, "ConnectionManager allocated"); 211 try { 213 pmf = ((Speedo) JDOHelper.getPersistenceManagerFactory(p)).getPMFComponent(); 214 } catch (Exception e) { 215 Exception ie = ExceptionHelper.getNested(e); 216 ResourceException re = new ResourceException ("Impossible to instanciate Speedo: "); 217 logger.log(BasicLevel.ERROR, re.getMessage(), ie); 218 re.setLinkedException(ie); 219 throw re; 220 } 221 logger.log(BasicLevel.INFO, "JdoManagedConnectionFactory started"); 222 } 223 started = true; 224 } 225 226 227 233 private Properties loadProperties() throws ResourceException { 234 if (propertiesFileName == null) { 235 throw new ResourceException ( 236 "No name provided for the properties file of the associated PersistenceManagerFactory"); 237 } 238 InputStream is = getClass().getClassLoader().getResourceAsStream( 239 propertiesFileName); 240 if (is == null) { 241 File f = new File (propertiesFileName); 242 try { 243 if (f.exists()) { 244 is = new FileInputStream (propertiesFileName); 245 logger.log(BasicLevel.DEBUG, "Properties file '" 246 + propertiesFileName 247 + "' found in the file system"); 248 } 249 } catch (FileNotFoundException e) { 250 } finally { 251 if (is == null) { 252 throw new ResourceException ( 253 "Unable to load properties file: " 254 + propertiesFileName); 255 } 256 } 257 } else { 258 logger.log(BasicLevel.DEBUG, "Properties file '" 259 + propertiesFileName + "' found in the classpath"); 260 } 261 Properties p = new Properties(); 262 try { 263 p.load(is); 264 } catch (IOException e) { 265 throw new ResourceException ("Unable to load properties file: " 266 + propertiesFileName); 267 } 268 return p; 269 } 270 271 281 private TransactionManager findTransactionManager(Properties p) 282 throws ResourceException { 283 if (tm != null) { 284 return tm; 285 } 286 if (tmName != null && lookupTM(tmName)) { 287 p.setProperty(SpeedoProperties.TM_NAME, tmName); 288 } else { 289 String tmName2 = p.getProperty(SpeedoProperties.TM_NAME); 292 if (tmName2 == null || !lookupTM(tmName2)) { 293 logger.log(BasicLevel.DEBUG, 294 "Try to find the transaction manager with default JNDI names."); 295 int i = 0; 296 while (i < DEFAULT_JNDI_NAMES.length 297 && !lookupTM(DEFAULT_JNDI_NAMES[i])) { 298 i++; 299 } 300 if (i < DEFAULT_JNDI_NAMES.length) { 301 p.setProperty(SpeedoProperties.TM_NAME, 302 DEFAULT_JNDI_NAMES[i]); 303 } 304 } 305 } 306 307 if (tm == null) { 308 throw new ResourceException ( 309 "A javax.transaction.TransactionManager instance is required," 310 + " in order to register the JDO driver as a Synchronization on transaction" 311 + (tmName == null ? "(No JNDI name specified)" 312 : "(Bad JNDI Name)")); 313 } 314 logger.log(BasicLevel.DEBUG, "Transaction manager found: " + tm); 315 return tm; 316 } 317 318 319 protected void finalize() throws Throwable { 320 stop(); 321 super.finalize(); 322 } 323 324 327 public void stop() throws ResourceException { 328 pmf = null; 329 } 330 331 332 335 public Object createConnection() throws ResourceException { 336 return connectionFactory.createConnection(); 337 } 338 339 341 342 346 XAContext getXAContext(Xid xid) { 347 XAContext xac = (XAContext) xid2xac.get(xid); 348 PersistenceManager txc = null; 349 if (xac != null) { 350 txc = xac.pm; 351 } 352 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) 353 logger.log(BasicLevel.DEBUG, 354 "Looking for the TxContext associated with XID (" + xid 355 + "): " + txc); 356 return xac; 357 } 358 359 363 XAContext createXAContext(Xid xid) { 364 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 365 Object pm = pmf.lookup(); 366 if (pm != null) { 367 logger.log(BasicLevel.DEBUG, 368 "Unbind the PM from the current thread: " 369 + "\t-current pm=" + pm 370 + "\t-xid=" + xid); 371 } else { 372 logger.log(BasicLevel.DEBUG, 373 "No PM to unbind from the current thread, xid=" + xid); 374 } 375 } 376 pmf.unbindPM(); 377 XAContext xac = new XAContext(xid); 378 if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 379 logger.log(BasicLevel.DEBUG, 380 "Creates an XAContext associated with the XID: " + xid); 381 } 382 xid2xac.put(xid, xac); 383 return xac; 384 } 385 386 390 XAContext releaseXAContext(Xid xid, boolean mustExist) throws XAException { 391 XAContext xac = (XAContext) xid2xac.remove(xid); 392 if (xac == null) { 393 if (mustExist) { 394 String msg = "Impossible to release the XAContext, xid=" + xid; 395 logger.log(BasicLevel.ERROR, msg); 396 throw new XAException (msg); 397 } 398 } else if (!xac.synchroRegistred && xac.pm != null) { 399 logger.log(BasicLevel.WARN, "Closing a persistenceManager because it has not been registered as a Synchronization on the transaction (pm=" 400 + xac.pm + "), xid: " + xid); 401 if (xac.pm.currentTransaction().isActive()) { 402 xac.pm.currentTransaction().rollback(); 403 } 404 xac.pm.close(); 405 } else if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) { 406 logger.log(BasicLevel.DEBUG, "Dissociates the JdoTxContext (" 407 + xac.pm + ") associated with XID: " + xid); 408 } 409 return xac; 410 } 411 412 413 415 420 public String getPropertyFile() { 421 return propertiesFileName; 422 } 423 424 429 public void setPropertyFile(String pf) { 430 propertiesFileName = pf; 431 } 432 433 public String getTransactionManagerJNDIName() { 434 return tmName; 435 } 436 437 public void setTransactionManagerJNDIName(String jndiname) throws ResourceException { 438 tmName = jndiname; 439 } 440 441 public void setTransactionManager(TransactionManager tm) { 442 this.tm = tm; 443 } 444 445 447 452 public Object createConnectionFactory(ConnectionManager cm) 453 throws ResourceException { 454 if (!started) { 455 start(); 456 } 457 connectionFactory.setConnectionManager(cm); 458 return connectionFactory; 459 } 460 461 464 public Object createConnectionFactory() throws ResourceException { 465 return createConnectionFactory(null); 466 } 467 468 471 public ManagedConnection createManagedConnection( 472 Subject subject, 473 ConnectionRequestInfo info) throws ResourceException { 474 if (logger == null || pmf == null) { 475 start(); 476 } 477 JdoManagedConnection jmc = new JdoManagedConnection(logger, this); 478 if (info != null) { 479 if (info instanceof JDOConnectionSpec) { 480 jmc.cri = (JDOConnectionSpec) info; 481 } else { 482 throw new ResourceException ("Impossible to create a " + 483 "ManagedConnection with this kind of ConnectionRequestInfo: " 484 + info); 485 } 486 } 487 return jmc; 488 } 489 490 494 public ManagedConnection matchManagedConnections( 495 Set set, 496 Subject subject, 497 ConnectionRequestInfo info) throws ResourceException { 498 if (set.size() == 0) 499 return null; 500 Iterator it = set.iterator(); 501 if (!it.hasNext()) { 502 return null; 503 } 504 JdoManagedConnection jmc = (JdoManagedConnection) it.next(); 505 if (info != null) { 506 if (info instanceof JDOConnectionSpec) { 507 jmc.cri = (JDOConnectionSpec) info; 508 } else { 509 throw new ResourceException ("Impossible to create a " + 510 "ManagedConnection with this kind of ConnectionRequestInfo: " 511 + info); 512 } 513 } 514 return jmc; 515 } 516 517 522 public void setLogWriter(PrintWriter writer) throws ResourceException { 523 if (logger == null) { 524 if (writer instanceof Loggable) { 525 logger = ((Loggable) writer).getLogger(); 526 loggerFactory = ((Loggable) writer).getLoggerFactory(); 527 } else { 528 LoggerImpl li = new LoggerImpl(writer); 529 logger = li; 530 loggerFactory = li; 531 } 532 } 533 printWriter = writer; 534 } 535 536 539 public PrintWriter getLogWriter() throws ResourceException { 540 return printWriter; 541 } 542 543 private byte getByteTxMode(String mode) { 545 if (mode == null || mode.length() == 0 || mode.equals(SpeedoProperties.TRANSACTION_MODE_NORMAL)) { 546 return SpeedoProperties.TRANSACTION_BMODE_NORMAL; 547 } 548 if (mode.equals(SpeedoProperties.TRANSACTION_MODE_REQUIRED)) { 549 return SpeedoProperties.TRANSACTION_BMODE_REQUIRED; 550 } 551 return SpeedoProperties.TRANSACTION_BMODE_UT; 552 } 553 } | Popular Tags |