blob: c8b2b745840d00eb81bdeefb5ca7a3bac4354122 [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;
37import java.util.List;
tom5f38b3a2014-08-27 23:50:54 -070038import java.util.concurrent.ThreadFactory;
39
Yuta HIGUCHI683e9782014-11-25 17:26:36 -080040import org.slf4j.Logger;
41
Ray Milkey705d9bc2014-11-18 08:19:00 -080042import com.google.common.base.Strings;
43import com.google.common.primitives.UnsignedLongs;
44import com.google.common.util.concurrent.ThreadFactoryBuilder;
45
tom5f38b3a2014-08-27 23:50:54 -070046public abstract class Tools {
47
48 private Tools() {
49 }
50
Thomas Vachuska02aeb032015-01-06 22:36:30 -080051 private static final Logger log = getLogger(Tools.class);
Yuta HIGUCHI683e9782014-11-25 17:26:36 -080052
tom5f38b3a2014-08-27 23:50:54 -070053 /**
54 * Returns a thread factory that produces threads named according to the
55 * supplied name pattern.
56 *
57 * @param pattern name pattern
58 * @return thread factory
59 */
60 public static ThreadFactory namedThreads(String pattern) {
Yuta HIGUCHI683e9782014-11-25 17:26:36 -080061 return new ThreadFactoryBuilder()
62 .setNameFormat(pattern)
Thomas Vachuska02aeb032015-01-06 22:36:30 -080063 // FIXME remove UncaughtExceptionHandler before release
Yuta HIGUCHI683e9782014-11-25 17:26:36 -080064 .setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
65
66 @Override
67 public void uncaughtException(Thread t, Throwable e) {
Thomas Vachuska02aeb032015-01-06 22:36:30 -080068 log.error("Uncaught exception on {}", t.getName(), e);
Yuta HIGUCHI683e9782014-11-25 17:26:36 -080069 }
70 }).build();
tom5f38b3a2014-08-27 23:50:54 -070071 }
72
tom782a7cf2014-09-11 23:58:38 -070073 /**
Yuta HIGUCHI06586272014-11-25 14:27:03 -080074 * Returns a thread factory that produces threads with MIN_PRIORITY.
75 *
76 * @param factory backing ThreadFactory
77 * @return thread factory
78 */
79 public static ThreadFactory minPriority(ThreadFactory factory) {
80 return new ThreadFactoryBuilder()
Thomas Vachuska02aeb032015-01-06 22:36:30 -080081 .setThreadFactory(factory)
82 .setPriority(Thread.MIN_PRIORITY)
83 .build();
Yuta HIGUCHI06586272014-11-25 14:27:03 -080084 }
85
86 /**
tom782a7cf2014-09-11 23:58:38 -070087 * Converts a string from hex to long.
88 *
89 * @param string hex number in string form; sans 0x
90 * @return long value
91 */
92 public static long fromHex(String string) {
93 return UnsignedLongs.parseUnsignedLong(string, 16);
94 }
95
96 /**
97 * Converts a long value to hex string; 16 wide and sans 0x.
98 *
99 * @param value long value
100 * @return hex string
101 */
102 public static String toHex(long value) {
103 return Strings.padStart(UnsignedLongs.toString(value, 16), 16, '0');
104 }
105
106 /**
107 * Converts a long value to hex string; 16 wide and sans 0x.
108 *
109 * @param value long value
110 * @param width string width; zero padded
111 * @return hex string
112 */
113 public static String toHex(long value, int width) {
114 return Strings.padStart(UnsignedLongs.toString(value, 16), width, '0');
115 }
tomf110fff2014-09-26 00:38:18 -0700116
117 /**
118 * Suspends the current thread for a specified number of millis.
119 *
120 * @param ms number of millis
121 */
122 public static void delay(int ms) {
123 try {
124 Thread.sleep(ms);
125 } catch (InterruptedException e) {
126 throw new RuntimeException("Interrupted", e);
127 }
128 }
129
tom53efab52014-10-07 17:43:48 -0700130 /**
131 * Slurps the contents of a file into a list of strings, one per line.
132 *
133 * @param path file path
134 * @return file contents
135 */
136 public static List<String> slurp(File path) {
Ray Milkey705d9bc2014-11-18 08:19:00 -0800137 try {
138 BufferedReader br = new BufferedReader(
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800139 new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8));
Ray Milkey705d9bc2014-11-18 08:19:00 -0800140
tom53efab52014-10-07 17:43:48 -0700141 List<String> lines = new ArrayList<>();
142 String line;
143 while ((line = br.readLine()) != null) {
144 lines.add(line);
145 }
146 return lines;
147
148 } catch (IOException e) {
149 return null;
150 }
151 }
152
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800153
154 /**
155 * Purges the specified directory path.&nbsp;Use with great caution since
156 * no attempt is made to check for symbolic links, which could result in
157 * deletion of unintended files.
158 *
159 * @param path directory to be removed
160 * @throws java.io.IOException if unable to remove contents
161 */
162 public static void removeDirectory(String path) throws IOException {
163 walkFileTree(Paths.get(path), new DirectoryDeleter());
164 }
165
166 /**
167 * Purges the specified directory path.&nbsp;Use with great caution since
168 * no attempt is made to check for symbolic links, which could result in
169 * deletion of unintended files.
170 *
171 * @param dir directory to be removed
172 * @throws java.io.IOException if unable to remove contents
173 */
174 public static void removeDirectory(File dir) throws IOException {
175 walkFileTree(Paths.get(dir.getAbsolutePath()), new DirectoryDeleter());
176 }
177
178
179 private static class DirectoryDeleter extends SimpleFileVisitor<Path> {
180 @Override
181 public FileVisitResult visitFile(Path file, BasicFileAttributes attributes)
182 throws IOException {
183 if (attributes.isRegularFile()) {
184 delete(file);
185 }
186 return FileVisitResult.CONTINUE;
187 }
188
189 @Override
190 public FileVisitResult postVisitDirectory(Path directory, IOException ioe)
191 throws IOException {
192 delete(directory);
193 return FileVisitResult.CONTINUE;
194 }
195
196 @Override
197 public FileVisitResult visitFileFailed(Path file, IOException ioe)
198 throws IOException {
199 log.warn("Unable to delete file {}", file);
200 log.warn("Boom", ioe);
201 return FileVisitResult.CONTINUE;
202 }
203 }
204
Thomas Vachuska90b453f2015-01-30 18:57:14 -0800205
206 /**
207 * Copies the specified directory path.&nbsp;Use with great caution since
208 * no attempt is made to check for symbolic links, which could result in
209 * copy of unintended files.
210 *
211 * @param src directory to be copied
212 * @param dst destination directory to be removed
213 * @throws java.io.IOException if unable to remove contents
214 */
215 public static void copyDirectory(String src, String dst) throws IOException {
216 walkFileTree(Paths.get(src), new DirectoryCopier(src, dst));
217 }
218
219 /**
220 * Copies the specified directory path.&nbsp;Use with great caution since
221 * no attempt is made to check for symbolic links, which could result in
222 * copy of unintended files.
223 *
224 * @param src directory to be copied
225 * @param dst destination directory to be removed
226 * @throws java.io.IOException if unable to remove contents
227 */
228 public static void copyDirectory(File src, File dst) throws IOException {
229 walkFileTree(Paths.get(src.getAbsolutePath()),
230 new DirectoryCopier(src.getAbsolutePath(),
231 dst.getAbsolutePath()));
232 }
233
234
235 public static class DirectoryCopier extends SimpleFileVisitor<Path> {
236 private Path src;
237 private Path dst;
238 private StandardCopyOption copyOption = StandardCopyOption.REPLACE_EXISTING;
239
240 DirectoryCopier(String src, String dst) {
241 this.src = Paths.get(src);
242 this.dst = Paths.get(dst);
243 }
244
245 @Override
246 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
247 Path targetPath = dst.resolve(src.relativize(dir));
248 if (!Files.exists(targetPath)) {
249 Files.createDirectory(targetPath);
250 }
251 return FileVisitResult.CONTINUE;
252 }
253
254 @Override
255 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
256 Files.copy(file, dst.resolve(src.relativize(file)), copyOption);
257 return FileVisitResult.CONTINUE;
258 }
259 }
260
tom5f38b3a2014-08-27 23:50:54 -0700261}