Package org.jboss.seam.integration.jbossas.vfs

Source Code of org.jboss.seam.integration.jbossas.vfs.VFSScanner

package org.jboss.seam.integration.jbossas.vfs;


import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Enumeration;
import java.util.List;

import org.jboss.seam.deployment.AbstractScanner;
import org.jboss.seam.deployment.DeploymentStrategy;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
import org.jboss.virtual.VFS;
import org.jboss.virtual.VirtualFile;
import org.jboss.virtual.spi.registry.VFSRegistry;

/**
* JBoss VFS aware scanner.
*
* @author <a href="mailto:ales.justin@jboss.com">Ales Justin</a>
* @author Pete Muir
*/
public class VFSScanner extends AbstractScanner
{
   protected final LogProvider log = Logging.getLogProvider(getClass());

   protected static Method handleMethod;
   private long timestamp;

   public VFSScanner(DeploymentStrategy deploymentStrategy)
   {
      super(deploymentStrategy);
   }

   static
   {
      try
      {
         handleMethod = AbstractScanner.class.getDeclaredMethod("handle", String.class);
         handleMethod.setAccessible(true);
      }
      catch (Throwable t)
      {
         handleMethod = null;
      }
   }

   /**
    * Get the virtual file root.
    *
    * @param url         the root URL
    * @param parentDepth level of parent depth
    * @return actual virtual file from url param
    * @throws IOException for any error
    */
   protected VirtualFile getRoot(URL url, int parentDepth) throws IOException
   {
      log.trace("Root url: " + url);

      // try cache first, it should also have proper depth
      VFSRegistry registry = VFSRegistry.getInstance();
      VirtualFile vf = registry.getFile(url);
      int depth = parentDepth;
      while (vf != null && depth > 0)
      {
         vf = vf.getParent();
         depth--;
      }
      if (vf != null)
         return vf;

      String urlString = url.toExternalForm();
      int p = urlString.indexOf(":");
      String file = urlString.substring(p + 1);
      URL vfsurl = null;
      String relative;
      File fp = new File(file);

      log.trace("File: " + fp);

      if (fp.exists())
      {
         vfsurl = fp.getParentFile().toURL();
         relative = fp.getName();
      }
      else
      {
         File curr = fp;
         relative = fp.getName();
         while ((curr = curr.getParentFile()) != null)
         {
            if (curr.exists())
            {
               vfsurl = curr.toURL();
               break;
            }
            else
            {
               relative = curr.getName() + "/" + relative;
            }
         }
      }

      log.trace("URL: " + vfsurl + ", relative: " + relative);

      // no sense in checking cache, we already did that
      VirtualFile top = VFS.createNewRoot(vfsurl);
      top = top.getChild(relative);
      while (parentDepth > 0)
      {
         if (top == null)
            throw new IllegalArgumentException("Null parent: " + vfsurl + ", relative: " + relative);
         top = top.getParent();
         parentDepth--;
      }

      log.trace("Top: " + top);

      return top;
   }

   public void scanDirectories(File[] directories)
   {
      scanDirectories(directories, new File[0]);
   }

   @Override
   public void scanDirectories(File[] directories, File[] excludedDirectories)
   {
      for (File directory : directories)
      {
         handleDirectory(directory, null, excludedDirectories);
      }
   }

   /**
    * Handle directories.
    *
    * @param file the file to handle
    * @param path the current path
    * @param excludedDirectories the excluded dirs
    */
   private void handleDirectory(File file, String path, File[] excludedDirectories)
   {
      for (File excludedDirectory : excludedDirectories)
      {
         if (file.equals(excludedDirectory))
         {
            log.trace("Skipping excluded directory: " + file);
            return;
         }
      }

      // one wrapper delegate per invocation
      FileModifiableResource delegate = new FileModifiableResource();

      log.trace("Handling directory: " + file);
      for (File child : file.listFiles())
      {
         String newPath = (path == null) ? child.getName() : path + '/' + child.getName();
         if (child.isDirectory())
         {
            handleDirectory(child, newPath, excludedDirectories);
         }
         else
         {
            delegate.setFile(child);
            try
            {
               handleItem(delegate, newPath);
            }
            catch (IOException ignored)
            {
            }
         }
      }
   }

   public void scanResources(String[] resources)
   {
      for (String resourceName : resources)
      {
         try
         {
            Enumeration<URL> urlEnum = getDeploymentStrategy().getClassLoader().getResources(resourceName);
            while (urlEnum.hasMoreElements())
            {
               URL url = urlEnum.nextElement();
               VirtualFile root = getRoot(url, resourceName.lastIndexOf('/') > 0 ? 2 : 1);
               if (root != null)
                  handleRoot(root);
               else
                  log.trace("Null root: " + url);
            }
         }
         catch (IOException ioe)
         {
            log.warn("Cannot read resource: " + resourceName, ioe);
         }
      }
   }

   /**
    * Handle virtual file root.
    *
    * @param root the virtual file root
    * @throws IOException for any error
    */
   protected void handleRoot(VirtualFile root) throws IOException
   {
      // one wrapper delegate per invocation
      VirtualFileModifiableResource delegate = new VirtualFileModifiableResource();

      if (root.isLeaf())
      {
         delegate.setFile(root);
         touchTimestamp(delegate);
         handleItemIgnoreErrors(root.getPathName());
      }
      else
      {
         boolean isArchive = root.isArchive();
         String rootPathName = root.getPathName();
         int rootPathNameLength = rootPathName.length();
         List<VirtualFile> children = root.getChildrenRecursively(LeafVirtualFileFilter.INSTANCE);
         for (VirtualFile child : children)
         {
            String name = child.getPathName();
            // move past '/'
            int length = rootPathNameLength;
            if (name.charAt(length) == '/')
               length++;

            String path = name.substring(length);

            if (isArchive)
            {
               // don't timestamp check zip entries, just handle them
               handleItemIgnoreErrors(path);
            }
            else
            {
               // check if we need to touch
               delegate.setFile(child);
               handleItem(delegate, path);
            }
         }
      }
   }

   /**
    * Handle item.
    *
    * @param resource the item's resource
    * @param name the item name
    * @throws IOException for any error
    */
   protected void handleItem(ModifiableResource resource, String name) throws IOException
   {
      boolean doTouch = true;
      try
      {
         if (handleMethod != null)
            doTouch = (Boolean)handleMethod.invoke(this, name);
      }
      catch (Exception e)
      {
         IOException ioe = new IOException();
         ioe.initCause(e);
         throw ioe;
      }

      if (doTouch)
      {
         touchTimestamp(resource);
      }
      // we haven't handled it before
      if (handleMethod == null)
      {
         handleItemIgnoreErrors(name);
      }
   }

   /**
    * Handle item, ignore any errors.
    *
    * @param name the item name
    */
   protected void handleItemIgnoreErrors(String name)
   {
      try
      {
         handleItem(name);
      }
      catch (Throwable t)
      {
         log.warn("Error handling item '" + name + "': " + t);
      }
   }

   /**
    * Update timestamp.
    *
    * @param file the file to check
    * @throws IOException for any error
    */
   private void touchTimestamp(ModifiableResource file) throws IOException
   {
      long lastModified = file.getLastModified();
      if (lastModified > timestamp)
      {
         timestamp = lastModified;
      }
   }

   @Override
   public long getTimestamp()
   {
      return timestamp;
   }
}
TOP

Related Classes of org.jboss.seam.integration.jbossas.vfs.VFSScanner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.