1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.maven.plugins.war.util;
20
21 import java.io.File;
22 import java.util.Collection;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.LinkedHashSet;
26 import java.util.Set;
27
28 import org.codehaus.plexus.util.DirectoryScanner;
29
30 /**
31 * Set of file's paths.
32 *
33 * The class extends functionality of a "normal" set of strings by a process of the paths normalization. All paths are
34 * converted to unix form (slashes) and they don't start with starting /.
35 *
36 * @author Piotr Tabor
37 */
38 public class PathSet implements Iterable<String> {
39 private static final String SEPARATOR = "/";
40 private static final char SEPARATOR_CHAR = SEPARATOR.charAt(0);
41 /**
42 * Set of normalized paths
43 */
44 private Set<String> pathsSet = new LinkedHashSet<>();
45
46 static String normalizeSubPath(String path) {
47 if (path.isEmpty()) {
48 return path;
49 }
50 String cleanPath = path.replaceAll("[\\\\]+", SEPARATOR).replaceAll("[/]+", SEPARATOR);
51 cleanPath = cleanPath.charAt(0) == SEPARATOR_CHAR ? cleanPath.substring(1) : cleanPath;
52 if (cleanPath.isEmpty()) {
53 return cleanPath;
54 }
55 if (cleanPath.charAt(cleanPath.length() - 1) == SEPARATOR_CHAR) {
56 return cleanPath.substring(0, cleanPath.length() - 1);
57 }
58 return cleanPath;
59 }
60
61 /*-------------------- Business interface ------------------------------*/
62
63 /**
64 * Creates an empty paths set
65 */
66 public PathSet() {
67 /* Empty default constructor */
68 }
69
70 /**
71 * Creates paths set and normalizate and adds all 'paths'. The source 'paths' will not be changed
72 *
73 * @param paths to be added
74 */
75 public PathSet(Collection<String> paths) {
76 addAll(paths);
77 }
78
79 /**
80 * Creates paths set and normalizate and adds all 'paths'. The source 'paths' will not be changed
81 *
82 * @param paths to be added
83 */
84 public PathSet(String[] paths) {
85 addAll(paths);
86 }
87
88 /**
89 * Normalizes and adds given path to the set.
90 *
91 * @param path to be added
92 */
93 public void add(String path) {
94 pathsSet.add(normalizeSubPath(path));
95 }
96
97 /**
98 * Normalizes and adds given paths (collection of strings) to the set. The source collection will not be changed
99 *
100 * @param paths - collection of strings to be added
101 * @param prefix added to all given paths
102 */
103 public void addAll(Collection<String> paths, String prefix) {
104 for (String val : paths) {
105 add(prefix + SEPARATOR + val);
106 }
107 }
108
109 /**
110 * Normalizes and adds given paths to the set. The source collection will not be changed
111 *
112 * @param paths to be added
113 * @param prefix added to all given paths
114 */
115 public void addAll(String[] paths, String prefix) {
116 for (String val : paths) {
117 add(prefix + SEPARATOR + val);
118 }
119 }
120
121 /**
122 * Adds given paths to the set. The source collection will not be changed
123 *
124 * @param paths to be added
125 * @param prefix added to all given paths
126 */
127 public void addAll(PathSet paths, String prefix) {
128 for (String path : paths) {
129 add(prefix + SEPARATOR + path);
130 }
131 }
132
133 /**
134 * Normalizes and adds given paths (collection of strings) to the set. The source collection will not be changed
135 *
136 * @param paths - collection of strings to be added
137 */
138 public void addAll(Collection<String> paths) {
139 addAll(paths, "");
140 }
141
142 /**
143 * Normalizes and adds given paths to the set. The source collection will not be changed
144 *
145 * @param paths to be added
146 */
147 public void addAll(String[] paths) {
148 addAll(paths, "");
149 }
150
151 /**
152 * Adds given paths to the set. The source collection will not be changed
153 *
154 * @param paths to be added
155 */
156 public void addAll(PathSet paths) {
157 addAll(paths, "");
158 }
159
160 /**
161 * Checks if the set constains given path. The path is normalized before check.
162 *
163 * @param path we are looking for in the set.
164 * @return information if the set constains the path.
165 */
166 public boolean contains(String path) {
167 return pathsSet.contains(normalizeSubPath(path));
168 }
169
170 /**
171 * Removes the specified path if it exists.
172 *
173 * @param path the path to remove
174 * @return true if the path was removed, false if it did not existed
175 */
176 boolean remove(String path) {
177 return pathsSet.remove(normalizeSubPath(path));
178 }
179
180 /**
181 * Returns iterator of normalized paths (strings)
182 *
183 * @return iterator of normalized paths (strings)
184 */
185 @Override
186 public Iterator<String> iterator() {
187 return pathsSet.iterator();
188 }
189
190 /**
191 * @return {@link #pathsSet}
192 */
193 public Collection<String> paths() {
194 return pathsSet;
195 }
196
197 /**
198 * Adds given prefix to all paths in the set.
199 *
200 * The prefix should be ended by '/'. The generated paths are normalized.
201 *
202 * @param prefix to be added to all items
203 */
204 public void addPrefix(String prefix) {
205 final Set<String> newSet = new HashSet<>();
206 for (String path : pathsSet) {
207 newSet.add(normalizeSubPath(prefix + path));
208 }
209 pathsSet = newSet;
210 }
211
212 /**
213 * Returns count of the paths in the set
214 *
215 * @return count of the paths in the set
216 */
217 public int size() {
218 return pathsSet.size();
219 }
220
221 /**
222 * Adds to the set all files in the given directory
223 *
224 * @param directory that will be searched for file's paths to add
225 * @param prefix to be added to all found files
226 */
227 public void addAllFilesInDirectory(File directory, String prefix) {
228 DirectoryScanner scanner = new DirectoryScanner();
229 scanner.setBasedir(directory);
230 scanner.scan();
231 addAll(scanner.getIncludedFiles(), prefix);
232 }
233 }