|
1 /* |
|
2 * Copyright (c) 2012, 2016, 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. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 * or visit www.oracle.com if you need additional information or have any |
|
23 * questions. |
|
24 */ |
|
25 |
|
26 package com.sun.tools.sjavac; |
|
27 |
|
28 import java.io.File; |
|
29 import java.io.PrintWriter; |
|
30 import java.io.StringWriter; |
|
31 import java.nio.file.Path; |
|
32 import java.util.Arrays; |
|
33 import java.util.Collection; |
|
34 import java.util.HashSet; |
|
35 import java.util.Map; |
|
36 import java.util.Set; |
|
37 import java.util.StringTokenizer; |
|
38 import java.util.function.Function; |
|
39 import java.util.regex.Pattern; |
|
40 import java.util.stream.Collectors; |
|
41 import java.util.stream.Stream; |
|
42 |
|
43 /** |
|
44 * Utilities. |
|
45 * |
|
46 * <p><b>This is NOT part of any supported API. |
|
47 * If you write code that depends on this, you do so at your own risk. |
|
48 * This code and its internal interfaces are subject to change or |
|
49 * deletion without notice.</b> |
|
50 */ |
|
51 public class Util { |
|
52 |
|
53 public static String toFileSystemPath(String pkgId) { |
|
54 if (pkgId == null || pkgId.length()==0) return null; |
|
55 String pn; |
|
56 if (pkgId.charAt(0) == ':') { |
|
57 // When the module is the default empty module. |
|
58 // Do not prepend the module directory, because there is none. |
|
59 // Thus :java.foo.bar translates to java/foo/bar (or \) |
|
60 pn = pkgId.substring(1).replace('.',File.separatorChar); |
|
61 } else { |
|
62 // There is a module. Thus jdk.base:java.foo.bar translates |
|
63 // into jdk.base/java/foo/bar |
|
64 int cp = pkgId.indexOf(':'); |
|
65 String mn = pkgId.substring(0,cp); |
|
66 pn = mn+File.separatorChar+pkgId.substring(cp+1).replace('.',File.separatorChar); |
|
67 } |
|
68 return pn; |
|
69 } |
|
70 |
|
71 public static String justPackageName(String pkgName) { |
|
72 int c = pkgName.indexOf(":"); |
|
73 if (c == -1) |
|
74 throw new IllegalArgumentException("Expected ':' in package name (" + pkgName + ")"); |
|
75 return pkgName.substring(c+1); |
|
76 } |
|
77 |
|
78 public static String extractStringOption(String opName, String s) { |
|
79 return extractStringOption(opName, s, null); |
|
80 } |
|
81 |
|
82 public static String extractStringOption(String opName, String s, String deflt) { |
|
83 int p = s.indexOf(opName+"="); |
|
84 if (p == -1) return deflt; |
|
85 p+=opName.length()+1; |
|
86 int pe = s.indexOf(',', p); |
|
87 if (pe == -1) pe = s.length(); |
|
88 return s.substring(p, pe); |
|
89 } |
|
90 |
|
91 public static boolean extractBooleanOption(String opName, String s, boolean deflt) { |
|
92 String str = extractStringOption(opName, s); |
|
93 return "true".equals(str) ? true |
|
94 : "false".equals(str) ? false |
|
95 : deflt; |
|
96 } |
|
97 |
|
98 public static int extractIntOption(String opName, String s) { |
|
99 return extractIntOption(opName, s, 0); |
|
100 } |
|
101 |
|
102 public static int extractIntOption(String opName, String s, int deflt) { |
|
103 int p = s.indexOf(opName+"="); |
|
104 if (p == -1) return deflt; |
|
105 p+=opName.length()+1; |
|
106 int pe = s.indexOf(',', p); |
|
107 if (pe == -1) pe = s.length(); |
|
108 int v = 0; |
|
109 try { |
|
110 v = Integer.parseInt(s.substring(p, pe)); |
|
111 } catch (Exception e) {} |
|
112 return v; |
|
113 } |
|
114 |
|
115 /** |
|
116 * Extract the package name from a fully qualified class name. |
|
117 * |
|
118 * Example: Given "pkg.subpkg.A" this method returns ":pkg.subpkg". |
|
119 * Given "C" this method returns ":". |
|
120 * |
|
121 * @returns package name of the given class name |
|
122 */ |
|
123 public static String pkgNameOfClassName(String fqClassName) { |
|
124 int i = fqClassName.lastIndexOf('.'); |
|
125 String pkg = i == -1 ? "" : fqClassName.substring(0, i); |
|
126 return ":" + pkg; |
|
127 } |
|
128 |
|
129 /** |
|
130 * Clean out unwanted sub options supplied inside a primary option. |
|
131 * For example to only had portfile remaining from: |
|
132 * settings="--server:id=foo,portfile=bar" |
|
133 * do settings = cleanOptions("--server:",Util.set("-portfile"),settings); |
|
134 * now settings equals "--server:portfile=bar" |
|
135 * |
|
136 * @param allowedSubOptions A set of the allowed sub options, id portfile etc. |
|
137 * @param s The option settings string. |
|
138 */ |
|
139 public static String cleanSubOptions(Set<String> allowedSubOptions, String s) { |
|
140 StringBuilder sb = new StringBuilder(); |
|
141 StringTokenizer st = new StringTokenizer(s, ","); |
|
142 while (st.hasMoreTokens()) { |
|
143 String o = st.nextToken(); |
|
144 int p = o.indexOf('='); |
|
145 if (p>0) { |
|
146 String key = o.substring(0,p); |
|
147 String val = o.substring(p+1); |
|
148 if (allowedSubOptions.contains(key)) { |
|
149 if (sb.length() > 0) sb.append(','); |
|
150 sb.append(key+"="+val); |
|
151 } |
|
152 } |
|
153 } |
|
154 return sb.toString(); |
|
155 } |
|
156 |
|
157 /** |
|
158 * Convenience method to create a set with strings. |
|
159 */ |
|
160 public static Set<String> set(String... ss) { |
|
161 Set<String> set = new HashSet<>(); |
|
162 set.addAll(Arrays.asList(ss)); |
|
163 return set; |
|
164 } |
|
165 |
|
166 /** |
|
167 * Normalize windows drive letter paths to upper case to enable string |
|
168 * comparison. |
|
169 * |
|
170 * @param file File name to normalize |
|
171 * @return The normalized string if file has a drive letter at the beginning, |
|
172 * otherwise the original string. |
|
173 */ |
|
174 public static String normalizeDriveLetter(String file) { |
|
175 if (file.length() > 2 && file.charAt(1) == ':') { |
|
176 return Character.toUpperCase(file.charAt(0)) + file.substring(1); |
|
177 } else if (file.length() > 3 && file.charAt(0) == '*' |
|
178 && file.charAt(2) == ':') { |
|
179 // Handle a wildcard * at the beginning of the string. |
|
180 return file.substring(0, 1) + Character.toUpperCase(file.charAt(1)) |
|
181 + file.substring(2); |
|
182 } |
|
183 return file; |
|
184 } |
|
185 |
|
186 /** |
|
187 * Locate the setting for the server properties. |
|
188 */ |
|
189 public static String findServerSettings(String[] args) { |
|
190 for (String s : args) { |
|
191 if (s.startsWith("--server:")) { |
|
192 return s; |
|
193 } |
|
194 } |
|
195 return null; |
|
196 } |
|
197 |
|
198 public static <E> Set<E> union(Set<? extends E> s1, |
|
199 Set<? extends E> s2) { |
|
200 Set<E> union = new HashSet<>(); |
|
201 union.addAll(s1); |
|
202 union.addAll(s2); |
|
203 return union; |
|
204 } |
|
205 |
|
206 public static <E> Set<E> subtract(Set<? extends E> orig, |
|
207 Set<? extends E> toSubtract) { |
|
208 Set<E> difference = new HashSet<>(orig); |
|
209 difference.removeAll(toSubtract); |
|
210 return difference; |
|
211 } |
|
212 |
|
213 public static String getStackTrace(Throwable t) { |
|
214 StringWriter sw = new StringWriter(); |
|
215 t.printStackTrace(new PrintWriter(sw)); |
|
216 return sw.toString(); |
|
217 } |
|
218 |
|
219 // TODO: Remove when refactoring from java.io.File to java.nio.file.Path. |
|
220 public static File pathToFile(Path path) { |
|
221 return path == null ? null : path.toFile(); |
|
222 } |
|
223 |
|
224 public static <E> Set<E> intersection(Collection<? extends E> c1, |
|
225 Collection<? extends E> c2) { |
|
226 Set<E> intersection = new HashSet<E>(c1); |
|
227 intersection.retainAll(c2); |
|
228 return intersection; |
|
229 } |
|
230 |
|
231 public static <I, T> Map<I, T> indexBy(Collection<? extends T> c, |
|
232 Function<? super T, ? extends I> indexFunction) { |
|
233 return c.stream().collect(Collectors.<T, I, T>toMap(indexFunction, o -> o)); |
|
234 } |
|
235 |
|
236 public static String fileSuffix(Path file) { |
|
237 String fileNameStr = file.getFileName().toString(); |
|
238 int dotIndex = fileNameStr.indexOf('.'); |
|
239 return dotIndex == -1 ? "" : fileNameStr.substring(dotIndex); |
|
240 } |
|
241 |
|
242 public static Stream<String> getLines(String str) { |
|
243 return str.isEmpty() |
|
244 ? Stream.empty() |
|
245 : Stream.of(str.split(Pattern.quote(System.lineSeparator()))); |
|
246 } |
|
247 } |