7 Replies Latest reply on Apr 16, 2008 9:46 AM by Ales Justin

    Programmatic policy for jar handling

    Ales Justin Master

      Regarding yesterday's discussion about breaking existing external frameworks working on top of VFS and no_copy jar handling.

      One way to change the behavior is by changing URI, to add additional query parameter.
      But I think we should add better control over this, introducing some sort of policy into VFSContext (or some other top level handle).
      This is what I have initially in mind:

      public interface JarHandlerPolicy
      {
       /**
       * Should we create a copy.
       *
       * @param context
       * @param parent
       * @param jarFile
       * @param entry
       * @param url
       * @param entryName
       * @return
       */
       boolean createCopy(VFSContext context, VirtualFileHandler parent, JarFile jarFile, ZipEntry entry, URL url, String entryName);
      }
      

      which would get used at the point where we decide whether we copy the jar or not:
       JarHandlerPolicy policy = context.getPolicy();
       if (forceCopy || policy.createCopy(context, parent, getJar(), entry, url, entryName))
       vfh = NestedJarHandler.create(context, parent, getJar(), entry, url, entryName);
       else
       vfh = new NoCopyNestedJarHandler(context, parent, getJar(), entry, url, entryName);
      

      And for example, very simple war policy would look like
      public class WarHandlingPolicy extends AbstractJarHandlingPolicy
      {
       public boolean internalCreateCopy(VFSContext context, VirtualFileHandler parent, JarFile jarFile, ZipEntry entry, URL url, String entryName)
       {
       return entryName.contains(".war");
       }
      }
      
      public abstract class AbstractJarHandlingPolicy implements JarHandlerPolicy
      {
       public boolean createCopy(VFSContext context, VirtualFileHandler parent, JarFile jarFile, ZipEntry entry, URL url, String entryName)
       {
       return hasCopyOption(context) || internalCreateCopy(context, parent, jarFile, entry, url, entryName);
       }
      
       protected abstract boolean internalCreateCopy(VFSContext context, VirtualFileHandler parent, JarFile jarFile, ZipEntry entry, URL url, String entryName);
      
       protected boolean hasCopyOption(VFSContext context)
       {
       Map<String, String> options = context.getOptions();
       return (options != null && options.get(VFSUtils.USE_COPY_QUERY) != null);
       }
      }
      


      The question is, if we decide to go this way, where do we set this policy?

        • 1. Re: Programmatic policy for jar handling
          Adrian Brock Master

          That's very adhoc and hacky and in the wrong place.

          The VFS doesn't need callbacks based on path names (which aren't even guaranteed)
          with the real semantics belonging in the VDF.

          The real issue is how the creator of the deployment controls the VFS url and the
          behaviour required behind the scenes to handle this problem.

          At the vfs level this is either a parameter on the initial url a failing that or a different protocol
          type to support the legacy unpacking mechanism and the return of a "jar:" url
          from the VirtualFile.toURL().

          For programmatic deployment its easy to decide what the URL upfront should be.

          Other more automatic rules should be in the Structure Deployers. They're the ones
          that know a context is a war and can decide based on some metadata in the deployment
          or an external ruile that a paricular war or all wars should be unpacked when
          they are subdeployments.

          • 2. Re: Programmatic policy for jar handling
            Ales Justin Master

             

            "adrian@jboss.org" wrote:

            At the vfs level this is either a parameter on the initial url a failing that or a different protocol
            type to support the legacy unpacking mechanism and the return of a "jar:" url
            from the VirtualFile.toURL().

            For programmatic deployment its easy to decide what the URL upfront should be.

            Is there a better way to do this than this:
             URL url = getResource("/vfs/context/" + name);
             URI uri = new URI(url.toExternalForm() + "?useCopyJarHandler=true");
            


            "adrian@jboss.org" wrote:

            Other more automatic rules should be in the Structure Deployers. They're the ones that know a context is a war and can decide based on some metadata in the deployment or an external rule that a paricular war or all wars should be unpacked when they are subdeployments.

            Then it could be too late.
            e.g. a War Structure deployer is already going inside war file, checking for WEB-INF and web.xml, by such caching the handler on its parent.
            And we already used what we actually wanted to set - we either created the copy, but the policy would say not to create them, or vice versa.

            • 3. Re: Programmatic policy for jar handling
              Adrian Brock Master

               

              "alesj" wrote:

              "adrian@jboss.org" wrote:

              Other more automatic rules should be in the Structure Deployers. They're the ones that know a context is a war and can decide based on some metadata in the deployment or an external rule that a paricular war or all wars should be unpacked when they are subdeployments.

              Then it could be too late.
              e.g. a War Structure deployer is already going inside war file, checking for WEB-INF and web.xml, by such caching the handler on its parent.
              And we already used what we actually wanted to set - we either created the copy, but the policy would say not to create them, or vice versa.


              The StructureDeployers are only looking for resources and creating ContextInfo.
              The real VFSDeploymentContext is constructed once the structure is determined.

              See VFSStructureBuilder::createChildDeploymentContext()
              which is where any additional metadata (e.g. unpack) would actually get used.

              • 4. Re: Programmatic policy for jar handling
                Adrian Brock Master

                 

                "adrian@jboss.org" wrote:

                The StructureDeployers are only looking for resources and creating ContextInfo.
                The real VFSDeploymentContext is constructed once the structure is determined.

                See VFSStructureBuilder::createChildDeploymentContext()
                which is where any additional metadata (e.g. unpack) would actually get used.


                In principle it could be all implemented in that method.

                If the ContextInfo says unpack=true we just copy the nested jar to temp
                and create a VirtualFileContext over it. The issue would be to make sure
                that the context has the correct parent such that it still has the correct VFS name.

                This is similar to how to the current (but unused) copy to java.io.tmpdir works so
                I knows its possible :-)

                • 5. Re: Programmatic policy for jar handling
                  Ales Justin Master

                  When I'm swapping the root with unpacked on top level, must I also change the root in VFSDeployment?
                  AbstractStructureBuilder.class

                   public DeploymentContext populateContext(Deployment deployment, StructureMetaData metaData) throws DeploymentException
                   {
                   if (deployment == null)
                   throw new IllegalArgumentException("Null deployment");
                   if (metaData == null)
                   throw new IllegalArgumentException("Null metaData");
                  
                   boolean trace = log.isTraceEnabled();
                   if (trace)
                   log.trace("Populating deployment " + deployment.getName() + " metaData=" + metaData);
                  
                   DeploymentContext result;
                   try
                   {
                   result = createRootDeploymentContext(deployment);
                   if (result == null)
                   throw new IllegalStateException("Root deployment context is null");
                   result.setDeployment(deployment);
                  
                   ContextInfo contextInfo = metaData.getContext("");
                   if (contextInfo == null)
                   contextInfo = StructureMetaDataFactory.createContextInfo("", null);
                  
                  // APPLY THE ContextInfo.isUnpack() check here
                  // implementing it in VSFStructureBuilder
                  
                   contextInfo.setPredeterminedManagedObjects(deployment.getPredeterminedManagedObjects());
                   applyContextInfo(result, contextInfo);
                   }
                   catch (Throwable t)
                   {
                   throw DeploymentException.rethrowAsDeploymentException("Error populating deployment " + deployment.getName(), t);
                   }
                  


                  • 6. Re: Programmatic policy for jar handling
                    Adrian Brock Master

                     

                    "alesj" wrote:
                    When I'm swapping the root with unpacked on top level, must I also change the root in VFSDeployment?


                    No the deployment represents the client side view over the original artifact.
                    i.e. it is the request not the response. :-)

                    • 7. Re: Programmatic policy for jar handling
                      Ales Justin Master

                      I'll probably need something like VirtualFilehandler::replaceChild(VirtualFileHandler original, VirtualFilehandler replacement)?