(empty log message)
@@ -1,5 +1,6 @@ | ||
1 | 1 | 2022.06.19 |
2 | 2 | |
3 | +・高速化: 読み込みバッファサイズの調整、不要な Pleiades 構成ファイルチェックをスキップ | |
3 | 4 | ・訳追加修正: Eclipse、m2e、ESP-IDF、STS、SQL Editor |
4 | 5 | |
5 | 6 | 2022.03.26 |
@@ -62,7 +62,7 @@ | ||
62 | 62 | // ・Fedora6, 7 や CentOS では NPE が発生する |
63 | 63 | |
64 | 64 | } catch (Throwable e) { |
65 | - abort(e, "Pleiades 初期化時にエラーが発生しました。"); | |
65 | + abortOnStartup(e, "Pleiades 初期化時にエラーが発生しました。"); | |
66 | 66 | } |
67 | 67 | } |
68 | 68 |
@@ -83,11 +83,11 @@ | ||
83 | 83 | } |
84 | 84 | |
85 | 85 | /** |
86 | - * エラーダイアログを表示し、アプリケーションを強制終了します。 | |
86 | + * 起動処理に失敗した場合のエラーダイアログを表示し、アプリケーションを強制終了します。 | |
87 | 87 | * @param e 例外 |
88 | 88 | * @param message メッセージ |
89 | 89 | */ |
90 | - public static void abort(Throwable e, String message) { | |
90 | + public static void abortOnStartup(Throwable e, String message) { | |
91 | 91 | |
92 | 92 | Logger log = Logger.getLogger(Pleiades.class); |
93 | 93 | log.fatal(e, message + "\n起動オプションに -clean を指定して起動してください。"); |
@@ -36,19 +36,22 @@ | ||
36 | 36 | |
37 | 37 | /** Pleiades プラグイン conf ディレクトリー */ |
38 | 38 | private static final File conf; |
39 | - | |
40 | - // conf ディレクトリーの解決 | |
41 | 39 | static { |
42 | - String marker = "/.marker"; | |
43 | - URL url = Filez.class.getResource(marker); | |
44 | - if (url == null) { | |
45 | - String msg = "conf の場所を決定するためのファイルがクラスパス上に見つかりません。" + marker; | |
46 | - Exception e = new FileNotFoundException(msg); | |
47 | - Pleiades.abort(e, msg); | |
40 | + File _conf = null; | |
41 | + try { | |
42 | + String marker = "/.marker"; | |
43 | + URL url = Filez.class.getResource(marker); | |
44 | + if (url == null) { | |
45 | + String msg = "conf の場所を決定するためのファイルがクラスパス上に見つかりません。" + marker; | |
46 | + throw new FileNotFoundException(msg); | |
47 | + } | |
48 | + String path = new File(url.getPath()).getParent(); | |
49 | + String unicodePath = decodeURL(path); | |
50 | + _conf = new File(unicodePath); | |
51 | + } catch (Throwable e) { | |
52 | + Pleiades.abortOnStartup(e, "conf ディレクトリーの解決に失敗しました。"); | |
48 | 53 | } |
49 | - String path = new File(url.getPath()).getParent(); | |
50 | - String unicodePath = decodeURL(path); | |
51 | - conf = new File(unicodePath); | |
54 | + conf = _conf; | |
52 | 55 | } |
53 | 56 | |
54 | 57 | /** |
@@ -29,6 +29,7 @@ | ||
29 | 29 | import java.util.zip.ZipInputStream; |
30 | 30 | import java.util.zip.ZipOutputStream; |
31 | 31 | |
32 | +import org.apache.commons.io.IOUtils; | |
32 | 33 | import org.apache.commons.lang3.StringUtils; |
33 | 34 | |
34 | 35 | import jp.sourceforge.mergedoc.pleiades.log.Logger; |
@@ -387,7 +388,8 @@ | ||
387 | 388 | } |
388 | 389 | |
389 | 390 | private void load0(LineReader lr) throws IOException { |
390 | - char[] convtBuf = new char[1024]; | |
391 | + //char[] convtBuf = new char[1024]; | |
392 | + char[] convtBuf = new char[IOUtils.DEFAULT_BUFFER_SIZE]; // 高速化 1024 → 8192 | |
391 | 393 | int limit; |
392 | 394 | int keyLen; |
393 | 395 | int valueStart; |
@@ -486,7 +488,8 @@ | ||
486 | 488 | |
487 | 489 | byte[] inByteBuf; |
488 | 490 | char[] inCharBuf; |
489 | - char[] lineBuf = new char[1024]; | |
491 | + //char[] lineBuf = new char[1024]; | |
492 | + char[] lineBuf = new char[IOUtils.DEFAULT_BUFFER_SIZE]; // 高速化 1024 → 8192 | |
490 | 493 | int inLimit = 0; |
491 | 494 | int inOff = 0; |
492 | 495 | Reader reader; |
@@ -12,7 +12,6 @@ | ||
12 | 12 | import java.util.concurrent.RejectedExecutionException; |
13 | 13 | import java.util.concurrent.TimeUnit; |
14 | 14 | |
15 | -import jp.sourceforge.mergedoc.pleiades.Pleiades; | |
16 | 15 | import jp.sourceforge.mergedoc.pleiades.log.Logger; |
17 | 16 | |
18 | 17 | /** |
@@ -53,7 +52,7 @@ | ||
53 | 52 | |
54 | 53 | } catch (Error e) { |
55 | 54 | // NoClassDefFoundError, ClassCircularityError など |
56 | - Pleiades.abort(e, processName + "に失敗しました。"); | |
55 | + log.fatal(e, processName + "に失敗しました。"); | |
57 | 56 | |
58 | 57 | } catch (Throwable e) { |
59 | 58 | if (e instanceof InvocationTargetException) { |
@@ -71,7 +71,7 @@ | ||
71 | 71 | _singleton = new LauncherTransformer(); |
72 | 72 | } |
73 | 73 | } catch (Throwable e) { |
74 | - Pleiades.abort(e, "起動トランスフォーマー生成時にエラーが発生しました。"); | |
74 | + Pleiades.abortOnStartup(e, "起動トランスフォーマー生成時にエラーが発生しました。"); | |
75 | 75 | } |
76 | 76 | singleton = _singleton; |
77 | 77 | } |
@@ -1,272 +0,0 @@ | ||
1 | -/* | |
2 | - * Copyright (c) 2005- Shinji Kashihara. | |
3 | - * All rights reserved. This program are made available under | |
4 | - * the terms of the Eclipse Public License v1.0 which accompanies | |
5 | - * this distribution, and is available at epl-v10.html. | |
6 | - */ | |
7 | -package jp.sourceforge.mergedoc.pleiades.runtime.advice; | |
8 | - | |
9 | -import java.util.Arrays; | |
10 | -import java.util.HashMap; | |
11 | -import java.util.HashSet; | |
12 | -import java.util.List; | |
13 | -import java.util.Map; | |
14 | -import java.util.Map.Entry; | |
15 | -import java.util.Set; | |
16 | - | |
17 | -import org.xml.sax.Attributes; | |
18 | -import org.xml.sax.SAXException; | |
19 | -import org.xml.sax.helpers.DefaultHandler; | |
20 | - | |
21 | -import jp.sourceforge.mergedoc.pleiades.log.Logger; | |
22 | -import jp.sourceforge.mergedoc.pleiades.runtime.advice.JoinPoint.EditPoint; | |
23 | - | |
24 | -/** | |
25 | - * Pleiades 構成ファイルの内容を取得・構築するアセンブラーです。<br> | |
26 | - * ジョイン・ポイントとポイント・カットの関連付けを行います。 | |
27 | - * <p> | |
28 | - * @author cypher256 | |
29 | - */ | |
30 | -public class PleiadesConfigAssembler extends DefaultHandler { | |
31 | - | |
32 | - /** ロガー */ | |
33 | - private static final Logger log = Logger.getLogger(PleiadesConfigAssembler.class); | |
34 | - | |
35 | - /** プロパティーを保持するマップ */ | |
36 | - private final Map<String, String> propertyMap = new HashMap<>(); | |
37 | - | |
38 | - /** トレース構成を保持するマップ */ | |
39 | - protected final Map<String, String> traceParamMap = new HashMap<>(); | |
40 | - | |
41 | - /** AOP 除外パッケージ・セット */ | |
42 | - protected final Set<String> excludePackageSet = new HashSet<>(); | |
43 | - | |
44 | - /** ジョイン・ポイントとポイント・カットを保持するマップ */ | |
45 | - protected final Map<JoinPoint, PointCut> joinPointCutMap = new HashMap<>(); | |
46 | - | |
47 | - /** ポイント・カット (コピー元として使用) */ | |
48 | - private PointCut pointCutOrigin; | |
49 | - | |
50 | - /** ポイント・カット */ | |
51 | - private PointCut pointCut; | |
52 | - | |
53 | - /** 要素 body 文字列バッファ */ | |
54 | - private StringBuilder elementBodyBuffer; | |
55 | - | |
56 | - /** ジョイン・ポイント */ | |
57 | - private JoinPoint joinPoint; | |
58 | - | |
59 | - /** 編集ポイント */ | |
60 | - private String editPoint; | |
61 | - | |
62 | - /** | |
63 | - * XML 要素開始時の処理です。 | |
64 | - */ | |
65 | - @Override | |
66 | - public void startElement(String uri, String localName, String tag, Attributes attributes) throws SAXException { | |
67 | - | |
68 | - if (tag.equals("pleiades")) { | |
69 | - | |
70 | - } else if (tag.equals("property")) { | |
71 | - | |
72 | - String name = attributes.getValue("name"); | |
73 | - String value = replacePropertyVariables(attributes.getValue("value")); | |
74 | - propertyMap.put("?{" + name + "}", value); | |
75 | - | |
76 | - } else if (tag.equals("excludePackage")) { | |
77 | - | |
78 | - elementBodyBuffer = new StringBuilder(); | |
79 | - | |
80 | - } else if (tag.equals("trace")) { | |
81 | - } else if (tag.equals("param")) { | |
82 | - | |
83 | - String name = attributes.getValue("name"); | |
84 | - String value = replacePropertyVariables(attributes.getValue("value")); | |
85 | - traceParamMap.put(name, value); | |
86 | - | |
87 | - } else if (tag.equals("pointCut")) { | |
88 | - | |
89 | - if ("true".equals(attributes.getValue("disabled"))) { | |
90 | - pointCutOrigin = null; | |
91 | - } else { | |
92 | - pointCutOrigin = new PointCut(); | |
93 | - pointCutOrigin.setTiming(attributes.getValue("timing")); | |
94 | - pointCutOrigin.setLevel(attributes.getValue("level")); | |
95 | - editPoint = attributes.getValue("editPoint"); | |
96 | - } | |
97 | - | |
98 | - // ここから下は pointCut 内の要素 | |
99 | - } else if (pointCutOrigin == null) { | |
100 | - | |
101 | - } else if (tag.equals("advice")) { | |
102 | - | |
103 | - elementBodyBuffer = new StringBuilder(); | |
104 | - | |
105 | - } else if (tag.equals("joinPoint")) { | |
106 | - | |
107 | - joinPoint = createJoinPoint(new JoinPoint(), attributes); | |
108 | - | |
109 | - /* TranslationEditor のコンストラクタ対応メソッド実装済み 2017.02.08 | |
110 | - String methodName = joinPoint.getMethodName(); | |
111 | - if ( | |
112 | - joinPoint.getEditPoint() == EditPoint.CALL && | |
113 | - methodName != null && !methodName.equals("") && Character.isUpperCase(methodName.charAt(0)) | |
114 | - ) { | |
115 | - // TranslationEditor のコンストラクタ対応メソッドを実装すれば対応可能 | |
116 | - throw new IllegalStateException( | |
117 | - "pointCut の editPoint が call の場合、joinPoint にコンストラクタを指定することはできません。" + | |
118 | - joinPoint); | |
119 | - } | |
120 | - */ | |
121 | - if (joinPointCutMap.containsKey(joinPoint)) { | |
122 | - log.warn("joinPoint 定義が重複しています。" + joinPoint); | |
123 | - } | |
124 | - // joinPoint ごとに親要素の pointCut のコピーを作成 (pointCut に joinPoint を持たせるため) | |
125 | - pointCut = new PointCut(pointCutOrigin); | |
126 | - pointCut.setJoinPoint(joinPoint); | |
127 | - joinPointCutMap.put(joinPoint, pointCut); | |
128 | - | |
129 | - } else if (tag.endsWith(/* include~ or exclude~ */"cludeWhere")) { | |
130 | - | |
131 | - if (pointCut.getJoinPoint().getEditPoint() == EditPoint.EXECUTION) { | |
132 | - throw new IllegalStateException( | |
133 | - "editPoint が execution の場合、*cludeWhere 属性を指定することはできません。" + pointCut); | |
134 | - } | |
135 | - | |
136 | - // *cludeWhere の descriptor は未サポート | |
137 | - JoinPoint where = createJoinPoint(new JoinPoint(), attributes); | |
138 | - | |
139 | - if (tag.equals("excludeWhere")) { | |
140 | - pointCut.getExcludeWheres().add(where); | |
141 | - } else if (tag.equals("includeWhere")) { | |
142 | - pointCut.getIncludeWheres().add(where); | |
143 | - } else { | |
144 | - throw new IllegalStateException("不正な属性名です。" + tag); | |
145 | - } | |
146 | - if (pointCut.getExcludeWheres().size() > 0 && pointCut.getIncludeWheres().size() > 0) { | |
147 | - throw new IllegalStateException( | |
148 | - "同じ joinPoint 内に excludeWhere と includeWhere を同時に指定できません。" + pointCut); | |
149 | - } | |
150 | - | |
151 | - } else if (tag.endsWith(/* include~ or exclude~ */"cludeTrace")) { | |
152 | - | |
153 | - if (pointCut.getJoinPoint().getEditPoint() == EditPoint.CALL) { | |
154 | - throw new IllegalStateException( | |
155 | - "editPoint が call の場合、*cludeTrace 属性を指定することはできません。" + pointCut); | |
156 | - } | |
157 | - if (!pointCut.getAdvice().contains("?{JOIN_POINT}")) { | |
158 | - throw new IllegalStateException( | |
159 | - "*cludeTrace を指定している場合は Advice に ?{JOIN_POINT} が含まれている必要があります。" + pointCut); | |
160 | - } | |
161 | - // *cludeTrace の descriptor は未サポート | |
162 | - TraceJoinPoint where = new TraceJoinPoint(); | |
163 | - String limit = attributes.getValue("limit"); | |
164 | - if (limit != null && !limit.isEmpty()) { | |
165 | - int lim = Integer.parseInt(limit); | |
166 | - if (lim <= 0) { | |
167 | - lim = Integer.MAX_VALUE; | |
168 | - } | |
169 | - where.setLimit(lim); | |
170 | - } | |
171 | - createJoinPoint(where, attributes); | |
172 | - | |
173 | - if (tag.equals("excludeTrace")) { | |
174 | - pointCut.getExcludeTrace().add(where); | |
175 | - } else if (tag.equals("includeTrace")) { | |
176 | - pointCut.getIncludeTrace().add(where); | |
177 | - } else { | |
178 | - throw new IllegalStateException("不正なタグ名です。" + tag); | |
179 | - } | |
180 | - /* 両方指定されている場合は include 優先 (CallHierarchyExplorer 参照) 2017.01.18 | |
181 | - if (curPointCut.getExcludeTrace().size() > 0 && curPointCut.getIncludeTrace().size() > 0) { | |
182 | - throw new IllegalStateException( | |
183 | - "同じ joinPoint 内に excludeTrace と includeTrace を同時に指定できません。" + | |
184 | - curPointCut); | |
185 | - } | |
186 | - */ | |
187 | - | |
188 | - } else if (tag.equals("jointPoint")) { | |
189 | - // 将来、この判定は削除 (タグ名変更) 2021.06.10 | |
190 | - throw new IllegalStateException("不正なタグ名です。" + tag + " を joinPoint に修正してください。"); | |
191 | - | |
192 | - } else { | |
193 | - throw new IllegalStateException("不正なタグ名です。" + tag); | |
194 | - } | |
195 | - } | |
196 | - | |
197 | - /** | |
198 | - * 属性から JoinPoint を作成します。 | |
199 | - * <p> | |
200 | - * @param joinPoint ジョイン・ポイント | |
201 | - * @param attributes 属性 | |
202 | - * @return JoinPoint | |
203 | - */ | |
204 | - private JoinPoint createJoinPoint(JoinPoint joinPoint, Attributes attributes) { | |
205 | - | |
206 | - String className = attributes.getValue("className"); | |
207 | - String methodName = attributes.getValue("methodName"); | |
208 | - String descriptor = attributes.getValue("descriptor"); | |
209 | - | |
210 | - joinPoint.setEditPoint(editPoint); | |
211 | - joinPoint.setClassName(className); | |
212 | - joinPoint.setMethodName(methodName); | |
213 | - joinPoint.setDescriptor(descriptor); | |
214 | - | |
215 | - if (className != null && className.contains(" ")) { | |
216 | - throw new IllegalStateException("className に空白が含まれています。" + joinPoint); | |
217 | - } | |
218 | - if (methodName != null && methodName.contains(" ")) { | |
219 | - throw new IllegalStateException("methodName に空白が含まれています。" + joinPoint); | |
220 | - } | |
221 | - if (descriptor != null && descriptor.matches(".+[a-z]\\).+")) { | |
222 | - throw new IllegalStateException("descriptor に指定する型の末尾には ; が必要です。" + joinPoint); | |
223 | - } | |
224 | - return joinPoint; | |
225 | - } | |
226 | - | |
227 | - /** | |
228 | - * プロパティ変数を置換します。 | |
229 | - * @param value 値 | |
230 | - * @return 置換後の値 | |
231 | - */ | |
232 | - private String replacePropertyVariables(String value) { | |
233 | - | |
234 | - if (value.contains("?{")) { | |
235 | - for (Entry<String, String> e : propertyMap.entrySet()) { | |
236 | - value = value.replace(e.getKey(), e.getValue()); | |
237 | - } | |
238 | - } | |
239 | - return value; | |
240 | - } | |
241 | - | |
242 | - /** | |
243 | - * XML 要素終了時の処理です。 | |
244 | - */ | |
245 | - @Override | |
246 | - public void endElement(String uri, String localName, String qName) throws SAXException { | |
247 | - | |
248 | - if (elementBodyBuffer == null) { | |
249 | - } else if (qName.equals("advice")) { | |
250 | - String advice = replacePropertyVariables(elementBodyBuffer.toString()); | |
251 | - elementBodyBuffer = null; | |
252 | - pointCutOrigin.setAdvice(advice); | |
253 | - | |
254 | - } else if (qName.equals("excludePackage")) { | |
255 | - String excludePackage = elementBodyBuffer.toString(); | |
256 | - elementBodyBuffer = null; | |
257 | - List<String> list = Arrays.asList(excludePackage.trim().split("\\s+")); | |
258 | - excludePackageSet.addAll(list); | |
259 | - } | |
260 | - } | |
261 | - | |
262 | - /** | |
263 | - * XML 要素ボディ部の処理です。 | |
264 | - */ | |
265 | - @Override | |
266 | - public void characters(char[] ch, int start, int length) throws SAXException { | |
267 | - | |
268 | - if (elementBodyBuffer != null) { | |
269 | - elementBodyBuffer.append(ch, start, length); | |
270 | - } | |
271 | - } | |
272 | -} |
@@ -47,8 +47,8 @@ | ||
47 | 47 | |
48 | 48 | //------------------------------------------------------------------------- |
49 | 49 | |
50 | - /** Pleiades 構成ファイルの内容を取得・構築するアセンブラー */ | |
51 | - private final PleiadesConfigAssembler pleiadesConfigAssembler = new PleiadesConfigAssembler(); | |
50 | + /** Pleiades 構成ファイルの内容を取得・構築する SAX ハンドラー */ | |
51 | + private final PleiadesConfigSaxHandler pleiadesConfigSaxHandler = new PleiadesConfigSaxHandler(); | |
52 | 52 | |
53 | 53 | /** call ウィービング対象となるクラス・メソッドセット */ |
54 | 54 | private final Set<String> callNameSet = new HashSet<>(); |
@@ -83,12 +83,12 @@ | ||
83 | 83 | Analyses.end(PleiadesConfig.class, "<init>:newSAXParser", s1); |
84 | 84 | |
85 | 85 | long s2 = System.nanoTime(); |
86 | - parser.parse(configXmlFile, pleiadesConfigAssembler); | |
86 | + parser.parse(configXmlFile, pleiadesConfigSaxHandler); | |
87 | 87 | Analyses.end(PleiadesConfig.class, "<init>:parse", s2); |
88 | 88 | log.info("Pleiades 構成ファイルをロードしました。" + configXmlPath); |
89 | 89 | |
90 | 90 | // 呼び出し階層の高速判定用コレクション作成 |
91 | - for (JoinPoint joinPoint : pleiadesConfigAssembler.joinPointCutMap.keySet()) { | |
91 | + for (JoinPoint joinPoint : pleiadesConfigSaxHandler.joinPointCutMap.keySet()) { | |
92 | 92 | if (joinPoint.getEditPoint() == EditPoint.CALL) { |
93 | 93 | |
94 | 94 | String className = joinPoint.getClassName(); |
@@ -105,12 +105,12 @@ | ||
105 | 105 | } |
106 | 106 | } |
107 | 107 | } catch (Throwable e) { |
108 | - Pleiades.abort(e, "Pleiades 構成ファイルのロードに失敗しました。\n" + configXmlFile); | |
108 | + Pleiades.abortOnStartup(e, "Pleiades 構成ファイルのロードに失敗しました。\n" + configXmlFile); | |
109 | 109 | } |
110 | 110 | |
111 | 111 | // トレース構成の作成 |
112 | 112 | if (log.isDebugEnabled()) { |
113 | - traceConfig = new TraceConfig(pleiadesConfigAssembler.traceParamMap); | |
113 | + traceConfig = new TraceConfig(pleiadesConfigSaxHandler.traceParamMap); | |
114 | 114 | } else { |
115 | 115 | traceConfig = null; |
116 | 116 | } |
@@ -171,7 +171,7 @@ | ||
171 | 171 | */ |
172 | 172 | public PointCut getPointCut(JoinPoint joinPoint) { |
173 | 173 | |
174 | - Map<JoinPoint, PointCut> jointMap = pleiadesConfigAssembler.joinPointCutMap; | |
174 | + Map<JoinPoint, PointCut> jointMap = pleiadesConfigSaxHandler.joinPointCutMap; | |
175 | 175 | PointCut pointCut = jointMap.get(joinPoint); |
176 | 176 | if (pointCut != null) { |
177 | 177 | return pointCut; |
@@ -213,7 +213,7 @@ | ||
213 | 213 | */ |
214 | 214 | public boolean isExcludePackage(String className) { |
215 | 215 | |
216 | - for (String packageName : pleiadesConfigAssembler.excludePackageSet) { | |
216 | + for (String packageName : pleiadesConfigSaxHandler.excludePackageSet) { | |
217 | 217 | if (className.startsWith(packageName)) { |
218 | 218 | return true; |
219 | 219 | } |
@@ -228,7 +228,7 @@ | ||
228 | 228 | public String toString() { |
229 | 229 | |
230 | 230 | long start = System.nanoTime(); |
231 | - Map<JoinPoint, PointCut> jointMap = pleiadesConfigAssembler.joinPointCutMap; | |
231 | + Map<JoinPoint, PointCut> jointMap = pleiadesConfigSaxHandler.joinPointCutMap; | |
232 | 232 | try { |
233 | 233 | return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) |
234 | 234 | .append(jointMap) |
@@ -0,0 +1,278 @@ | ||
1 | +/* | |
2 | + * Copyright (c) 2005- Shinji Kashihara. | |
3 | + * All rights reserved. This program are made available under | |
4 | + * the terms of the Eclipse Public License v1.0 which accompanies | |
5 | + * this distribution, and is available at epl-v10.html. | |
6 | + */ | |
7 | +package jp.sourceforge.mergedoc.pleiades.runtime.advice; | |
8 | + | |
9 | +import java.util.Arrays; | |
10 | +import java.util.HashMap; | |
11 | +import java.util.HashSet; | |
12 | +import java.util.List; | |
13 | +import java.util.Map; | |
14 | +import java.util.Map.Entry; | |
15 | +import java.util.Set; | |
16 | + | |
17 | +import org.xml.sax.Attributes; | |
18 | +import org.xml.sax.SAXException; | |
19 | +import org.xml.sax.helpers.DefaultHandler; | |
20 | + | |
21 | +import jp.sourceforge.mergedoc.pleiades.log.Logger; | |
22 | +import jp.sourceforge.mergedoc.pleiades.runtime.advice.JoinPoint.EditPoint; | |
23 | + | |
24 | +/** | |
25 | + * Pleiades 構成ファイルの内容を取得・構築する SAX ハンドラーです。<br> | |
26 | + * ジョイン・ポイントとポイント・カットの関連付けを行います。 | |
27 | + * <p> | |
28 | + * @author cypher256 | |
29 | + */ | |
30 | +public class PleiadesConfigSaxHandler extends DefaultHandler { | |
31 | + | |
32 | + /** ロガー */ | |
33 | + private static final Logger log = Logger.getLogger(PleiadesConfigSaxHandler.class); | |
34 | + | |
35 | + /** debug 時は true */ | |
36 | + private static final boolean isDebugEnabled = log.isDebugEnabled(); | |
37 | + | |
38 | + /** プロパティーを保持するマップ */ | |
39 | + private final Map<String, String> propertyMap = new HashMap<>(); | |
40 | + | |
41 | + /** トレース構成を保持するマップ */ | |
42 | + protected final Map<String, String> traceParamMap = new HashMap<>(); | |
43 | + | |
44 | + /** AOP 除外パッケージ・セット */ | |
45 | + protected final Set<String> excludePackageSet = new HashSet<>(); | |
46 | + | |
47 | + /** ジョイン・ポイントとポイント・カットを保持するマップ */ | |
48 | + protected final Map<JoinPoint, PointCut> joinPointCutMap = new HashMap<>(); | |
49 | + | |
50 | + /** ポイント・カット (コピー元として使用) */ | |
51 | + private PointCut pointCutOrigin; | |
52 | + | |
53 | + /** ポイント・カット */ | |
54 | + private PointCut pointCut; | |
55 | + | |
56 | + /** 要素 body 文字列バッファ */ | |
57 | + private StringBuilder elementBodyBuffer; | |
58 | + | |
59 | + /** ジョイン・ポイント */ | |
60 | + private JoinPoint joinPoint; | |
61 | + | |
62 | + /** 編集ポイント */ | |
63 | + private String editPoint; | |
64 | + | |
65 | + /** | |
66 | + * XML 要素開始時の処理です。 | |
67 | + */ | |
68 | + @Override | |
69 | + public void startElement(String uri, String localName, String tag, Attributes attributes) throws SAXException { | |
70 | + | |
71 | + if (tag.equals("pleiades")) { | |
72 | + | |
73 | + } else if (tag.equals("property")) { | |
74 | + | |
75 | + String name = attributes.getValue("name"); | |
76 | + String value = replacePropertyVariables(attributes.getValue("value")); | |
77 | + propertyMap.put("?{" + name + "}", value); | |
78 | + | |
79 | + } else if (tag.equals("excludePackage")) { | |
80 | + | |
81 | + elementBodyBuffer = new StringBuilder(); | |
82 | + | |
83 | + } else if (tag.equals("trace")) { | |
84 | + } else if (tag.equals("param")) { | |
85 | + | |
86 | + String name = attributes.getValue("name"); | |
87 | + String value = replacePropertyVariables(attributes.getValue("value")); | |
88 | + traceParamMap.put(name, value); | |
89 | + | |
90 | + } else if (tag.equals("pointCut")) { | |
91 | + | |
92 | + if ("true".equals(attributes.getValue("disabled"))) { | |
93 | + pointCutOrigin = null; | |
94 | + } else { | |
95 | + pointCutOrigin = new PointCut(); | |
96 | + pointCutOrigin.setTiming(attributes.getValue("timing")); | |
97 | + pointCutOrigin.setLevel(attributes.getValue("level")); | |
98 | + editPoint = attributes.getValue("editPoint"); | |
99 | + } | |
100 | + | |
101 | + // ここから下は pointCut 内の要素 | |
102 | + } else if (pointCutOrigin == null) { | |
103 | + | |
104 | + } else if (tag.equals("advice")) { | |
105 | + | |
106 | + elementBodyBuffer = new StringBuilder(); | |
107 | + | |
108 | + } else if (tag.equals("joinPoint")) { | |
109 | + | |
110 | + joinPoint = createJoinPoint(new JoinPoint(), attributes); | |
111 | + | |
112 | + /* TranslationEditor のコンストラクタ対応メソッド実装済み 2017.02.08 | |
113 | + String methodName = joinPoint.getMethodName(); | |
114 | + if ( | |
115 | + joinPoint.getEditPoint() == EditPoint.CALL && | |
116 | + methodName != null && !methodName.equals("") && Character.isUpperCase(methodName.charAt(0)) | |
117 | + ) { | |
118 | + // TranslationEditor のコンストラクタ対応メソッドを実装すれば対応可能 | |
119 | + throw new IllegalStateException( | |
120 | + "pointCut の editPoint が call の場合、joinPoint にコンストラクタを指定することはできません。" + | |
121 | + joinPoint); | |
122 | + } | |
123 | + */ | |
124 | + if (joinPointCutMap.containsKey(joinPoint)) { | |
125 | + log.warn("joinPoint 定義が重複しています。" + joinPoint); | |
126 | + } | |
127 | + // joinPoint ごとに親要素の pointCut のコピーを作成 (pointCut に joinPoint を持たせるため) | |
128 | + pointCut = new PointCut(pointCutOrigin); | |
129 | + pointCut.setJoinPoint(joinPoint); | |
130 | + joinPointCutMap.put(joinPoint, pointCut); | |
131 | + | |
132 | + } else if (tag.endsWith(/* include~ or exclude~ */"cludeWhere")) { | |
133 | + | |
134 | + if (pointCut.getJoinPoint().getEditPoint() == EditPoint.EXECUTION) { | |
135 | + throw new IllegalStateException( | |
136 | + "editPoint が execution の場合、*cludeWhere 属性を指定することはできません。" + pointCut); | |
137 | + } | |
138 | + | |
139 | + // *cludeWhere の descriptor は未サポート | |
140 | + JoinPoint where = createJoinPoint(new JoinPoint(), attributes); | |
141 | + | |
142 | + if (tag.equals("excludeWhere")) { | |
143 | + pointCut.getExcludeWheres().add(where); | |
144 | + } else if (tag.equals("includeWhere")) { | |
145 | + pointCut.getIncludeWheres().add(where); | |
146 | + } else { | |
147 | + throw new IllegalStateException("不正な属性名です。" + tag); | |
148 | + } | |
149 | + if (pointCut.getExcludeWheres().size() > 0 && pointCut.getIncludeWheres().size() > 0) { | |
150 | + throw new IllegalStateException( | |
151 | + "同じ joinPoint 内に excludeWhere と includeWhere を同時に指定できません。" + pointCut); | |
152 | + } | |
153 | + | |
154 | + } else if (tag.endsWith(/* include~ or exclude~ */"cludeTrace")) { | |
155 | + | |
156 | + if (pointCut.getJoinPoint().getEditPoint() == EditPoint.CALL) { | |
157 | + throw new IllegalStateException( | |
158 | + "editPoint が call の場合、*cludeTrace 属性を指定することはできません。" + pointCut); | |
159 | + } | |
160 | + if (!pointCut.getAdvice().contains("?{JOIN_POINT}")) { | |
161 | + throw new IllegalStateException( | |
162 | + "*cludeTrace を指定している場合は Advice に ?{JOIN_POINT} が含まれている必要があります。" + pointCut); | |
163 | + } | |
164 | + // *cludeTrace の descriptor は未サポート | |
165 | + TraceJoinPoint where = new TraceJoinPoint(); | |
166 | + String limit = attributes.getValue("limit"); | |
167 | + if (limit != null && !limit.isEmpty()) { | |
168 | + int lim = Integer.parseInt(limit); | |
169 | + if (lim <= 0) { | |
170 | + lim = Integer.MAX_VALUE; | |
171 | + } | |
172 | + where.setLimit(lim); | |
173 | + } | |
174 | + createJoinPoint(where, attributes); | |
175 | + | |
176 | + if (tag.equals("excludeTrace")) { | |
177 | + pointCut.getExcludeTrace().add(where); | |
178 | + } else if (tag.equals("includeTrace")) { | |
179 | + pointCut.getIncludeTrace().add(where); | |
180 | + } else { | |
181 | + throw new IllegalStateException("不正なタグ名です。" + tag); | |
182 | + } | |
183 | + /* 両方指定されている場合は include 優先 (CallHierarchyExplorer 参照) 2017.01.18 | |
184 | + if (curPointCut.getExcludeTrace().size() > 0 && curPointCut.getIncludeTrace().size() > 0) { | |
185 | + throw new IllegalStateException( | |
186 | + "同じ joinPoint 内に excludeTrace と includeTrace を同時に指定できません。" + | |
187 | + curPointCut); | |
188 | + } | |
189 | + */ | |
190 | + | |
191 | + } else if (tag.equals("jointPoint")) { | |
192 | + // 将来、この判定は削除 (タグ名変更) 2021.06.10 | |
193 | + throw new IllegalStateException("不正なタグ名です。" + tag + " を joinPoint に修正してください。"); | |
194 | + | |
195 | + } else { | |
196 | + throw new IllegalStateException("不正なタグ名です。" + tag); | |
197 | + } | |
198 | + } | |
199 | + | |
200 | + /** | |
201 | + * 属性から JoinPoint を作成します。 | |
202 | + * <p> | |
203 | + * @param joinPoint ジョイン・ポイント | |
204 | + * @param attributes 属性 | |
205 | + * @return JoinPoint | |
206 | + */ | |
207 | + private JoinPoint createJoinPoint(JoinPoint joinPoint, Attributes attributes) { | |
208 | + | |
209 | + String className = attributes.getValue("className"); | |
210 | + String methodName = attributes.getValue("methodName"); | |
211 | + String descriptor = attributes.getValue("descriptor"); | |
212 | + | |
213 | + joinPoint.setEditPoint(editPoint); | |
214 | + joinPoint.setClassName(className); | |
215 | + joinPoint.setMethodName(methodName); | |
216 | + joinPoint.setDescriptor(descriptor); | |
217 | + | |
218 | + // 属性値チェック (高速化のため debug 時のみ判定) | |
219 | + if (isDebugEnabled) { | |
220 | + if (className != null && className.contains(" ")) { | |
221 | + throw new IllegalStateException("className に空白が含まれています。" + joinPoint); | |
222 | + } | |
223 | + if (methodName != null && methodName.contains(" ")) { | |
224 | + throw new IllegalStateException("methodName に空白が含まれています。" + joinPoint); | |
225 | + } | |
226 | + if (descriptor != null && descriptor.matches(".+[a-z]\\).+")) { | |
227 | + throw new IllegalStateException("descriptor に指定する型の末尾には ; が必要です。" + joinPoint); | |
228 | + } | |
229 | + } | |
230 | + return joinPoint; | |
231 | + } | |
232 | + | |
233 | + /** | |
234 | + * プロパティ変数を置換します。 | |
235 | + * @param value 値 | |
236 | + * @return 置換後の値 | |
237 | + */ | |
238 | + private String replacePropertyVariables(String value) { | |
239 | + | |
240 | + if (value.contains("?{")) { | |
241 | + for (Entry<String, String> e : propertyMap.entrySet()) { | |
242 | + value = value.replace(e.getKey(), e.getValue()); | |
243 | + } | |
244 | + } | |
245 | + return value; | |
246 | + } | |
247 | + | |
248 | + /** | |
249 | + * XML 要素終了時の処理です。 | |
250 | + */ | |
251 | + @Override | |
252 | + public void endElement(String uri, String localName, String qName) throws SAXException { | |
253 | + | |
254 | + if (elementBodyBuffer == null) { | |
255 | + } else if (qName.equals("advice")) { | |
256 | + String advice = replacePropertyVariables(elementBodyBuffer.toString()); | |
257 | + elementBodyBuffer = null; | |
258 | + pointCutOrigin.setAdvice(advice); | |
259 | + | |
260 | + } else if (qName.equals("excludePackage")) { | |
261 | + String excludePackage = elementBodyBuffer.toString(); | |
262 | + elementBodyBuffer = null; | |
263 | + List<String> list = Arrays.asList(excludePackage.trim().split("\\s+")); | |
264 | + excludePackageSet.addAll(list); | |
265 | + } | |
266 | + } | |
267 | + | |
268 | + /** | |
269 | + * XML 要素ボディ部の処理です。 | |
270 | + */ | |
271 | + @Override | |
272 | + public void characters(char[] ch, int start, int length) throws SAXException { | |
273 | + | |
274 | + if (elementBodyBuffer != null) { | |
275 | + elementBodyBuffer.append(ch, start, length); | |
276 | + } | |
277 | + } | |
278 | +} |
@@ -78,7 +78,7 @@ | ||
78 | 78 | for (ZipEntry zipEntry; (zipEntry = zis.getNextEntry()) != null;) { |
79 | 79 | |
80 | 80 | String classId = zipEntry.getName(); |
81 | - byte[] bytecode = zis.readAllBytes(); | |
81 | + byte[] bytecode = zis.readAllBytes(); // 高速化 (Java 9 以降) | |
82 | 82 | map.put(classId, bytecode); |
83 | 83 | } |
84 | 84 | log.info("load %6d エントリー %s", map.size(), CLASS_CACHE_FILE.getName()); |