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

Reply via email to