de.schlichtherle.io.ArchiveDetector Maven / Gradle / Ivy
Show all versions of truezip Show documentation
/*
* Copyright (C) 2005-2010 Schlichtherle IT Services
*
* 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 de.schlichtherle.io;
import de.schlichtherle.io.archive.spi.*;
import java.io.*;
import java.net.*;
/**
* Detects archive files solely by scanning file paths -
* usually by testing for file name suffixes like .zip or the
* like.
* Whenever an archive file is recognized, the
* {@link #getArchiveDriver(String)} method returns an instance of the
* {@link ArchiveDriver} interface which allows to access it.
*
* {@code ArchiveDetector} instances are assigned to {@code File}
* instances in the following way:
*
* - If an archive detector is explicitly provided as a parameter to the
* constructor of the {@code File} class or any other method which
* creates {@code File} instances (e.g. {@code listFiles(*)}),
* then this archive detector is used.
*
- Otherwise, the archive detector returned by
* {@link File#getDefaultArchiveDetector} is used.
* This is initially set to the predefined instance {@link #DEFAULT}.
* Both the class property and the predefined instance can be customized.
*
*
* An archive file which has been recognized by an archive detector is said
* to be a prospective archive file.
* On the first read or write access to a prospective archive file, TrueZIP
* checks its true state in cooperation with the {@link ArchiveDriver}.
* If the true state of the file turns out to be actually a directory or not
* to be compatible to the archive file format, it's said to be a false
* positive archive file.
* TrueZIP implements the appropriate behavior for all read or write
* operations according to the true state.
* Thanks to this design, TrueZIP detects and handles all kinds of false
* positives correctly.
*
* Implementations must be (virtually) immutable and hence thread safe.
*
* Rather than implementing {@code ArchiveDetector} directly, it's easier
* to instantiate or subclass the {@link DefaultArchiveDetector} class.
* This class provides a registry for archive file suffixes and archive drivers
* which can be easily customized via configuration files or Java code.
*
* Since TrueZIP 6.4, although it's not required, it's recommended for
* implementations to implement the {@link java.io.Serializable} interface,
* too, so that {@link de.schlichtherle.io.File} instances which use it can
* be serialized.
*
* @see DefaultArchiveDetector
* @see File
* @see ArchiveDriver
* @author Christian Schlichtherle
* @version $Id$
* @since TrueZIP 6.0
*/
public interface ArchiveDetector extends FileFactory {
//
// Predefined default implementations:
//
/**
* Never recognizes archive files in a path.
* This can be used as the end of a chain of
* {@code DefaultArchiveDetector} instances or if archive files
* shall be treated like ordinary files rather than (virtual) directories.
*
* @see DefaultArchiveDetector
*/
DefaultArchiveDetector NULL = new DefaultArchiveDetector(""); // or null
/**
* Recognizes the archive file suffixes defined by the key
* {@code DEFAULT} in the configuration file(s).
* If only TrueZIP's default configuration file is used, then this is set
* so that no additional JARs are required on the runtime class path.
*
* This archive detector is initially returned by
* {@link File#getDefaultArchiveDetector}.
*
* Note that the actual set of archive file suffixes detected by this
* instance may be extended without prior notice in future releases.
*
* @see DefaultArchiveDetector How Configuration Files are located and
* processed by the DefaultArchiveDetector class
*/
DefaultArchiveDetector DEFAULT = new DefaultArchiveDetector(
GlobalArchiveDriverRegistry.INSTANCE.defaultSuffixes);
/**
* Recognizes all archive file suffixes registerd in the global registry
* by the configuration file(s).
* This requires additional JARs
* on the runtime class path.
*
* Note that the actual set of archive file suffixes detected by this
* instance may be extended without prior notice in future releases.
*
* @see DefaultArchiveDetector How Configuration Files are located and
* processed by the DefaultArchiveDetector class
*/
DefaultArchiveDetector ALL = new DefaultArchiveDetector(
GlobalArchiveDriverRegistry.INSTANCE.allSuffixes);
//
// The one and only method this interface really adds:
//
/**
* Detects whether the given {@code path} identifies a prospective
* archive file or not by applying heuristics to it and returns an
* appropriate {@code ArchiveDriver} to use or {@code null}
* if the path does not denote a prospective archive file or an
* appropriate {@code ArchiveDriver} is not available for some
* reason.
*
* Please note that implementations must not check the actual
* contents of the file identified by {@code path}!
* This is because this method may be used to detect archive files
* by their names before they are actually created or to detect archive
* files which are enclosed in other archive files, in which case there
* is no way to check the file contents in the real file system.
*
* @param path The (not necessarily absolute) path of the prospective
* archive file.
* This does not actually need to be accessible in the real file
* system!
* @return An {@code ArchiveDriver} instance for this archive file
* or {@code null} if the path does not denote an archive
* file (i.e. the path does not have a known suffix)
* or an appropriate {@code ArchiveDriver} is not available
* for some reason.
* @throws NullPointerException If {@code path} is {@code null}.
* @throws RuntimeException A subclass is thrown if loading or
* instantiating an archive driver class fails.
*/
ArchiveDriver getArchiveDriver(String path);
//
// Specification of the (undocumented) contract inherited from FileFactory:
//
/**
* Constructs a new {@link File} instance from the given
* {@code blueprint}.
*
* @param blueprint The file to use as a blueprint. If this is an instance
* of the {@link File} class, its fields are simply copied.
*
* @return A newly created instance of the class {@link File}.
*/
File createFile(java.io.File blueprint);
/**
* @deprecated This factory method is not intented for public use
* - do not use it!
*/
File createFile(java.io.File delegate, File innerArchive);
/**
* @deprecated This factory method is not intented for public use
* and is broken by design - do not use it!
*/
File createFile(File blueprint, java.io.File delegate, File enclArchive);
/**
* Constructs a new {@link File} instance which uses this
* {@link ArchiveDetector} to detect any archive files in its pathname.
*
* @param path The pathname of the file.
* @return A newly created instance of the class {@link File}.
*/
File createFile(String path);
/**
* Constructs a new {@link File} instance which uses this
* {@link ArchiveDetector} to detect any archive files in its pathname.
*
* @param parent The parent pathname as a {@link String}.
* @param child The child pathname as a {@link String}.
*
* @return A newly created instance of the class {@link File}.
*/
File createFile(String parent, String child);
/**
* Constructs a new {@link File} instance which uses this
* {@link ArchiveDetector} to detect any archive files in its pathname.
*
* @param parent The parent pathname as a {@code File}.
* @param child The child pathname as a {@link String}.
*
* @return A newly created instance of the class {@link File}.
*/
File createFile(java.io.File parent, String child);
/**
* Constructs a new {@link File} instance from the given
* {@code uri}. This method behaves similar to
* {@link java.io.File#File(URI) new java.io.File(uri)} with the following
* amendment:
* If the URI matches the pattern
* {@code (jar:)*file:(path!/)*entry}, then the
* constructed file object treats the URI like a (possibly ZIPped) file.
*
* The newly created {@link File} instance uses this
* {@link ArchiveDetector} to detect any archive files in its pathname.
*
* @param uri an absolute, hierarchical URI with a scheme equal to
* {@code file} or {@code jar}, a non-empty path component,
* and undefined authority, query, and fragment components.
*
* @return A newly created instance of the class {@link File}.
*
* @throws NullPointerException if {@code uri} is {@code null}.
* @throws IllegalArgumentException if the preconditions on the
* parameter {@code uri} do not hold.
*/
File createFile(URI uri);
/**
* Creates a new {@link FileInputStream} to read the content of the
* given file.
*
* @param file The file to read.
*
* @return A newly created instance of the class {@link FileInputStream}.
*
* @throws FileNotFoundException On any I/O related issue when opening the file.
*/
FileInputStream createFileInputStream(java.io.File file)
throws FileNotFoundException;
/**
* Creates a new {@link FileOutputStream} to write the new content of the
* given file.
*
* @param file The file to write.
* @param append If {@code true} the new content should be appended
* to the old content rather than overwriting it.
*
* @return A newly created instance of the class {@link FileOutputStream}.
*
* @throws FileNotFoundException On any I/O related issue when opening the file.
*/
FileOutputStream createFileOutputStream(java.io.File file, boolean append)
throws FileNotFoundException;
}