1 19 package org.netbeans.modules.web.struts.editor; 20 21 import java.io.IOException ; 22 import java.text.MessageFormat ; 23 import java.util.Collections ; 24 import java.util.Hashtable ; 25 import javax.lang.model.element.TypeElement; 26 import javax.lang.model.util.Elements; 27 import javax.swing.text.BadLocationException ; 28 import javax.swing.text.JTextComponent ; 29 import org.netbeans.api.java.source.ClasspathInfo; 30 import org.netbeans.api.java.source.CompilationController; 31 import org.netbeans.api.java.source.JavaSource; 32 import org.netbeans.api.java.source.UiUtils; 33 import org.netbeans.editor.BaseDocument; 34 import org.netbeans.editor.TokenItem; 35 import org.netbeans.editor.Utilities; 36 import org.netbeans.editor.ext.ExtSyntaxSupport; 37 import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider; 39 import org.netbeans.modules.editor.NbEditorUtilities; 40 import org.netbeans.modules.j2ee.common.source.AbstractTask; 41 import org.netbeans.modules.web.api.webmodule.WebModule; 43 import org.netbeans.modules.web.struts.StrutsConfigDataObject; 44 import org.netbeans.modules.web.struts.StrutsConfigUtilities; 45 import org.openide.ErrorManager; 46 import org.openide.cookies.OpenCookie; 47 import org.openide.filesystems.FileObject; 48 import org.openide.loaders.DataObject; 49 import org.openide.loaders.DataObjectNotFoundException; 50 import org.openide.nodes.Node; 51 import org.openide.util.NbBundle; 52 import org.openide.util.RequestProcessor; 53 54 58 public class StrutsConfigHyperlinkProvider implements HyperlinkProvider { 59 60 static private boolean debug = false; 61 private static Hashtable hyperlinkTable; 62 63 private final int JAVA_CLASS = 0; 64 private final int FORM_NAME = 1; 65 private final int RESOURCE_PATH = 2; 66 67 { 68 hyperlinkTable = new Hashtable (); 69 hyperlinkTable.put("data-source#className", new Integer (JAVA_CLASS)); hyperlinkTable.put("data-source#type", new Integer (JAVA_CLASS)); hyperlinkTable.put("form-beans#type", new Integer (JAVA_CLASS)); hyperlinkTable.put("form-bean#className", new Integer (JAVA_CLASS)); hyperlinkTable.put("form-bean#type", new Integer (JAVA_CLASS)); hyperlinkTable.put("form-property#className", new Integer (JAVA_CLASS)); hyperlinkTable.put("form-property#type", new Integer (JAVA_CLASS)); hyperlinkTable.put("exception#className", new Integer (JAVA_CLASS)); hyperlinkTable.put("exception#type", new Integer (JAVA_CLASS)); hyperlinkTable.put("exception#handler", new Integer (JAVA_CLASS)); hyperlinkTable.put("exception#path", new Integer (RESOURCE_PATH)); hyperlinkTable.put("global-forwards#type", new Integer (JAVA_CLASS)); hyperlinkTable.put("forward#className", new Integer (JAVA_CLASS)); hyperlinkTable.put("forward#type", new Integer (JAVA_CLASS)); hyperlinkTable.put("forward#path", new Integer (RESOURCE_PATH)); hyperlinkTable.put("action-mappings#type", new Integer (JAVA_CLASS)); hyperlinkTable.put("action#name", new Integer (FORM_NAME)); hyperlinkTable.put("action#className", new Integer (JAVA_CLASS)); hyperlinkTable.put("action#type", new Integer (JAVA_CLASS)); hyperlinkTable.put("action#forward", new Integer (RESOURCE_PATH)); hyperlinkTable.put("action#include", new Integer (RESOURCE_PATH)); hyperlinkTable.put("action#input", new Integer (RESOURCE_PATH)); hyperlinkTable.put("action#path", new Integer (RESOURCE_PATH)); hyperlinkTable.put("controller#className", new Integer (JAVA_CLASS)); hyperlinkTable.put("controller#processorClass", new Integer (JAVA_CLASS)); hyperlinkTable.put("controller#multipartClass", new Integer (JAVA_CLASS)); hyperlinkTable.put("message-resources#className", new Integer (JAVA_CLASS)); hyperlinkTable.put("message-resources#factory", new Integer (JAVA_CLASS)); hyperlinkTable.put("plug-in#className", new Integer (JAVA_CLASS)); } 99 100 private int valueOffset; 101 private String [] eav = null; 102 103 public StrutsConfigHyperlinkProvider() { 104 } 105 106 public int[] getHyperlinkSpan(javax.swing.text.Document doc, int offset) { 107 if (debug) debug(":: getHyperlinkSpan"); 108 if (eav != null){ 109 return new int []{valueOffset, valueOffset + eav[2].length() -1}; 110 } 111 return null; 112 } 113 114 public boolean isHyperlinkPoint(javax.swing.text.Document doc, int offset) { 115 if (debug) debug(":: isHyperlinkSpan - offset: " + offset); 117 DataObject dObject = NbEditorUtilities.getDataObject(doc); 120 if (! (dObject instanceof StrutsConfigDataObject)) 121 return false; 122 123 eav = getElementAttrValue(doc, offset); 124 if (eav != null){ 125 if (hyperlinkTable.get(eav[0]+"#"+eav[1])!= null) 126 return true; 127 } 128 return false; 129 } 130 131 public void performClickAction(javax.swing.text.Document doc, int offset) { 132 if (debug) debug(":: performClickAction"); 133 if (hyperlinkTable.get(eav[0]+"#"+eav[1])!= null){ 134 int type = ((Integer )hyperlinkTable.get(eav[0]+"#"+eav[1])).intValue(); 135 switch (type){ 136 case JAVA_CLASS: findJavaClass(eav[2], doc); break; 137 case FORM_NAME: findForm(eav[2], (BaseDocument)doc);break; 138 case RESOURCE_PATH: findResourcePath(eav[2], (BaseDocument)doc);break; 139 } 140 } 141 } 142 143 static void debug(String message){ 144 System.out.println("StrutsHyperlinkProvider: " + message); } 146 150 private String [] getElementAttrValue(javax.swing.text.Document doc, int offset){ 151 String attribute = null; 152 String tag = null; 153 String value = null; 154 155 try { 156 BaseDocument bdoc = (BaseDocument) doc; 157 JTextComponent target = Utilities.getFocusedComponent(); 158 159 if (target == null || target.getDocument() != bdoc) 160 return null; 161 162 ExtSyntaxSupport sup = (ExtSyntaxSupport)bdoc.getSyntaxSupport(); 163 TokenItem token = sup.getTokenChain(offset, offset+1); 165 if (token == null || token.getTokenID().getNumericID() != StrutsEditorUtilities.XML_ATTRIBUTE_VALUE) 168 return null; 169 value = token.getImage(); 170 if (value != null){ 171 value = value.trim(); 174 valueOffset = token.getOffset(); 175 if (value.charAt(0) == '"') { 176 value = value.substring(1); 177 valueOffset ++; 178 } 179 180 if (value.length() > 0 && value.charAt(value.length()-1) == '"') value = value.substring(0, value.length()-1); 181 value = value.trim(); 182 } 184 185 while(token != null && token.getTokenID().getNumericID() != StrutsEditorUtilities.XML_ATTRIBUTE 190 && token.getTokenID().getNumericID() != StrutsEditorUtilities.XML_ELEMENT) 191 token = token.getPrevious(); 192 if (token != null && token.getTokenID().getNumericID() == StrutsEditorUtilities.XML_ATTRIBUTE){ 193 attribute = token.getImage(); 194 while(token != null && token.getTokenID().getNumericID() != StrutsEditorUtilities.XML_ELEMENT) 195 token = token.getPrevious(); 196 if (token != null && token.getTokenID().getNumericID() == StrutsEditorUtilities.XML_ELEMENT) 197 tag = token.getImage(); 198 } 199 if (attribute == null || tag == null) 200 return null; 201 tag = tag.substring(1); 202 if (debug) debug("element: " + tag ); if (debug) debug("attribute: " + attribute ); if (debug) debug("value: " + value ); return new String []{tag, attribute, value}; 206 } catch (BadLocationException e) { 207 } 208 return null; 209 } 210 211 private void findJavaClass(final String fqn, javax.swing.text.Document doc){ 212 FileObject fo = NbEditorUtilities.getFileObject(doc); 213 if (fo != null){ 214 WebModule wm = WebModule.getWebModule(fo); 215 if (wm != null){ 216 try { 217 final ClasspathInfo cpi = ClasspathInfo.create(wm.getDocumentBase()); 218 JavaSource js = JavaSource.create(cpi, Collections.EMPTY_LIST); 219 220 js.runUserActionTask(new AbstractTask<CompilationController>() { 221 222 public void run(CompilationController cc) throws Exception { 223 Elements elements = cc.getElements(); 224 TypeElement element = elements.getTypeElement(fqn.trim()); 225 if (element != null) { 226 if (!UiUtils.open(cpi, element)){ 227 String key = "goto_source_not_found"; String msg = NbBundle.getBundle(StrutsConfigHyperlinkProvider.class).getString(key); 229 org.openide.awt.StatusDisplayer.getDefault().setStatusText(MessageFormat.format(msg, new Object [] { fqn } )); 230 231 } 232 } 233 } 234 }, false); 235 } catch (IOException ex) { 236 java.util.logging.Logger.getLogger("global").log(java.util.logging.Level.SEVERE, 237 ex.getMessage(), ex); 238 }; 239 } 240 } 241 } 242 243 private void findForm(String name, BaseDocument doc){ 244 ExtSyntaxSupport sup = (ExtSyntaxSupport)doc.getSyntaxSupport(); 245 246 int offset = findDefinitionInSection(sup, "form-beans", "form-bean", "name", name); 247 if (offset > 0){ 248 JTextComponent target = Utilities.getFocusedComponent(); 249 target.setCaretPosition(offset); 250 } else { 251 String key = "goto_formbean_not_found"; String msg = NbBundle.getBundle(StrutsConfigHyperlinkProvider.class).getString(key); 253 org.openide.awt.StatusDisplayer.getDefault().setStatusText(MessageFormat.format(msg, new Object [] { name } )); 254 } 255 } 256 257 private void findResourcePath(String path, BaseDocument doc){ 258 path = path.trim(); 259 if (debug) debug("path: " + path); 260 if (path.indexOf('?') > 0){ 261 path = path.substring(0, path.indexOf('?')); 263 } 264 WebModule wm = WebModule.getWebModule(NbEditorUtilities.getFileObject(doc)); 265 if (wm != null){ 266 FileObject docBase= wm.getDocumentBase(); 267 FileObject fo = docBase.getFileObject(path); 268 if (fo == null){ 269 String servletMapping = StrutsConfigUtilities.getActionServletMapping(wm.getDeploymentDescriptor()); 271 if (servletMapping != null){ 272 String actionPath = null; 273 if (servletMapping != null && servletMapping.lastIndexOf('.')>0){ 274 String extension = servletMapping.substring(servletMapping.lastIndexOf('.')); 276 if (path.endsWith(extension)) 277 actionPath = path.substring(0, path.length()-extension.length()); 278 else 279 actionPath = path; 280 } else{ 281 servletMapping = servletMapping.trim(); 283 String prefix = servletMapping.substring(0, servletMapping.length()-2); 284 if (path.startsWith(prefix)) 285 actionPath = path.substring(prefix.length(), path.length()); 286 else 287 actionPath = path; 288 } 289 if (debug) debug(" actionPath: " + actionPath); 290 if(actionPath != null){ 291 ExtSyntaxSupport sup = (ExtSyntaxSupport)doc.getSyntaxSupport(); 292 int offset = findDefinitionInSection(sup, "action-mappings","action","path", actionPath); 293 if (offset > 0){ 294 JTextComponent target = Utilities.getFocusedComponent(); 295 target.setCaretPosition(offset); 296 } 297 } 298 } 299 } else 300 openInEditor(fo); 301 } 302 } 303 304 private int findDefinitionInSection(ExtSyntaxSupport sup, String section, String tag, String attribute, String value){ 305 TokenItem token; 306 String startSection = "<"+ section; 307 String endSection = "</" + section; 308 String element = "<" + tag; 309 String attributeValue = "\""+ value + "\""; 310 int tagOffset = 0; 311 try{ 312 token = sup.getTokenChain(0, 1); 313 while (token != null 315 && !(token.getTokenID().getNumericID() == StrutsEditorUtilities.XML_ELEMENT 316 && token.getImage().equals(startSection))){ 317 token = token.getNext(); 318 } 319 if (token.getImage().equals(startSection)){ 320 token = token.getNext(); 322 while (token != null 323 && (token.getTokenID().getNumericID() != StrutsEditorUtilities.XML_ELEMENT 324 || token.getImage().equals(">"))) 325 token = token.getNext(); 326 if(token.getImage().equals("/>") || token.getImage().equals(endSection)) 327 return -1; 329 while(token != null 330 && !(token.getTokenID().getNumericID() == StrutsEditorUtilities.XML_ELEMENT 331 && token.getImage().equals(endSection))){ 332 while (token != null 334 && (token.getTokenID().getNumericID() != StrutsEditorUtilities.XML_ELEMENT 335 || (!token.getImage().equals(endSection) 336 && !token.getImage().equals(element))) ) 337 token = token.getNext(); 338 if (token == null) return -1; 339 tagOffset = token.getOffset(); 340 if (token.getImage().equals(element)){ 341 token = token.getNext(); 343 while (token != null 344 && token.getTokenID().getNumericID() != StrutsEditorUtilities.XML_ELEMENT 345 && !(token.getTokenID().getNumericID() == StrutsEditorUtilities.XML_ATTRIBUTE 346 && token.getImage().equals(attribute))) 347 token = token.getNext(); 348 if (token == null) return -1; 349 if (token.getImage().equals(attribute)){ 350 token = token.getNext(); 352 while (token != null 353 && token.getTokenID().getNumericID() != StrutsEditorUtilities.XML_ATTRIBUTE_VALUE 354 && token.getTokenID().getNumericID() != StrutsEditorUtilities.XML_ELEMENT 355 && token.getTokenID().getNumericID() != StrutsEditorUtilities.XML_ATTRIBUTE) 356 token = token.getNext(); 357 if (token.getImage().equals(attributeValue)) 358 return tagOffset; 359 } 360 } else 361 token = token.getNext(); 362 } 363 } 364 } catch (BadLocationException e){ 365 e.printStackTrace(System.out); 366 } 367 return -1; 368 } 369 370 private void openInEditor(FileObject fObj){ 371 if (fObj != null){ 372 DataObject dobj = null; 373 try{ 374 dobj = DataObject.find(fObj); 375 } catch (DataObjectNotFoundException e){ 376 ErrorManager.getDefault().notify(e); 377 return; 378 } 379 if (dobj != null){ 380 Node.Cookie cookie = dobj.getCookie(OpenCookie.class); 381 if (cookie != null) 382 ((OpenCookie)cookie).open(); 383 } 384 } 385 } 386 } 387 | Popular Tags |