aboutsummaryrefslogtreecommitdiff
path: root/jimfs/src/main/java/com/google/common/jimfs/AttributeProvider.java
blob: f5cade23c3a962bb6b9af29913ca54b86f38f454 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
 * 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);
  }
}