1/*
2 * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/* @test
25 * @bug 4313887 6838333
26 * @summary Unit test for java.nio.file.attribute.UserDefinedFileAttributeView
27 * @library ../..
28 * @key randomness
29 */
30
31import java.nio.ByteBuffer;
32import java.nio.charset.Charset;
33import java.nio.file.*;
34import static java.nio.file.LinkOption.*;
35import java.nio.file.attribute.*;
36import java.util.Arrays;
37import java.util.Map;
38import java.util.Random;
39import java.io.IOException;
40
41public class Basic {
42
43    private static Random rand = new Random();
44
45    private static final String ATTR_NAME = "mime_type";
46    private static final String ATTR_VALUE = "text/plain";
47    private static final String ATTR_VALUE2 = "text/html";
48
49    static interface Task {
50        void run() throws Exception;
51    }
52
53    static void tryCatch(Class<? extends Throwable> ex, Task task) {
54        boolean caught = false;
55        try {
56            task.run();
57        } catch (Throwable x) {
58            if (ex.isAssignableFrom(x.getClass())) {
59                caught = true;
60            } else {
61                throw new RuntimeException(x);
62            }
63        }
64        if (!caught)
65            throw new RuntimeException(ex.getName() + " expected");
66    }
67
68    static void expectNullPointerException(Task task) {
69        tryCatch(NullPointerException.class, task);
70    }
71
72    static boolean hasAttribute(UserDefinedFileAttributeView view, String attr)
73        throws IOException
74    {
75        for (String name: view.list()) {
76            if (name.equals(ATTR_NAME))
77                return true;
78        }
79        return false;
80    }
81
82    static void test(Path file, LinkOption... options) throws IOException {
83        final UserDefinedFileAttributeView view =
84            Files.getFileAttributeView(file, UserDefinedFileAttributeView.class, options);
85        ByteBuffer buf = rand.nextBoolean() ?
86            ByteBuffer.allocate(100) : ByteBuffer.allocateDirect(100);
87
88        // Test: write
89        buf.put(ATTR_VALUE.getBytes()).flip();
90        int size = buf.remaining();
91        int nwrote = view.write(ATTR_NAME, buf);
92        if (nwrote != size)
93            throw new RuntimeException("Unexpected number of bytes written");
94
95        // Test: size
96        if (view.size(ATTR_NAME) != size)
97            throw new RuntimeException("Unexpected size");
98
99        // Test: read
100        buf.clear();
101        int nread = view.read(ATTR_NAME, buf);
102        if (nread != size)
103            throw new RuntimeException("Unexpected number of bytes read");
104        buf.flip();
105        String value = Charset.defaultCharset().decode(buf).toString();
106        if (!value.equals(ATTR_VALUE))
107            throw new RuntimeException("Unexpected attribute value");
108
109        // Test: read with insufficient space
110        tryCatch(IOException.class, new Task() {
111            public void run() throws IOException {
112                view.read(ATTR_NAME, ByteBuffer.allocateDirect(1));
113            }});
114
115        // Test: replace value
116        buf.clear();
117        buf.put(ATTR_VALUE2.getBytes()).flip();
118        size = buf.remaining();
119        view.write(ATTR_NAME, buf);
120        if (view.size(ATTR_NAME) != size)
121            throw new RuntimeException("Unexpected size");
122
123        // Test: list
124        if (!hasAttribute(view, ATTR_NAME))
125            throw new RuntimeException("Attribute name not in list");
126
127        // Test: delete
128        view.delete(ATTR_NAME);
129        if (hasAttribute(view, ATTR_NAME))
130            throw new RuntimeException("Attribute name in list");
131
132        // Test: dynamic access
133        String name = "user:" + ATTR_NAME;
134        byte[] valueAsBytes = ATTR_VALUE.getBytes();
135        Files.setAttribute(file, name, valueAsBytes);
136        byte[] actualAsBytes = (byte[])Files.getAttribute(file, name);
137        if (!Arrays.equals(valueAsBytes, actualAsBytes))
138            throw new RuntimeException("Unexpected attribute value");
139        Map<String,?> map = Files.readAttributes(file, name);
140        if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
141            throw new RuntimeException("Unexpected attribute value");
142        map = Files.readAttributes(file, "user:*");
143        if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
144            throw new RuntimeException("Unexpected attribute value");
145    }
146
147    static void miscTests(final Path file) throws IOException {
148        final UserDefinedFileAttributeView view =
149            Files.getFileAttributeView(file, UserDefinedFileAttributeView.class);
150        view.write(ATTR_NAME, ByteBuffer.wrap(ATTR_VALUE.getBytes()));
151
152        // NullPointerException
153        final ByteBuffer buf = ByteBuffer.allocate(100);
154
155        expectNullPointerException(new Task() {
156            public void run() throws IOException {
157                view.read(null, buf);
158            }});
159        expectNullPointerException(new Task() {
160            public void run() throws IOException {
161                view.read(ATTR_NAME, null);
162            }});
163        expectNullPointerException(new Task() {
164            public void run() throws IOException {
165                view.write(null, buf);
166            }});
167        expectNullPointerException(new Task() {
168            public void run() throws IOException {
169               view.write(ATTR_NAME, null);
170            }});
171        expectNullPointerException(new Task() {
172            public void run() throws IOException {
173                view.size(null);
174            }});
175        expectNullPointerException(new Task() {
176            public void run() throws IOException {
177                view.delete(null);
178            }});
179        expectNullPointerException(new Task() {
180            public void run() throws IOException {
181                Files.getAttribute(file, null);
182            }});
183        expectNullPointerException(new Task() {
184            public void run() throws IOException {
185                Files.getAttribute(file, "user:" + ATTR_NAME, (LinkOption[])null);
186            }});
187        expectNullPointerException(new Task() {
188            public void run() throws IOException {
189                Files.setAttribute(file, "user:" + ATTR_NAME, null);
190            }});
191        expectNullPointerException(new Task() {
192            public void run() throws IOException {
193                Files.setAttribute(file, null, new byte[0]);
194            }});
195        expectNullPointerException(new Task() {
196            public void run() throws IOException {
197                Files.setAttribute(file, "user: " + ATTR_NAME, new byte[0], (LinkOption[])null);
198            }});
199        expectNullPointerException(new Task() {
200            public void run() throws IOException {
201                Files.readAttributes(file, (String)null);
202            }});
203        expectNullPointerException(new Task() {
204            public void run() throws IOException {
205                Files.readAttributes(file, "*", (LinkOption[])null);
206            }});
207
208        // Read-only buffer
209        tryCatch(IllegalArgumentException.class, new Task() {
210            public void run() throws IOException {
211                ByteBuffer buf = ByteBuffer.wrap(ATTR_VALUE.getBytes()).asReadOnlyBuffer();
212                view.write(ATTR_NAME, buf);
213                buf.flip();
214                view.read(ATTR_NAME, buf);
215            }});
216
217        // Zero bytes remaining
218        tryCatch(IOException.class, new Task() {
219            public void run() throws IOException {
220                ByteBuffer buf = buf = ByteBuffer.allocateDirect(100);
221                buf.position(buf.capacity());
222                view.read(ATTR_NAME, buf);
223            }});
224    }
225
226    public static void main(String[] args) throws IOException {
227        // create temporary directory to run tests
228        Path dir = TestUtil.createTemporaryDirectory();
229        try {
230            if (!Files.getFileStore(dir).supportsFileAttributeView("user")) {
231                System.out.println("UserDefinedFileAttributeView not supported - skip test");
232                return;
233            }
234
235            // test access to user defined attributes of regular file
236            Path file = dir.resolve("foo.html");
237            Files.createFile(file);
238            try {
239                test(file);
240            } finally {
241                Files.delete(file);
242            }
243
244            // test access to user defined attributes of directory
245            Path subdir = dir.resolve("foo");
246            Files.createDirectory(subdir);
247            try {
248                test(subdir);
249            } finally {
250                Files.delete(subdir);
251            }
252
253            // test access to user defined attributes of sym link
254            if (TestUtil.supportsLinks(dir)) {
255                Path target = dir.resolve("doesnotexist");
256                Path link = dir.resolve("link");
257                Files.createSymbolicLink(link, target);
258                try {
259                    test(link, NOFOLLOW_LINKS);
260                } catch (IOException x) {
261                    // access to attributes of sym link may not be supported
262                } finally {
263                    Files.delete(link);
264                }
265            }
266
267            // misc. tests
268            try {
269                file = dir.resolve("foo.txt");
270                Files.createFile(file);
271                miscTests(dir);
272            } finally {
273                Files.delete(file);
274            }
275
276        } finally {
277            TestUtil.removeAll(dir);
278        }
279    }
280 }
281