1 29 30 package com.caucho.jca; 31 32 import com.caucho.config.BuilderProgram; 33 import com.caucho.config.Config; 34 import com.caucho.config.ConfigException; 35 import com.caucho.config.types.InitProgram; 36 import com.caucho.jca.cfg.JavaMailConfig; 37 import com.caucho.jmx.IntrospectionMBean; 38 import com.caucho.jmx.Jmx; 39 import com.caucho.loader.ClassLoaderListener; 40 import com.caucho.loader.CloseListener; 41 import com.caucho.loader.Environment; 42 import com.caucho.loader.EnvironmentListener; 43 import com.caucho.loader.StartListener; 44 import com.caucho.naming.Jndi; 45 import com.caucho.util.CharBuffer; 46 import com.caucho.util.L10N; 47 48 import javax.annotation.PostConstruct; 49 import javax.management.Attribute ; 50 import javax.management.MBeanAttributeInfo ; 51 import javax.management.MBeanInfo ; 52 import javax.management.MBeanServer ; 53 import javax.management.NotificationFilter ; 54 import javax.management.ObjectName ; 55 import javax.naming.Context ; 56 import javax.naming.InitialContext ; 57 import javax.resource.spi.ManagedConnectionFactory ; 58 import javax.resource.spi.ResourceAdapter ; 59 import java.lang.reflect.Constructor ; 60 import java.lang.reflect.Method ; 61 import java.util.ArrayList ; 62 import java.util.logging.Level ; 63 import java.util.logging.Logger ; 64 65 68 public class Resource { 69 private static final Logger log 70 = Logger.getLogger(Resource.class.getName()); 71 72 private static L10N L = new L10N(Resource.class); 73 74 private Class _type; 75 76 private String _var; 77 private String _jndiName; 78 79 private String _mbeanName; 80 81 private Class _mbeanInterface; 82 83 private ArrayList <Object > _args = new ArrayList <Object >(); 85 86 private boolean _isPreInit; 87 private boolean _localTransactionOptimization = true; 88 private boolean _shareable = true; 89 90 private Object _object; 91 private MBeanInfo _mbeanInfo; 92 93 96 public void setVar(String var) 97 { 98 _var = var; 99 } 100 101 104 public void setJndiName(String name) 105 { 106 _jndiName = name; 107 } 108 109 112 public String getJndiName() 113 { 114 return _jndiName; 115 } 116 117 120 public void setMbeanName(String name) 121 { 122 _mbeanName = name; 123 } 124 125 128 public String getMbeanName() 129 { 130 return _mbeanName; 131 } 132 133 136 public void setType(Class resourceClass) 137 { 138 if (resourceClass.getName().equals("javax.mail.Session")) 139 _type = JavaMailConfig.class; 140 else 141 _type = resourceClass; 142 } 143 144 147 public void setClass(Class resourceClass) 148 { 149 _type = resourceClass; 150 } 151 152 155 public Class getType() 156 { 157 return _type; 158 } 159 160 163 public void setMBeanInterface(Class cl) 164 { 165 _mbeanInterface = cl; 166 } 167 168 171 177 public void addArg(Object arg) 178 { 179 _args.add(arg); 180 } 181 182 185 public void setLocalTransactionOptimization(boolean enable) 186 { 187 _localTransactionOptimization = enable; 188 } 189 190 193 public void setShareable(boolean shareable) 194 { 195 _shareable = shareable; 196 } 197 198 201 public void addInit(InitProgram init) 202 throws Throwable 203 { 204 preInit(); 205 206 init.configure(_object); 207 } 208 209 212 public Object createListener() 213 throws Throwable 214 { 215 return createMbeanListener(); 216 } 217 218 221 public Object createMbeanListener() 222 throws Throwable 223 { 224 preInit(); 225 226 if (_mbeanName != null) 227 return new MBeanListener(); 228 else 229 throw new ConfigException(L.l("<listener> needs a <resource> with an mbean-name.")); 230 } 231 232 ObjectName getObjectName() 233 throws Throwable 234 { 235 preInit(); 236 237 if (_mbeanName != null) 238 return Jmx.getObjectName(_mbeanName); 239 else 240 return null; 241 } 242 243 MBeanInfo getMBeanInfo() 244 throws Throwable 245 { 246 preInit(); 247 248 return _mbeanInfo; 249 } 250 251 254 private void preInit() 255 throws Throwable 256 { 257 if (_isPreInit) 258 return; 259 _isPreInit = true; 260 261 Object oldObject = null; 262 263 if (_jndiName != null) { 264 try { 265 String jndiName = Jndi.getFullName(_jndiName); 266 267 Context ic = new InitialContext (); 268 oldObject = ic.lookup(_jndiName); 269 } catch (Exception e) { 270 } 271 } 272 273 MBeanServer mbeanServer = Jmx.getMBeanServer(); 274 275 ObjectName mbeanName = null; 276 277 if (_mbeanName != null) 278 mbeanName = Jmx.getObjectName(_mbeanName); 279 280 if (_type != null) { 281 } 282 else if (oldObject != null) { 283 _object = oldObject; 284 return; 285 } 286 else if (mbeanName != null && 287 mbeanServer.getMBeanInfo(mbeanName) != null) { 288 return; 289 } 290 else 291 throw new ConfigException(L.l("<resource> configuration needs a <type>. The <type> is the class name of the resource bean.")); 292 293 Constructor constructor = getConstructor(_args.size()); 294 295 Class []params = constructor.getParameterTypes(); 296 297 Object []args = new Object [_args.size()]; 298 299 303 for (int i = 0; i < args.length; i++) 304 args[i] = _args.get(i); 305 306 _object = constructor.newInstance(args); 307 308 if (mbeanName != null) { 309 Object mbean = _object; 310 311 if (_mbeanInterface != null) 312 mbean = new IntrospectionMBean(mbean, _mbeanInterface); 313 314 Jmx.register(mbean, mbeanName); 315 _mbeanInfo = mbeanServer.getMBeanInfo(mbeanName); 316 } 317 } 318 319 322 private Constructor getConstructor(int len) 323 throws Exception 324 { 325 Constructor []constructors = _type.getConstructors(); 326 327 for (int i = 0; i < constructors.length; i++) { 328 if (constructors[i].getParameterTypes().length == len) 329 return constructors[i]; 330 } 331 332 throw new ConfigException(L.l("`{0}' has no matching constructors.", 333 _type.getName())); 334 } 335 336 339 @PostConstruct 340 public void init() 341 throws Throwable 342 { 343 preInit(); 344 345 if (_type == null || _object == null) 346 return; 347 348 Config.init(_object); 349 _object = Config.replaceObject(_object); 350 351 if (_object instanceof ClassLoaderListener) { 352 ClassLoaderListener listener = (ClassLoaderListener) _object; 353 354 Environment.addClassLoaderListener(listener); 355 } 356 357 if (_object instanceof EnvironmentListener) { 358 EnvironmentListener listener = (EnvironmentListener) _object; 359 360 Environment.addEnvironmentListener(listener); 361 } 362 363 Object jndiObject = _object; 364 boolean isStart = false; 365 366 if (_object instanceof ResourceAdapter ) { 367 ResourceManagerImpl.addResource((ResourceAdapter ) _object); 368 isStart = true; 369 } 370 371 if (_object instanceof ManagedConnectionFactory ) { 372 ResourceManagerImpl rm = ResourceManagerImpl.createLocalManager(); 373 374 ManagedConnectionFactory mcf; 375 mcf = (ManagedConnectionFactory ) _object; 376 377 ConnectionPool cm = rm.createConnectionPool(); 378 379 cm.setShareable(_shareable); 380 cm.setLocalTransactionOptimization(_localTransactionOptimization); 381 Object connectionFactory = cm.init(mcf); 382 cm.start(); 383 384 jndiObject = connectionFactory; 385 386 isStart = true; 387 } 388 389 Method start = null; 390 try { 391 start = _object.getClass().getMethod("start", new Class [0]); 392 } catch (Throwable e) { 393 } 394 395 Method stop = null; 396 try { 397 stop = _object.getClass().getMethod("stop", new Class [0]); 398 } catch (Throwable e) { 399 } 400 401 if (_jndiName != null) 402 Jndi.bindDeepShort(_jndiName, jndiObject); 403 404 if (_var != null) 405 Config.setCurrentVar(_var, jndiObject); 406 407 if (isStart) { 408 } 409 else if (start != null || stop != null) 410 Environment.addEnvironmentListener(new StartListener(_object)); 411 else if (CloseListener.getDestroyMethod(_object.getClass()) != null) 412 Environment.addClassLoaderListener(new CloseListener(_object)); 413 414 if (log.isLoggable(Level.CONFIG)) 415 logConfig(); 416 } 417 418 private void logConfig() 419 { 420 StringBuilder sb = new StringBuilder (); 421 422 if (_object instanceof ResourceAdapter ) 423 sb.append("jca-resource"); 424 else if (_object instanceof ManagedConnectionFactory ) 425 sb.append("jca-resource"); 426 else 427 sb.append("resource"); 428 429 sb.append("["); 430 boolean hasValue = false; 431 432 if (_jndiName != null) { 433 if (hasValue) sb.append(", "); 434 hasValue = true; 435 sb.append("jndi-name=" + _jndiName); 436 } 437 438 if (_var != null) { 439 if (hasValue) sb.append(", "); 440 hasValue = true; 441 sb.append("var=" + _var); 442 } 443 444 if (_mbeanName != null) { 445 if (hasValue) sb.append(", "); 446 hasValue = true; 447 sb.append("mbean-name=" + _mbeanName); 448 } 449 450 if (_type != null) { 451 if (hasValue) sb.append(", "); 452 hasValue = true; 453 sb.append("type=" + _type); 454 } 455 456 sb.append("]"); 457 458 log.config(sb.toString() + " configured"); 459 } 460 461 public String toString() 462 { 463 if (_mbeanName != null) 464 return "Resource[" + _mbeanName + "]"; 465 else 466 return "Resource[" + _jndiName + "]"; 467 } 468 469 public class MBeanInit { 470 public void setProperty(String attrName, BuilderProgram program) 471 throws Throwable 472 { 473 MBeanAttributeInfo attr = getAttribute(attrName); 474 if (attr == null) 475 throw new ConfigException(L.l("`{0}' is an unknown attribute for {1}", 476 attrName, _mbeanName)); 477 478 String typeName = attr.getType(); 479 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 480 Class type = Class.forName(typeName, false, loader); 481 482 Object value = program.configure(type); 483 484 MBeanServer server = Jmx.getMBeanServer(); 485 486 server.setAttribute(getObjectName(), 487 new Attribute (attr.getName(), value)); 488 } 489 490 private MBeanAttributeInfo getAttribute(String key) 491 throws Throwable 492 { 493 MBeanInfo info = getMBeanInfo(); 494 495 MBeanAttributeInfo []attrs = info.getAttributes(); 496 497 if (attrs == null) 498 return null; 499 500 for (int i = 0; i < attrs.length; i++) { 501 if (attrs[i].getName().equals(key)) 502 return attrs[i]; 503 } 504 505 for (int i = 0; i < attrs.length; i++) { 506 if (convertName(attrs[i].getName()).equals(key)) 507 return attrs[i]; 508 } 509 510 return null; 511 } 512 513 private String convertName(String key) 514 { 515 CharBuffer cb = CharBuffer.allocate(); 516 517 for (int i = 0; i < key.length(); i++) { 518 char ch = key.charAt(i); 519 520 if (! Character.isUpperCase(ch)) 521 cb.append(ch); 522 else if (i == 0) 523 cb.append(Character.toLowerCase(ch)); 524 else if (Character.isLowerCase(key.charAt(i - 1))) { 525 cb.append('-'); 526 cb.append(Character.toLowerCase(ch)); 527 } 528 else if (i + 1 != key.length() && 529 Character.isLowerCase(key.charAt(i + 1))) { 530 cb.append('-'); 531 cb.append(Character.toLowerCase(ch)); 532 } 533 else 534 cb.append(Character.toLowerCase(ch)); 535 } 536 537 return cb.close(); 538 } 539 } 540 541 public class MBeanListener { 542 private String _mbeanName; 543 private Object _handback; 544 private NotificationFilter _filter; 545 546 public void setMBeanName(String name) 547 { 548 _mbeanName = name; 549 } 550 551 public String getMBeanName() 552 { 553 return _mbeanName; 554 } 555 556 public void setHandback(Object handback) 557 { 558 _handback = handback; 559 } 560 561 public Object getHandback() 562 { 563 return _handback; 564 } 565 566 @PostConstruct 567 public void init() 568 throws Throwable 569 { 570 if (_mbeanName != null) { 571 ObjectName mbeanName = Jmx.getObjectName(_mbeanName); 572 573 ObjectName listenerName = getObjectName(); 574 575 MBeanServer server = Jmx.getMBeanServer(); 576 577 server.addNotificationListener(mbeanName, listenerName, 578 _filter, _handback); 579 580 } 581 else 582 throw new ConfigException(L.l("mbean name is required")); 583 } 584 } 585 } 586 587 | Popular Tags |