Package limelight.io

Source Code of limelight.io.FileSystem$RelativePath

//- Copyright © 2008-2011 8th Light, Inc. All Rights Reserved.
//- Limelight and all included source files are distributed under terms of the MIT License.

package limelight.io;

import limelight.Context;
import limelight.LimelightException;

import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class FileSystem
{
  public static final Pattern WinDrive = Pattern.compile("[A-Z]\\:(\\\\|/)");

  protected String separator = System.getProperty("file.separator");
  protected boolean windows = System.getProperty("os.name").toLowerCase().contains("windows");

  public static FileSystem installed()
  {
    FileSystem fs = new FileSystem();
    Context.instance().fs = fs;
    return fs;
  }

  public void createDirectory(String path)
  {
    resolve(path).mkdirs();
  }

  public boolean exists(String path)
  {
    return resolve(path).exists();
  }

  public boolean isRoot(String path)
  {
    return resolve(path).isRoot();
  }

  public boolean isDirectory(String path)
  {
    return resolve(path).isDirectory();
  }

  public String absolutePath(String path)
  {
    return resolve(path).getAbsolutePath();
  }

  public OutputStream outputStream(String path)
  {
    return resolve(path).outputStream();
  }

  public InputStream inputStream(String path)
  {
    return resolve(path).inputStream();
  }

  public String[] fileListing(String path)
  {
    return resolve(path).listing();
  }

  public long modificationTime(String path)
  {
    return resolve(path).lastModified();
  }

  public void delete(String path)
  {
    resolve(path).delete();
  }

  public void createTextFile(String path, String content)
  {
    createDirectory(parentPath(path));
    try
    {
      final OutputStream output = outputStream(path);
      output.write(content.getBytes());
      output.close();
    }
    catch(IOException e)
    {
      throw new LimelightException(e);
    }
  }

  public String readTextFile(String path)
  {
    StreamReader reader = new StreamReader(inputStream(path));
    String result = reader.readAll();
    reader.close();
    return result;
  }

  public String parentPath(String path)
  {
    return resolve(path).parentPath();
  }

  public boolean isAbsolute(String path)
  {
    return resolve(path).isAbsolute();
  }

  public String relativePathBetween(String origin, String target)
  {
    if(origin.equals(target))
      return ".";

    final String absoluteOrigin = absolutePath(origin);
    final String absoluteTarget = absolutePath(target);
    if(absoluteOrigin.equals(absoluteTarget))
      return ".";

    String path = "";
    String commonParent = absoluteOrigin;
    while(!absoluteTarget.startsWith(commonParent))
    {
      path += ".." + "/";
      commonParent = parentPath(commonParent);
      if(isRoot(commonParent))
        break;
    }
    String result = path + absoluteTarget.substring(commonParent.length());
    result = result.startsWith("/") ? result.substring(1) : result;
    return removeDuplicateSeparators(result.replace("/", separator()));
  }

  // UTILITY  METHODS --------------------------------------------------------------------------------------------------

  public String separator()
  {
    return separator;
  }

  public String homeDir()
  {
    return absolutePath(System.getProperty("user.home"));
  }

  public String workingDir()
  {
    return absolutePath(System.getProperty("user.dir"));
  }

  public String join(String root, String... parts)
  {
    if(parts.length == 0)
      return root;
    Path path = resolve(root);
    for(String part : parts)
      path = path.append(part);
    return path.toPath();
  }

  public String baseName(String path)
  {
    String name = filename(path);
    final int extensionIndex = name.lastIndexOf(".");
    if(extensionIndex == -1)
      return name;
    else
      return name.substring(0, extensionIndex);
  }

  public String fileExtension(String path)
  {
    final File file = new File(path);
    String name = file.getName();
    final int extensionIndex = name.lastIndexOf(".");
    if(extensionIndex == -1)
      return "";
    else
      return name.substring(extensionIndex);
  }

  public String filename(String path)
  {
    if((windows && WinDrive.matcher(path).matches()) || "/".equals(path))
      return path;
    path = path.replace(separator, "/");
    if(path.endsWith("/"))
      path = path.substring(0, path.length() - 1);
    final int lastSeparator = path.lastIndexOf("/");
    if(lastSeparator == -1)
      return path;
    return path.substring(lastSeparator + 1);
  }

  public String pathTo(String parent, String target)
  {
    if(target == null)
      return parent;
    else if(parent == null || isAbsolute(target))
      return target;
    else
      return join(parent, target);
  }

  // HELPER METHODS ----------------------------------------------------------------------------------------------------

  private static void deleteDirectory(File current)
  {
    File[] files = current.listFiles();

    for(int i = 0; files != null && i < files.length; i++)
    {
      File file = files[i];
      if(file.isDirectory())
        deleteDirectory(file);
      else
        deleteFile(file);
    }
    deleteFile(current);
  }

  private static void deleteFile(File file)
  {
    if(!file.exists())
      return;
    if(!file.delete())
      throw new RuntimeException("Could not delete '" + file.getAbsoluteFile() + "'");
    waitUntilFileIsDeleted(file);
  }

  private static void waitUntilFileIsDeleted(File file)
  {
    int checks = 10;
    while(file.exists())
    {
      if(--checks <= 0)
      {
        System.out.println("Breaking out of delete wait");
        break;
      }
      try
      {
        Thread.sleep(100);
      }
      catch(InterruptedException e)
      {
        //okay
      }
    }
  }

  protected String removeDuplicateSeparators(String path)
  {
    return removeDuplicateSeparators(path, separator());
  }

  protected String removeDuplicateSeparators(String path, String separator)
  {
    final String duplicate = separator + separator;
    if(path.contains(duplicate))
      return removeDuplicateSeparators(path.replace(duplicate, separator));
    else
      return path;
  }

  // WHERE THE MAGIC HAPPENS -------------------------------------------------------------------------------------------

  protected Path resolve(String path)
  {
    if(path.startsWith("file:"))
      return new UriPath(this, path);
    else if(path.startsWith("jar:"))
      return new ZipPath(this, path);
    else
      return new RelativePath(this, path);
  }

  protected static interface Path
  {
    boolean exists();

    void mkdirs();

    boolean isDirectory();

    OutputStream outputStream();

    InputStream inputStream();

    String getAbsolutePath();

    void delete();

    String[] listing();

    long lastModified();

    boolean isRoot();

    String parentPath();

    boolean isAbsolute();

    Path append(String part);

    String toPath();
  }

  private static abstract class FileBasedPath implements Path
  {
    protected abstract File file();

    public boolean exists()
    {
      return file().exists();
    }

    public void mkdirs()
    {
      if(!file().exists() && !file().mkdirs())
        throw new LimelightException("Can't establish directory: " + file().getPath());
    }

    public boolean isDirectory()
    {
      return file().isDirectory();
    }

    public OutputStream outputStream()
    {
      try
      {
        return new FileOutputStream(file());
      }
      catch(FileNotFoundException e)
      {
        throw new LimelightException(e);
      }
    }

    public InputStream inputStream()
    {
      try
      {
        return new FileInputStream(file());
      }
      catch(FileNotFoundException e)
      {
        throw new LimelightException(e);
      }
    }

    public void delete()
    {
      if(file().isDirectory())
        deleteDirectory(file());
      else
        deleteFile(file());
    }

    public String[] listing()
    {
      return file().list();
    }

    public long lastModified()
    {
      return file().lastModified();
    }

    public boolean isRoot()
    {
      try
      {
        return file().getCanonicalFile().getParent() == null;
      }
      catch(IOException e)
      {
        return false;
      }
    }
  }

  private static class UriPath extends FileBasedPath
  {
    private URI uri;
    private File file;
    private FileSystem fs;

    private UriPath(FileSystem fs, String path)
    {
      this.fs = fs;
      try
      {
        if(path.charAt(5) != '/')
          uri = new URI("file:/" + path.substring(5));
        else
          uri = new URI(path);
      }
      catch(URISyntaxException e)
      {
        throw new LimelightException("Failed to create URIPath from: " + path, e);
      }
    }

    protected File file()
    {
      if(file == null)
        file = new File(uri.getPath());
      return file;
    }

    public String getAbsolutePath()
    {
      return uri.toString();
    }

    public String parentPath()
    {
      String path = uri.toString();
      if("file:/".equals(path) || WinDrive.matcher(path.substring(6)).matches())
        return path;
      final int lastSlashIndex = path.lastIndexOf("/");
      if(lastSlashIndex == 8 && WinDrive.matcher(path.substring(6, 9)).matches())
        return path.substring(0, lastSlashIndex + 1);
      else if(lastSlashIndex == 5)
        return "file:/";
      else
        return path.substring(0, lastSlashIndex);
    }

    public boolean isAbsolute()
    {
      return uri.isAbsolute();
    }

    public Path append(String part)
    {
      String path = uri.toString();
      return new UriPath(fs, fs.removeDuplicateSeparators(path + "/" + part, "/"));
    }

    public String toPath()
    {
      return getAbsolutePath();
    }
  }

  private static class RelativePath extends FileBasedPath
  {
    private String path;
    private File file;
    private FileSystem fs;

    public RelativePath(FileSystem fs, String path)
    {
      this.fs = fs;
      this.path = path;
    }

    public File file()
    {
      if(file == null)
        file = new File(path);
      return file;
    }

    public String parentPath()
    {
      final File parent = file().getAbsoluteFile().getParentFile();
      if(parent != null)
        return parent.toURI().toString();
      else
        return getAbsolutePath();
    }

    public boolean isAbsolute()
    {
      return fs.windows ? startsWithWinDive() : path.startsWith(fs.separator);
    }

    public Path append(String part)
    {
      return new RelativePath(fs, fs.removeDuplicateSeparators(path + fs.separator() + part));
    }

    public String toPath()
    {
      return path;
    }

    private boolean startsWithWinDive()
    {
      final Matcher matcher = WinDrive.matcher(path);
      return matcher.find() && matcher.start() == 0;
    }

    public String getAbsolutePath()
    {
      return file().toURI().toString();
    }
  }

  private static class ZipPath implements Path
  {
    private FileBasedPath zipPath;
    private String filePath;
    private ZipFile zip;
    private FileSystem fs;

    private ZipPath(FileSystem fs, String path)
    {
      this.fs = fs;
      final int bangIndex = path.indexOf("!");
      if(bangIndex == -1)
        throw new LimelightException("Invalid Jar file path: " + path);

      zipPath = (FileBasedPath) fs.resolve(path.substring(4, bangIndex));
      filePath = path.substring(bangIndex + 2);
    }

    private ZipPath(FileSystem fs, FileBasedPath zipPath, ZipFile zip, String filePath)
    {
      this.fs = fs;
      this.zipPath = zipPath;
      this.zip = zip;
      this.filePath = filePath;
    }

    private ZipFile zip()
    {
      if(zip == null)
      {
        try
        {
          zip = new ZipFile(zipPath.file());
        }
        catch(IOException e)
        {
          throw new LimelightException(e);
        }
      }
      return zip;
    }

    private ZipEntry zipEntry()
    {
      return zip().getEntry(filePath);
    }

    public boolean exists()
    {
      return zipPath.exists() && (zipEntry() != null);
    }

    public void mkdirs()
    {
      throw new LimelightException("JarPath.mkdirs() is not supported");
    }

    public boolean isDirectory()
    {
      if(filePath.endsWith("/"))
        return zipEntry().isDirectory();
      else
      {
        final ZipEntry entry = zip().getEntry(filePath + "/");
        return entry != null && entry.isDirectory();
      }
    }

    public OutputStream outputStream()
    {
      throw new LimelightException("JarPath.outputStream() is not supported");
    }

    public InputStream inputStream()
    {
      try
      {
        return zip().getInputStream(zipEntry());
      }
      catch(IOException e)
      {
        throw new LimelightException(e);
      }
    }

    public String getAbsolutePath()
    {
      return "jar:" + zipPath.getAbsolutePath() + "!/" + filePath;
    }

    public void delete()
    {
      throw new LimelightException("JarPath.delete() is not supported");
    }

    public String[] listing()
    {
      if(!isDirectory())
        return new String[0];
      else
      {
        filePath = filePath.endsWith("/") ? filePath : filePath + "/";
        ArrayList<String> list = new ArrayList<String>();
        final Enumeration<? extends ZipEntry> entries = zip().entries();
        while(entries.hasMoreElements())
        {
          ZipEntry entry = entries.nextElement();
          final String entryName = entry.getName();
          if(entryName.startsWith(filePath))
          {
            String name = entryName.substring(filePath.length());
            if(name.endsWith("/"))
              name = name.substring(0, name.length() - 2);
            if(name.length() > 0 && !name.contains("/"))
              list.add(fs.filename(entryName));
          }
        }
        return list.toArray(new String[list.size()]);
      }
    }

    public long lastModified()
    {
      return zipEntry().getTime();
    }

    public boolean isRoot()
    {
      return filePath.isEmpty();
    }

    public String parentPath()
    {
      final String base = "jar:" + zipPath.getAbsolutePath() + "!/";
      final int lastSlashIndex = filePath.lastIndexOf("/");
      if(lastSlashIndex > 0)
        return base + filePath.substring(0, lastSlashIndex);
      else
        return base;
    }

    public boolean isAbsolute()
    {
      return zipPath.isAbsolute();
    }

    public Path append(String part)
    {
      final String newFilePath = fs.removeDuplicateSeparators(filePath + "/" + part, "/");
      return new ZipPath(fs, zipPath, zip, newFilePath);
    }

    public String toPath()
    {
      return getAbsolutePath();
    }
  }
}
TOP

Related Classes of limelight.io.FileSystem$RelativePath

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.