1 22 package org.jboss.naming; 23 24 import java.io.IOException ; 25 import java.io.InputStream ; 26 import java.io.Serializable ; 27 import java.lang.reflect.Constructor ; 28 import java.lang.reflect.InvocationHandler ; 29 import java.lang.reflect.InvocationTargetException ; 30 import java.lang.reflect.Method ; 31 import java.lang.reflect.Proxy ; 32 import java.net.URL ; 33 import java.util.Hashtable ; 34 import java.util.Properties ; 35 36 import javax.naming.CompositeName ; 37 import javax.naming.Context ; 38 import javax.naming.InitialContext ; 39 import javax.naming.Name ; 40 import javax.naming.NamingException ; 41 import javax.naming.RefAddr ; 42 import javax.naming.Reference ; 43 import javax.naming.Referenceable ; 44 import javax.naming.ldap.Control ; 45 import javax.naming.spi.ObjectFactory ; 46 47 import org.jboss.system.ServiceMBeanSupport; 48 49 64 public class ExternalContext 65 extends ServiceMBeanSupport 66 implements ExternalContextMBean 67 { 68 private boolean remoteAccess; 69 private SerializableInitialContext contextInfo = new SerializableInitialContext(); 70 71 74 public ExternalContext() 75 { 76 super(); 77 } 78 79 public ExternalContext(String jndiName, String contextPropsURL) 80 throws IOException , NamingException 81 { 82 setJndiName(jndiName); 83 setPropertiesURL(contextPropsURL); 84 } 85 86 91 public String getJndiName() 92 { 93 return contextInfo.getJndiName(); 94 } 95 96 101 public void setJndiName(String jndiName) throws NamingException 102 { 103 contextInfo.setJndiName(jndiName); 104 if( super.getState() == STARTED ) 105 { 106 unbind(jndiName); 107 try 108 { 109 rebind(); 110 } 111 catch(Exception e) 112 { 113 NamingException ne = new NamingException ("Failed to update jndiName"); 114 ne.setRootCause(e); 115 throw ne; 116 } 117 } 118 } 119 120 123 public boolean getRemoteAccess() 124 { 125 return remoteAccess; 126 } 127 128 131 public void setRemoteAccess(final boolean remoteAccess) 132 { 133 this.remoteAccess = remoteAccess; 134 } 135 136 139 public boolean getCacheContext() 140 { 141 return contextInfo.getCacheContext(); 142 } 143 144 147 public void setCacheContext(boolean cacheContext) 148 { 149 contextInfo.setCacheContext(cacheContext); 150 } 151 152 165 public String getInitialContext() 166 { 167 return contextInfo.getInitialContext(); 168 } 169 170 183 public void setInitialContext(String className) throws ClassNotFoundException 184 { 185 contextInfo.loadClass(className); 186 } 187 188 193 public void setPropertiesURL(String contextPropsURL) throws IOException 194 { 195 contextInfo.loadProperties(contextPropsURL); 196 } 197 198 203 public void setProperties(final Properties props) throws IOException 204 { 205 contextInfo.setProperties(props); 206 } 207 208 213 public Properties getProperties() throws IOException 214 { 215 return contextInfo.getProperties(); 216 } 217 218 222 protected void startService() throws Exception 223 { 224 rebind(); 225 } 226 227 231 protected void stopService() throws Exception 232 { 233 if( contextInfo.getCacheContext() ) 234 unbind(contextInfo.getJndiName()); 235 } 236 237 private static Context createContext(Context rootContext, Name name) throws NamingException 238 { 239 Context subctx = rootContext; 240 for(int n = 0; n < name.size(); n ++) 241 { 242 String atom = name.get(n); 243 try 244 { 245 Object obj = subctx.lookup(atom); 246 subctx = (Context ) obj; 247 } 248 catch(NamingException e) 249 { 250 subctx = subctx.createSubcontext(atom); 252 } 253 } 254 255 return subctx; 256 } 257 258 private void rebind() throws Exception 259 { 260 Context ctx = contextInfo.newContext(); 261 Context rootCtx = (Context ) new InitialContext (); 262 263 log.debug("ctx="+ctx+", env="+ctx.getEnvironment()); 264 265 String jndiName = contextInfo.getJndiName(); 267 Name fullName = rootCtx.getNameParser("").parse(jndiName); 268 269 log.debug("fullName="+fullName); 270 271 Name parentName = fullName; 272 if( fullName.size() > 1 ) 273 parentName = fullName.getPrefix(fullName.size()-1); 274 else 275 parentName = new CompositeName (); 276 277 log.debug("parentName="+parentName); 278 279 Context parentCtx = createContext(rootCtx, parentName); 280 281 log.debug("parentCtx="+parentCtx); 282 283 Name atomName = fullName.getSuffix(fullName.size()-1); 284 String atom = atomName.get(0); 285 boolean cacheContext = contextInfo.getCacheContext(); 286 287 if( remoteAccess == true ) 288 { 289 parentCtx.rebind(atom, contextInfo); 291 292 if( cacheContext == true ) 295 { 296 ctx = CachedContext.createProxyContext(ctx); 300 NonSerializableFactory.rebind(jndiName, ctx); 301 } 302 } 303 else if( cacheContext == true ) 304 { 305 310 Context proxyCtx = CachedContext.createProxyContext(ctx); 311 NonSerializableFactory.rebind(rootCtx, jndiName, proxyCtx); 312 } 313 else 314 { 315 319 parentCtx.rebind(atom, contextInfo); 320 } 321 } 322 323 private void unbind(String jndiName) 324 { 325 try 326 { 327 Context rootCtx = new InitialContext (); 328 Context ctx = (Context ) rootCtx.lookup(jndiName); 329 if( ctx != null ) 330 ctx.close(); 331 rootCtx.unbind(jndiName); 332 NonSerializableFactory.unbind(jndiName); 333 } 334 catch(NamingException e) 335 { 336 log.error("unbind failed", e); 337 } 338 } 339 340 345 public static class SerializableInitialContext 346 extends RefAddr 347 implements Referenceable , Serializable , ObjectFactory 348 { 349 private static final long serialVersionUID = -6512260531255770463L; 350 private String jndiName; 351 private Class contextClass = javax.naming.InitialContext .class; 352 private Properties contextProps; 353 private boolean cacheContext = true; 354 private transient Context initialContext; 355 356 public SerializableInitialContext() 357 { 358 this("SerializableInitialContext"); 359 } 360 361 public SerializableInitialContext(String addrType) 362 { 363 super(addrType); 364 } 365 366 public String getJndiName() 367 { 368 return jndiName; 369 } 370 371 public void setJndiName(final String jndiName) 372 { 373 this.jndiName = jndiName; 374 } 375 376 public boolean getCacheContext() 377 { 378 return cacheContext; 379 } 380 381 public void setCacheContext(final boolean cacheContext) 382 { 383 this.cacheContext = cacheContext; 384 } 385 386 public String getInitialContext() 387 { 388 return contextClass.getName(); 389 } 390 391 public void loadClass(String className) throws ClassNotFoundException 392 { 393 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 394 contextClass = loader.loadClass(className); 395 } 396 397 public void setProperties(final Properties props) 398 { 399 contextProps = props; 400 } 401 402 public Properties getProperties() 403 { 404 return contextProps; 405 } 406 407 public void loadProperties(String contextPropsURL) throws IOException 408 { 409 InputStream is = null; 410 contextProps = new Properties (); 411 412 try 414 { 415 URL url = new URL (contextPropsURL); 416 is = url.openStream(); 417 contextProps.load(is); 418 return; 419 } 420 catch (IOException e) 421 { is = null; 423 } 424 425 is = Thread.currentThread().getContextClassLoader().getResourceAsStream(contextPropsURL); 426 if( is == null ) 427 { 428 throw new IOException ("Failed to locate context props as URL or resource:"+contextPropsURL); 429 } 430 contextProps.load(is); 431 } 432 433 Context newContext() throws Exception 434 { 435 initialContext = (Context ) NonSerializableFactory.lookup(jndiName); 437 if( initialContext == null ) 439 initialContext = newContext(contextClass, contextProps); 440 return initialContext; 441 } 442 443 static Context newContext(Class contextClass, Properties contextProps) 444 throws Exception 445 { 446 Context ctx = null; 447 try 448 { 449 ctx = newDefaultContext(contextClass, contextProps); 450 } 451 catch(NoSuchMethodException e) 452 { 453 ctx = newLdapContext(contextClass, contextProps); 454 } 455 return ctx; 456 } 457 458 private static Context newDefaultContext(Class contextClass, Properties contextProps) 459 throws Exception 460 { 461 Context ctx = null; 462 Class [] types = {Hashtable .class}; 463 Constructor ctor = contextClass.getConstructor(types); 464 Object [] args = {contextProps}; 465 ctx = (Context ) ctor.newInstance(args); 466 return ctx; 467 } 468 469 private static Context newLdapContext(Class contextClass, Properties contextProps) 470 throws Exception 471 { 472 Context ctx = null; 473 Class [] types = {Hashtable .class, Control [].class}; 474 Constructor ctor = contextClass.getConstructor(types); 475 Object [] args = {contextProps, null}; 476 ctx = (Context ) ctor.newInstance(args); 477 return ctx; 478 } 479 480 public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) 481 throws Exception 482 { 483 Reference ref = (Reference ) obj; 484 SerializableInitialContext sic = (SerializableInitialContext) ref.get(0); 485 return sic.newContext(); 486 } 487 488 public Reference getReference() throws NamingException 489 { 490 Reference ref = new Reference (Context .class.getName(), this, this.getClass().getName(), null); 491 return ref; 492 } 493 494 public Object getContent() 495 { 496 return null; 497 } 498 } 499 500 505 static class CachedContext implements InvocationHandler 506 { 507 Context externalCtx; 508 509 CachedContext(Context externalCtx) 510 { 511 this.externalCtx = externalCtx; 512 } 513 514 static Context createProxyContext(Context ctx) 515 { 516 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 517 Class [] interfaces = ctx.getClass().getInterfaces(); 518 InvocationHandler handler = new CachedContext(ctx); 519 Context proxyCtx = (Context ) Proxy.newProxyInstance(loader, interfaces, handler); 520 return proxyCtx; 521 } 522 523 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable 524 { 525 Object value = null; 526 if( method.getName().equals("close") ) 527 { 528 } 530 else 531 { 532 try 533 { 534 value = method.invoke(externalCtx, args); 535 } 536 catch(InvocationTargetException e) 537 { 538 throw e.getTargetException(); 539 } 540 } 541 return value; 542 } 543 } 544 } 545 | Popular Tags |