blob: 5e28fcd6a842ccc994bb4baef00ab7b9369d80a9 [file] [log] [blame]
Thomas Vachuska24c849c2014-10-27 09:53:05 -07001/*
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07002 * Copyright 2014 Open Networking Laboratory
Thomas Vachuska24c849c2014-10-27 09:53:05 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska24c849c2014-10-27 09:53:05 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska24c849c2014-10-27 09:53:05 -070015 */
tom5f38b3a2014-08-27 23:50:54 -070016package org.onlab.util;
17
Thomas Vachuska02aeb032015-01-06 22:36:30 -080018import static java.nio.file.Files.delete;
19import static java.nio.file.Files.walkFileTree;
Yuta HIGUCHI683e9782014-11-25 17:26:36 -080020import static org.slf4j.LoggerFactory.getLogger;
21
tom53efab52014-10-07 17:43:48 -070022import java.io.BufferedReader;
23import java.io.File;
Ray Milkey705d9bc2014-11-18 08:19:00 -080024import java.io.FileInputStream;
tom53efab52014-10-07 17:43:48 -070025import java.io.IOException;
Ray Milkey705d9bc2014-11-18 08:19:00 -080026import java.io.InputStreamReader;
Yuta HIGUCHI683e9782014-11-25 17:26:36 -080027import java.lang.Thread.UncaughtExceptionHandler;
Ray Milkey705d9bc2014-11-18 08:19:00 -080028import java.nio.charset.StandardCharsets;
Thomas Vachuska02aeb032015-01-06 22:36:30 -080029import java.nio.file.FileVisitResult;
Thomas Vachuska90b453f2015-01-30 18:57:14 -080030import java.nio.file.Files;
Thomas Vachuska02aeb032015-01-06 22:36:30 -080031import java.nio.file.Path;
32import java.nio.file.Paths;
33import java.nio.file.SimpleFileVisitor;
Thomas Vachuska90b453f2015-01-30 18:57:14 -080034import java.nio.file.StandardCopyOption;
Thomas Vachuska02aeb032015-01-06 22:36:30 -080035import java.nio.file.attribute.BasicFileAttributes;
tom53efab52014-10-07 17:43:48 -070036import java.util.ArrayList;
Brian O'Connore2eac102015-02-12 18:30:22 -080037import java.util.Collection;
tom53efab52014-10-07 17:43:48 -070038import java.util.List;
tom5f38b3a2014-08-27 23:50:54 -070039import java.util.concurrent.ThreadFactory;
40
Yuta HIGUCHI683e9782014-11-25 17:26:36 -080041import org.slf4j.Logger;
42
Ray Milkey705d9bc2014-11-18 08:19:00 -080043import com.google.common.base.Strings;
44import com.google.common.primitives.UnsignedLongs;
45import com.google.common.util.concurrent.ThreadFactoryBuilder;
46
tom5f38b3a2014-08-27 23:50:54 -070047public abstract class Tools {
48
49 private Tools() {
50 }
51
Thomas Vachuska02aeb032015-01-06 22:36:30 -080052 private static final Logger log = getLogger(Tools.class);
Yuta HIGUCHI683e9782014-11-25 17:26:36 -080053
tom5f38b3a2014-08-27 23:50:54 -070054 /**
55 * Returns a thread factory that produces threads named according to the
56 * supplied name pattern.
57 *
58 * @param pattern name pattern
59 * @return thread factory
60 */
61 public static ThreadFactory namedThreads(String pattern) {
Yuta HIGUCHI683e9782014-11-25 17:26:36 -080062 return new ThreadFactoryBuilder()
63 .setNameFormat(pattern)
Thomas Vachuska02aeb032015-01-06 22:36:30 -080064 // FIXME remove UncaughtExceptionHandler before release
Yuta HIGUCHI683e9782014-11-25 17:26:36 -080065 .setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
66
67 @Override
68 public void uncaughtException(Thread t, Throwable e) {
Thomas Vachuska02aeb032015-01-06 22:36:30 -080069 log.error("Uncaught exception on {}", t.getName(), e);
Yuta HIGUCHI683e9782014-11-25 17:26:36 -080070 }
71 }).build();
tom5f38b3a2014-08-27 23:50:54 -070072 }
73
tom782a7cf2014-09-11 23:58:38 -070074 /**
Yuta HIGUCHI06586272014-11-25 14:27:03 -080075 * Returns a thread factory that produces threads with MIN_PRIORITY.
76 *
77 * @param factory backing ThreadFactory
78 * @return thread factory
79 */
80 public static ThreadFactory minPriority(ThreadFactory factory) {
81 return new ThreadFactoryBuilder()
Thomas Vachuska02aeb032015-01-06 22:36:30 -080082 .setThreadFactory(factory)
83 .setPriority(Thread.MIN_PRIORITY)
84 .build();
Yuta HIGUCHI06586272014-11-25 14:27:03 -080085 }
86
87 /**
Brian O'Connore2eac102015-02-12 18:30:22 -080088 * Returns true if the collection is null or is empty.
89 *
90 * @param collection collection to test
91 * @return true if null or empty; false otherwise
92 */
93 public static boolean isNullOrEmpty(Collection collection) {
94 return collection == null || collection.isEmpty();
95 }
96
97 /**
tom782a7cf2014-09-11 23:58:38 -070098 * Converts a string from hex to long.
99 *
100 * @param string hex number in string form; sans 0x
101 * @return long value
102 */
103 public static long fromHex(String string) {
104 return UnsignedLongs.parseUnsignedLong(string, 16);
105 }
106
107 /**
108 * Converts a long value to hex string; 16 wide and sans 0x.
109 *
110 * @param value long value
111 * @return hex string
112 */
113 public static String toHex(long value) {
114 return Strings.padStart(UnsignedLongs.toString(value, 16), 16, '0');
115 }
116
117 /**
118 * Converts a long value to hex string; 16 wide and sans 0x.
119 *
120 * @param value long value
121 * @param width string width; zero padded
122 * @return hex string
123 */
124 public static String toHex(long value, int width) {
125 return Strings.padStart(UnsignedLongs.toString(value, 16), width, '0');
126 }
tomf110fff2014-09-26 00:38:18 -0700127
128 /**
129 * Suspends the current thread for a specified number of millis.
130 *
131 * @param ms number of millis
132 */
133 public static void delay(int ms) {
134 try {
135 Thread.sleep(ms);
136 } catch (InterruptedException e) {
137 throw new RuntimeException("Interrupted", e);
138 }
139 }
140
tom53efab52014-10-07 17:43:48 -0700141 /**
142 * Slurps the contents of a file into a list of strings, one per line.
143 *
144 * @param path file path
145 * @return file contents
146 */
147 public static List<String> slurp(File path) {
Ray Milkey705d9bc2014-11-18 08:19:00 -0800148 try {
149 BufferedReader br = new BufferedReader(
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800150 new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8));
Ray Milkey705d9bc2014-11-18 08:19:00 -0800151
tom53efab52014-10-07 17:43:48 -0700152 List<String> lines = new ArrayList<>();
153 String line;
154 while ((line = br.readLine()) != null) {
155 lines.add(line);
156 }
157 return lines;
158
159 } catch (IOException e) {
160 return null;
161 }
162 }
163
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800164
165 /**
166 * Purges the specified directory path.&nbsp;Use with great caution since
167 * no attempt is made to check for symbolic links, which could result in
168 * deletion of unintended files.
169 *
170 * @param path directory to be removed
171 * @throws java.io.IOException if unable to remove contents
172 */
173 public static void removeDirectory(String path) throws IOException {
174 walkFileTree(Paths.get(path), new DirectoryDeleter());
175 }
176
177 /**
178 * Purges the specified directory path.&nbsp;Use with great caution since
179 * no attempt is made to check for symbolic links, which could result in
180 * deletion of unintended files.
181 *
182 * @param dir directory to be removed
183 * @throws java.io.IOException if unable to remove contents
184 */
185 public static void removeDirectory(File dir) throws IOException {
186 walkFileTree(Paths.get(dir.getAbsolutePath()), new DirectoryDeleter());
187 }
188
189
190 private static class DirectoryDeleter extends SimpleFileVisitor<Path> {
191 @Override
192 public FileVisitResult visitFile(Path file, BasicFileAttributes attributes)
193 throws IOException {
194 if (attributes.isRegularFile()) {
195 delete(file);
196 }
197 return FileVisitResult.CONTINUE;
198 }
199
200 @Override
201 public FileVisitResult postVisitDirectory(Path directory, IOException ioe)
202 throws IOException {
203 delete(directory);
204 return FileVisitResult.CONTINUE;
205 }
206
207 @Override
208 public FileVisitResult visitFileFailed(Path file, IOException ioe)
209 throws IOException {
210 log.warn("Unable to delete file {}", file);
211 log.warn("Boom", ioe);
212 return FileVisitResult.CONTINUE;
213 }
214 }
215
Thomas Vachuska90b453f2015-01-30 18:57:14 -0800216
217 /**
218 * Copies the specified directory path.&nbsp;Use with great caution since
219 * no attempt is made to check for symbolic links, which could result in
220 * copy of unintended files.
221 *
222 * @param src directory to be copied
223 * @param dst destination directory to be removed
224 * @throws java.io.IOException if unable to remove contents
225 */
226 public static void copyDirectory(String src, String dst) throws IOException {
227 walkFileTree(Paths.get(src), new DirectoryCopier(src, dst));
228 }
229
230 /**
231 * Copies the specified directory path.&nbsp;Use with great caution since
232 * no attempt is made to check for symbolic links, which could result in
233 * copy of unintended files.
234 *
235 * @param src directory to be copied
236 * @param dst destination directory to be removed
237 * @throws java.io.IOException if unable to remove contents
238 */
239 public static void copyDirectory(File src, File dst) throws IOException {
240 walkFileTree(Paths.get(src.getAbsolutePath()),
241 new DirectoryCopier(src.getAbsolutePath(),
242 dst.getAbsolutePath()));
243 }
244
245
246 public static class DirectoryCopier extends SimpleFileVisitor<Path> {
247 private Path src;
248 private Path dst;
249 private StandardCopyOption copyOption = StandardCopyOption.REPLACE_EXISTING;
250
251 DirectoryCopier(String src, String dst) {
252 this.src = Paths.get(src);
253 this.dst = Paths.get(dst);
254 }
255
256 @Override
257 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
258 Path targetPath = dst.resolve(src.relativize(dir));
259 if (!Files.exists(targetPath)) {
260 Files.createDirectory(targetPath);
261 }
262 return FileVisitResult.CONTINUE;
263 }
264
265 @Override
266 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
267 Files.copy(file, dst.resolve(src.relativize(file)), copyOption);
268 return FileVisitResult.CONTINUE;
269 }
270 }
271
tom5f38b3a2014-08-27 23:50:54 -0700272}