1d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak/*
2d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak * Copyright (C) 2017 The Android Open Source Project
3d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak *
4d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak * Licensed under the Apache License, Version 2.0 (the "License");
5d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak * you may not use this file except in compliance with the License.
6d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak * You may obtain a copy of the License at
7d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak *
8d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak *      http://www.apache.org/licenses/LICENSE-2.0
9d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak *
10d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak * Unless required by applicable law or agreed to in writing, software
11d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak * distributed under the License is distributed on an "AS IS" BASIS,
12d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak * See the License for the specific language governing permissions and
14d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak * limitations under the License
15d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak */
16d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakpackage libcore.java.nio.file;
17d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
18d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport org.junit.Assert;
19d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport org.junit.Test;
20d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport org.junit.runner.RunWith;
21d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport org.junit.runners.JUnit4;
22d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport org.junit.After;
23d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport org.junit.Before;
24d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport org.junit.Rule;
25d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
26d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.io.IOException;
27d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.nio.file.FileStore;
28d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.nio.file.FileSystems;
29d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.nio.file.Files;
30d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.nio.file.Path;
31d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.nio.file.Paths;
32d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.nio.file.WatchEvent;
33d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.nio.file.WatchKey;
34d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.nio.file.WatchService;
35d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.util.ArrayList;
36d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.util.Arrays;
37d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.util.HashMap;
38d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.util.Iterator;
39d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.util.List;
40d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.util.Map;
41d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport java.util.concurrent.TimeUnit;
42d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
43d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport static junit.framework.TestCase.assertEquals;
44d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport static junit.framework.TestCase.assertFalse;
45d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport static junit.framework.TestCase.assertNotNull;
46d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport static junit.framework.TestCase.assertNull;
47d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport static junit.framework.TestCase.assertTrue;
48d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport static junit.framework.TestCase.fail;
49d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
50d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
51d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
52d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakimport static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
53d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
54d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak@RunWith(JUnit4.class)
55d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniakpublic class WatchServiceTest {
56d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    private static final WatchEvent.Kind<?>[] ALL_EVENTS_KINDS =
57d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        {ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY};
58d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
59d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    @Rule
60d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    public final FilesSetup filesSetup = new FilesSetup();
61d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
62d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    static class WatchEventResult {
63d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        final WatchEvent.Kind<Path> expectedKind;
64d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        final int expectedCount;
65d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        final boolean testCount;
66d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
67d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        public WatchEventResult(WatchEvent.Kind<Path> expectedKind) {
68d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            this.expectedKind = expectedKind;
69d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            this.expectedCount = 0;
70d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            this.testCount = false;
71d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        }
72d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
73d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        public WatchEventResult(WatchEvent.Kind<Path> expectedKind,
74d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                int expectedCount) {
75d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            this.expectedKind = expectedKind;
76d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            this.expectedCount = expectedCount;
77d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            this.testCount = true;
78d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        }
79d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    }
80d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
81d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    static public void assertWatchServiceEvent(WatchService watchService,
82d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            WatchKey expectedWatchKey,
83d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            List<WatchEventResult> expectedEvents,
84d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            boolean expectedResetResult) throws InterruptedException {
85d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Iterator<WatchEventResult> expectedEventsIterator = expectedEvents.iterator();
86d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
87d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        while (expectedEventsIterator.hasNext()) {
88d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            WatchKey watchKey = watchService.poll(2, TimeUnit.SECONDS);
89d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            assertEquals(expectedWatchKey, watchKey);
90d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
91d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            for (WatchEvent<?> event : watchKey.pollEvents()) {
92d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                WatchEventResult expectedEventResult = expectedEventsIterator.next();
93d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                assertNotNull(expectedEventResult);
94d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
95d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                assertEquals(expectedEventResult.expectedKind, event.kind());
96d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                if (expectedEventResult.testCount) {
97d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                    assertEquals(expectedEventResult.expectedCount, event.count());
98d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                }
99d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            }
100d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
101d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            assertEquals(expectedResetResult, watchKey.reset());
102d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        }
103d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    }
104d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
105d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    @Test
106d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    public void test_singleFile() throws Exception {
107d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchService watchService = FileSystems.getDefault().newWatchService();
108d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path file = Paths.get(filesSetup.getTestDir(), "directory/file");
109d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path directory = Paths.get(filesSetup.getTestDir(), "directory");
110d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertFalse(Files.exists(file));
111d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createDirectories(directory);
112d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchKey directoryKey1 = directory.register(watchService, ALL_EVENTS_KINDS);
113d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
114d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // emit EVENT_CREATE
115d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createFile(file);
11600e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService, directoryKey1,
11700e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak            Arrays.asList(new WatchEventResult(ENTRY_CREATE, 1)), true);
11800e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        assertNull(watchService.poll());
11900e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak
120d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // emit EVENT_MODIFY
121d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.write(file, "hello1".getBytes());
12200e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService, directoryKey1,
12300e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak            Arrays.asList(new WatchEventResult(ENTRY_MODIFY)), true);
12400e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak
12500e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        // http:///b/35346596
12600e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        // Sometimes we receive a second, latent EVENT_MODIFY that happens shortly
12700e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        // after the first one. This will intercept it and make sure it won't
12800e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        // mess with ENTRY_DELETE later.
12900e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        Thread.sleep(500);
13000e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        WatchKey doubleModifyKey = watchService.poll();
13100e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        if (doubleModifyKey != null) {
13200e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak            List<WatchEvent<?>> event = doubleModifyKey.pollEvents();
13300e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak            assertEquals(ENTRY_MODIFY, event.get(0).kind());
13400e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak            doubleModifyKey.reset();
13500e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        }
13600e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        assertNull(watchService.poll());
13700e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak
138d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // emit EVENT_DELETE
139d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.delete(file);
140d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService, directoryKey1,
14100e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak            Arrays.asList(new WatchEventResult(ENTRY_DELETE, 1)), true);
14200e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak
14300e74329e97b38ed7c17c61ad47a04f537ff2522Przemyslaw Szczepaniak        // Assert no more events
144d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertNull(watchService.poll());
145d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        watchService.close();
146d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    }
147d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
148d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    @Test
149d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    public void test_EventMask() throws Exception {
150d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchService watchService = FileSystems.getDefault().newWatchService();
151d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchEvent.Kind<?>[] events = {ENTRY_DELETE};
152d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path file = Paths.get(filesSetup.getTestDir(), "directory/file");
153d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path directory = Paths.get(filesSetup.getTestDir(), "directory");
154d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertFalse(Files.exists(file));
155d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createDirectories(directory);
156d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchKey directoryKey1 = directory.register(watchService, events);
157d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
158d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // emit EVENT_CREATE
159d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createFile(file);
160d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // emit EVENT_MODIFY (masked)
161d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.write(file, "hello1".getBytes());
162d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // emit EVENT_DELETE (masked)
163d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.delete(file);
164d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
165d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService, directoryKey1,
166d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                Arrays.asList(new WatchEventResult(ENTRY_DELETE, 1)), true);
167d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertNull(watchService.poll());
168d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        watchService.close();
169d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    }
170d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
171d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    @Test
172d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    public void test_singleDirectory() throws Exception {
173d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchService watchService = FileSystems.getDefault().newWatchService();
174d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path dirInDir = Paths.get(filesSetup.getTestDir(), "directory/dir");
175d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path directory = Paths.get(filesSetup.getTestDir(), "directory");
176d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertFalse(Files.exists(dirInDir));
177d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createDirectories(directory);
178d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchKey directoryKey1 = directory.register(watchService, ALL_EVENTS_KINDS);
179d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
180d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // emit EVENT_CREATE
181d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createDirectories(dirInDir);
182d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
183d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // Shouldn't emit EVENT_MODIFY
184d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path dirInDirInDir = Paths.get(filesSetup.getTestDir(), "directory/dir/dir");
185d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createDirectories(dirInDirInDir);
186d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.delete(dirInDirInDir);
187d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
188d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // emit EVENT_DELETE
189d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.delete(dirInDir);
190d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
191d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService, directoryKey1,
192d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                Arrays.asList(new WatchEventResult(ENTRY_CREATE, 1),
193d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                              new WatchEventResult(ENTRY_DELETE, 1)), true);
194d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertNull(watchService.poll());
195d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        watchService.close();
196d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
197d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        watchService.close();
198d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    }
199d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
200d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    @Test
201d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    public void test_cancel() throws Exception {
202d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchService watchService = FileSystems.getDefault().newWatchService();
203d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path file = Paths.get(filesSetup.getTestDir(), "directory/file");
204d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path directory = Paths.get(filesSetup.getTestDir(), "directory");
205d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertFalse(Files.exists(file));
206d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createDirectories(directory);
207d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchKey directoryKey1 = directory.register(watchService, ALL_EVENTS_KINDS);
208d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
209d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // emit EVENT_CREATE
210d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createFile(file);
211d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
212d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // Canceling the key may prevent the EVENT_CREATE from being picked-up...
213d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // TODO: Fix this (b/35190858).
214d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Thread.sleep(500);
215d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
216d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // Cancel the key
217d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        directoryKey1.cancel();
218d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertFalse(directoryKey1.isValid());
219d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
220d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // Shouldn't emit EVENT_MODIFY and EVENT_DELETE
221d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.write(file, "hello1".getBytes());
222d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.delete(file);
223d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
224d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService, directoryKey1,
225d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                Arrays.asList(new WatchEventResult(ENTRY_CREATE, 1)), false);
226d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertNull(watchService.poll());
227d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        watchService.close();
228d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    }
229d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
230d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    @Test
231d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    public void test_removeTarget() throws Exception {
232d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchService watchService = FileSystems.getDefault().newWatchService();
233d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path file = Paths.get(filesSetup.getTestDir(), "directory/file");
234d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path directory = Paths.get(filesSetup.getTestDir(), "directory");
235d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertFalse(Files.exists(file));
236d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createDirectories(directory);
237d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchKey directoryKey1 = directory.register(watchService, ALL_EVENTS_KINDS);
238d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
239d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // emit EVENT_CREATE x1
240d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createFile(file);
241d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.delete(file);
242d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
243d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // Delete underlying target.
244d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertTrue(directoryKey1.isValid());
245d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.delete(directory);
246d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
247d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // We need to give some time to watch service thread to catch up with the
248d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // deletion
249d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        while (directoryKey1.isValid()) {
250d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            Thread.sleep(500);
251d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        }
252d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
253d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService, directoryKey1,
254d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                Arrays.asList(new WatchEventResult(ENTRY_CREATE, 1),
255d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                              new WatchEventResult(ENTRY_DELETE, 1)), false);
256d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertNull(watchService.poll());
257d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
258d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        watchService.close();
259d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    }
260d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
261d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    @Test
262d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    public void test_multipleKeys() throws Exception {
263d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchService watchService1 = FileSystems.getDefault().newWatchService();
264d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
265d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path directory1 = Paths.get(filesSetup.getTestDir(), "directory1");
266d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path directory2 = Paths.get(filesSetup.getTestDir(), "directory2");
267d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
268d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path dir1file1 = Paths.get(filesSetup.getTestDir(), "directory1/file1");
269d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertFalse(Files.exists(dir1file1));
270d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path dir2file1 = Paths.get(filesSetup.getTestDir(), "directory2/file1");
271d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertFalse(Files.exists(dir2file1));
272d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
273d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createDirectories(directory1);
274d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createDirectories(directory2);
275d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchKey directoryKey1 = directory1.register(watchService1, ALL_EVENTS_KINDS);
276d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchKey directoryKey2 = directory2.register(watchService1, ALL_EVENTS_KINDS);
277d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
278d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // emit EVENT_CREATE/DELETE for all
279d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path[] allFiles = new Path[]{dir1file1, dir2file1};
280d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        for (Path path : allFiles) {
281d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            Files.createFile(path);
282d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            Files.delete(path);
283d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        }
284d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
285d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService1, directoryKey1,
286d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                Arrays.asList(new WatchEventResult(ENTRY_CREATE, 1),
287d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                              new WatchEventResult(ENTRY_DELETE, 1)), true);
288d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService1, directoryKey2,
289d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                Arrays.asList(new WatchEventResult(ENTRY_CREATE, 1),
290d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                              new WatchEventResult(ENTRY_DELETE, 1)), true);
291d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
292d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertNull(watchService1.poll());
293d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        watchService1.close();
294d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    }
295d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
296d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    @Test
297d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    public void test_multipleServices() throws Exception {
298d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchService watchService1 = FileSystems.getDefault().newWatchService();
299d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchService watchService2 = FileSystems.getDefault().newWatchService();
300d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
301d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path directory1 = Paths.get(filesSetup.getTestDir(), "directory1");
302d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path directory2 = Paths.get(filesSetup.getTestDir(), "directory2");
303d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
304d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path dir1file1 = Paths.get(filesSetup.getTestDir(), "directory1/file1");
305d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertFalse(Files.exists(dir1file1));
306d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path dir2file1 = Paths.get(filesSetup.getTestDir(), "directory2/file1");
307d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertFalse(Files.exists(dir2file1));
308d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
309d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createDirectories(directory1);
310d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Files.createDirectories(directory2);
311d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
312d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // 2 services listening for distinct directories
313d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchKey directoryKey1 = directory1.register(watchService1, ALL_EVENTS_KINDS);
314d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchKey directoryKey2 = directory2.register(watchService2, ALL_EVENTS_KINDS);
315d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // emit EVENT_CREATE/DELETE for all
316d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        Path[] allFiles = new Path[]{dir1file1, dir2file1};
317d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        for (Path path : allFiles) {
318d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            Files.createFile(path);
319d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            Files.delete(path);
320d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        }
321d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
322d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService1, directoryKey1,
323d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                Arrays.asList(new WatchEventResult(ENTRY_CREATE, 1),
324d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                              new WatchEventResult(ENTRY_DELETE, 1)), true);
325d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService2, directoryKey2,
326d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                Arrays.asList(new WatchEventResult(ENTRY_CREATE, 1),
327d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                              new WatchEventResult(ENTRY_DELETE, 1)), true);
328d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
329d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        // 2 services listening for a same directory
330d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        WatchKey directoryKey3 = directory1.register(watchService2, ALL_EVENTS_KINDS);
331d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        {
332d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            Files.createFile(dir1file1);
333d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak            Files.delete(dir1file1);
334d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        }
335d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService1, directoryKey1,
336d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                Arrays.asList(new WatchEventResult(ENTRY_CREATE, 1),
337d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                              new WatchEventResult(ENTRY_DELETE, 1)), true);
338d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertWatchServiceEvent(watchService2, directoryKey3,
339d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                Arrays.asList(new WatchEventResult(ENTRY_CREATE, 1),
340d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak                                              new WatchEventResult(ENTRY_DELETE, 1)), true);
341d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
342d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
343d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak
344d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertNull(watchService1.poll());
345d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        watchService1.close();
346d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        assertNull(watchService2.poll());
347d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak        watchService2.close();
348d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak    }
349d37b519cc3f4db065e0d3f9abe5ef81d3872a801Przemyslaw Szczepaniak}