4 Replies Latest reply on Jul 23, 2008 12:20 PM by Ales Justin

    BootstrapDeployersTest enhancements and AssembledDirectory

    Adrian Brock Master

      I've added some support to the BootstrapDeployersTest
      so you can use the vfs's AssembledDirectory.

      i.e. you can create deployments out of disparate parts of the testsuite structure

      For some simple examples see:
      http://viewvc.jboss.org/cgi-bin/viewvc.cgi/jbossas/projects/jboss-deployers/trunk/deployers-vfs/src/tests/org/jboss/test/deployers/vfs/classloader/test/BootstrapDeployersSmokeTestUnitTestCase.java?revision=75958&view=markup

      But this was a lot harder work than I expected. The AssembledDirectory
      has a number of problems (bugs?) and is not very easy to use.

      There's some FIXMEs here:
      http://viewvc.jboss.org/cgi-bin/viewvc.cgi/jbossas/projects/jboss-deployers/trunk/deployers-vfs/src/tests/org/jboss/test/deployers/BootstrapDeployersTest.java?revision=75958&view=markup
      which show where the problems are, but I'll give some more explanation on this thread

      First the only factory for AssembledDirectory is the AssembledContext
      which is not a part of the public api.

      Also the api should return an AssembledDirectory so you don't have
      to cast from the super class.

      import org.jboss.virtual.plugins.context.vfs.AssembledContext;
      ...
      
       // FIXME Missing factor method in the public api
       protected AssembledDirectory createAssembledDirectory(String name) throws Exception
       {
       AssembledContext ctx = new AssembledContext(name, "");
       return (AssembledDirectory) ctx.getRoot().getVirtualFile();
       }
      


      There is no support for doing something as simple as adding a META-INF directory
      and all its contents to the assembled directory, so I wrote it myself,
      but this obviously should be in the AssembledDirectory class.

       // FIXME why doesn't AssembledDirectory support this simple use case?
       protected void addPath(final AssembledDirectory dir, String path, String name) throws Exception
       {
       URL url = getResource(path);
       if (url == null)
       fail(path + " not found");
       VirtualFile file = VFS.getVirtualFile(url, name);
      
       final VisitorAttributes va = new VisitorAttributes();
       va.setLeavesOnly(true);
       SuffixesExcludeFilter noJars = new SuffixesExcludeFilter(JarUtils.getSuffixes());
       va.setRecurseFilter(noJars);
      
       VirtualFileVisitor visitor = new VirtualFileVisitor()
       {
       public VisitorAttributes getAttributes()
       {
       return va;
       }
      
       public void visit(VirtualFile virtualFile)
       {
       dir.mkdirs(virtualFile.getPathName()).addChild(virtualFile);
       }
       };
       file.visit(visitor);
       }
      


      The urls for assembled directories are broken.
      e.g. if you have vfs://a/ and do mkdir("b") on it, you get back a url
      that says vfs://ab/

      I think this is because it passes null to the "path" when it constructs
      the URI in AssembledContext, but I didn't confirm it.

      For now I've hacked the url handling in the test.

       protected DeploymentUnit assertChild(DeploymentUnit parent, String name)
       {
       // FIXME AssembledContext URLs are broken
       String parentName = parent.getName();
       if (parentName.endsWith("/"))
       parentName = parentName.substring(0, parentName.length()-1);
       name = name + "/";
      
       name = parentName + name ;
       List<DeploymentUnit> children = parent.getChildren();
       for (DeploymentUnit child : children)
       {
       if (name.equals(child.getName()))
       return child;
       }
       throw new AssertionFailedError("Child " + name + " not found in " + children);
       }
      


      addResources() is a not very easy to use api and it is slow
      (takes about 1 second for deployers-vfs).

      The example here looks easy, but it actually scans the whole class
      and resource structure, even though I've already told it
      which package I want it to add.

      Having filters is nice, but there's no need to be dumb or slow about simple cases.

       protected void addPackage(AssembledDirectory dir, Class<?> reference) throws Exception
       {
       String packagePath = ClassLoaderUtils.packageNameToPath(reference.getName());
       dir.addResources(reference, new String[] { packagePath + "/*.class" } , new String[0]);
       }
      


      Part of the reason it is slow is that it is trying to open jars
      (some of which in deployers-vfs are deliberately broken to test
      error handling).

      I hacked the test to reduce the noise from this,
      as the FIXME says, there should really be a method in AbstractTestCase
      to change the logging level, rather than having to assume log4j

       protected void setUp() throws Exception
       {
       super.setUp();
       // This is a hack for a hack. ;-)
       AbstractJDKChecker.getExcluded().add(BootstrapDeployersTest.class);
      
       // Reduce the noise from the VFS
       // FIXME add method change logging levels to AbstractTestCase
       Logger.getLogger(FileSystemContext.class).setLevel(Level.INFO);
       }