1 19 package org.netbeans.modules.xsl.transform; 20 21 import java.io.File ; 22 import java.io.IOException ; 23 import java.io.StringWriter ; 24 import java.io.OutputStream ; 25 import java.util.*; 26 import java.net.URL ; 27 import java.net.MalformedURLException ; 28 import java.net.UnknownHostException ; 29 import java.awt.Dialog ; 30 import java.awt.event.ActionListener ; 31 import java.awt.event.ActionEvent ; 32 import java.awt.event.WindowAdapter ; 33 import java.awt.event.WindowEvent ; 34 import java.beans.PropertyVetoException ; 35 36 import org.openide.cookies.SaveCookie; 37 38 import org.xml.sax.*; 39 import javax.xml.parsers.*; 40 import javax.xml.transform.*; 41 import javax.xml.transform.sax.*; 42 import javax.xml.transform.stream.*; 43 44 import org.openide.*; 45 import org.openide.awt.HtmlBrowser; 46 import org.openide.filesystems.*; 47 import org.openide.nodes.Node; 48 import org.openide.loaders.DataObject; 49 import org.openide.util.HelpCtx; 50 import org.openide.util.RequestProcessor; 51 import org.openide.util.Task; 52 import org.openide.util.actions.CookieAction; 53 54 import org.netbeans.api.xml.cookies.*; 55 56 import org.netbeans.modules.xml.core.XMLDataObject; 57 import org.netbeans.modules.xml.core.actions.CollectXMLAction; 58 import org.netbeans.modules.xml.core.actions.InputOutputReporter; 59 60 import org.netbeans.modules.xml.core.lib.GuiUtil; 61 import org.netbeans.modules.xml.core.lib.FileUtilities; 62 63 import org.netbeans.modules.xsl.XSLDataObject; 64 import org.netbeans.modules.xsl.ui.TransformPanel; 65 import org.netbeans.modules.xsl.settings.TransformHistory; 66 import org.netbeans.modules.xsl.actions.TransformAction; 67 import org.netbeans.modules.xsl.utils.TransformUtil; 68 import org.openide.loaders.DataObjectNotFoundException; 69 70 79 public class TransformPerformer { 80 81 private InputOutputReporter cookieObserver = null; 82 private Node[] nodes; 83 84 private volatile boolean stalled = false; 86 private volatile boolean active = true; 87 88 public TransformPerformer(Node[] nodes) { 89 this.nodes = nodes; 90 } 91 92 95 private void saveBeforeTransformation (DataObject dObject){ 96 if (dObject.isModified()){ 97 SaveCookie save; 98 save = (SaveCookie)dObject.getCookie(SaveCookie.class); 99 if (save != null) { 100 try { 101 save.save(); 102 } catch (IOException ex) { 103 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 104 } 105 } 106 } 107 } 108 109 113 public void perform() { 114 115 if (stalled) throw new IllegalStateException (); 116 117 try { 118 if ( nodes.length == 2 ) { 119 120 123 DataObject do1 = (DataObject) nodes[0].getCookie(DataObject.class); 124 boolean xslt1 = TransformUtil.isXSLTransformation(do1); 125 DataObject do2 = (DataObject) nodes[1].getCookie(DataObject.class); 126 boolean xslt2 = TransformUtil.isXSLTransformation(do2); 127 128 saveBeforeTransformation(do1); 130 saveBeforeTransformation(do2); 131 132 if ( Util.THIS.isLoggable() ) { 133 Util.THIS.debug("TransformAction.performAction:"); 134 Util.THIS.debug(" do1 [" + xslt1 + "] = " + do1); 135 Util.THIS.debug(" do2 [" + xslt2 + "] = " + do2); 136 } 137 138 if ( xslt1 != xslt2 ) { 139 TransformableCookie transformable; 140 DataObject xmlDO; 141 DataObject xslDO; 142 if ( xslt1 ) { 143 transformable = (TransformableCookie) nodes[1].getCookie(TransformableCookie.class); 144 xmlDO = do2; 145 xslDO = do1; 146 } else { 147 transformable = (TransformableCookie) nodes[0].getCookie(TransformableCookie.class); 148 xmlDO = do1; 149 xslDO = do2; 150 } 151 DoublePerformer performer = new DoublePerformer(transformable, xmlDO, xslDO); 152 performer.perform(); 153 } else { 154 TransformableCookie transformable1 = (TransformableCookie) nodes[0].getCookie(TransformableCookie.class); 155 SinglePerformer performer = new SinglePerformer(transformable1, do1, xslt1); 156 performer.setLastInBatch(false); 157 performer.perform(); 158 159 TransformableCookie transformable2 = (TransformableCookie) nodes[1].getCookie(TransformableCookie.class); 160 performer = new SinglePerformer(transformable2, do2, xslt2); 161 performer.perform(); 162 } 163 } else { for ( int i = 0; i < nodes.length; i++ ) { 165 DataObject dataObject = (DataObject) nodes[i].getCookie(DataObject.class); 166 saveBeforeTransformation(dataObject); 168 TransformableCookie transformable = null; 169 boolean xslt = TransformUtil.isXSLTransformation(dataObject); 170 if ( xslt == false ) { 171 transformable = (TransformableCookie) nodes[i].getCookie(TransformableCookie.class); 172 } 173 SinglePerformer performer = new SinglePerformer(transformable, dataObject, xslt); 174 performer.setLastInBatch(i == (nodes.length -1)); 175 performer.perform(); 176 } 177 } 178 } finally { 179 stalled = true; 180 } 181 } 182 183 186 public boolean isActive() { 187 return active; 188 } 189 190 193 private InputOutputReporter getCookieObserver() { 194 if ( cookieObserver == null ) { 195 String label = Util.THIS.getString("PROP_transformation_io_name"); 196 cookieObserver = new InputOutputReporter(label); 197 } 198 return cookieObserver; 199 } 200 201 202 206 private abstract class AbstractPerformer extends WindowAdapter implements ActionListener { 207 private TransformableCookie transformableCookie; 209 protected DataObject xmlDO; 211 protected Source xmlStylesheetSource; 213 protected DataObject xslDO; 215 protected FileObject baseFO; 217 protected URL baseURL; 219 private Source xmlSource; 221 private Source xslSource; 223 private FileObject resultFO; 225 226 private TransformPanel transformPanel; 227 private DialogDescriptor dialogDescriptor; 228 private Dialog dialog; 229 230 private TransformPanel.Data data; 231 private boolean last = true; 232 233 private boolean workaround31850 = true; 235 236 237 public AbstractPerformer(TransformableCookie transformable) { 238 this.transformableCookie = transformable; 239 } 240 241 242 245 public final void perform() { 246 try { 247 init(); showDialog(); } catch (IOException exc) { 250 if ( Util.THIS.isLoggable() ) Util.THIS.debug(exc); 251 252 NotifyDescriptor nd = new NotifyDescriptor.Message(exc.getLocalizedMessage(), NotifyDescriptor.WARNING_MESSAGE); 253 DialogDisplayer.getDefault().notify(nd); 254 255 if (isLastInBatch()) { 256 active = false; 257 } 258 } 259 } 260 261 protected abstract void init() throws IOException ; 262 263 protected abstract void storeData(); 264 265 private void showDialog() throws IOException { 266 String xmlStylesheetName = null; 267 if ( xmlStylesheetSource != null ) { 268 xmlStylesheetName = xmlStylesheetSource.getSystemId(); 269 } 270 transformPanel = new TransformPanel(xmlDO, xmlStylesheetName, xslDO); 271 272 dialogDescriptor = new DialogDescriptor(transformPanel, 273 Util.THIS.getString("NAME_transform_panel_title"), true, 274 DialogDescriptor.OK_CANCEL_OPTION, DialogDescriptor.OK_OPTION, 275 DialogDescriptor.BOTTOM_ALIGN, 276 new HelpCtx(TransformAction.class), null); 277 dialogDescriptor.setClosingOptions(new Object [] { DialogDescriptor.CANCEL_OPTION }); 278 dialogDescriptor.setButtonListener(this); 279 280 dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor); 281 dialog.addWindowListener(this); dialog.show(); 283 } 284 285 protected void prepareData() throws IOException , FileStateInvalidException, MalformedURLException , ParserConfigurationException, SAXException { 286 data = transformPanel.getData(); 287 288 if ( Util.THIS.isLoggable() ) { 289 Util.THIS.debug("TransformPerformer...performTransformation"); 290 Util.THIS.debug(" transformable = " + transformableCookie); 291 Util.THIS.debug(" baseFileObject = " + baseFO); 292 Util.THIS.debug(" data = " + data); 293 } 294 295 try { 296 xmlSource = TransformUtil.createSource(baseURL, data.getInput()); } catch (IOException ex) { 298 ErrorManager.getDefault().annotate(ex, Util.THIS.getString("MSG_sourceError")); 299 throw ex; 300 } 301 if ( Util.THIS.isLoggable() ) Util.THIS.debug(" xmlSource = " + xmlSource.getSystemId()); 302 303 if ( data.getXSL() != null ) { 304 try { 305 xslSource = TransformUtil.createSource(baseURL, data.getXSL()); } catch (IOException ex) { 307 ErrorManager.getDefault().annotate(ex, Util.THIS.getString("MSG_transError")); 308 throw ex; 309 } 310 } else { 311 xslSource = xmlStylesheetSource; 312 } 313 314 if ( Util.THIS.isLoggable() ) Util.THIS.debug(" xslSource = " + xslSource.getSystemId()); 315 316 if ( data.getOutput() != null ) { String fileName = data.getOutput().toString().replace('\\', '/'); 318 try { 319 resultFO = FileUtilities.createFileObject(baseFO.getParent(), fileName, data.isOverwriteOutput()); } catch (IOException ex) { 321 ErrorManager.getDefault().annotate(ex, Util.THIS.getString("MSG_resultError")); 322 throw ex; 323 } 324 325 if ( Util.THIS.isLoggable() ) Util.THIS.debug(" resultFO = " + resultFO); 326 } 327 } 328 329 protected void updateHistory(DataObject dataObject, boolean xslt) { 330 FileObject fileObject = dataObject.getPrimaryFile(); 331 TransformHistory history = (TransformHistory) fileObject.getAttribute(TransformHistory.TRANSFORM_HISTORY_ATTRIBUTE); 332 if ( history == null ) { 333 history = new TransformHistory(); 334 } 335 String outputStr=null; 336 if(data.getOutput()!=null) { 337 outputStr=data.getOutput().toString(); 338 } 339 if ( xslt ) { 340 history.addXML(data.getInput(), outputStr); 341 } else { 342 history.addXSL(data.getXSL(), outputStr); 343 } 344 history.setOverwriteOutput(data.isOverwriteOutput()); 345 history.setProcessOutput(data.getProcessOutput()); 346 347 try { 348 fileObject.setAttribute(TransformHistory.TRANSFORM_HISTORY_ATTRIBUTE, history); 349 } catch (IOException exc) { 350 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, exc); 352 } 353 } 354 355 359 private void previewOutput() throws MalformedURLException , UnknownHostException { 360 TransformServlet.prepare(transformableCookie, xmlSource, xslSource); 361 showURL(TransformServlet.getServletURL()); 362 } 363 364 367 private void fileOutput() throws IOException , FileStateInvalidException, TransformerException { 368 OutputStream outputStream = null; 369 FileLock fileLock = null; 370 try { 371 fileLock = resultFO.lock(); 372 outputStream = resultFO.getOutputStream(fileLock); 373 374 Result outputResult = new StreamResult(outputStream); 376 if ( Util.THIS.isLoggable() ) { 377 Util.THIS.debug(" resultFO = " + resultFO); 378 Util.THIS.debug(" outputResult = " + outputResult); 379 } 380 381 String xmlName = data.getInput(); 382 String xslName = data.getXSL(); 383 TransformPerformer.this.getCookieObserver().message(Util.THIS.getString("MSG_transformation_1", xmlName, xslName)); 384 TransformUtil.transform(xmlSource, transformableCookie, xslSource, outputResult, TransformPerformer.this.getCookieObserver()); 386 try { 388 DataObject dataObject = DataObject.find(resultFO); 389 dataObject.setValid(false); 390 } catch (DataObjectNotFoundException dnf) { 391 throw new IllegalStateException (); 392 } catch (PropertyVetoException pve) { 393 ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, "Cannot invalidate " + resultFO); 394 } 395 396 if ( data.getProcessOutput() == TransformHistory.APPLY_DEFAULT_ACTION ) { 397 GuiUtil.performDefaultAction(resultFO); 398 GuiUtil.performDefaultAction(resultFO); 399 } else if ( data.getProcessOutput() == TransformHistory.OPEN_IN_BROWSER ) { 400 showURL(resultFO.getURL()); 401 } 402 } catch (FileAlreadyLockedException exc) { 403 throw (FileAlreadyLockedException) ErrorManager.getDefault().annotate(exc, Util.THIS.getString("ERR_FileAlreadyLockedException_output")); 404 } finally { 405 if ( outputStream != null ) { 406 outputStream.close(); 407 } 408 if ( fileLock != null ) { 409 fileLock.releaseLock(); 410 } 411 } 412 } 413 414 private void showURL(URL url) { 415 HtmlBrowser.URLDisplayer.getDefault().showURL(url); 416 GuiUtil.setStatusText(Util.THIS.getString("MSG_opening_browser")); 417 } 418 419 420 424 public final void actionPerformed(ActionEvent e) { 425 if ( Util.THIS.isLoggable() ) { 426 Util.THIS.debug("[TransformPerformer::AbstractPerformer] actionPerformed: " + e); 427 Util.THIS.debug(" ActionEvent.getSource(): " + e.getSource()); 428 } 429 430 workaround31850 = false; 431 if ( DialogDescriptor.OK_OPTION.equals(e.getSource()) ) { 432 try { 433 prepareData(); 435 if ( ( data.getOutput() != null ) && 436 ( resultFO == null ) ) { 437 return; 438 } 439 440 dialog.dispose(); 441 storeData(); 442 async(); 443 444 } catch (Exception exc) { if ( Util.THIS.isLoggable() ) Util.THIS.debug(exc); 447 448 451 ErrorManager.getDefault().notify(ErrorManager.WARNING, exc); 452 if (isLastInBatch()) { 453 active = false; 454 } 455 } 456 } else { 457 active = false; 458 } 459 } 460 461 public void windowClosed(WindowEvent e) { 463 super.windowClosed(e); 464 if (workaround31850) { 465 active = false; 466 } 467 } 468 469 472 private void async() { 473 RequestProcessor rp = RequestProcessor.getDefault(); 474 rp.post(new Runnable () { 475 public void run() { 476 try { 477 if ( data.getOutput() == null ) { previewOutput(); } else { 480 fileOutput(); } 482 } catch (TransformerException exc) { } catch (Exception exc) { if ( Util.THIS.isLoggable() ) Util.THIS.debug(exc); 487 488 491 ErrorManager.getDefault().notify(ErrorManager.WARNING, exc); 492 } finally { 493 if (isLastInBatch()) { 494 InputOutputReporter cookieObserver = getCookieObserver(); 495 if ( cookieObserver != null ) { 496 cookieObserver.message(Util.THIS.getString("MSG_transformation_2")); 497 cookieObserver.moveToFront(true); 498 } 499 active = false; 500 } 501 } 502 } 503 }); 504 } 505 506 507 511 protected URL preferFileURL(FileObject fileObject) throws MalformedURLException , FileStateInvalidException { 512 URL fileURL = null; 513 File file = FileUtil.toFile(fileObject); 514 515 if ( file != null ) { 516 fileURL = file.toURL(); 517 } else { 518 fileURL = fileObject.getURL(); 519 } 520 return fileURL; 521 } 522 523 public final void setLastInBatch(boolean last) { 524 this.last = last; 525 } 526 527 530 public final boolean isLastInBatch() { 531 return last; 532 } 533 } 535 536 540 private class SinglePerformer extends AbstractPerformer { 541 private DataObject dataObject; 542 private boolean xslt; 543 544 public SinglePerformer(TransformableCookie transformable, DataObject dataObject, boolean xslt) { 545 super(transformable); 546 547 this.dataObject = dataObject; 548 this.xslt = xslt; 549 } 550 551 554 protected void init() throws IOException { 555 baseFO = dataObject.getPrimaryFile(); 556 baseURL = preferFileURL(baseFO); 557 558 if ( xslt ) { 559 xmlDO = null; 560 xmlStylesheetSource = null; 561 xslDO = dataObject; 562 } else { 563 xmlDO = dataObject; 564 xmlStylesheetSource = TransformUtil.getAssociatedStylesheet(baseURL); 565 xslDO = null; 566 } 567 } 568 569 protected void storeData() { 570 updateHistory(dataObject, xslt); 571 } 572 573 } 575 576 580 private class DoublePerformer extends AbstractPerformer { 581 582 public DoublePerformer(TransformableCookie transformable, DataObject xmlDO, DataObject xslDO) { 583 super(transformable); 584 585 this.xmlDO = xmlDO; 586 this.xslDO = xslDO; 587 } 588 589 592 protected void init() throws IOException { 593 baseFO = xmlDO.getPrimaryFile(); 594 baseURL = preferFileURL(baseFO); 595 } 596 597 protected void storeData() { 598 updateHistory(xmlDO, false); 599 updateHistory(xslDO, true); 600 } 601 602 603 } 605 } 606 | Popular Tags |