blob: 0f2a00d2e4555e292a89f668c805639c136a1d4a [file] [log] [blame]
/*-
* Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package com.sleepycat.je.utilint;
import java.io.IOException;
/**
* Provides information about the file store associated with a specific file.
* This class is a wrapper for the information made available by the {@code
* java.nio.file.FileStore} class introduced in Java 7, but using reflection to
* permit Java 6 to determine cleanly at runtime that file stores are not
* supported.
*
* TODO:
* We no longer support Java 6 so much of this mechanism can be removed. Other
* code can assume that a FileStore is always available. Also, if an
* IOException is thrown by FileStore methods, instead of tolerating this we
* should invalidate the Environment, since this is standard JE policy.
* However, we may want to leave the factory interface in place to support
* testing with arbitrary disk space limits.
*/
public abstract class FileStoreInfo {
/**
* The full name of the Java 7 FileStore class, which must be present for
* this class to be supported.
*/
public static final String FILE_STORE_CLASS = "java.nio.file.FileStore";
/** The full name of the Java 7 implementation factory class. */
private static final String JAVA7_FILE_STORE_FACTORY_CLASS =
"com.sleepycat.je.utilint.Java7FileStoreInfo$Java7Factory";
/** The standard factory. */
private static final Factory standardFactory = createFactory();
/** If not null, a factory to use for testing. */
private static volatile Factory testFactory = null;
/** A factory interface for getting FileStoreInfo instances. */
interface Factory {
/** @see #checkSupported */
void factoryCheckSupported();
/** @see #getInfo */
abstract FileStoreInfo factoryGetInfo(String file)
throws IOException;
}
/** A factory class whose operations fail with a given exception. */
private static class FailingFactory implements Factory {
final RuntimeException exception;
FailingFactory(final RuntimeException exception) {
this.exception = exception;
}
@Override
public void factoryCheckSupported() {
throw exception;
}
@Override
public FileStoreInfo factoryGetInfo(@SuppressWarnings("unused")
String file) {
throw exception;
}
}
/** Support subclasses. */
protected FileStoreInfo() { }
/** Create the standard factory. */
private static Factory createFactory() {
try {
Class.forName(FILE_STORE_CLASS);
} catch (ClassNotFoundException e) {
return new FailingFactory(
new UnsupportedOperationException(
"FileStoreInfo is only supported for Java 7 and later"));
}
try {
return Class.forName(JAVA7_FILE_STORE_FACTORY_CLASS)
.asSubclass(Factory.class)
.newInstance();
} catch (Exception e) {
return new FailingFactory(
new IllegalStateException(
"Problem accessing class " +
JAVA7_FILE_STORE_FACTORY_CLASS + ": " + e,
e));
}
}
/**
* Checks whether the current Java runtime supports providing information
* about file stores. Returns normally if called on a Java 7 runtime
* or later, otherwise throws {@link UnsupportedOperationException}.
*
* @throws UnsupportedOperationException if the current runtime does not
* support file stores
*/
public static final synchronized void checkSupported() {
getFactory().factoryCheckSupported();
}
/** Returns the current factory. */
private static synchronized Factory getFactory() {
return (testFactory == null) ? standardFactory : testFactory;
}
/** For testing: specifies the factory, or null for the default. */
public static void setFactory(final Factory factory) {
testFactory = factory;
}
/**
* Returns a {@link FileStoreInfo} instance that provides information about
* the file store associated with the specified file. Throws {@link
* UnsupportedOperationException} if called on a Java runtime prior to Java
* 7. Equal objects will be returned for all files associated with the
* same file store.
*
* @param file the file
* @return an instance of {@code FileStoreInfo}
* @throws UnsupportedOperationException if called on a Java runtime prior
* to Java 7
* @throws IllegalStateException if an unexpected exception occurs when
* attempting to use reflection to access the underlying implementation
* @throws IOException if an I/O error occurs
*/
public static FileStoreInfo getInfo(final String file)
throws IOException {
return getFactory().factoryGetInfo(file);
}
/**
* Returns the size, in bytes, of the file store.
*
* @return the size of the file store, in bytes
* @throws IOException if an I/O error occurs
*/
public abstract long getTotalSpace()
throws IOException;
/**
* Returns the number of bytes available in the file store.
*
* @return the number of bytes available
* @throws IOException if an I/O error occurs
*/
public abstract long getUsableSpace()
throws IOException;
}