aboutsummaryrefslogtreecommitdiff
path: root/jimfs/src/main/java/com/google/common/jimfs/UnixAttributeProvider.java
diff options
context:
space:
mode:
Diffstat (limited to 'jimfs/src/main/java/com/google/common/jimfs/UnixAttributeProvider.java')
-rw-r--r--jimfs/src/main/java/com/google/common/jimfs/UnixAttributeProvider.java170
1 files changed, 170 insertions, 0 deletions
diff --git a/jimfs/src/main/java/com/google/common/jimfs/UnixAttributeProvider.java b/jimfs/src/main/java/com/google/common/jimfs/UnixAttributeProvider.java
new file mode 100644
index 0000000..e314643
--- /dev/null
+++ b/jimfs/src/main/java/com/google/common/jimfs/UnixAttributeProvider.java
@@ -0,0 +1,170 @@
+/*
+ * 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.FileAttributeView;
+import java.nio.file.attribute.FileTime;
+import java.nio.file.attribute.GroupPrincipal;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.UserPrincipal;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Attribute provider that provides the "unix" attribute view.
+ *
+ * @author Colin Decker
+ */
+final class UnixAttributeProvider extends AttributeProvider {
+
+ private static final ImmutableSet<String> ATTRIBUTES =
+ ImmutableSet.of("uid", "ino", "dev", "nlink", "rdev", "ctime", "mode", "gid");
+
+ private static final ImmutableSet<String> INHERITED_VIEWS =
+ ImmutableSet.of("basic", "owner", "posix");
+
+ private final AtomicInteger uidGenerator = new AtomicInteger();
+ private final ConcurrentMap<Object, Integer> idCache = new ConcurrentHashMap<>();
+
+ @Override
+ public String name() {
+ return "unix";
+ }
+
+ @Override
+ public ImmutableSet<String> inherits() {
+ return INHERITED_VIEWS;
+ }
+
+ @Override
+ public ImmutableSet<String> fixedAttributes() {
+ return ATTRIBUTES;
+ }
+
+ @Override
+ public Class<UnixFileAttributeView> viewType() {
+ return UnixFileAttributeView.class;
+ }
+
+ @Override
+ public UnixFileAttributeView view(
+ FileLookup lookup, ImmutableMap<String, FileAttributeView> inheritedViews) {
+ // This method should not be called... and it cannot be called through the public APIs in
+ // java.nio.file since there is no public UnixFileAttributeView type.
+ throw new UnsupportedOperationException();
+ }
+
+ // TODO(cgdecker): Since we can now guarantee that the owner/group for an file are our own
+ // implementation of UserPrincipal/GroupPrincipal, it would be nice to have them store a unique
+ // ID themselves and just get that rather than doing caching here. Then this could be a singleton
+ // like the rest of the AttributeProviders. However, that would require a way for the owner/posix
+ // providers to create their default principals using the lookup service for the specific file
+ // system.
+
+ /** Returns an ID that is guaranteed to be the same for any invocation with equal objects. */
+ private Integer getUniqueId(Object object) {
+ Integer id = idCache.get(object);
+ if (id == null) {
+ id = uidGenerator.incrementAndGet();
+ Integer existing = idCache.putIfAbsent(object, id);
+ if (existing != null) {
+ return existing;
+ }
+ }
+ return id;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object get(File file, String attribute) {
+ switch (attribute) {
+ case "uid":
+ UserPrincipal user = (UserPrincipal) file.getAttribute("owner", "owner");
+ return getUniqueId(user);
+ case "gid":
+ GroupPrincipal group = (GroupPrincipal) file.getAttribute("posix", "group");
+ return getUniqueId(group);
+ case "mode":
+ Set<PosixFilePermission> permissions =
+ (Set<PosixFilePermission>) file.getAttribute("posix", "permissions");
+ return toMode(permissions);
+ case "ctime":
+ return FileTime.fromMillis(file.getCreationTime());
+ case "rdev":
+ return 0L;
+ case "dev":
+ return 1L;
+ case "ino":
+ return file.id();
+ case "nlink":
+ return file.links();
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public void set(File file, String view, String attribute, Object value, boolean create) {
+ throw unsettable(view, attribute, create);
+ }
+
+ @SuppressWarnings("OctalInteger")
+ private static int toMode(Set<PosixFilePermission> permissions) {
+ int result = 0;
+ for (PosixFilePermission permission : permissions) {
+ checkNotNull(permission);
+ switch (permission) {
+ case OWNER_READ:
+ result |= 0400; // note: octal numbers
+ break;
+ case OWNER_WRITE:
+ result |= 0200;
+ break;
+ case OWNER_EXECUTE:
+ result |= 0100;
+ break;
+ case GROUP_READ:
+ result |= 0040;
+ break;
+ case GROUP_WRITE:
+ result |= 0020;
+ break;
+ case GROUP_EXECUTE:
+ result |= 0010;
+ break;
+ case OTHERS_READ:
+ result |= 0004;
+ break;
+ case OTHERS_WRITE:
+ result |= 0002;
+ break;
+ case OTHERS_EXECUTE:
+ result |= 0001;
+ break;
+ default:
+ throw new AssertionError(); // no other possible values
+ }
+ }
+ return result;
+ }
+}