(empty log message)
@@ -16,7 +16,8 @@ | ||
16 | 16 | import jp.sourceforge.mergedoc.pleiades.runtime.LauncherTransformer; |
17 | 17 | |
18 | 18 | /** |
19 | - * Pleiades AOP を起動するためのエージェントです。 | |
19 | + * Pleiades AOP を起動するためのエージェントです。<br> | |
20 | + * このクラスは javaagent で指定される jar の manifest に Premain-Class として設定されています。 | |
20 | 21 | * @author cypher256 |
21 | 22 | */ |
22 | 23 | public class Pleiades { |
@@ -34,7 +35,7 @@ | ||
34 | 35 | private static File pleiadesTempDir; |
35 | 36 | |
36 | 37 | /** |
37 | - * 起動エントリー・ポイントとなると premain メソッドです。<br> | |
38 | + * 対象 Java アプリケーションの main メソッドの前に呼び出されるメソッドです。<br> | |
38 | 39 | * 起動時の main スレッドから呼び出されるため、時間がかかる処理は非同期で行います。 |
39 | 40 | * @param agentArg -javaagent 引数 |
40 | 41 | * @param inst トランスフォーマー登録・削除用 Instrumentation |
@@ -42,7 +43,7 @@ | ||
42 | 43 | public static void premain(final String agentArg, final Instrumentation inst) { |
43 | 44 | |
44 | 45 | try { |
45 | - // Eclipse ファイル > 再開 で premain が 2 回呼び出される問題に対応 | |
46 | + // Eclipse メニューの ファイル > 再開 で premain が 2 回呼び出される問題に対応 | |
46 | 47 | if (instrumentation != null) { |
47 | 48 | Logger log = Logger.getLogger(Pleiades.class); |
48 | 49 | log.info("instrumentation がすでに存在するため premain 処理を実行しません。"); |
@@ -88,8 +89,8 @@ | ||
88 | 89 | } |
89 | 90 | |
90 | 91 | /** |
91 | - * バイトコード変換トランスフォーマーを登録・削除するための Instrumentation を取得します。 | |
92 | - * @return トランスフォーマー登録・削除用 Instrumentation (not null) | |
92 | + * AOP バイトコード変換トランスフォーマーを登録・削除するための Instrumentation を取得します。 | |
93 | + * @return AOP トランスフォーマー登録・削除用 Instrumentation (not null) | |
93 | 94 | */ |
94 | 95 | public static Instrumentation getInstrumentation() { |
95 | 96 | return instrumentation; |
@@ -118,6 +119,6 @@ | ||
118 | 119 | * @return ファイル。JUnit やツールからの実行時は null。 |
119 | 120 | */ |
120 | 121 | public static File temp(String... path) { |
121 | - return Filez.concatPath(pleiadesTempDir, path); | |
122 | + return Filez.joinPath(pleiadesTempDir, path); | |
122 | 123 | } |
123 | 124 | } |
@@ -12,7 +12,7 @@ | ||
12 | 12 | import jp.sourceforge.mergedoc.pleiades.log.Logger.LogLevel; |
13 | 13 | |
14 | 14 | /** |
15 | - * Pleiades 全体から参照するコンテキスト情報です。 | |
15 | + * Pleiades 実行時に全体から参照されるコンテキスト情報です。 | |
16 | 16 | * @author cypher256 |
17 | 17 | */ |
18 | 18 | public class PleiadesContext { |
@@ -78,7 +78,7 @@ | ||
78 | 78 | * -javaagent:plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar=debug |
79 | 79 | * -javaagent:plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar=debug,no.clean.message |
80 | 80 | * </pre> |
81 | - * @param agentArg -javaagent 引数 (未指定の場合は null) | |
81 | + * @param agentArg -javaagent 引数 (未指定の場合は null) | |
82 | 82 | */ |
83 | 83 | PleiadesContext(String agentArg) { |
84 | 84 |
@@ -8,7 +8,6 @@ | ||
8 | 8 | |
9 | 9 | import java.io.File; |
10 | 10 | import java.io.PrintStream; |
11 | -import java.util.Collection; | |
12 | 11 | import java.util.HashMap; |
13 | 12 | import java.util.Map; |
14 | 13 |
@@ -26,16 +25,6 @@ | ||
26 | 25 | /** ファイル PrintStream マップ <ログファイル名, プリントストリーム> */ |
27 | 26 | private static Map<String, PrintStream> fileOutMap = new HashMap<>(); |
28 | 27 | |
29 | - /** | |
30 | - * 開かれている出力ストリームをクローズします。 | |
31 | - */ | |
32 | - public static void close() { // 厳密には getOut() と同期が必要 | |
33 | - | |
34 | - Collection<PrintStream> printStreams = fileOutMap.values(); | |
35 | - fileOutMap = null; | |
36 | - printStreams.forEach(Filez::closeQuietly); | |
37 | - } | |
38 | - | |
39 | 28 | //------------------------------------------------------------------------- |
40 | 29 | |
41 | 30 | /** ログ・ファイル名 */ |
@@ -62,17 +51,22 @@ | ||
62 | 51 | logFile.delete(); |
63 | 52 | PrintStream out = Filez.newPrintStream(logFile); |
64 | 53 | fileOutMap.put(logFileName, out); |
54 | + | |
55 | + // エラー時の System.exit に対応するためにシャットダウンフックでクローズ | |
56 | + Runtime.getRuntime().addShutdownHook(new Thread(() -> { | |
57 | + debug("シャットダウンフックによるクローズ: %s", logFile.getName()); | |
58 | + fileOutMap.remove(logFileName); // close 後の getOut 対応 | |
59 | + Filez.closeQuietly(out); | |
60 | + })); | |
65 | 61 | } |
66 | 62 | |
67 | 63 | /** |
68 | - * ファイル PrintStream を取得します。 | |
64 | + * ログ出力先となるファイル PrintStream を取得します。 | |
69 | 65 | */ |
70 | 66 | @Override |
71 | 67 | protected PrintStream getOut() { |
72 | - if (fileOutMap == null) { | |
73 | - return System.err; // close 済みの場合は、代わりにエラー出力を使用する | |
74 | - } | |
75 | - return fileOutMap.get(logFileName); | |
68 | + // null (close 済み) の場合は、代わりにエラー出力を使用する | |
69 | + return fileOutMap.getOrDefault(logFileName, System.err); | |
76 | 70 | } |
77 | 71 | |
78 | 72 | /** |
@@ -40,7 +40,7 @@ | ||
40 | 40 | String markResource = "/.marker"; |
41 | 41 | URL url = Filez.class.getResource(markResource); |
42 | 42 | if (url == null) { |
43 | - | |
43 | + | |
44 | 44 | // 注)ログの出力先は、これを元に解決されるため、この時点ではロガーは使用できない |
45 | 45 | String msg = "conf の場所を決定するためのファイルがクラスパス上に見つかりません。" + markResource; |
46 | 46 | Exception e = new FileNotFoundException(msg); |
@@ -76,7 +76,7 @@ | ||
76 | 76 | |
77 | 77 | /** |
78 | 78 | * 相対パスを指定して AOP 定義や辞書として読み取るファイルを取得します。<br> |
79 | - * 基準となるパスは .marker ファイルがあるディレクトリです。 | |
79 | + * 基準となるパスはクラスパス上の .marker ファイルがあるディレクトリです。 | |
80 | 80 | * <ul> |
81 | 81 | * <li>javaagent 実行時: plugins/jp.sourceforge.mergedoc.pleiades/conf |
82 | 82 | * <li>JUnit など実行時: src/main/resources |
@@ -85,7 +85,7 @@ | ||
85 | 85 | * @return リソース File オブジェクト |
86 | 86 | */ |
87 | 87 | public static File conf(String... path) { |
88 | - return concatPath(conf, path); | |
88 | + return joinPath(conf, path); | |
89 | 89 | } |
90 | 90 | |
91 | 91 | /** |
@@ -94,7 +94,7 @@ | ||
94 | 94 | * @param path 基準ディレクトリからの相対パス (可変長引数) |
95 | 95 | * @return 連結後の File オブジェクト (baseDir が null の場合は null) |
96 | 96 | */ |
97 | - public static File concatPath(File baseDir, String... path) { | |
97 | + public static File joinPath(File baseDir, String... path) { | |
98 | 98 | if (baseDir == null) { |
99 | 99 | return null; |
100 | 100 | } |
@@ -151,8 +151,8 @@ | ||
151 | 151 | if (closeable != null) { |
152 | 152 | closeable.close(); |
153 | 153 | } |
154 | - } catch (final IOException ioe) { | |
155 | - throw new IllegalStateException(ioe); | |
154 | + } catch (final IOException e) { | |
155 | + throw new IllegalStateException(e); | |
156 | 156 | } |
157 | 157 | } |
158 | 158 |
@@ -168,7 +168,7 @@ | ||
168 | 168 | String folderPath = folder.getCanonicalPath(); |
169 | 169 | String filePath = file.getCanonicalPath(); |
170 | 170 | return filePath.replace(folderPath, ""); |
171 | - | |
171 | + | |
172 | 172 | } catch (IOException e) { |
173 | 173 | throw new IllegalArgumentException(folder + ", " + file, e); |
174 | 174 | } |
@@ -91,7 +91,7 @@ | ||
91 | 91 | * @param props Java 標準プロパティー |
92 | 92 | */ |
93 | 93 | public PropertySet(Properties... props) { |
94 | - | |
94 | + | |
95 | 95 | for (Properties prop : props) { |
96 | 96 | for (Entry<Object, Object> entry : prop.entrySet()) { |
97 | 97 | put((String) entry.getKey(), (String) entry.getValue()); |
@@ -104,7 +104,7 @@ | ||
104 | 104 | * @param props プロパティー・セット |
105 | 105 | */ |
106 | 106 | public PropertySet(PropertySet... props) { |
107 | - | |
107 | + | |
108 | 108 | for (PropertySet prop : props) { |
109 | 109 | putAll(prop); |
110 | 110 | } |
@@ -125,7 +125,7 @@ | ||
125 | 125 | * @return このインスタンス |
126 | 126 | */ |
127 | 127 | public PropertySet load(String... paths) { |
128 | - | |
128 | + | |
129 | 129 | for (String path : paths) { |
130 | 130 | File file = Filez.conf(path); |
131 | 131 | load(file); |
@@ -141,19 +141,19 @@ | ||
141 | 141 | * @return このインスタンス |
142 | 142 | */ |
143 | 143 | public PropertySet load(File... files) { |
144 | - | |
144 | + | |
145 | 145 | for (File file : files) { |
146 | - | |
146 | + | |
147 | 147 | // ディレクトリーの場合 |
148 | 148 | if (file.isDirectory()) { |
149 | - | |
149 | + | |
150 | 150 | for (File f : listPropertiesFiles(file)) { |
151 | - loadFile(f); | |
151 | + loadFileWithLog(f); | |
152 | 152 | } |
153 | 153 | } |
154 | 154 | // ファイルの場合 |
155 | 155 | else { |
156 | - loadFile(file); | |
156 | + loadFileWithLog(file); | |
157 | 157 | } |
158 | 158 | } |
159 | 159 | return this; |
@@ -166,11 +166,11 @@ | ||
166 | 166 | * @return プロパティー・ファイル・リスト |
167 | 167 | */ |
168 | 168 | public static File[] listPropertiesFiles(File dir) { |
169 | - | |
169 | + | |
170 | 170 | File[] fs = Filez.listFiles(dir); |
171 | 171 | Arrays.sort(fs); // 昇順 |
172 | 172 | List<File> list = new ArrayList<>(); |
173 | - | |
173 | + | |
174 | 174 | for (File f : fs) { |
175 | 175 | String name = f.getName(); |
176 | 176 | if (name.endsWith(PROP_EXTENSION) || name.endsWith(PROP_EXTENSION + ZIP_EXTENSION)) { |
@@ -186,10 +186,10 @@ | ||
186 | 186 | * @param is 入力ストリーム |
187 | 187 | */ |
188 | 188 | public void load(InputStream is) { |
189 | - | |
189 | + | |
190 | 190 | try { |
191 | 191 | loadUTF8(is); |
192 | - | |
192 | + | |
193 | 193 | } catch (IOException e) { |
194 | 194 | throw new IllegalArgumentException(e); |
195 | 195 | } |
@@ -201,12 +201,12 @@ | ||
201 | 201 | * @param dirs ディレクトリー |
202 | 202 | */ |
203 | 203 | public void loadRecursive(File... dirs) { |
204 | - | |
204 | + | |
205 | 205 | for (File dir : dirs) { |
206 | - | |
206 | + | |
207 | 207 | File[] fs = dir.listFiles(); |
208 | 208 | Arrays.sort(fs); // 昇順 |
209 | - | |
209 | + | |
210 | 210 | for (File f : fs) { |
211 | 211 | if (f.isDirectory()) { |
212 | 212 | loadRecursive(f); // 再帰 |
@@ -233,7 +233,7 @@ | ||
233 | 233 | */ |
234 | 234 | @Override |
235 | 235 | public void putAll(Map<? extends String, ? extends String> m) { |
236 | - | |
236 | + | |
237 | 237 | for (Entry<? extends String, ? extends String> entry : m.entrySet()) { |
238 | 238 | put(entry.getKey(), entry.getValue()); |
239 | 239 | } |
@@ -246,7 +246,7 @@ | ||
246 | 246 | * @return 保存されたキーのリスト (ソート済み)。保存されなかった場合は null。 |
247 | 247 | */ |
248 | 248 | public List<String> store(String path, String comment) { |
249 | - | |
249 | + | |
250 | 250 | File resourceFile = Filez.conf(path); |
251 | 251 | return store(resourceFile, comment); |
252 | 252 | } |
@@ -258,20 +258,20 @@ | ||
258 | 258 | * @return 保存されたキーのリスト (ソート済み)。保存されなかった場合は null。 |
259 | 259 | */ |
260 | 260 | public List<String> store(File file, String comment) { |
261 | - | |
261 | + | |
262 | 262 | long startTime = System.nanoTime(); |
263 | 263 | String fileName = file.getName(); |
264 | - | |
264 | + | |
265 | 265 | // 既存ファイルと内容が同じであれば保存しない (コメントの日付更新抑止) |
266 | 266 | if (file.exists() && fileName.endsWith(PROP_EXTENSION)) { |
267 | 267 | PropertySet old = new PropertySet(); |
268 | - old.loadFileWithoutLog(file); | |
268 | + old.loadFile(file); | |
269 | 269 | if (old.equals(this)) { |
270 | 270 | log.info("store 更新なし %6d エントリー %-34s", size(), fileName); |
271 | 271 | return null; |
272 | 272 | } |
273 | 273 | } |
274 | - | |
274 | + | |
275 | 275 | // ヘッダーの作成 |
276 | 276 | List<String> headerList = new ArrayList<>(); |
277 | 277 | headerList.add(saveConvertComment("このファイルは Pleiades により生成されました。" + size() + " エントリー。")); |
@@ -283,11 +283,11 @@ | ||
283 | 283 | headerList.add("# "); |
284 | 284 | headerList.add("####################################################################################################"); |
285 | 285 | String header = StringUtils.join(headerList, "\n"); |
286 | - | |
286 | + | |
287 | 287 | OutputStream os = null; |
288 | 288 | try { |
289 | 289 | os = Filez.newBufferedOutputStream(file); |
290 | - | |
290 | + | |
291 | 291 | // 拡張子が .properties.zip の場合、ZipOutputStream でラップ |
292 | 292 | if (fileName.endsWith(PROP_EXTENSION + ZIP_EXTENSION)) { |
293 | 293 | ZipOutputStream zos = new ZipOutputStream(os); |
@@ -296,15 +296,15 @@ | ||
296 | 296 | os = zos; |
297 | 297 | } |
298 | 298 | List<String> keyList = store(os, header); |
299 | - | |
299 | + | |
300 | 300 | log.info("store %4.3f 秒 - %6d エントリー %s", (System.nanoTime() - startTime) / 1e9, size(), fileName); |
301 | 301 | return keyList; |
302 | - | |
302 | + | |
303 | 303 | } catch (IOException e) { |
304 | 304 | throw new IllegalArgumentException(file.toString(), e); |
305 | - | |
305 | + | |
306 | 306 | } finally { |
307 | - Filez.closeQuietly(os); | |
307 | + Filez.closeQuietly(os); // zos ラップのため try-with- は使用できない | |
308 | 308 | } |
309 | 309 | } |
310 | 310 |
@@ -315,22 +315,22 @@ | ||
315 | 315 | */ |
316 | 316 | @Override |
317 | 317 | public Iterator<Property> iterator() { |
318 | - | |
318 | + | |
319 | 319 | final Iterator<Entry<String, String>> it = entrySet().iterator(); |
320 | - | |
320 | + | |
321 | 321 | return new Iterator<>() { |
322 | - | |
322 | + | |
323 | 323 | @Override |
324 | 324 | public boolean hasNext() { |
325 | 325 | return it.hasNext(); |
326 | 326 | } |
327 | - | |
327 | + | |
328 | 328 | @Override |
329 | 329 | public Property next() { |
330 | 330 | Entry<String, String> entry = it.next(); |
331 | 331 | return new Property(entry.getKey(), entry.getValue()); |
332 | 332 | } |
333 | - | |
333 | + | |
334 | 334 | @Override |
335 | 335 | public void remove() { |
336 | 336 | throw new UnsupportedOperationException(); |
@@ -345,10 +345,10 @@ | ||
345 | 345 | private int loadCount; |
346 | 346 | |
347 | 347 | protected InputStream getInputStream(File file) throws IOException { |
348 | - | |
348 | + | |
349 | 349 | // 拡張子 .properties |
350 | 350 | InputStream is = Filez.newBufferedInputStream(file); |
351 | - | |
351 | + | |
352 | 352 | // 拡張子 .properties.zip |
353 | 353 | if (file.getName().endsWith(PROP_EXTENSION + ZIP_EXTENSION)) { |
354 | 354 | ZipInputStream zis = new ZipInputStream(is); |
@@ -358,24 +358,22 @@ | ||
358 | 358 | return is; |
359 | 359 | } |
360 | 360 | |
361 | - private void loadFile(File file) { | |
362 | - | |
361 | + private void loadFileWithLog(File file) { | |
362 | + | |
363 | 363 | long startTime = System.nanoTime(); |
364 | - | |
365 | - loadFileWithoutLog(file); | |
366 | - | |
364 | + loadFile(file); | |
367 | 365 | log.debug("load %4.3f 秒 - %6d エントリー %s", (System.nanoTime() - startTime) / 1e9, loadCount, file.getName()); |
368 | 366 | loadCount = 0; |
369 | 367 | } |
370 | 368 | |
371 | - private void loadFileWithoutLog(File file) { | |
372 | - | |
369 | + private void loadFile(File file) { | |
370 | + | |
373 | 371 | try (InputStream is = getInputStream(file)) { |
374 | 372 | if (is == null) { |
375 | 373 | return; |
376 | 374 | } |
377 | - loadUTF8(is); | |
378 | - | |
375 | + loadUTF8(is); | |
376 | + | |
379 | 377 | } catch (IOException e) { |
380 | 378 | throw new IllegalArgumentException(e); |
381 | 379 | } |
@@ -382,7 +380,7 @@ | ||
382 | 380 | } |
383 | 381 | |
384 | 382 | private void loadUTF8(InputStream is) throws IOException { |
385 | - load0(new LineReader(new InputStreamReader(is, StandardCharsets.UTF_8))); | |
383 | + load0(new LineReader(new InputStreamReader(is, StandardCharsets.UTF_8))); | |
386 | 384 | } |
387 | 385 | |
388 | 386 | private void load0(LineReader lr) throws IOException { |
@@ -393,13 +391,13 @@ | ||
393 | 391 | char c; |
394 | 392 | boolean hasSep; |
395 | 393 | boolean precedingBackslash; |
396 | - | |
394 | + | |
397 | 395 | while ((limit = lr.readLine()) >= 0) { |
398 | 396 | c = 0; |
399 | 397 | keyLen = 0; |
400 | 398 | valueStart = limit; |
401 | 399 | hasSep = false; |
402 | - | |
400 | + | |
403 | 401 | // System.out.println("line=<" + new String(lineBuf, 0, limit) + ">"); |
404 | 402 | precedingBackslash = false; |
405 | 403 | while (keyLen < limit) { |
@@ -440,13 +438,13 @@ | ||
440 | 438 | |
441 | 439 | @SuppressWarnings("unchecked") |
442 | 440 | private List<String> store(OutputStream out, String comments) throws IOException { |
443 | - | |
441 | + | |
444 | 442 | BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8)); |
445 | 443 | if (comments != null) { |
446 | 444 | writeln(writer, "#" + comments); |
447 | 445 | } |
448 | 446 | writeln(writer, "#" + new Date().toString()); |
449 | - | |
447 | + | |
450 | 448 | // ConcurrentModificationException 低減のため clone |
451 | 449 | HashMap<String, String> c = null; |
452 | 450 | try { |
@@ -460,11 +458,11 @@ | ||
460 | 458 | return null; |
461 | 459 | } |
462 | 460 | } |
463 | - | |
461 | + | |
464 | 462 | // キーでソート |
465 | 463 | List<String> keyList = new ArrayList<>(c.keySet()); |
466 | 464 | keyList.sort(String.CASE_INSENSITIVE_ORDER); |
467 | - | |
465 | + | |
468 | 466 | for (String key : keyList) { |
469 | 467 | String val = get(key); |
470 | 468 | key = saveConvert(key, true); |
@@ -472,17 +470,17 @@ | ||
472 | 470 | writeln(writer, key + "=" + val); |
473 | 471 | } |
474 | 472 | writer.flush(); |
475 | - | |
473 | + | |
476 | 474 | return keyList; |
477 | 475 | } |
478 | 476 | |
479 | 477 | class LineReader { |
480 | - | |
478 | + | |
481 | 479 | public LineReader(Reader reader) { |
482 | 480 | this.reader = reader; |
483 | 481 | inCharBuf = new char[8192]; |
484 | 482 | } |
485 | - | |
483 | + | |
486 | 484 | byte[] inByteBuf; |
487 | 485 | char[] inCharBuf; |
488 | 486 | char[] lineBuf = new char[1024]; |
@@ -489,11 +487,11 @@ | ||
489 | 487 | int inLimit = 0; |
490 | 488 | int inOff = 0; |
491 | 489 | Reader reader; |
492 | - | |
490 | + | |
493 | 491 | int readLine() throws IOException { |
494 | 492 | int len = 0; |
495 | 493 | char c = 0; |
496 | - | |
494 | + | |
497 | 495 | boolean skipWhiteSpace = true; |
498 | 496 | boolean isCommentLine = false; |
499 | 497 | boolean isNewLine = true; |
@@ -500,7 +498,7 @@ | ||
500 | 498 | boolean appendedLineBegin = false; |
501 | 499 | boolean precedingBackslash = false; |
502 | 500 | boolean skipLF = false; |
503 | - | |
501 | + | |
504 | 502 | while (true) { |
505 | 503 | if (inOff >= inLimit) { |
506 | 504 | inLimit = reader.read(inCharBuf); |
@@ -536,7 +534,7 @@ | ||
536 | 534 | continue; |
537 | 535 | } |
538 | 536 | } |
539 | - | |
537 | + | |
540 | 538 | if (c != '\n' && c != '\r') { |
541 | 539 | lineBuf[len++] = c; |
542 | 540 | if (len == lineBuf.length) { |
@@ -600,7 +598,7 @@ | ||
600 | 598 | char[] out = convtBuf; |
601 | 599 | int outLen = 0; |
602 | 600 | int end = off + len; |
603 | - | |
601 | + | |
604 | 602 | while (off < end) { |
605 | 603 | aChar = in[off++]; |
606 | 604 | if (aChar == '\\') { |
@@ -664,13 +662,13 @@ | ||
664 | 662 | } |
665 | 663 | |
666 | 664 | private String saveConvertComment(String theString) { |
667 | - | |
665 | + | |
668 | 666 | String space = theString.replaceFirst("(\\s*).*", "$1"); |
669 | 667 | return space + saveConvert(theString.trim(), false); |
670 | 668 | } |
671 | 669 | |
672 | 670 | private String saveConvert(String theString, boolean escapeSpace) { |
673 | - | |
671 | + | |
674 | 672 | int len = theString.length(); |
675 | 673 | int bufLen = len * 2; |
676 | 674 | if (bufLen < 0) { |
@@ -677,7 +675,7 @@ | ||
677 | 675 | bufLen = Integer.MAX_VALUE; |
678 | 676 | } |
679 | 677 | StringBuilder outBuffer = new StringBuilder(bufLen); |
680 | - | |
678 | + | |
681 | 679 | for (int x = 0; x < len; x++) { |
682 | 680 | char aChar = theString.charAt(x); |
683 | 681 | if ((aChar > 61) && (aChar < 127)) { |
@@ -30,7 +30,7 @@ | ||
30 | 30 | private static final Logger log = Logger.getLogger(TranslationNotFoundProperties.class); |
31 | 31 | |
32 | 32 | /** 訳無しプロパティー出力ファイル名 */ |
33 | - private static final File NOT_FOUND_LOG_FILE = Pleiades.temp("translation-notfound.properties"); | |
33 | + private static final File NOTFOUND_PROP_FILE = Pleiades.temp("translation-notfound.properties"); | |
34 | 34 | |
35 | 35 | /** 訳無しプロパティー出力から除外する要素をリストしたファイル名 */ |
36 | 36 | private static final File NOTFOUND_EXCLUDE_FILE = Filez.conf("translation-notfound-exclud.list"); |
@@ -82,13 +82,13 @@ | ||
82 | 82 | */ |
83 | 83 | // Java 11 以降で private だと AOP エラーになる |
84 | 84 | protected void init() { |
85 | - | |
85 | + | |
86 | 86 | excludSet = new HashSet<>(); |
87 | 87 | excludPatternSet = new HashSet<>(); |
88 | 88 | loggedSet = Collections.synchronizedSet(new HashSet<>()); |
89 | - | |
89 | + | |
90 | 90 | try (BufferedReader in = new BufferedReader(new FileReader(NOTFOUND_EXCLUDE_FILE))) { |
91 | - | |
91 | + | |
92 | 92 | for (String line; (line = in.readLine()) != null;) { |
93 | 93 | if (!line.startsWith("#")) { |
94 | 94 | String str = line.replace("\\n", "\n"); |
@@ -106,12 +106,12 @@ | ||
106 | 106 | log.fatal(msg); |
107 | 107 | throw new IllegalStateException(msg, e); |
108 | 108 | } |
109 | - | |
110 | - out = Filez.newPrintStream(NOT_FOUND_LOG_FILE); | |
111 | - | |
109 | + | |
110 | + out = Filez.newPrintStream(NOTFOUND_PROP_FILE); | |
111 | + | |
112 | 112 | // VM シャットダウン・フックに PrintStream のクローズを登録 |
113 | 113 | Runtime.getRuntime().addShutdownHook(new Thread(() -> { |
114 | - // ここではすでにログはクローズ済みのため、出力できない | |
114 | + log.debug("シャットダウンフックによるクローズ: %s", NOTFOUND_PROP_FILE.getName()); | |
115 | 115 | Filez.closeQuietly(out); |
116 | 116 | })); |
117 | 117 | log.debug("訳無しプロパティーを生成しました。"); |
@@ -126,10 +126,10 @@ | ||
126 | 126 | * @param enTs 英語文字列 |
127 | 127 | */ |
128 | 128 | public void put(TranslationString enTs) { |
129 | - | |
129 | + | |
130 | 130 | // trimForce された状態を元に戻す |
131 | 131 | enTs.init(); |
132 | - | |
132 | + | |
133 | 133 | println(enTs.toString().trim()); |
134 | 134 | println(enTs.trim()); |
135 | 135 | println(enTs.trimForce()); |
@@ -140,7 +140,7 @@ | ||
140 | 140 | * @param en ニーモニックを含まない英語リソース文字列 |
141 | 141 | */ |
142 | 142 | protected void println(String en) { |
143 | - | |
143 | + | |
144 | 144 | if (loggedSet.contains(en)) { |
145 | 145 | return; |
146 | 146 | } |
@@ -153,10 +153,10 @@ | ||
153 | 153 | } |
154 | 154 | } |
155 | 155 | loggedSet.add(en); |
156 | - | |
156 | + | |
157 | 157 | String key = Property.escapeKey(en); |
158 | 158 | String value = Property.escapeValue(en); |
159 | - | |
159 | + | |
160 | 160 | // 翻訳しやすいように右辺の改行文字は空白に置換 |
161 | 161 | value = value.replace("\\r", " "); |
162 | 162 | value = value.replace("\\n", " "); |
@@ -53,8 +53,8 @@ | ||
53 | 53 | try { |
54 | 54 | return super.computeIfAbsent(key, mappingFunction); |
55 | 55 | } catch (ConcurrentModificationException e) { |
56 | - // ほぼ発生しないが 1 回だけリトライ (debug 時のみだが目立つように warn レベル) | |
57 | - getLog().warn(e, "計測記録リトライ %s", key); | |
56 | + // 数百万回に 1 回程度しか発生しないが 1 回だけリトライ (このクラスの処理は debug 時のみ) | |
57 | + getLog().debug(e, "計測記録リトライ computeIfAbsent %s", key); | |
58 | 58 | return super.computeIfAbsent(key, mappingFunction); |
59 | 59 | } |
60 | 60 | } |
@@ -243,7 +243,7 @@ | ||
243 | 243 | * @return Eclipse ホーム・ディレクトリー。Eclipse javaagent からの起動ではない場合 (IDEA など) は null。 |
244 | 244 | */ |
245 | 245 | public static File eclipseHome(String... path) { |
246 | - return Filez.concatPath(eclipseHome, path); | |
246 | + return Filez.joinPath(eclipseHome, path); | |
247 | 247 | } |
248 | 248 | |
249 | 249 | /** |
@@ -253,6 +253,6 @@ | ||
253 | 253 | * @return Eclipse OSGi ホーム・ディレクトリー。Eclipse javaagent からの起動ではない場合 (IDEA など) は null。 |
254 | 254 | */ |
255 | 255 | public static File osgiHome(String... path) { |
256 | - return Filez.concatPath(osgiHome, path); | |
256 | + return Filez.joinPath(osgiHome, path); | |
257 | 257 | } |
258 | 258 | } |
@@ -18,7 +18,6 @@ | ||
18 | 18 | import javassist.CtMethod; |
19 | 19 | import javassist.NotFoundException; |
20 | 20 | import jp.sourceforge.mergedoc.pleiades.Pleiades; |
21 | -import jp.sourceforge.mergedoc.pleiades.log.FileLogger; | |
22 | 21 | import jp.sourceforge.mergedoc.pleiades.log.Logger; |
23 | 22 | import jp.sourceforge.mergedoc.pleiades.resource.PropertySet; |
24 | 23 | import jp.sourceforge.mergedoc.pleiades.runtime.advice.PleiadesConfig; |
@@ -382,9 +381,6 @@ | ||
382 | 381 | |
383 | 382 | // プロセス間排他ロック解除 |
384 | 383 | ProcessLockz.release(); |
385 | - | |
386 | - // ログファイルのクローズ | |
387 | - FileLogger.close(); | |
388 | 384 | } |
389 | 385 | } |
390 | 386 | } |
@@ -28,7 +28,7 @@ | ||
28 | 28 | private static final Logger log = Logger.getLogger(ProcessLockz.class); |
29 | 29 | |
30 | 30 | /** ロック・ファイル */ |
31 | - private static final File lockFile = Pleiades.temp(".lock"); | |
31 | + private static final File LOCK_FILE = Pleiades.temp(".lock"); | |
32 | 32 | |
33 | 33 | /** ロック・ファイル・チャンネル */ |
34 | 34 | private static volatile FileChannel fileChannel; |
@@ -35,7 +35,7 @@ | ||
35 | 35 | |
36 | 36 | static { |
37 | 37 | try { |
38 | - lockFile.createNewFile(); | |
38 | + LOCK_FILE.createNewFile(); | |
39 | 39 | } catch (IOException e) { |
40 | 40 | log.error(e, "プロセス間排他ロック・ファイルの作成に失敗しました。"); |
41 | 41 | } |
@@ -56,7 +56,7 @@ | ||
56 | 56 | } |
57 | 57 | log.debug("プロセス間排他ロックします。"); |
58 | 58 | |
59 | - try (RandomAccessFile raf = new RandomAccessFile(lockFile.getPath(), "rw")) { | |
59 | + try (RandomAccessFile raf = new RandomAccessFile(LOCK_FILE.getPath(), "rw")) { | |
60 | 60 | fileChannel = raf.getChannel(); |
61 | 61 | |
62 | 62 | FileLock lock = fileChannel.tryLock(); |
@@ -28,10 +28,11 @@ | ||
28 | 28 | * @return 1 つでも更新されている場合は true |
29 | 29 | */ |
30 | 30 | public boolean isUpdated(File... targetDirs) throws IOException { |
31 | - | |
31 | + | |
32 | 32 | if (targetDirs.length == 0) { |
33 | 33 | throw new IllegalStateException("ターゲットディレクトリが指定されていません。"); |
34 | 34 | } |
35 | + | |
35 | 36 | long start = System.nanoTime(); |
36 | 37 | File pluginModifiedFile = Pleiades.temp(".plugin-modified"); |
37 | 38 | long prevLastModified = pluginModifiedFile.lastModified(); |
@@ -57,6 +58,7 @@ | ||
57 | 58 | pluginModifiedFile.setLastModified(lastModified); |
58 | 59 | isUpdated = true; |
59 | 60 | } |
61 | + | |
60 | 62 | Analyses.end(Applicationz.class, "isUpdated", start); |
61 | 63 | return isUpdated; |
62 | 64 | } |
@@ -73,14 +75,17 @@ | ||
73 | 75 | boolean isParentPluginsDir = parent.equals("plugins") || parent.equals("lib"/* IDEA */); |
74 | 76 | |
75 | 77 | for (File file : parentDir.listFiles()) { |
78 | + String name = file.getName(); | |
76 | 79 | |
77 | - String name = file.getName(); | |
78 | 80 | if (name.equals("features") || name.startsWith(".")) { |
79 | 81 | // チェックしない |
82 | + | |
80 | 83 | } else if (isParentPluginsDir) { |
81 | 84 | // 親がプラグインディレクトリの場合は再帰しないで自身のみチェック (ファイルの場合もあり) |
82 | 85 | latest = max(file, latest); |
86 | + | |
83 | 87 | } else if (file.isFile()) { |
88 | + | |
84 | 89 | if (name.endsWith(".xml") || name.endsWith(".properties")) { |
85 | 90 | // conf 配下の設定ファイル (画像などを除く) |
86 | 91 | latest = max(file, latest); |
@@ -29,7 +29,7 @@ | ||
29 | 29 | private static final Logger log = Logger.getLogger(ExcludeClassNameCache.class); |
30 | 30 | |
31 | 31 | /** 変換除外クラス名キャッシュ・ファイル */ |
32 | - public static final File cacheFile = Pleiades.temp(CacheFilez.EXCLUDE_CLASS_LIST); | |
32 | + public static final File EXCLUDE_CACHE_FILE = Pleiades.temp(CacheFilez.EXCLUDE_CLASS_LIST); | |
33 | 33 | |
34 | 34 | /** このクラスのシングルトン・インスタンス */ |
35 | 35 | private static final ExcludeClassNameCache singleton = new ExcludeClassNameCache(); |
@@ -66,20 +66,20 @@ | ||
66 | 66 | long start = System.nanoTime(); |
67 | 67 | Set<String> set = new HashSet<>(); |
68 | 68 | |
69 | - if (!cacheFile.exists()) { | |
70 | - log.info(cacheFile.getName() + " が存在しません。"); | |
69 | + if (!EXCLUDE_CACHE_FILE.exists()) { | |
70 | + log.info(EXCLUDE_CACHE_FILE.getName() + " が存在しません。"); | |
71 | 71 | |
72 | 72 | } else { |
73 | 73 | |
74 | 74 | try { |
75 | - set.addAll(FileUtils.readLines(cacheFile, StandardCharsets.UTF_8)); | |
76 | - log.info("load %6d エントリー %s", set.size(), cacheFile.getName()); | |
75 | + set.addAll(FileUtils.readLines(EXCLUDE_CACHE_FILE, StandardCharsets.UTF_8)); | |
76 | + log.info("load %6d エントリー %s", set.size(), EXCLUDE_CACHE_FILE.getName()); | |
77 | 77 | |
78 | 78 | } catch (Exception e) { |
79 | 79 | |
80 | 80 | // キャッシュ破損、自己復元 |
81 | - log.warn("除外クラス名キャッシュ %s の破損を検出。復元中... - %s", cacheFile, e.toString()); | |
82 | - cacheFile.delete(); | |
81 | + log.warn("除外クラス名キャッシュ %s の破損を検出。復元中... - %s", EXCLUDE_CACHE_FILE, e.toString()); | |
82 | + EXCLUDE_CACHE_FILE.delete(); | |
83 | 83 | set.clear(); |
84 | 84 | } |
85 | 85 | } |
@@ -105,11 +105,11 @@ | ||
105 | 105 | storeSet = null; |
106 | 106 | diskSet.addAll(newSet); |
107 | 107 | |
108 | - FileUtils.writeLines(cacheFile, null, diskSet); | |
109 | - log.info("store %6d エントリー %s", diskSet.size(), cacheFile.getName()); | |
108 | + FileUtils.writeLines(EXCLUDE_CACHE_FILE, null, diskSet); | |
109 | + log.info("store %6d エントリー %s", diskSet.size(), EXCLUDE_CACHE_FILE.getName()); | |
110 | 110 | |
111 | 111 | } catch (IOException e) { |
112 | - log.error(e, cacheFile.getName() + " の保存に失敗しました。"); | |
112 | + log.error(e, EXCLUDE_CACHE_FILE.getName() + " の保存に失敗しました。"); | |
113 | 113 | } |
114 | 114 | } |
115 | 115 |
@@ -31,6 +31,9 @@ | ||
31 | 31 | /** ロガー */ |
32 | 32 | private static final Logger log = Logger.getLogger(TransformedClassCache.class); |
33 | 33 | |
34 | + /** クラス・キャッシュ・ファイル */ | |
35 | + private static final File CLASS_CACHE_FILE = Pleiades.temp(CacheFilez.TRANSFORMED_CLASS_CACHE); | |
36 | + | |
34 | 37 | /** このクラスのシングルトン・インスタンス */ |
35 | 38 | private static final TransformedClassCache singleton = new TransformedClassCache(); |
36 | 39 |
@@ -44,9 +47,6 @@ | ||
44 | 47 | |
45 | 48 | //------------------------------------------------------------------------- |
46 | 49 | |
47 | - /** クラス・キャッシュ・ファイル */ | |
48 | - private final File cacheFile = Pleiades.temp(CacheFilez.TRANSFORMED_CLASS_CACHE); | |
49 | - | |
50 | 50 | /** ロードされたクラス・マップ */ |
51 | 51 | private Map<String, byte[]> loadedMap = new HashMap<>(); |
52 | 52 |
@@ -69,12 +69,12 @@ | ||
69 | 69 | long start = System.nanoTime(); |
70 | 70 | Map<String, byte[]> map = new HashMap<>(); |
71 | 71 | |
72 | - if (!cacheFile.exists()) { | |
73 | - log.info(cacheFile.getName() + " が存在しません。"); | |
72 | + if (!CLASS_CACHE_FILE.exists()) { | |
73 | + log.info(CLASS_CACHE_FILE.getName() + " が存在しません。"); | |
74 | 74 | |
75 | 75 | } else { |
76 | 76 | |
77 | - try (ZipInputStream zis = new ZipInputStream(Filez.newBufferedInputStream(cacheFile))) { | |
77 | + try (ZipInputStream zis = new ZipInputStream(Filez.newBufferedInputStream(CLASS_CACHE_FILE))) { | |
78 | 78 | for (ZipEntry zipEntry; (zipEntry = zis.getNextEntry()) != null;) { |
79 | 79 | |
80 | 80 | String classId = zipEntry.getName(); |
@@ -81,12 +81,12 @@ | ||
81 | 81 | byte[] bytecode = zis.readAllBytes(); |
82 | 82 | map.put(classId, bytecode); |
83 | 83 | } |
84 | - log.info("load %6d エントリー %s", map.size(), cacheFile.getName()); | |
84 | + log.info("load %6d エントリー %s", map.size(), CLASS_CACHE_FILE.getName()); | |
85 | 85 | |
86 | 86 | } catch (Exception e) { |
87 | 87 | |
88 | - log.warn("変換済みクラス・キャッシュ %s 破損検出によるクリア - %s", cacheFile, e.toString()); | |
89 | - cacheFile.delete(); | |
88 | + log.warn("変換済みクラス・キャッシュ %s 破損検出によるクリア - %s", CLASS_CACHE_FILE, e.toString()); | |
89 | + CLASS_CACHE_FILE.delete(); | |
90 | 90 | map.clear(); |
91 | 91 | } |
92 | 92 | } |
@@ -106,7 +106,7 @@ | ||
106 | 106 | return; |
107 | 107 | } |
108 | 108 | Map<String, byte[]> map = load(); |
109 | - try (ZipOutputStream out = new ZipOutputStream(Filez.newBufferedOutputStream(cacheFile))) { | |
109 | + try (ZipOutputStream out = new ZipOutputStream(Filez.newBufferedOutputStream(CLASS_CACHE_FILE))) { | |
110 | 110 | out.setLevel(Deflater.BEST_SPEED); |
111 | 111 | |
112 | 112 | // ConcurrentModificationException 防止 |
@@ -120,10 +120,10 @@ | ||
120 | 120 | out.putNextEntry(new ZipEntry(classId)); |
121 | 121 | out.write(bytecode); |
122 | 122 | } |
123 | - log.info("store %6d エントリー %s", map.size(), cacheFile.getName()); | |
123 | + log.info("store %6d エントリー %s", map.size(), CLASS_CACHE_FILE.getName()); | |
124 | 124 | |
125 | 125 | } catch (IOException e) { |
126 | - log.error(e, cacheFile.getName() + "の保存に失敗しました。"); | |
126 | + log.error(e, CLASS_CACHE_FILE.getName() + "の保存に失敗しました。"); | |
127 | 127 | } |
128 | 128 | } |
129 | 129 |
@@ -44,10 +44,10 @@ | ||
44 | 44 | private static final Logger log = Logger.getLogger(TranslationDictionary.class); |
45 | 45 | |
46 | 46 | /** 翻訳キャッシュ・プロパティー・ファイル */ |
47 | - private static final File transCacheFile = Pleiades.temp(CacheFilez.TRANS_CACHE_PROP); | |
47 | + private static final File TRANS_CACHE_FILE = Pleiades.temp(CacheFilez.TRANS_CACHE_PROP); | |
48 | 48 | |
49 | 49 | /** ニーモニック変換キャッシュ・プロパティー・ファイル */ |
50 | - private static final File mnemonicCacheFile = Pleiades.temp(CacheFilez.MNEMONIC_CACHE_PROP); | |
50 | + private static final File MNEMONIC_CACHE_FILE = Pleiades.temp(CacheFilez.MNEMONIC_CACHE_PROP); | |
51 | 51 | |
52 | 52 | /** 正規表現キープレフィックス */ |
53 | 53 | private static final String REGEX_KEY_PREFIX = "%REGEX%"; |
@@ -145,24 +145,24 @@ | ||
145 | 145 | mnemonicCacheProp = new CachePropertySet(5000, "ニーモニック変換キャッシュ・プロパティー"); |
146 | 146 | |
147 | 147 | // キャッシュファイルがある場合 (2 回目以降の起動) : JUnit 起動時は null |
148 | - if (transCacheFile != null && transCacheFile.exists()) { | |
148 | + if (TRANS_CACHE_FILE != null && TRANS_CACHE_FILE.exists()) { | |
149 | 149 | |
150 | 150 | // 翻訳キャッシュをロード (後で必要になったときに原本を load) |
151 | 151 | try { |
152 | - transCacheProp.load(transCacheFile); | |
153 | - if (mnemonicCacheFile.exists()) { | |
154 | - mnemonicCacheProp.load(mnemonicCacheFile); | |
152 | + transCacheProp.load(TRANS_CACHE_FILE); | |
153 | + if (MNEMONIC_CACHE_FILE.exists()) { | |
154 | + mnemonicCacheProp.load(MNEMONIC_CACHE_FILE); | |
155 | 155 | } |
156 | 156 | |
157 | 157 | } catch (RuntimeException e) { |
158 | 158 | |
159 | 159 | // キャッシュ破損、自己復元 |
160 | - log.warn("翻訳キャッシュ %s の破損を検出。復元中... - %s", transCacheFile, e.toString()); | |
161 | - transCacheFile.delete(); | |
160 | + log.warn("翻訳キャッシュ %s の破損を検出。復元中... - %s", TRANS_CACHE_FILE, e.toString()); | |
161 | + TRANS_CACHE_FILE.delete(); | |
162 | 162 | transCacheProp.clear(); |
163 | 163 | transCacheProp.load(validateExists(FileNamez.TRANS_FIRST_PROP)); |
164 | 164 | |
165 | - mnemonicCacheFile.delete(); | |
165 | + MNEMONIC_CACHE_FILE.delete(); | |
166 | 166 | mnemonicCacheProp.clear(); |
167 | 167 | } |
168 | 168 | } |
@@ -205,7 +205,7 @@ | ||
205 | 205 | File additionsDir = Filez.conf(TRANS_ADDITIONS_DIR); |
206 | 206 | if (additionsDir.exists()) { |
207 | 207 | |
208 | - new PropertySet(additionsDir){ | |
208 | + new PropertySet(additionsDir) { | |
209 | 209 | @Override |
210 | 210 | public String put(String en, String ja) { |
211 | 211 |
@@ -276,7 +276,7 @@ | ||
276 | 276 | public void shutdown() { |
277 | 277 | |
278 | 278 | isLoadedDefault = true; |
279 | - mnemonicCacheProp.store(mnemonicCacheFile); | |
279 | + mnemonicCacheProp.store(MNEMONIC_CACHE_FILE); | |
280 | 280 | |
281 | 281 | // 安全のためキャッシュが大きくなりすぎている場合はクリア (通常は発生しない想定) |
282 | 282 | if (transCacheProp.size() > 50 * 10000) { |
@@ -283,11 +283,11 @@ | ||
283 | 283 | log.warn("翻訳キャッシュが大きくなりすぎているためクリアしました。" + transCacheProp.size()); |
284 | 284 | transCacheProp.clear(); |
285 | 285 | } |
286 | - transCacheProp.store(transCacheFile); | |
286 | + transCacheProp.store(TRANS_CACHE_FILE); | |
287 | 287 | |
288 | 288 | // デバッグ時は zip でない形式でも保存 |
289 | 289 | if (pleiadesContext.enabledNotFoundLog) { |
290 | - transCacheProp.store(new File(transCacheFile.getPath().replaceFirst("\\.zip$", ""))); | |
290 | + transCacheProp.store(new File(TRANS_CACHE_FILE.getPath().replaceFirst("\\.zip$", ""))); | |
291 | 291 | } |
292 | 292 | } |
293 | 293 |