Package juzu.impl.fs.spi

Source Code of juzu.impl.fs.spi.ReadFileSystem

/*
* 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;

import juzu.impl.common.Resource;
import juzu.impl.common.Timestamped;
import juzu.impl.fs.Filter;
import juzu.impl.fs.Visitor;
import juzu.impl.common.Tools;
import juzu.impl.fs.spi.disk.DiskFileSystem;
import juzu.impl.fs.spi.jar.JarFileSystem;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicInteger;

/**
* File system provider interface.
*
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
*/
public abstract class ReadFileSystem<P> {

  public static ReadFileSystem<?> create(URL url) throws IOException {
    String protocol = url.getProtocol();
    if (protocol.equals("jar")) {
      String path = url.getPath();
      int pos = path.lastIndexOf("!/");
      URL nested = new URL(path.substring(0, pos));
      if (nested.getProtocol().equals("file")) {
        return new JarFileSystem(url);
      } else {
        throw new IOException("Cannot handle nested jar URL " + url);
      }
    } else if (protocol.equals("file")) {
      File f;
      try {
        f = new File(url.toURI());
      }
      catch (URISyntaxException e) {
        throw new IOException(e);
      }
      if (f.isDirectory()) {
        return new DiskFileSystem(f);
      } else {
        return new JarFileSystem(url);
      }
    } else {
      throw new IOException("Unsupported URL: " + url);
    }
  }

  /** . */
  public static final int DIR = 0;

  /** . */
  public static final int FILE = 1;

  /** . */
  public static final int PATH = 2;

  /** . */
  private static final Filter NULL = new Filter.Default();

  /** . */
  private final Charset encoding;

  protected ReadFileSystem() {
    // For now it's hardcoded
    this.encoding = Charset.defaultCharset();
  }

  public final Charset getEncoding() {
    return encoding;
  }

  public abstract boolean equals(P left, P right);

  public abstract P getRoot() throws IOException;

  public abstract P getChild(P dir, String name) throws IOException;

  public abstract long getLastModified(P path) throws IOException;

  /**
   * Return the file system type.
   *
   * @return the file system type
   */
  public abstract Class<P> getType();

  /**
   * Returns an description for the file system (for debugging purposes).
   *
   * @return the id
   */
  public abstract String getDescription();

  public abstract String getName(P path);

  public abstract Iterable<String> getNames(P path);

  public abstract Iterator<P> getChildren(P dir) throws IOException;

  public abstract PathType typeOf(P path) throws IOException;

  public abstract Timestamped<Resource> getResource(P file) throws IOException;

  /**
   * Attempt to return a {@link java.io.File} associated with this file or null if no physical file exists.
   *
   * @param path the path
   * @return the file system object
   */
  public abstract File getFile(P path);

  /**
   * Get an URL for the provided path or return null if no such URL can be found.
   *
   * @param path the path
   * @return the URL for this path
   * @throws NullPointerException if the path is null
   * @throws IOException          any io exception
   */
  public abstract URL getURL(P path) throws NullPointerException, IOException;

  public final boolean isDir(P path) throws IOException {
    return typeOf(path) == PathType.DIR;
  }

  public final boolean isFile(P path) throws IOException {
    return typeOf(path) == PathType.FILE;
  }

  public final void dump(Appendable appendable) throws IOException {
    dump(getRoot(), appendable);
  }

  public final void dump(P path, final Appendable appendable) throws IOException {
    final StringBuilder prefix = new StringBuilder();
    traverse(path, new Visitor<P>() {
      public void enterDir(P dir, String name) throws IOException {
        if (name.length() > 0) {
          prefix.append('/').append(name);
        }
      }

      public void file(P file, String name) throws IOException {
        appendable.append(prefix).append(name).append("\n");
      }

      public void leaveDir(P dir, String name) throws IOException {
        if (name.length() > 0) {
          prefix.setLength(prefix.length() - 1 - name.length());
        }
      }
    });
  }

  public final Timestamped<Resource> getResource(Iterable<String> names) throws IOException {
    P path = getPath(names);
    if (path != null && isFile(path)) {
      return getResource(path);
    }
    else {
      return null;
    }
  }

  public final P getPath(String... names) throws IOException {
    return getPath(Arrays.asList(names));
  }

  public final P getPath(Iterable<String> names) throws IOException {
    return getPath(getRoot(), names);
  }

  public final P getPath(P from, String... names) throws IOException {
    return getPath(from, Arrays.asList(names));
  }

  public final P getPath(P from, Iterable<String> names) throws IOException {
    for (String name : names) {
      if (isDir(from)) {
        P child = getChild(from, name);
        if (child != null) {
          from = child;
        }
        else {
          return null;
        }
      }
      else {
        throw new UnsupportedOperationException("handle me gracefully : was expecting " + Tools.list(names) + " to resolve");
      }
    }
    return from;
  }

  public final int size(final int mode) throws IOException {
    switch (mode) {
      case DIR:
      case PATH:
      case FILE:
        break;
      default:
        throw new IllegalArgumentException("Illegal mode " + mode);
    }
    final AtomicInteger size = new AtomicInteger();
    traverse(new Visitor.Default<P>() {
      @Override
      public void enterDir(P dir, String name) throws IOException {
        if (getLastModified(dir) > 0 && (mode == PATH || mode == DIR)) {
          size.incrementAndGet();
        }
      }

      @Override
      public void file(P file, String name) throws IOException {
        if (getLastModified(file) > 0 && (mode == PATH || mode == FILE)) {
          size.incrementAndGet();
        }
      }
    });
    return size.get();
  }

  public final void traverse(Filter<P> filter, Visitor<P> visitor) throws IOException {
    traverse(getRoot(), filter, visitor);
  }

  public final void traverse(Visitor<P> visitor) throws IOException {
    traverse(getRoot(), visitor);
  }

  public final void traverse(P path, Visitor<P> visitor) throws IOException {
    // This is OK as it always return true
    @SuppressWarnings("unchecked")
    Filter<P> filter = NULL;
    traverse(path, filter, visitor);
  }

  public final void traverse(P path, Filter<P> filter, Visitor<P> visitor) throws IOException {
    String name = getName(path);
    if (isDir(path)) {
      if (filter.acceptDir(path, name)) {
        visitor.enterDir(path, name);
        for (Iterator<P> i = getChildren(path);i.hasNext();) {
          P child = i.next();
          traverse(child, filter, visitor);
        }
        visitor.leaveDir(path, name);
      }
    }
    else if (filter.acceptFile(path, name)) {
      visitor.file(path, name);
    }
  }

  public <D> void copy(ReadWriteFileSystem<D> dst) throws IOException {
    copy(new Filter.Default<P>(), dst);
  }

  public <D> void copy(ReadWriteFileSystem<D> dst, D dstPath) throws IOException {
    copy(getRoot(), new Filter.Default<P>(), dst, dstPath);
  }

  public <D> void copy(Filter<P> filter, ReadWriteFileSystem<D> dst) throws IOException {
    copy(getRoot(), filter, dst, dst.getRoot());
  }

  public <D> void copy(P srcPath, Filter<P> filter, ReadWriteFileSystem<D> dst, D dstPath) throws IOException {
    int kind = kind(srcPath, dst, dstPath);
    String srcName = getName(srcPath);

    //
    switch (kind) {
      case 0: {
        if (filter.acceptFile(srcPath, srcName)) {
          dst.updateResource(dstPath, getResource(srcPath).getObject());
        }
        break;
      }
      case 1: {
        // Inspect destination
        for (Iterator<D> i = dst.getChildren(dstPath);i.hasNext();) {
          D next = i.next();
          String name = dst.getName(next);
          P a = getChild(srcPath, name);

          //
          boolean remove;
          if (a == null) {
            remove = true;
          }
          else {
            switch (kind(a, dst, next)) {
              default:
                remove = true;
                break;
              case 0:
                remove = !filter.acceptFile(a, name);
                break;
              case 1:
              case 3:
                remove = !filter.acceptDir(a, name);
                break;
            }
          }

          // Remove or copy
          if (remove) {
            i.remove();
          }
          else {
            copy(a, filter, dst, next);
          }
        }

        //
        for (Iterator<P> i = getChildren(srcPath);i.hasNext();) {
          P next = i.next();
          String name = getName(next);
          D a = dst.getChild(dstPath, name);
          if (a == null) {
            boolean dir = isDir(next);
            boolean accept = dir ? filter.acceptDir(next, name) : filter.acceptFile(next, name);
            if (accept) {
              a = dst.makePath(dstPath, name);
              copy(next, filter, dst, a);
            }
          }
          else {
            // We should not go in this case as the previous loop
            // took care of synchronizing everthing that was existing in the destination
          }
        }
        break;
      }
      default:
        throw new UnsupportedOperationException("Todo " + kind);
    }
  }

  // 0 :
  // 1 :
  // 2 :
  private <D> int kind(P srcPath, ReadWriteFileSystem<D> dst, D dstPath) throws IOException {
    if (isDir(srcPath)) {
      if (dst.isDir(dstPath)) {
        return 1;
      } else if (dst.isFile(dstPath)) {
        return 2;
      } else {
        return 1;
      }
    } else if (isFile(srcPath)) {
      if (dst.isFile(dstPath)) {
        return 0;
      } else if (dst.isDir(dstPath)) {
        return 3;
      } else {
        return 0;
      }
    } else {
      return 4;
    }
  }

  public final URL getURL() throws IOException {
    P root = getRoot();
    return getURL(root);
  }

}
TOP

Related Classes of juzu.impl.fs.spi.ReadFileSystem

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.