1 19 20 package org.netbeans.modules.j2ee.ejbfreeform; 21 22 import java.io.BufferedOutputStream ; 23 import java.io.IOException ; 24 import java.io.InputStream ; 25 import java.io.OutputStream ; 26 import java.util.Iterator ; 27 import javax.swing.JButton ; 28 import javax.xml.parsers.ParserConfigurationException ; 29 import javax.xml.parsers.SAXParser ; 30 import javax.xml.parsers.SAXParserFactory ; 31 import org.netbeans.api.java.project.JavaProjectConstants; 32 import org.netbeans.api.project.Project; 33 import org.netbeans.api.project.ProjectInformation; 34 import org.netbeans.api.project.ProjectManager; 35 import org.netbeans.api.project.ProjectUtils; 36 import org.netbeans.modules.ant.freeform.spi.support.Util; 37 import org.netbeans.spi.project.ActionProvider; 38 import org.netbeans.spi.project.AuxiliaryConfiguration; 39 import org.netbeans.spi.project.support.ant.AntProjectHelper; 40 import org.netbeans.spi.project.support.ant.EditableProperties; 41 import org.openide.DialogDisplayer; 42 import org.openide.ErrorManager; 43 import org.openide.NotifyDescriptor; 44 import org.openide.cookies.EditCookie; 45 import org.openide.cookies.LineCookie; 46 import org.openide.filesystems.FileLock; 47 import org.openide.filesystems.FileObject; 48 import org.openide.filesystems.FileUtil; 49 import org.openide.loaders.DataObject; 50 import org.openide.loaders.DataObjectNotFoundException; 51 import org.openide.text.Line; 52 import org.openide.util.NbBundle; 53 import org.openide.xml.XMLUtil; 54 import org.w3c.dom.Comment ; 55 import org.w3c.dom.Document ; 56 import org.w3c.dom.Element ; 57 import org.xml.sax.Attributes ; 58 import org.xml.sax.InputSource ; 59 import org.xml.sax.Locator ; 60 import org.xml.sax.SAXException ; 61 import org.xml.sax.helpers.DefaultHandler ; 62 63 69 public class EjbFreeFormActionProvider implements ActionProvider { 70 71 80 static final String FILE_SCRIPT_PATH = "nbproject/ide-file-targets.xml"; 82 87 static final String GENERAL_SCRIPT_PATH = "nbproject/ide-targets.xml"; 89 private static final String LOAD_PROPS_TARGET = "-load-props"; private static final String CHECK_PROPS_TARGET = "-check-props"; private static final String INIT_TARGET = "-init"; private static final String DEBUG_TARGET = "debug-nb"; private static final String DISPLAY_BROWSER = "debug-display-browser"; 95 private static final String [] DEBUG_PROPERTIES = new String [] { 96 EjbFreeformProperties.JPDA_SESSION_NAME, 97 EjbFreeformProperties.JPDA_HOST, 98 EjbFreeformProperties.JPDA_ADDRESS, 99 EjbFreeformProperties.JPDA_TRANSPORT, 100 EjbFreeformProperties.DEBUG_SOURCEPATH, 101 }; 102 103 private static final String DEBUG_PROPERTIES_TEMPLATE = "/org/netbeans/modules/j2ee/ejbfreeform/resources/debug-properties.template"; 105 private final Project project; 106 private final AntProjectHelper helper; 107 private final AuxiliaryConfiguration aux; 108 109 private static final String [] SUPPORTED_ACTIONS = { 110 ActionProvider.COMMAND_DEBUG, 111 }; 112 113 116 public EjbFreeFormActionProvider(Project aProject, AntProjectHelper aHelper, AuxiliaryConfiguration aAux) { 117 project = aProject; 118 helper = aHelper; 119 aux = aAux; 120 } 121 122 public boolean isActionEnabled(String command, org.openide.util.Lookup context) throws IllegalArgumentException { 123 boolean enabled = false; 124 if (command.equals(ActionProvider.COMMAND_DEBUG)) 125 enabled = true; 126 return enabled; 127 } 128 129 public void invokeAction(String command, org.openide.util.Lookup context) throws IllegalArgumentException { 130 try { 131 try { 132 if (command.equals(ActionProvider.COMMAND_DEBUG)) 133 handleDebug(); 134 } catch (SAXException e) { 135 throw (IOException ) new IOException (e.toString()).initCause(e); 136 } 137 } catch (IOException e) { 138 ErrorManager.getDefault().notify(e); 139 } 140 } 141 142 public String [] getSupportedActions() { 143 return SUPPORTED_ACTIONS; 144 } 145 146 private void handleDebug() throws IOException , SAXException { 147 if (!alert(NbBundle.getMessage(EjbFreeFormActionProvider.class, "ACTION_debug"), GENERAL_SCRIPT_PATH)) 149 return; 150 151 String propertiesFile = writeDebugProperties(); 153 154 Document script = readCustomScript(GENERAL_SCRIPT_PATH); 156 if (script == null) script = createCustomScript(); 158 159 writeComments(script); 161 writeTargets(script, propertiesFile); 162 163 writeCustomScript(script, GENERAL_SCRIPT_PATH); 165 166 addBinding(ActionProvider.COMMAND_DEBUG, GENERAL_SCRIPT_PATH, DEBUG_TARGET, null, null, null, null, null); 168 169 jumpToBinding(ActionProvider.COMMAND_DEBUG); 171 jumpToBuildScript(GENERAL_SCRIPT_PATH, DEBUG_TARGET); 172 openFile(propertiesFile); 173 } 174 175 181 private boolean alert(String commandDisplayName, String scriptPath) { 182 String projectDisplayName = ProjectUtils.getInformation(project).getDisplayName(); 183 String title = NbBundle.getMessage(EjbFreeFormActionProvider.class, "TITLE_generate_target_dialog", commandDisplayName, projectDisplayName); 184 String body = NbBundle.getMessage(EjbFreeFormActionProvider.class, "TEXT_generate_target_dialog", commandDisplayName, scriptPath); 185 NotifyDescriptor d = new NotifyDescriptor.Message(body, NotifyDescriptor.QUESTION_MESSAGE); 186 d.setTitle(title); 187 d.setOptionType(NotifyDescriptor.OK_CANCEL_OPTION); 188 JButton generate = new JButton (NbBundle.getMessage(EjbFreeFormActionProvider.class, "LBL_generate")); 189 generate.setDefaultCapable(true); 190 d.setOptions(new Object [] {generate, NotifyDescriptor.CANCEL_OPTION}); 191 return DialogDisplayer.getDefault().notify(d) == generate; 192 } 193 194 199 Document readCustomScript(String scriptPath) throws IOException , SAXException { 200 201 Document script = null; 202 FileObject scriptFile = helper.getProjectDirectory().getFileObject(scriptPath); 203 if (scriptFile != null) { 204 InputStream is = scriptFile.getInputStream(); 205 try { 206 script = XMLUtil.parse(new InputSource (is), false, true, null, null); 207 } finally { 208 is.close(); 209 } 210 } 211 212 return script; 213 } 214 215 219 Document createCustomScript() { 220 Document script = XMLUtil.createDocument("project", null, null, null); Element scriptRoot = script.getDocumentElement(); 223 scriptRoot.setAttribute("basedir", ".."); String projname = ProjectUtils.getInformation(project).getDisplayName(); 225 scriptRoot.setAttribute("name", NbBundle.getMessage(EjbFreeFormActionProvider.class, "LBL_generated_script_name", projname)); 226 227 copyProperties(Util.getPrimaryConfigurationData(helper), scriptRoot); 229 230 return script; 231 } 232 233 240 private void copyProperties(Element config, Element script) { 241 244 Element data = Util.getPrimaryConfigurationData(helper); 245 Element properties = Util.findElement(data, "properties", Util.NAMESPACE); if (properties != null) { 247 Iterator propertiesIt = Util.findSubElements(properties).iterator(); 248 while (propertiesIt.hasNext()) { 249 Element el = (Element ) propertiesIt.next(); 250 Element nue = script.getOwnerDocument().createElement("property"); if (el.getLocalName().equals("property")) { String name = el.getAttribute("name"); assert name != null; 254 String text = Util.findText(el); 255 assert text != null; 256 nue.setAttribute("name", name); nue.setAttribute("value", text); } else if (el.getLocalName().equals("property-file")) { String text = Util.findText(el); 260 assert text != null; 261 nue.setAttribute("file", text); } else { 263 assert false : el; 264 } 265 script.appendChild(nue); 266 } 267 } 268 } 269 270 274 private void writeComments(Document script) { 275 Comment comm4Edit = script.createComment(" " + NbBundle.getMessage(EjbFreeFormActionProvider.class, "COMMENT_edit_target") + " "); Comment comm4Info = script.createComment(" " + NbBundle.getMessage(EjbFreeFormActionProvider.class, "COMMENT_more_info_debug") + " "); 278 Element scriptRoot = script.getDocumentElement(); 279 scriptRoot.appendChild(comm4Edit); 280 scriptRoot.appendChild(comm4Info); 281 } 282 283 287 private void writeTargets(Document script, String propertiesFile) { 288 createLoadPropertiesTarget(script, propertiesFile); 289 createCheckPropertiesTarget(script); 290 createInitTarget(script); 291 createDebugTarget(script); 292 } 293 294 301 private void createLoadPropertiesTarget(Document script, String propertiesFile) { 302 Element target = script.createElement("target"); target.setAttribute("name", LOAD_PROPS_TARGET); Element property = script.createElement("property"); property.setAttribute("file", propertiesFile); target.appendChild(property); 307 script.getDocumentElement().appendChild(target); 308 } 309 310 320 private void createCheckPropertiesTarget(Document script) { 321 Element target = script.createElement("target"); target.setAttribute("name", CHECK_PROPS_TARGET); Element fail; 324 for (int i = 0; i < DEBUG_PROPERTIES.length; i++) { 325 fail = script.createElement("fail"); fail.setAttribute("unless", DEBUG_PROPERTIES[i]); target.appendChild(fail); 328 } 329 330 script.getDocumentElement().appendChild(target); 331 } 332 333 338 private void createInitTarget(Document script) { 339 Element target = script.createElement("target"); target.setAttribute("name", INIT_TARGET); target.setAttribute("depends", LOAD_PROPS_TARGET + ", " + CHECK_PROPS_TARGET); script.getDocumentElement().appendChild(target); 343 } 344 345 352 private void createDebugTarget(Document script) { 353 Element target = script.createElement("target"); 354 target.setAttribute("name", DEBUG_TARGET); target.setAttribute("depends", INIT_TARGET); target.setAttribute("if", "netbeans.home"); Element nbjpdaconnect = script.createElement("nbjpdaconnect"); nbjpdaconnect.setAttribute("name", "${" + EjbFreeformProperties.JPDA_SESSION_NAME + "}"); nbjpdaconnect.setAttribute("host", "${" + EjbFreeformProperties.JPDA_HOST + "}"); nbjpdaconnect.setAttribute("address", "${" + EjbFreeformProperties.JPDA_ADDRESS + "}"); nbjpdaconnect.setAttribute("transport", "${" + EjbFreeformProperties.JPDA_TRANSPORT + "}"); Element sourcepath = script.createElement("sourcepath"); Element path = script.createElement("path"); path.setAttribute("path", "${debug.sourcepath}"); sourcepath.appendChild(path); 366 nbjpdaconnect.appendChild(sourcepath); 367 target.appendChild(nbjpdaconnect); 368 369 script.getDocumentElement().appendChild(target); 370 } 371 372 377 void writeCustomScript(Document script, String scriptPath) throws IOException { 378 FileObject scriptFile = helper.getProjectDirectory().getFileObject(scriptPath); 379 if (scriptFile == null) { 380 scriptFile = FileUtil.createData(helper.getProjectDirectory(), scriptPath); 381 } 382 FileLock lock = scriptFile.lock(); 383 try { 384 OutputStream os = scriptFile.getOutputStream(lock); 385 try { 386 XMLUtil.write(script, os, "UTF-8"); } finally { 388 os.close(); 389 } 390 } finally { 391 lock.releaseLock(); 392 } 393 } 394 395 407 void addBinding(String command, String scriptPath, String target, String propertyName, String dir, String pattern, String format, String separator) throws IOException { 408 Element data = Util.getPrimaryConfigurationData(helper); 411 Element ideActions = Util.findElement(data, "ide-actions", Util.NAMESPACE); if (ideActions == null) { 413 return; 416 } 417 Document doc = data.getOwnerDocument(); 418 Element action = doc.createElementNS(Util.NAMESPACE, "action"); action.setAttribute("name", command); Element script = doc.createElementNS(Util.NAMESPACE, "script"); script.appendChild(doc.createTextNode(scriptPath)); 422 action.appendChild(script); 423 Element targetEl = doc.createElementNS(Util.NAMESPACE, "target"); targetEl.appendChild(doc.createTextNode(target)); 425 action.appendChild(targetEl); 426 ideActions.appendChild(action); 427 428 if (propertyName != null) { 429 Element context = doc.createElementNS(Util.NAMESPACE, "context"); Element property = doc.createElementNS(Util.NAMESPACE, "property"); property.appendChild(doc.createTextNode(propertyName)); 432 context.appendChild(property); 433 Element folder = doc.createElementNS(Util.NAMESPACE, "folder"); folder.appendChild(doc.createTextNode(dir)); 435 context.appendChild(folder); 436 if (pattern != null) { 437 Element patternEl = doc.createElementNS(Util.NAMESPACE, "pattern"); patternEl.appendChild(doc.createTextNode(pattern)); 439 context.appendChild(patternEl); 440 } 441 Element formatEl = doc.createElementNS(Util.NAMESPACE, "format"); formatEl.appendChild(doc.createTextNode(format)); 443 context.appendChild(formatEl); 444 Element arity = doc.createElementNS(Util.NAMESPACE, "arity"); if (separator != null) { 446 Element separatorEl = doc.createElementNS(Util.NAMESPACE, "separated-files"); separatorEl.appendChild(doc.createTextNode(separator)); 448 arity.appendChild(separatorEl); 449 } else { 450 arity.appendChild(doc.createElementNS(Util.NAMESPACE, "one-file-only")); } 452 context.appendChild(arity); 453 action.appendChild(context); 454 } else { 455 Element view = Util.findElement(data, "view", Util.NAMESPACE); if (view != null) { 459 Element contextMenu = Util.findElement(view, "context-menu", Util.NAMESPACE); if (contextMenu != null) { 461 Element ideAction = doc.createElementNS(Util.NAMESPACE, "ide-action"); ideAction.setAttribute("name", command); contextMenu.appendChild(ideAction); 464 } 465 } 466 } 467 468 Util.putPrimaryConfigurationData(helper, data); 469 ProjectManager.getDefault().saveProject(project); 470 } 471 472 private String writeDebugProperties() throws IOException { 473 String fileName = "debug"; String file; 475 int i = 0; 476 do { 477 file = "nbproject/" + fileName + (i != 0 ? String.valueOf(i) : "") + ".properties"; i++; 479 } while (helper.resolveFileObject(file) != null); 480 FileObject fo = FileUtil.createData(project.getProjectDirectory(), file); 481 FileLock lock = fo.lock(); 482 OutputStream out = null; 483 InputStream in = null; 484 try { 485 out = new BufferedOutputStream (fo.getOutputStream(lock)); 486 in = EjbFreeFormActionProvider.class.getResourceAsStream(DEBUG_PROPERTIES_TEMPLATE); 487 byte[] buffer = new byte[4096]; 488 int read; 489 do { 490 read = in.read(buffer); 491 out.write(buffer, 0, read); 492 } while (read == buffer.length); 493 } 494 finally { 495 if (in != null) 496 in.close(); 497 if (out != null) 498 out.close(); 499 lock.releaseLock(); 500 } 501 502 EditableProperties ep = helper.getProperties(file); 504 ProjectInformation pi = ProjectUtils.getInformation(project); 505 ep.setProperty(EjbFreeformProperties.JPDA_SESSION_NAME, pi.getName()); 506 ep.setProperty(EjbFreeformProperties.DEBUG_SOURCEPATH, findSourceFolders(JavaProjectConstants.SOURCES_TYPE_JAVA)); 507 helper.putProperties(file, ep); 508 509 return file; 510 } 511 512 516 private void jumpToBinding(String command) { 517 jumpToFile(AntProjectHelper.PROJECT_XML_PATH, command, "action", "name"); } 519 520 525 private void jumpToBuildScript(String scriptPath, String target) { 526 jumpToFile(scriptPath, target, "target", "name"); } 528 529 536 private void jumpToFile(String path, String match, String elementLocalName, String elementAttributeName) { 537 FileObject file = helper.getProjectDirectory().getFileObject(path); 538 if (file == null) { 539 return; 540 } 541 int line; 542 try { 543 line = findLine(file, match, elementLocalName, elementAttributeName); 544 } catch (Exception e) { 545 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 546 return; 547 } 548 if (line == -1) { 549 line = 0; 551 } 552 DataObject fileDO; 553 try { 554 fileDO = DataObject.find(file); 555 } catch (DataObjectNotFoundException e) { 556 throw new AssertionError (e); 557 } 558 LineCookie lines = (LineCookie) fileDO.getCookie(LineCookie.class); 559 if (lines != null) { 560 try { 561 lines.getLineSet().getCurrent(line).show(Line.SHOW_GOTO); 562 } catch (IndexOutOfBoundsException e) { 563 ErrorManager.getDefault().getInstance(EjbFreeFormActionProvider.class.getName()).log( 565 ErrorManager.WARNING, e + " [file=" + file + " match=" + match + " line=" + line + "]"); lines.getLineSet().getCurrent(0).show(Line.SHOW_GOTO); 567 } 568 } 569 } 570 571 private void openFile(String path) { 572 FileObject file = helper.getProjectDirectory().getFileObject(path); 573 if (file == null) 574 return; 575 576 DataObject fileDO; 577 try { 578 fileDO = DataObject.find(file); 579 } 580 catch (DataObjectNotFoundException e) { 581 throw new AssertionError (e); 582 } 583 584 EditCookie edit = (EditCookie)fileDO.getCookie(EditCookie.class); 585 if (edit != null) { 586 edit.edit(); 587 } 588 } 589 590 600 static final int findLine(FileObject file, final String match, final String elementLocalName, final String elementAttributeName) throws IOException , SAXException , ParserConfigurationException { 601 InputSource in = new InputSource (file.getURL().toString()); 602 SAXParserFactory factory = SAXParserFactory.newInstance(); 603 factory.setNamespaceAware(true); 604 SAXParser parser = factory.newSAXParser(); 605 final int[] line = new int[] {-1}; 606 class Handler extends DefaultHandler { 607 private Locator locator; 608 public void setDocumentLocator(Locator l) { 609 locator = l; 610 } 611 public void startElement(String uri, String localname, String qname, Attributes attr) throws SAXException { 612 if (line[0] == -1) { 613 if (localname.equals(elementLocalName) && match.equals(attr.getValue(elementAttributeName))) { line[0] = locator.getLineNumber() - 1; 615 } 616 } 617 } 618 } 619 parser.parse(in, new Handler ()); 620 return line[0]; 621 } 622 623 private String findSourceFolders(String type) { 624 StringBuffer result = new StringBuffer (); 625 Element data = Util.getPrimaryConfigurationData(helper); 626 Element foldersEl = Util.findElement(data, "folders", Util.NAMESPACE); if (foldersEl != null) { 628 for (Iterator i = Util.findSubElements(foldersEl).iterator(); i.hasNext();) { 629 Element sourceFolderEl = (Element )i.next(); 630 Element typeEl = Util.findElement(sourceFolderEl , "type", Util.NAMESPACE); if (typeEl == null || !Util.findText(typeEl).equals(type)) 632 continue; 633 Element locationEl = Util.findElement(sourceFolderEl , "location", Util.NAMESPACE); if (locationEl == null) 635 continue; 636 String location = Util.findText(locationEl); 637 if (result.length() > 0) 638 result.append(":"); result.append(location); 640 } 641 } 642 return result.toString(); 643 } 644 } 645 | Popular Tags |