Package juzu.impl.fs.spi.url

Source Code of juzu.impl.fs.spi.url.URLFileSystem

/*
* Copyright 2013 eXo Platform SAS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package juzu.impl.fs.spi.url;

import juzu.impl.common.Resource;
import juzu.impl.common.Timestamped;
import juzu.impl.common.Tools;
import juzu.impl.fs.spi.PathType;
import juzu.impl.fs.spi.ReadFileSystem;

import javax.inject.Inject;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
public class URLFileSystem extends ReadFileSystem<Node> {

  /** . */
  private final Node root;

  public URLFileSystem() {
    this.root = new Node();
  }

  /**
   * Add the resources from the specified classloader only.
   *
   * @param loader the loader
   * @return this url file system
   * @throws IOException any io exception
   * @throws URISyntaxException any uri syntax exception
   */
  public URLFileSystem add(ClassLoader loader) throws IOException, URISyntaxException {
    return add(loader, loader.getParent());
  }

  /**
   * Add the resources from the <code>from</code> classloader up to the <code>to</code> classloader
   * that is excluded.
   *
   * @param from the classloader from which resources are included
   * @param to the classloader from which resources are excluded
   * @return this url file system
   * @throws IOException any io exception
   * @throws URISyntaxException any uri syntax exception
   */
  public URLFileSystem add(ClassLoader from, ClassLoader to) throws IOException, URISyntaxException {

    // Get file urls from loader
    HashSet<URL> urls = Tools.set(from.getResources(""));

    // Get jar urls from loader
    for (Enumeration<URL> e = from.getResources("META-INF/MANIFEST.MF"); e.hasMoreElements();) {
      URL url = e.nextElement();
      if ("jar".equals(url.getProtocol())) {
        urls.add(url);
      }
    }

    // Remove URLs from extension classloader and above (bootstrap)
    if (to != null) {

      // Remove file urls we don't need
      for (Enumeration<URL> e = to.getResources("");e.hasMoreElements();) {
        urls.remove(e.nextElement());
      }

      // Remove jar urls we don't need
      for (Enumeration<URL> e = to.getResources("META-INF/MANIFEST.MF"); e.hasMoreElements();) {
        URL url = e.nextElement();
        if ("jar".equals(url.getProtocol())) {
          urls.remove(url);
        }
      }
    } else {

    }

    // Add manually this one (fucked up jar: no META-INF/MANIFEST.MF)
    ClassLoader injectCL = Inject.class.getClassLoader();
    URL injectURL = from.getResource(Inject.class.getName().replace('.', '/') + ".class");
    if (injectURL != null) {
      if (to != null) {
        for (ClassLoader current = from;current != to;current = current.getParent()) {
          if (current == injectCL) {
            urls.add(injectURL);
            break;
          }
        }
      } else {
        urls.add(injectURL);
      }
    }

    // Now handle urls
    for (URL url : urls) {
      if (url.getProtocol().equals("jar")) {
        // Correct URL to get root and not manifest
        String s = url.toString();
        int pos = s.lastIndexOf("!/");
        add(new URL(s.substring(0, pos + 2)));
      } else {
        add(url);
      }
    }

    //
    return this;
  }

  public URLFileSystem add(URL url) throws IOException, URISyntaxException {
    String protocol = url.getProtocol();
    if ("file".equals(protocol)) {
      File file = new File(url.toURI());
      if (file.isDirectory()) {
        root.merge(file);
      } else {
        JarFile jar = new JarFile(file, false);
        for (JarEntry entry : Tools.iterable(jar.entries())) {
          root.merge("jar:" + url + "!/", entry.getName());
        }
      }
    } else if ("jar".equals(protocol)) {
      String path = url.getPath();
      int pos = path.lastIndexOf("!/");
      if (pos == -1) {
        throw new MalformedURLException("Malformed URL " + url);
      }
      URL inner = new URL(path.substring(0, pos));
      if (inner.getProtocol().equals("file")) {
        File file = new File(inner.toURI());
        if (file.isDirectory()) {
          throw new IllegalArgumentException("Wrong jar URL " + url);
        } else {
          String prefix = path.substring(pos + 2);
          if (prefix.length() > 0 && !prefix.endsWith("/")) {
            throw new IllegalArgumentException("Wrong nested jar URL, should end with a / or be empty" + url);
          }
          JarFile jar = new JarFile(file, false);
          for (JarEntry entry : Tools.iterable(jar.entries())) {
            String name = entry.getName();
            if (name.startsWith(prefix)) {
              root.merge("jar:" + inner + "!/" + prefix, name.substring(prefix.length()));
            }
          }
        }
      } else {
        throw new UnsupportedOperationException("Not yet supported");
      }
    } else {
      throw new UnsupportedOperationException("Cannot handle url " + url + " yet");
    }
    return this;
  }

  @Override
  public Class<Node> getType() {
    return null;
  }

  @Override
  public String getDescription() {
    return "URLFileSystem[]";
  }

  @Override
  public boolean equals(Node left, Node right) {
    return left == right;
  }

  @Override
  public Node getRoot() throws IOException {
    return root;
  }

  @Override
  public Node getChild(Node dir, String name) throws IOException {
    return dir.get(name);
  }

  @Override
  public long getLastModified(Node path) throws IOException {
    return 1;
  }

  @Override
  public String getName(Node path) {
    return path == root ? "" : path.getKey();
  }

  @Override
  public Iterable<String> getNames(Node path) {
    return path.getPath();
  }

  @Override
  public Iterator<Node> getChildren(Node dir) throws IOException {
    return dir.getEntries();
/*
    return new Iterator<Node>() {

      */
/** . *//*

      private Node next;

      public boolean hasNext() {
        while (next == null && entries.hasNext()) {
          Node next = entries.next();
          this.next = next;
        }
        return next != null;
      }

      public Node next() {
        if (!hasNext()) {
          throw new NoSuchElementException();
        }
        try {
          return next;
        }
        finally {
          next = null;
        }
      }

      public void remove() {
        throw new UnsupportedOperationException();
      }
    };
*/
  }

  @Override
  public PathType typeOf(Node path) throws IOException {
    return path.url == null ? PathType.DIR : PathType.FILE;
  }

  @Override
  public Timestamped<Resource> getResource(Node file) throws IOException {
    if (file.url == null) {
      throw new IOException("Cannot find file " + file.getPath());
    }

    //
    URLConnection conn = file.url.openConnection();
    long lastModified = conn.getLastModified();
    byte[] bytes = Tools.bytes(conn.getInputStream());
    return new Timestamped<Resource>(lastModified, new Resource(bytes, Charset.defaultCharset()));
  }

  @Override
  public File getFile(Node path){
    return null;
  }

  @Override
  public URL getURL(Node path) throws NullPointerException, IOException {
    return path.url;
  }
}
TOP

Related Classes of juzu.impl.fs.spi.url.URLFileSystem

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.