[jboss-cvs] jboss-cvs-commits Digest, Vol 42, Issue 123

Ales Justin ales.justin at gmail.com
Thu Dec 10 10:39:00 EST 2009


This looks wrong, at least to me.

Here are my concerns:
(1) VFSHandleRegistry is complete VFS impl detail, and as such, doesn't 
belong to Deployers
(2) like I already mentioned, StructureDeployer(s) might not even be invoked
(2a) even if SD(a) are invoked, you don't know which one will be invoked 1st
(2b) if none SD gets invoked, who will mount this? (auto-mount?)
(3) addition to (2a), this means each SD will have to include this mount 
code, which is very intrusive
(4) addition to (2b), the next step are real deployers, where this code 
also doesn't belong -- I only wanna think about my logic in my deployer, 
nothing else

VFS3 looks a lot like what we did for previous Deployers (pre AS5),
but there one deployer controlled it all, making such mount/unmount easy 
to add/handle.
With "aspectized" deployers, and clean separation of user/dev/server 
view and structure/real handling and predetermined/vfs, this becomes 
harder to impl in such a straight way.

Apart from being very much intrusive and not actually finding proper 
place to mount, I only see auto-mounting as a solution.
While DeploymentContext::cleanup is already a proper place to unmount.

Well, this is all already being discussed on the forum and jboss-dev,
but you're not listening to me at all ... just don't say I didn't warn 
you when we're gonna disagree on the actual inclusion of this into MC. ;-)

 > ----------------------------------------------------------------------
 >
 > Message: 1
 > Date: Wed, 9 Dec 2009 21:48:22 -0500
 > From: jboss-cvs-commits at lists.jboss.org
 > Subject: [jboss-cvs] JBossAS SVN: r97658 - in
 > 	projects/jboss-deployers/branches/vfs3/deployers-vfs/src:
 > 	main/java/org/jboss/deployers/vfs/plugins/structure/jar and 1	other
 > 	directories.
 > To: jboss-cvs-commits at lists.jboss.org
 > Message-ID:
 > 	<200912100248.nBA2mMpr004411 at svn01.web.mwc.hst.phx2.redhat.com>
 > Content-Type: text/plain; charset=UTF-8
 >
 > Author: johnbailey
 > Date: 2009-12-09 21:48:22 -0500 (Wed, 09 Dec 2009)
 > New Revision: 97658
 >
 > Added:
 > 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/main/java/org/jboss/deployers/vfs/plugins/structure/VFSHandleRegistry.java
 > 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/test/java/org/jboss/test/deployers/vfs/structure/VFSHandleRegistryTest.java
 > Modified:
 > 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/main/java/org/jboss/deployers/vfs/plugins/structure/AbstractVFSDeploymentContext.java
 > 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/main/java/org/jboss/deployers/vfs/plugins/structure/jar/JARStructure.java
 > Log:
 > [JBAS-7362] Introduced basic VFS Handle Registry for managing and 
cleaning up mount handles
 >
 > Modified: 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/main/java/org/jboss/deployers/vfs/plugins/structure/AbstractVFSDeploymentContext.java
 > ===================================================================
 > --- 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/main/java/org/jboss/deployers/vfs/plugins/structure/AbstractVFSDeploymentContext.java 
2009-12-10 02:37:38 UTC (rev 97657)
 > +++ 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/main/java/org/jboss/deployers/vfs/plugins/structure/AbstractVFSDeploymentContext.java 
2009-12-10 02:48:22 UTC (rev 97658)
 > @@ -451,6 +451,16 @@
 >     {
 >        return new AbstractVFSDeploymentUnit(this);
 >     }
 > +
 > +   @Override
 > +   public void cleanup()
 > +   {
 > +      if(VFSHandleRegistry.isMounted(root))
 > +      {
 > +         VFSHandleRegistry.cleanup(root);
 > +      }
 > +      super.cleanup();
 > +   }
 >
 >     @SuppressWarnings("unchecked")
 >     public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException
 >
 > Added: 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/main/java/org/jboss/deployers/vfs/plugins/structure/VFSHandleRegistry.java
 > ===================================================================
 > --- 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/main/java/org/jboss/deployers/vfs/plugins/structure/VFSHandleRegistry.java 
                         (rev 0)
 > +++ 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/main/java/org/jboss/deployers/vfs/plugins/structure/VFSHandleRegistry.java 
2009-12-10 02:48:22 UTC (rev 97658)
 > @@ -0,0 +1,233 @@
 > +/*
 > + * JBoss, Home of Professional Open Source
 > + * Copyright 2009, JBoss Inc., and individual contributors as indicated
 > + * by the @authors tag. See the copyright.txt in the distribution for a
 > + * full listing of individual contributors.
 > + *
 > + * This is free software; you can redistribute it and/or modify it
 > + * under the terms of the GNU Lesser General Public License as
 > + * published by the Free Software Foundation; either version 2.1 of
 > + * the License, or (at your option) any later version.
 > + *
 > + * This software is distributed in the hope that it will be useful,
 > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 > + * Lesser General Public License for more details.
 > + *
 > + * You should have received a copy of the GNU Lesser General Public
 > + * License along with this software; if not, write to the Free
 > + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 > + * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 > + */
 > +package org.jboss.deployers.vfs.plugins.structure;
 > +
 > +import java.io.Closeable;
 > +import java.io.IOException;
 > +import java.util.Collection;
 > +import java.util.Collections;
 > +import java.util.LinkedList;
 > +import java.util.List;
 > +import java.util.concurrent.ConcurrentHashMap;
 > +import java.util.concurrent.ConcurrentMap;
 > +import java.util.concurrent.Executors;
 > +import java.util.concurrent.atomic.AtomicInteger;
 > +
 > +import org.jboss.vfs.TempFileProvider;
 > +import org.jboss.vfs.VFS;
 > +import org.jboss.vfs.VFSUtils;
 > +import org.jboss.vfs.VirtualFile;
 > +import org.jboss.vfs.util.PathTokenizer;
 > +
 > +/**
 > + * Registry used to manage handles to mounted Virtual FileSystems.
 > + *
 > + * @author <a href="jbailey at redhat.com">John Bailey</a>
 > + */
 > +public class VFSHandleRegistry
 > +{
 > +   /*
 > +    * Simple handle with no side effects.
 > +    */
 > +   private static final Closeable NO_OP_HANDLE = new Closeable()
 > +   {
 > +      public void close() throws IOException
 > +      {
 > +      }
 > +   };
 > +
 > +   /* Root entry in the tree. */
 > +   private static final RegistryEntry rootEntry = new RegistryEntry();
 > +
 > +   /**
 > +    * Private constructor
 > +    */
 > +   private VFSHandleRegistry()
 > +   {
 > +   }
 > +
 > +   /**
 > +    * Determine if the provided {@link VirtualFile} has been mounted.
 > +    */
 > +   public static boolean isMounted(VirtualFile virtualFile)
 > +   {
 > +      return getEntry(virtualFile).isMounted();
 > +   }
 > +
 > +   /**
 > +    * Add a registry entry for the provided {@link VirtualFile} and 
attache the handle
 > +    *
 > +    * @param virtualFile
 > +    * @param handle
 > +    */
 > +   public static void addHandle(VirtualFile virtualFile, Closeable 
handle)
 > +   {
 > +      getEntry(virtualFile).setHandle(handle);
 > +   }
 > +
 > +   /**
 > +    * Get a handle for the provided {@link VirtualFile}.  If the 
entry is already mounted
 > +    * a the reference count will be incremented and a a handle will 
be returned.  If the entry
 > +    * is not mounted, the entry will be mounted based on they type 
of {@link VirtualFile} provided.
 > +    * Files will be mounted as a Zip archive, and directories will 
register a no-op handle.
 > +    *
 > +    * @param virtualFile
 > +    * @return a handle to the {@link VirtualFile}
 > +    * @throws IOException
 > +    */
 > +   public static Closeable getHandleFor(VirtualFile virtualFile) 
throws IOException
 > +   {
 > +      RegistryEntry entry = getEntry(virtualFile);
 > +      if (!entry.isMounted())
 > +      {
 > +         Closeable handle = null;
 > +         if (virtualFile.isFile())
 > +         {
 > +            handle = VFS.mountZip(virtualFile, virtualFile, 
getTempFileProvider(virtualFile.getName()));
 > +         }
 > +         else
 > +         {
 > +            handle = NO_OP_HANDLE;
 > +         }
 > +         addHandle(virtualFile, handle);
 > +      }
 > +      return entry.aquireReference();
 > +   }
 > +
 > +   /**
 > +    * Recursively cleanup all mounted handles starting at the 
provided {@link VirtualFile} location.
 > +    *
 > +    * @param virtualFile
 > +    */
 > +   public static void cleanup(VirtualFile virtualFile)
 > +   {
 > +      RegistryEntry startEntry = getEntry(virtualFile);
 > +      Collection<RegistryEntry> entries = 
startEntry.getEntriesRecursive();
 > +      for (RegistryEntry entry : entries)
 > +      {
 > +         entry.cleanup();
 > +      }
 > +   }
 > +
 > +   /**
 > +    * Get the entry from the tree creating the entry if not present.
 > +    *
 > +    * @param virtualFile
 > +    * @return
 > +    */
 > +   private static RegistryEntry getEntry(VirtualFile virtualFile)
 > +   {
 > +      if (virtualFile == null)
 > +      {
 > +         throw new IllegalArgumentException("A valid VirtualFile is 
required.");
 > +      }
 > +      return rootEntry.find(virtualFile);
 > +   }
 > +
 > +   private static TempFileProvider getTempFileProvider(String name) 
throws IOException
 > +   {
 > +      return TempFileProvider.create(name, 
Executors.newSingleThreadScheduledExecutor());
 > +   }
 > +
 > +   static class RegistryEntry
 > +   {
 > +      private final ConcurrentMap<String, RegistryEntry> children = 
new ConcurrentHashMap<String, RegistryEntry>();
 > +
 > +      private Closeable handle;
 > +
 > +      private final AtomicInteger refCount = new AtomicInteger();
 > +
 > +      Collection<RegistryEntry> getChildren()
 > +      {
 > +         return Collections.unmodifiableCollection(children.values());
 > +      }
 > +
 > +      RegistryEntry find(VirtualFile file)
 > +      {
 > +         return find(PathTokenizer.getTokens(file.getPathName()));
 > +      }
 > +
 > +      RegistryEntry find(List<String> path)
 > +      {
 > +         if (path.isEmpty())
 > +         {
 > +            return this;
 > +         }
 > +         String current = path.remove(0);
 > +         children.putIfAbsent(current, new RegistryEntry());
 > +         RegistryEntry childEntry = children.get(current);
 > +         return childEntry.find(path);
 > +      }
 > +
 > +      void setHandle(Closeable handle)
 > +      {
 > +         this.handle = handle;
 > +      }
 > +
 > +      void cleanup()
 > +      {
 > +         VFSUtils.safeClose(handle);
 > +         handle = null;
 > +         refCount.set(0);
 > +      }
 > +
 > +      boolean isMounted()
 > +      {
 > +         return handle != null;
 > +      }
 > +
 > +      Collection<RegistryEntry> getEntriesRecursive()
 > +      {
 > +         List<RegistryEntry> allHandles = new 
LinkedList<RegistryEntry>();
 > +         collectEntries(this, allHandles);
 > +         return allHandles;
 > +      }
 > +
 > +      void collectEntries(RegistryEntry registryEntry, 
List<RegistryEntry> entries)
 > +      {
 > +         for (RegistryEntry childEntry : registryEntry.getChildren())
 > +         {
 > +            collectEntries(childEntry, entries);
 > +         }
 > +         entries.add(registryEntry);
 > +      }
 > +
 > +      Closeable aquireReference()
 > +      {
 > +         refCount.incrementAndGet();
 > +         return new Reference();
 > +      }
 > +
 > +      class Reference implements Closeable
 > +      {
 > +         public void close() throws IOException
 > +         {
 > +            if (refCount.decrementAndGet() == 0)
 > +            {
 > +               cleanup();
 > +            }
 > +
 > +         }
 > +      }
 > +
 > +   }
 > +}
 >
 > Modified: 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/main/java/org/jboss/deployers/vfs/plugins/structure/jar/JARStructure.java
 > ===================================================================
 > --- 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/main/java/org/jboss/deployers/vfs/plugins/structure/jar/JARStructure.java 
2009-12-10 02:37:38 UTC (rev 97657)
 > +++ 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/main/java/org/jboss/deployers/vfs/plugins/structure/jar/JARStructure.java 
2009-12-10 02:48:22 UTC (rev 97658)
 > @@ -21,9 +21,11 @@
 >  */
 >  package org.jboss.deployers.vfs.plugins.structure.jar;
 >
 > +import java.io.Closeable;
 >  import java.util.Set;
 >  import java.util.Collections;
 >  import java.util.HashSet;
 > +import java.util.concurrent.Executors;
 >
 >  import org.jboss.beans.metadata.api.annotations.Install;
 >  import org.jboss.beans.metadata.api.annotations.Uninstall;
 > @@ -31,7 +33,11 @@
 >  import org.jboss.deployers.spi.deployer.matchers.JarExtensionProvider;
 >  import org.jboss.deployers.spi.structure.ContextInfo;
 >  import 
org.jboss.deployers.vfs.plugins.structure.AbstractVFSStructureDeployer;
 > +import org.jboss.deployers.vfs.plugins.structure.VFSHandleRegistry;
 >  import org.jboss.deployers.vfs.spi.structure.StructureContext;
 > +import org.jboss.vfs.TempFileProvider;
 > +import org.jboss.vfs.VFS;
 > +import org.jboss.vfs.VFSUtils;
 >  import org.jboss.vfs.VirtualFile;
 >
 >  /**
 > @@ -101,27 +107,23 @@
 >           suffixes.remove(extension);
 >     }
 >
 > -   private boolean isArchive(String name) {
 > -      int i = name.length() - 1;
 > -      for (;;) {
 > -         i = name.lastIndexOf('.', i);
 > -         if (i == -1) {
 > -            return false;
 > -         }
 > -         if (suffixes.contains(name.substring(i))) {
 > -            return true;
 > -         }
 > -      }
 > +   private boolean isArchive(String name)
 > +   {
 > +      int idx = name.lastIndexOf('.');
 > +      if (idx == -1)
 > +         return false;
 > +      return suffixes.contains(name.substring(idx).toLowerCase());
 >     }
 >
 >     public boolean determineStructure(StructureContext 
structureContext) throws DeploymentException
 >     {
 >        ContextInfo context = null;
 >        VirtualFile file = structureContext.getFile();
 > +      Closeable handle = null;
 > +      boolean valid = true;
 >        try
 >        {
 >           boolean trace = log.isTraceEnabled();
 > -
 >           if (isLeaf(file) == false)
 >           {
 >              // For non top level directories that don't look like jars
 > @@ -155,6 +157,13 @@
 >           }
 >           else if (isArchive(file.getName()))
 >           {
 > +            if(!VFSHandleRegistry.isMounted(file))
 > +            {
 > +               // Need to mount the archive.
 > +               handle = VFS.mountZip(file, file, 
TempFileProvider.create(file.getName(), 
Executors.newSingleThreadScheduledExecutor()));
 > +               VFSHandleRegistry.addHandle(file, handle);
 > +            }
 > +
 >              if (trace)
 >                 log.trace("... ok - its an archive or at least 
pretending to be.");
 >           }
 > @@ -165,8 +174,6 @@
 >              return false;
 >           }
 >
 > -         boolean valid = true;
 > -
 >           if (isSupportsCandidateAnnotations())
 >           {
 >              StructureContext parentContext = 
structureContext.getParentContext();
 > @@ -193,11 +200,19 @@
 >        }
 >        catch (Exception e)
 >        {
 > +         valid = false;
 >           // Remove the invalid context
 >           if(context != null)
 >              structureContext.removeChild(context);
 >
 >           throw 
DeploymentException.rethrowAsDeploymentException("Error determining 
structure: " + file.getName(), e);
 >        }
 > +      finally
 > +      {
 > +         if(!valid)
 > +         {
 > +            VFSUtils.safeClose(handle);
 > +         }
 > +      }
 >     }
 >  }
 >
 > Added: 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/test/java/org/jboss/test/deployers/vfs/structure/VFSHandleRegistryTest.java
 > ===================================================================
 > --- 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/test/java/org/jboss/test/deployers/vfs/structure/VFSHandleRegistryTest.java 
                         (rev 0)
 > +++ 
projects/jboss-deployers/branches/vfs3/deployers-vfs/src/test/java/org/jboss/test/deployers/vfs/structure/VFSHandleRegistryTest.java 
2009-12-10 02:48:22 UTC (rev 97658)
 > @@ -0,0 +1,187 @@
 > +/*
 > + * JBoss, Home of Professional Open Source
 > + * Copyright 2009, JBoss Inc., and individual contributors as indicated
 > + * by the @authors tag. See the copyright.txt in the distribution for a
 > + * full listing of individual contributors.
 > + *
 > + * This is free software; you can redistribute it and/or modify it
 > + * under the terms of the GNU Lesser General Public License as
 > + * published by the Free Software Foundation; either version 2.1 of
 > + * the License, or (at your option) any later version.
 > + *
 > + * This software is distributed in the hope that it will be useful,
 > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 > + * Lesser General Public License for more details.
 > + *
 > + * You should have received a copy of the GNU Lesser General Public
 > + * License along with this software; if not, write to the Free
 > + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 > + * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 > + */
 > +package org.jboss.test.deployers.vfs.structure;
 > +
 > +import java.io.Closeable;
 > +import java.io.IOException;
 > +import java.net.URL;
 > +import java.util.ArrayList;
 > +import java.util.List;
 > +
 > +import org.jboss.deployers.vfs.plugins.structure.VFSHandleRegistry;
 > +import org.jboss.test.BaseTestCase;
 > +import org.jboss.vfs.VFS;
 > +import org.jboss.vfs.VirtualFile;
 > +
 > +/**
 > + * Test for {@link VFSHandleRegistry}
 > + *
 > + * @author <a href="jbailey at redhat.com">John Bailey</a>
 > + */
 > +public class VFSHandleRegistryTest extends BaseTestCase
 > +{
 > +   private static final Closeable DEFAULT_NO_OP_HANDLE = 
createNoOpTestHandle();
 > +
 > +   public VFSHandleRegistryTest(String name)
 > +   {
 > +      super(name);
 > +   }
 > +
 > +   public void testRegister() throws Exception
 > +   {
 > +      VirtualFile virtualFile = VFS.getChild("test/path/test.ear");
 > +
 > +      VFSHandleRegistry.addHandle(virtualFile, DEFAULT_NO_OP_HANDLE);
 > +      assertTrue(VFSHandleRegistry.isMounted(virtualFile));
 > +   }
 > +
 > +   public void testCleanup() throws Exception
 > +   {
 > +      VirtualFile virtualFile = VFS.getChild("test/path/test.ear");
 > +
 > +      TestHandle handle = createNoOpTestHandle();
 > +
 > +      VFSHandleRegistry.addHandle(virtualFile, handle);
 > +      assertTrue(VFSHandleRegistry.isMounted(virtualFile));
 > +
 > +      VFSHandleRegistry.cleanup(virtualFile);
 > +
 > +      assertTrue(handle.isClosed());
 > +      assertFalse(VFSHandleRegistry.isMounted(virtualFile));
 > +   }
 > +
 > +   public void testCleanupWithChildren() throws Exception
 > +   {
 > +      final List<Closeable> handles = new ArrayList<Closeable>();
 > +
 > +      Callback callback = new Callback()
 > +      {
 > +         public void call(TestHandle handle)
 > +         {
 > +            handles.add(handle);
 > +         }
 > +      };
 > +
 > +      TestHandle earHandle = createTestHandle(callback);
 > +
 > +      VirtualFile earVirtualFile = VFS.getChild("test/path/test.ear");
 > +      VFSHandleRegistry.addHandle(earVirtualFile, earHandle);
 > +
 > +      TestHandle warHandle = createTestHandle(callback);
 > +
 > +      VirtualFile warVirtualFile = 
VFS.getChild("test/path/test.ear/test.war");
 > +      VFSHandleRegistry.addHandle(warVirtualFile, warHandle);
 > +
 > +      TestHandle jarHandle = createTestHandle(callback);
 > +
 > +      VirtualFile jarVirtualFile = 
VFS.getChild("test/path/test.ear/test.war/WEB-INF/lib/test.jar");
 > +      VFSHandleRegistry.addHandle(jarVirtualFile, jarHandle);
 > +
 > +      assertFalse(jarHandle.isClosed());
 > +      assertFalse(warHandle.isClosed());
 > +      assertFalse(earHandle.isClosed());
 > +
 > +      VFSHandleRegistry.cleanup(earVirtualFile);
 > +
 > +      assertTrue(jarHandle.isClosed());
 > +      assertTrue(warHandle.isClosed());
 > +      assertTrue(earHandle.isClosed());
 > +
 > +      assertEquals(jarHandle, handles.get(0));
 > +      assertEquals(warHandle, handles.get(1));
 > +      assertEquals(earHandle, handles.get(2));
 > +   }
 > +
 > +   public void testReferenceCounting() throws Exception
 > +   {
 > +      VirtualFile virtualFile = VFS.getChild("test/path/test.jar");
 > +      Closeable handleOne = VFSHandleRegistry.getHandleFor(virtualFile);
 > +      assertTrue(VFSHandleRegistry.isMounted(virtualFile));
 > +      Closeable handleTwo = VFSHandleRegistry.getHandleFor(virtualFile);
 > +      handleOne.close();
 > +      assertTrue(VFSHandleRegistry.isMounted(virtualFile));
 > +      handleTwo.close();
 > +      assertFalse(VFSHandleRegistry.isMounted(virtualFile));
 > +   }
 > +
 > +   public void testAutoMount() throws Exception {
 > +      VirtualFile file = 
getVirtualFile("/structure/jar/indirectory/archive.jar");
 > +      assertTrue(file.isFile());
 > +      Closeable handleOne = VFSHandleRegistry.getHandleFor(file);
 > +      assertTrue(VFSHandleRegistry.isMounted(file));
 > +      assertTrue(file.isDirectory());
 > +      handleOne.close();
 > +      assertTrue(file.isFile());
 > +   }
 > +
 > +   private static TestHandle createTestHandle(Callback callback)
 > +   {
 > +      return new TestHandle(callback);
 > +   }
 > +
 > +   private static TestHandle createNoOpTestHandle()
 > +   {
 > +      return new TestHandle(new Callback()
 > +      {
 > +         public void call(TestHandle handle)
 > +         {
 > +
 > +         }
 > +      });
 > +   }
 > +
 > +   protected VirtualFile getVirtualFile(String path) throws Exception
 > +   {
 > +      URL url = getResource(path);
 > +      VirtualFile rootFile = VFS.getChild(url);
 > +      return rootFile;
 > +   }
 > +
 > +   private static class TestHandle implements Closeable
 > +   {
 > +      private boolean closed;
 > +
 > +      private final Callback callback;
 > +
 > +      public TestHandle(Callback callback)
 > +      {
 > +         super();
 > +         this.callback = callback;
 > +      }
 > +
 > +      public void close() throws IOException
 > +      {
 > +         closed = true;
 > +         callback.call(this);
 > +      }
 > +
 > +      public boolean isClosed()
 > +      {
 > +         return closed;
 > +      }
 > +   }
 > +
 > +   private static interface Callback
 > +   {
 > +      void call(TestHandle handle);
 > +   }
 > +}
 >



More information about the jboss-cvs-commits mailing list