blob: f5cade23c3a962bb6b9af29913ca54b86f38f454 [file] [log] [blame]
/*
* Copyright 2013 Google Inc.
*
* 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 com.google.common.jimfs;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttributeView;
import java.util.Arrays;
import java.util.Map;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
/**
* Abstract provider for handling a specific file attribute view.
*
* @author Colin Decker
*/
public abstract class AttributeProvider {
/** Returns the view name that's used to get attributes from this provider. */
public abstract String name();
/** Returns the names of other providers that this provider inherits attributes from. */
public ImmutableSet<String> inherits() {
return ImmutableSet.of();
}
/** Returns the type of the view interface that this provider supports. */
public abstract Class<? extends FileAttributeView> viewType();
/**
* Returns a view of the file located by the given lookup callback. The given map contains the
* views inherited by this view.
*/
public abstract FileAttributeView view(
FileLookup lookup, ImmutableMap<String, FileAttributeView> inheritedViews);
/**
* Returns a map containing the default attribute values for this provider. The keys of the map
* are attribute identifier strings (in "view:attribute" form) and the value for each is the
* default value that should be set for that attribute when creating a new file.
*
* <p>The given map should be in the same format and contains user-provided default values. If the
* user provided any default values for attributes handled by this provider, those values should
* be checked to ensure they are of the correct type. Additionally, if any changes to a
* user-provided attribute are necessary (for example, creating an immutable defensive copy), that
* should be done. The resulting values should be included in the result map along with default
* values for any attributes the user did not provide a value for.
*/
public ImmutableMap<String, ?> defaultValues(Map<String, ?> userDefaults) {
return ImmutableMap.of();
}
/** Returns the set of attributes that are always available from this provider. */
public abstract ImmutableSet<String> fixedAttributes();
/** Returns whether or not this provider supports the given attribute directly. */
public boolean supports(String attribute) {
return fixedAttributes().contains(attribute);
}
/**
* Returns the set of attributes supported by this view that are present in the given file. For
* most providers, this will be a fixed set of attributes.
*/
public ImmutableSet<String> attributes(File file) {
return fixedAttributes();
}
/**
* Returns the value of the given attribute in the given file or null if the attribute is not
* supported by this provider.
*/
@NullableDecl
public abstract Object get(File file, String attribute);
/**
* Sets the value of the given attribute in the given file object. The {@code create} parameter
* indicates whether or not the value is being set upon creation of a new file via a user-provided
* {@code FileAttribute}.
*
* @throws IllegalArgumentException if the given attribute is one supported by this provider but
* it is not allowed to be set by the user
* @throws UnsupportedOperationException if the given attribute is one supported by this provider
* and is allowed to be set by the user, but not on file creation and {@code create} is true
*/
public abstract void set(File file, String view, String attribute, Object value, boolean create);
// optional
/**
* Returns the type of file attributes object this provider supports, or null if it doesn't
* support reading its attributes as an object.
*/
@NullableDecl
public Class<? extends BasicFileAttributes> attributesType() {
return null;
}
/**
* Reads this provider's attributes from the given file as an attributes object.
*
* @throws UnsupportedOperationException if this provider does not support reading an attributes
* object
*/
public BasicFileAttributes readAttributes(File file) {
throw new UnsupportedOperationException();
}
// exception helpers
/** Throws a runtime exception indicating that the given attribute cannot be set. */
protected static RuntimeException unsettable(String view, String attribute, boolean create) {
// This matches the behavior of the real file system implementations: if the attempt to set the
// attribute is being made during file creation, throw UOE even though the attribute is one
// that cannot be set under any circumstances
checkNotCreate(view, attribute, create);
throw new IllegalArgumentException("cannot set attribute '" + view + ":" + attribute + "'");
}
/**
* Checks that the attribute is not being set by the user on file creation, throwing an
* unsupported operation exception if it is.
*/
protected static void checkNotCreate(String view, String attribute, boolean create) {
if (create) {
throw new UnsupportedOperationException(
"cannot set attribute '" + view + ":" + attribute + "' during file creation");
}
}
/**
* Checks that the given value is of the given type, returning the value if so and throwing an
* exception if not.
*/
protected static <T> T checkType(String view, String attribute, Object value, Class<T> type) {
checkNotNull(value);
if (type.isInstance(value)) {
return type.cast(value);
}
throw invalidType(view, attribute, value, type);
}
/**
* Throws an illegal argument exception indicating that the given value is not one of the expected
* types for the given attribute.
*/
protected static IllegalArgumentException invalidType(
String view, String attribute, Object value, Class<?>... expectedTypes) {
Object expected =
expectedTypes.length == 1 ? expectedTypes[0] : "one of " + Arrays.toString(expectedTypes);
throw new IllegalArgumentException(
"invalid type "
+ value.getClass()
+ " for attribute '"
+ view
+ ":"
+ attribute
+ "': expected "
+ expected);
}
}