//
// Location.java
//
/*
LOCI Bio-Formats package for reading and converting biological file formats.
Copyright (C) 2005-@year@ Melissa Linkert, Curtis Rueden, Chris Allan,
Eric Kjellman and Brian Loranger.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package loci.formats;
import java.io.*;
import java.net.*;
import java.util.Hashtable;
import java.util.Vector;
/**
* Pseudo-extension of java.io.File that supports reading over HTTP.
* It is strongly recommended that you use this instead of java.io.File.
*
* <dl><dt><b>Source code:</b></dt>
* <dd><a href="https://skyking.microscopy.wisc.edu/trac/java/browser/trunk/loci/formats/Location.java">Trac</a>,
* <a href="https://skyking.microscopy.wisc.edu/svn/java/trunk/loci/formats/Location.java">SVN</a></dd></dl>
*/
public class Location {
// -- Static fields --
/** Map from given filenames to actual filenames. */
private static Hashtable idMap = new Hashtable();
// -- Fields --
private boolean isURL = true;
private URL url;
private File file;
// -- Constructors --
public Location(String pathname) {
try {
url = new URL(getMappedId(pathname));
}
catch (MalformedURLException e) {
isURL = false;
}
if (!isURL) file = new File(getMappedId(pathname));
}
public Location(File file) {
isURL = false;
this.file = file;
}
public Location(String parent, String child) {
this(parent + "/" + child);
}
public Location(Location parent, String child) {
this(parent.getAbsolutePath(), child);
}
// -- Location API methods --
/**
* Maps the given id to the actual filename on disk. Typically actual
* filenames are used for ids, making this step unnecessary, but in some
* cases it is useful; e.g., if the file has been renamed to conform to a
* standard naming scheme and the original file extension is lost, then
* using the original filename as the id assists format handlers with type
* identification and pattern matching, and the id can be mapped to the
* actual filename for reading the file's contents.
* @see #getMappedId(String)
*/
public static void mapId(String id, String filename) {
if (idMap == null) idMap = new Hashtable();
if (id == null) return;
if (filename == null) idMap.remove(id);
else idMap.put(id, filename);
}
/**
* Gets the actual filename on disk for the given id. Typically the id itself
* is the filename, but in some cases may not be; e.g., if OMEIS has renamed
* a file from its original name to a standard location such as Files/101,
* the original filename is useful for checking the file extension and doing
* pattern matching, but the renamed filename is required to read its
* contents.
* @see #mapId(String, String)
*/
public static String getMappedId(String id) {
if (idMap == null) return id;
String filename = id == null ? null : (String) idMap.get(id);
return filename == null ? id : filename;
}
public static Hashtable getIdMap() { return idMap; }
public static void setIdMap(Hashtable map) {
if (map != null) idMap = map;
else idMap = new Hashtable();
}
// -- File API methods --
/* @see java.io.File#canRead() */
public boolean canRead() {
return isURL ? true : file.canRead();
}
/* @see java.io.File#canWrite() */
public boolean canWrite() {
return isURL ? false : file.canWrite();
}
/* @see java.io.File#createNewFile() */
public boolean createNewFile() throws IOException {
if (isURL) throw new IOException("Unimplemented");
return file.createNewFile();
}
/* @see java.io.File#delete() */
public boolean delete() {
return isURL ? false : file.delete();
}
/* @see java.io.File#deleteOnExit() */
public void deleteOnExit() {
if (!isURL) file.deleteOnExit();
}
/* @see java.io.File#equals(Object) */
public boolean equals(Object obj) {
return isURL ? url.equals(obj) : file.equals(obj);
}
/* @see java.io.File#exists() */
public boolean exists() {
if (isURL) {
try {
url.getContent();
return true;
}
catch (IOException e) {
return false;
}
}
return file.exists();
}
/* @see java.io.File#getAbsoluteFile() */
public Location getAbsoluteFile() {
return new Location(getAbsolutePath());
}
/* @see java.io.File#getAbsolutePath() */
public String getAbsolutePath() {
return isURL ? url.toExternalForm() : file.getAbsolutePath();
}
/* @see java.io.File#getCanonicalFile() */
public Location getCanonicalFile() throws IOException {
return getAbsoluteFile();
}
/* @see java.io.File#getCanonicalPath() */
public String getCanonicalPath() throws IOException {
return isURL ? getAbsolutePath() : file.getCanonicalPath();
}
/* @see java.io.File#getName() */
public String getName() {
if (isURL) {
String name = url.getFile();
name = name.substring(name.lastIndexOf("/") + 1);
return name;
}
return file.getName();
}
/* @see java.io.File#getParent() */
public String getParent() {
if (isURL) {
String absPath = getAbsolutePath();
absPath = absPath.substring(0, absPath.lastIndexOf("/"));
return absPath;
}
return file.getParent();
}
/* @see java.io.File#getParentFile() */
public Location getParentFile() {
return new Location(getParent());
}
/* @see java.io.File#getPath() */
public String getPath() {
return isURL ? url.getHost() + url.getPath() : file.getPath();
}
/* @see java.io.File#isAbsolute() */
public boolean isAbsolute() {
return isURL ? true : file.isAbsolute();
}
/* @see java.io.File#isDirectory() */
public boolean isDirectory() {
return isURL ? lastModified() == 0 : file.isDirectory();
}
/* @see java.io.File#isFile() */
public boolean isFile() {
return isURL ? lastModified() > 0 : file.isFile();
}
/* @see java.io.File#isHidden() */
public boolean isHidden() {
return isURL ? false : file.isHidden();
}
/* @see java.io.File#lastModified() */
public long lastModified() {
if (isURL) {
try {
return url.openConnection().getLastModified();
}
catch (IOException e) { return 0; }
}
return file.lastModified();
}
/* @see java.io.File#length() */
public long length() {
if (isURL) {
try {
return url.openConnection().getContentLength();
}
catch (IOException e) { return 0; }
}
return file.length();
}
/* @see java.io.File#list() */
public String[] list() {
if (isURL) {
if (!isDirectory()) return null;
try {
URLConnection c = url.openConnection();
InputStream is = c.getInputStream();
boolean foundEnd = false;
Vector files = new Vector();
while (!foundEnd) {
byte[] b = new byte[is.available()];
String s = new String(b);
if (s.toLowerCase().indexOf("</html>") != -1) foundEnd = true;
while (s.indexOf("a href") != -1) {
int ndx = s.indexOf("a href") + 8;
String f = s.substring(ndx, s.indexOf("\"", ndx));
s = s.substring(s.indexOf("\"", ndx) + 1);
Location check = new Location(getAbsolutePath(), f);
if (check.exists()) {
files.add(check.getName());
}
}
}
return (String[]) files.toArray(new String[0]);
}
catch (IOException e) {
return null;
}
}
return file.list();
}
/* @see java.io.File#listFiles() */
public Location[] listFiles() {
String[] s = list();
if (s == null) return null;
Location[] f = new Location[s.length];
for (int i=0; i<f.length; i++) {
f[i] = new Location(getAbsolutePath(), s[i]);
f[i] = f[i].getAbsoluteFile();
}
return f;
}
/* @see java.io.File#toURL() */
public URL toURL() throws MalformedURLException {
return isURL ? url : file.toURI().toURL();
}
// -- Object API methods --
/* @see java.lang.Object#toString() */
public String toString() {
return isURL ? url.toString() : file.toString();
}
}