• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.jimfs;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.collect.ImmutableMap;
22 import com.google.common.collect.ImmutableSet;
23 import java.nio.file.attribute.BasicFileAttributes;
24 import java.nio.file.attribute.FileAttributeView;
25 import java.util.Arrays;
26 import java.util.Map;
27 import org.checkerframework.checker.nullness.compatqual.NullableDecl;
28 
29 /**
30  * Abstract provider for handling a specific file attribute view.
31  *
32  * @author Colin Decker
33  */
34 public abstract class AttributeProvider {
35 
36   /** Returns the view name that's used to get attributes from this provider. */
name()37   public abstract String name();
38 
39   /** Returns the names of other providers that this provider inherits attributes from. */
inherits()40   public ImmutableSet<String> inherits() {
41     return ImmutableSet.of();
42   }
43 
44   /** Returns the type of the view interface that this provider supports. */
viewType()45   public abstract Class<? extends FileAttributeView> viewType();
46 
47   /**
48    * Returns a view of the file located by the given lookup callback. The given map contains the
49    * views inherited by this view.
50    */
view( FileLookup lookup, ImmutableMap<String, FileAttributeView> inheritedViews)51   public abstract FileAttributeView view(
52       FileLookup lookup, ImmutableMap<String, FileAttributeView> inheritedViews);
53 
54   /**
55    * Returns a map containing the default attribute values for this provider. The keys of the map
56    * are attribute identifier strings (in "view:attribute" form) and the value for each is the
57    * default value that should be set for that attribute when creating a new file.
58    *
59    * <p>The given map should be in the same format and contains user-provided default values. If the
60    * user provided any default values for attributes handled by this provider, those values should
61    * be checked to ensure they are of the correct type. Additionally, if any changes to a
62    * user-provided attribute are necessary (for example, creating an immutable defensive copy), that
63    * should be done. The resulting values should be included in the result map along with default
64    * values for any attributes the user did not provide a value for.
65    */
defaultValues(Map<String, ?> userDefaults)66   public ImmutableMap<String, ?> defaultValues(Map<String, ?> userDefaults) {
67     return ImmutableMap.of();
68   }
69 
70   /** Returns the set of attributes that are always available from this provider. */
fixedAttributes()71   public abstract ImmutableSet<String> fixedAttributes();
72 
73   /** Returns whether or not this provider supports the given attribute directly. */
supports(String attribute)74   public boolean supports(String attribute) {
75     return fixedAttributes().contains(attribute);
76   }
77 
78   /**
79    * Returns the set of attributes supported by this view that are present in the given file. For
80    * most providers, this will be a fixed set of attributes.
81    */
attributes(File file)82   public ImmutableSet<String> attributes(File file) {
83     return fixedAttributes();
84   }
85 
86   /**
87    * Returns the value of the given attribute in the given file or null if the attribute is not
88    * supported by this provider.
89    */
90   @NullableDecl
get(File file, String attribute)91   public abstract Object get(File file, String attribute);
92 
93   /**
94    * Sets the value of the given attribute in the given file object. The {@code create} parameter
95    * indicates whether or not the value is being set upon creation of a new file via a user-provided
96    * {@code FileAttribute}.
97    *
98    * @throws IllegalArgumentException if the given attribute is one supported by this provider but
99    *     it is not allowed to be set by the user
100    * @throws UnsupportedOperationException if the given attribute is one supported by this provider
101    *     and is allowed to be set by the user, but not on file creation and {@code create} is true
102    */
set(File file, String view, String attribute, Object value, boolean create)103   public abstract void set(File file, String view, String attribute, Object value, boolean create);
104 
105   // optional
106 
107   /**
108    * Returns the type of file attributes object this provider supports, or null if it doesn't
109    * support reading its attributes as an object.
110    */
111   @NullableDecl
attributesType()112   public Class<? extends BasicFileAttributes> attributesType() {
113     return null;
114   }
115 
116   /**
117    * Reads this provider's attributes from the given file as an attributes object.
118    *
119    * @throws UnsupportedOperationException if this provider does not support reading an attributes
120    *     object
121    */
readAttributes(File file)122   public BasicFileAttributes readAttributes(File file) {
123     throw new UnsupportedOperationException();
124   }
125 
126   // exception helpers
127 
128   /** Throws a runtime exception indicating that the given attribute cannot be set. */
unsettable(String view, String attribute, boolean create)129   protected static RuntimeException unsettable(String view, String attribute, boolean create) {
130     // This matches the behavior of the real file system implementations: if the attempt to set the
131     // attribute is being made during file creation, throw UOE even though the attribute is one
132     // that cannot be set under any circumstances
133     checkNotCreate(view, attribute, create);
134     throw new IllegalArgumentException("cannot set attribute '" + view + ":" + attribute + "'");
135   }
136 
137   /**
138    * Checks that the attribute is not being set by the user on file creation, throwing an
139    * unsupported operation exception if it is.
140    */
checkNotCreate(String view, String attribute, boolean create)141   protected static void checkNotCreate(String view, String attribute, boolean create) {
142     if (create) {
143       throw new UnsupportedOperationException(
144           "cannot set attribute '" + view + ":" + attribute + "' during file creation");
145     }
146   }
147 
148   /**
149    * Checks that the given value is of the given type, returning the value if so and throwing an
150    * exception if not.
151    */
checkType(String view, String attribute, Object value, Class<T> type)152   protected static <T> T checkType(String view, String attribute, Object value, Class<T> type) {
153     checkNotNull(value);
154     if (type.isInstance(value)) {
155       return type.cast(value);
156     }
157 
158     throw invalidType(view, attribute, value, type);
159   }
160 
161   /**
162    * Throws an illegal argument exception indicating that the given value is not one of the expected
163    * types for the given attribute.
164    */
invalidType( String view, String attribute, Object value, Class<?>... expectedTypes)165   protected static IllegalArgumentException invalidType(
166       String view, String attribute, Object value, Class<?>... expectedTypes) {
167     Object expected =
168         expectedTypes.length == 1 ? expectedTypes[0] : "one of " + Arrays.toString(expectedTypes);
169     throw new IllegalArgumentException(
170         "invalid type "
171             + value.getClass()
172             + " for attribute '"
173             + view
174             + ":"
175             + attribute
176             + "': expected "
177             + expected);
178   }
179 }
180