Add full Java module support
emmanue1
4 years ago
210 | 210 | } |
211 | 211 | |
212 | 212 | protected void filter(Indexes indexes, String pattern, int flags, Set<Container.Entry> matchingEntries) { |
213 | boolean declarations = ((flags & SearchInConstantPoolsView.SEARCH_TYPE_DECLARATION) != 0); | |
214 | boolean references = ((flags & SearchInConstantPoolsView.SEARCH_TYPE_REFERENCE) != 0); | |
215 | ||
216 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_TYPE) != 0) { | |
213 | boolean declarations = ((flags & SearchInConstantPoolsView.SEARCH_DECLARATION) != 0); | |
214 | boolean references = ((flags & SearchInConstantPoolsView.SEARCH_REFERENCE) != 0); | |
215 | ||
216 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE) != 0) { | |
217 | 217 | if (declarations) |
218 | 218 | match(indexes, "typeDeclarations", pattern, |
219 | 219 | SearchInConstantPoolsController::matchTypeEntriesWithChar, |
224 | 224 | SearchInConstantPoolsController::matchTypeEntriesWithString, matchingEntries); |
225 | 225 | } |
226 | 226 | |
227 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_CONSTRUCTOR) != 0) { | |
227 | if ((flags & SearchInConstantPoolsView.SEARCH_CONSTRUCTOR) != 0) { | |
228 | 228 | if (declarations) |
229 | 229 | match(indexes, "constructorDeclarations", pattern, |
230 | 230 | SearchInConstantPoolsController::matchTypeEntriesWithChar, |
235 | 235 | SearchInConstantPoolsController::matchTypeEntriesWithString, matchingEntries); |
236 | 236 | } |
237 | 237 | |
238 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_METHOD) != 0) { | |
238 | if ((flags & SearchInConstantPoolsView.SEARCH_METHOD) != 0) { | |
239 | 239 | if (declarations) |
240 | 240 | match(indexes, "methodDeclarations", pattern, |
241 | 241 | SearchInConstantPoolsController::matchWithChar, |
246 | 246 | SearchInConstantPoolsController::matchWithString, matchingEntries); |
247 | 247 | } |
248 | 248 | |
249 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_FIELD) != 0) { | |
249 | if ((flags & SearchInConstantPoolsView.SEARCH_FIELD) != 0) { | |
250 | 250 | if (declarations) |
251 | 251 | match(indexes, "fieldDeclarations", pattern, |
252 | 252 | SearchInConstantPoolsController::matchWithChar, |
257 | 257 | SearchInConstantPoolsController::matchWithString, matchingEntries); |
258 | 258 | } |
259 | 259 | |
260 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_STRING) != 0) { | |
260 | if ((flags & SearchInConstantPoolsView.SEARCH_STRING) != 0) { | |
261 | 261 | if (declarations || references) |
262 | 262 | match(indexes, "strings", pattern, |
263 | 263 | SearchInConstantPoolsController::matchWithChar, |
264 | 264 | SearchInConstantPoolsController::matchWithString, matchingEntries); |
265 | } | |
266 | ||
267 | if ((flags & SearchInConstantPoolsView.SEARCH_MODULE) != 0) { | |
268 | if (declarations) | |
269 | match(indexes, "javaModuleDeclarations", pattern, | |
270 | SearchInConstantPoolsController::matchWithChar, | |
271 | SearchInConstantPoolsController::matchWithString, matchingEntries); | |
272 | if (references) | |
273 | match(indexes, "javaModuleReferences", pattern, | |
274 | SearchInConstantPoolsController::matchWithChar, | |
275 | SearchInConstantPoolsController::matchWithString, matchingEntries); | |
265 | 276 | } |
266 | 277 | } |
267 | 278 | |
274 | 285 | |
275 | 286 | if (patternLength > 0) { |
276 | 287 | String key = String.valueOf(indexes.hashCode()) + "***" + indexName + "***" + pattern; |
277 | Map<String, Collection> matchedTypes = cache.get(key); | |
278 | ||
279 | if (matchedTypes == null) { | |
288 | Map<String, Collection> matchedEntries = cache.get(key); | |
289 | ||
290 | if (matchedEntries == null) { | |
280 | 291 | Map<String, Collection> index = indexes.getIndex(indexName); |
281 | 292 | |
282 | 293 | if (patternLength == 1) { |
283 | matchedTypes = matchWithCharFunction.apply(pattern.charAt(0), index); | |
294 | matchedEntries = matchWithCharFunction.apply(pattern.charAt(0), index); | |
284 | 295 | } else { |
285 | 296 | String lastKey = key.substring(0, key.length() - 1); |
286 | 297 | Map<String, Collection> lastMatchedTypes = cache.get(lastKey); |
287 | 298 | if (lastMatchedTypes != null) { |
288 | matchedTypes = matchWithStringFunction.apply(pattern, lastMatchedTypes); | |
299 | matchedEntries = matchWithStringFunction.apply(pattern, lastMatchedTypes); | |
289 | 300 | } else { |
290 | matchedTypes = matchWithStringFunction.apply(pattern, index); | |
301 | matchedEntries = matchWithStringFunction.apply(pattern, index); | |
291 | 302 | } |
292 | 303 | } |
293 | 304 | |
294 | 305 | // Cache matchingEntries |
295 | cache.put(key, matchedTypes); | |
296 | } | |
297 | ||
298 | if (matchedTypes != null) { | |
299 | for (Collection<Container.Entry> entries : matchedTypes.values()) { | |
306 | cache.put(key, matchedEntries); | |
307 | } | |
308 | ||
309 | if (matchedEntries != null) { | |
310 | for (Collection<Container.Entry> entries : matchedEntries.values()) { | |
300 | 311 | matchingEntries.addAll(entries); |
301 | 312 | } |
302 | 313 | } |
305 | 316 | |
306 | 317 | protected static Map<String, Collection> matchTypeEntriesWithChar(char c, Map<String, Collection> index) { |
307 | 318 | if ((c == '*') || (c == '?')) { |
308 | return Collections.emptyMap(); | |
319 | return index; | |
309 | 320 | } else { |
310 | 321 | Map<String, Collection> map = new HashMap<>(); |
311 | 322 | |
344 | 355 | |
345 | 356 | protected static Map<String, Collection> matchWithChar(char c, Map<String, Collection> index) { |
346 | 357 | if ((c == '*') || (c == '?')) { |
347 | return Collections.emptyMap(); | |
358 | return index; | |
348 | 359 | } else { |
349 | 360 | Map<String, Collection> map = new HashMap<>(); |
350 | 361 | |
351 | for (String typeName : index.keySet()) { | |
352 | if (!typeName.isEmpty() && (typeName.charAt(0) == c)) { | |
353 | map.put(typeName, index.get(typeName)); | |
362 | for (String key : index.keySet()) { | |
363 | if (!key.isEmpty() && (key.charAt(0) == c)) { | |
364 | map.put(key, index.get(key)); | |
354 | 365 | } |
355 | 366 | } |
356 | 367 | |
362 | 373 | Pattern p = createPattern(pattern); |
363 | 374 | Map<String, Collection> map = new HashMap<>(); |
364 | 375 | |
365 | for (String typeName : index.keySet()) { | |
366 | if (p.matcher(typeName).matches()) { | |
367 | map.put(typeName, index.get(typeName)); | |
376 | for (String key : index.keySet()) { | |
377 | if (p.matcher(key).matches()) { | |
378 | map.put(key, index.get(key)); | |
368 | 379 | } |
369 | 380 | } |
370 | 381 | |
418 | 429 | sbPattern.append(pattern); |
419 | 430 | sbPattern.append("&highlightFlags="); |
420 | 431 | |
421 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_DECLARATION) != 0) | |
432 | if ((flags & SearchInConstantPoolsView.SEARCH_DECLARATION) != 0) | |
422 | 433 | sbPattern.append('d'); |
423 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_REFERENCE) != 0) | |
434 | if ((flags & SearchInConstantPoolsView.SEARCH_REFERENCE) != 0) | |
424 | 435 | sbPattern.append('r'); |
425 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_TYPE) != 0) | |
436 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE) != 0) | |
426 | 437 | sbPattern.append('t'); |
427 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_CONSTRUCTOR) != 0) | |
438 | if ((flags & SearchInConstantPoolsView.SEARCH_CONSTRUCTOR) != 0) | |
428 | 439 | sbPattern.append('c'); |
429 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_METHOD) != 0) | |
440 | if ((flags & SearchInConstantPoolsView.SEARCH_METHOD) != 0) | |
430 | 441 | sbPattern.append('m'); |
431 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_FIELD) != 0) | |
442 | if ((flags & SearchInConstantPoolsView.SEARCH_FIELD) != 0) | |
432 | 443 | sbPattern.append('f'); |
433 | if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_STRING) != 0) | |
444 | if ((flags & SearchInConstantPoolsView.SEARCH_STRING) != 0) | |
434 | 445 | sbPattern.append('s'); |
446 | if ((flags & SearchInConstantPoolsView.SEARCH_MODULE) != 0) | |
447 | sbPattern.append('M'); | |
435 | 448 | |
436 | 449 | // TODO In a future release, add 'highlightScope' to display search results in correct type and inner-type |
437 | 450 | // def type = TypeFactoryService.instance.get(entry)?.make(api, entry, null) |
25 | 25 | * file://codebase/a/b/c/D$E.class => file://codebase/a/b/c/D.class#typeDeclaration=D$E |
26 | 26 | */ |
27 | 27 | public static URI createURI(API api, Collection<Future<Indexes>> collectionOfFutureIndexes, Container.Entry entry, String query, String fragment) { |
28 | TypeFactory typeFactory = TypeFactoryService.getInstance().get(entry); | |
28 | URI uri = entry.getUri(); | |
29 | 29 | |
30 | if (typeFactory != null) { | |
31 | Type type = typeFactory.make(api, entry, fragment); | |
30 | try { | |
31 | String path = uri.getPath(); | |
32 | TypeFactory typeFactory = TypeFactoryService.getInstance().get(entry); | |
32 | 33 | |
33 | if (type != null) { | |
34 | URI uri = entry.getUri(); | |
35 | String path = getOuterPath(collectionOfFutureIndexes, entry, type); | |
34 | if (typeFactory != null) { | |
35 | Type type = typeFactory.make(api, entry, fragment); | |
36 | 36 | |
37 | try { | |
38 | return new URI(uri.getScheme(), uri.getHost(), path, query, fragment); | |
39 | } catch (URISyntaxException e) { | |
40 | assert ExceptionUtil.printStackTrace(e); | |
37 | if (type != null) { | |
38 | path = getOuterPath(collectionOfFutureIndexes, entry, type); | |
41 | 39 | } |
42 | 40 | } |
41 | ||
42 | return new URI(uri.getScheme(), uri.getHost(), path, query, fragment); | |
43 | } catch (URISyntaxException e) { | |
44 | assert ExceptionUtil.printStackTrace(e); | |
45 | return uri; | |
43 | 46 | } |
44 | ||
45 | return null; | |
46 | 47 | } |
47 | 48 | |
48 | 49 | @SuppressWarnings("unchecked") |
35 | 35 | public class SearchInConstantPoolsView<T extends DefaultMutableTreeNode & ContainerEntryGettable & UriGettable> { |
36 | 36 | protected static final ContainerComparator CONTAINER_COMPARATOR = new ContainerComparator(); |
37 | 37 | |
38 | public static final int SEARCH_TYPE_TYPE = 1; | |
39 | public static final int SEARCH_TYPE_CONSTRUCTOR = 2; | |
40 | public static final int SEARCH_TYPE_METHOD = 4; | |
41 | public static final int SEARCH_TYPE_FIELD = 8; | |
42 | public static final int SEARCH_TYPE_STRING = 16; | |
43 | public static final int SEARCH_TYPE_DECLARATION = 32; | |
44 | public static final int SEARCH_TYPE_REFERENCE = 64; | |
38 | public static final int SEARCH_TYPE = 1; | |
39 | public static final int SEARCH_CONSTRUCTOR = 2; | |
40 | public static final int SEARCH_METHOD = 4; | |
41 | public static final int SEARCH_FIELD = 8; | |
42 | public static final int SEARCH_STRING = 16; | |
43 | public static final int SEARCH_MODULE = 32; | |
44 | public static final int SEARCH_DECLARATION = 64; | |
45 | public static final int SEARCH_REFERENCE = 128; | |
45 | 46 | |
46 | 47 | protected API api; |
47 | 48 | protected Set<URI> accepted = new HashSet<>(); |
55 | 56 | protected JCheckBox searchInConstantPoolsCheckBoxConstructor; |
56 | 57 | protected JCheckBox searchInConstantPoolsCheckBoxMethod; |
57 | 58 | protected JCheckBox searchInConstantPoolsCheckBoxString; |
59 | protected JCheckBox searchInConstantPoolsCheckBoxModule; | |
58 | 60 | protected JCheckBox searchInConstantPoolsCheckBoxDeclarations; |
59 | 61 | protected JCheckBox searchInConstantPoolsCheckBoxReferences; |
60 | 62 | protected Tree searchInConstantPoolsTree; |
158 | 160 | subsubpanel.setLayout(new GridLayout(2, 1)); |
159 | 161 | subsubpanel.add(searchInConstantPoolsCheckBoxString = new JCheckBox("String Constant")); |
160 | 162 | searchInConstantPoolsCheckBoxString.addItemListener(checkBoxListener); |
163 | subsubpanel.add(searchInConstantPoolsCheckBoxModule = new JCheckBox("Java Module")); | |
164 | searchInConstantPoolsCheckBoxModule.addItemListener(checkBoxListener); | |
161 | 165 | subhbox.add(subsubpanel); |
162 | 166 | |
163 | 167 | subpanel = new JPanel(); |
337 | 341 | int flags = 0; |
338 | 342 | |
339 | 343 | if (searchInConstantPoolsCheckBoxType.isSelected()) |
340 | flags += SEARCH_TYPE_TYPE; | |
344 | flags += SEARCH_TYPE; | |
341 | 345 | if (searchInConstantPoolsCheckBoxConstructor.isSelected()) |
342 | flags += SEARCH_TYPE_CONSTRUCTOR; | |
346 | flags += SEARCH_CONSTRUCTOR; | |
343 | 347 | if (searchInConstantPoolsCheckBoxMethod.isSelected()) |
344 | flags += SEARCH_TYPE_METHOD; | |
348 | flags += SEARCH_METHOD; | |
345 | 349 | if (searchInConstantPoolsCheckBoxField.isSelected()) |
346 | flags += SEARCH_TYPE_FIELD; | |
350 | flags += SEARCH_FIELD; | |
347 | 351 | if (searchInConstantPoolsCheckBoxString.isSelected()) |
348 | flags += SEARCH_TYPE_STRING; | |
352 | flags += SEARCH_STRING; | |
353 | if (searchInConstantPoolsCheckBoxModule.isSelected()) | |
354 | flags += SEARCH_MODULE; | |
349 | 355 | if (searchInConstantPoolsCheckBoxDeclarations.isSelected()) |
350 | flags += SEARCH_TYPE_DECLARATION; | |
356 | flags += SEARCH_DECLARATION; | |
351 | 357 | if (searchInConstantPoolsCheckBoxReferences.isSelected()) |
352 | flags += SEARCH_TYPE_REFERENCE; | |
358 | flags += SEARCH_REFERENCE; | |
353 | 359 | |
354 | 360 | return flags; |
355 | 361 | } |
143 | 143 | pageChangedListenersEnabled = false; |
144 | 144 | // Search & display main tab |
145 | 145 | T page = showPage(uri); |
146 | ||
146 | 147 | if (page != null) { |
147 | if (!uri.equals(page.getUri()) && (page instanceof UriOpenable)) { | |
148 | if (page instanceof UriOpenable) { | |
148 | 149 | // Enable page changed event |
149 | 150 | pageChangedListenersEnabled = true; |
150 | 151 | // Search & display sub tab |
151 | 152 | return ((UriOpenable)page).openUri(uri); |
152 | 153 | } |
153 | 154 | return true; |
154 | } else { | |
155 | return false; | |
156 | 155 | } |
157 | 156 | } finally { |
158 | 157 | // Enable page changed event |
159 | 158 | pageChangedListenersEnabled = true; |
160 | 159 | } |
160 | ||
161 | return false; | |
161 | 162 | } |
162 | 163 | |
163 | 164 | // --- PageChangedListener --- // |
107 | 107 | tabbedPanel.setMinimumSize(new Dimension(150, 10)); |
108 | 108 | tabbedPanel.tabbedPane.addChangeListener(e -> pageChanged()); |
109 | 109 | |
110 | setLayout(new BorderLayout()); | |
111 | ||
112 | JSplitPane splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(tree), tabbedPanel); | |
110 | setLayout(new BorderLayout()); | |
111 | ||
112 | JSplitPane splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(tree), tabbedPanel); | |
113 | 113 | splitter.setResizeWeight(0.2); |
114 | 114 | |
115 | 115 | add(splitter, BorderLayout.CENTER); |
229 | 229 | public boolean openUri(URI uri) { |
230 | 230 | try { |
231 | 231 | URI baseUri = new URI(uri.getScheme(), uri.getHost(), uri.getPath(), null); |
232 | DefaultMutableTreeNode baseNode = searchTreeNode(baseUri, (DefaultMutableTreeNode)tree.getModel().getRoot()); | |
233 | ||
234 | if ((baseNode != null) && showPage(uri, baseUri, baseNode)) { | |
235 | DefaultMutableTreeNode node = searchTreeNode(uri, baseNode); | |
232 | ||
233 | if (this.uri.equals(baseUri)) { | |
234 | return true; | |
235 | } else { | |
236 | DefaultMutableTreeNode node = searchTreeNode(baseUri, (DefaultMutableTreeNode) tree.getModel().getRoot()); | |
237 | ||
238 | if (showPage(uri, baseUri, node)) { | |
239 | DefaultMutableTreeNode childNode = searchTreeNode(uri, node); | |
240 | if (childNode != null) { | |
241 | node = childNode; | |
242 | } | |
243 | } | |
236 | 244 | |
237 | 245 | if (node != null) { |
238 | 246 | try { |
239 | 247 | // Disable tree node changed listener |
240 | 248 | treeNodeChangedEnabled = false; |
249 | // Populate and expand node | |
250 | if (!(node instanceof PageCreator) && (node instanceof TreeNodeExpandable)) { | |
251 | ((TreeNodeExpandable) node).populateTreeNode(api); | |
252 | tree.expandPath(new TreePath(node.getPath())); | |
253 | } | |
241 | 254 | // Select tree node |
242 | 255 | TreePath treePath = new TreePath(node.getPath()); |
243 | 256 | tree.setSelectionPath(treePath); |
246 | 259 | // Enable tree node changed listener |
247 | 260 | treeNodeChangedEnabled = true; |
248 | 261 | } |
249 | } | |
250 | return true; | |
262 | return true; | |
263 | } | |
251 | 264 | } |
252 | 265 | } catch (URISyntaxException e) { |
253 | 266 | assert ExceptionUtil.printStackTrace(e); |
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.model.container; | |
8 | ||
9 | import org.jd.gui.api.API; | |
10 | import org.jd.gui.api.model.Container; | |
11 | ||
12 | import java.nio.file.Path; | |
13 | ||
14 | public class JavaModuleContainer extends GenericContainer { | |
15 | public JavaModuleContainer(API api, Container.Entry parentEntry, Path rootPath) { | |
16 | super(api, parentEntry, rootPath); | |
17 | } | |
18 | ||
19 | public String getType() { return "jmod"; } | |
20 | } |
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.model.container; | |
8 | ||
9 | import org.jd.gui.api.API; | |
10 | import org.jd.gui.api.model.Container; | |
11 | ||
12 | import java.nio.file.Path; | |
13 | ||
14 | public class JmodContainer extends GenericContainer { | |
15 | public JmodContainer(API api, Container.Entry parentEntry, Path rootPath) { | |
16 | super(api, parentEntry, rootPath); | |
17 | } | |
18 | ||
19 | public String getType() { return "jmod"; } | |
20 | } |
+43
-0
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.service.container; | |
8 | ||
9 | import org.jd.gui.api.API; | |
10 | import org.jd.gui.api.model.Container; | |
11 | import org.jd.gui.model.container.JavaModuleContainer; | |
12 | import org.jd.gui.spi.ContainerFactory; | |
13 | import org.jd.gui.util.exception.ExceptionUtil; | |
14 | ||
15 | import java.nio.file.Files; | |
16 | import java.nio.file.InvalidPathException; | |
17 | import java.nio.file.Path; | |
18 | ||
19 | public class JavaModuleContainerFactoryProvider implements ContainerFactory { | |
20 | @Override | |
21 | public String getType() { return "jmod"; } | |
22 | ||
23 | @Override | |
24 | public boolean accept(API api, Path rootPath) { | |
25 | if (rootPath.toUri().toString().toLowerCase().endsWith(".jmod!/")) { | |
26 | return true; | |
27 | } else { | |
28 | // Extension: accept uncompressed JMOD file containing a folder 'classes' | |
29 | try { | |
30 | return rootPath.getFileSystem().provider().getScheme().equals("file") && Files.exists(rootPath.resolve("classes")); | |
31 | } catch (InvalidPathException e) { | |
32 | assert ExceptionUtil.printStackTrace(e); | |
33 | return false; | |
34 | } | |
35 | } | |
36 | } | |
37 | ||
38 | @Override | |
39 | public Container make(API api, Container.Entry parentEntry, Path rootPath) { | |
40 | return new JavaModuleContainer(api, parentEntry, rootPath); | |
41 | } | |
42 | } |
+0
-43
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.service.container; | |
8 | ||
9 | import org.jd.gui.api.API; | |
10 | import org.jd.gui.api.model.Container; | |
11 | import org.jd.gui.model.container.JmodContainer; | |
12 | import org.jd.gui.spi.ContainerFactory; | |
13 | import org.jd.gui.util.exception.ExceptionUtil; | |
14 | ||
15 | import java.nio.file.Files; | |
16 | import java.nio.file.InvalidPathException; | |
17 | import java.nio.file.Path; | |
18 | ||
19 | public class JmodContainerFactoryProvider implements ContainerFactory { | |
20 | @Override | |
21 | public String getType() { return "jmod"; } | |
22 | ||
23 | @Override | |
24 | public boolean accept(API api, Path rootPath) { | |
25 | if (rootPath.toUri().toString().toLowerCase().endsWith(".jmod!/")) { | |
26 | return true; | |
27 | } else { | |
28 | // Extension: accept uncompressed JMOD file containing a folder 'classes' | |
29 | try { | |
30 | return rootPath.getFileSystem().provider().getScheme().equals("file") && Files.exists(rootPath.resolve("classes")); | |
31 | } catch (InvalidPathException e) { | |
32 | assert ExceptionUtil.printStackTrace(e); | |
33 | return false; | |
34 | } | |
35 | } | |
36 | } | |
37 | ||
38 | @Override | |
39 | public Container make(API api, Container.Entry parentEntry, Path rootPath) { | |
40 | return new JmodContainer(api, parentEntry, rootPath); | |
41 | } | |
42 | } |
+24
-0
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.service.fileloader; | |
8 | ||
9 | import org.jd.gui.api.API; | |
10 | ||
11 | import java.io.File; | |
12 | ||
13 | public class JavaModuleFileLoaderProvider extends ZipFileLoaderProvider { | |
14 | protected static final String[] EXTENSIONS = { "jmod" }; | |
15 | ||
16 | @Override public String[] getExtensions() { return EXTENSIONS; } | |
17 | @Override public String getDescription() { return "Java module files (*.jmod)"; } | |
18 | ||
19 | @Override | |
20 | public boolean accept(API api, File file) { | |
21 | return file.exists() && file.isFile() && file.canRead() && file.getName().toLowerCase().endsWith(".jmod"); | |
22 | } | |
23 | } |
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.service.fileloader; | |
8 | ||
9 | import org.jd.gui.api.API; | |
10 | ||
11 | import java.io.File; | |
12 | ||
13 | public class JmodFileLoaderProvider extends ZipFileLoaderProvider { | |
14 | protected static final String[] EXTENSIONS = { "jmod" }; | |
15 | ||
16 | @Override public String[] getExtensions() { return EXTENSIONS; } | |
17 | @Override public String getDescription() { return "Java module files (*.jmod)"; } | |
18 | ||
19 | @Override | |
20 | public boolean accept(API api, File file) { | |
21 | return file.exists() && file.isFile() && file.canRead() && file.getName().toLowerCase().endsWith(".jmod"); | |
22 | } | |
23 | } |
76 | 76 | } |
77 | 77 | } |
78 | 78 | |
79 | public Pattern getPathPattern() { return externalPathPattern; } | |
79 | @Override public Pattern getPathPattern() { return externalPathPattern; } | |
80 | 80 | |
81 | 81 | @SuppressWarnings("unchecked") |
82 | protected static void addToIndex(Indexes indexes, String indexName, Set<String> set, Container.Entry entry) { | |
82 | protected static void addToIndexes(Indexes indexes, String indexName, Set<String> set, Container.Entry entry) { | |
83 | 83 | if (set.size() > 0) { |
84 | 84 | Map<String, Collection> index = indexes.getIndex(indexName); |
85 | 85 |
18 | 18 | import java.util.Collection; |
19 | 19 | import java.util.HashSet; |
20 | 20 | import java.util.Map; |
21 | import java.util.regex.Pattern; | |
22 | ||
23 | import static org.objectweb.asm.ClassReader.*; | |
21 | 24 | |
22 | 25 | /** |
23 | 26 | * Unsafe thread implementation of class file indexer. |
35 | 38 | protected HashSet<String> superTypeNameSet = new HashSet<>(); |
36 | 39 | protected HashSet<String> descriptorSet = new HashSet<>(); |
37 | 40 | |
38 | protected ClassIndexer classIndexer = new ClassIndexer( | |
39 | typeDeclarationSet, constructorDeclarationSet, methodDeclarationSet, | |
40 | fieldDeclarationSet, typeReferenceSet, superTypeNameSet, descriptorSet); | |
41 | protected SignatureIndexer signatureIndexer = new SignatureIndexer(typeReferenceSet); | |
41 | protected ClassIndexer classIndexer = new ClassIndexer(); | |
42 | protected SignatureIndexer signatureIndexer = new SignatureIndexer(); | |
42 | 43 | |
43 | 44 | @Override public String[] getSelectors() { return appendSelectors("*:file:*.class"); } |
45 | ||
46 | @Override | |
47 | public Pattern getPathPattern() { | |
48 | if (externalPathPattern == null) { | |
49 | return Pattern.compile("^((?!module-info\\.class).)*$"); | |
50 | } else { | |
51 | return externalPathPattern; | |
52 | } | |
53 | } | |
44 | 54 | |
45 | 55 | @Override |
46 | 56 | @SuppressWarnings("unchecked") |
61 | 71 | try (InputStream inputStream = entry.getInputStream()) { |
62 | 72 | // Index field, method, interfaces & super type |
63 | 73 | ClassReader classReader = new ClassReader(inputStream); |
64 | classReader.accept(classIndexer, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); | |
74 | classReader.accept(classIndexer, SKIP_CODE|SKIP_DEBUG|SKIP_FRAMES); | |
65 | 75 | |
66 | 76 | // Index descriptors |
67 | 77 | for (String descriptor : descriptorSet) { |
123 | 133 | String typeName = classIndexer.name; |
124 | 134 | |
125 | 135 | // Append sets to indexes |
126 | addToIndex(indexes, "typeDeclarations", typeDeclarationSet, entry); | |
127 | addToIndex(indexes, "constructorDeclarations", constructorDeclarationSet, entry); | |
128 | addToIndex(indexes, "methodDeclarations", methodDeclarationSet, entry); | |
129 | addToIndex(indexes, "fieldDeclarations", fieldDeclarationSet, entry); | |
130 | addToIndex(indexes, "typeReferences", typeReferenceSet, entry); | |
131 | addToIndex(indexes, "constructorReferences", constructorReferenceSet, entry); | |
132 | addToIndex(indexes, "methodReferences", methodReferenceSet, entry); | |
133 | addToIndex(indexes, "fieldReferences", fieldReferenceSet, entry); | |
134 | addToIndex(indexes, "strings", stringSet, entry); | |
136 | addToIndexes(indexes, "typeDeclarations", typeDeclarationSet, entry); | |
137 | addToIndexes(indexes, "constructorDeclarations", constructorDeclarationSet, entry); | |
138 | addToIndexes(indexes, "methodDeclarations", methodDeclarationSet, entry); | |
139 | addToIndexes(indexes, "fieldDeclarations", fieldDeclarationSet, entry); | |
140 | addToIndexes(indexes, "typeReferences", typeReferenceSet, entry); | |
141 | addToIndexes(indexes, "constructorReferences", constructorReferenceSet, entry); | |
142 | addToIndexes(indexes, "methodReferences", methodReferenceSet, entry); | |
143 | addToIndexes(indexes, "fieldReferences", fieldReferenceSet, entry); | |
144 | addToIndexes(indexes, "strings", stringSet, entry); | |
135 | 145 | |
136 | 146 | // Populate map [super type name : [sub type name]] |
137 | 147 | if (superTypeNameSet.size() > 0) { |
146 | 156 | } |
147 | 157 | } |
148 | 158 | |
149 | protected static class ClassIndexer extends ClassVisitor { | |
150 | protected HashSet<String> typeDeclarationSet; | |
151 | protected HashSet<String> constructorDeclarationSet; | |
152 | protected HashSet<String> methodDeclarationSet; | |
153 | protected HashSet<String> fieldDeclarationSet; | |
154 | protected HashSet<String> typeReferenceSet; | |
155 | protected HashSet<String> superTypeNameSet; | |
156 | protected HashSet<String> descriptorSet; | |
157 | ||
158 | protected AnnotationIndexer annotationIndexer; | |
159 | protected FieldIndexer fieldIndexer; | |
160 | protected MethodIndexer methodIndexer; | |
159 | protected class ClassIndexer extends ClassVisitor { | |
160 | protected AnnotationIndexer annotationIndexer = new AnnotationIndexer(); | |
161 | protected FieldIndexer fieldIndexer = new FieldIndexer(annotationIndexer); | |
162 | protected MethodIndexer methodIndexer = new MethodIndexer(annotationIndexer); | |
161 | 163 | |
162 | 164 | protected String name; |
163 | 165 | |
164 | public ClassIndexer( | |
165 | HashSet<String> typeDeclarationSet, HashSet<String> constructorDeclarationSet, | |
166 | HashSet<String> methodDeclarationSet, HashSet<String> fieldDeclarationSet, | |
167 | HashSet<String> typeReferenceSet, HashSet<String> superTypeNameSet, HashSet<String> descriptorSet) { | |
168 | super(Opcodes.ASM7); | |
169 | ||
170 | this.typeDeclarationSet = typeDeclarationSet; | |
171 | this.constructorDeclarationSet = constructorDeclarationSet; | |
172 | this.methodDeclarationSet = methodDeclarationSet; | |
173 | this.fieldDeclarationSet = fieldDeclarationSet; | |
174 | this.typeReferenceSet = typeReferenceSet; | |
175 | this.superTypeNameSet = superTypeNameSet; | |
176 | this.descriptorSet = descriptorSet; | |
177 | ||
178 | this.annotationIndexer = new AnnotationIndexer(descriptorSet); | |
179 | this.fieldIndexer = new FieldIndexer(descriptorSet, annotationIndexer); | |
180 | this.methodIndexer = new MethodIndexer(descriptorSet, annotationIndexer); | |
181 | } | |
182 | ||
166 | public ClassIndexer() { super(Opcodes.ASM7); } | |
167 | ||
168 | @Override | |
183 | 169 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { |
184 | 170 | this.name = name; |
185 | 171 | typeDeclarationSet.add(name); |
195 | 181 | } |
196 | 182 | } |
197 | 183 | |
184 | @Override | |
198 | 185 | public AnnotationVisitor visitAnnotation(String desc, boolean visible) { |
199 | 186 | descriptorSet.add(desc); |
200 | 187 | return annotationIndexer; |
201 | 188 | } |
202 | 189 | |
190 | @Override | |
203 | 191 | public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { |
204 | 192 | descriptorSet.add(desc); |
205 | 193 | return annotationIndexer; |
206 | 194 | } |
207 | 195 | |
196 | @Override | |
208 | 197 | public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { |
209 | 198 | fieldDeclarationSet.add(name); |
210 | 199 | descriptorSet.add(signature==null ? desc : signature); |
211 | 200 | return fieldIndexer; |
212 | 201 | } |
213 | 202 | |
203 | @Override | |
214 | 204 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { |
215 | 205 | if ("<init>".equals(name)) { |
216 | 206 | constructorDeclarationSet.add(this.name); |
229 | 219 | } |
230 | 220 | } |
231 | 221 | |
232 | protected static class SignatureIndexer extends SignatureVisitor { | |
233 | protected HashSet<String> typeReferenceSet; | |
234 | ||
235 | SignatureIndexer(HashSet<String> typeReferenceSet) { | |
222 | protected class SignatureIndexer extends SignatureVisitor { | |
223 | SignatureIndexer() { super(Opcodes.ASM7); } | |
224 | ||
225 | @Override public void visitClassType(String name) { typeReferenceSet.add(name); } | |
226 | } | |
227 | ||
228 | protected class AnnotationIndexer extends AnnotationVisitor { | |
229 | public AnnotationIndexer() { super(Opcodes.ASM7); } | |
230 | ||
231 | @Override public void visitEnum(String name, String desc, String value) { descriptorSet.add(desc); } | |
232 | ||
233 | @Override | |
234 | public AnnotationVisitor visitAnnotation(String name, String desc) { | |
235 | descriptorSet.add(desc); | |
236 | return this; | |
237 | } | |
238 | } | |
239 | ||
240 | protected class FieldIndexer extends FieldVisitor { | |
241 | protected AnnotationIndexer annotationIndexer; | |
242 | ||
243 | public FieldIndexer(AnnotationIndexer annotationIndexer) { | |
236 | 244 | super(Opcodes.ASM7); |
237 | this.typeReferenceSet = typeReferenceSet; | |
238 | } | |
239 | ||
240 | public void visitClassType(String name) { | |
241 | typeReferenceSet.add(name); | |
242 | } | |
243 | } | |
244 | ||
245 | protected static class AnnotationIndexer extends AnnotationVisitor { | |
246 | protected HashSet<String> descriptorSet; | |
247 | ||
248 | public AnnotationIndexer(HashSet<String> descriptorSet) { | |
245 | this.annotationIndexer = annotationIndexer; | |
246 | } | |
247 | ||
248 | @Override | |
249 | public AnnotationVisitor visitAnnotation(String desc, boolean visible) { | |
250 | descriptorSet.add(desc); | |
251 | return annotationIndexer; | |
252 | } | |
253 | ||
254 | @Override | |
255 | public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { | |
256 | descriptorSet.add(desc); | |
257 | return annotationIndexer; | |
258 | } | |
259 | } | |
260 | ||
261 | protected class MethodIndexer extends MethodVisitor { | |
262 | protected AnnotationIndexer annotationIndexer; | |
263 | ||
264 | public MethodIndexer(AnnotationIndexer annotationIndexer) { | |
249 | 265 | super(Opcodes.ASM7); |
250 | this.descriptorSet = descriptorSet; | |
251 | } | |
252 | ||
253 | public void visitEnum(String name, String desc, String value) { | |
254 | descriptorSet.add(desc); | |
255 | } | |
256 | ||
257 | public AnnotationVisitor visitAnnotation(String name, String desc) { | |
258 | descriptorSet.add(desc); | |
259 | return this; | |
260 | } | |
261 | } | |
262 | ||
263 | protected static class FieldIndexer extends FieldVisitor { | |
264 | protected HashSet<String> descriptorSet; | |
265 | protected AnnotationIndexer annotationIndexer; | |
266 | ||
267 | public FieldIndexer(HashSet<String> descriptorSet, AnnotationIndexer annotationInexer) { | |
268 | super(Opcodes.ASM7); | |
269 | this.descriptorSet = descriptorSet; | |
270 | this.annotationIndexer = annotationInexer; | |
271 | } | |
272 | ||
266 | this.annotationIndexer = annotationIndexer; | |
267 | } | |
268 | ||
269 | @Override | |
273 | 270 | public AnnotationVisitor visitAnnotation(String desc, boolean visible) { |
274 | 271 | descriptorSet.add(desc); |
275 | 272 | return annotationIndexer; |
276 | 273 | } |
277 | 274 | |
275 | @Override | |
278 | 276 | public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { |
279 | 277 | descriptorSet.add(desc); |
280 | 278 | return annotationIndexer; |
281 | 279 | } |
282 | } | |
283 | ||
284 | protected static class MethodIndexer extends MethodVisitor { | |
285 | protected HashSet<String> descriptorSet; | |
286 | protected AnnotationIndexer annotationIndexer; | |
287 | ||
288 | public MethodIndexer(HashSet<String> descriptorSet, AnnotationIndexer annotationIndexer) { | |
289 | super(Opcodes.ASM7); | |
290 | this.descriptorSet = descriptorSet; | |
291 | this.annotationIndexer = annotationIndexer; | |
292 | } | |
293 | ||
294 | public AnnotationVisitor visitAnnotation(String desc, boolean visible) { | |
295 | descriptorSet.add(desc); | |
296 | return annotationIndexer; | |
297 | } | |
298 | ||
299 | public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { | |
300 | descriptorSet.add(desc); | |
301 | return annotationIndexer; | |
302 | } | |
303 | ||
280 | ||
281 | @Override | |
304 | 282 | public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { |
305 | 283 | descriptorSet.add(desc); |
306 | 284 | return annotationIndexer; |
42 | 42 | ANTLRJavaParser.parse(new ANTLRInputStream(inputStream), listener); |
43 | 43 | |
44 | 44 | // Append sets to indexes |
45 | addToIndex(indexes, "typeDeclarations", listener.getTypeDeclarationSet(), entry); | |
46 | addToIndex(indexes, "constructorDeclarations", listener.getConstructorDeclarationSet(), entry); | |
47 | addToIndex(indexes, "methodDeclarations", listener.getMethodDeclarationSet(), entry); | |
48 | addToIndex(indexes, "fieldDeclarations", listener.getFieldDeclarationSet(), entry); | |
49 | addToIndex(indexes, "typeReferences", listener.getTypeReferenceSet(), entry); | |
50 | addToIndex(indexes, "constructorReferences", listener.getConstructorReferenceSet(), entry); | |
51 | addToIndex(indexes, "methodReferences", listener.getMethodReferenceSet(), entry); | |
52 | addToIndex(indexes, "fieldReferences", listener.getFieldReferenceSet(), entry); | |
53 | addToIndex(indexes, "strings", listener.getStringSet(), entry); | |
45 | addToIndexes(indexes, "typeDeclarations", listener.getTypeDeclarationSet(), entry); | |
46 | addToIndexes(indexes, "constructorDeclarations", listener.getConstructorDeclarationSet(), entry); | |
47 | addToIndexes(indexes, "methodDeclarations", listener.getMethodDeclarationSet(), entry); | |
48 | addToIndexes(indexes, "fieldDeclarations", listener.getFieldDeclarationSet(), entry); | |
49 | addToIndexes(indexes, "typeReferences", listener.getTypeReferenceSet(), entry); | |
50 | addToIndexes(indexes, "constructorReferences", listener.getConstructorReferenceSet(), entry); | |
51 | addToIndexes(indexes, "methodReferences", listener.getMethodReferenceSet(), entry); | |
52 | addToIndexes(indexes, "fieldReferences", listener.getFieldReferenceSet(), entry); | |
53 | addToIndexes(indexes, "strings", listener.getStringSet(), entry); | |
54 | 54 | |
55 | 55 | // Populate map [super type name : [sub type name]] |
56 | 56 | Map<String, Collection> index = indexes.getIndex("subTypeNames"); |
+54
-0
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.service.indexer; | |
8 | ||
9 | import org.jd.gui.api.API; | |
10 | import org.jd.gui.api.model.Container; | |
11 | import org.jd.gui.api.model.Indexes; | |
12 | import org.jd.gui.spi.Indexer; | |
13 | ||
14 | import java.util.Collection; | |
15 | import java.util.Map; | |
16 | ||
17 | public class JavaModuleFileIndexerProvider extends AbstractIndexerProvider { | |
18 | ||
19 | @Override public String[] getSelectors() { return appendSelectors("*:file:*.jmod"); } | |
20 | ||
21 | @Override | |
22 | public void index(API api, Container.Entry entry, Indexes indexes) { | |
23 | for (Container.Entry e : entry.getChildren()) { | |
24 | if (e.isDirectory() && e.getPath().equals("classes")) { | |
25 | Map<String, Collection> packageDeclarationIndex = indexes.getIndex("packageDeclarations"); | |
26 | ||
27 | // Index module-info, packages and CLASS files | |
28 | index(api, e, indexes, packageDeclarationIndex); | |
29 | break; | |
30 | } | |
31 | } | |
32 | } | |
33 | ||
34 | protected static void index(API api, Container.Entry entry, Indexes indexes, Map<String, Collection> packageDeclarationIndex) { | |
35 | for (Container.Entry e : entry.getChildren()) { | |
36 | if (e.isDirectory()) { | |
37 | String path = e.getPath(); | |
38 | ||
39 | if (!path.startsWith("classes/META-INF")) { | |
40 | packageDeclarationIndex.get(path.substring(8)).add(e); // 8 = "classes/".length() | |
41 | } | |
42 | ||
43 | index(api, e, indexes, packageDeclarationIndex); | |
44 | } else { | |
45 | Indexer indexer = api.getIndexer(e); | |
46 | ||
47 | if (indexer != null) { | |
48 | indexer.index(api, e, indexes); | |
49 | } | |
50 | } | |
51 | } | |
52 | } | |
53 | } |
+103
-0
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.service.indexer; | |
8 | ||
9 | import org.jd.gui.api.API; | |
10 | import org.jd.gui.api.model.Container; | |
11 | import org.jd.gui.api.model.Indexes; | |
12 | import org.jd.gui.util.exception.ExceptionUtil; | |
13 | import org.objectweb.asm.*; | |
14 | ||
15 | import java.io.InputStream; | |
16 | import java.util.HashSet; | |
17 | ||
18 | import static org.objectweb.asm.ClassReader.*; | |
19 | ||
20 | /** | |
21 | * Unsafe thread implementation of class file indexer. | |
22 | */ | |
23 | public class JavaModuleInfoFileIndexerProvider extends AbstractIndexerProvider { | |
24 | protected HashSet<String> javaModuleDeclarationSet = new HashSet<>(); | |
25 | protected HashSet<String> javaModuleReferenceSet = new HashSet<>(); | |
26 | protected HashSet<String> typeReferenceSet = new HashSet<>(); | |
27 | ||
28 | protected ClassIndexer classIndexer = new ClassIndexer(); | |
29 | ||
30 | @Override public String[] getSelectors() { return appendSelectors("jmod:file:classes/module-info.class"); } | |
31 | ||
32 | @Override | |
33 | @SuppressWarnings("unchecked") | |
34 | public void index(API api, Container.Entry entry, Indexes indexes) { | |
35 | // Cleaning sets... | |
36 | javaModuleDeclarationSet.clear(); | |
37 | javaModuleReferenceSet.clear(); | |
38 | typeReferenceSet.clear(); | |
39 | ||
40 | try (InputStream inputStream = entry.getInputStream()) { | |
41 | // Index field, method, interfaces & super type | |
42 | ClassReader classReader = new ClassReader(inputStream); | |
43 | classReader.accept(classIndexer, SKIP_CODE|SKIP_DEBUG|SKIP_FRAMES); | |
44 | ||
45 | // Append sets to indexes | |
46 | addToIndexes(indexes, "javaModuleDeclarations", javaModuleDeclarationSet, entry); | |
47 | addToIndexes(indexes, "javaModuleReferences", javaModuleReferenceSet, entry); | |
48 | addToIndexes(indexes, "typeReferences", typeReferenceSet, entry); | |
49 | } catch (Exception e) { | |
50 | assert ExceptionUtil.printStackTrace(e); | |
51 | } | |
52 | } | |
53 | ||
54 | protected class ClassIndexer extends ClassVisitor { | |
55 | protected ModuleIndexer moduleIndexer = new ModuleIndexer(); | |
56 | ||
57 | public ClassIndexer() { super(Opcodes.ASM7); } | |
58 | ||
59 | @Override | |
60 | public ModuleVisitor visitModule(String moduleName, int moduleFlags, String moduleVersion) { | |
61 | javaModuleDeclarationSet.add(moduleName); | |
62 | return moduleIndexer; | |
63 | } | |
64 | } | |
65 | ||
66 | protected class ModuleIndexer extends ModuleVisitor { | |
67 | public ModuleIndexer() { super(Opcodes.ASM7); } | |
68 | ||
69 | @Override public void visitMainClass(final String mainClass) { typeReferenceSet.add(mainClass); } | |
70 | @Override public void visitRequire(final String module, final int access, final String version) { javaModuleReferenceSet.add(module); } | |
71 | @Override public void visitUse(final String service) { typeReferenceSet.add(service); } | |
72 | ||
73 | @Override | |
74 | public void visitExport(final String packaze, final int access, final String... modules) { | |
75 | if (modules != null) { | |
76 | for (String module : modules) { | |
77 | javaModuleReferenceSet.add(module); | |
78 | } | |
79 | } | |
80 | } | |
81 | ||
82 | @Override | |
83 | public void visitOpen(final String packaze, final int access, final String... modules) { | |
84 | if (modules != null) { | |
85 | for (String module : modules) { | |
86 | javaModuleReferenceSet.add(module); | |
87 | } | |
88 | } | |
89 | } | |
90 | ||
91 | @Override | |
92 | public void visitProvide(final String service, final String... providers) { | |
93 | typeReferenceSet.add(service); | |
94 | ||
95 | if (providers != null) { | |
96 | for (String provider : providers) { | |
97 | typeReferenceSet.add(provider); | |
98 | } | |
99 | } | |
100 | } | |
101 | } | |
102 | } |
13 | 13 | |
14 | 14 | public class ZipFileIndexerProvider extends AbstractIndexerProvider { |
15 | 15 | |
16 | @Override public String[] getSelectors() { return appendSelectors("*:file:*.zip", "*:file:*.jar", "*:file:*.war", "*:file:*.ear", "*:file:*.aar", "*:file:*.jmod"); } | |
16 | @Override public String[] getSelectors() { return appendSelectors("*:file:*.zip", "*:file:*.jar", "*:file:*.war", "*:file:*.ear", "*:file:*.aar"); } | |
17 | 17 | |
18 | 18 | @Override |
19 | 19 | public void index(API api, Container.Entry entry, Indexes indexes) { |
+33
-0
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.service.treenode; | |
8 | ||
9 | import org.jd.gui.api.API; | |
10 | import org.jd.gui.api.feature.ContainerEntryGettable; | |
11 | import org.jd.gui.api.feature.UriGettable; | |
12 | import org.jd.gui.api.model.Container; | |
13 | import org.jd.gui.view.data.TreeNodeBean; | |
14 | ||
15 | import javax.swing.tree.DefaultMutableTreeNode; | |
16 | import java.io.File; | |
17 | ||
18 | public class JavaModuleFileTreeNodeFactoryProvider extends ZipFileTreeNodeFactoryProvider { | |
19 | @Override public String[] getSelectors() { return appendSelectors("*:file:*.jmod"); } | |
20 | ||
21 | @Override | |
22 | @SuppressWarnings("unchecked") | |
23 | public <T extends DefaultMutableTreeNode & ContainerEntryGettable & UriGettable> T make(API api, Container.Entry entry) { | |
24 | int lastSlashIndex = entry.getPath().lastIndexOf("/"); | |
25 | String label = entry.getPath().substring(lastSlashIndex+1); | |
26 | String location = new File(entry.getUri()).getPath(); | |
27 | T node = (T)new TreeNode(entry, new TreeNodeBean(label, "Location: " + location, ICON)); | |
28 | // Add dummy node | |
29 | node.add(new DefaultMutableTreeNode()); | |
30 | return node; | |
31 | } | |
32 | } |
+24
-0
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.service.treenode; | |
8 | ||
9 | import java.util.regex.Pattern; | |
10 | ||
11 | public class JavaModulePackageTreeNodeFactoryProvider extends PackageTreeNodeFactoryProvider { | |
12 | ||
13 | @Override public String[] getSelectors() { return appendSelectors("jmod:dir:*"); } | |
14 | ||
15 | @Override | |
16 | public Pattern getPathPattern() { | |
17 | if (externalPathPattern == null) { | |
18 | return Pattern.compile("classes\\/.*"); | |
19 | } else { | |
20 | return externalPathPattern; | |
21 | } | |
22 | } | |
23 | } |
+0
-33
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.service.treenode; | |
8 | ||
9 | import org.jd.gui.api.API; | |
10 | import org.jd.gui.api.feature.ContainerEntryGettable; | |
11 | import org.jd.gui.api.feature.UriGettable; | |
12 | import org.jd.gui.api.model.Container; | |
13 | import org.jd.gui.view.data.TreeNodeBean; | |
14 | ||
15 | import javax.swing.tree.DefaultMutableTreeNode; | |
16 | import java.io.File; | |
17 | ||
18 | public class JmodFileTreeNodeFactoryProvider extends ZipFileTreeNodeFactoryProvider { | |
19 | @Override public String[] getSelectors() { return appendSelectors("*:file:*.jmod"); } | |
20 | ||
21 | @Override | |
22 | @SuppressWarnings("unchecked") | |
23 | public <T extends DefaultMutableTreeNode & ContainerEntryGettable & UriGettable> T make(API api, Container.Entry entry) { | |
24 | int lastSlashIndex = entry.getPath().lastIndexOf("/"); | |
25 | String label = entry.getPath().substring(lastSlashIndex+1); | |
26 | String location = new File(entry.getUri()).getPath(); | |
27 | T node = (T)new TreeNode(entry, new TreeNodeBean(label, "Location: " + location, ICON)); | |
28 | // Add dummy node | |
29 | node.add(new DefaultMutableTreeNode()); | |
30 | return node; | |
31 | } | |
32 | } |
+0
-24
0 | /* | |
1 | * Copyright (c) 2008-2019 Emmanuel Dupuy. | |
2 | * This project is distributed under the GPLv3 license. | |
3 | * This is a Copyleft license that gives the user the right to use, | |
4 | * copy and modify the code freely for non-commercial purposes. | |
5 | */ | |
6 | ||
7 | package org.jd.gui.service.treenode; | |
8 | ||
9 | import java.util.regex.Pattern; | |
10 | ||
11 | public class JmodPackageTreeNodeFactoryProvider extends PackageTreeNodeFactoryProvider { | |
12 | ||
13 | @Override public String[] getSelectors() { return appendSelectors("jmod:dir:*"); } | |
14 | ||
15 | @Override | |
16 | public Pattern getPathPattern() { | |
17 | if (externalPathPattern == null) { | |
18 | return Pattern.compile("classes\\/.*"); | |
19 | } else { | |
20 | return externalPathPattern; | |
21 | } | |
22 | } | |
23 | } |
+31
-1
10 | 10 | import org.jd.gui.api.feature.ContainerEntryGettable; |
11 | 11 | import org.jd.gui.api.feature.UriGettable; |
12 | 12 | import org.jd.gui.api.model.Container; |
13 | import org.jd.gui.api.model.Type; | |
14 | import org.jd.gui.spi.TypeFactory; | |
13 | 15 | import org.jd.gui.util.exception.ExceptionUtil; |
14 | 16 | import org.jd.gui.view.component.ModuleInfoFilePage; |
15 | 17 | import org.jd.gui.view.data.TreeNodeBean; |
17 | 19 | import javax.swing.*; |
18 | 20 | import javax.swing.tree.DefaultMutableTreeNode; |
19 | 21 | import java.io.File; |
22 | import java.util.Collection; | |
20 | 23 | import java.util.regex.Pattern; |
21 | 24 | |
22 | 25 | public class ModuleInfoFileTreeNodeFactoryProvider extends ClassFileTreeNodeFactoryProvider { |
26 | protected static final ImageIcon MODULE_FILE_ICON = new ImageIcon(ClassFileTreeNodeFactoryProvider.class.getClassLoader().getResource("org/jd/gui/images/module_obj.png")); | |
23 | 27 | protected static final Factory FACTORY = new Factory(); |
24 | 28 | |
25 | 29 | static { |
40 | 44 | public <T extends DefaultMutableTreeNode & ContainerEntryGettable & UriGettable> T make(API api, Container.Entry entry) { |
41 | 45 | int lastSlashIndex = entry.getPath().lastIndexOf('/'); |
42 | 46 | String label = entry.getPath().substring(lastSlashIndex+1); |
43 | return (T)new FileTreeNode(entry, new TreeNodeBean(label, CLASS_FILE_ICON), FACTORY); | |
47 | return (T)new ModuleInfoFileTreeNode(entry, new TreeNodeBean(label, CLASS_FILE_ICON), FACTORY); | |
48 | } | |
49 | ||
50 | protected static class ModuleInfoFileTreeNode extends FileTreeNode { | |
51 | public ModuleInfoFileTreeNode(Container.Entry entry, Object userObject, PageAndTipFactory pageAndTipFactory) { | |
52 | super(entry, null, userObject, pageAndTipFactory); | |
53 | } | |
54 | ||
55 | // --- TreeNodeExpandable --- // | |
56 | @Override | |
57 | public void populateTreeNode(API api) { | |
58 | if (!initialized) { | |
59 | removeAllChildren(); | |
60 | // Create type node | |
61 | TypeFactory typeFactory = api.getTypeFactory(entry); | |
62 | ||
63 | if (typeFactory != null) { | |
64 | Collection<Type> types = typeFactory.make(api, entry); | |
65 | ||
66 | for (Type type : types) { | |
67 | add(new BaseTreeNode(entry, type.getName(), new TreeNodeBean(type.getDisplayTypeName(), MODULE_FILE_ICON), factory)); | |
68 | } | |
69 | } | |
70 | ||
71 | initialized = true; | |
72 | } | |
73 | } | |
44 | 74 | } |
45 | 75 | |
46 | 76 | protected static class Factory implements AbstractTypeFileTreeNodeFactoryProvider.PageAndTipFactory { |
9 | 9 | import org.jd.core.v1.api.printer.Printer; |
10 | 10 | |
11 | 11 | public class StringBuilderPrinter implements Printer { |
12 | protected static final String TAB = " "; | |
13 | protected static final String NEWLINE = "\n"; | |
12 | protected static final String TAB = " "; | |
13 | protected static final String NEWLINE = "\n"; | |
14 | 14 | |
15 | protected StringBuilder stringBuffer = new StringBuilder(10*1024); | |
15 | protected StringBuilder stringBuffer = new StringBuilder(10*1024); | |
16 | 16 | |
17 | protected boolean unicodeEscape = true; | |
18 | protected boolean realignmentLineNumber = false; | |
17 | protected boolean unicodeEscape = true; | |
18 | protected boolean realignmentLineNumber = false; | |
19 | 19 | |
20 | protected int majorVersion = 0; | |
21 | protected int minorVersion = 0; | |
22 | protected int indentationCount; | |
20 | protected int majorVersion = 0; | |
21 | protected int minorVersion = 0; | |
22 | protected int indentationCount; | |
23 | 23 | |
24 | public void setUnicodeEscape(boolean unicodeEscape) { this.unicodeEscape = unicodeEscape; } | |
25 | public void setRealignmentLineNumber(boolean realignmentLineNumber) { this.realignmentLineNumber = realignmentLineNumber; } | |
24 | public void setUnicodeEscape(boolean unicodeEscape) { this.unicodeEscape = unicodeEscape; } | |
25 | public void setRealignmentLineNumber(boolean realignmentLineNumber) { this.realignmentLineNumber = realignmentLineNumber; } | |
26 | 26 | |
27 | public int getMajorVersion() { return majorVersion; } | |
28 | public int getMinorVersion() { return minorVersion; } | |
29 | public StringBuilder getStringBuffer() { return stringBuffer; } | |
27 | public int getMajorVersion() { return majorVersion; } | |
28 | public int getMinorVersion() { return minorVersion; } | |
29 | public StringBuilder getStringBuffer() { return stringBuffer; } | |
30 | 30 | |
31 | public void append(char c) { stringBuffer.append(c); } | |
32 | public void append(String s) { stringBuffer.append(s); } | |
31 | public void append(char c) { stringBuffer.append(c); } | |
32 | public void append(String s) { stringBuffer.append(s); } | |
33 | 33 | |
34 | protected void printEscape(String s) { | |
35 | if (unicodeEscape && (s != null)) { | |
36 | int length = s.length(); | |
34 | protected void printEscape(String s) { | |
35 | if (unicodeEscape && (s != null)) { | |
36 | int length = s.length(); | |
37 | 37 | |
38 | for (int i=0; i<length; i++) { | |
39 | char c = s.charAt(i); | |
38 | for (int i=0; i<length; i++) { | |
39 | char c = s.charAt(i); | |
40 | 40 | |
41 | if (c == '\t') { | |
42 | append(c); | |
43 | } else if (c < 32) { | |
44 | // Write octal format | |
45 | append("\\0"); | |
46 | append((char) ('0' + (c >> 3))); | |
47 | append((char) ('0' + (c & 0x7))); | |
48 | } else if (c > 127) { | |
49 | // Write octal format | |
50 | append("\\u"); | |
41 | if (c == '\t') { | |
42 | append(c); | |
43 | } else if (c < 32) { | |
44 | // Write octal format | |
45 | append("\\0"); | |
46 | append((char) ('0' + (c >> 3))); | |
47 | append((char) ('0' + (c & 0x7))); | |
48 | } else if (c > 127) { | |
49 | // Write octal format | |
50 | append("\\u"); | |
51 | 51 | |
52 | int z = (c >> 12); | |
53 | append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); | |
54 | z = ((c >> 8) & 0xF); | |
55 | append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); | |
56 | z = ((c >> 4) & 0xF); | |
57 | append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); | |
58 | z = (c & 0xF); | |
59 | append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); | |
60 | } else { | |
61 | append(c); | |
62 | } | |
63 | } | |
64 | } else { | |
65 | append(s); | |
66 | } | |
67 | } | |
52 | int z = (c >> 12); | |
53 | append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); | |
54 | z = ((c >> 8) & 0xF); | |
55 | append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); | |
56 | z = ((c >> 4) & 0xF); | |
57 | append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); | |
58 | z = (c & 0xF); | |
59 | append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); | |
60 | } else { | |
61 | append(c); | |
62 | } | |
63 | } | |
64 | } else { | |
65 | append(s); | |
66 | } | |
67 | } | |
68 | 68 | |
69 | // --- Printer --- // | |
70 | @Override | |
71 | public void start(int maxLineNumber, int majorVersion, int minorVersion) { | |
72 | this.stringBuffer.setLength(0); | |
73 | this.majorVersion = majorVersion; | |
74 | this.minorVersion = minorVersion; | |
75 | this.indentationCount = 0; | |
76 | } | |
69 | // --- Printer --- // | |
70 | @Override | |
71 | public void start(int maxLineNumber, int majorVersion, int minorVersion) { | |
72 | this.stringBuffer.setLength(0); | |
73 | this.majorVersion = majorVersion; | |
74 | this.minorVersion = minorVersion; | |
75 | this.indentationCount = 0; | |
76 | } | |
77 | 77 | |
78 | @Override public void end() {} | |
78 | @Override public void end() {} | |
79 | 79 | |
80 | @Override public void printText(String text) { printEscape(text); } | |
81 | @Override public void printNumericConstant(String constant) { append(constant); } | |
82 | @Override public void printStringConstant(String constant, String ownerInternalName) { append(constant); } | |
83 | @Override public void printKeyword(String keyword) { append(keyword); } | |
80 | @Override public void printText(String text) { printEscape(text); } | |
81 | @Override public void printNumericConstant(String constant) { append(constant); } | |
82 | @Override public void printStringConstant(String constant, String ownerInternalName) { append(constant); } | |
83 | @Override public void printKeyword(String keyword) { append(keyword); } | |
84 | 84 | |
85 | @Override public void printDeclaration(int flags, String internalTypeName, String name, String descriptor) { append(name); } | |
86 | @Override public void printReference(int flags, String internalTypeName, String name, String descriptor, String ownerInternalName) { append(name); } | |
85 | @Override public void printDeclaration(int type, String internalTypeName, String name, String descriptor) { append(name); } | |
86 | @Override public void printReference(int type, String internalTypeName, String name, String descriptor, String ownerInternalName) { append(name); } | |
87 | 87 | |
88 | @Override public void indent() { indentationCount++; } | |
89 | @Override public void unindent() { if (indentationCount > 0) indentationCount--; } | |
88 | @Override public void indent() { indentationCount++; } | |
89 | @Override public void unindent() { if (indentationCount > 0) indentationCount--; } | |
90 | 90 | |
91 | @Override public void startLine(int lineNumber) { for (int i=0; i<indentationCount; i++) append(TAB); } | |
92 | @Override public void endLine() { append(NEWLINE); } | |
93 | @Override public void extraLine(int count) { if (realignmentLineNumber) while (count-- > 0) append(NEWLINE); } | |
91 | @Override public void startLine(int lineNumber) { for (int i=0; i<indentationCount; i++) append(TAB); } | |
92 | @Override public void endLine() { append(NEWLINE); } | |
93 | @Override public void extraLine(int count) { if (realignmentLineNumber) while (count-- > 0) append(NEWLINE); } | |
94 | 94 | |
95 | @Override public void startMarker(int type) {} | |
96 | @Override public void endMarker(int type) {} | |
95 | @Override public void startMarker(int type) {} | |
96 | @Override public void endMarker(int type) {} | |
97 | 97 | } |
18 | 18 | |
19 | 19 | public class IndexesUtil { |
20 | 20 | public static boolean containsInternalTypeName(Collection<Future<Indexes>> collectionOfFutureIndexes, String internalTypeName) { |
21 | return contains(collectionOfFutureIndexes, "typeDeclarations", internalTypeName); | |
22 | } | |
23 | ||
24 | @SuppressWarnings("unchecked") | |
25 | public static List<Container.Entry> findInternalTypeName(Collection<Future<Indexes>> collectionOfFutureIndexes, String internalTypeName) { | |
26 | return find(collectionOfFutureIndexes, "typeDeclarations", internalTypeName); | |
27 | } | |
28 | ||
29 | public static boolean contains(Collection<Future<Indexes>> collectionOfFutureIndexes, String indexName, String key) { | |
21 | 30 | try { |
22 | 31 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { |
23 | 32 | if (futureIndexes.isDone()) { |
24 | Map<String, Collection> index = futureIndexes.get().getIndex("typeDeclarations"); | |
25 | if ((index != null) && (index.get(internalTypeName) != null)) { | |
33 | Map<String, Collection> index = futureIndexes.get().getIndex(indexName); | |
34 | if ((index != null) && (index.get(key) != null)) { | |
26 | 35 | return true; |
27 | 36 | } |
28 | 37 | } |
35 | 44 | } |
36 | 45 | |
37 | 46 | @SuppressWarnings("unchecked") |
38 | public static List<Container.Entry> findInternalTypeName(Collection<Future<Indexes>> collectionOfFutureIndexes, String internalTypeName) { | |
47 | public static List<Container.Entry> find(Collection<Future<Indexes>> collectionOfFutureIndexes, String indexName, String key) { | |
39 | 48 | ArrayList<Container.Entry> entries = new ArrayList<>(); |
40 | 49 | |
41 | 50 | try { |
42 | 51 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { |
43 | 52 | if (futureIndexes.isDone()) { |
44 | Map<String, Collection> index = futureIndexes.get().getIndex("typeDeclarations"); | |
53 | Map<String, Collection> index = futureIndexes.get().getIndex(indexName); | |
45 | 54 | if (index != null) { |
46 | Collection<Container.Entry> collection = index.get(internalTypeName); | |
55 | Collection<Container.Entry> collection = index.get(key); | |
47 | 56 | if (collection != null) { |
48 | 57 | entries.addAll(collection); |
49 | 58 | } |
168 | 168 | } |
169 | 169 | |
170 | 170 | @Override |
171 | public void printDeclaration(int flags, String internalTypeName, String name, String descriptor) { | |
171 | public void printDeclaration(int type, String internalTypeName, String name, String descriptor) { | |
172 | 172 | if (internalTypeName == null) internalTypeName = "null"; |
173 | 173 | if (name == null) name = "null"; |
174 | 174 | if (descriptor == null) descriptor = "null"; |
175 | 175 | |
176 | switch (flags) { | |
177 | case TYPE_FLAG: | |
176 | switch (type) { | |
177 | case TYPE: | |
178 | 178 | TypePage.DeclarationData data = new TypePage.DeclarationData(stringBuffer.length(), name.length(), internalTypeName, null, null); |
179 | 179 | declarations.put(internalTypeName, data); |
180 | 180 | typeDeclarations.put(stringBuffer.length(), data); |
181 | 181 | break; |
182 | case CONSTRUCTOR_FLAG: | |
182 | case CONSTRUCTOR: | |
183 | 183 | declarations.put(internalTypeName + "-<init>-" + descriptor, new TypePage.DeclarationData(stringBuffer.length(), name.length(), internalTypeName, "<init>", descriptor)); |
184 | 184 | break; |
185 | 185 | default: |
186 | 186 | declarations.put(internalTypeName + '-' + name + '-' + descriptor, new TypePage.DeclarationData(stringBuffer.length(), name.length(), internalTypeName, name, descriptor)); |
187 | 187 | break; |
188 | 188 | } |
189 | super.printDeclaration(flags, internalTypeName, name, descriptor); | |
190 | } | |
191 | ||
192 | @Override | |
193 | public void printReference(int flags, String internalTypeName, String name, String descriptor, String ownerInternalName) { | |
189 | super.printDeclaration(type, internalTypeName, name, descriptor); | |
190 | } | |
191 | ||
192 | @Override | |
193 | public void printReference(int type, String internalTypeName, String name, String descriptor, String ownerInternalName) { | |
194 | 194 | if (internalTypeName == null) internalTypeName = "null"; |
195 | 195 | if (name == null) name = "null"; |
196 | 196 | if (descriptor == null) descriptor = "null"; |
197 | 197 | |
198 | switch (flags) { | |
199 | case TYPE_FLAG: | |
198 | switch (type) { | |
199 | case TYPE: | |
200 | 200 | addHyperlink(new TypePage.HyperlinkReferenceData(stringBuffer.length(), name.length(), newReferenceData(internalTypeName, null, null, ownerInternalName))); |
201 | 201 | break; |
202 | case CONSTRUCTOR_FLAG: | |
202 | case CONSTRUCTOR: | |
203 | 203 | addHyperlink(new TypePage.HyperlinkReferenceData(stringBuffer.length(), name.length(), newReferenceData(internalTypeName, "<init>", descriptor, ownerInternalName))); |
204 | 204 | break; |
205 | 205 | default: |
206 | 206 | addHyperlink(new TypePage.HyperlinkReferenceData(stringBuffer.length(), name.length(), newReferenceData(internalTypeName, name, descriptor, ownerInternalName))); |
207 | 207 | break; |
208 | 208 | } |
209 | super.printReference(flags, internalTypeName, name, descriptor, ownerInternalName); | |
209 | super.printReference(type, internalTypeName, name, descriptor, ownerInternalName); | |
210 | 210 | } |
211 | 211 | |
212 | 212 | @Override |
7 | 7 | package org.jd.gui.view.component; |
8 | 8 | |
9 | 9 | import org.fife.ui.rsyntaxtextarea.*; |
10 | import org.fife.ui.rtextarea.Marker; | |
10 | 11 | import org.jd.gui.api.API; |
11 | 12 | import org.jd.gui.api.model.Container; |
13 | import org.jd.gui.api.model.Indexes; | |
12 | 14 | import org.jd.gui.util.decompiler.ContainerLoader; |
15 | import org.jd.gui.util.decompiler.StringBuilderPrinter; | |
13 | 16 | import org.jd.gui.util.exception.ExceptionUtil; |
17 | import org.jd.gui.util.index.IndexesUtil; | |
14 | 18 | |
15 | 19 | import javax.swing.text.Segment; |
16 | import java.util.Map; | |
20 | import java.awt.*; | |
21 | import java.net.URI; | |
22 | import java.net.URISyntaxException; | |
23 | import java.util.*; | |
24 | import java.util.List; | |
25 | import java.util.concurrent.Future; | |
26 | import java.util.regex.Matcher; | |
27 | import java.util.regex.Pattern; | |
28 | ||
29 | import static org.jd.core.v1.api.printer.Printer.MODULE; | |
30 | import static org.jd.core.v1.api.printer.Printer.PACKAGE; | |
31 | import static org.jd.core.v1.api.printer.Printer.TYPE; | |
17 | 32 | |
18 | 33 | public class ModuleInfoFilePage extends ClassFilePage { |
19 | 34 | public static final String SYNTAX_STYLE_JAVA_MODULE = "text/java-module"; |
28 | 43 | super(api, entry); |
29 | 44 | } |
30 | 45 | |
46 | @Override | |
31 | 47 | public void decompile(Map<String, String> preferences) { |
32 | 48 | try { |
33 | 49 | // Clear ... |
58 | 74 | } |
59 | 75 | } |
60 | 76 | |
77 | @Override | |
61 | 78 | public String getSyntaxStyle() { return SYNTAX_STYLE_JAVA_MODULE; } |
62 | 79 | |
63 | public class ModuleInfoFilePrinter extends ClassFilePrinter { | |
80 | @Override | |
81 | protected void openHyperlink(int x, int y, HyperlinkData hyperlinkData) { | |
82 | HyperlinkReferenceData hyperlinkReferenceData = (HyperlinkReferenceData)hyperlinkData; | |
83 | ||
84 | if (hyperlinkReferenceData.reference.enabled) { | |
85 | try { | |
86 | // Save current position in history | |
87 | Point location = textArea.getLocationOnScreen(); | |
88 | int offset = textArea.viewToModel(new Point(x - location.x, y - location.y)); | |
89 | URI uri = entry.getUri(); | |
90 | api.addURI(new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), "position=" + offset, null)); | |
91 | ||
92 | // Open link | |
93 | ModuleInfoReferenceData moduleInfoReferenceData = (ModuleInfoReferenceData)hyperlinkReferenceData.reference; | |
94 | List<Container.Entry> entries; | |
95 | String fragment; | |
96 | ||
97 | switch (moduleInfoReferenceData.type) { | |
98 | case TYPE: | |
99 | entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, fragment = moduleInfoReferenceData.typeName); | |
100 | break; | |
101 | case PACKAGE: | |
102 | entries = IndexesUtil.find(collectionOfFutureIndexes, "packageDeclarations", moduleInfoReferenceData.typeName); | |
103 | fragment = null; | |
104 | break; | |
105 | default: // MODULE | |
106 | entries = IndexesUtil.find(collectionOfFutureIndexes, "javaModuleDeclarations", moduleInfoReferenceData.name); | |
107 | fragment = moduleInfoReferenceData.typeName; | |
108 | break; | |
109 | } | |
110 | ||
111 | if (entries.contains(entry)) { | |
112 | api.openURI(uri); | |
113 | } else { | |
114 | String rootUri = entry.getContainer().getRoot().getUri().toString(); | |
115 | ArrayList<Container.Entry> sameContainerEntries = new ArrayList<>(); | |
116 | ||
117 | for (Container.Entry entry : entries) { | |
118 | if (entry.getUri().toString().startsWith(rootUri)) { | |
119 | sameContainerEntries.add(entry); | |
120 | } | |
121 | } | |
122 | ||
123 | if (sameContainerEntries.size() > 0) { | |
124 | api.openURI(x, y, sameContainerEntries, null, fragment); | |
125 | } else if (entries.size() > 0) { | |
126 | api.openURI(x, y, entries, null, fragment); | |
127 | } | |
128 | } | |
129 | } catch (URISyntaxException e) { | |
130 | assert ExceptionUtil.printStackTrace(e); | |
131 | } | |
132 | } | |
133 | } | |
134 | ||
135 | // --- UriOpenable --- // | |
136 | @Override | |
137 | public boolean openUri(URI uri) { | |
138 | ArrayList<DocumentRange> ranges = new ArrayList<>(); | |
139 | String fragment = uri.getFragment(); | |
140 | String query = uri.getQuery(); | |
141 | ||
142 | Marker.clearMarkAllHighlights(textArea); | |
143 | ||
144 | if ((fragment != null) && (declarations.size() == 1)) { | |
145 | DeclarationData declaration = declarations.entrySet().iterator().next().getValue(); | |
146 | ||
147 | if (fragment.equals(declaration.typeName)) { | |
148 | ranges.add(new DocumentRange(declaration.startPosition, declaration.endPosition)); | |
149 | } | |
150 | } | |
151 | ||
152 | if (query != null) { | |
153 | Map<String, String> parameters = parseQuery(query); | |
154 | ||
155 | String highlightFlags = parameters.get("highlightFlags"); | |
156 | String highlightPattern = parameters.get("highlightPattern"); | |
157 | ||
158 | if ((highlightFlags != null) && (highlightPattern != null)) { | |
159 | String regexp = createRegExp(highlightPattern); | |
160 | Pattern pattern = Pattern.compile(regexp + ".*"); | |
161 | ||
162 | boolean t = (highlightFlags.indexOf('t') != -1); // Highlight types | |
163 | boolean M = (highlightFlags.indexOf('M') != -1); // Highlight modules | |
164 | ||
165 | if (highlightFlags.indexOf('d') != -1) { | |
166 | // Highlight declarations | |
167 | for (Map.Entry<String, DeclarationData> entry : declarations.entrySet()) { | |
168 | DeclarationData declaration = entry.getValue(); | |
169 | ||
170 | if (M) { | |
171 | matchAndAddDocumentRange(pattern, declaration.name, declaration.startPosition, declaration.endPosition, ranges); | |
172 | } | |
173 | } | |
174 | } | |
175 | ||
176 | if (highlightFlags.indexOf('r') != -1) { | |
177 | // Highlight references | |
178 | for (Map.Entry<Integer, HyperlinkData> entry : hyperlinks.entrySet()) { | |
179 | HyperlinkData hyperlink = entry.getValue(); | |
180 | ReferenceData reference = ((HyperlinkReferenceData)hyperlink).reference; | |
181 | ModuleInfoReferenceData moduleInfoReferenceData = (ModuleInfoReferenceData)reference; | |
182 | ||
183 | if (t && (moduleInfoReferenceData.type == TYPE)) { | |
184 | matchAndAddDocumentRange(pattern, getMostInnerTypeName(moduleInfoReferenceData.typeName), hyperlink.startPosition, hyperlink.endPosition, ranges); | |
185 | } | |
186 | if (M && (moduleInfoReferenceData.type == MODULE)) { | |
187 | matchAndAddDocumentRange(pattern, moduleInfoReferenceData.name, hyperlink.startPosition, hyperlink.endPosition, ranges); | |
188 | } | |
189 | } | |
190 | } | |
191 | } | |
192 | } | |
193 | ||
194 | if ((ranges != null) && !ranges.isEmpty()) { | |
195 | textArea.setMarkAllHighlightColor(SELECT_HIGHLIGHT_COLOR); | |
196 | Marker.markAll(textArea, ranges); | |
197 | ranges.sort(null); | |
198 | setCaretPositionAndCenter(ranges.get(0)); | |
199 | } | |
200 | ||
201 | return true; | |
202 | } | |
203 | ||
204 | // --- IndexesChangeListener --- // | |
205 | @Override | |
206 | public void indexesChanged(Collection<Future<Indexes>> collectionOfFutureIndexes) { | |
207 | // Update the list of containers | |
208 | this.collectionOfFutureIndexes = collectionOfFutureIndexes; | |
209 | // Refresh links | |
210 | boolean refresh = false; | |
211 | ||
212 | for (ReferenceData reference : references) { | |
213 | ModuleInfoReferenceData moduleInfoReferenceData = (ModuleInfoReferenceData)reference; | |
214 | boolean enabled = false; | |
215 | ||
216 | try { | |
217 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { | |
218 | if (futureIndexes.isDone()) { | |
219 | Map<String, Collection> index; | |
220 | String key; | |
221 | ||
222 | switch (moduleInfoReferenceData.type) { | |
223 | case TYPE: | |
224 | index = futureIndexes.get().getIndex("typeDeclarations"); | |
225 | key = reference.typeName; | |
226 | break; | |
227 | case PACKAGE: | |
228 | index = futureIndexes.get().getIndex("packageDeclarations"); | |
229 | key = reference.typeName; | |
230 | break; | |
231 | default: // MODULE | |
232 | index = futureIndexes.get().getIndex("javaModuleDeclarations"); | |
233 | key = reference.name; | |
234 | break; | |
235 | } | |
236 | ||
237 | if ((index != null) && (index.get(key) != null)) { | |
238 | enabled = true; | |
239 | break; | |
240 | } | |
241 | } | |
242 | } | |
243 | } catch (Exception e) { | |
244 | assert ExceptionUtil.printStackTrace(e); | |
245 | } | |
246 | ||
247 | if (reference.enabled != enabled) { | |
248 | reference.enabled = enabled; | |
249 | refresh = true; | |
250 | } | |
251 | } | |
252 | ||
253 | if (refresh) { | |
254 | textArea.repaint(); | |
255 | } | |
256 | } | |
257 | ||
258 | protected static class ModuleInfoReferenceData extends ReferenceData { | |
259 | public int type; | |
260 | ||
261 | public ModuleInfoReferenceData(int type, String typeName, String name, String descriptor, String owner) { | |
262 | super(typeName, name, descriptor, owner); | |
263 | this.type = type; | |
264 | } | |
265 | } | |
266 | ||
267 | public class ModuleInfoFilePrinter extends StringBuilderPrinter { | |
268 | protected HashMap<String, ReferenceData> referencesCache = new HashMap<>(); | |
269 | ||
64 | 270 | @Override |
65 | 271 | public void start(int maxLineNumber, int majorVersion, int minorVersion) {} |
66 | 272 | |
68 | 274 | public void end() { |
69 | 275 | setText(stringBuffer.toString()); |
70 | 276 | initLineNumbers(); |
277 | } | |
278 | ||
279 | @Override | |
280 | public void printDeclaration(int type, String internalTypeName, String name, String descriptor) { | |
281 | declarations.put(internalTypeName, new TypePage.DeclarationData(stringBuffer.length(), name.length(), internalTypeName, name, descriptor)); | |
282 | super.printDeclaration(type, internalTypeName, name, descriptor); | |
283 | } | |
284 | ||
285 | @Override | |
286 | public void printReference(int type, String internalTypeName, String name, String descriptor, String ownerInternalName) { | |
287 | String key = (type == MODULE) ? name : internalTypeName; | |
288 | ReferenceData reference = referencesCache.get(key); | |
289 | ||
290 | if (reference == null) { | |
291 | reference = new ModuleInfoReferenceData(type, internalTypeName, name, descriptor, ownerInternalName); | |
292 | referencesCache.put(key, reference); | |
293 | references.add(reference); | |
294 | } | |
295 | ||
296 | addHyperlink(new HyperlinkReferenceData(stringBuffer.length(), name.length(), reference)); | |
297 | super.printReference(type, internalTypeName, name, descriptor, ownerInternalName); | |
71 | 298 | } |
72 | 299 | } |
73 | 300 |
342 | 342 | String typeName = reference.typeName; |
343 | 343 | boolean enabled; |
344 | 344 | |
345 | if (reference.name != null) { | |
345 | if (reference.name == null) { | |
346 | enabled = false; | |
347 | ||
348 | try { | |
349 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { | |
350 | if (futureIndexes.isDone()) { | |
351 | Map<String, Collection> index = futureIndexes.get().getIndex("typeDeclarations"); | |
352 | if ((index != null) && (index.get(typeName) != null)) { | |
353 | enabled = true; | |
354 | break; | |
355 | } | |
356 | } | |
357 | } | |
358 | } catch (Exception e) { | |
359 | assert ExceptionUtil.printStackTrace(e); | |
360 | } | |
361 | } else { | |
346 | 362 | try { |
347 | 363 | // Recursive search |
348 | 364 | typeName = searchTypeHavingMember(typeName, reference.name, reference.descriptor, entry); |
358 | 374 | assert ExceptionUtil.printStackTrace(e); |
359 | 375 | enabled = false; |
360 | 376 | } |
361 | } else { | |
362 | enabled = false; | |
363 | ||
364 | try { | |
365 | for (Future<Indexes> futureIndexes : collectionOfFutureIndexes) { | |
366 | if (futureIndexes.isDone()) { | |
367 | Map<String, Collection> index = futureIndexes.get().getIndex("typeDeclarations"); | |
368 | if ((index != null) && (index.get(typeName) != null)) { | |
369 | enabled = true; | |
370 | break; | |
371 | } | |
372 | } | |
373 | } | |
374 | } catch (Exception e) { | |
375 | assert ExceptionUtil.printStackTrace(e); | |
376 | } | |
377 | 377 | } |
378 | 378 | |
379 | 379 | if (reference.enabled != enabled) { |
504 | 504 | } |
505 | 505 | } |
506 | 506 | |
507 | public static class ReferenceData { | |
507 | protected static class ReferenceData { | |
508 | 508 | public String typeName; |
509 | 509 | /** |
510 | 510 | * Field or method name or null for type |
524 | 524 | */ |
525 | 525 | public boolean enabled = false; |
526 | 526 | |
527 | ReferenceData(String typeName, String name, String descriptor, String owner) { | |
527 | public ReferenceData(String typeName, String name, String descriptor, String owner) { | |
528 | 528 | this.typeName = typeName; |
529 | 529 | this.name = name; |
530 | 530 | this.descriptor = descriptor; |
0 | 0 | # Order is important : 'GenericContainerFactoryProvider' must be the last |
1 | org.jd.gui.service.container.JmodContainerFactoryProvider | |
1 | org.jd.gui.service.container.JavaModuleContainerFactoryProvider | |
2 | 2 | org.jd.gui.service.container.EarContainerFactoryProvider |
3 | 3 | org.jd.gui.service.container.WarContainerFactoryProvider |
4 | 4 | org.jd.gui.service.container.JarContainerFactoryProvider |
2 | 2 | org.jd.gui.service.fileloader.EarFileLoaderProvider |
3 | 3 | org.jd.gui.service.fileloader.JarFileLoaderProvider |
4 | 4 | org.jd.gui.service.fileloader.JavaFileLoaderProvider |
5 | org.jd.gui.service.fileloader.JmodFileLoaderProvider | |
5 | org.jd.gui.service.fileloader.JavaModuleFileLoaderProvider | |
6 | 6 | org.jd.gui.service.fileloader.LogFileLoaderProvider |
7 | 7 | org.jd.gui.service.fileloader.WarFileLoaderProvider |
8 | 8 | org.jd.gui.service.fileloader.ZipFileLoaderProvider |
1 | 1 | org.jd.gui.service.indexer.ClassFileIndexerProvider |
2 | 2 | org.jd.gui.service.indexer.EjbJarXmlFileIndexerProvider |
3 | 3 | org.jd.gui.service.indexer.JavaFileIndexerProvider |
4 | org.jd.gui.service.indexer.JavaModuleFileIndexerProvider | |
5 | org.jd.gui.service.indexer.JavaModuleInfoFileIndexerProvider | |
4 | 6 | org.jd.gui.service.indexer.MetainfServiceFileIndexerProvider |
5 | 7 | org.jd.gui.service.indexer.TextFileIndexerProvider |
6 | 8 | org.jd.gui.service.indexer.WebXmlFileIndexerProvider |
9 | 9 | org.jd.gui.service.treenode.JarFileTreeNodeFactoryProvider |
10 | 10 | org.jd.gui.service.treenode.JavaFileTreeNodeFactoryProvider |
11 | 11 | org.jd.gui.service.treenode.JavascriptFileTreeNodeFactoryProvider |
12 | org.jd.gui.service.treenode.JmodFileTreeNodeFactoryProvider | |
13 | org.jd.gui.service.treenode.JmodPackageTreeNodeFactoryProvider | |
12 | org.jd.gui.service.treenode.JavaModuleFileTreeNodeFactoryProvider | |
13 | org.jd.gui.service.treenode.JavaModulePackageTreeNodeFactoryProvider | |
14 | 14 | org.jd.gui.service.treenode.JsonFileTreeNodeFactoryProvider |
15 | 15 | org.jd.gui.service.treenode.JspFileTreeNodeFactoryProvider |
16 | 16 | org.jd.gui.service.treenode.ManifestFileTreeNodeFactoryProvider |
Binary diff not shown
Binary diff not shown
Binary diff not shown