mirror of
https://github.com/java-decompiler/jd-gui.git
synced 2025-01-22 12:05:44 +00:00
Improves XML page & indexer : adds hyperlinks on Spring bean declarations
This commit is contained in:
parent
347799254c
commit
5ef246ff5e
@ -10,7 +10,7 @@ import jd.gui.api.model.Container
|
||||
import jd.gui.api.model.Indexes
|
||||
import jd.gui.util.xml.AbstractXmlPathFinder
|
||||
|
||||
class EjbJarXmlFileIndexerProvider extends XmlFileIndexerProvider {
|
||||
class EjbJarXmlFileIndexerProvider extends XmlBasedFileIndexerProvider {
|
||||
|
||||
/**
|
||||
* @return local + optional external selectors
|
||||
|
@ -10,7 +10,7 @@ import jd.gui.api.model.Container
|
||||
import jd.gui.api.model.Indexes
|
||||
import jd.gui.util.xml.AbstractXmlPathFinder
|
||||
|
||||
class WebXmlFileIndexerProvider extends XmlFileIndexerProvider {
|
||||
class WebXmlFileIndexerProvider extends XmlBasedFileIndexerProvider {
|
||||
|
||||
/**
|
||||
* @return local + optional external selectors
|
||||
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2015 Emmanuel Dupuy
|
||||
* This program is made available under the terms of the GPLv3 License.
|
||||
*/
|
||||
|
||||
package jd.gui.service.indexer
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import jd.gui.api.API
|
||||
import jd.gui.api.model.Container
|
||||
import jd.gui.api.model.Indexes
|
||||
|
||||
import javax.xml.stream.XMLInputFactory
|
||||
import javax.xml.stream.XMLStreamConstants
|
||||
|
||||
class XmlBasedFileIndexerProvider extends AbstractIndexerProvider {
|
||||
XMLInputFactory factory
|
||||
|
||||
XmlBasedFileIndexerProvider() {
|
||||
factory = XMLInputFactory.newInstance()
|
||||
factory.setProperty(XMLInputFactory.SUPPORT_DTD, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return local + optional external selectors
|
||||
*/
|
||||
String[] getSelectors() { ['*:file:*.xsl', '*:file:*.xslt', '*:file:*.xsd'] + externalSelectors }
|
||||
|
||||
@CompileStatic
|
||||
void index(API api, Container.Entry entry, Indexes indexes) {
|
||||
def stringSet = new HashSet<String>()
|
||||
def reader
|
||||
|
||||
try {
|
||||
reader = factory.createXMLStreamReader(entry.inputStream)
|
||||
|
||||
stringSet.add(reader.version)
|
||||
stringSet.add(reader.encoding)
|
||||
stringSet.add(reader.characterEncodingScheme)
|
||||
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.next()) {
|
||||
case XMLStreamConstants.START_ELEMENT:
|
||||
stringSet.add(reader.localName)
|
||||
for (int i = reader.attributeCount - 1; i >= 0; i--) {
|
||||
stringSet.add(reader.getAttributeLocalName(i))
|
||||
stringSet.add(reader.getAttributeValue(i))
|
||||
}
|
||||
for (int i = reader.namespaceCount - 1; i >= 0; i--) {
|
||||
stringSet.add(reader.getNamespacePrefix(i))
|
||||
stringSet.add(reader.getNamespaceURI(i))
|
||||
}
|
||||
break
|
||||
case XMLStreamConstants.PROCESSING_INSTRUCTION:
|
||||
stringSet.add(reader.getPITarget())
|
||||
stringSet.add(reader.getPIData())
|
||||
break
|
||||
case XMLStreamConstants.START_DOCUMENT:
|
||||
stringSet.add(reader.version)
|
||||
stringSet.add(reader.encoding)
|
||||
stringSet.add(reader.characterEncodingScheme)
|
||||
break
|
||||
case XMLStreamConstants.ENTITY_REFERENCE:
|
||||
stringSet.add(reader.localName)
|
||||
stringSet.add(reader.text)
|
||||
break
|
||||
case XMLStreamConstants.ATTRIBUTE:
|
||||
stringSet.add(reader.prefix)
|
||||
stringSet.add(reader.namespaceURI)
|
||||
stringSet.add(reader.localName)
|
||||
stringSet.add(reader.text)
|
||||
break
|
||||
case XMLStreamConstants.COMMENT:
|
||||
case XMLStreamConstants.DTD:
|
||||
case XMLStreamConstants.CDATA:
|
||||
case XMLStreamConstants.CHARACTERS:
|
||||
stringSet.add(reader.text.trim())
|
||||
break
|
||||
case XMLStreamConstants.NAMESPACE:
|
||||
for (int i = reader.namespaceCount - 1; i >= 0; i--) {
|
||||
stringSet.add(reader.getNamespacePrefix(i))
|
||||
stringSet.add(reader.getNamespaceURI(i))
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
} finally {
|
||||
reader?.close()
|
||||
}
|
||||
|
||||
def stringIndex = indexes.getIndex('strings')
|
||||
|
||||
for (def string : stringSet) {
|
||||
if (string) {
|
||||
stringIndex.get(string).add(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -24,63 +24,73 @@ class XmlFileIndexerProvider extends AbstractIndexerProvider {
|
||||
/**
|
||||
* @return local + optional external selectors
|
||||
*/
|
||||
String[] getSelectors() { ['*:file:*.xml', '*:file:*.xsl', '*:file:*.xslt', '*:file:*.xsd'] + externalSelectors }
|
||||
String[] getSelectors() { ['*:file:*.xml'] + externalSelectors }
|
||||
|
||||
@CompileStatic
|
||||
void index(API api, Container.Entry entry, Indexes indexes) {
|
||||
def index = indexes.getIndex('strings')
|
||||
def set = new HashSet<String>()
|
||||
def stringSet = new HashSet<String>()
|
||||
def typeReferenceSet = new HashSet<String>()
|
||||
def reader
|
||||
|
||||
try {
|
||||
reader = factory.createXMLStreamReader(entry.inputStream)
|
||||
|
||||
set.add(reader.version)
|
||||
set.add(reader.encoding)
|
||||
set.add(reader.characterEncodingScheme)
|
||||
stringSet.add(reader.version)
|
||||
stringSet.add(reader.encoding)
|
||||
stringSet.add(reader.characterEncodingScheme)
|
||||
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.next()) {
|
||||
case XMLStreamConstants.START_ELEMENT:
|
||||
set.add(reader.localName)
|
||||
boolean beanFlag = reader.localName.equals('bean')
|
||||
|
||||
stringSet.add(reader.localName)
|
||||
for (int i = reader.attributeCount - 1; i >= 0; i--) {
|
||||
set.add(reader.getAttributeLocalName(i))
|
||||
set.add(reader.getAttributeValue(i))
|
||||
def attributeName = reader.getAttributeLocalName(i)
|
||||
|
||||
stringSet.add(attributeName)
|
||||
|
||||
if (beanFlag && attributeName.equals('class')) {
|
||||
// String bean reference
|
||||
typeReferenceSet.add(reader.getAttributeValue(i).replace('.', '/'))
|
||||
} else {
|
||||
stringSet.add(reader.getAttributeValue(i))
|
||||
}
|
||||
}
|
||||
for (int i = reader.namespaceCount - 1; i >= 0; i--) {
|
||||
set.add(reader.getNamespacePrefix(i))
|
||||
set.add(reader.getNamespaceURI(i))
|
||||
stringSet.add(reader.getNamespacePrefix(i))
|
||||
stringSet.add(reader.getNamespaceURI(i))
|
||||
}
|
||||
break
|
||||
case XMLStreamConstants.PROCESSING_INSTRUCTION:
|
||||
set.add(reader.getPITarget())
|
||||
set.add(reader.getPIData())
|
||||
stringSet.add(reader.getPITarget())
|
||||
stringSet.add(reader.getPIData())
|
||||
break
|
||||
case XMLStreamConstants.START_DOCUMENT:
|
||||
set.add(reader.version)
|
||||
set.add(reader.encoding)
|
||||
set.add(reader.characterEncodingScheme)
|
||||
stringSet.add(reader.version)
|
||||
stringSet.add(reader.encoding)
|
||||
stringSet.add(reader.characterEncodingScheme)
|
||||
break
|
||||
case XMLStreamConstants.ENTITY_REFERENCE:
|
||||
set.add(reader.localName)
|
||||
set.add(reader.text)
|
||||
stringSet.add(reader.localName)
|
||||
stringSet.add(reader.text)
|
||||
break
|
||||
case XMLStreamConstants.ATTRIBUTE:
|
||||
set.add(reader.prefix)
|
||||
set.add(reader.namespaceURI)
|
||||
set.add(reader.localName)
|
||||
set.add(reader.text)
|
||||
stringSet.add(reader.prefix)
|
||||
stringSet.add(reader.namespaceURI)
|
||||
stringSet.add(reader.localName)
|
||||
stringSet.add(reader.text)
|
||||
break
|
||||
case XMLStreamConstants.COMMENT:
|
||||
case XMLStreamConstants.DTD:
|
||||
case XMLStreamConstants.CDATA:
|
||||
case XMLStreamConstants.CHARACTERS:
|
||||
set.add(reader.text.trim())
|
||||
stringSet.add(reader.text.trim())
|
||||
break
|
||||
case XMLStreamConstants.NAMESPACE:
|
||||
for (int i = reader.namespaceCount - 1; i >= 0; i--) {
|
||||
set.add(reader.getNamespacePrefix(i))
|
||||
set.add(reader.getNamespaceURI(i))
|
||||
stringSet.add(reader.getNamespacePrefix(i))
|
||||
stringSet.add(reader.getNamespaceURI(i))
|
||||
}
|
||||
break
|
||||
}
|
||||
@ -90,9 +100,18 @@ class XmlFileIndexerProvider extends AbstractIndexerProvider {
|
||||
reader?.close()
|
||||
}
|
||||
|
||||
for (def string : set) {
|
||||
def stringIndex = indexes.getIndex('strings')
|
||||
def typeReferenceIndex = indexes.getIndex('typeReferences')
|
||||
|
||||
for (def string : stringSet) {
|
||||
if (string) {
|
||||
index.get(string).add(entry)
|
||||
stringIndex.get(string).add(entry)
|
||||
}
|
||||
}
|
||||
|
||||
for (def ref : typeReferenceSet) {
|
||||
if (ref) {
|
||||
typeReferenceIndex.get(ref).add(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2015 Emmanuel Dupuy
|
||||
* This program is made available under the terms of the GPLv3 License.
|
||||
*/
|
||||
|
||||
package jd.gui.service.treenode
|
||||
|
||||
import jd.gui.api.API
|
||||
import jd.gui.api.feature.UriGettable
|
||||
import jd.gui.api.model.Container
|
||||
import jd.gui.view.data.TreeNodeBean
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants
|
||||
|
||||
import javax.swing.*
|
||||
import javax.swing.tree.DefaultMutableTreeNode
|
||||
|
||||
class XmlBasedFileTreeNodeFactoryProvider extends TextFileTreeNodeFactoryProvider {
|
||||
static final ImageIcon ICON = new ImageIcon(XmlBasedFileTreeNodeFactoryProvider.class.classLoader.getResource('images/xml_obj.gif'))
|
||||
|
||||
/**
|
||||
* @return local + optional external selectors
|
||||
*/
|
||||
String[] getSelectors() { ['*:file:*.xsl', '*:file:*.xslt', '*:file:*.xsd', '*:file:*.tld', '*:file:*.wsdl'] + externalSelectors }
|
||||
|
||||
public <T extends DefaultMutableTreeNode & UriGettable> T make(API api, Container.Entry entry) {
|
||||
int lastSlashIndex = entry.path.lastIndexOf('/')
|
||||
def name = entry.path.substring(lastSlashIndex+1)
|
||||
return new TreeNode(entry, new TreeNodeBean(label:name, icon:ICON, tip:"Location: $entry.uri.path"))
|
||||
}
|
||||
|
||||
static class TreeNode extends TextFileTreeNodeFactoryProvider.TreeNode {
|
||||
TreeNode(Container.Entry entry, Object userObject) {
|
||||
super(entry, userObject)
|
||||
}
|
||||
|
||||
public <T extends JComponent & UriGettable> T createPage(API api) {
|
||||
return new TextFileTreeNodeFactoryProvider.Page(entry) {
|
||||
String getSyntaxStyle() {
|
||||
SyntaxConstants.SYNTAX_STYLE_XML
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -8,8 +8,8 @@ package jd.gui.service.treenode
|
||||
import jd.gui.api.API
|
||||
import jd.gui.api.feature.UriGettable
|
||||
import jd.gui.api.model.Container
|
||||
import jd.gui.view.component.XmlFilePage
|
||||
import jd.gui.view.data.TreeNodeBean
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants
|
||||
|
||||
import javax.swing.*
|
||||
import javax.swing.tree.DefaultMutableTreeNode
|
||||
@ -20,7 +20,7 @@ class XmlFileTreeNodeFactoryProvider extends TextFileTreeNodeFactoryProvider {
|
||||
/**
|
||||
* @return local + optional external selectors
|
||||
*/
|
||||
String[] getSelectors() { ['*:file:*.xml', '*:file:*.xsl', '*:file:*.xslt', '*:file:*.xsd', '*:file:*.tld', '*:file:*.wsdl'] + externalSelectors }
|
||||
String[] getSelectors() { ['*:file:*.xml'] + externalSelectors }
|
||||
|
||||
public <T extends DefaultMutableTreeNode & UriGettable> T make(API api, Container.Entry entry) {
|
||||
int lastSlashIndex = entry.path.lastIndexOf('/')
|
||||
@ -34,11 +34,7 @@ class XmlFileTreeNodeFactoryProvider extends TextFileTreeNodeFactoryProvider {
|
||||
}
|
||||
|
||||
public <T extends JComponent & UriGettable> T createPage(API api) {
|
||||
return new TextFileTreeNodeFactoryProvider.Page(entry) {
|
||||
String getSyntaxStyle() {
|
||||
SyntaxConstants.SYNTAX_STYLE_XML
|
||||
}
|
||||
}
|
||||
return new XmlFilePage(api, entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2015 Emmanuel Dupuy
|
||||
* This program is made available under the terms of the GPLv3 License.
|
||||
*/
|
||||
|
||||
package jd.gui.view.component
|
||||
|
||||
import jd.gui.api.API
|
||||
import jd.gui.api.feature.IndexesChangeListener
|
||||
import jd.gui.api.feature.UriGettable
|
||||
import jd.gui.api.model.Container
|
||||
import jd.gui.api.model.Indexes
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants
|
||||
|
||||
import java.awt.*
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class XmlFilePage extends TypeReferencePage implements UriGettable, IndexesChangeListener {
|
||||
protected API api
|
||||
protected Container.Entry entry
|
||||
protected Collection<Indexes> collectionOfIndexes
|
||||
|
||||
XmlFilePage(API api, Container.Entry entry) {
|
||||
this.api = api
|
||||
this.entry = entry
|
||||
// Load content file
|
||||
def text = entry.inputStream.text
|
||||
// Create hyperlinks
|
||||
def pattern = Pattern.compile('(?s)<\\s*bean[^<]+class\\s*=\\s*"([^"]*)"')
|
||||
def matcher = text =~ pattern
|
||||
|
||||
while (matcher.find()) {
|
||||
// Spring type reference found
|
||||
def value = matcher.group(1)
|
||||
def trim = value.trim()
|
||||
|
||||
if (trim) {
|
||||
int startIndex = matcher.start(1) - 1
|
||||
int endIndex = startIndex + value.length() + 2
|
||||
def internalTypeName = trim.replace('.', '/')
|
||||
addHyperlink(new TypeReferencePage.TypeHyperlinkData(startIndex, endIndex, internalTypeName))
|
||||
}
|
||||
}
|
||||
// Display
|
||||
setText(text)
|
||||
// Show hyperlinks
|
||||
indexesChanged(api.collectionOfIndexes)
|
||||
}
|
||||
|
||||
String getSyntaxStyle() { SyntaxConstants.SYNTAX_STYLE_XML }
|
||||
|
||||
protected boolean isHyperlinkEnabled(HyperlinkPage.HyperlinkData hyperlinkData) { hyperlinkData.enabled }
|
||||
|
||||
protected void openHyperlink(int x, int y, HyperlinkPage.HyperlinkData hyperlinkData) {
|
||||
if (hyperlinkData.enabled) {
|
||||
// Save current position in history
|
||||
def location = textArea.getLocationOnScreen()
|
||||
int offset = textArea.viewToModel(new Point(x-location.x as int, y-location.y as int))
|
||||
def uri = entry.uri
|
||||
api.addURI(new URI(uri.scheme, uri.authority, uri.path, 'position=' + offset, null))
|
||||
|
||||
// Open link
|
||||
def internalTypeName = hyperlinkData.internalTypeName
|
||||
def entries = collectionOfIndexes?.collect { it.getIndex('typeDeclarations')?.get(internalTypeName) }.flatten().grep { it!=null }
|
||||
def rootUri = entry.container.root.uri.toString()
|
||||
def sameContainerEntries = entries?.grep { it.uri.toString().startsWith(rootUri) }
|
||||
|
||||
if (sameContainerEntries) {
|
||||
api.openURI(x, y, sameContainerEntries, null, hyperlinkData.internalTypeName)
|
||||
} else if (entries) {
|
||||
api.openURI(x, y, entries, null, hyperlinkData.internalTypeName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- UriGettable --- //
|
||||
URI getUri() { entry.uri }
|
||||
|
||||
// --- ContentSavable --- //
|
||||
String getFileName() {
|
||||
def path = entry.path
|
||||
int index = path.lastIndexOf('/')
|
||||
return path.substring(index+1)
|
||||
}
|
||||
|
||||
// --- IndexesChangeListener --- //
|
||||
void indexesChanged(Collection<Indexes> collectionOfIndexes) {
|
||||
// Update the list of containers
|
||||
this.collectionOfIndexes = collectionOfIndexes
|
||||
// Refresh links
|
||||
boolean refresh = false
|
||||
|
||||
for (def entry : hyperlinks.entrySet()) {
|
||||
def data = entry.value
|
||||
def internalTypeName = data.internalTypeName
|
||||
boolean enabled = collectionOfIndexes.find { it.getIndex('typeDeclarations')?.get(internalTypeName) } != null
|
||||
|
||||
if (data.enabled != enabled) {
|
||||
data.enabled = enabled
|
||||
refresh = true
|
||||
}
|
||||
}
|
||||
|
||||
if (refresh) {
|
||||
textArea.repaint()
|
||||
}
|
||||
}
|
||||
}
|
@ -6,4 +6,5 @@ jd.gui.service.indexer.MetainfServiceFileIndexerProvider
|
||||
jd.gui.service.indexer.TextFileIndexerProvider
|
||||
jd.gui.service.indexer.WebXmlFileIndexerProvider
|
||||
jd.gui.service.indexer.ZipFileIndexerProvider
|
||||
jd.gui.service.indexer.XmlBasedFileIndexerProvider
|
||||
jd.gui.service.indexer.XmlFileIndexerProvider
|
||||
|
@ -23,5 +23,6 @@ jd.gui.service.treenode.WarPackageTreeNodeFactoryProvider
|
||||
jd.gui.service.treenode.WebinfClassesDirectoryTreeNodeFactoryProvider
|
||||
jd.gui.service.treenode.WebinfLibDirectoryTreeNodeFactoryProvider
|
||||
jd.gui.service.treenode.WebXmlFileTreeNodeFactoryProvider
|
||||
jd.gui.service.treenode.XmlBasedFileTreeNodeFactoryProvider
|
||||
jd.gui.service.treenode.XmlFileTreeNodeFactoryProvider
|
||||
jd.gui.service.treenode.ZipFileTreeNodeFactoryProvider
|
||||
|
Loading…
x
Reference in New Issue
Block a user