1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
|
package org.eclipse.jst.jsp.ui.internal.hyperlink;
import java.io.File;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.URLHyperlink;
import org.eclipse.jst.jsp.core.internal.provisional.JSP11Namespace;
import org.eclipse.jst.jsp.core.taglib.ITLDRecord;
import org.eclipse.jst.jsp.core.taglib.ITaglibRecord;
import org.eclipse.jst.jsp.core.taglib.TaglibIndex;
import org.eclipse.jst.jsp.core.text.IJSPPartitions;
import org.eclipse.jst.jsp.ui.internal.Logger;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredPartitioning;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.utils.StringUtils;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* Detects hyperlinks for taglibs.
*/
public class TaglibHyperlinkDetector implements IHyperlinkDetector {
private final String HTTP_PROTOCOL = "http://";//$NON-NLS-1$
public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
IHyperlink hyperlink = null;
if (textViewer != null && region != null) {
IDocument doc = textViewer.getDocument();
if (doc != null) {
try {
// check if jsp tag/directive first
ITypedRegion partition = TextUtilities.getPartition(doc, IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING, region.getOffset(), false);
if (partition != null && partition.getType() == IJSPPartitions.JSP_DIRECTIVE) {
// check if jsp taglib directive
Node currentNode = getCurrentNode(doc, region.getOffset());
if (currentNode != null && currentNode.getNodeType() == Node.ELEMENT_NODE && JSP11Namespace.ElementName.DIRECTIVE_TAGLIB.equalsIgnoreCase(currentNode.getNodeName())) {
// get the uri attribute
Attr taglibNode = ((Element) currentNode).getAttributeNode(JSP11Namespace.ATTR_NAME_URI);
ITaglibRecord reference = TaglibIndex.resolve(getBaseLocationForTaglib(doc), taglibNode.getValue(), false);
if (reference != null) {
// handle taglibs
switch (reference.getRecordType()) {
case (ITaglibRecord.TLD) : {
ITLDRecord record = (ITLDRecord) reference;
String uriString = record.getPath().toString();
IRegion hyperlinkRegion = getHyperlinkRegion(taglibNode);
hyperlink = createHyperlink(uriString, hyperlinkRegion, doc, taglibNode);
}
break;
case (ITaglibRecord.JAR) :
case (ITaglibRecord.URL) : {
IRegion hyperlinkRegion = getHyperlinkRegion(taglibNode);
hyperlink = new TaglibJarUriHyperlink(hyperlinkRegion, reference);
}
}
}
}
}
}
catch (BadLocationException e) {
Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e);
}
}
}
if (hyperlink != null)
return new IHyperlink[]{hyperlink};
return null;
}
/**
* Get the base location from the current model (if within workspace,
* location is relative to workspace, otherwise, file system path)
*/
private String getBaseLocationForTaglib(IDocument document) {
String baseLoc = null;
// get the base location from the current model
IStructuredModel sModel = null;
try {
sModel = StructuredModelManager.getModelManager().getExistingModelForRead(document);
if (sModel != null) {
baseLoc = sModel.getBaseLocation();
}
}
finally {
if (sModel != null) {
sModel.releaseFromRead();
}
}
return baseLoc;
}
// the below methods were copied from URIHyperlinkDetector
private IRegion getHyperlinkRegion(Node node) {
IRegion hyperRegion = null;
if (node != null) {
short nodeType = node.getNodeType();
if (nodeType == Node.DOCUMENT_TYPE_NODE) {
// handle doc type node
IDOMNode docNode = (IDOMNode) node;
hyperRegion = new Region(docNode.getStartOffset(), docNode.getEndOffset() - docNode.getStartOffset());
}
else if (nodeType == Node.ATTRIBUTE_NODE) {
// handle attribute nodes
IDOMAttr att = (IDOMAttr) node;
// do not include quotes in attribute value region
int regOffset = att.getValueRegionStartOffset();
ITextRegion valueRegion = att.getValueRegion();
if (valueRegion != null) {
int regLength = valueRegion.getTextLength();
String attValue = att.getValueRegionText();
if (StringUtils.isQuoted(attValue)) {
++regOffset;
regLength = regLength - 2;
}
hyperRegion = new Region(regOffset, regLength);
}
}
}
return hyperRegion;
}
/**
* Returns an IFile from the given uri.
*
* @param fileString
* workspace-relative path to an existing file in the workspace
* @return returns existing IFile
*/
private IFile getFile(String fileString) {
/*
* Note at this point, fileString is already guaranteed to be pointing
* to an existing file in the workspace, so we can just call getFile.
*/
return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(fileString));
}
/**
* Create the appropriate hyperlink
*
* @param uriString
* @param hyperlinkRegion
* @return IHyperlink
*/
private IHyperlink createHyperlink(String uriString, IRegion hyperlinkRegion, IDocument document, Node node) {
IHyperlink link = null;
if (uriString != null) {
String temp = uriString.toLowerCase();
if (temp.startsWith(HTTP_PROTOCOL)) {
// this is a URLHyperlink since this is a web address
link = new URLHyperlink(hyperlinkRegion, uriString);
}
// try to locate the file in the workspace
IFile file = getFile(uriString);
if (file != null) {
// this is a WorkspaceFileHyperlink since file exists in
// workspace
link = new WorkspaceFileHyperlink(hyperlinkRegion, file);
}
else {
// this is an ExternalFileHyperlink since file does not exist
// in workspace
File externalFile = new File(uriString);
link = new ExternalFileHyperlink(hyperlinkRegion, externalFile);
}
}
return link;
}
/**
* Returns the node the cursor is currently on in the document. null if no
* node is selected
*
* @param offset
* @return Node either element, doctype, text, or null
*/
private Node getCurrentNode(IDocument document, int offset) {
// get the current node at the offset (returns either: element,
// doctype, text)
IndexedRegion inode = null;
IStructuredModel sModel = null;
try {
sModel = StructuredModelManager.getModelManager().getExistingModelForRead(document);
inode = sModel.getIndexedRegion(offset);
if (inode == null)
inode = sModel.getIndexedRegion(offset - 1);
}
finally {
if (sModel != null)
sModel.releaseFromRead();
}
if (inode instanceof Node) {
return (Node) inode;
}
return null;
}
}
|