User: starksm
Date: 01/04/20 22:59:05
Modified: src/main/org/jboss/naming ExternalContext.java
ExternalContextMBean.java
Log:
Add a CacheContext attribute and wrap the external Context in a
proxy that ignores user close invocations on inmemory Context
objects.
Revision Changes Path
1.5 +97 -16 jboss/src/main/org/jboss/naming/ExternalContext.java
Index: ExternalContext.java
===================================================================
RCS file: /cvsroot/jboss/jboss/src/main/org/jboss/naming/ExternalContext.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- ExternalContext.java 2001/03/14 19:16:24 1.4
+++ ExternalContext.java 2001/04/21 05:59:05 1.5
@@ -12,6 +12,10 @@
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.net.URL;
import java.util.Hashtable;
import java.util.Properties;
@@ -43,12 +47,10 @@
@see org.jboss.naming.NonSerializableFactory
@author [EMAIL PROTECTED]
-@version $Revision: 1.4 $
+@version $Revision: 1.5 $
*/
public class ExternalContext extends ServiceMBeanSupport implements
ExternalContextMBean
{
- // Constants -----------------------------------------------------
-
// Attributes ----------------------------------------------------
private boolean remoteAccess;
private SerializableInitialContext contextInfo = new
SerializableInitialContext();
@@ -99,6 +101,14 @@
{
this.remoteAccess = remoteAccess;
}
+ public boolean getCacheContext()
+ {
+ return contextInfo.getCacheContext();
+ }
+ public void setCacheContext(boolean cacheContext)
+ {
+ contextInfo.setCacheContext(cacheContext);
+ }
/** Get the class name of the InitialContext implementation to
use. Should be one of:
@@ -154,7 +164,8 @@
*/
public void stopService()
{
- unbind(contextInfo.getJndiName());
+ if( contextInfo.getCacheContext() )
+ unbind(contextInfo.getJndiName());
}
// Protected -----------------------------------------------------
@@ -197,28 +208,49 @@
log.debug("parentCtx="+parentCtx);
Name atomName = fullName.getSuffix(fullName.size()-1);
String atom = atomName.get(0);
+ boolean cacheContext = contextInfo.getCacheContext();
if( remoteAccess == true )
{
// Bind contextInfo as a Referenceable
parentCtx.rebind(atom, contextInfo);
- /* Cache the context in the NonSerializableFactory to avoid creating
+ /* Cache the context using NonSerializableFactory to avoid creating
more than one context for in VM lookups
*/
- NonSerializableFactory.rebind(jndiName, ctx);
+ if( cacheContext == true )
+ {
+ /* If cacheContext is true we need to wrap the Context in a
+ proxy that allows the user to issue close on the lookup
+ Context without closing the inmemory Context.
+ */
+ ctx = CachedContext.createProxyContext(ctx);
+ NonSerializableFactory.rebind(jndiName, ctx);
+ }
}
- else
+ else if( cacheContext == true )
{
/* Bind a reference to the extern context using
- NonSerializableFactory as the ObjectFactory */
- NonSerializableFactory.rebind(rootCtx, jndiName, ctx);
+ NonSerializableFactory as the ObjectFactory. The Context must
+ be wrapped in a proxy that allows the user to issue close on the
+ lookup Context without closing the inmemory Context.
+ */
+ Context proxyCtx = CachedContext.createProxyContext(ctx);
+ NonSerializableFactory.rebind(rootCtx, jndiName, proxyCtx);
}
+ else
+ {
+ /* Bind the contextInfo so that each lookup results in the creation
+ of a new Context object. The returned Context must be closed
+ by the user to prevent resource leaks.
+ */
+ parentCtx.rebind(atom, contextInfo);
+ }
}
private void unbind(String jndiName)
{
try
{
- Context rootCtx = (Context) new InitialContext();
+ Context rootCtx = new InitialContext();
Context ctx = (Context) rootCtx.lookup(jndiName);
if( ctx != null )
ctx.close();
@@ -242,6 +274,7 @@
private String jndiName;
private Class contextClass = javax.naming.InitialContext.class;
private Properties contextProps;
+ private boolean cacheContext = true;
private transient Context initialContext;
public SerializableInitialContext()
@@ -261,6 +294,14 @@
{
this.jndiName = jndiName;
}
+ public boolean getCacheContext()
+ {
+ return cacheContext;
+ }
+ public void setCacheContext(boolean cacheContext)
+ {
+ this.cacheContext = cacheContext;
+ }
public String getInitialContext()
{
return contextClass.getName();
@@ -302,13 +343,11 @@
Context newContext() throws Exception
{
+ // First check the NonSerializableFactory cache
+ initialContext = (Context) NonSerializableFactory.lookup(jndiName);
+ // Create the context from the contextClass and contextProps
if( initialContext == null )
- { // First check the NonSerializableFactory cache
- initialContext = (Context) NonSerializableFactory.lookup(jndiName);
- // Create the context from the contextClass and contextProps
- if( initialContext == null )
- initialContext = newContext(contextClass, contextProps);
- }
+ initialContext = newContext(contextClass, contextProps);
return initialContext;
}
@@ -366,4 +405,46 @@
}
}
+ /** A proxy implementation of Context that simply intercepts the
+ close() method and ignores it since the underlying Context
+ object is being maintained in memory.
+ */
+ static class CachedContext implements InvocationHandler
+ {
+ Context externalCtx;
+ CachedContext(Context externalCtx)
+ {
+ this.externalCtx = externalCtx;
+ }
+
+ static Context createProxyContext(Context ctx)
+ {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ Class[] interfaces = ctx.getClass().getInterfaces();
+ InvocationHandler handler = new CachedContext(ctx);
+ Context proxyCtx = (Context) Proxy.newProxyInstance(loader, interfaces,
handler);
+ return proxyCtx;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable
+ {
+ Object value = null;
+ if( method.getName().equals("close") )
+ {
+ // We just ignore the close method
+ }
+ else
+ {
+ try
+ {
+ value = method.invoke(externalCtx, args);
+ }
+ catch(InvocationTargetException e)
+ {
+ throw e.getTargetException();
+ }
+ }
+ return value;
+ }
+ }
}
1.4 +14 -1 jboss/src/main/org/jboss/naming/ExternalContextMBean.java
Index: ExternalContextMBean.java
===================================================================
RCS file: /cvsroot/jboss/jboss/src/main/org/jboss/naming/ExternalContextMBean.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ExternalContextMBean.java 2001/03/14 06:40:54 1.3
+++ ExternalContextMBean.java 2001/04/21 05:59:05 1.4
@@ -12,7 +12,7 @@
/** The ExternalContext mbean interface.
@author [EMAIL PROTECTED]
-@version $Revision: 1.3 $
+@version $Revision: 1.4 $
*/
public interface ExternalContextMBean extends org.jboss.util.ServiceMBean
{
@@ -32,6 +32,19 @@
remotely.
*/
public void setRemoteAccess(boolean remoteAccess);
+
+ /** Get the cacheContext flag.
+ */
+ public boolean getCacheContext();
+ /** set the cacheContext flag. When set to true, the external Context
+ is only created when the mbean is started and then stored as an in
+ memory object until the mbean is stopped. If cacheContext if set to
+ false, the external Context is created on each lookup using the
+ mbean Properties and InitialContext class. When the uncached Context
+ is looked up by a client, the client should invoke close() on the
+ Context to prevent resource leaks.
+ */
+ public void setCacheContext(boolean flag);
/** Get the class name of the InitialContext implementation to
use. Should be one of:
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development