001 /** 002 * ======================================== 003 * JFreeReport : a free Java report library 004 * ======================================== 005 * 006 * Project Info: http://reporting.pentaho.org/ 007 * 008 * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors. 009 * 010 * This library is free software; you can redistribute it and/or modify it under the terms 011 * of the GNU Lesser General Public License as published by the Free Software Foundation; 012 * either version 2.1 of the License, or (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 015 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 016 * See the GNU Lesser General Public License for more details. 017 * 018 * You should have received a copy of the GNU Lesser General Public License along with this 019 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, 020 * Boston, MA 02111-1307, USA. 021 * 022 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 023 * in the United States and other countries.] 024 * 025 * ------------ 026 * $Id: HtmlZipExportDialog.java 3525 2007-10-16 11:43:48Z tmorgner $ 027 * ------------ 028 * (C) Copyright 2000-2005, by Object Refinery Limited. 029 * (C) Copyright 2005-2007, by Pentaho Corporation. 030 */ 031 032 package org.jfree.report.modules.gui.swing.html; 033 034 import java.awt.BorderLayout; 035 import java.awt.Dialog; 036 import java.awt.Frame; 037 import java.awt.GridBagConstraints; 038 import java.awt.GridBagLayout; 039 import java.awt.GridLayout; 040 import java.awt.Insets; 041 import java.awt.event.ActionEvent; 042 import java.awt.event.KeyEvent; 043 import java.io.File; 044 import java.text.MessageFormat; 045 import java.util.ResourceBundle; 046 import javax.swing.AbstractAction; 047 import javax.swing.Action; 048 import javax.swing.ButtonGroup; 049 import javax.swing.JButton; 050 import javax.swing.JComponent; 051 import javax.swing.JFileChooser; 052 import javax.swing.JLabel; 053 import javax.swing.JOptionPane; 054 import javax.swing.JPanel; 055 import javax.swing.JRadioButton; 056 import javax.swing.JTextField; 057 import javax.swing.KeyStroke; 058 059 import org.jfree.base.config.ModifiableConfiguration; 060 import org.jfree.io.IOUtils; 061 import org.jfree.report.flow.ReportJob; 062 import org.jfree.report.modules.gui.common.DefaultIconTheme; 063 import org.jfree.report.modules.gui.common.GuiContext; 064 import org.jfree.report.modules.gui.swing.common.AbstractExportDialog; 065 import org.jfree.report.modules.gui.swing.common.JStatusBar; 066 import org.jfree.report.modules.gui.swing.common.localization.JLabelLocaleUpdateHandler; 067 import org.jfree.ui.FilesystemFilter; 068 import org.jfree.ui.action.ActionButton; 069 import org.jfree.util.Configuration; 070 import org.jfree.util.DefaultConfiguration; 071 import org.jfree.util.StringUtils; 072 073 /** 074 * A dialog that is used to perform the printing of a report into an HTML file. 075 */ 076 public class HtmlZipExportDialog extends AbstractExportDialog 077 { 078 private static final String ZIP_FILE_EXTENSION = ".zip"; 079 080 /** 081 * An action to select the export target file. 082 */ 083 private class ActionSelectTargetFile extends AbstractAction 084 { 085 /** 086 * Default constructor. 087 */ 088 private ActionSelectTargetFile (final ResourceBundle resources) 089 { 090 putValue(Action.NAME, resources.getString("htmlexportdialog.select")); 091 } 092 093 /** 094 * Receives notification that the action has occurred. 095 * 096 * @param e the action event. 097 */ 098 public void actionPerformed (final ActionEvent e) 099 { 100 performSelectFile(); 101 } 102 103 } 104 105 private JTextField filenameField; 106 private JFileChooser fileChooserHtml; 107 private JTextField dataDirField; 108 private JStatusBar statusBar; 109 private JRadioButton rbPageableExport; 110 private JRadioButton rbStreamExport; 111 private JRadioButton rbFlowExport; 112 113 114 /** 115 * Creates a non-modal dialog without a title and without a specified 116 * <code>Frame</code> owner. A shared, hidden frame will be set as the owner 117 * of the dialog. 118 */ 119 public HtmlZipExportDialog() 120 { 121 initializeComponents(); 122 } 123 124 /** 125 * Creates a non-modal dialog without a title with the specified 126 * <code>Frame</code> as its owner. If <code>owner</code> is 127 * <code>null</code>, a shared, hidden frame will be set as the owner of the 128 * dialog. 129 * 130 * @param owner the <code>Frame</code> from which the dialog is displayed 131 */ 132 public HtmlZipExportDialog(final Frame owner) 133 { 134 super(owner); 135 initializeComponents(); 136 } 137 138 /** 139 * Creates a non-modal dialog without a title with the specified 140 * <code>Dialog</code> as its owner. 141 * 142 * @param owner the non-null <code>Dialog</code> from which the dialog is 143 * displayed 144 */ 145 public HtmlZipExportDialog(final Dialog owner) 146 { 147 super(owner); 148 initializeComponents(); 149 } 150 151 public String getFilename() 152 { 153 return filenameField.getText(); 154 } 155 156 public void setFilename(final String filename) 157 { 158 this.filenameField.setText(filename); 159 } 160 161 private void initializeComponents () 162 { 163 final JPanel contentPane = new JPanel(); 164 contentPane.setLayout(new GridBagLayout()); 165 166 filenameField = new JTextField(); 167 dataDirField = new JTextField(); 168 statusBar = new JStatusBar(new DefaultIconTheme()); 169 170 final JLabel targetLabel = new JLabel(); 171 addPropertyChangeListener(new JLabelLocaleUpdateHandler(targetLabel, 172 SwingHtmlModule.BUNDLE_NAME, "htmlexportdialog.filename")); 173 174 final JLabel dataLabel = new JLabel(); 175 addPropertyChangeListener(new JLabelLocaleUpdateHandler(dataLabel, 176 SwingHtmlModule.BUNDLE_NAME, "htmlexportdialog.datafilename")); 177 178 final JLabel exportMethodLabel = 179 new JLabel(getResources().getString("htmlexportdialog.exportMethod")); 180 addPropertyChangeListener("locale", new JLabelLocaleUpdateHandler(exportMethodLabel, 181 SwingHtmlModule.BUNDLE_NAME, "htmlexportdialog.exportMethod")); 182 183 184 rbStreamExport = new JRadioButton(getResources().getString 185 ("htmlexportdialog.stream-export")); 186 rbStreamExport.setSelected(true); 187 rbFlowExport = new JRadioButton(getResources().getString 188 ("htmlexportdialog.flow-export")); 189 rbPageableExport = new JRadioButton(getResources().getString 190 ("htmlexportdialog.pageable-export")); 191 192 final ButtonGroup bgExport = new ButtonGroup(); 193 bgExport.add(rbStreamExport); 194 bgExport.add(rbFlowExport); 195 bgExport.add(rbPageableExport); 196 197 final JPanel exportTypeSelectionPanel = new JPanel(); 198 exportTypeSelectionPanel.setLayout(new GridLayout(3, 1, 5, 5)); 199 exportTypeSelectionPanel.add(rbStreamExport); 200 exportTypeSelectionPanel.add(rbFlowExport); 201 exportTypeSelectionPanel.add(rbPageableExport); 202 203 GridBagConstraints gbc = new GridBagConstraints(); 204 gbc.fill = GridBagConstraints.NONE; 205 gbc.anchor = GridBagConstraints.WEST; 206 gbc.gridx = 0; 207 gbc.gridy = 0; 208 gbc.insets = new Insets(1, 1, 1, 5); 209 contentPane.add(targetLabel, gbc); 210 211 gbc = new GridBagConstraints(); 212 gbc.fill = GridBagConstraints.NONE; 213 gbc.anchor = GridBagConstraints.WEST; 214 gbc.gridx = 0; 215 gbc.gridy = 1; 216 gbc.insets = new Insets(1, 1, 1, 5); 217 contentPane.add(dataLabel, gbc); 218 219 gbc = new GridBagConstraints(); 220 gbc.anchor = GridBagConstraints.WEST; 221 gbc.fill = GridBagConstraints.HORIZONTAL; 222 gbc.gridx = 1; 223 gbc.gridy = 0; 224 gbc.gridwidth = 1; 225 gbc.weightx = 1; 226 gbc.insets = new Insets(1, 1, 1, 1); 227 contentPane.add(filenameField, gbc); 228 229 gbc = new GridBagConstraints(); 230 gbc.anchor = GridBagConstraints.WEST; 231 gbc.fill = GridBagConstraints.HORIZONTAL; 232 gbc.gridx = 2; 233 gbc.gridy = 0; 234 final HtmlZipExportDialog.ActionSelectTargetFile selectTargetAction = 235 new HtmlZipExportDialog.ActionSelectTargetFile(getResources()); 236 contentPane.add(new ActionButton(selectTargetAction), gbc); 237 238 gbc = new GridBagConstraints(); 239 gbc.anchor = GridBagConstraints.WEST; 240 gbc.fill = GridBagConstraints.HORIZONTAL; 241 gbc.gridx = 1; 242 gbc.gridy = 1; 243 gbc.gridwidth = 1; 244 gbc.weightx = 1; 245 gbc.insets = new Insets(1, 1, 1, 1); 246 contentPane.add(dataDirField, gbc); 247 248 249 gbc = new GridBagConstraints(); 250 gbc.anchor = GridBagConstraints.WEST; 251 gbc.fill = GridBagConstraints.HORIZONTAL; 252 gbc.gridx = 0; 253 gbc.gridy = 2; 254 contentPane.add(exportMethodLabel, gbc); 255 256 gbc = new GridBagConstraints(); 257 gbc.anchor = GridBagConstraints.WEST; 258 gbc.fill = GridBagConstraints.HORIZONTAL; 259 gbc.gridx = 1; 260 gbc.gridy = 2; 261 gbc.gridwidth = 1; 262 gbc.insets = new Insets(1, 1, 1, 1); 263 contentPane.add(exportTypeSelectionPanel, gbc); 264 265 266 final JButton btnCancel = new ActionButton(getCancelAction()); 267 final JButton btnConfirm = new ActionButton(getConfirmAction()); 268 269 final JPanel buttonPanel = new JPanel(); 270 buttonPanel.setLayout(new GridLayout()); 271 buttonPanel.add(btnConfirm); 272 buttonPanel.add(btnCancel); 273 btnConfirm.setDefaultCapable(true); 274 buttonPanel.registerKeyboardAction(getConfirmAction(), 275 KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), 276 JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 277 278 gbc = new GridBagConstraints(); 279 gbc.fill = GridBagConstraints.NONE; 280 gbc.anchor = GridBagConstraints.EAST; 281 gbc.weightx = 1; 282 gbc.gridx = 0; 283 gbc.gridwidth = 3; 284 gbc.gridy = 15; 285 gbc.insets = new Insets(10, 0, 10, 0); 286 contentPane.add(buttonPanel, gbc); 287 288 289 final JPanel contentWithStatus = new JPanel(); 290 contentWithStatus.setLayout(new BorderLayout()); 291 contentWithStatus.add(contentPane, BorderLayout.CENTER); 292 contentWithStatus.add(statusBar, BorderLayout.SOUTH); 293 294 setContentPane(contentWithStatus); 295 296 getFormValidator().registerTextField(dataDirField); 297 getFormValidator().registerTextField(filenameField); 298 } 299 300 301 public JStatusBar getStatusBar() 302 { 303 return statusBar; 304 } 305 306 protected boolean performValidate() 307 { 308 getStatusBar().clear(); 309 310 final String filename = getFilename(); 311 if (filename.trim().length() == 0) 312 { 313 getStatusBar().setStatus(JStatusBar.TYPE_ERROR, 314 getResources().getString("htmlexportdialog.targetIsEmpty")); 315 return false; 316 } 317 final File f = new File(filename); 318 if (f.exists()) 319 { 320 if (f.isFile() == false) 321 { 322 getStatusBar().setStatus(JStatusBar.TYPE_ERROR, 323 getResources().getString("htmlexportdialog.targetIsNoFile")); 324 return false; 325 } 326 if (f.canWrite() == false) 327 { 328 getStatusBar().setStatus(JStatusBar.TYPE_ERROR, 329 getResources().getString("htmlexportdialog.targetIsNotWritable")); 330 return false; 331 } 332 333 final String message = MessageFormat.format(getResources().getString 334 ("htmlexportdialog.targetExistsWarning"), 335 new Object[]{filename}); 336 getStatusBar().setStatus(JStatusBar.TYPE_WARNING, message); 337 } 338 339 try 340 { 341 final File dataDir = new File(dataDirField.getText()); 342 final File baseDir = new File(""); 343 344 if (IOUtils.getInstance().isSubDirectory(baseDir, dataDir) == false) 345 { 346 getStatusBar().setStatus(JStatusBar.TYPE_ERROR, 347 getResources().getString("htmlexportdialog.targetPathIsAbsolute")); 348 return false; 349 } 350 } 351 catch (Exception e) 352 { 353 getStatusBar().setStatus(JStatusBar.TYPE_ERROR, "error.validationfailed"); 354 return false; 355 } 356 357 return true; 358 } 359 360 protected boolean performConfirm() 361 { 362 final String filename = getFilename(); 363 final File f = new File(filename).getAbsoluteFile(); 364 if (f.exists()) 365 { 366 final String key1 = "htmlexportdialog.targetOverwriteConfirmation"; 367 final String key2 = "htmlexportdialog.targetOverwriteTitle"; 368 if (JOptionPane.showConfirmDialog(this, 369 MessageFormat.format(getResources().getString(key1), 370 new Object[]{getFilename()}), 371 getResources().getString(key2), 372 JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) 373 == JOptionPane.NO_OPTION) 374 { 375 return false; 376 } 377 } 378 379 return true; 380 } 381 382 protected void initializeFromJob(final ReportJob job, final GuiContext guiContext) 383 { 384 statusBar.setIconTheme(guiContext.getIconTheme()); 385 } 386 387 protected String getConfigurationPrefix() 388 { 389 return "org.jfree.report.modules.gui.common.html.zip."; 390 } 391 392 protected Configuration grabDialogContents(final boolean full) 393 { 394 final ModifiableConfiguration conf = new DefaultConfiguration(); 395 if (full) 396 { 397 conf.setConfigProperty 398 ("org.jfree.report.modules.gui.common.html.zip.TargetFileName", filenameField.getText()); 399 conf.setConfigProperty 400 ("org.jfree.report.modules.gui.common.html.zip.DataDirectory", dataDirField.getText()); 401 } 402 conf.setConfigProperty 403 ("org.jfree.report.modules.gui.common.html.zip.ExportMethod", getExportMethod()); 404 405 return conf; 406 } 407 408 protected void setDialogContents(final Configuration properties) 409 { 410 filenameField.setText(properties.getConfigProperty 411 ("org.jfree.report.modules.gui.common.html.zip.TargetFileName", "")); 412 dataDirField.setText(properties.getConfigProperty 413 ("org.jfree.report.modules.gui.common.html.zip.DataDirectory", "")); 414 setExportMethod(properties.getConfigProperty 415 ("org.jfree.report.modules.gui.common.html.zip.ExportMethod", "")); 416 } 417 418 419 protected String getConfigurationSuffix () 420 { 421 return "_htmlexport_file"; 422 } 423 424 public String getExportMethod() 425 { 426 if (rbPageableExport.isSelected()) 427 { 428 return "pageable"; 429 } 430 if (rbFlowExport.isSelected()) 431 { 432 return "flow"; 433 } 434 return "stream"; 435 } 436 437 public void setExportMethod (final String method) 438 { 439 if ("pageable".equals(method)) 440 { 441 rbPageableExport.setSelected(true); 442 } 443 else if ("flow".equals(method)) 444 { 445 rbFlowExport.setSelected(true); 446 } 447 else 448 { 449 rbStreamExport.setSelected(true); 450 } 451 } 452 453 public void clear() 454 { 455 filenameField.setText(""); 456 dataDirField.setText(""); 457 rbStreamExport.setSelected(true); 458 } 459 460 protected String getResourceBaseName() 461 { 462 return SwingHtmlModule.BUNDLE_NAME; 463 } 464 465 /** 466 * Selects a file to use as target for the report processing. 467 */ 468 protected void performSelectFile () 469 { 470 final File file = new File(getFilename()); 471 472 if (fileChooserHtml == null) 473 { 474 fileChooserHtml = new JFileChooser(); 475 fileChooserHtml.addChoosableFileFilter 476 (new FilesystemFilter(new String[]{HtmlZipExportDialog.ZIP_FILE_EXTENSION}, 477 getResources().getString("htmlexportdialog.zip-archives"), true)); 478 fileChooserHtml.setMultiSelectionEnabled(false); 479 } 480 481 fileChooserHtml.setCurrentDirectory(file); 482 fileChooserHtml.setSelectedFile(file); 483 final int option = fileChooserHtml.showSaveDialog(this); 484 if (option == JFileChooser.APPROVE_OPTION) 485 { 486 final File selFile = fileChooserHtml.getSelectedFile(); 487 String selFileName = selFile.getAbsolutePath(); 488 489 // Test if ends on html 490 if (StringUtils.endsWithIgnoreCase(selFileName, HtmlZipExportDialog.ZIP_FILE_EXTENSION) == false) 491 { 492 selFileName = selFileName + HtmlZipExportDialog.ZIP_FILE_EXTENSION; 493 } 494 setFilename(selFileName); 495 } 496 } 497 498 }