package org.basex.io;
import java.io.IOException;
import java.text.SimpleDateFormat;
import org.basex.data.Data;
import org.basex.io.in.BufferInput;
import org.basex.util.Token;
import org.xml.sax.InputSource;
/**
* Generic representation for inputs and outputs. The underlying source can
* be a local file ({@link IOFile}), a URL ({@link IOUrl}) or a byte array
* ({@link IOContent}).
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public abstract class IO {
/** Database file suffix. */
public static final String BASEXSUFFIX = ".basex";
/** XQuery file suffix. */
public static final String XQSUFFIX = ".xq";
/** XML file suffix. */
public static final String XMLSUFFIX = ".xml";
/** ZIP file suffix. */
public static final String ZIPSUFFIX = ".zip";
/** CSV file suffix. */
public static final String CSVSUFFIX = ".csv";
/** Text file suffix. */
public static final String TXTSUFFIX = ".txt";
/** JSON file suffix. */
public static final String JSONSUFFIX = ".json";
/** GZIP file suffix. */
public static final String GZSUFFIX = ".gz";
/** File prefix. */
public static final String FILEPREF = "file:";
/** Date format which is appended to backups. */
public static final SimpleDateFormat DATE =
new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
/** Date pattern. */
public static final String DATEPATTERN =
"-\\d{4}-\\d{2}-\\d{2}-\\d{2}-\\d{2}-\\d{2}";
/** XQuery suffixes. */
public static final String[] XQSUFFIXES =
{ XQSUFFIX, ".xqm", ".xqy", ".xql", ".xquery" };
/** ZIP suffixes. */
public static final String[] ZIPSUFFIXES =
{ ZIPSUFFIX, ".docx", ".pptx", ".xslx", ".odt", ".odp", ".ods", ".gz" };
/** XML suffixes. */
static final String[] XMLSUFFIXES =
{ XMLSUFFIX, ".xsl", ".xslt" };
/** HTML suffixes. */
public static final String[] HTMLSUFFIXES =
{ ".xhtml", ".html", ".htm" };
/** Disk block/page size (default: 4096). */
public static final int BLOCKSIZE = 1 << 12;
/** Table node size power (default: 4). */
public static final int NODEPOWER = 4;
/** Table node size power (default: 4). */
public static final int NODESIZE = 1 << NODEPOWER;
/** Entries per block (default: 256). */
public static final int ENTRIES = BLOCKSIZE >>> NODEPOWER;
/** Maximum number of attributes (see bit layout in {@link Data} class). */
public static final int MAXATTS = 0x1F;
/** Offset for inlining numbers (see bit layout in {@link Data} class). */
public static final long OFFNUM = 0x8000000000L;
/** Offset for compressing texts (see bit layout in {@link Data} class). */
public static final long OFFCOMP = 0x4000000000L;
/** File path. The path uses forward slashes, no matter which OS is used. */
String path;
/** First call. */
private boolean more;
/** File name. */
String name;
/**
* Protected constructor.
* @param p path
*/
IO(final String p) {
init(p);
}
/**
* Sets the file path and name.
* @param p file path
*/
final void init(final String p) {
path = p;
final String n = p.substring(p.lastIndexOf('/') + 1);
// use current time if no name is given
name = n.isEmpty() ? Long.toString(System.currentTimeMillis()) +
XMLSUFFIX : n;
}
/**
* <p>Returns a class instance for the specified string. The type of the
* returned instance depends on the string value:</p>
* <ul>
* <li>{@link IOContent}: if the string starts with an angle bracket (<)
* or if it is a {@code null} reference, it is interpreted as XML fragment
* and handled as byte array</li>
* <li>{@link IOFile}: if the string starts with <code>file:</code>, or if it
* does not contain the substring <code>://</code>, it is interpreted as
* local file instance</li>
* <li>{@link IOUrl}: otherwise, it is handled as URL</li>
* </ul>
* If the content of the string value is known in advance, it is advisable
* to call the direct constructors of the correspondent sub class.
*
* @param source source string
* @return IO reference
*/
public static IO get(final String source) {
if(source == null) return new IOContent(Token.EMPTY);
final String s = source.trim();
if(s.startsWith("<")) return new IOContent(Token.token(s));
if(s.startsWith(FILEPREF)) return new IOFile(IOUrl.file(s));
if(IOFile.valid(s)) return new IOFile(s);
return new IOUrl(s);
}
/**
* Returns the contents.
* @return contents
* @throws IOException I/O exception
*/
public abstract byte[] read() throws IOException;
/**
* Tests if the file exists.
* @return result of check
*/
public boolean exists() {
return true;
}
/**
* Tests if this is a directory instance.
* @return result of check
*/
public boolean isDir() {
return false;
}
/**
* Returns the modification date of this file.
* @return modification date
*/
public long timeStamp() {
return System.currentTimeMillis();
}
/**
* Returns the file length.
* @return file length
*/
public abstract long length();
/**
* Checks if more input streams are found.
* @param archive parse archives
* @return result of check
* @throws IOException I/O exception
*/
@SuppressWarnings("unused")
public boolean more(final boolean archive) throws IOException {
return more ^= true;
}
/**
* Returns the next input source.
* @return input source
*/
public abstract InputSource inputSource();
/**
* Returns a buffered reader for the input.
* @return buffered reader
* @throws IOException I/O exception
*/
public abstract BufferInput buffer() throws IOException;
/**
* Merges two filenames.
* @param fn file name/path to be merged
* @return contents
*/
public abstract IO merge(final String fn);
/**
* Checks if this file is an archive.
* @return result of check
*/
public boolean isArchive() {
return false;
}
/**
* Checks if this file contains XML.
* @return result of check
*/
public boolean isXML() {
return false;
}
/**
* Chops the path and the file suffix of the specified filename
* and returns the database name.
* @return database name
*/
public final String dbname() {
final String n = name();
final int i = n.lastIndexOf('.');
return (i != -1 ? n.substring(0, i) : n).replaceAll("[^\\w-]", "");
}
/**
* Returns the name of the resource.
* @return file name
*/
public final String name() {
return name;
}
/**
* Sets the name of the resource.
* @param n file name
*/
public final void name(final String n) {
name = n;
if(path.isEmpty()) path = n;
}
/**
* Returns the path.
* The path uses forward slashes, no matter which OS is used.
* @return path
*/
public final String path() {
return path;
}
/**
* Creates a URL from the specified path.
* @return URL
*/
public String url() {
return path;
}
/**
* Returns the directory.
* @return chopped filename
*/
public String dir() {
return "";
}
/**
* Compares the filename of the specified IO reference.
* @param io io reference
* @return result of check
*/
public final boolean eq(final IO io) {
return path.equals(io.path);
}
@Override
public String toString() {
return path;
}
}