1 19 20 package org.netbeans.modules.web.core.jsploader; 21 import java.beans.PropertyChangeEvent ; 22 import java.beans.PropertyChangeListener ; 23 import java.io.Reader ; 24 import java.io.InputStreamReader ; 25 import java.io.OutputStream ; 26 import java.io.OutputStreamWriter ; 27 import java.io.Writer ; 28 import java.io.IOException ; 29 import java.io.InputStream ; 30 import java.io.ObjectInput ; 31 import javax.swing.Timer ; 32 import javax.swing.event.CaretListener ; 33 import javax.swing.event.CaretEvent ; 34 import javax.swing.event.DocumentListener ; 35 import javax.swing.event.ChangeListener ; 36 import javax.swing.event.DocumentEvent ; 37 import javax.swing.event.ChangeEvent ; 38 import javax.swing.text.BadLocationException ; 39 import javax.swing.text.StyledDocument ; 40 import javax.swing.text.EditorKit ; 41 import org.netbeans.modules.web.core.palette.JSPPaletteFactory; 42 import org.netbeans.modules.web.jsps.parserapi.JspParserAPI; 43 import org.netbeans.modules.web.jsps.parserapi.JspParserFactory; 44 import org.openide.ErrorManager; 45 import org.openide.filesystems.FileUtil; 46 47 import org.openide.text.DataEditorSupport; 48 import org.openide.filesystems.FileObject; 49 import org.openide.filesystems.FileLock; 50 import org.openide.loaders.MultiDataObject; 51 import org.openide.cookies.*; 52 import org.openide.text.CloneableEditor; 53 import org.openide.util.Lookup; 54 import org.openide.util.TaskListener; 55 import org.openide.util.Task; 56 import org.openide.DialogDisplayer; 57 import org.openide.NotifyDescriptor; 58 import org.openide.util.lookup.AbstractLookup; 59 import org.openide.util.lookup.InstanceContent; 60 import org.openide.util.lookup.Lookups; 61 import org.openide.util.lookup.ProxyLookup; 62 import org.openide.windows.CloneableOpenSupport; 63 import org.openide.nodes.Node; 64 import org.openide.util.NbBundle; 65 68 import org.openide.loaders.DataObject; 69 import org.netbeans.modules.web.api.webmodule.WebModule; 70 import org.netbeans.spi.palette.PaletteController; 71 72 class BaseJspEditorSupport extends DataEditorSupport implements EditCookie, EditorCookie.Observable, OpenCookie, LineCookie, CloseCookie, PrintCookie { 73 74 private static final int AUTO_PARSING_DELAY = 2000; 76 77 private Timer timer; 78 79 80 private String encoding; 81 82 85 private static String defaulEncoding = "UTF-8"; 87 public BaseJspEditorSupport(JspDataObject obj) { 88 super(obj, new BaseJspEnv(obj)); 89 DataObject data = getDataObject(); 90 if ((data!=null) && (data instanceof JspDataObject)) { 91 setMIMEType(JspLoader.getMimeType((JspDataObject)data)); 92 } 93 initialize(); 94 } 95 96 public boolean close() { 97 TagLibParseSupport sup = (TagLibParseSupport)getDataObject().getCookie(TagLibParseSupport.class); 100 if(sup != null) { 101 sup.cancelParsingTask(); 102 } 103 104 return super.close(); 105 } 106 107 private void initialize() { 108 timer = new Timer (0, new java.awt.event.ActionListener () { 110 public void actionPerformed(java.awt.event.ActionEvent e) { 111 final TagLibParseSupport sup = (TagLibParseSupport)getDataObject().getCookie(TagLibParseSupport.class); 112 if (sup != null && WebModule.getWebModule(getDataObject().getPrimaryFile())!= null) { 113 sup.autoParse().addTaskListener(new TaskListener() { 114 public void taskFinished(Task t) { 115 notifyParsingDone(sup); 116 } 117 }); 118 } 119 } 120 }); 121 timer.setInitialDelay(AUTO_PARSING_DELAY); 122 timer.setRepeats(false); 123 124 final DocumentListener docListener = new DocumentListener () { 126 public void insertUpdate(DocumentEvent e) { change(e); } 127 public void changedUpdate(DocumentEvent e) { } 128 public void removeUpdate(DocumentEvent e) { change(e); } 129 130 private void change(DocumentEvent e) { 131 restartTimer(false); 132 TagLibParseSupport sup = (TagLibParseSupport)getDataObject().getCookie(TagLibParseSupport.class); 133 if (sup != null) { 134 sup.setDocumentDirty(true); 135 } 136 } 137 }; 138 139 addChangeListener(new ChangeListener () { 141 public void stateChanged(ChangeEvent evt) { 142 if (isDocumentLoaded()) { 143 if (getDocument() != null) { 144 getDocument().addDocumentListener(docListener); 145 } 146 } 147 } 148 }); 149 150 encoding = null; 151 152 JspParserAccess 153 .getJspParserWM (getWebModule (getDataObject().getPrimaryFile())) 154 .addPropertyChangeListener( 155 new PropertyChangeListener () { 156 public void propertyChange(java.beans.PropertyChangeEvent evt) { 157 String propName = evt.getPropertyName(); 158 if (JspParserAPI.WebModule.PROP_LIBRARIES.equals(propName) 159 || JspParserAPI.WebModule.PROP_PACKAGE_ROOTS.equals(propName)) { 160 restartTimer(false); 162 } 163 } 164 }); 165 166 167 } 168 169 private WebModule getWebModule(FileObject fo){ 170 WebModule wm = WebModule.getWebModule(fo); 171 if (wm != null){ 172 FileObject wmRoot = wm.getDocumentBase(); 173 if (wmRoot != null && (fo == wmRoot || FileUtil.isParentOf(wmRoot, fo))) { 174 return wm; 175 } 176 } 177 return null; 178 } 179 180 183 private void restartTimer(boolean onlyIfRunning) { 184 if (onlyIfRunning && !timer.isRunning()){ 185 return; 186 } 187 188 189 int delay = AUTO_PARSING_DELAY; 190 if (delay > 0) { 191 timer.setInitialDelay(delay); 192 timer.restart(); 193 } 194 } 195 196 private boolean isSupportedEncoding(String encoding){ 197 boolean supported; 198 try{ 199 supported = java.nio.charset.Charset.isSupported(encoding); 200 } 201 catch (java.nio.charset.IllegalCharsetNameException e){ 202 supported = false; 203 } 204 205 return supported; 206 } 207 208 public void open(){ 209 long a = System.currentTimeMillis(); 210 encoding = getObjectEncoding(false, false); 212 if (!isSupportedEncoding(encoding)){ 213 NotifyDescriptor nd = new NotifyDescriptor.Confirmation( 214 NbBundle.getMessage (BaseJspEditorSupport.class, "MSG_BadEncodingDuringLoad", new Object [] { getDataObject().getPrimaryFile().getNameExt(), 216 encoding, 217 defaulEncoding} ), 218 NotifyDescriptor.YES_NO_OPTION, 219 NotifyDescriptor.WARNING_MESSAGE); 220 DialogDisplayer.getDefault().notify(nd); 221 if(nd.getValue() != NotifyDescriptor.YES_OPTION) return; 222 } 223 super.open(); 224 } 225 226 protected void loadFromStreamToKit(StyledDocument doc, InputStream stream, EditorKit kit) throws IOException , BadLocationException { 227 228 Reader reader = null; 229 encoding = getObjectEncoding(false, true); 231 if (!isSupportedEncoding(encoding)){ 232 encoding = defaulEncoding; 233 } 234 try { 235 reader = new InputStreamReader (stream, encoding); 236 kit.read(reader, doc, 0); 237 } 238 finally { 239 if (reader != null) 240 reader.close(); 241 } 242 } 243 244 protected void saveFromKitToStream(StyledDocument doc, EditorKit kit, OutputStream stream) throws IOException , BadLocationException { 245 Writer wr = null; 246 if (encoding == null) { 247 encoding = getObjectEncoding(false, true); } 249 try { 250 if (!isSupportedEncoding(encoding)){ 251 encoding = defaulEncoding; 252 } 253 wr = new OutputStreamWriter (stream, encoding); 254 kit.write(wr, doc, 0, doc.getLength()); 255 } 256 finally { 257 if (wr != null) 258 wr.close(); 259 } 260 } 261 262 264 protected void notifyClose() {} 265 266 268 protected void notifyParsingDone(TagLibParseSupport sup) { 269 if (sup.isDocumentDirty()) { 270 restartTimer(false); 271 } 272 } 273 274 protected boolean notifyModified() { 275 boolean notify = super.notifyModified(); 276 if (!notify) { 277 return false; 278 } 279 JspDataObject obj = (JspDataObject)getDataObject(); 280 if (obj.getCookie(SaveCookie.class) == null) { 281 obj.addSaveCookie(new SaveCookie() { 282 public void save() throws java.io.IOException { 283 saveDocument(); 284 } 285 }); 286 } 287 return true; 288 } 289 290 293 protected void notifyUnmodified() { 294 super.notifyUnmodified(); 295 JspDataObject obj = (JspDataObject)getDataObject(); 296 obj.removeSaveCookie(); 297 } 298 299 protected String getObjectEncoding(boolean useEditor) { 300 return getObjectEncoding(useEditor, false); 301 } 302 303 310 protected String getObjectEncoding(boolean useEditor, boolean useCache) { 311 return ((JspDataObject)getDataObject()).getFileEncoding(!useCache, useEditor).trim(); 312 } 313 314 317 public void saveDocument() throws IOException { 318 saveDocument(true, true); 319 } 320 321 325 protected void saveDocumentIfNecessary(boolean parse) throws IOException { 326 saveDocument(parse, false); 327 } 328 329 334 private void saveDocument(boolean parse, boolean forceSave) throws IOException { 335 if (forceSave || isModified()) { 336 encoding = getObjectEncoding(true); if (!isSupportedEncoding(encoding)){ 338 NotifyDescriptor nd = new NotifyDescriptor.Confirmation( 339 NbBundle.getMessage (BaseJspEditorSupport.class, "MSG_BadEncodingDuringSave", new Object [] { getDataObject().getPrimaryFile().getNameExt(), 341 encoding, 342 defaulEncoding} ), 343 NotifyDescriptor.YES_NO_OPTION, 344 NotifyDescriptor.WARNING_MESSAGE); 345 nd.setValue(NotifyDescriptor.NO_OPTION); 346 DialogDisplayer.getDefault().notify(nd); 347 if(nd.getValue() != NotifyDescriptor.YES_OPTION) return; 348 } 349 else { 350 try { 351 java.nio.charset.CharsetEncoder coder = java.nio.charset.Charset.forName(encoding).newEncoder(); 352 if (!coder.canEncode(getDocument().getText(0, getDocument().getLength()))){ 353 NotifyDescriptor nd = new NotifyDescriptor.Confirmation( 354 NbBundle.getMessage (BaseJspEditorSupport.class, "MSG_BadCharConversion", new Object [] { getDataObject().getPrimaryFile().getNameExt(), 356 encoding}), 357 NotifyDescriptor.YES_NO_OPTION, 358 NotifyDescriptor.WARNING_MESSAGE); 359 nd.setValue(NotifyDescriptor.NO_OPTION); 360 DialogDisplayer.getDefault().notify(nd); 361 if(nd.getValue() != NotifyDescriptor.YES_OPTION) return; 362 } 363 } 364 catch (javax.swing.text.BadLocationException e){ 365 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 366 } 367 } 368 super.saveDocument(); 369 if (parse) { 370 TagLibParseSupport sup = (TagLibParseSupport)getDataObject().getCookie(TagLibParseSupport.class); 371 if (sup != null) { 372 sup.prepare(); 373 } 374 } 375 } 376 } 377 378 381 protected CloneableEditor createCloneableEditor() { 382 return new BaseJspEditor(this); 383 } 384 385 public static class BaseJspEnv extends DataEditorSupport.Env { 386 387 private static final long serialVersionUID = -800036748848958489L; 388 389 public BaseJspEnv(JspDataObject obj) { 390 super(obj); 391 } 392 393 protected FileObject getFile() { 394 return getDataObject().getPrimaryFile(); 395 } 396 397 protected FileLock takeLock() throws IOException { 398 return ((MultiDataObject)getDataObject()).getPrimaryEntry().takeLock(); 399 } 400 401 public CloneableOpenSupport findCloneableOpenSupport() { 402 return (BaseJspEditorSupport)getDataObject().getCookie(BaseJspEditorSupport.class); 403 } 404 } 405 406 public static class BaseJspEditor extends CloneableEditor { 407 408 public static final String JSP_MIME_TYPE = "text/x-jsp"; public static final String TAG_MIME_TYPE = "text/x-tag"; 411 private TagLibParseSupport taglibParseSupport; 412 private InstanceContent instanceContent; 413 414 415 CaretListener caretListener; 416 418 public BaseJspEditor() { 419 super(); 420 } 421 422 public boolean isXmlSyntax(DataObject dataObject) { 423 424 FileObject fileObject = (dataObject != null) ? dataObject.getPrimaryFile() : null; 425 if (fileObject == null) 426 return false; 427 428 return taglibParseSupport.getCachedOpenInfo(false, false).isXmlSyntax(); 429 } 430 431 void associatePalette(BaseJspEditorSupport s) { 432 433 DataObject dataObject = s.getDataObject(); 434 String mimeType = dataObject.getPrimaryFile().getMIMEType(); 435 instanceContent.add(getActionMap()); 436 437 if (dataObject instanceof JspDataObject && 438 (mimeType.equals(JSP_MIME_TYPE) || mimeType.equals(TAG_MIME_TYPE)) && 439 !isXmlSyntax(dataObject)) 440 { 441 try { 442 PaletteController pc = JSPPaletteFactory.getPalette(); 443 instanceContent.add(pc); 444 } 445 catch (IOException ioe) { 446 ioe.printStackTrace(); 448 } 449 } 450 } 451 452 453 public BaseJspEditor(BaseJspEditorSupport s) { 454 super(s); 455 initialize(); 456 } 457 458 protected void notifyParsingDone() { 459 } 460 461 private void initialize() { 462 Node nodes[] = {((DataEditorSupport)cloneableEditorSupport()).getDataObject().getNodeDelegate()}; 463 464 instanceContent = new InstanceContent(); 466 associateLookup(new ProxyLookup(new Lookup[] { new AbstractLookup(instanceContent), nodes[0].getLookup()})); 467 468 setActivatedNodes(nodes); 469 caretListener = new CaretListener () { 470 public void caretUpdate(CaretEvent e) { 471 ((BaseJspEditorSupport)cloneableEditorSupport()).restartTimer(true); 472 } 473 }; 474 475 taglibParseSupport = (TagLibParseSupport)((BaseJspEditorSupport)cloneableEditorSupport()).getDataObject().getCookie(TagLibParseSupport.class); 476 477 } 478 479 482 protected void componentActivated() { 483 if (getEditorPane() != null){ 485 getEditorPane().addCaretListener(caretListener); 486 super.componentActivated(); 487 } 488 ((BaseJspEditorSupport)cloneableEditorSupport()).restartTimer(false); 489 490 taglibParseSupport.setEditorOpened(true); 492 associatePalette((BaseJspEditorSupport)cloneableEditorSupport()); 494 495 } 496 497 501 protected void componentDeactivated() { 502 getEditorPane().removeCaretListener(caretListener); 503 super.componentDeactivated(); 504 taglibParseSupport.setEditorOpened(false); 505 } 506 507 510 protected boolean closeLast() { 511 if (!super.closeLast()) return false; 512 ((BaseJspEditorSupport)cloneableEditorSupport()).notifyClose(); 513 return true; 514 } 515 516 519 public void readExternal(ObjectInput in) throws IOException , ClassNotFoundException { 520 super.readExternal(in); 521 initialize(); 522 associatePalette((BaseJspEditorSupport)cloneableEditorSupport()); 523 } 524 525 } 527 } 528 | Popular Tags |