acl) throws IOException {
140 | checkNotNull(acl);
141 | lookupFile().setAttribute("acl", "acl", ImmutableList.copyOf(acl));
142 | }
143 |
144 | @Override
145 | public UserPrincipal getOwner() throws IOException {
146 | return ownerView.getOwner();
147 | }
148 |
149 | @Override
150 | public void setOwner(UserPrincipal owner) throws IOException {
151 | ownerView.setOwner(owner);
152 | }
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/AttributeCopyOption.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 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 | /**
20 | * Options for how to handle copying of file attributes when copying a file.
21 | *
22 | * @author Colin Decker
23 | */
24 | enum AttributeCopyOption {
25 | /** Copy all attributes on the file. */
26 | ALL,
27 | /** Copy only the basic attributes (file times) of the file. */
28 | BASIC,
29 | /** Do not copy any of the file's attributes. */
30 | NONE
31 | }
32 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/DirectoryEntry.java:
--------------------------------------------------------------------------------
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 | import static com.google.common.base.Preconditions.checkState;
21 |
22 | import com.google.common.base.MoreObjects;
23 | import com.google.errorprone.annotations.CanIgnoreReturnValue;
24 | import java.nio.file.FileAlreadyExistsException;
25 | import java.nio.file.NoSuchFileException;
26 | import java.nio.file.NotDirectoryException;
27 | import java.nio.file.NotLinkException;
28 | import java.nio.file.Path;
29 | import java.util.Objects;
30 | import org.jspecify.annotations.Nullable;
31 |
32 | /**
33 | * Entry in a directory, containing references to the directory itself, the file the entry links to
34 | * and the name of the entry.
35 | *
36 | * May also represent a non-existent entry if the name does not link to any file in the
37 | * directory.
38 | */
39 | final class DirectoryEntry {
40 |
41 | private final Directory directory;
42 | private final Name name;
43 |
44 | private final @Nullable File file;
45 |
46 | @Nullable DirectoryEntry next; // for use in Directory
47 |
48 | DirectoryEntry(Directory directory, Name name, @Nullable File file) {
49 | this.directory = checkNotNull(directory);
50 | this.name = checkNotNull(name);
51 | this.file = file;
52 | }
53 |
54 | /** Returns {@code true} if and only if this entry represents an existing file. */
55 | public boolean exists() {
56 | return file != null;
57 | }
58 |
59 | /**
60 | * Checks that this entry exists, throwing an exception if not.
61 | *
62 | * @return this
63 | * @throws NoSuchFileException if this entry does not exist
64 | */
65 | @CanIgnoreReturnValue
66 | public DirectoryEntry requireExists(Path pathForException) throws NoSuchFileException {
67 | if (!exists()) {
68 | throw new NoSuchFileException(pathForException.toString());
69 | }
70 | return this;
71 | }
72 |
73 | /**
74 | * Checks that this entry does not exist, throwing an exception if it does.
75 | *
76 | * @return this
77 | * @throws FileAlreadyExistsException if this entry does not exist
78 | */
79 | @CanIgnoreReturnValue
80 | public DirectoryEntry requireDoesNotExist(Path pathForException)
81 | throws FileAlreadyExistsException {
82 | if (exists()) {
83 | throw new FileAlreadyExistsException(pathForException.toString());
84 | }
85 | return this;
86 | }
87 |
88 | /**
89 | * Checks that this entry exists and links to a directory, throwing an exception if not.
90 | *
91 | * @return this
92 | * @throws NoSuchFileException if this entry does not exist
93 | * @throws NotDirectoryException if this entry does not link to a directory
94 | */
95 | @CanIgnoreReturnValue
96 | public DirectoryEntry requireDirectory(Path pathForException)
97 | throws NoSuchFileException, NotDirectoryException {
98 | requireExists(pathForException);
99 | if (!file().isDirectory()) {
100 | throw new NotDirectoryException(pathForException.toString());
101 | }
102 | return this;
103 | }
104 |
105 | /**
106 | * Checks that this entry exists and links to a symbolic link, throwing an exception if not.
107 | *
108 | * @return this
109 | * @throws NoSuchFileException if this entry does not exist
110 | * @throws NotLinkException if this entry does not link to a symbolic link
111 | */
112 | @CanIgnoreReturnValue
113 | public DirectoryEntry requireSymbolicLink(Path pathForException)
114 | throws NoSuchFileException, NotLinkException {
115 | requireExists(pathForException);
116 | if (!file().isSymbolicLink()) {
117 | throw new NotLinkException(pathForException.toString());
118 | }
119 | return this;
120 | }
121 |
122 | /** Returns the directory containing this entry. */
123 | public Directory directory() {
124 | return directory;
125 | }
126 |
127 | /** Returns the name of this entry. */
128 | public Name name() {
129 | return name;
130 | }
131 |
132 | /**
133 | * Returns the file this entry links to.
134 | *
135 | * @throws IllegalStateException if the file does not exist
136 | */
137 | public File file() {
138 | checkState(exists());
139 | return file;
140 | }
141 |
142 | /** Returns the file this entry links to or {@code null} if the file does not exist */
143 | public @Nullable File fileOrNull() {
144 | return file;
145 | }
146 |
147 | @Override
148 | public boolean equals(Object obj) {
149 | if (obj instanceof DirectoryEntry) {
150 | DirectoryEntry other = (DirectoryEntry) obj;
151 | return directory.equals(other.directory)
152 | && name.equals(other.name)
153 | && Objects.equals(file, other.file);
154 | }
155 | return false;
156 | }
157 |
158 | @Override
159 | public int hashCode() {
160 | return Objects.hash(directory, name, file);
161 | }
162 |
163 | @Override
164 | public String toString() {
165 | return MoreObjects.toStringHelper(this)
166 | .add("directory", directory)
167 | .add("name", name)
168 | .add("file", file)
169 | .toString();
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/DowngradedDirectoryStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 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 java.io.IOException;
22 | import java.nio.file.DirectoryStream;
23 | import java.nio.file.Path;
24 | import java.nio.file.SecureDirectoryStream;
25 | import java.util.Iterator;
26 |
27 | /**
28 | * A thin wrapper around a {@link SecureDirectoryStream} that exists only to implement {@link
29 | * DirectoryStream} and NOT implement {@link SecureDirectoryStream}.
30 | *
31 | * @author Colin Decker
32 | */
33 | final class DowngradedDirectoryStream implements DirectoryStream {
34 |
35 | private final SecureDirectoryStream secureDirectoryStream;
36 |
37 | DowngradedDirectoryStream(SecureDirectoryStream secureDirectoryStream) {
38 | this.secureDirectoryStream = checkNotNull(secureDirectoryStream);
39 | }
40 |
41 | @Override
42 | public Iterator iterator() {
43 | return secureDirectoryStream.iterator();
44 | }
45 |
46 | @Override
47 | public void close() throws IOException {
48 | secureDirectoryStream.close();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/DowngradedSeekableByteChannel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 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.errorprone.annotations.CanIgnoreReturnValue;
22 | import java.io.IOException;
23 | import java.nio.ByteBuffer;
24 | import java.nio.channels.FileChannel;
25 | import java.nio.channels.SeekableByteChannel;
26 |
27 | /**
28 | * A thin wrapper around a {@link FileChannel} that exists only to implement {@link
29 | * SeekableByteChannel} but NOT extend {@link FileChannel}.
30 | *
31 | * @author Colin Decker
32 | */
33 | final class DowngradedSeekableByteChannel implements SeekableByteChannel {
34 |
35 | private final FileChannel channel;
36 |
37 | DowngradedSeekableByteChannel(FileChannel channel) {
38 | this.channel = checkNotNull(channel);
39 | }
40 |
41 | @Override
42 | public int read(ByteBuffer dst) throws IOException {
43 | return channel.read(dst);
44 | }
45 |
46 | @Override
47 | public int write(ByteBuffer src) throws IOException {
48 | return channel.write(src);
49 | }
50 |
51 | @Override
52 | public long position() throws IOException {
53 | return channel.position();
54 | }
55 |
56 | @Override
57 | @CanIgnoreReturnValue
58 | public SeekableByteChannel position(long newPosition) throws IOException {
59 | channel.position(newPosition);
60 | return this;
61 | }
62 |
63 | @Override
64 | public long size() throws IOException {
65 | return channel.size();
66 | }
67 |
68 | @Override
69 | @CanIgnoreReturnValue
70 | public SeekableByteChannel truncate(long size) throws IOException {
71 | channel.truncate(size);
72 | return this;
73 | }
74 |
75 | @Override
76 | public boolean isOpen() {
77 | return channel.isOpen();
78 | }
79 |
80 | @Override
81 | public void close() throws IOException {
82 | channel.close();
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/Feature.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 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 java.nio.channels.AsynchronousFileChannel;
20 | import java.nio.channels.FileChannel;
21 | import java.nio.channels.SeekableByteChannel;
22 | import java.nio.file.DirectoryStream;
23 | import java.nio.file.Files;
24 | import java.nio.file.OpenOption;
25 | import java.nio.file.Path;
26 | import java.nio.file.SecureDirectoryStream;
27 | import java.nio.file.attribute.FileAttribute;
28 | import java.util.Set;
29 | import java.util.concurrent.ExecutorService;
30 |
31 | /**
32 | * Optional file system features that may be supported or unsupported by a Jimfs file system
33 | * instance.
34 | *
35 | * @author Colin Decker
36 | */
37 | public enum Feature {
38 |
39 | /**
40 | * Feature controlling support for hard links to regular files.
41 | *
42 | * Affected method:
43 | *
44 | *
45 | * - {@link Files#createLink(Path, Path)}
46 | *
47 | *
48 | * If this feature is not enabled, this method will throw {@link
49 | * UnsupportedOperationException}.
50 | */
51 | LINKS,
52 |
53 | /**
54 | * Feature controlling support for symbolic links.
55 | *
56 | *
Affected methods:
57 | *
58 | *
59 | * - {@link Files#createSymbolicLink(Path, Path, FileAttribute...)}
60 | *
- {@link Files#readSymbolicLink(Path)}
61 | *
62 | *
63 | * If this feature is not enabled, these methods will throw {@link
64 | * UnsupportedOperationException}.
65 | */
66 | SYMBOLIC_LINKS,
67 |
68 | /**
69 | * Feature controlling support for {@link SecureDirectoryStream}.
70 | *
71 | *
Affected methods:
72 | *
73 | *
74 | * - {@link Files#newDirectoryStream(Path)}
75 | *
- {@link Files#newDirectoryStream(Path, DirectoryStream.Filter)}
76 | *
- {@link Files#newDirectoryStream(Path, String)}
77 | *
78 | *
79 | * If this feature is enabled, the {@link DirectoryStream} instances returned by these methods
80 | * will also implement {@link SecureDirectoryStream}.
81 | */
82 | SECURE_DIRECTORY_STREAM,
83 |
84 | /**
85 | * Feature controlling support for {@link FileChannel}.
86 | *
87 | *
Affected methods:
88 | *
89 | *
90 | * - {@link Files#newByteChannel(Path, OpenOption...)}
91 | *
- {@link Files#newByteChannel(Path, Set, FileAttribute...)}
92 | *
- {@link FileChannel#open(Path, OpenOption...)}
93 | *
- {@link FileChannel#open(Path, Set, FileAttribute...)}
94 | *
- {@link AsynchronousFileChannel#open(Path, OpenOption...)}
95 | *
- {@link AsynchronousFileChannel#open(Path, Set, ExecutorService, FileAttribute...)}
96 | *
97 | *
98 | * If this feature is not enabled, the {@link SeekableByteChannel} instances returned by the
99 | * {@code Files} methods will not be {@code FileChannel} instances and the {@code
100 | * FileChannel.open} and {@code AsynchronousFileChannel.open} methods will throw {@link
101 | * UnsupportedOperationException}.
102 | */
103 | // TODO(cgdecker): Should support for AsynchronousFileChannel be a separate feature?
104 | FILE_CHANNEL
105 | }
106 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/FileFactory.java:
--------------------------------------------------------------------------------
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.annotations.VisibleForTesting;
22 | import com.google.common.base.Supplier;
23 | import java.io.IOException;
24 | import java.util.concurrent.atomic.AtomicInteger;
25 |
26 | /**
27 | * Factory for creating new files and copying files. One piece of the file store implementation.
28 | *
29 | * @author Colin Decker
30 | */
31 | final class FileFactory {
32 |
33 | private final AtomicInteger idGenerator = new AtomicInteger();
34 |
35 | private final HeapDisk disk;
36 | private final FileTimeSource fileTimeSource;
37 |
38 | /**
39 | * Creates a new file factory using the given disk for regular files and the given time source.
40 | */
41 | public FileFactory(HeapDisk disk, FileTimeSource fileTimeSource) {
42 | this.disk = checkNotNull(disk);
43 | this.fileTimeSource = checkNotNull(fileTimeSource);
44 | }
45 |
46 | private int nextFileId() {
47 | return idGenerator.getAndIncrement();
48 | }
49 |
50 | /** Creates a new directory. */
51 | public Directory createDirectory() {
52 | return Directory.create(nextFileId(), fileTimeSource.now());
53 | }
54 |
55 | /** Creates a new root directory with the given name. */
56 | public Directory createRootDirectory(Name name) {
57 | return Directory.createRoot(nextFileId(), fileTimeSource.now(), name);
58 | }
59 |
60 | /** Creates a new regular file. */
61 | @VisibleForTesting
62 | RegularFile createRegularFile() {
63 | return RegularFile.create(nextFileId(), fileTimeSource.now(), disk);
64 | }
65 |
66 | /** Creates a new symbolic link referencing the given target path. */
67 | @VisibleForTesting
68 | SymbolicLink createSymbolicLink(JimfsPath target) {
69 | return SymbolicLink.create(nextFileId(), fileTimeSource.now(), target);
70 | }
71 |
72 | /** Creates and returns a copy of the given file. */
73 | public File copyWithoutContent(File file) throws IOException {
74 | return file.copyWithoutContent(nextFileId(), fileTimeSource.now());
75 | }
76 |
77 | // suppliers to act as file creation callbacks
78 |
79 | private final Supplier directorySupplier = new DirectorySupplier();
80 |
81 | private final Supplier regularFileSupplier = new RegularFileSupplier();
82 |
83 | /** Returns a supplier that creates directories. */
84 | public Supplier directoryCreator() {
85 | return directorySupplier;
86 | }
87 |
88 | /** Returns a supplier that creates regular files. */
89 | public Supplier regularFileCreator() {
90 | return regularFileSupplier;
91 | }
92 |
93 | /** Returns a supplier that creates a symbolic links to the given path. */
94 | public Supplier symbolicLinkCreator(JimfsPath target) {
95 | return new SymbolicLinkSupplier(target);
96 | }
97 |
98 | private final class DirectorySupplier implements Supplier {
99 | @Override
100 | public Directory get() {
101 | return createDirectory();
102 | }
103 | }
104 |
105 | private final class RegularFileSupplier implements Supplier {
106 | @Override
107 | public RegularFile get() {
108 | return createRegularFile();
109 | }
110 | }
111 |
112 | private final class SymbolicLinkSupplier implements Supplier {
113 |
114 | private final JimfsPath target;
115 |
116 | protected SymbolicLinkSupplier(JimfsPath target) {
117 | this.target = checkNotNull(target);
118 | }
119 |
120 | @Override
121 | public SymbolicLink get() {
122 | return createSymbolicLink(target);
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/FileLookup.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 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 java.io.IOException;
20 |
21 | /**
22 | * Callback for looking up a file.
23 | *
24 | * @author Colin Decker
25 | */
26 | public interface FileLookup {
27 |
28 | /**
29 | * Looks up the file.
30 | *
31 | * @throws IOException if the lookup fails for any reason, such as the file not existing
32 | */
33 | File lookup() throws IOException;
34 | }
35 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/FileSystemState.java:
--------------------------------------------------------------------------------
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 | import static com.google.common.base.Throwables.throwIfInstanceOf;
21 | import static com.google.common.base.Throwables.throwIfUnchecked;
22 |
23 | import com.google.common.collect.Sets;
24 | import com.google.errorprone.annotations.CanIgnoreReturnValue;
25 | import java.io.Closeable;
26 | import java.io.IOException;
27 | import java.nio.file.ClosedFileSystemException;
28 | import java.nio.file.attribute.FileTime;
29 | import java.util.Set;
30 | import java.util.concurrent.atomic.AtomicBoolean;
31 | import java.util.concurrent.atomic.AtomicInteger;
32 |
33 | /**
34 | * Object that manages the open/closed state of a file system, ensuring that all open resources are
35 | * closed when the file system is closed and that file system methods throw an exception when the
36 | * file system has been closed.
37 | *
38 | * @author Colin Decker
39 | */
40 | final class FileSystemState implements Closeable {
41 |
42 | private final Set resources = Sets.newConcurrentHashSet();
43 | private final FileTimeSource fileTimeSource;
44 | private final Runnable onClose;
45 |
46 | private final AtomicBoolean open = new AtomicBoolean(true);
47 |
48 | /** Count of resources currently in the process of being registered. */
49 | private final AtomicInteger registering = new AtomicInteger();
50 |
51 | FileSystemState(FileTimeSource fileTimeSource, Runnable onClose) {
52 | this.fileTimeSource = checkNotNull(fileTimeSource);
53 | this.onClose = checkNotNull(onClose);
54 | }
55 |
56 | /** Returns whether or not the file system is open. */
57 | public boolean isOpen() {
58 | return open.get();
59 | }
60 |
61 | /**
62 | * Checks that the file system is open, throwing {@link ClosedFileSystemException} if it is not.
63 | */
64 | public void checkOpen() {
65 | if (!open.get()) {
66 | throw new ClosedFileSystemException();
67 | }
68 | }
69 |
70 | /**
71 | * Registers the given resource to be closed when the file system is closed. Should be called when
72 | * the resource is opened.
73 | */
74 | @CanIgnoreReturnValue
75 | public C register(C resource) {
76 | // Initial open check to avoid incrementing registering if we already know it's closed.
77 | // This is to prevent any possibility of a weird pathalogical situation where the do/while
78 | // loop in close() keeps looping as register() is called repeatedly from multiple threads.
79 | checkOpen();
80 |
81 | registering.incrementAndGet();
82 | try {
83 | // Need to check again after marking registration in progress to avoid a potential race.
84 | // (close() could have run completely between the first checkOpen() and
85 | // registering.incrementAndGet().)
86 | checkOpen();
87 | resources.add(resource);
88 | return resource;
89 | } finally {
90 | registering.decrementAndGet();
91 | }
92 | }
93 |
94 | /** Unregisters the given resource. Should be called when the resource is closed. */
95 | public void unregister(Closeable resource) {
96 | resources.remove(resource);
97 | }
98 |
99 | /** Returns the current {@link FileTime}. */
100 | public FileTime now() {
101 | return fileTimeSource.now();
102 | }
103 |
104 | /**
105 | * Closes the file system, runs the {@code onClose} callback and closes all registered resources.
106 | */
107 | @Override
108 | public void close() throws IOException {
109 | if (open.compareAndSet(true, false)) {
110 | onClose.run();
111 |
112 | Throwable thrown = null;
113 | do {
114 | for (Closeable resource : resources) {
115 | try {
116 | resource.close();
117 | } catch (Throwable e) {
118 | if (thrown == null) {
119 | thrown = e;
120 | } else {
121 | thrown.addSuppressed(e);
122 | }
123 | } finally {
124 | // ensure the resource is removed even if it doesn't remove itself when closed
125 | resources.remove(resource);
126 | }
127 | }
128 |
129 | // It's possible for a thread registering a resource to register that resource after open
130 | // has been set to false and even after we've looped through and closed all the resources.
131 | // Since registering must be incremented *before* checking the state of open, however,
132 | // when we reach this point in that situation either the register call is still in progress
133 | // (registering > 0) or the new resource has been successfully added (resources not empty).
134 | // In either case, we just need to repeat the loop until there are no more register calls
135 | // in progress (no new calls can start and no resources left to close.
136 | } while (registering.get() > 0 || !resources.isEmpty());
137 | if (thrown != null) {
138 | throwIfInstanceOf(thrown, IOException.class);
139 | throwIfUnchecked(thrown);
140 | }
141 | }
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/FileTimeSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 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 java.nio.file.attribute.FileTime;
20 |
21 | /**
22 | * A source of the current time as a {@link FileTime}, to enable fake time sources for testing.
23 | *
24 | * @since 1.3
25 | */
26 | public interface FileTimeSource {
27 | /** Returns the current time according to this source as a {@link FileTime}. */
28 | FileTime now();
29 | }
30 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/GuardedBy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 The Error Prone Authors.
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 | package com.google.common.jimfs;
17 |
18 | import static java.lang.annotation.ElementType.FIELD;
19 | import static java.lang.annotation.ElementType.METHOD;
20 | import static java.lang.annotation.RetentionPolicy.CLASS;
21 |
22 | import java.lang.annotation.Retention;
23 | import java.lang.annotation.Target;
24 |
25 | // TODO(cpovirk): Delete this in favor of the copy in Error Prone once that has a module name.
26 | /** Indicates that the annotated element should be used only while holding the specified lock. */
27 | @Target({FIELD, METHOD})
28 | @Retention(CLASS)
29 | @interface GuardedBy {
30 | /**
31 | * The lock that should be held, specified in the format given in Java
33 | * Concurrency in Practice.
34 | */
35 | String value();
36 | }
37 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/Handler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 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.checkArgument;
20 |
21 | import java.io.IOException;
22 | import java.net.InetAddress;
23 | import java.net.URL;
24 | import java.net.URLConnection;
25 | import java.net.URLStreamHandler;
26 | import org.jspecify.annotations.Nullable;
27 |
28 | /**
29 | * {@link URLStreamHandler} implementation for jimfs. Named {@code Handler} so that the class can be
30 | * found by Java as described in the documentation for {@link URL#URL(String, String, int, String)
31 | * URL}.
32 | *
33 | * This class is only public because it is necessary for Java to find it. It is not intended to
34 | * be used directly.
35 | *
36 | * @author Colin Decker
37 | * @since 1.1
38 | */
39 | public final class Handler extends URLStreamHandler {
40 |
41 | private static final String JAVA_PROTOCOL_HANDLER_PACKAGES = "java.protocol.handler.pkgs";
42 |
43 | /**
44 | * Registers this handler by adding the package {@code com.google.common} to the system property
45 | * {@code "java.protocol.handler.pkgs"}. Java will then look for this class in the {@code jimfs}
46 | * (the name of the protocol) package of {@code com.google.common}.
47 | *
48 | * @throws SecurityException if the system property that needs to be set to register this handler
49 | * can't be read or written.
50 | */
51 | static void register() {
52 | register(Handler.class);
53 | }
54 |
55 | /** Generic method that would allow registration of any properly placed {@code Handler} class. */
56 | static void register(Class extends URLStreamHandler> handlerClass) {
57 | checkArgument("Handler".equals(handlerClass.getSimpleName()));
58 |
59 | String pkg = handlerClass.getPackage().getName();
60 | int lastDot = pkg.lastIndexOf('.');
61 | checkArgument(lastDot > 0, "package for Handler (%s) must have a parent package", pkg);
62 |
63 | String parentPackage = pkg.substring(0, lastDot);
64 |
65 | String packages = System.getProperty(JAVA_PROTOCOL_HANDLER_PACKAGES);
66 | if (packages == null) {
67 | packages = parentPackage;
68 | } else {
69 | packages += "|" + parentPackage;
70 | }
71 | System.setProperty(JAVA_PROTOCOL_HANDLER_PACKAGES, packages);
72 | }
73 |
74 | /** @deprecated Not intended to be called directly; this class is only for use by Java itself. */
75 | @Deprecated
76 | public Handler() {} // a public, no-arg constructor is required
77 |
78 | @Override
79 | protected URLConnection openConnection(URL url) throws IOException {
80 | return new PathURLConnection(url);
81 | }
82 |
83 | @Override
84 | @SuppressWarnings("UnsynchronizedOverridesSynchronized") // no need to synchronize to return null
85 | protected @Nullable InetAddress getHostAddress(URL url) {
86 | // jimfs uses the URI host to specify the name of the file system being used.
87 | // In the default implementation of getHostAddress(URL), a non-null host would cause an attempt
88 | // to look up the IP address, causing a slowdown on calling equals/hashCode methods on the URL
89 | // object. By returning null, we speed up equality checks on URL's (since there isn't an IP to
90 | // connect to).
91 | return null;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/InternalCharMatcher.java:
--------------------------------------------------------------------------------
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 java.util.Arrays;
20 |
21 | /**
22 | * Simple replacement for the real CharMatcher until it's out of @Beta.
23 | *
24 | * @author Colin Decker
25 | */
26 | final class InternalCharMatcher {
27 |
28 | public static InternalCharMatcher anyOf(String chars) {
29 | return new InternalCharMatcher(chars);
30 | }
31 |
32 | private final char[] chars;
33 |
34 | private InternalCharMatcher(String chars) {
35 | this.chars = chars.toCharArray();
36 | Arrays.sort(this.chars);
37 | }
38 |
39 | public boolean matches(char c) {
40 | return Arrays.binarySearch(chars, c) >= 0;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/Java8Compatibility.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | */
14 |
15 | package com.google.common.jimfs;
16 |
17 | import java.nio.Buffer;
18 |
19 | /**
20 | * Wrappers around {@link Buffer} methods that are covariantly overridden in Java 9+. See
21 | * https://github.com/google/guava/issues/3990
22 | */
23 | final class Java8Compatibility {
24 | static void clear(Buffer b) {
25 | b.clear();
26 | }
27 |
28 | private Java8Compatibility() {}
29 | }
30 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/JimfsFileSystems.java:
--------------------------------------------------------------------------------
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 java.io.IOException;
20 | import java.lang.reflect.InvocationTargetException;
21 | import java.lang.reflect.Method;
22 | import java.net.URI;
23 | import java.util.HashMap;
24 | import java.util.Map;
25 |
26 | /**
27 | * Initializes and configures new file system instances.
28 | *
29 | * @author Colin Decker
30 | */
31 | final class JimfsFileSystems {
32 |
33 | private JimfsFileSystems() {}
34 |
35 | private static final Runnable DO_NOTHING =
36 | new Runnable() {
37 | @Override
38 | public void run() {}
39 | };
40 |
41 | /**
42 | * Returns a {@code Runnable} that will remove the file system with the given {@code URI} from the
43 | * system provider's cache when called.
44 | */
45 | private static Runnable removeFileSystemRunnable(URI uri) {
46 | if (Jimfs.systemProvider == null) {
47 | // TODO(cgdecker): Use Runnables.doNothing() when it's out of @Beta
48 | return DO_NOTHING;
49 | }
50 |
51 | // We have to invoke the SystemJimfsFileSystemProvider.removeFileSystemRunnable(URI)
52 | // method reflectively since the system-loaded instance of it may be a different class
53 | // than the one we'd get if we tried to cast it and call it like normal here.
54 | try {
55 | Method method =
56 | Jimfs.systemProvider.getClass().getDeclaredMethod("removeFileSystemRunnable", URI.class);
57 | return (Runnable) method.invoke(null, uri);
58 | } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
59 | throw new RuntimeException(
60 | "Unable to get Runnable for removing the FileSystem from the cache when it is closed", e);
61 | }
62 | }
63 |
64 | /**
65 | * Initialize and configure a new file system with the given provider and URI, using the given
66 | * configuration.
67 | */
68 | public static JimfsFileSystem newFileSystem(
69 | JimfsFileSystemProvider provider, URI uri, Configuration config) throws IOException {
70 | PathService pathService = new PathService(config);
71 | FileSystemState state =
72 | new FileSystemState(config.fileTimeSource, removeFileSystemRunnable(uri));
73 |
74 | JimfsFileStore fileStore = createFileStore(config, pathService, state);
75 | FileSystemView defaultView = createDefaultView(config, fileStore, pathService);
76 | WatchServiceConfiguration watchServiceConfig = config.watchServiceConfig;
77 |
78 | JimfsFileSystem fileSystem =
79 | new JimfsFileSystem(provider, uri, fileStore, pathService, defaultView, watchServiceConfig);
80 |
81 | pathService.setFileSystem(fileSystem);
82 | return fileSystem;
83 | }
84 |
85 | /** Creates the file store for the file system. */
86 | private static JimfsFileStore createFileStore(
87 | Configuration config, PathService pathService, FileSystemState state) {
88 | AttributeService attributeService = new AttributeService(config);
89 |
90 | HeapDisk disk = new HeapDisk(config);
91 | FileFactory fileFactory = new FileFactory(disk, config.fileTimeSource);
92 |
93 | Map roots = new HashMap<>();
94 |
95 | // create roots
96 | for (String root : config.roots) {
97 | JimfsPath path = pathService.parsePath(root);
98 | if (!path.isAbsolute() && path.getNameCount() == 0) {
99 | throw new IllegalArgumentException("Invalid root path: " + root);
100 | }
101 |
102 | Name rootName = path.root();
103 |
104 | Directory rootDir = fileFactory.createRootDirectory(rootName);
105 | attributeService.setInitialAttributes(rootDir);
106 | roots.put(rootName, rootDir);
107 | }
108 |
109 | return new JimfsFileStore(
110 | new FileTree(roots), fileFactory, disk, attributeService, config.supportedFeatures, state);
111 | }
112 |
113 | /** Creates the default view of the file system using the given working directory. */
114 | private static FileSystemView createDefaultView(
115 | Configuration config, JimfsFileStore fileStore, PathService pathService) throws IOException {
116 | JimfsPath workingDirPath = pathService.parsePath(config.workingDirectory);
117 |
118 | Directory dir = fileStore.getRoot(workingDirPath.root());
119 | if (dir == null) {
120 | throw new IllegalArgumentException("Invalid working dir path: " + workingDirPath);
121 | }
122 |
123 | for (Name name : workingDirPath.names()) {
124 | Directory newDir = fileStore.directoryCreator().get();
125 | fileStore.setInitialAttributes(newDir);
126 | dir.link(name, newDir);
127 |
128 | dir = newDir;
129 | }
130 |
131 | return new FileSystemView(fileStore, dir, workingDirPath);
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/JimfsInputStream.java:
--------------------------------------------------------------------------------
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 | import static com.google.common.base.Preconditions.checkPositionIndexes;
21 |
22 | import com.google.common.annotations.VisibleForTesting;
23 | import com.google.common.primitives.Ints;
24 | import java.io.IOException;
25 | import java.io.InputStream;
26 |
27 | /**
28 | * {@link InputStream} for reading from a file's {@link RegularFile}.
29 | *
30 | * @author Colin Decker
31 | */
32 | final class JimfsInputStream extends InputStream {
33 |
34 | @GuardedBy("this")
35 | @VisibleForTesting
36 | RegularFile file;
37 |
38 | @GuardedBy("this")
39 | private long pos;
40 |
41 | @GuardedBy("this")
42 | private boolean finished;
43 |
44 | private final FileSystemState fileSystemState;
45 |
46 | public JimfsInputStream(RegularFile file, FileSystemState fileSystemState) {
47 | this.file = checkNotNull(file);
48 | this.fileSystemState = fileSystemState;
49 | fileSystemState.register(this);
50 | }
51 |
52 | @Override
53 | public synchronized int read() throws IOException {
54 | checkNotClosed();
55 | if (finished) {
56 | return -1;
57 | }
58 |
59 | file.readLock().lock();
60 | try {
61 |
62 | int b = file.read(pos++); // it's ok for pos to go beyond size()
63 | if (b == -1) {
64 | finished = true;
65 | } else {
66 | file.setLastAccessTime(fileSystemState.now());
67 | }
68 | return b;
69 | } finally {
70 | file.readLock().unlock();
71 | }
72 | }
73 |
74 | @Override
75 | public int read(byte[] b) throws IOException {
76 | return readInternal(b, 0, b.length);
77 | }
78 |
79 | @Override
80 | public int read(byte[] b, int off, int len) throws IOException {
81 | checkPositionIndexes(off, off + len, b.length);
82 | return readInternal(b, off, len);
83 | }
84 |
85 | private synchronized int readInternal(byte[] b, int off, int len) throws IOException {
86 | checkNotClosed();
87 | if (finished) {
88 | return -1;
89 | }
90 |
91 | file.readLock().lock();
92 | try {
93 | int read = file.read(pos, b, off, len);
94 | if (read == -1) {
95 | finished = true;
96 | } else {
97 | pos += read;
98 | }
99 |
100 | file.setLastAccessTime(fileSystemState.now());
101 | return read;
102 | } finally {
103 | file.readLock().unlock();
104 | }
105 | }
106 |
107 | @Override
108 | public long skip(long n) throws IOException {
109 | if (n <= 0) {
110 | return 0;
111 | }
112 |
113 | synchronized (this) {
114 | checkNotClosed();
115 | if (finished) {
116 | return 0;
117 | }
118 |
119 | // available() must be an int, so the min must be also
120 | int skip = (int) Math.min(Math.max(file.size() - pos, 0), n);
121 | pos += skip;
122 | return skip;
123 | }
124 | }
125 |
126 | @Override
127 | public synchronized int available() throws IOException {
128 | checkNotClosed();
129 | if (finished) {
130 | return 0;
131 | }
132 | long available = Math.max(file.size() - pos, 0);
133 | return Ints.saturatedCast(available);
134 | }
135 |
136 | @GuardedBy("this")
137 | private void checkNotClosed() throws IOException {
138 | if (file == null) {
139 | throw new IOException("stream is closed");
140 | }
141 | }
142 |
143 | @Override
144 | public synchronized void close() throws IOException {
145 | if (isOpen()) {
146 | fileSystemState.unregister(this);
147 | file.closed();
148 |
149 | // file is set to null here and only here
150 | file = null;
151 | }
152 | }
153 |
154 | @GuardedBy("this")
155 | private boolean isOpen() {
156 | return file != null;
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/JimfsOutputStream.java:
--------------------------------------------------------------------------------
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 | import static com.google.common.base.Preconditions.checkPositionIndexes;
21 |
22 | import com.google.common.annotations.VisibleForTesting;
23 | import java.io.IOException;
24 | import java.io.OutputStream;
25 |
26 | /**
27 | * {@link OutputStream} for writing to a {@link RegularFile}.
28 | *
29 | * @author Colin Decker
30 | */
31 | final class JimfsOutputStream extends OutputStream {
32 |
33 | @GuardedBy("this")
34 | @VisibleForTesting
35 | RegularFile file;
36 |
37 | @GuardedBy("this")
38 | private long pos;
39 |
40 | private final boolean append;
41 | private final FileSystemState fileSystemState;
42 |
43 | JimfsOutputStream(RegularFile file, boolean append, FileSystemState fileSystemState) {
44 | this.file = checkNotNull(file);
45 | this.append = append;
46 | this.fileSystemState = fileSystemState;
47 | fileSystemState.register(this);
48 | }
49 |
50 | @Override
51 | public synchronized void write(int b) throws IOException {
52 | checkNotClosed();
53 |
54 | file.writeLock().lock();
55 | try {
56 | if (append) {
57 | pos = file.sizeWithoutLocking();
58 | }
59 | file.write(pos++, (byte) b);
60 |
61 | file.setLastModifiedTime(fileSystemState.now());
62 | } finally {
63 | file.writeLock().unlock();
64 | }
65 | }
66 |
67 | @Override
68 | public void write(byte[] b) throws IOException {
69 | writeInternal(b, 0, b.length);
70 | }
71 |
72 | @Override
73 | public void write(byte[] b, int off, int len) throws IOException {
74 | checkPositionIndexes(off, off + len, b.length);
75 | writeInternal(b, off, len);
76 | }
77 |
78 | private synchronized void writeInternal(byte[] b, int off, int len) throws IOException {
79 | checkNotClosed();
80 |
81 | file.writeLock().lock();
82 | try {
83 | if (append) {
84 | pos = file.sizeWithoutLocking();
85 | }
86 | pos += file.write(pos, b, off, len);
87 |
88 | file.setLastModifiedTime(fileSystemState.now());
89 | } finally {
90 | file.writeLock().unlock();
91 | }
92 | }
93 |
94 | @GuardedBy("this")
95 | private void checkNotClosed() throws IOException {
96 | if (file == null) {
97 | throw new IOException("stream is closed");
98 | }
99 | }
100 |
101 | @Override
102 | public synchronized void close() throws IOException {
103 | if (isOpen()) {
104 | fileSystemState.unregister(this);
105 | file.closed();
106 |
107 | // file is set to null here and only here
108 | file = null;
109 | }
110 | }
111 |
112 | @GuardedBy("this")
113 | private boolean isOpen() {
114 | return file != null;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/Name.java:
--------------------------------------------------------------------------------
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.annotations.VisibleForTesting;
22 | import java.util.Comparator;
23 | import org.jspecify.annotations.Nullable;
24 |
25 | /**
26 | * Immutable representation of a file name. Used both for the name components of paths and as the
27 | * keys for directory entries.
28 | *
29 | * A name has both a display string (used in the {@code toString()} form of a {@code Path} as
30 | * well as for {@code Path} equality and sort ordering) and a canonical string, which is used for
31 | * determining equality of the name during file lookup.
32 | *
33 | *
Note: all factory methods return a constant name instance when given the original string "."
34 | * or "..", ensuring that those names can be accessed statically elsewhere in the code while still
35 | * being equal to any names created for those values, regardless of normalization settings.
36 | *
37 | * @author Colin Decker
38 | */
39 | final class Name {
40 |
41 | /** The empty name. */
42 | static final Name EMPTY = new Name("", "");
43 |
44 | /** The name to use for a link from a directory to itself. */
45 | public static final Name SELF = new Name(".", ".");
46 |
47 | /** The name to use for a link from a directory to its parent directory. */
48 | public static final Name PARENT = new Name("..", "..");
49 |
50 | /** Creates a new name with no normalization done on the given string. */
51 | @VisibleForTesting
52 | static Name simple(String name) {
53 | switch (name) {
54 | case ".":
55 | return SELF;
56 | case "..":
57 | return PARENT;
58 | default:
59 | return new Name(name, name);
60 | }
61 | }
62 |
63 | /**
64 | * Creates a name with the given display representation and the given canonical representation.
65 | */
66 | public static Name create(String display, String canonical) {
67 | return new Name(display, canonical);
68 | }
69 |
70 | private final String display;
71 | private final String canonical;
72 |
73 | private Name(String display, String canonical) {
74 | this.display = checkNotNull(display);
75 | this.canonical = checkNotNull(canonical);
76 | }
77 |
78 | @Override
79 | public boolean equals(@Nullable Object obj) {
80 | if (obj instanceof Name) {
81 | Name other = (Name) obj;
82 | return canonical.equals(other.canonical);
83 | }
84 | return false;
85 | }
86 |
87 | @Override
88 | public int hashCode() {
89 | return Util.smearHash(canonical.hashCode());
90 | }
91 |
92 | @Override
93 | public String toString() {
94 | return display;
95 | }
96 |
97 | /** Returns a comparator that orders names by their display representation. */
98 | static Comparator displayComparator() {
99 | return DISPLAY_COMPARATOR;
100 | }
101 |
102 | /** Returns a comparator that orders names by their canonical representation. */
103 | static Comparator canonicalComparator() {
104 | return CANONICAL_COMPARATOR;
105 | }
106 |
107 | private static final Comparator DISPLAY_COMPARATOR =
108 | Comparator.comparing((Name n) -> n.display);
109 |
110 | private static final Comparator CANONICAL_COMPARATOR =
111 | Comparator.comparing((Name n) -> n.canonical);
112 | }
113 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/Options.java:
--------------------------------------------------------------------------------
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 | import static java.nio.file.StandardCopyOption.ATOMIC_MOVE;
21 | import static java.nio.file.StandardOpenOption.APPEND;
22 | import static java.nio.file.StandardOpenOption.CREATE;
23 | import static java.nio.file.StandardOpenOption.READ;
24 | import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
25 | import static java.nio.file.StandardOpenOption.WRITE;
26 |
27 | import com.google.common.collect.ImmutableSet;
28 | import com.google.common.collect.Lists;
29 | import java.nio.file.CopyOption;
30 | import java.nio.file.LinkOption;
31 | import java.nio.file.OpenOption;
32 | import java.util.Arrays;
33 | import java.util.Collection;
34 | import java.util.Set;
35 |
36 | /**
37 | * Utility methods for normalizing user-provided options arrays and sets to canonical immutable sets
38 | * of options.
39 | *
40 | * @author Colin Decker
41 | */
42 | final class Options {
43 |
44 | private Options() {}
45 |
46 | /** Immutable set containing LinkOption.NOFOLLOW_LINKS. */
47 | public static final ImmutableSet NOFOLLOW_LINKS =
48 | ImmutableSet.of(LinkOption.NOFOLLOW_LINKS);
49 |
50 | /** Immutable empty LinkOption set. */
51 | public static final ImmutableSet FOLLOW_LINKS = ImmutableSet.of();
52 |
53 | private static final ImmutableSet DEFAULT_READ = ImmutableSet.of(READ);
54 |
55 | private static final ImmutableSet DEFAULT_READ_NOFOLLOW_LINKS =
56 | ImmutableSet.of(READ, LinkOption.NOFOLLOW_LINKS);
57 |
58 | private static final ImmutableSet DEFAULT_WRITE =
59 | ImmutableSet.of(WRITE, CREATE, TRUNCATE_EXISTING);
60 |
61 | /** Returns an immutable set of link options. */
62 | public static ImmutableSet getLinkOptions(LinkOption... options) {
63 | return options.length == 0 ? FOLLOW_LINKS : NOFOLLOW_LINKS;
64 | }
65 |
66 | /** Returns an immutable set of open options for opening a new file channel. */
67 | public static ImmutableSet getOptionsForChannel(Set extends OpenOption> options) {
68 | if (options.isEmpty()) {
69 | return DEFAULT_READ;
70 | }
71 |
72 | boolean append = options.contains(APPEND);
73 | boolean write = append || options.contains(WRITE);
74 | boolean read = !write || options.contains(READ);
75 |
76 | if (read) {
77 | if (append) {
78 | throw new UnsupportedOperationException("'READ' + 'APPEND' not allowed");
79 | }
80 |
81 | if (!write) {
82 | // ignore all write related options
83 | return options.contains(LinkOption.NOFOLLOW_LINKS)
84 | ? DEFAULT_READ_NOFOLLOW_LINKS
85 | : DEFAULT_READ;
86 | }
87 | }
88 |
89 | // options contains write or append and may also contain read
90 | // it does not contain both read and append
91 | return addWrite(options);
92 | }
93 |
94 | /** Returns an immutable set of open options for opening a new input stream. */
95 | @SuppressWarnings("unchecked") // safe covariant cast
96 | public static ImmutableSet getOptionsForInputStream(OpenOption... options) {
97 | boolean nofollowLinks = false;
98 | for (OpenOption option : options) {
99 | if (checkNotNull(option) != READ) {
100 | if (option == LinkOption.NOFOLLOW_LINKS) {
101 | nofollowLinks = true;
102 | } else {
103 | throw new UnsupportedOperationException("'" + option + "' not allowed");
104 | }
105 | }
106 | }
107 |
108 | // just return the link options for finding the file, nothing else is needed
109 | return (ImmutableSet)
110 | (ImmutableSet>) (nofollowLinks ? NOFOLLOW_LINKS : FOLLOW_LINKS);
111 | }
112 |
113 | /** Returns an immutable set of open options for opening a new output stream. */
114 | public static ImmutableSet getOptionsForOutputStream(OpenOption... options) {
115 | if (options.length == 0) {
116 | return DEFAULT_WRITE;
117 | }
118 |
119 | ImmutableSet result = addWrite(Arrays.asList(options));
120 | if (result.contains(READ)) {
121 | throw new UnsupportedOperationException("'READ' not allowed");
122 | }
123 | return result;
124 | }
125 |
126 | /**
127 | * Returns an {@link ImmutableSet} copy of the given {@code options}, adding {@link
128 | * StandardOpenOption#WRITE} if it isn't already present.
129 | */
130 | private static ImmutableSet addWrite(Collection extends OpenOption> options) {
131 | return options.contains(WRITE)
132 | ? ImmutableSet.copyOf(options)
133 | : ImmutableSet.builder().add(WRITE).addAll(options).build();
134 | }
135 |
136 | /** Returns an immutable set of the given options for a move. */
137 | public static ImmutableSet getMoveOptions(CopyOption... options) {
138 | return ImmutableSet.copyOf(Lists.asList(LinkOption.NOFOLLOW_LINKS, options));
139 | }
140 |
141 | /** Returns an immutable set of the given options for a copy. */
142 | public static ImmutableSet getCopyOptions(CopyOption... options) {
143 | ImmutableSet result = ImmutableSet.copyOf(options);
144 | if (result.contains(ATOMIC_MOVE)) {
145 | throw new UnsupportedOperationException("'ATOMIC_MOVE' not allowed");
146 | }
147 | return result;
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/OwnerAttributeProvider.java:
--------------------------------------------------------------------------------
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 | import static com.google.common.jimfs.UserLookupService.createUserPrincipal;
21 |
22 | import com.google.common.collect.ImmutableMap;
23 | import com.google.common.collect.ImmutableSet;
24 | import java.io.IOException;
25 | import java.nio.file.attribute.FileAttributeView;
26 | import java.nio.file.attribute.FileOwnerAttributeView;
27 | import java.nio.file.attribute.UserPrincipal;
28 | import java.util.Map;
29 | import org.jspecify.annotations.Nullable;
30 |
31 | /**
32 | * Attribute provider that provides the {@link FileOwnerAttributeView} ("owner").
33 | *
34 | * @author Colin Decker
35 | */
36 | final class OwnerAttributeProvider extends AttributeProvider {
37 |
38 | private static final ImmutableSet ATTRIBUTES = ImmutableSet.of("owner");
39 |
40 | private static final UserPrincipal DEFAULT_OWNER = createUserPrincipal("user");
41 |
42 | @Override
43 | public String name() {
44 | return "owner";
45 | }
46 |
47 | @Override
48 | public ImmutableSet fixedAttributes() {
49 | return ATTRIBUTES;
50 | }
51 |
52 | @Override
53 | public ImmutableMap defaultValues(Map userProvidedDefaults) {
54 | Object userProvidedOwner = userProvidedDefaults.get("owner:owner");
55 |
56 | UserPrincipal owner = DEFAULT_OWNER;
57 | if (userProvidedOwner != null) {
58 | if (userProvidedOwner instanceof String) {
59 | owner = createUserPrincipal((String) userProvidedOwner);
60 | } else {
61 | throw invalidType("owner", "owner", userProvidedOwner, String.class, UserPrincipal.class);
62 | }
63 | }
64 |
65 | return ImmutableMap.of("owner:owner", owner);
66 | }
67 |
68 | @Override
69 | public @Nullable Object get(File file, String attribute) {
70 | if (attribute.equals("owner")) {
71 | return file.getAttribute("owner", "owner");
72 | }
73 | return null;
74 | }
75 |
76 | @Override
77 | public void set(File file, String view, String attribute, Object value, boolean create) {
78 | if (attribute.equals("owner")) {
79 | checkNotCreate(view, attribute, create);
80 | UserPrincipal user = checkType(view, attribute, value, UserPrincipal.class);
81 | // TODO(cgdecker): Do we really need to do this? Any reason not to allow any UserPrincipal?
82 | if (!(user instanceof UserLookupService.JimfsUserPrincipal)) {
83 | user = createUserPrincipal(user.getName());
84 | }
85 | file.setAttribute("owner", "owner", user);
86 | }
87 | }
88 |
89 | @Override
90 | public Class viewType() {
91 | return FileOwnerAttributeView.class;
92 | }
93 |
94 | @Override
95 | public FileOwnerAttributeView view(
96 | FileLookup lookup, ImmutableMap inheritedViews) {
97 | return new View(lookup);
98 | }
99 |
100 | /** Implementation of {@link FileOwnerAttributeView}. */
101 | private static final class View extends AbstractAttributeView implements FileOwnerAttributeView {
102 |
103 | public View(FileLookup lookup) {
104 | super(lookup);
105 | }
106 |
107 | @Override
108 | public String name() {
109 | return "owner";
110 | }
111 |
112 | @Override
113 | public UserPrincipal getOwner() throws IOException {
114 | return (UserPrincipal) lookupFile().getAttribute("owner", "owner");
115 | }
116 |
117 | @Override
118 | public void setOwner(UserPrincipal owner) throws IOException {
119 | lookupFile().setAttribute("owner", "owner", checkNotNull(owner));
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/PathMatchers.java:
--------------------------------------------------------------------------------
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.checkArgument;
20 | import static com.google.common.base.Preconditions.checkNotNull;
21 |
22 | import com.google.common.annotations.VisibleForTesting;
23 | import com.google.common.base.Ascii;
24 | import com.google.common.base.MoreObjects;
25 | import com.google.common.collect.ImmutableSet;
26 | import java.nio.file.FileSystem;
27 | import java.nio.file.Path;
28 | import java.nio.file.PathMatcher;
29 | import java.util.regex.Pattern;
30 |
31 | /**
32 | * {@link PathMatcher} factory for any file system.
33 | *
34 | * @author Colin Decker
35 | */
36 | final class PathMatchers {
37 |
38 | private PathMatchers() {}
39 |
40 | /**
41 | * Gets a {@link PathMatcher} for the given syntax and pattern as specified by {@link
42 | * FileSystem#getPathMatcher}. The {@code separators} string contains the path name element
43 | * separators (one character each) recognized by the file system. For a glob-syntax path matcher,
44 | * any of the given separators will be recognized as a separator in the pattern, and any of them
45 | * will be matched as a separator when checking a path.
46 | */
47 | // TODO(cgdecker): Should I be just canonicalizing separators rather than matching any separator?
48 | // Perhaps so, assuming Path always canonicalizes its separators
49 | public static PathMatcher getPathMatcher(
50 | String syntaxAndPattern, String separators, ImmutableSet normalizations) {
51 | int syntaxSeparator = syntaxAndPattern.indexOf(':');
52 | checkArgument(
53 | syntaxSeparator > 0, "Must be of the form 'syntax:pattern': %s", syntaxAndPattern);
54 |
55 | String syntax = Ascii.toLowerCase(syntaxAndPattern.substring(0, syntaxSeparator));
56 | String pattern = syntaxAndPattern.substring(syntaxSeparator + 1);
57 |
58 | switch (syntax) {
59 | case "glob":
60 | pattern = GlobToRegex.toRegex(pattern, separators);
61 | // fall through
62 | case "regex":
63 | return fromRegex(pattern, normalizations);
64 | default:
65 | throw new UnsupportedOperationException("Invalid syntax: " + syntaxAndPattern);
66 | }
67 | }
68 |
69 | private static PathMatcher fromRegex(String regex, Iterable normalizations) {
70 | return new RegexPathMatcher(PathNormalization.compilePattern(regex, normalizations));
71 | }
72 |
73 | /**
74 | * {@code PathMatcher} that matches the {@code toString()} form of a {@code Path} against a regex
75 | * {@code Pattern}.
76 | */
77 | @VisibleForTesting
78 | static final class RegexPathMatcher implements PathMatcher {
79 |
80 | private final Pattern pattern;
81 |
82 | private RegexPathMatcher(Pattern pattern) {
83 | this.pattern = checkNotNull(pattern);
84 | }
85 |
86 | @Override
87 | public boolean matches(Path path) {
88 | return pattern.matcher(path.toString()).matches();
89 | }
90 |
91 | @Override
92 | public String toString() {
93 | return MoreObjects.toStringHelper(this).addValue(pattern).toString();
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/PathNormalization.java:
--------------------------------------------------------------------------------
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 com.google.common.base.Ascii;
20 | import com.google.common.base.Function;
21 | import com.ibm.icu.lang.UCharacter;
22 | import java.text.Normalizer;
23 | import java.util.regex.Pattern;
24 |
25 | /**
26 | * Normalizations that can be applied to names in paths. Includes Unicode normalizations and
27 | * normalizations for case insensitive paths. These normalizations can be set in {@code
28 | * Configuration.Builder} when creating a Jimfs file system instance and are automatically applied
29 | * to paths in the file system.
30 | *
31 | * @author Colin Decker
32 | */
33 | public enum PathNormalization implements Function {
34 |
35 | /** No normalization. */
36 | NONE(0) {
37 | @Override
38 | public String apply(String string) {
39 | return string;
40 | }
41 | },
42 |
43 | /** Unicode composed normalization (form {@linkplain java.text.Normalizer.Form#NFC NFC}). */
44 | NFC(Pattern.CANON_EQ) {
45 | @Override
46 | public String apply(String string) {
47 | return Normalizer.normalize(string, Normalizer.Form.NFC);
48 | }
49 | },
50 |
51 | /** Unicode decomposed normalization (form {@linkplain java.text.Normalizer.Form#NFD NFD}). */
52 | NFD(Pattern.CANON_EQ) {
53 | @Override
54 | public String apply(String string) {
55 | return Normalizer.normalize(string, Normalizer.Form.NFD);
56 | }
57 | },
58 |
59 | /*
60 | * Some notes on case folding/case insensitivity of file systems:
61 | *
62 | * In general (I don't have any counterexamples) case-insensitive file systems handle
63 | * their case insensitivity in a locale-independent way. NTFS, for example, writes a
64 | * special case mapping file ($UpCase) to the file system when it's first initialized,
65 | * and this is not affected by the locale of either the user or the copy of Windows
66 | * being used. This means that it will NOT handle i/I-variants in filenames as you'd
67 | * expect for Turkic languages, even for a Turkish user who has installed a Turkish
68 | * copy of Windows.
69 | */
70 |
71 | /** Unicode case folding for case insensitive paths. Requires ICU4J on the classpath. */
72 | CASE_FOLD_UNICODE(Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) {
73 | @Override
74 | public String apply(String string) {
75 | try {
76 | return UCharacter.foldCase(string, true);
77 | } catch (NoClassDefFoundError e) {
78 | NoClassDefFoundError error =
79 | new NoClassDefFoundError(
80 | "PathNormalization.CASE_FOLD_UNICODE requires ICU4J. "
81 | + "Did you forget to include it on your classpath?");
82 | error.initCause(e);
83 | throw error;
84 | }
85 | }
86 | },
87 |
88 | /** ASCII case folding for simple case insensitive paths. */
89 | CASE_FOLD_ASCII(Pattern.CASE_INSENSITIVE) {
90 | @Override
91 | public String apply(String string) {
92 | return Ascii.toLowerCase(string);
93 | }
94 | };
95 |
96 | private final int patternFlags;
97 |
98 | private PathNormalization(int patternFlags) {
99 | this.patternFlags = patternFlags;
100 | }
101 |
102 | /** Applies this normalization to the given string, returning the normalized result. */
103 | @Override
104 | public abstract String apply(String string);
105 |
106 | /**
107 | * Returns the flags that should be used when creating a regex {@link Pattern} in order to
108 | * approximate this normalization.
109 | */
110 | public int patternFlags() {
111 | return patternFlags;
112 | }
113 |
114 | /**
115 | * Applies the given normalizations to the given string in order, returning the normalized result.
116 | */
117 | public static String normalize(String string, Iterable normalizations) {
118 | String result = string;
119 | for (PathNormalization normalization : normalizations) {
120 | result = normalization.apply(result);
121 | }
122 | return result;
123 | }
124 |
125 | /** Compiles a regex pattern using flags based on the given normalizations. */
126 | public static Pattern compilePattern(String regex, Iterable normalizations) {
127 | int flags = 0;
128 | for (PathNormalization normalization : normalizations) {
129 | flags |= normalization.patternFlags();
130 | }
131 | return Pattern.compile(regex, flags);
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/PathURLConnection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 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 | import static java.nio.charset.StandardCharsets.UTF_8;
21 |
22 | import com.google.common.base.Ascii;
23 | import com.google.common.base.MoreObjects;
24 | import com.google.common.collect.ImmutableListMultimap;
25 | import com.google.common.collect.ImmutableMap;
26 | import com.google.common.collect.Iterables;
27 | import java.io.ByteArrayInputStream;
28 | import java.io.IOException;
29 | import java.io.InputStream;
30 | import java.net.URI;
31 | import java.net.URISyntaxException;
32 | import java.net.URL;
33 | import java.net.URLConnection;
34 | import java.nio.file.DirectoryStream;
35 | import java.nio.file.Files;
36 | import java.nio.file.Path;
37 | import java.nio.file.Paths;
38 | import java.nio.file.attribute.FileTime;
39 | import java.text.DateFormat;
40 | import java.text.SimpleDateFormat;
41 | import java.util.Date;
42 | import java.util.List;
43 | import java.util.Locale;
44 | import java.util.Map;
45 | import java.util.TimeZone;
46 | import org.jspecify.annotations.Nullable;
47 |
48 | /**
49 | * {@code URLConnection} implementation.
50 | *
51 | * @author Colin Decker
52 | */
53 | final class PathURLConnection extends URLConnection {
54 |
55 | /*
56 | * This implementation should be able to work for any proper file system implementation... it
57 | * might be useful to release it and make it usable by other file systems.
58 | */
59 |
60 | private static final String HTTP_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss \'GMT\'";
61 | private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
62 |
63 | private InputStream stream;
64 | private ImmutableListMultimap headers = ImmutableListMultimap.of();
65 |
66 | PathURLConnection(URL url) {
67 | super(checkNotNull(url));
68 | }
69 |
70 | @Override
71 | public void connect() throws IOException {
72 | if (stream != null) {
73 | return;
74 | }
75 |
76 | Path path = Paths.get(toUri(url));
77 |
78 | long length;
79 | if (Files.isDirectory(path)) {
80 | // Match File URL behavior for directories by having the stream contain the filenames in
81 | // the directory separated by newlines.
82 | StringBuilder builder = new StringBuilder();
83 | try (DirectoryStream files = Files.newDirectoryStream(path)) {
84 | for (Path file : files) {
85 | builder.append(file.getFileName()).append('\n');
86 | }
87 | }
88 | byte[] bytes = builder.toString().getBytes(UTF_8);
89 | stream = new ByteArrayInputStream(bytes);
90 | length = bytes.length;
91 | } else {
92 | stream = Files.newInputStream(path);
93 | length = Files.size(path);
94 | }
95 |
96 | FileTime lastModified = Files.getLastModifiedTime(path);
97 | String contentType =
98 | MoreObjects.firstNonNull(Files.probeContentType(path), DEFAULT_CONTENT_TYPE);
99 |
100 | ImmutableListMultimap.Builder builder = ImmutableListMultimap.builder();
101 | builder.put("content-length", "" + length);
102 | builder.put("content-type", contentType);
103 | if (lastModified != null) {
104 | DateFormat format = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
105 | format.setTimeZone(TimeZone.getTimeZone("GMT"));
106 | builder.put("last-modified", format.format(new Date(lastModified.toMillis())));
107 | }
108 |
109 | headers = builder.build();
110 | }
111 |
112 | private static URI toUri(URL url) throws IOException {
113 | try {
114 | return url.toURI();
115 | } catch (URISyntaxException e) {
116 | throw new IOException("URL " + url + " cannot be converted to a URI", e);
117 | }
118 | }
119 |
120 | @Override
121 | public InputStream getInputStream() throws IOException {
122 | connect();
123 | return stream;
124 | }
125 |
126 | @SuppressWarnings("unchecked") // safe by specification of ListMultimap.asMap()
127 | @Override
128 | public Map> getHeaderFields() {
129 | try {
130 | connect();
131 | } catch (IOException e) {
132 | return ImmutableMap.of();
133 | }
134 | return (ImmutableMap>) (ImmutableMap) headers.asMap();
135 | }
136 |
137 | @Override
138 | public @Nullable String getHeaderField(String name) {
139 | try {
140 | connect();
141 | } catch (IOException e) {
142 | return null;
143 | }
144 |
145 | // no header should have more than one value
146 | return Iterables.getFirst(headers.get(Ascii.toLowerCase(name)), null);
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/StandardAttributeProviders.java:
--------------------------------------------------------------------------------
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 com.google.common.collect.ImmutableMap;
20 | import org.jspecify.annotations.Nullable;
21 |
22 | /**
23 | * Static registry of {@link AttributeProvider} implementations for the standard set of file
24 | * attribute views Jimfs supports.
25 | *
26 | * @author Colin Decker
27 | */
28 | final class StandardAttributeProviders {
29 |
30 | private StandardAttributeProviders() {}
31 |
32 | private static final ImmutableMap PROVIDERS =
33 | new ImmutableMap.Builder()
34 | .put("basic", new BasicAttributeProvider())
35 | .put("owner", new OwnerAttributeProvider())
36 | .put("posix", new PosixAttributeProvider())
37 | .put("dos", new DosAttributeProvider())
38 | .put("acl", new AclAttributeProvider())
39 | .put("user", new UserDefinedAttributeProvider())
40 | .build();
41 |
42 | /**
43 | * Returns the attribute provider for the given view, or {@code null} if the given view is not one
44 | * of the attribute views this supports.
45 | */
46 | public static @Nullable AttributeProvider get(String view) {
47 | AttributeProvider provider = PROVIDERS.get(view);
48 |
49 | if (provider == null && view.equals("unix")) {
50 | // create a new UnixAttributeProvider per file system, as it does some caching that should be
51 | // cleaned up when the file system is garbage collected
52 | return new UnixAttributeProvider();
53 | }
54 |
55 | return provider;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/SymbolicLink.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 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 java.nio.file.attribute.FileTime;
22 |
23 | /**
24 | * A symbolic link file, containing a {@linkplain JimfsPath path}.
25 | *
26 | * @author Colin Decker
27 | */
28 | final class SymbolicLink extends File {
29 |
30 | private final JimfsPath target;
31 |
32 | /** Creates a new symbolic link with the given ID and target. */
33 | public static SymbolicLink create(int id, FileTime creationTime, JimfsPath target) {
34 | return new SymbolicLink(id, creationTime, target);
35 | }
36 |
37 | private SymbolicLink(int id, FileTime creationTime, JimfsPath target) {
38 | super(id, creationTime);
39 | this.target = checkNotNull(target);
40 | }
41 |
42 | /** Returns the target path of this symbolic link. */
43 | JimfsPath target() {
44 | return target;
45 | }
46 |
47 | @Override
48 | File copyWithoutContent(int id, FileTime creationTime) {
49 | return SymbolicLink.create(id, creationTime, target);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/SystemFileTimeSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 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 java.nio.file.attribute.FileTime;
20 | import java.time.Instant;
21 |
22 | /** Implementation of of {@link FileTimeSource} that gets the current time from the system. */
23 | enum SystemFileTimeSource implements FileTimeSource {
24 | INSTANCE;
25 |
26 | @Override
27 | public FileTime now() {
28 | return FileTime.from(Instant.now());
29 | }
30 |
31 | @Override
32 | public String toString() {
33 | return "SystemFileTimeSource";
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/UnixFileAttributeView.java:
--------------------------------------------------------------------------------
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 java.nio.file.attribute.FileAttributeView;
20 |
21 | /**
22 | * Dummy view interface for the "unix" view, which doesn't have a public view interface.
23 | *
24 | * @author Colin Decker
25 | */
26 | interface UnixFileAttributeView extends FileAttributeView {}
27 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/UnixPathType.java:
--------------------------------------------------------------------------------
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.checkArgument;
20 |
21 | import java.nio.file.InvalidPathException;
22 | import org.jspecify.annotations.Nullable;
23 |
24 | /**
25 | * Unix-style path type.
26 | *
27 | * @author Colin Decker
28 | */
29 | final class UnixPathType extends PathType {
30 |
31 | /** Unix path type. */
32 | static final PathType INSTANCE = new UnixPathType();
33 |
34 | private UnixPathType() {
35 | super(false, '/');
36 | }
37 |
38 | @Override
39 | public ParseResult parsePath(String path) {
40 | if (path.isEmpty()) {
41 | return emptyPath();
42 | }
43 |
44 | checkValid(path);
45 |
46 | String root = path.startsWith("/") ? "/" : null;
47 | return new ParseResult(root, splitter().split(path));
48 | }
49 |
50 | private static void checkValid(String path) {
51 | int nulIndex = path.indexOf('\0');
52 | if (nulIndex != -1) {
53 | throw new InvalidPathException(path, "nul character not allowed", nulIndex);
54 | }
55 | }
56 |
57 | @Override
58 | public String toString(@Nullable String root, Iterable names) {
59 | StringBuilder builder = new StringBuilder();
60 | if (root != null) {
61 | builder.append(root);
62 | }
63 | joiner().appendTo(builder, names);
64 | return builder.toString();
65 | }
66 |
67 | @Override
68 | public String toUriPath(String root, Iterable names, boolean directory) {
69 | StringBuilder builder = new StringBuilder();
70 | for (String name : names) {
71 | builder.append('/').append(name);
72 | }
73 |
74 | if (directory || builder.length() == 0) {
75 | builder.append('/');
76 | }
77 | return builder.toString();
78 | }
79 |
80 | @Override
81 | public ParseResult parseUriPath(String uriPath) {
82 | checkArgument(uriPath.startsWith("/"), "uriPath (%s) must start with /", uriPath);
83 | return parsePath(uriPath);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/UserDefinedAttributeProvider.java:
--------------------------------------------------------------------------------
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.io.IOException;
24 | import java.nio.ByteBuffer;
25 | import java.nio.file.attribute.FileAttributeView;
26 | import java.nio.file.attribute.UserDefinedFileAttributeView;
27 | import java.util.List;
28 | import org.jspecify.annotations.Nullable;
29 |
30 | /**
31 | * Attribute provider that provides the {@link UserDefinedFileAttributeView} ("user"). Unlike most
32 | * other attribute providers, this one has no pre-defined set of attributes. Rather, it allows
33 | * arbitrary user defined attributes to be set (as {@code ByteBuffer} or {@code byte[]}) and read
34 | * (as {@code byte[]}).
35 | *
36 | * @author Colin Decker
37 | */
38 | final class UserDefinedAttributeProvider extends AttributeProvider {
39 |
40 | UserDefinedAttributeProvider() {}
41 |
42 | @Override
43 | public String name() {
44 | return "user";
45 | }
46 |
47 | @Override
48 | public ImmutableSet fixedAttributes() {
49 | // no fixed set of attributes for this view
50 | return ImmutableSet.of();
51 | }
52 |
53 | @Override
54 | public boolean supports(String attribute) {
55 | // any attribute name is supported
56 | return true;
57 | }
58 |
59 | @Override
60 | public ImmutableSet attributes(File file) {
61 | return userDefinedAttributes(file);
62 | }
63 |
64 | private static ImmutableSet userDefinedAttributes(File file) {
65 | ImmutableSet.Builder builder = ImmutableSet.builder();
66 | for (String attribute : file.getAttributeNames("user")) {
67 | builder.add(attribute);
68 | }
69 | return builder.build();
70 | }
71 |
72 | @Override
73 | public @Nullable Object get(File file, String attribute) {
74 | Object value = file.getAttribute("user", attribute);
75 | if (value instanceof byte[]) {
76 | byte[] bytes = (byte[]) value;
77 | return bytes.clone();
78 | }
79 | return null;
80 | }
81 |
82 | @Override
83 | public void set(File file, String view, String attribute, Object value, boolean create) {
84 | checkNotNull(value);
85 | checkNotCreate(view, attribute, create);
86 |
87 | byte[] bytes;
88 | if (value instanceof byte[]) {
89 | bytes = ((byte[]) value).clone();
90 | } else if (value instanceof ByteBuffer) {
91 | // value instanceof ByteBuffer
92 | ByteBuffer buffer = (ByteBuffer) value;
93 | bytes = new byte[buffer.remaining()];
94 | buffer.get(bytes);
95 | } else {
96 | throw invalidType(view, attribute, value, byte[].class, ByteBuffer.class);
97 | }
98 |
99 | file.setAttribute("user", attribute, bytes);
100 | }
101 |
102 | @Override
103 | public Class viewType() {
104 | return UserDefinedFileAttributeView.class;
105 | }
106 |
107 | @Override
108 | public UserDefinedFileAttributeView view(
109 | FileLookup lookup, ImmutableMap inheritedViews) {
110 | return new View(lookup);
111 | }
112 |
113 | /** Implementation of {@link UserDefinedFileAttributeView}. */
114 | private static class View extends AbstractAttributeView implements UserDefinedFileAttributeView {
115 |
116 | public View(FileLookup lookup) {
117 | super(lookup);
118 | }
119 |
120 | @Override
121 | public String name() {
122 | return "user";
123 | }
124 |
125 | @Override
126 | public List list() throws IOException {
127 | return userDefinedAttributes(lookupFile()).asList();
128 | }
129 |
130 | private byte[] getStoredBytes(String name) throws IOException {
131 | byte[] bytes = (byte[]) lookupFile().getAttribute(name(), name);
132 | if (bytes == null) {
133 | throw new IllegalArgumentException("attribute '" + name() + ":" + name + "' is not set");
134 | }
135 | return bytes;
136 | }
137 |
138 | @Override
139 | public int size(String name) throws IOException {
140 | return getStoredBytes(name).length;
141 | }
142 |
143 | @Override
144 | public int read(String name, ByteBuffer dst) throws IOException {
145 | byte[] bytes = getStoredBytes(name);
146 | dst.put(bytes);
147 | return bytes.length;
148 | }
149 |
150 | @Override
151 | public int write(String name, ByteBuffer src) throws IOException {
152 | byte[] bytes = new byte[src.remaining()];
153 | src.get(bytes);
154 | lookupFile().setAttribute(name(), name, bytes);
155 | return bytes.length;
156 | }
157 |
158 | @Override
159 | public void delete(String name) throws IOException {
160 | lookupFile().deleteAttribute(name(), name);
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/UserLookupService.java:
--------------------------------------------------------------------------------
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 java.io.IOException;
22 | import java.nio.file.attribute.GroupPrincipal;
23 | import java.nio.file.attribute.UserPrincipal;
24 | import java.nio.file.attribute.UserPrincipalLookupService;
25 | import java.nio.file.attribute.UserPrincipalNotFoundException;
26 |
27 | /**
28 | * {@link UserPrincipalLookupService} implementation.
29 | *
30 | * @author Colin Decker
31 | */
32 | final class UserLookupService extends UserPrincipalLookupService {
33 |
34 | private final boolean supportsGroups;
35 |
36 | public UserLookupService(boolean supportsGroups) {
37 | this.supportsGroups = supportsGroups;
38 | }
39 |
40 | @Override
41 | public UserPrincipal lookupPrincipalByName(String name) {
42 | return createUserPrincipal(name);
43 | }
44 |
45 | @Override
46 | public GroupPrincipal lookupPrincipalByGroupName(String group) throws IOException {
47 | if (!supportsGroups) {
48 | throw new UserPrincipalNotFoundException(group); // required by spec
49 | }
50 | return createGroupPrincipal(group);
51 | }
52 |
53 | /** Creates a {@link UserPrincipal} for the given user name. */
54 | static UserPrincipal createUserPrincipal(String name) {
55 | return new JimfsUserPrincipal(name);
56 | }
57 |
58 | /** Creates a {@link GroupPrincipal} for the given group name. */
59 | static GroupPrincipal createGroupPrincipal(String name) {
60 | return new JimfsGroupPrincipal(name);
61 | }
62 |
63 | /** Base class for {@link UserPrincipal} and {@link GroupPrincipal} implementations. */
64 | private abstract static class NamedPrincipal implements UserPrincipal {
65 |
66 | protected final String name;
67 |
68 | private NamedPrincipal(String name) {
69 | this.name = checkNotNull(name);
70 | }
71 |
72 | @Override
73 | public final String getName() {
74 | return name;
75 | }
76 |
77 | @Override
78 | public final int hashCode() {
79 | return name.hashCode();
80 | }
81 |
82 | @Override
83 | public final String toString() {
84 | return name;
85 | }
86 | }
87 |
88 | /** {@link UserPrincipal} implementation. */
89 | static final class JimfsUserPrincipal extends NamedPrincipal {
90 |
91 | private JimfsUserPrincipal(String name) {
92 | super(name);
93 | }
94 |
95 | @Override
96 | public boolean equals(Object obj) {
97 | return obj instanceof JimfsUserPrincipal
98 | && getName().equals(((JimfsUserPrincipal) obj).getName());
99 | }
100 | }
101 |
102 | /** {@link GroupPrincipal} implementation. */
103 | static final class JimfsGroupPrincipal extends NamedPrincipal implements GroupPrincipal {
104 |
105 | private JimfsGroupPrincipal(String name) {
106 | super(name);
107 | }
108 |
109 | @Override
110 | public boolean equals(Object obj) {
111 | return obj instanceof JimfsGroupPrincipal && ((JimfsGroupPrincipal) obj).name.equals(name);
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/Util.java:
--------------------------------------------------------------------------------
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.checkArgument;
20 | import static com.google.common.base.Preconditions.checkNotNull;
21 |
22 | import com.google.common.collect.ImmutableCollection;
23 |
24 | /**
25 | * Miscellaneous static utility methods.
26 | *
27 | * @author Colin Decker
28 | * @author Austin Appleby
29 | */
30 | final class Util {
31 |
32 | private Util() {}
33 |
34 | /** Returns the next power of 2 >= n. */
35 | public static int nextPowerOf2(int n) {
36 | if (n == 0) {
37 | return 1;
38 | }
39 | int b = Integer.highestOneBit(n);
40 | return b == n ? n : b << 1;
41 | }
42 |
43 | /**
44 | * Checks that the given number is not negative, throwing IAE if it is. The given description
45 | * describes the number in the exception message.
46 | */
47 | static void checkNotNegative(long n, String description) {
48 | checkArgument(n >= 0, "%s must not be negative: %s", description, n);
49 | }
50 |
51 | /** Checks that no element in the given iterable is null, throwing NPE if any is. */
52 | static void checkNoneNull(Iterable> objects) {
53 | if (!(objects instanceof ImmutableCollection)) {
54 | for (Object o : objects) {
55 | checkNotNull(o);
56 | }
57 | }
58 | }
59 |
60 | private static final int C1 = 0xcc9e2d51;
61 | private static final int C2 = 0x1b873593;
62 |
63 | /*
64 | * This method was rewritten in Java from an intermediate step of the Murmur hash function in
65 | * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp, which contained the
66 | * following header:
67 | *
68 | * MurmurHash3 was written by Austin Appleby, and is placed in the public domain. The author
69 | * hereby disclaims copyright to this source code.
70 | */
71 | static int smearHash(int hashCode) {
72 | return C2 * Integer.rotateLeft(hashCode * C1, 15);
73 | }
74 |
75 | private static final int ARRAY_LEN = 8192;
76 | private static final byte[] ZERO_ARRAY = new byte[ARRAY_LEN];
77 | private static final byte[][] NULL_ARRAY = new byte[ARRAY_LEN][];
78 |
79 | /** Zeroes all bytes between off (inclusive) and off + len (exclusive) in the given array. */
80 | static void zero(byte[] bytes, int off, int len) {
81 | // this is significantly faster than looping or Arrays.fill (which loops), particularly when
82 | // the length of the slice to be zeroed is <= to ARRAY_LEN (in that case, it's faster by a
83 | // factor of 2)
84 | int remaining = len;
85 | while (remaining > ARRAY_LEN) {
86 | System.arraycopy(ZERO_ARRAY, 0, bytes, off, ARRAY_LEN);
87 | off += ARRAY_LEN;
88 | remaining -= ARRAY_LEN;
89 | }
90 |
91 | System.arraycopy(ZERO_ARRAY, 0, bytes, off, remaining);
92 | }
93 |
94 | /**
95 | * Clears (sets to null) all blocks between off (inclusive) and off + len (exclusive) in the given
96 | * array.
97 | */
98 | static void clear(byte[][] blocks, int off, int len) {
99 | // this is significantly faster than looping or Arrays.fill (which loops), particularly when
100 | // the length of the slice to be cleared is <= to ARRAY_LEN (in that case, it's faster by a
101 | // factor of 2)
102 | int remaining = len;
103 | while (remaining > ARRAY_LEN) {
104 | System.arraycopy(NULL_ARRAY, 0, blocks, off, ARRAY_LEN);
105 | off += ARRAY_LEN;
106 | remaining -= ARRAY_LEN;
107 | }
108 |
109 | System.arraycopy(NULL_ARRAY, 0, blocks, off, remaining);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/WatchServiceConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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.checkArgument;
20 | import static com.google.common.base.Preconditions.checkNotNull;
21 | import static java.util.concurrent.TimeUnit.SECONDS;
22 |
23 | import java.nio.file.WatchService;
24 | import java.util.concurrent.TimeUnit;
25 |
26 | /**
27 | * Configuration for the {@link WatchService} implementation used by a file system.
28 | *
29 | * @author Colin Decker
30 | * @since 1.1
31 | */
32 | public abstract class WatchServiceConfiguration {
33 |
34 | /** The default configuration that's used if the user doesn't provide anything more specific. */
35 | static final WatchServiceConfiguration DEFAULT = polling(5, SECONDS);
36 |
37 | /**
38 | * Returns a configuration for a {@link WatchService} that polls watched directories for changes
39 | * every {@code interval} of the given {@code timeUnit} (e.g. every 5 {@link TimeUnit#SECONDS
40 | * seconds}).
41 | */
42 | @SuppressWarnings("GoodTime") // should accept a java.time.Duration
43 | public static WatchServiceConfiguration polling(long interval, TimeUnit timeUnit) {
44 | return new PollingConfig(interval, timeUnit);
45 | }
46 |
47 | WatchServiceConfiguration() {}
48 |
49 | /** Creates a new {@link AbstractWatchService} implementation. */
50 | // return type and parameters of this method subject to change if needed for any future
51 | // implementations
52 | abstract AbstractWatchService newWatchService(FileSystemView view, PathService pathService);
53 |
54 | /** Implementation for {@link #polling}. */
55 | private static final class PollingConfig extends WatchServiceConfiguration {
56 |
57 | private final long interval;
58 | private final TimeUnit timeUnit;
59 |
60 | private PollingConfig(long interval, TimeUnit timeUnit) {
61 | checkArgument(interval > 0, "interval (%s) must be positive", interval);
62 | this.interval = interval;
63 | this.timeUnit = checkNotNull(timeUnit);
64 | }
65 |
66 | @Override
67 | AbstractWatchService newWatchService(FileSystemView view, PathService pathService) {
68 | return new PollingWatchService(view, pathService, view.state(), interval, timeUnit);
69 | }
70 |
71 | @Override
72 | public String toString() {
73 | return "WatchServiceConfiguration.polling(" + interval + ", " + timeUnit + ")";
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/jimfs/src/main/java/com/google/common/jimfs/package-info.java:
--------------------------------------------------------------------------------
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 | /**
18 | * Package containing the Jimfs file system API and implementation. Most users should only need to
19 | * use the {@link com.google.common.jimfs.Jimfs Jimfs} and {@link
20 | * com.google.common.jimfs.Configuration Configuration} classes.
21 | */
22 | @CheckReturnValue
23 | @ParametersAreNonnullByDefault
24 | package com.google.common.jimfs;
25 |
26 | import com.google.errorprone.annotations.CheckReturnValue;
27 | import javax.annotation.ParametersAreNonnullByDefault;
28 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/AbstractAttributeProviderTest.java:
--------------------------------------------------------------------------------
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.truth.Truth.assertThat;
20 | import static org.junit.Assert.fail;
21 |
22 | import com.google.common.collect.ImmutableMap;
23 | import java.io.IOException;
24 | import java.nio.file.attribute.FileAttributeView;
25 | import java.util.Map;
26 | import java.util.Set;
27 | import org.junit.Before;
28 |
29 | /**
30 | * Abstract base class for tests of individual {@link AttributeProvider} implementations.
31 | *
32 | * @author Colin Decker
33 | */
34 | public abstract class AbstractAttributeProviderTest {
35 |
36 | protected static final ImmutableMap NO_INHERITED_VIEWS =
37 | ImmutableMap.of();
38 |
39 | protected final FakeFileTimeSource fileTimeSource = new FakeFileTimeSource();
40 |
41 | protected P provider;
42 | protected File file;
43 |
44 | /** Create the provider being tested. */
45 | protected abstract P createProvider();
46 |
47 | /** Creates the set of providers the provider being tested depends on. */
48 | protected abstract Set extends AttributeProvider> createInheritedProviders();
49 |
50 | protected FileLookup fileLookup() {
51 | return new FileLookup() {
52 | @Override
53 | public File lookup() throws IOException {
54 | return file;
55 | }
56 | };
57 | }
58 |
59 | @Before
60 | public void setUp() {
61 | this.provider = createProvider();
62 | this.file = Directory.create(0, fileTimeSource.now());
63 |
64 | Map defaultValues = createDefaultValues();
65 | setDefaultValues(file, provider, defaultValues);
66 |
67 | Set extends AttributeProvider> inheritedProviders = createInheritedProviders();
68 | for (AttributeProvider inherited : inheritedProviders) {
69 | setDefaultValues(file, inherited, defaultValues);
70 | }
71 | }
72 |
73 | private static void setDefaultValues(
74 | File file, AttributeProvider provider, Map defaultValues) {
75 | Map defaults = provider.defaultValues(defaultValues);
76 | for (Map.Entry entry : defaults.entrySet()) {
77 | int separatorIndex = entry.getKey().indexOf(':');
78 | String view = entry.getKey().substring(0, separatorIndex);
79 | String attr = entry.getKey().substring(separatorIndex + 1);
80 | file.setAttribute(view, attr, entry.getValue());
81 | }
82 | }
83 |
84 | protected Map createDefaultValues() {
85 | return ImmutableMap.of();
86 | }
87 |
88 | // assertions
89 |
90 | protected void assertSupportsAll(String... attributes) {
91 | for (String attribute : attributes) {
92 | assertThat(provider.supports(attribute)).isTrue();
93 | }
94 | }
95 |
96 | protected void assertContainsAll(File file, ImmutableMap expectedAttributes) {
97 | for (Map.Entry entry : expectedAttributes.entrySet()) {
98 | String attribute = entry.getKey();
99 | Object value = entry.getValue();
100 |
101 | assertThat(provider.get(file, attribute)).isEqualTo(value);
102 | }
103 | }
104 |
105 | protected void assertSetAndGetSucceeds(String attribute, Object value) {
106 | assertSetAndGetSucceeds(attribute, value, false);
107 | }
108 |
109 | protected void assertSetAndGetSucceeds(String attribute, Object value, boolean create) {
110 | provider.set(file, provider.name(), attribute, value, create);
111 | assertThat(provider.get(file, attribute)).isEqualTo(value);
112 | }
113 |
114 | protected void assertSetAndGetSucceedsOnCreate(String attribute, Object value) {
115 | assertSetAndGetSucceeds(attribute, value, true);
116 | }
117 |
118 | @SuppressWarnings("EmptyCatchBlock")
119 | protected void assertSetFails(String attribute, Object value) {
120 | try {
121 | provider.set(file, provider.name(), attribute, value, false);
122 | fail();
123 | } catch (IllegalArgumentException expected) {
124 | }
125 | }
126 |
127 | @SuppressWarnings("EmptyCatchBlock")
128 | protected void assertSetFailsOnCreate(String attribute, Object value) {
129 | try {
130 | provider.set(file, provider.name(), attribute, value, true);
131 | fail();
132 | } catch (UnsupportedOperationException expected) {
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/AbstractJimfsIntegrationTest.java:
--------------------------------------------------------------------------------
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.jimfs.PathSubject.paths;
20 | import static com.google.common.truth.Truth.assertThat;
21 | import static com.google.common.truth.Truth.assert_;
22 |
23 | import java.io.IOException;
24 | import java.nio.file.FileSystem;
25 | import java.nio.file.Files;
26 | import java.nio.file.LinkOption;
27 | import java.nio.file.Path;
28 | import java.nio.file.attribute.BasicFileAttributes;
29 | import java.nio.file.attribute.FileTime;
30 | import org.junit.After;
31 | import org.junit.Before;
32 |
33 | /** @author Colin Decker */
34 | public abstract class AbstractJimfsIntegrationTest {
35 |
36 | protected FileSystem fs;
37 |
38 | @Before
39 | public void setUp() throws IOException {
40 | fs = createFileSystem();
41 | }
42 |
43 | @After
44 | public void tearDown() throws IOException {
45 | fs.close();
46 | }
47 |
48 | /** Creates the file system to use in the tests. */
49 | protected abstract FileSystem createFileSystem();
50 |
51 | // helpers
52 |
53 | protected Path path(String first, String... more) {
54 | return fs.getPath(first, more);
55 | }
56 |
57 | protected Object getFileKey(String path, LinkOption... options) throws IOException {
58 | return Files.getAttribute(path(path), "fileKey", options);
59 | }
60 |
61 | protected PathSubject assertThatPath(String path, LinkOption... options) {
62 | return assertThatPath(path(path), options);
63 | }
64 |
65 | protected static PathSubject assertThatPath(Path path, LinkOption... options) {
66 | PathSubject subject = assert_().about(paths()).that(path);
67 | if (options.length != 0) {
68 | subject = subject.noFollowLinks();
69 | }
70 | return subject;
71 | }
72 |
73 | /** Tester for testing changes in file times. */
74 | protected static final class FileTimeTester {
75 |
76 | private final Path path;
77 |
78 | private FileTime accessTime;
79 | private FileTime modifiedTime;
80 |
81 | FileTimeTester(Path path) throws IOException {
82 | this.path = path;
83 |
84 | BasicFileAttributes attrs = attrs();
85 | accessTime = attrs.lastAccessTime();
86 | modifiedTime = attrs.lastModifiedTime();
87 | }
88 |
89 | private BasicFileAttributes attrs() throws IOException {
90 | return Files.readAttributes(path, BasicFileAttributes.class);
91 | }
92 |
93 | public void assertAccessTimeChanged() throws IOException {
94 | FileTime t = attrs().lastAccessTime();
95 | assertThat(t).isNotEqualTo(accessTime);
96 | accessTime = t;
97 | }
98 |
99 | public void assertAccessTimeDidNotChange() throws IOException {
100 | FileTime t = attrs().lastAccessTime();
101 | assertThat(t).isEqualTo(accessTime);
102 | }
103 |
104 | public void assertModifiedTimeChanged() throws IOException {
105 | FileTime t = attrs().lastModifiedTime();
106 | assertThat(t).isNotEqualTo(modifiedTime);
107 | modifiedTime = t;
108 | }
109 |
110 | public void assertModifiedTimeDidNotChange() throws IOException {
111 | FileTime t = attrs().lastModifiedTime();
112 | assertThat(t).isEqualTo(modifiedTime);
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/AclAttributeProviderTest.java:
--------------------------------------------------------------------------------
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.jimfs.UserLookupService.createUserPrincipal;
20 | import static com.google.common.truth.Truth.assertThat;
21 | import static java.nio.file.attribute.AclEntryFlag.DIRECTORY_INHERIT;
22 | import static java.nio.file.attribute.AclEntryPermission.APPEND_DATA;
23 | import static java.nio.file.attribute.AclEntryPermission.DELETE;
24 | import static java.nio.file.attribute.AclEntryType.ALLOW;
25 | import static org.junit.Assert.assertNotNull;
26 |
27 | import com.google.common.collect.ImmutableList;
28 | import com.google.common.collect.ImmutableMap;
29 | import com.google.common.collect.ImmutableSet;
30 | import java.io.IOException;
31 | import java.nio.file.attribute.AclEntry;
32 | import java.nio.file.attribute.AclFileAttributeView;
33 | import java.nio.file.attribute.FileAttributeView;
34 | import java.nio.file.attribute.UserPrincipal;
35 | import java.util.Map;
36 | import java.util.Set;
37 | import org.junit.Test;
38 | import org.junit.runner.RunWith;
39 | import org.junit.runners.JUnit4;
40 |
41 | /**
42 | * Tests for {@link AclAttributeProvider}.
43 | *
44 | * @author Colin Decker
45 | */
46 | @RunWith(JUnit4.class)
47 | public class AclAttributeProviderTest extends AbstractAttributeProviderTest {
48 |
49 | private static final UserPrincipal USER = createUserPrincipal("user");
50 | private static final UserPrincipal FOO = createUserPrincipal("foo");
51 |
52 | private static final ImmutableList defaultAcl =
53 | new ImmutableList.Builder()
54 | .add(
55 | AclEntry.newBuilder()
56 | .setType(ALLOW)
57 | .setFlags(DIRECTORY_INHERIT)
58 | .setPermissions(DELETE, APPEND_DATA)
59 | .setPrincipal(USER)
60 | .build())
61 | .add(
62 | AclEntry.newBuilder()
63 | .setType(ALLOW)
64 | .setFlags(DIRECTORY_INHERIT)
65 | .setPermissions(DELETE, APPEND_DATA)
66 | .setPrincipal(FOO)
67 | .build())
68 | .build();
69 |
70 | @Override
71 | protected AclAttributeProvider createProvider() {
72 | return new AclAttributeProvider();
73 | }
74 |
75 | @Override
76 | protected Set extends AttributeProvider> createInheritedProviders() {
77 | return ImmutableSet.of(new BasicAttributeProvider(), new OwnerAttributeProvider());
78 | }
79 |
80 | @Override
81 | protected Map createDefaultValues() {
82 | return ImmutableMap.of("acl:acl", defaultAcl);
83 | }
84 |
85 | @Test
86 | public void testInitialAttributes() {
87 | assertThat(provider.get(file, "acl")).isEqualTo(defaultAcl);
88 | }
89 |
90 | @Test
91 | public void testSet() {
92 | assertSetAndGetSucceeds("acl", ImmutableList.of());
93 | assertSetFailsOnCreate("acl", ImmutableList.of());
94 | assertSetFails("acl", ImmutableSet.of());
95 | assertSetFails("acl", ImmutableList.of("hello"));
96 | }
97 |
98 | @Test
99 | public void testView() throws IOException {
100 | AclFileAttributeView view =
101 | provider.view(
102 | fileLookup(),
103 | ImmutableMap.of(
104 | "owner", new OwnerAttributeProvider().view(fileLookup(), NO_INHERITED_VIEWS)));
105 | assertNotNull(view);
106 |
107 | assertThat(view.name()).isEqualTo("acl");
108 |
109 | assertThat(view.getAcl()).isEqualTo(defaultAcl);
110 |
111 | view.setAcl(ImmutableList.of());
112 | view.setOwner(FOO);
113 |
114 | assertThat(view.getAcl()).isEqualTo(ImmutableList.of());
115 | assertThat(view.getOwner()).isEqualTo(FOO);
116 |
117 | assertThat(file.getAttribute("acl", "acl")).isEqualTo(ImmutableList.of());
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/BasicAttributeProviderTest.java:
--------------------------------------------------------------------------------
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.truth.Truth.assertThat;
20 |
21 | import com.google.common.collect.ImmutableMap;
22 | import com.google.common.collect.ImmutableSet;
23 | import java.io.IOException;
24 | import java.nio.file.attribute.BasicFileAttributeView;
25 | import java.nio.file.attribute.BasicFileAttributes;
26 | import java.nio.file.attribute.FileTime;
27 | import java.util.Set;
28 | import org.junit.Test;
29 | import org.junit.runner.RunWith;
30 | import org.junit.runners.JUnit4;
31 |
32 | /**
33 | * Tests for {@link BasicAttributeProvider}.
34 | *
35 | * @author Colin Decker
36 | */
37 | @RunWith(JUnit4.class)
38 | public class BasicAttributeProviderTest
39 | extends AbstractAttributeProviderTest {
40 |
41 | @Override
42 | protected BasicAttributeProvider createProvider() {
43 | return new BasicAttributeProvider();
44 | }
45 |
46 | @Override
47 | protected Set extends AttributeProvider> createInheritedProviders() {
48 | return ImmutableSet.of();
49 | }
50 |
51 | @Test
52 | public void testSupportedAttributes() {
53 | assertSupportsAll(
54 | "fileKey",
55 | "size",
56 | "isDirectory",
57 | "isRegularFile",
58 | "isSymbolicLink",
59 | "isOther",
60 | "creationTime",
61 | "lastModifiedTime",
62 | "lastAccessTime");
63 | }
64 |
65 | @Test
66 | public void testInitialAttributes() {
67 | FileTime expected = fileTimeSource.now();
68 | assertThat(file.getCreationTime()).isEqualTo(expected);
69 | assertThat(file.getLastAccessTime()).isEqualTo(expected);
70 | assertThat(file.getLastModifiedTime()).isEqualTo(expected);
71 |
72 | assertContainsAll(
73 | file,
74 | ImmutableMap.builder()
75 | .put("fileKey", 0)
76 | .put("size", 0L)
77 | .put("isDirectory", true)
78 | .put("isRegularFile", false)
79 | .put("isSymbolicLink", false)
80 | .put("isOther", false)
81 | .build());
82 | }
83 |
84 | @Test
85 | public void testSet() {
86 | FileTime time = FileTime.fromMillis(0L);
87 |
88 | // settable
89 | assertSetAndGetSucceeds("creationTime", time);
90 | assertSetAndGetSucceeds("lastModifiedTime", time);
91 | assertSetAndGetSucceeds("lastAccessTime", time);
92 |
93 | // unsettable
94 | assertSetFails("fileKey", 3L);
95 | assertSetFails("size", 1L);
96 | assertSetFails("isRegularFile", true);
97 | assertSetFails("isDirectory", true);
98 | assertSetFails("isSymbolicLink", true);
99 | assertSetFails("isOther", true);
100 |
101 | // invalid type
102 | assertSetFails("creationTime", "foo");
103 | }
104 |
105 | @Test
106 | public void testSetOnCreate() {
107 | FileTime time = FileTime.fromMillis(0L);
108 |
109 | assertSetFailsOnCreate("creationTime", time);
110 | assertSetFailsOnCreate("lastModifiedTime", time);
111 | assertSetFailsOnCreate("lastAccessTime", time);
112 | }
113 |
114 | @Test
115 | public void testView() throws IOException {
116 | BasicFileAttributeView view = provider.view(fileLookup(), NO_INHERITED_VIEWS);
117 |
118 | assertThat(view).isNotNull();
119 | assertThat(view.name()).isEqualTo("basic");
120 |
121 | BasicFileAttributes attrs = view.readAttributes();
122 | assertThat(attrs.fileKey()).isEqualTo(0);
123 |
124 | FileTime initial = fileTimeSource.now();
125 | assertThat(attrs.creationTime()).isEqualTo(initial);
126 | assertThat(attrs.lastAccessTime()).isEqualTo(initial);
127 | assertThat(attrs.lastModifiedTime()).isEqualTo(initial);
128 |
129 | view.setTimes(null, null, null);
130 |
131 | assertThat(attrs.creationTime()).isEqualTo(initial);
132 | assertThat(attrs.lastAccessTime()).isEqualTo(initial);
133 | assertThat(attrs.lastModifiedTime()).isEqualTo(initial);
134 |
135 | view.setTimes(FileTime.fromMillis(0L), null, null);
136 |
137 | attrs = view.readAttributes();
138 | assertThat(attrs.creationTime()).isEqualTo(initial);
139 | assertThat(attrs.lastAccessTime()).isEqualTo(initial);
140 | assertThat(attrs.lastModifiedTime()).isEqualTo(FileTime.fromMillis(0L));
141 | }
142 |
143 | @Test
144 | public void testAttributes() {
145 | BasicFileAttributes attrs = provider.readAttributes(file);
146 | assertThat(attrs.fileKey()).isEqualTo(0);
147 | assertThat(attrs.isDirectory()).isTrue();
148 | assertThat(attrs.isRegularFile()).isFalse();
149 | assertThat(attrs.creationTime()).isNotNull();
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/BasicFileAttribute.java:
--------------------------------------------------------------------------------
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 java.nio.file.attribute.FileAttribute;
22 |
23 | /** @author Colin Decker */
24 | public class BasicFileAttribute implements FileAttribute {
25 |
26 | private final String name;
27 | private final T value;
28 |
29 | public BasicFileAttribute(String name, T value) {
30 | this.name = checkNotNull(name);
31 | this.value = checkNotNull(value);
32 | }
33 |
34 | @Override
35 | public String name() {
36 | return name;
37 | }
38 |
39 | @Override
40 | public T value() {
41 | return value;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/ByteBufferChannel.java:
--------------------------------------------------------------------------------
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 com.google.errorprone.annotations.CanIgnoreReturnValue;
20 | import java.io.IOException;
21 | import java.nio.ByteBuffer;
22 | import java.nio.channels.SeekableByteChannel;
23 |
24 | /** @author Colin Decker */
25 | public class ByteBufferChannel implements SeekableByteChannel {
26 |
27 | private final ByteBuffer buffer;
28 |
29 | public ByteBufferChannel(byte[] bytes) {
30 | this.buffer = ByteBuffer.wrap(bytes);
31 | }
32 |
33 | public ByteBufferChannel(byte[] bytes, int offset, int length) {
34 | this.buffer = ByteBuffer.wrap(bytes, offset, length);
35 | }
36 |
37 | public ByteBufferChannel(int capacity) {
38 | this.buffer = ByteBuffer.allocate(capacity);
39 | }
40 |
41 | public ByteBufferChannel(ByteBuffer buffer) {
42 | this.buffer = buffer;
43 | }
44 |
45 | public ByteBuffer buffer() {
46 | return buffer;
47 | }
48 |
49 | @Override
50 | public int read(ByteBuffer dst) throws IOException {
51 | if (buffer.remaining() == 0) {
52 | return -1;
53 | }
54 | int length = Math.min(dst.remaining(), buffer.remaining());
55 | for (int i = 0; i < length; i++) {
56 | dst.put(buffer.get());
57 | }
58 | return length;
59 | }
60 |
61 | @Override
62 | public int write(ByteBuffer src) throws IOException {
63 | int length = Math.min(src.remaining(), buffer.remaining());
64 | for (int i = 0; i < length; i++) {
65 | buffer.put(src.get());
66 | }
67 | return length;
68 | }
69 |
70 | @Override
71 | public long position() throws IOException {
72 | return buffer.position();
73 | }
74 |
75 | @Override
76 | @CanIgnoreReturnValue
77 | public SeekableByteChannel position(long newPosition) throws IOException {
78 | buffer.position((int) newPosition);
79 | return this;
80 | }
81 |
82 | @Override
83 | public long size() throws IOException {
84 | return buffer.limit();
85 | }
86 |
87 | @Override
88 | @CanIgnoreReturnValue
89 | public SeekableByteChannel truncate(long size) throws IOException {
90 | buffer.limit((int) size);
91 | return this;
92 | }
93 |
94 | @Override
95 | public boolean isOpen() {
96 | return true;
97 | }
98 |
99 | @Override
100 | public void close() throws IOException {}
101 | }
102 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/ClassLoaderTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 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 java.nio.charset.StandardCharsets.UTF_8;
20 | import static org.junit.Assert.assertEquals;
21 | import static org.junit.Assert.assertFalse;
22 | import static org.junit.Assert.assertTrue;
23 |
24 | import com.google.common.base.MoreObjects;
25 | import com.google.common.collect.ImmutableList;
26 | import java.io.IOException;
27 | import java.lang.reflect.Method;
28 | import java.net.URLClassLoader;
29 | import java.nio.file.FileSystem;
30 | import java.nio.file.Files;
31 | import java.nio.file.Path;
32 | import java.nio.file.spi.FileSystemProvider;
33 | import java.util.List;
34 | import org.junit.Test;
35 | import org.junit.runner.RunWith;
36 | import org.junit.runners.JUnit4;
37 |
38 | /**
39 | * Tests behavior when user code loads Jimfs in a separate class loader from the system class loader
40 | * (which is what {@link FileSystemProvider#installedProviders()} uses to load {@link
41 | * FileSystemProvider}s as services from the classpath).
42 | *
43 | * @author Colin Decker
44 | */
45 | @RunWith(JUnit4.class)
46 | public class ClassLoaderTest {
47 |
48 | @Test
49 | public void separateClassLoader() throws Exception {
50 | ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
51 | ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
52 |
53 | ClassLoader loader = MoreObjects.firstNonNull(contextLoader, systemLoader);
54 |
55 | if (loader instanceof URLClassLoader) {
56 | // Anything we can do if it isn't a URLClassLoader?
57 | URLClassLoader urlLoader = (URLClassLoader) loader;
58 |
59 | ClassLoader separateLoader =
60 | new URLClassLoader(
61 | urlLoader.getURLs(), systemLoader.getParent()); // either null or the boostrap loader
62 |
63 | Thread.currentThread().setContextClassLoader(separateLoader);
64 | try {
65 | Class> thisClass = separateLoader.loadClass(getClass().getName());
66 | Method createFileSystem = thisClass.getDeclaredMethod("createFileSystem");
67 |
68 | // First, the call to Jimfs.newFileSystem in createFileSystem needs to succeed
69 | Object fs = createFileSystem.invoke(null);
70 |
71 | // Next, some sanity checks:
72 |
73 | // The file system is a JimfsFileSystem
74 | assertEquals("com.google.common.jimfs.JimfsFileSystem", fs.getClass().getName());
75 |
76 | // But it is not seen as an instance of JimfsFileSystem here because it was loaded by a
77 | // different ClassLoader
78 | assertFalse(fs instanceof JimfsFileSystem);
79 |
80 | // But it should be an instance of FileSystem regardless, which is the important thing.
81 | assertTrue(fs instanceof FileSystem);
82 |
83 | // And normal file operations should work on it despite its provenance from a different
84 | // ClassLoader
85 | writeAndRead((FileSystem) fs, "bar.txt", "blah blah");
86 |
87 | // And for the heck of it, test the contents of the file that was created in
88 | // createFileSystem too
89 | assertEquals(
90 | "blah", Files.readAllLines(((FileSystem) fs).getPath("foo.txt"), UTF_8).get(0));
91 | } finally {
92 | Thread.currentThread().setContextClassLoader(contextLoader);
93 | }
94 | }
95 | }
96 |
97 | /**
98 | * This method is really just testing that {@code Jimfs.newFileSystem()} succeeds. Without special
99 | * handling, when the system class loader loads our {@code FileSystemProvider} implementation as a
100 | * service and this code (the user code) is loaded in a separate class loader, the system-loaded
101 | * provider won't see the instance of {@code Configuration} we give it as being an instance of the
102 | * {@code Configuration} it's expecting (they're completely separate classes) and creation of the
103 | * file system will fail.
104 | */
105 | public static FileSystem createFileSystem() throws IOException {
106 | FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
107 |
108 | // Just some random operations to verify that basic things work on the created file system.
109 | writeAndRead(fs, "foo.txt", "blah");
110 |
111 | return fs;
112 | }
113 |
114 | private static void writeAndRead(FileSystem fs, String path, String text) throws IOException {
115 | Path p = fs.getPath(path);
116 | Files.write(p, ImmutableList.of(text), UTF_8);
117 | List lines = Files.readAllLines(p, UTF_8);
118 | assertEquals(text, lines.get(0));
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/DosAttributeProviderTest.java:
--------------------------------------------------------------------------------
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.truth.Truth.assertThat;
20 | import static org.junit.Assert.assertNotNull;
21 |
22 | import com.google.common.collect.ImmutableList;
23 | import com.google.common.collect.ImmutableMap;
24 | import com.google.common.collect.ImmutableSet;
25 | import java.io.IOException;
26 | import java.nio.file.attribute.DosFileAttributeView;
27 | import java.nio.file.attribute.DosFileAttributes;
28 | import java.nio.file.attribute.FileAttributeView;
29 | import java.nio.file.attribute.FileTime;
30 | import java.util.Set;
31 | import org.junit.Test;
32 | import org.junit.runner.RunWith;
33 | import org.junit.runners.JUnit4;
34 |
35 | /**
36 | * Tests for {@link DosAttributeProvider}.
37 | *
38 | * @author Colin Decker
39 | */
40 | @RunWith(JUnit4.class)
41 | public class DosAttributeProviderTest extends AbstractAttributeProviderTest {
42 |
43 | private static final ImmutableList DOS_ATTRIBUTES =
44 | ImmutableList.of("hidden", "archive", "readonly", "system");
45 |
46 | @Override
47 | protected DosAttributeProvider createProvider() {
48 | return new DosAttributeProvider();
49 | }
50 |
51 | @Override
52 | protected Set extends AttributeProvider> createInheritedProviders() {
53 | return ImmutableSet.of(new BasicAttributeProvider(), new OwnerAttributeProvider());
54 | }
55 |
56 | @Test
57 | public void testInitialAttributes() {
58 | for (String attribute : DOS_ATTRIBUTES) {
59 | assertThat(provider.get(file, attribute)).isEqualTo(false);
60 | }
61 | }
62 |
63 | @Test
64 | public void testSet() {
65 | for (String attribute : DOS_ATTRIBUTES) {
66 | assertSetAndGetSucceeds(attribute, true);
67 | assertSetFailsOnCreate(attribute, true);
68 | }
69 | }
70 |
71 | @Test
72 | public void testView() throws IOException {
73 | DosFileAttributeView view =
74 | provider.view(
75 | fileLookup(),
76 | ImmutableMap.of(
77 | "basic", new BasicAttributeProvider().view(fileLookup(), NO_INHERITED_VIEWS)));
78 | assertNotNull(view);
79 |
80 | assertThat(view.name()).isEqualTo("dos");
81 |
82 | DosFileAttributes attrs = view.readAttributes();
83 | assertThat(attrs.isHidden()).isFalse();
84 | assertThat(attrs.isArchive()).isFalse();
85 | assertThat(attrs.isReadOnly()).isFalse();
86 | assertThat(attrs.isSystem()).isFalse();
87 |
88 | view.setArchive(true);
89 | view.setReadOnly(true);
90 | view.setHidden(true);
91 | view.setSystem(false);
92 |
93 | assertThat(attrs.isHidden()).isFalse();
94 | assertThat(attrs.isArchive()).isFalse();
95 | assertThat(attrs.isReadOnly()).isFalse();
96 |
97 | attrs = view.readAttributes();
98 | assertThat(attrs.isHidden()).isTrue();
99 | assertThat(attrs.isArchive()).isTrue();
100 | assertThat(attrs.isReadOnly()).isTrue();
101 | assertThat(attrs.isSystem()).isFalse();
102 |
103 | view.setTimes(FileTime.fromMillis(0L), null, null);
104 | assertThat(view.readAttributes().lastModifiedTime()).isEqualTo(FileTime.fromMillis(0L));
105 | }
106 |
107 | @Test
108 | public void testAttributes() {
109 | DosFileAttributes attrs = provider.readAttributes(file);
110 | assertThat(attrs.isHidden()).isFalse();
111 | assertThat(attrs.isArchive()).isFalse();
112 | assertThat(attrs.isReadOnly()).isFalse();
113 | assertThat(attrs.isSystem()).isFalse();
114 |
115 | file.setAttribute("dos", "hidden", true);
116 |
117 | attrs = provider.readAttributes(file);
118 | assertThat(attrs.isHidden()).isTrue();
119 | assertThat(attrs.isArchive()).isFalse();
120 | assertThat(attrs.isReadOnly()).isFalse();
121 | assertThat(attrs.isSystem()).isFalse();
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/FakeFileTimeSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 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 com.google.errorprone.annotations.CanIgnoreReturnValue;
20 | import java.nio.file.attribute.FileTime;
21 | import java.time.Duration;
22 | import java.time.Instant;
23 | import java.util.Random;
24 |
25 | /** Fake implementation of {@link FileTimeSource}. */
26 | final class FakeFileTimeSource implements FileTimeSource {
27 |
28 | private final Random random = new Random(System.currentTimeMillis());
29 | private Instant now;
30 |
31 | FakeFileTimeSource() {
32 | randomize();
33 | }
34 |
35 | @CanIgnoreReturnValue
36 | FakeFileTimeSource randomize() {
37 | now =
38 | Instant.ofEpochSecond(
39 | random
40 | .longs(Instant.MIN.getEpochSecond(), Instant.MAX.getEpochSecond())
41 | .findAny()
42 | .getAsLong(),
43 | random.nextInt(1_000_000_000));
44 | return this;
45 | }
46 |
47 | @CanIgnoreReturnValue
48 | FakeFileTimeSource advance(Duration duration) {
49 | this.now = now.plus(duration);
50 | return this;
51 | }
52 |
53 | @Override
54 | public FileTime now() {
55 | return FileTime.from(now);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/FileFactoryTest.java:
--------------------------------------------------------------------------------
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.truth.Truth.assertThat;
20 |
21 | import org.junit.Before;
22 | import org.junit.Test;
23 | import org.junit.runner.RunWith;
24 | import org.junit.runners.JUnit4;
25 |
26 | /**
27 | * Tests for {@link FileFactory}.
28 | *
29 | * @author Colin Decker
30 | */
31 | @RunWith(JUnit4.class)
32 | public class FileFactoryTest {
33 |
34 | private final FakeFileTimeSource fileTimeSource = new FakeFileTimeSource();
35 |
36 | private FileFactory factory;
37 |
38 | @Before
39 | public void setUp() {
40 | factory = new FileFactory(new HeapDisk(2, 2, 0), fileTimeSource);
41 | }
42 |
43 | @Test
44 | public void testCreateFiles_basic() {
45 | File file = factory.createDirectory();
46 | assertThat(file.id()).isEqualTo(0L);
47 | assertThat(file.isDirectory()).isTrue();
48 | assertThat(file.getCreationTime()).isEqualTo(fileTimeSource.now());
49 |
50 | fileTimeSource.randomize();
51 | file = factory.createRegularFile();
52 | assertThat(file.id()).isEqualTo(1L);
53 | assertThat(file.isRegularFile()).isTrue();
54 | assertThat(file.getCreationTime()).isEqualTo(fileTimeSource.now());
55 |
56 | fileTimeSource.randomize();
57 | file = factory.createSymbolicLink(fakePath());
58 | assertThat(file.id()).isEqualTo(2L);
59 | assertThat(file.isSymbolicLink()).isTrue();
60 | assertThat(file.getCreationTime()).isEqualTo(fileTimeSource.now());
61 | }
62 |
63 | @Test
64 | public void testCreateFiles_withSupplier() {
65 | File file = factory.directoryCreator().get();
66 | assertThat(file.id()).isEqualTo(0L);
67 | assertThat(file.isDirectory()).isTrue();
68 | assertThat(file.getCreationTime()).isEqualTo(fileTimeSource.now());
69 |
70 | fileTimeSource.randomize();
71 | file = factory.regularFileCreator().get();
72 | assertThat(file.id()).isEqualTo(1L);
73 | assertThat(file.isRegularFile()).isTrue();
74 | assertThat(file.getCreationTime()).isEqualTo(fileTimeSource.now());
75 |
76 | fileTimeSource.randomize();
77 | file = factory.symbolicLinkCreator(fakePath()).get();
78 | assertThat(file.id()).isEqualTo(2L);
79 | assertThat(file.isSymbolicLink()).isTrue();
80 | assertThat(file.getCreationTime()).isEqualTo(fileTimeSource.now());
81 | }
82 |
83 | static JimfsPath fakePath() {
84 | return PathServiceTest.fakeUnixPathService().emptyPath();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/FileSystemStateTest.java:
--------------------------------------------------------------------------------
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.truth.Truth.assertThat;
20 | import static org.junit.Assert.assertEquals;
21 | import static org.junit.Assert.assertFalse;
22 | import static org.junit.Assert.assertTrue;
23 | import static org.junit.Assert.fail;
24 |
25 | import com.google.common.collect.ImmutableList;
26 | import com.google.common.collect.ImmutableSet;
27 | import java.io.Closeable;
28 | import java.io.IOException;
29 | import java.nio.file.ClosedFileSystemException;
30 | import java.time.Duration;
31 | import java.util.List;
32 | import org.junit.Test;
33 | import org.junit.runner.RunWith;
34 | import org.junit.runners.JUnit4;
35 |
36 | /**
37 | * Tests for {@link FileSystemState}.
38 | *
39 | * @author Colin Decker
40 | */
41 | @RunWith(JUnit4.class)
42 | public class FileSystemStateTest {
43 |
44 | private final TestRunnable onClose = new TestRunnable();
45 | private final FakeFileTimeSource fileTimeSource = new FakeFileTimeSource();
46 | private final FileSystemState state = new FileSystemState(fileTimeSource, onClose);
47 |
48 | @Test
49 | public void testIsOpen() throws IOException {
50 | assertTrue(state.isOpen());
51 | state.close();
52 | assertFalse(state.isOpen());
53 | }
54 |
55 | @Test
56 | public void testCheckOpen() throws IOException {
57 | state.checkOpen(); // does not throw
58 | state.close();
59 | try {
60 | state.checkOpen();
61 | fail();
62 | } catch (ClosedFileSystemException expected) {
63 | }
64 | }
65 |
66 | @Test
67 | public void testNow() {
68 | assertThat(state.now()).isEqualTo(fileTimeSource.now());
69 | fileTimeSource.advance(Duration.ofSeconds(1));
70 | assertThat(state.now()).isEqualTo(fileTimeSource.now());
71 | }
72 |
73 | @Test
74 | public void testClose_callsOnCloseRunnable() throws IOException {
75 | assertEquals(0, onClose.runCount);
76 | state.close();
77 | assertEquals(1, onClose.runCount);
78 | }
79 |
80 | @Test
81 | public void testClose_multipleTimesDoNothing() throws IOException {
82 | state.close();
83 | assertEquals(1, onClose.runCount);
84 | state.close();
85 | state.close();
86 | assertEquals(1, onClose.runCount);
87 | }
88 |
89 | @Test
90 | public void testClose_registeredResourceIsClosed() throws IOException {
91 | TestCloseable resource = new TestCloseable();
92 | state.register(resource);
93 | assertFalse(resource.closed);
94 | state.close();
95 | assertTrue(resource.closed);
96 | }
97 |
98 | @Test
99 | public void testClose_unregisteredResourceIsNotClosed() throws IOException {
100 | TestCloseable resource = new TestCloseable();
101 | state.register(resource);
102 | assertFalse(resource.closed);
103 | state.unregister(resource);
104 | state.close();
105 | assertFalse(resource.closed);
106 | }
107 |
108 | @Test
109 | public void testClose_multipleRegisteredResourcesAreClosed() throws IOException {
110 | List resources =
111 | ImmutableList.of(new TestCloseable(), new TestCloseable(), new TestCloseable());
112 | for (TestCloseable resource : resources) {
113 | state.register(resource);
114 | assertFalse(resource.closed);
115 | }
116 | state.close();
117 | for (TestCloseable resource : resources) {
118 | assertTrue(resource.closed);
119 | }
120 | }
121 |
122 | @Test
123 | public void testClose_resourcesThatThrowOnClose() {
124 | List resources =
125 | ImmutableList.of(
126 | new TestCloseable(),
127 | new ThrowsOnClose("a"),
128 | new TestCloseable(),
129 | new ThrowsOnClose("b"),
130 | new ThrowsOnClose("c"),
131 | new TestCloseable(),
132 | new TestCloseable());
133 | for (TestCloseable resource : resources) {
134 | state.register(resource);
135 | assertFalse(resource.closed);
136 | }
137 |
138 | try {
139 | state.close();
140 | fail();
141 | } catch (IOException expected) {
142 | Throwable[] suppressed = expected.getSuppressed();
143 | assertEquals(2, suppressed.length);
144 | ImmutableSet messages =
145 | ImmutableSet.of(
146 | expected.getMessage(), suppressed[0].getMessage(), suppressed[1].getMessage());
147 | assertEquals(ImmutableSet.of("a", "b", "c"), messages);
148 | }
149 |
150 | for (TestCloseable resource : resources) {
151 | assertTrue(resource.closed);
152 | }
153 | }
154 |
155 | private static class TestCloseable implements Closeable {
156 |
157 | boolean closed = false;
158 |
159 | @Override
160 | public void close() throws IOException {
161 | closed = true;
162 | }
163 | }
164 |
165 | private static final class TestRunnable implements Runnable {
166 | int runCount = 0;
167 |
168 | @Override
169 | public void run() {
170 | runCount++;
171 | }
172 | }
173 |
174 | private static class ThrowsOnClose extends TestCloseable {
175 |
176 | private final String string;
177 |
178 | private ThrowsOnClose(String string) {
179 | this.string = string;
180 | }
181 |
182 | @Override
183 | public void close() throws IOException {
184 | super.close();
185 | throw new IOException(string);
186 | }
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/FileTest.java:
--------------------------------------------------------------------------------
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.jimfs.FileFactoryTest.fakePath;
20 | import static com.google.common.jimfs.TestUtils.regularFile;
21 | import static com.google.common.truth.Truth.assertThat;
22 |
23 | import org.junit.Test;
24 | import org.junit.runner.RunWith;
25 | import org.junit.runners.JUnit4;
26 |
27 | /**
28 | * Tests for {@link File}.
29 | *
30 | * @author Colin Decker
31 | */
32 | @RunWith(JUnit4.class)
33 | public class FileTest {
34 |
35 | private final FakeFileTimeSource fileTimeSource = new FakeFileTimeSource();
36 |
37 | @Test
38 | public void testAttributes() {
39 | // these methods are basically just thin wrappers around a map, so no need to test too
40 | // thoroughly
41 |
42 | File file = RegularFile.create(0, fileTimeSource.now(), new HeapDisk(10, 10, 10));
43 |
44 | assertThat(file.getAttributeKeys()).isEmpty();
45 | assertThat(file.getAttribute("foo", "foo")).isNull();
46 |
47 | file.deleteAttribute("foo", "foo"); // doesn't throw
48 |
49 | file.setAttribute("foo", "foo", "foo");
50 |
51 | assertThat(file.getAttributeKeys()).containsExactly("foo:foo");
52 | assertThat(file.getAttribute("foo", "foo")).isEqualTo("foo");
53 |
54 | file.deleteAttribute("foo", "foo");
55 |
56 | assertThat(file.getAttributeKeys()).isEmpty();
57 | assertThat(file.getAttribute("foo", "foo")).isNull();
58 | }
59 |
60 | @Test
61 | public void testFileBasics() {
62 | File file = regularFile(0);
63 |
64 | assertThat(file.id()).isEqualTo(0);
65 | assertThat(file.links()).isEqualTo(0);
66 | }
67 |
68 | @Test
69 | public void testDirectory() {
70 | File file = Directory.create(0, fileTimeSource.now());
71 | assertThat(file.isDirectory()).isTrue();
72 | assertThat(file.isRegularFile()).isFalse();
73 | assertThat(file.isSymbolicLink()).isFalse();
74 | }
75 |
76 | @Test
77 | public void testRegularFile() {
78 | File file = regularFile(10);
79 | assertThat(file.isDirectory()).isFalse();
80 | assertThat(file.isRegularFile()).isTrue();
81 | assertThat(file.isSymbolicLink()).isFalse();
82 | }
83 |
84 | @Test
85 | public void testSymbolicLink() {
86 | File file = SymbolicLink.create(0, fileTimeSource.now(), fakePath());
87 | assertThat(file.isDirectory()).isFalse();
88 | assertThat(file.isRegularFile()).isFalse();
89 | assertThat(file.isSymbolicLink()).isTrue();
90 | }
91 |
92 | @Test
93 | public void testRootDirectory() {
94 | Directory file = Directory.createRoot(0, fileTimeSource.now(), Name.simple("/"));
95 | assertThat(file.isRootDirectory()).isTrue();
96 |
97 | Directory otherFile = Directory.createRoot(1, fileTimeSource.now(), Name.simple("$"));
98 | assertThat(otherFile.isRootDirectory()).isTrue();
99 | }
100 |
101 | @Test
102 | public void testLinkAndUnlink() {
103 | File file = regularFile(0);
104 | assertThat(file.links()).isEqualTo(0);
105 |
106 | file.incrementLinkCount();
107 | assertThat(file.links()).isEqualTo(1);
108 |
109 | file.incrementLinkCount();
110 | assertThat(file.links()).isEqualTo(2);
111 |
112 | file.decrementLinkCount();
113 | assertThat(file.links()).isEqualTo(1);
114 |
115 | file.decrementLinkCount();
116 | assertThat(file.links()).isEqualTo(0);
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/NameTest.java:
--------------------------------------------------------------------------------
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.truth.Truth.assertThat;
20 |
21 | import org.junit.Test;
22 | import org.junit.runner.RunWith;
23 | import org.junit.runners.JUnit4;
24 |
25 | /**
26 | * Tests for {@link Name}.
27 | *
28 | * @author Colin Decker
29 | */
30 | @RunWith(JUnit4.class)
31 | public class NameTest {
32 |
33 | @Test
34 | public void testNames() {
35 | assertThat(Name.create("foo", "foo")).isEqualTo(Name.create("foo", "foo"));
36 | assertThat(Name.create("FOO", "foo")).isEqualTo(Name.create("foo", "foo"));
37 | assertThat(Name.create("FOO", "foo")).isNotEqualTo(Name.create("FOO", "FOO"));
38 |
39 | assertThat(Name.create("a", "b").toString()).isEqualTo("a");
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/OwnerAttributeProviderTest.java:
--------------------------------------------------------------------------------
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.jimfs.UserLookupService.createUserPrincipal;
20 | import static com.google.common.truth.Truth.assertThat;
21 |
22 | import com.google.common.collect.ImmutableSet;
23 | import java.io.IOException;
24 | import java.nio.file.attribute.FileOwnerAttributeView;
25 | import java.util.Set;
26 | import org.junit.Test;
27 | import org.junit.runner.RunWith;
28 | import org.junit.runners.JUnit4;
29 |
30 | /**
31 | * Tests for {@link OwnerAttributeProvider}.
32 | *
33 | * @author Colin Decker
34 | */
35 | @RunWith(JUnit4.class)
36 | public class OwnerAttributeProviderTest
37 | extends AbstractAttributeProviderTest {
38 |
39 | @Override
40 | protected OwnerAttributeProvider createProvider() {
41 | return new OwnerAttributeProvider();
42 | }
43 |
44 | @Override
45 | protected Set extends AttributeProvider> createInheritedProviders() {
46 | return ImmutableSet.of();
47 | }
48 |
49 | @Test
50 | public void testInitialAttributes() {
51 | assertThat(provider.get(file, "owner")).isEqualTo(createUserPrincipal("user"));
52 | }
53 |
54 | @Test
55 | public void testSet() {
56 | assertSetAndGetSucceeds("owner", createUserPrincipal("user"));
57 | assertSetFailsOnCreate("owner", createUserPrincipal("user"));
58 |
59 | // invalid type
60 | assertSetFails("owner", "root");
61 | }
62 |
63 | @Test
64 | public void testView() throws IOException {
65 | FileOwnerAttributeView view = provider.view(fileLookup(), NO_INHERITED_VIEWS);
66 | assertThat(view).isNotNull();
67 |
68 | assertThat(view.name()).isEqualTo("owner");
69 | assertThat(view.getOwner()).isEqualTo(createUserPrincipal("user"));
70 |
71 | view.setOwner(createUserPrincipal("root"));
72 | assertThat(view.getOwner()).isEqualTo(createUserPrincipal("root"));
73 | assertThat(file.getAttribute("owner", "owner")).isEqualTo(createUserPrincipal("root"));
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/PathTypeTest.java:
--------------------------------------------------------------------------------
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.checkArgument;
20 | import static com.google.common.truth.Truth.assertThat;
21 |
22 | import com.google.common.collect.ImmutableList;
23 | import com.google.common.jimfs.PathType.ParseResult;
24 | import java.net.URI;
25 | import org.jspecify.annotations.Nullable;
26 | import org.junit.Test;
27 | import org.junit.runner.RunWith;
28 | import org.junit.runners.JUnit4;
29 |
30 | /**
31 | * Tests for {@link PathType}.
32 | *
33 | * @author Colin Decker
34 | */
35 | @RunWith(JUnit4.class)
36 | public class PathTypeTest {
37 |
38 | private static final FakePathType type = new FakePathType();
39 | static final URI fileSystemUri = URI.create("jimfs://foo");
40 |
41 | @Test
42 | public void testBasicProperties() {
43 | assertThat(type.getSeparator()).isEqualTo("/");
44 | assertThat(type.getOtherSeparators()).isEqualTo("\\");
45 | }
46 |
47 | @Test
48 | public void testParsePath() {
49 | ParseResult path = type.parsePath("foo/bar/baz/one\\two");
50 | assertParseResult(path, null, "foo", "bar", "baz", "one", "two");
51 |
52 | ParseResult path2 = type.parsePath("$one//\\two");
53 | assertParseResult(path2, "$", "one", "two");
54 | }
55 |
56 | @Test
57 | public void testToString() {
58 | ParseResult path = type.parsePath("foo/bar\\baz");
59 | assertThat(type.toString(path.root(), path.names())).isEqualTo("foo/bar/baz");
60 |
61 | ParseResult path2 = type.parsePath("$/foo/bar");
62 | assertThat(type.toString(path2.root(), path2.names())).isEqualTo("$foo/bar");
63 | }
64 |
65 | @Test
66 | public void testToUri() {
67 | URI fileUri = type.toUri(fileSystemUri, "$", ImmutableList.of("foo", "bar"), false);
68 | assertThat(fileUri.toString()).isEqualTo("jimfs://foo/$/foo/bar");
69 | assertThat(fileUri.getPath()).isEqualTo("/$/foo/bar");
70 |
71 | URI directoryUri = type.toUri(fileSystemUri, "$", ImmutableList.of("foo", "bar"), true);
72 | assertThat(directoryUri.toString()).isEqualTo("jimfs://foo/$/foo/bar/");
73 | assertThat(directoryUri.getPath()).isEqualTo("/$/foo/bar/");
74 |
75 | URI rootUri = type.toUri(fileSystemUri, "$", ImmutableList.of(), true);
76 | assertThat(rootUri.toString()).isEqualTo("jimfs://foo/$/");
77 | assertThat(rootUri.getPath()).isEqualTo("/$/");
78 | }
79 |
80 | @Test
81 | public void testToUri_escaping() {
82 | URI fileUri = type.toUri(fileSystemUri, "$", ImmutableList.of("foo", "bar baz"), false);
83 | assertThat(fileUri.toString()).isEqualTo("jimfs://foo/$/foo/bar%20baz");
84 | assertThat(fileUri.getRawPath()).isEqualTo("/$/foo/bar%20baz");
85 | assertThat(fileUri.getPath()).isEqualTo("/$/foo/bar baz");
86 | }
87 |
88 | @Test
89 | public void testUriRoundTrips() {
90 | assertUriRoundTripsCorrectly(type, "$");
91 | assertUriRoundTripsCorrectly(type, "$foo");
92 | assertUriRoundTripsCorrectly(type, "$foo/bar/baz");
93 | assertUriRoundTripsCorrectly(type, "$foo bar");
94 | assertUriRoundTripsCorrectly(type, "$foo/bar baz");
95 | }
96 |
97 | static void assertParseResult(ParseResult result, @Nullable String root, String... names) {
98 | assertThat(result.root()).isEqualTo(root);
99 | assertThat(result.names()).containsExactly((Object[]) names).inOrder();
100 | }
101 |
102 | static void assertUriRoundTripsCorrectly(PathType type, String path) {
103 | ParseResult result = type.parsePath(path);
104 | URI uri = type.toUri(fileSystemUri, result.root(), result.names(), false);
105 | ParseResult parsedUri = type.fromUri(uri);
106 | assertThat(parsedUri.root()).isEqualTo(result.root());
107 | assertThat(parsedUri.names()).containsExactlyElementsIn(result.names()).inOrder();
108 | }
109 |
110 | /** Arbitrary path type with $ as the root, / as the separator and \ as an alternate separator. */
111 | private static final class FakePathType extends PathType {
112 |
113 | protected FakePathType() {
114 | super(false, '/', '\\');
115 | }
116 |
117 | @Override
118 | public ParseResult parsePath(String path) {
119 | String root = null;
120 | if (path.startsWith("$")) {
121 | root = "$";
122 | path = path.substring(1);
123 | }
124 |
125 | return new ParseResult(root, splitter().split(path));
126 | }
127 |
128 | @Override
129 | public String toString(@Nullable String root, Iterable names) {
130 | StringBuilder builder = new StringBuilder();
131 | if (root != null) {
132 | builder.append(root);
133 | }
134 | joiner().appendTo(builder, names);
135 | return builder.toString();
136 | }
137 |
138 | @Override
139 | public String toUriPath(String root, Iterable names, boolean directory) {
140 | StringBuilder builder = new StringBuilder();
141 | builder.append('/').append(root);
142 | for (String name : names) {
143 | builder.append('/').append(name);
144 | }
145 | if (directory) {
146 | builder.append('/');
147 | }
148 | return builder.toString();
149 | }
150 |
151 | @Override
152 | public ParseResult parseUriPath(String uriPath) {
153 | checkArgument(uriPath.startsWith("/$"), "uriPath (%s) must start with /$", uriPath);
154 | return parsePath(uriPath.substring(1));
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/PosixAttributeProviderTest.java:
--------------------------------------------------------------------------------
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.jimfs.UserLookupService.createGroupPrincipal;
20 | import static com.google.common.jimfs.UserLookupService.createUserPrincipal;
21 | import static com.google.common.truth.Truth.assertThat;
22 | import static org.junit.Assert.assertNotNull;
23 |
24 | import com.google.common.collect.ImmutableList;
25 | import com.google.common.collect.ImmutableMap;
26 | import com.google.common.collect.ImmutableSet;
27 | import java.io.IOException;
28 | import java.nio.file.attribute.PosixFileAttributeView;
29 | import java.nio.file.attribute.PosixFileAttributes;
30 | import java.nio.file.attribute.PosixFilePermission;
31 | import java.nio.file.attribute.PosixFilePermissions;
32 | import java.util.Set;
33 | import org.junit.Test;
34 | import org.junit.runner.RunWith;
35 | import org.junit.runners.JUnit4;
36 |
37 | /**
38 | * Tests for {@link PosixAttributeProvider}.
39 | *
40 | * @author Colin Decker
41 | */
42 | @RunWith(JUnit4.class)
43 | public class PosixAttributeProviderTest
44 | extends AbstractAttributeProviderTest {
45 |
46 | @Override
47 | protected PosixAttributeProvider createProvider() {
48 | return new PosixAttributeProvider();
49 | }
50 |
51 | @Override
52 | protected Set extends AttributeProvider> createInheritedProviders() {
53 | return ImmutableSet.of(new BasicAttributeProvider(), new OwnerAttributeProvider());
54 | }
55 |
56 | @Test
57 | public void testInitialAttributes() {
58 | assertContainsAll(
59 | file,
60 | ImmutableMap.of(
61 | "group", createGroupPrincipal("group"),
62 | "permissions", PosixFilePermissions.fromString("rw-r--r--")));
63 | }
64 |
65 | @Test
66 | public void testSet() {
67 | assertSetAndGetSucceeds("group", createGroupPrincipal("foo"));
68 | assertSetAndGetSucceeds("permissions", PosixFilePermissions.fromString("rwxrwxrwx"));
69 |
70 | // invalid types
71 | assertSetFails("permissions", ImmutableList.of(PosixFilePermission.GROUP_EXECUTE));
72 | assertSetFails("permissions", ImmutableSet.of("foo"));
73 | }
74 |
75 | @Test
76 | public void testSetOnCreate() {
77 | assertSetAndGetSucceedsOnCreate("permissions", PosixFilePermissions.fromString("rwxrwxrwx"));
78 | assertSetFailsOnCreate("group", createGroupPrincipal("foo"));
79 | }
80 |
81 | @Test
82 | public void testView() throws IOException {
83 | file.setAttribute("owner", "owner", createUserPrincipal("user"));
84 |
85 | PosixFileAttributeView view =
86 | provider.view(
87 | fileLookup(),
88 | ImmutableMap.of(
89 | "basic", new BasicAttributeProvider().view(fileLookup(), NO_INHERITED_VIEWS),
90 | "owner", new OwnerAttributeProvider().view(fileLookup(), NO_INHERITED_VIEWS)));
91 | assertNotNull(view);
92 |
93 | assertThat(view.name()).isEqualTo("posix");
94 | assertThat(view.getOwner()).isEqualTo(createUserPrincipal("user"));
95 |
96 | PosixFileAttributes attrs = view.readAttributes();
97 | assertThat(attrs.fileKey()).isEqualTo(0);
98 | assertThat(attrs.owner()).isEqualTo(createUserPrincipal("user"));
99 | assertThat(attrs.group()).isEqualTo(createGroupPrincipal("group"));
100 | assertThat(attrs.permissions()).isEqualTo(PosixFilePermissions.fromString("rw-r--r--"));
101 |
102 | view.setOwner(createUserPrincipal("root"));
103 | assertThat(view.getOwner()).isEqualTo(createUserPrincipal("root"));
104 | assertThat(file.getAttribute("owner", "owner")).isEqualTo(createUserPrincipal("root"));
105 |
106 | view.setGroup(createGroupPrincipal("root"));
107 | assertThat(view.readAttributes().group()).isEqualTo(createGroupPrincipal("root"));
108 | assertThat(file.getAttribute("posix", "group")).isEqualTo(createGroupPrincipal("root"));
109 |
110 | view.setPermissions(PosixFilePermissions.fromString("rwx------"));
111 | assertThat(view.readAttributes().permissions())
112 | .isEqualTo(PosixFilePermissions.fromString("rwx------"));
113 | assertThat(file.getAttribute("posix", "permissions"))
114 | .isEqualTo(PosixFilePermissions.fromString("rwx------"));
115 | }
116 |
117 | @Test
118 | public void testAttributes() {
119 | PosixFileAttributes attrs = provider.readAttributes(file);
120 | assertThat(attrs.permissions()).isEqualTo(PosixFilePermissions.fromString("rw-r--r--"));
121 | assertThat(attrs.group()).isEqualTo(createGroupPrincipal("group"));
122 | assertThat(attrs.fileKey()).isEqualTo(0);
123 | }
124 |
125 | @Test
126 | public void testAttributes_permissionsAreModifiable() {
127 | Set permissions = provider.readAttributes(file).permissions();
128 | permissions.add(PosixFilePermission.OWNER_EXECUTE);
129 | assertThat(permissions).isEqualTo(PosixFilePermissions.fromString("rwxr--r--"));
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/RegexGlobMatcherTest.java:
--------------------------------------------------------------------------------
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 org.junit.Assert.assertEquals;
20 |
21 | import com.google.common.collect.ImmutableSet;
22 | import java.nio.file.FileSystem;
23 | import java.nio.file.FileSystems;
24 | import java.nio.file.PathMatcher;
25 | import java.util.regex.Pattern;
26 | import org.junit.Test;
27 | import org.junit.runner.RunWith;
28 | import org.junit.runners.JUnit4;
29 |
30 | /**
31 | * Tests for {@link PathMatcher} instances created by {@link GlobToRegex}.
32 | *
33 | * @author Colin Decker
34 | */
35 | @RunWith(JUnit4.class)
36 | public class RegexGlobMatcherTest extends AbstractGlobMatcherTest {
37 |
38 | @Override
39 | protected PathMatcher matcher(String pattern) {
40 | return PathMatchers.getPathMatcher(
41 | "glob:" + pattern, "/", ImmutableSet.of());
42 | }
43 |
44 | @Override
45 | protected PathMatcher realMatcher(String pattern) {
46 | FileSystem defaultFileSystem = FileSystems.getDefault();
47 | if ("/".equals(defaultFileSystem.getSeparator())) {
48 | return defaultFileSystem.getPathMatcher("glob:" + pattern);
49 | }
50 | return null;
51 | }
52 |
53 | @Test
54 | public void testRegexTranslation() {
55 | assertGlobRegexIs("foo", "foo");
56 | assertGlobRegexIs("/", "/");
57 | assertGlobRegexIs("?", "[^/]");
58 | assertGlobRegexIs("*", "[^/]*");
59 | assertGlobRegexIs("**", ".*");
60 | assertGlobRegexIs("/foo", "/foo");
61 | assertGlobRegexIs("?oo", "[^/]oo");
62 | assertGlobRegexIs("*oo", "[^/]*oo");
63 | assertGlobRegexIs("**/*.java", ".*/[^/]*\\.java");
64 | assertGlobRegexIs("[a-z]", "[[^/]&&[a-z]]");
65 | assertGlobRegexIs("[!a-z]", "[[^/]&&[^a-z]]");
66 | assertGlobRegexIs("[-a-z]", "[[^/]&&[-a-z]]");
67 | assertGlobRegexIs("[!-a-z]", "[[^/]&&[^-a-z]]");
68 | assertGlobRegexIs("{a,b,c}", "(a|b|c)");
69 | assertGlobRegexIs("{?oo,[A-Z]*,foo/**}", "([^/]oo|[[^/]&&[A-Z]][^/]*|foo/.*)");
70 | }
71 |
72 | @Test
73 | public void testRegexEscaping() {
74 | assertGlobRegexIs("(", "\\(");
75 | assertGlobRegexIs(".", "\\.");
76 | assertGlobRegexIs("^", "\\^");
77 | assertGlobRegexIs("$", "\\$");
78 | assertGlobRegexIs("+", "\\+");
79 | assertGlobRegexIs("\\\\", "\\\\");
80 | assertGlobRegexIs("]", "\\]");
81 | assertGlobRegexIs(")", "\\)");
82 | assertGlobRegexIs("}", "\\}");
83 | }
84 |
85 | @Test
86 | public void testRegexTranslationWithMultipleSeparators() {
87 | assertGlobRegexIs("?", "[^\\\\/]", "\\/");
88 | assertGlobRegexIs("*", "[^\\\\/]*", "\\/");
89 | assertGlobRegexIs("/", "[\\\\/]", "\\/");
90 | assertGlobRegexIs("\\\\", "[\\\\/]", "\\/");
91 | }
92 |
93 | private static void assertGlobRegexIs(String glob, String regex) {
94 | assertGlobRegexIs(glob, regex, "/");
95 | }
96 |
97 | private static void assertGlobRegexIs(String glob, String regex, String separators) {
98 | assertEquals(regex, GlobToRegex.toRegex(glob, separators));
99 | Pattern.compile(regex); // ensure the regex syntax is valid
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/TestAttributeView.java:
--------------------------------------------------------------------------------
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 java.io.IOException;
20 | import java.nio.file.attribute.BasicFileAttributeView;
21 |
22 | /** @author Colin Decker */
23 | public interface TestAttributeView extends BasicFileAttributeView {
24 |
25 | TestAttributes readAttributes() throws IOException;
26 |
27 | void setBar(long bar) throws IOException;
28 |
29 | void setBaz(int baz) throws IOException;
30 | }
31 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/TestAttributes.java:
--------------------------------------------------------------------------------
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 java.nio.file.attribute.BasicFileAttributes;
20 |
21 | /** @author Colin Decker */
22 | public interface TestAttributes extends BasicFileAttributes {
23 |
24 | String foo();
25 |
26 | long bar();
27 |
28 | int baz();
29 | }
30 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/TestUtils.java:
--------------------------------------------------------------------------------
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 java.nio.file.LinkOption.NOFOLLOW_LINKS;
20 | import static org.junit.Assert.assertFalse;
21 |
22 | import com.google.common.collect.ImmutableList;
23 | import java.io.IOException;
24 | import java.nio.ByteBuffer;
25 | import java.nio.file.DirectoryStream;
26 | import java.nio.file.Files;
27 | import java.nio.file.Path;
28 | import java.util.ArrayList;
29 | import java.util.Arrays;
30 | import java.util.HashSet;
31 | import java.util.List;
32 | import java.util.Objects;
33 | import java.util.Set;
34 |
35 | /** @author Colin Decker */
36 | public final class TestUtils {
37 |
38 | private TestUtils() {}
39 |
40 | public static byte[] bytes(int... bytes) {
41 | byte[] result = new byte[bytes.length];
42 | for (int i = 0; i < bytes.length; i++) {
43 | result[i] = (byte) bytes[i];
44 | }
45 | return result;
46 | }
47 |
48 | public static byte[] bytes(String bytes) {
49 | byte[] result = new byte[bytes.length()];
50 | for (int i = 0; i < bytes.length(); i++) {
51 | String digit = bytes.substring(i, i + 1);
52 | result[i] = Byte.parseByte(digit);
53 | }
54 | return result;
55 | }
56 |
57 | public static byte[] preFilledBytes(int length, int fillValue) {
58 | byte[] result = new byte[length];
59 | Arrays.fill(result, (byte) fillValue);
60 | return result;
61 | }
62 |
63 | public static byte[] preFilledBytes(int length) {
64 | byte[] bytes = new byte[length];
65 | for (int i = 0; i < length; i++) {
66 | bytes[i] = (byte) i;
67 | }
68 | return bytes;
69 | }
70 |
71 | public static ByteBuffer buffer(String bytes) {
72 | return ByteBuffer.wrap(bytes(bytes));
73 | }
74 |
75 | public static Iterable buffers(String... bytes) {
76 | List result = new ArrayList<>();
77 | for (String b : bytes) {
78 | result.add(buffer(b));
79 | }
80 | return result;
81 | }
82 |
83 | /** Returns a number of permutations of the given path that should all locate the same file. */
84 | public static Iterable permutations(Path path) throws IOException {
85 | Path workingDir = path.getFileSystem().getPath("").toRealPath();
86 | boolean directory = Files.isDirectory(path);
87 |
88 | Set results = new HashSet<>();
89 | results.add(path);
90 | if (path.isAbsolute()) {
91 | results.add(workingDir.relativize(path));
92 | } else {
93 | results.add(workingDir.resolve(path));
94 | }
95 | if (directory) {
96 | for (Path p : ImmutableList.copyOf(results)) {
97 | results.add(p.resolve("."));
98 | results.add(p.resolve(".").resolve("."));
99 | Path fileName = p.getFileName();
100 | if (fileName != null
101 | && !fileName.toString().equals(".")
102 | && !fileName.toString().equals("..")) {
103 | results.add(p.resolve("..").resolve(fileName));
104 | results.add(p.resolve("..").resolve(".").resolve(fileName));
105 | results.add(p.resolve("..").resolve(".").resolve(fileName).resolve("."));
106 | results.add(p.resolve(".").resolve("..").resolve(".").resolve(fileName));
107 | }
108 | }
109 |
110 | try (DirectoryStream stream = Files.newDirectoryStream(path)) {
111 | for (Path child : stream) {
112 | if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
113 | Path childName = child.getFileName();
114 | for (Path p : ImmutableList.copyOf(results)) {
115 | results.add(p.resolve(childName).resolve(".."));
116 | results.add(p.resolve(childName).resolve(".").resolve(".").resolve(".."));
117 | results.add(p.resolve(childName).resolve("..").resolve("."));
118 | results.add(
119 | p.resolve(childName).resolve("..").resolve(childName).resolve(".").resolve(".."));
120 | }
121 | break; // no need to add more than one child
122 | }
123 | }
124 | }
125 | }
126 | return results;
127 | }
128 |
129 | // equivalent to the Junit 4.11 method.
130 | public static void assertNotEquals(Object unexpected, Object actual) {
131 | assertFalse(
132 | "Values should be different. Actual: " + actual, Objects.equals(unexpected, actual));
133 | }
134 |
135 | static RegularFile regularFile(int size) {
136 | RegularFile file =
137 | RegularFile.create(0, new FakeFileTimeSource().now(), new HeapDisk(8096, 1000, 1000));
138 | try {
139 | file.write(0, new byte[size], 0, size);
140 | return file;
141 | } catch (IOException e) {
142 | throw new AssertionError(e);
143 | }
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/UnixAttributeProviderTest.java:
--------------------------------------------------------------------------------
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.jimfs.UserLookupService.createGroupPrincipal;
20 | import static com.google.common.jimfs.UserLookupService.createUserPrincipal;
21 | import static com.google.common.truth.Truth.assertThat;
22 |
23 | import com.google.common.collect.ImmutableSet;
24 | import java.nio.file.attribute.PosixFilePermissions;
25 | import java.util.Set;
26 | import org.junit.Test;
27 | import org.junit.runner.RunWith;
28 | import org.junit.runners.JUnit4;
29 |
30 | /**
31 | * Tests for {@link UnixAttributeProvider}.
32 | *
33 | * @author Colin Decker
34 | */
35 | @RunWith(JUnit4.class)
36 | @SuppressWarnings("OctalInteger")
37 | public class UnixAttributeProviderTest
38 | extends AbstractAttributeProviderTest {
39 |
40 | @Override
41 | protected UnixAttributeProvider createProvider() {
42 | return new UnixAttributeProvider();
43 | }
44 |
45 | @Override
46 | protected Set extends AttributeProvider> createInheritedProviders() {
47 | return ImmutableSet.of(
48 | new BasicAttributeProvider(), new OwnerAttributeProvider(), new PosixAttributeProvider());
49 | }
50 |
51 | @Test
52 | public void testInitialAttributes() {
53 | // unix provider relies on other providers to set their initial attributes
54 | file.setAttribute("owner", "owner", createUserPrincipal("foo"));
55 | file.setAttribute("posix", "group", createGroupPrincipal("bar"));
56 | file.setAttribute(
57 | "posix", "permissions", ImmutableSet.copyOf(PosixFilePermissions.fromString("rw-r--r--")));
58 |
59 | // these are pretty much meaningless here since they aren't properties this
60 | // file system actually has, so don't really care about the exact value of these
61 | assertThat(provider.get(file, "uid")).isInstanceOf(Integer.class);
62 | assertThat(provider.get(file, "gid")).isInstanceOf(Integer.class);
63 | assertThat(provider.get(file, "rdev")).isEqualTo(0L);
64 | assertThat(provider.get(file, "dev")).isEqualTo(1L);
65 | assertThat(provider.get(file, "ino")).isInstanceOf(Integer.class);
66 |
67 | // these have logical origins in attributes from other views
68 | assertThat(provider.get(file, "mode")).isEqualTo(0644); // rw-r--r--
69 | assertThat(provider.get(file, "ctime")).isEqualTo(file.getCreationTime());
70 |
71 | // this is based on a property this file system does actually have
72 | assertThat(provider.get(file, "nlink")).isEqualTo(1);
73 |
74 | file.incrementLinkCount();
75 | assertThat(provider.get(file, "nlink")).isEqualTo(2);
76 | file.decrementLinkCount();
77 | assertThat(provider.get(file, "nlink")).isEqualTo(1);
78 | }
79 |
80 | @Test
81 | public void testSet() {
82 | assertSetFails("unix:uid", 1);
83 | assertSetFails("unix:gid", 1);
84 | assertSetFails("unix:rdev", 1L);
85 | assertSetFails("unix:dev", 1L);
86 | assertSetFails("unix:ino", 1);
87 | assertSetFails("unix:mode", 1);
88 | assertSetFails("unix:ctime", 1L);
89 | assertSetFails("unix:nlink", 1);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/UnixPathTypeTest.java:
--------------------------------------------------------------------------------
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.jimfs.PathTypeTest.assertParseResult;
20 | import static com.google.common.jimfs.PathTypeTest.assertUriRoundTripsCorrectly;
21 | import static com.google.common.jimfs.PathTypeTest.fileSystemUri;
22 | import static com.google.common.truth.Truth.assertThat;
23 | import static org.junit.Assert.assertEquals;
24 | import static org.junit.Assert.fail;
25 |
26 | import com.google.common.collect.ImmutableList;
27 | import java.net.URI;
28 | import java.nio.file.InvalidPathException;
29 | import org.junit.Test;
30 | import org.junit.runner.RunWith;
31 | import org.junit.runners.JUnit4;
32 |
33 | /**
34 | * Tests for {@link UnixPathType}.
35 | *
36 | * @author Colin Decker
37 | */
38 | @RunWith(JUnit4.class)
39 | public class UnixPathTypeTest {
40 |
41 | @Test
42 | public void testUnix() {
43 | PathType unix = PathType.unix();
44 | assertThat(unix.getSeparator()).isEqualTo("/");
45 | assertThat(unix.getOtherSeparators()).isEqualTo("");
46 |
47 | // "//foo/bar" is what will be passed to parsePath if "/", "foo", "bar" is passed to getPath
48 | PathType.ParseResult path = unix.parsePath("//foo/bar");
49 | assertParseResult(path, "/", "foo", "bar");
50 | assertThat(unix.toString(path.root(), path.names())).isEqualTo("/foo/bar");
51 |
52 | PathType.ParseResult path2 = unix.parsePath("foo/bar/");
53 | assertParseResult(path2, null, "foo", "bar");
54 | assertThat(unix.toString(path2.root(), path2.names())).isEqualTo("foo/bar");
55 | }
56 |
57 | @Test
58 | public void testUnix_toUri() {
59 | URI fileUri = PathType.unix().toUri(fileSystemUri, "/", ImmutableList.of("foo", "bar"), false);
60 | assertThat(fileUri.toString()).isEqualTo("jimfs://foo/foo/bar");
61 | assertThat(fileUri.getPath()).isEqualTo("/foo/bar");
62 |
63 | URI directoryUri =
64 | PathType.unix().toUri(fileSystemUri, "/", ImmutableList.of("foo", "bar"), true);
65 | assertThat(directoryUri.toString()).isEqualTo("jimfs://foo/foo/bar/");
66 | assertThat(directoryUri.getPath()).isEqualTo("/foo/bar/");
67 |
68 | URI rootUri = PathType.unix().toUri(fileSystemUri, "/", ImmutableList.of(), true);
69 | assertThat(rootUri.toString()).isEqualTo("jimfs://foo/");
70 | assertThat(rootUri.getPath()).isEqualTo("/");
71 | }
72 |
73 | @Test
74 | public void testUnix_toUri_escaping() {
75 | URI uri = PathType.unix().toUri(fileSystemUri, "/", ImmutableList.of("foo bar"), false);
76 | assertThat(uri.toString()).isEqualTo("jimfs://foo/foo%20bar");
77 | assertThat(uri.getRawPath()).isEqualTo("/foo%20bar");
78 | assertThat(uri.getPath()).isEqualTo("/foo bar");
79 | }
80 |
81 | @Test
82 | public void testUnix_uriRoundTrips() {
83 | assertUriRoundTripsCorrectly(PathType.unix(), "/");
84 | assertUriRoundTripsCorrectly(PathType.unix(), "/foo");
85 | assertUriRoundTripsCorrectly(PathType.unix(), "/foo/bar/baz");
86 | assertUriRoundTripsCorrectly(PathType.unix(), "/foo/bar baz/one/two");
87 | assertUriRoundTripsCorrectly(PathType.unix(), "/foo bar");
88 | assertUriRoundTripsCorrectly(PathType.unix(), "/foo bar/");
89 | assertUriRoundTripsCorrectly(PathType.unix(), "/foo bar/baz/one");
90 | }
91 |
92 | @Test
93 | public void testUnix_illegalCharacters() {
94 | try {
95 | PathType.unix().parsePath("/foo/bar\0");
96 | fail();
97 | } catch (InvalidPathException expected) {
98 | assertEquals(8, expected.getIndex());
99 | }
100 |
101 | try {
102 | PathType.unix().parsePath("/\u00001/foo");
103 | fail();
104 | } catch (InvalidPathException expected) {
105 | assertEquals(1, expected.getIndex());
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/UrlTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 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.StandardSystemProperty.LINE_SEPARATOR;
20 | import static com.google.common.truth.Truth.assertThat;
21 | import static java.nio.charset.StandardCharsets.UTF_8;
22 |
23 | import com.google.common.collect.ImmutableList;
24 | import com.google.common.collect.Range;
25 | import com.google.common.io.Resources;
26 | import java.io.IOException;
27 | import java.net.MalformedURLException;
28 | import java.net.URL;
29 | import java.net.URLConnection;
30 | import java.nio.file.FileSystem;
31 | import java.nio.file.Files;
32 | import java.nio.file.Path;
33 | import java.nio.file.attribute.FileTime;
34 | import org.junit.Test;
35 | import org.junit.runner.RunWith;
36 | import org.junit.runners.JUnit4;
37 |
38 | /**
39 | * Tests that {@link URL} instances can be created and used from jimfs URIs.
40 | *
41 | * @author Colin Decker
42 | */
43 | @RunWith(JUnit4.class)
44 | public class UrlTest {
45 |
46 | private final FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
47 | private Path path = fs.getPath("foo");
48 |
49 | @Test
50 | public void creatUrl() throws MalformedURLException {
51 | URL url = path.toUri().toURL();
52 | assertThat(url).isNotNull();
53 | }
54 |
55 | @Test
56 | public void readFromUrl() throws IOException {
57 | Files.write(path, ImmutableList.of("Hello World"), UTF_8);
58 |
59 | URL url = path.toUri().toURL();
60 | assertThat(Resources.asCharSource(url, UTF_8).read())
61 | .isEqualTo("Hello World" + LINE_SEPARATOR.value());
62 | }
63 |
64 | @Test
65 | public void readDirectoryContents() throws IOException {
66 | Files.createDirectory(path);
67 | Files.createFile(path.resolve("a.txt"));
68 | Files.createFile(path.resolve("b.txt"));
69 | Files.createDirectory(path.resolve("c"));
70 |
71 | URL url = path.toUri().toURL();
72 | assertThat(Resources.asCharSource(url, UTF_8).read()).isEqualTo("a.txt\nb.txt\nc\n");
73 | }
74 |
75 | @Test
76 | public void headers() throws IOException {
77 | byte[] bytes = {1, 2, 3};
78 | Files.write(path, bytes);
79 | FileTime lastModified = Files.getLastModifiedTime(path);
80 |
81 | URL url = path.toUri().toURL();
82 | URLConnection conn = url.openConnection();
83 |
84 | // read header fields directly
85 | assertThat(conn.getHeaderFields()).containsEntry("content-length", ImmutableList.of("3"));
86 | assertThat(conn.getHeaderFields())
87 | .containsEntry("content-type", ImmutableList.of("application/octet-stream"));
88 |
89 | if (lastModified != null) {
90 | assertThat(conn.getHeaderFields()).containsKey("last-modified");
91 | assertThat(conn.getHeaderFields()).hasSize(3);
92 | } else {
93 | assertThat(conn.getHeaderFields()).hasSize(2);
94 | }
95 |
96 | // use the specific methods for reading the expected headers
97 | assertThat(conn.getContentLengthLong()).isEqualTo(Files.size(path));
98 | assertThat(conn.getContentType()).isEqualTo("application/octet-stream");
99 |
100 | if (lastModified != null) {
101 | // The HTTP date format does not include milliseconds, which means that the last modified time
102 | // returned from the connection may not be exactly the same as that of the file system itself.
103 | // The difference should less than 1000ms though, and should never be greater.
104 | long difference = lastModified.toMillis() - conn.getLastModified();
105 | assertThat(difference).isIn(Range.closedOpen(0L, 1000L));
106 | } else {
107 | assertThat(conn.getLastModified()).isEqualTo(0L);
108 | }
109 | }
110 |
111 | @Test
112 | public void contentType() throws IOException {
113 | path = fs.getPath("foo.txt");
114 | Files.write(path, ImmutableList.of("Hello World"), UTF_8);
115 |
116 | URL url = path.toUri().toURL();
117 | URLConnection conn = url.openConnection();
118 |
119 | // Should be text/plain, but this is entirely dependent on the installed FileTypeDetectors
120 | String detectedContentType = Files.probeContentType(path);
121 | if (detectedContentType == null) {
122 | assertThat(conn.getContentType()).isEqualTo("application/octet-stream");
123 | } else {
124 | assertThat(conn.getContentType()).isEqualTo(detectedContentType);
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/UserDefinedAttributeProviderTest.java:
--------------------------------------------------------------------------------
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.truth.Truth.assertThat;
20 | import static org.junit.Assert.assertNotNull;
21 | import static org.junit.Assert.fail;
22 |
23 | import com.google.common.collect.ImmutableList;
24 | import com.google.common.collect.ImmutableSet;
25 | import java.io.IOException;
26 | import java.nio.ByteBuffer;
27 | import java.nio.file.attribute.UserDefinedFileAttributeView;
28 | import java.util.Arrays;
29 | import java.util.Set;
30 | import org.junit.Test;
31 | import org.junit.runner.RunWith;
32 | import org.junit.runners.JUnit4;
33 |
34 | /**
35 | * Tests for {@link UserDefinedAttributeProvider}.
36 | *
37 | * @author Colin Decker
38 | */
39 | @RunWith(JUnit4.class)
40 | public class UserDefinedAttributeProviderTest
41 | extends AbstractAttributeProviderTest {
42 |
43 | @Override
44 | protected UserDefinedAttributeProvider createProvider() {
45 | return new UserDefinedAttributeProvider();
46 | }
47 |
48 | @Override
49 | protected Set extends AttributeProvider> createInheritedProviders() {
50 | return ImmutableSet.of();
51 | }
52 |
53 | @Test
54 | public void testInitialAttributes() {
55 | // no initial attributes
56 | assertThat(ImmutableList.copyOf(file.getAttributeKeys())).isEmpty();
57 | assertThat(provider.attributes(file)).isEmpty();
58 | }
59 |
60 | @Test
61 | public void testGettingAndSetting() {
62 | byte[] bytes = {0, 1, 2, 3};
63 | provider.set(file, "user", "one", bytes, false);
64 | provider.set(file, "user", "two", ByteBuffer.wrap(bytes), false);
65 |
66 | byte[] one = (byte[]) provider.get(file, "one");
67 | byte[] two = (byte[]) provider.get(file, "two");
68 | assertThat(Arrays.equals(one, bytes)).isTrue();
69 | assertThat(Arrays.equals(two, bytes)).isTrue();
70 |
71 | assertSetFails("foo", "hello");
72 |
73 | assertThat(provider.attributes(file)).containsExactly("one", "two");
74 | }
75 |
76 | @Test
77 | public void testSetOnCreate() {
78 | assertSetFailsOnCreate("anything", new byte[0]);
79 | }
80 |
81 | @Test
82 | public void testView() throws IOException {
83 | UserDefinedFileAttributeView view = provider.view(fileLookup(), NO_INHERITED_VIEWS);
84 | assertNotNull(view);
85 |
86 | assertThat(view.name()).isEqualTo("user");
87 | assertThat(view.list()).isEmpty();
88 |
89 | byte[] b1 = {0, 1, 2};
90 | byte[] b2 = {0, 1, 2, 3, 4};
91 |
92 | view.write("b1", ByteBuffer.wrap(b1));
93 | view.write("b2", ByteBuffer.wrap(b2));
94 |
95 | assertThat(view.list()).containsAtLeast("b1", "b2");
96 | assertThat(file.getAttributeKeys()).containsExactly("user:b1", "user:b2");
97 |
98 | assertThat(view.size("b1")).isEqualTo(3);
99 | assertThat(view.size("b2")).isEqualTo(5);
100 |
101 | ByteBuffer buf1 = ByteBuffer.allocate(view.size("b1"));
102 | ByteBuffer buf2 = ByteBuffer.allocate(view.size("b2"));
103 |
104 | view.read("b1", buf1);
105 | view.read("b2", buf2);
106 |
107 | assertThat(Arrays.equals(b1, buf1.array())).isTrue();
108 | assertThat(Arrays.equals(b2, buf2.array())).isTrue();
109 |
110 | view.delete("b2");
111 |
112 | assertThat(view.list()).containsExactly("b1");
113 | assertThat(file.getAttributeKeys()).containsExactly("user:b1");
114 |
115 | try {
116 | view.size("b2");
117 | fail();
118 | } catch (IllegalArgumentException expected) {
119 | assertThat(expected.getMessage()).contains("not set");
120 | }
121 |
122 | try {
123 | view.read("b2", ByteBuffer.allocate(10));
124 | fail();
125 | } catch (IllegalArgumentException expected) {
126 | assertThat(expected.getMessage()).contains("not set");
127 | }
128 |
129 | view.write("b1", ByteBuffer.wrap(b2));
130 | assertThat(view.size("b1")).isEqualTo(5);
131 |
132 | view.delete("b2"); // succeeds
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/UserLookupServiceTest.java:
--------------------------------------------------------------------------------
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.truth.Truth.assertThat;
20 | import static org.junit.Assert.fail;
21 |
22 | import java.io.IOException;
23 | import java.nio.file.attribute.GroupPrincipal;
24 | import java.nio.file.attribute.UserPrincipal;
25 | import java.nio.file.attribute.UserPrincipalLookupService;
26 | import java.nio.file.attribute.UserPrincipalNotFoundException;
27 | import org.junit.Test;
28 | import org.junit.runner.RunWith;
29 | import org.junit.runners.JUnit4;
30 |
31 | /**
32 | * Tests for {@link UserLookupService}.
33 | *
34 | * @author Colin Decker
35 | */
36 | @RunWith(JUnit4.class)
37 | public class UserLookupServiceTest {
38 |
39 | @Test
40 | public void testUserLookupService() throws IOException {
41 | UserPrincipalLookupService service = new UserLookupService(true);
42 | UserPrincipal bob1 = service.lookupPrincipalByName("bob");
43 | UserPrincipal bob2 = service.lookupPrincipalByName("bob");
44 | UserPrincipal alice = service.lookupPrincipalByName("alice");
45 |
46 | assertThat(bob1).isEqualTo(bob2);
47 | assertThat(bob1).isNotEqualTo(alice);
48 |
49 | GroupPrincipal group1 = service.lookupPrincipalByGroupName("group");
50 | GroupPrincipal group2 = service.lookupPrincipalByGroupName("group");
51 | GroupPrincipal foo = service.lookupPrincipalByGroupName("foo");
52 |
53 | assertThat(group1).isEqualTo(group2);
54 | assertThat(group1).isNotEqualTo(foo);
55 | }
56 |
57 | @Test
58 | public void testServiceNotSupportingGroups() throws IOException {
59 | UserPrincipalLookupService service = new UserLookupService(false);
60 |
61 | try {
62 | service.lookupPrincipalByGroupName("group");
63 | fail();
64 | } catch (UserPrincipalNotFoundException expected) {
65 | assertThat(expected.getName()).isEqualTo("group");
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/jimfs/src/test/java/com/google/common/jimfs/WatchServiceConfigurationTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 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.truth.Truth.assertThat;
20 | import static java.util.concurrent.TimeUnit.MILLISECONDS;
21 | import static java.util.concurrent.TimeUnit.SECONDS;
22 |
23 | import java.io.IOException;
24 | import java.nio.file.WatchService;
25 | import org.junit.After;
26 | import org.junit.Before;
27 | import org.junit.Test;
28 | import org.junit.runner.RunWith;
29 | import org.junit.runners.JUnit4;
30 |
31 | /**
32 | * Tests for {@link WatchServiceConfiguration}.
33 | *
34 | * @author Colin Decker
35 | */
36 | @RunWith(JUnit4.class)
37 | public class WatchServiceConfigurationTest {
38 |
39 | private JimfsFileSystem fs;
40 |
41 | @Before
42 | public void setUp() {
43 | // kind of putting the cart before the horse maybe, but it's the easiest way to get valid
44 | // instances of both a FileSystemView and a PathService
45 | fs = (JimfsFileSystem) Jimfs.newFileSystem();
46 | }
47 |
48 | @After
49 | public void tearDown() throws IOException {
50 | fs.close();
51 | fs = null;
52 | }
53 |
54 | @Test
55 | public void testPollingConfig() {
56 | WatchServiceConfiguration polling = WatchServiceConfiguration.polling(50, MILLISECONDS);
57 | WatchService watchService = polling.newWatchService(fs.getDefaultView(), fs.getPathService());
58 | assertThat(watchService).isInstanceOf(PollingWatchService.class);
59 |
60 | PollingWatchService pollingWatchService = (PollingWatchService) watchService;
61 | assertThat(pollingWatchService.interval).isEqualTo(50);
62 | assertThat(pollingWatchService.timeUnit).isEqualTo(MILLISECONDS);
63 | }
64 |
65 | @Test
66 | public void testDefaultConfig() {
67 | WatchService watchService =
68 | WatchServiceConfiguration.DEFAULT.newWatchService(fs.getDefaultView(), fs.getPathService());
69 | assertThat(watchService).isInstanceOf(PollingWatchService.class);
70 |
71 | PollingWatchService pollingWatchService = (PollingWatchService) watchService;
72 | assertThat(pollingWatchService.interval).isEqualTo(5);
73 | assertThat(pollingWatchService.timeUnit).isEqualTo(SECONDS);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/util/update_snapshot_docs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -eu
4 |
5 | echo -e "Publishing docs...\n"
6 |
7 | GH_PAGES_DIR="$HOME/gh-pages"
8 |
9 | git clone --quiet --branch=gh-pages https://x-access-token:${GITHUB_TOKEN}@github.com/google/jimfs.git $GH_PAGES_DIR > /dev/null
10 |
11 | cd $GH_PAGES_DIR
12 |
13 | git config --global user.name "$GITHUB_ACTOR"
14 | git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com"
15 |
16 | ./updaterelease.sh snapshot
17 |
18 | git push -fq origin gh-pages > /dev/null
19 |
20 | echo -e "Published docs to gh-pages.\n"
21 |
--------------------------------------------------------------------------------