12 Replies Latest reply on Apr 25, 2009 1:52 AM by Ales Justin

    Retrieve all metadata from a deployment unit.

    Daniel Bevenius Master

      Hi,

      I'm wondering what the correct way of retrieving all metadata from a VFSDeploymentUnit is.
      The following test decribes what we are doing.

      package org.jboss.deployers.vfs.plugins.structure;
      
      import static org.junit.Assert.assertEquals;
      import static org.junit.Assert.assertNotNull;
      
      import java.io.IOException;
      import java.net.URL;
      import java.util.Arrays;
      import java.util.List;
      
      import org.jboss.virtual.MemoryFileFactory;
      import org.jboss.virtual.VFS;
      import org.jboss.virtual.VirtualFile;
      import org.junit.Before;
      import org.junit.BeforeClass;
      import org.junit.Test;
      
      public class AbstractVFSDeploymentContextTest
      {
       private AbstractVFSDeploymentContext context;
       private String fileName = "/WEB-INF/wsdl/test.wsdl";
      
       @BeforeClass
       public static void initVFS()
       {
       VFS.init();
       }
      
       @Before
       public void populateVirtualFileSystem() throws IOException
       {
       context = new AbstractVFSDeploymentContext();
       URL dynamicClassRoot = new URL("vfsmemory", getClass().getSimpleName(), "");
       VirtualFile dynamicClasspathDir = MemoryFileFactory.createRoot(dynamicClassRoot).getRoot();
       URL wsdlUrl = new URL(dynamicClassRoot + fileName);
       MemoryFileFactory.putFile(wsdlUrl, "wsdlcontent".getBytes());
      
       context.setMetaDataLocations(Arrays.asList(new VirtualFile[] {dynamicClasspathDir}));
       }
      
       @Test
       public void getMetaDataFile() throws IOException
       {
       VirtualFile metaDataFile = context.getMetaDataFile(fileName);
       assertNotNull(metaDataFile);
       }
      
       @Test
       public void getMetaDataFiles() throws IOException
       {
       List<VirtualFile> metaDataFiles = context.getMetaDataFiles(null, "");
       assertEquals(1, metaDataFiles.size());
       }
      
       @Test
       public void getAllMetaDataFiles() throws IOException
       {
       List<VirtualFile> metaDataFiles = context.getAllMetaDataFiles();
       assertEquals(1, metaDataFiles.size());
       }
      
      }
      

      Now, the second test method, getMetaDataFiles, fails. This is what we are currently using to retrieve all metadata. Is there another way of retrieving all metadata?

      For the third test method I add the following method to AbstractVFSDeploymentContext and it returns all metadata from the deployment context:
      public List<VirtualFile> getAllMetaDataFiles()
       {
       List<VirtualFile> results = new ArrayList<VirtualFile>();
       try
       {
       for (VirtualFile location : metaDataLocations)
       {
       List<VirtualFile> result = location.getChildren();
       if (result != null && result.isEmpty() == false)
       {
       results.addAll(result);
       deployed();
       }
       }
       }
       catch(final IOException e)
       {
       log.debug("Error retrieving all meta data");
       }
       return results;
      

      }

      This is related to this jira: https://jira.jboss.org/jira/browse/JBWS-2619

      Thanks,

      /Daniel


        • 1. Re: Retrieve all metadata from a deployment unit.
          Ales Justin Master

          First of all you shouldn't code against (VFS)DeploymentContext, as that is considered impl detail.
          It's the (VFS)DeploymentUnit which is the user "face" of deployment's server side.

          And looking at the the AbstractVFSDeploymentContext::getMetaDataFiles(String name, String suffix),
          I don't see why your test doesn't pick up all metadata files.

          As this filter should match your "" suffix.

           public boolean accepts(VirtualFile file)
           {
           String fileName = file.getName();
           if (name != null && fileName.equals(name))
           return true;
           if (suffix != null)
           return fileName.endsWith(suffix);
           return false;
           }
          


          What does the debugging say?

          • 2. Re: Retrieve all metadata from a deployment unit.
            Daniel Bevenius Master

             

            First of all you shouldn't code against (VFS)DeploymentContext, as that is considered impl detail.
            It's the (VFS)DeploymentUnit which is the user "face" of deployment's server side.

            Sorry, the actual code only uses the VFSDeploymentUnit and does not directly access the DeploymentContext. Only this test case does to show that getMetaDataFiles does not return all the meta data files when used with the "" suffix.

            I'll debug this and report back my findings.

            Thanks,

            /Daniel

            • 3. Re: Retrieve all metadata from a deployment unit.
              Daniel Bevenius Master

              In our case the file we are looking of is in a subdirectory and I think this is the problem.
              getMetaDataFiles does not look for files recursively in all metadata locations.

              // Look in the meta data location
              List<VirtualFile> results = new ArrayList<VirtualFile>();
              for (VirtualFile location : metaDataLocations)
              {
               List<VirtualFile> result = location.getChildren(new MetaDataMatchFilter(name, suffix));
               if (result != null && result.isEmpty() == false)
               {
              ...

              There is another constructor for MetaDataMatcher that takes VisitorAttributes. When using the constructor with name and suffix the attributes will be set to VisitorAttributes.LEAVES_ONLY:
              if (attributes == null)
               attributes = VisitorAttributes.LEAVES_ONLY;

              Using the second constructor and setting VisitorAttributes.RECURSE_LEAVES_ONLY does what we want:
              List<VirtualFile> results = new ArrayList<VirtualFile>();
              for (VirtualFile location : metaDataLocations)
              {
               List<VirtualFile> result = location.getChildren(new MetaDataMatchFilter(name, suffix, VisitorAttributes.RECURSE_LEAVES_ONLY));
               if (result != null && result.isEmpty() == false)
               {
              ...

              This might be by design but is there a way for us to accomplish this?

              Thanks,

              /Daniel

              • 4. Re: Retrieve all metadata from a deployment unit.
                Ales Justin Master

                 

                "beve" wrote:
                In our case the file we are looking of is in a subdirectory and I think this is the problem.
                getMetaDataFiles does not look for files recursively in all metadata locations.

                Why would you want to recurse into a metadata location?
                I don't think that's a "natural" behavior.

                Looking up too much might lead to weird behavior.
                e.g. someone might have META-INF/backup/copy-my-jboss-beans.xml
                Hence only "you" know what you wanna scan as sub-dir,
                where as META-INF is by the spec.

                "beve" wrote:

                This might be by design but is there a way for us to accomplish this?

                You can add all the possible metadata sub-directories as metadata locations.


                • 5. Re: Retrieve all metadata from a deployment unit.
                  Daniel Bevenius Master

                   

                  Why would you want to recurse into a metadata location?
                  I don't think that's a "natural" behavior.

                  Well this is not the reason we are using it for right now but there might be the need to have a META-INF/services directory containing Service Provider coniguration files and you might want to include it in the search.





                  • 6. Re: Retrieve all metadata from a deployment unit.
                    Ales Justin Master

                    I'll add this to VFSDeploymentUnit:

                     /**
                     * Gets the metadata files for this deployment unit
                     *
                     * @param filter the file filter
                     * @return the virtual files that match
                     * @throws IllegalArgumentException if both the name and suffix are null
                     */
                     List<VirtualFile> getMetaDataFiles(VirtualFileFilter filter);
                    


                    This will enable you to easily get what you're looking for.
                    e.g. if filter is instance of VirtualFileFilterWithAttributes it will also recurse into metadata locations

                    • 7. Re: Retrieve all metadata from a deployment unit.
                      Daniel Bevenius Master

                       

                      Hence only "you" know what you wanna scan as sub-dir

                      Ah, I think I understand what you mean. I'm not sure if it's a convention to put wsdl files in WEB/wsdl but if so then the JBossWS could:

                      VirtualFile metaDataFile = context.getMetaDataFile("/WEB-INF/wsdl");
                      List<VirtualFile> children = metaDataFile.getChildren();
                      

                      And they could specify a filter if they are only interested in ".wsdl" files.
                      Is that what you meant?

                      Thanks,

                      /Daniel


                      • 8. Re: Retrieve all metadata from a deployment unit.
                        Ales Justin Master

                        Not really. :-)

                        You can definitely do what you posted (except for a little error --> WEB-INF in path :-)),
                        but it's a bit unpractical - you would have to hard code that into a deployer.

                        Where if you do this via filter, directly on metadata locations,
                        you can easily extend your filter, push it to deployer, and you're done.



                        • 9. Re: Retrieve all metadata from a deployment unit.
                          Daniel Bevenius Master

                           

                          You can definitely do what you posted (except for a little error --> WEB-INF in path :-)),
                          but it's a bit unpractical - you would have to hard code that into a deployer.

                          I agree and that is great if you can add this to the VFSDeploymentUnit.

                          Thanks for this! :)

                          /Daniel

                          • 10. Re: Retrieve all metadata from a deployment unit.
                            Ales Justin Master

                            This is now already in 2.0.6.GA Deployers. ;-)

                            • 11. Re: Retrieve all metadata from a deployment unit.
                              Alessio Soldano Master

                              Thanks Ales; btw I see you moved jboss AS Branch_5_x to using the 2.0.6.GA deployers, can we do the same for AS trunk?

                              • 12. Re: Retrieve all metadata from a deployment unit.
                                Ales Justin Master

                                Sure, afaic there shouldn't be any problems.

                                Or you can wait for me to do it,
                                as I have to port the 5_x changes anyway - probably the following week.