/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.designer.core.editor.bundle;
import org.pentaho.reporting.designer.core.Messages;
import org.pentaho.reporting.designer.core.ReportDesignerContext;
import org.pentaho.reporting.designer.core.editor.ReportDocumentContext;
import org.pentaho.reporting.designer.core.util.exceptions.UncaughtExceptionsModel;
import org.pentaho.reporting.designer.core.util.table.TextAreaPropertyEditorDialog;
import org.pentaho.reporting.libraries.base.util.FilesystemFilter;
import org.pentaho.reporting.libraries.base.util.IOUtils;
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
import org.pentaho.reporting.libraries.base.util.StringBufferWriter;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import org.pentaho.reporting.libraries.designtime.swing.LibSwingUtil;
import org.pentaho.reporting.libraries.designtime.swing.filechooser.CommonFileChooser;
import org.pentaho.reporting.libraries.designtime.swing.filechooser.FileChooserService;
import org.pentaho.reporting.libraries.docbundle.BundleUtilities;
import org.pentaho.reporting.libraries.docbundle.WriteableDocumentBundle;
import org.pentaho.reporting.libraries.docbundle.WriteableDocumentMetaData;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
public class BundledResourceEditor extends JDialog {
private class ImportFileAction extends AbstractAction {
/**
* Defines an <code>Action</code> object with a default description string and default icon.
*/
private ImportFileAction() {
putValue( Action.NAME, Messages.getString( "BundledResourceEditor.Import" ) );
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed( final ActionEvent e ) {
final ImportBundleFileDialog dialog = new ImportBundleFileDialog( BundledResourceEditor.this );
if ( dialog.performCreateEntry( bundle ) == false ) {
return;
}
final String entryName = dialog.getEntryName();
final String fileName = dialog.getFileName();
final String mimeType = dialog.getMimeType();
try {
final FileInputStream fin = new FileInputStream( fileName );
try {
final OutputStream outputStream = bundle.createEntry( entryName, mimeType );
try {
IOUtils.getInstance().copyStreams( fin, outputStream );
} finally {
outputStream.close();
}
bundle.getWriteableDocumentMetaData()
.setEntryAttribute( entryName, BundleUtilities.STICKY_FLAG, "true" ); // NON-NLS
} finally {
fin.close();
}
} catch ( IOException ioe ) {
UncaughtExceptionsModel.getInstance().addException( ioe );
}
changed = true;
refreshBundleList();
}
}
private class ExportFileAction extends AbstractAction {
/**
* Defines an <code>Action</code> object with a default description string and default icon.
*/
private ExportFileAction() {
putValue( Action.NAME, Messages.getString( "BundledResourceEditor.Export" ) );
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed( final ActionEvent e ) {
final String entryName = getSelectedEntry();
final FileFilter[] filters = {
new FilesystemFilter( ".properties", // NON-NLS
Messages.getString( "BundledResourceEditor.PropertiesTranslations" ) ),
new FilesystemFilter( new String[] { ".xml", ".report", ".prpt", ".prpti", ".prptstyle" }, // NON-NLS
Messages.getString( "BundledResourceEditor.Resources" ), true ),
new FilesystemFilter( new String[] { ".gif", ".jpg", ".jpeg", ".png", ".svg", ".wmf" }, // NON-NLS
Messages.getString( "BundledResourceEditor.Images" ), true ),
};
final CommonFileChooser fileChooser = FileChooserService.getInstance().getFileChooser( "resources" );//NON-NLS
fileChooser.setFilters( filters );
if ( fileChooser.showDialog( BundledResourceEditor.this, JFileChooser.OPEN_DIALOG ) == false ) {
return;
}
final File selectedFile = fileChooser.getSelectedFile();
if ( selectedFile == null ) {
return;
}
try {
final FileOutputStream fout = new FileOutputStream( selectedFile );
try {
final InputStream inputStream = bundle.getEntryAsStream( entryName );
try {
IOUtils.getInstance().copyStreams( inputStream, fout );
} finally {
inputStream.close();
}
bundle.getWriteableDocumentMetaData()
.setEntryAttribute( entryName, BundleUtilities.STICKY_FLAG, "true" ); // NON-NLS
} finally {
fout.close();
}
} catch ( IOException ioe ) {
UncaughtExceptionsModel.getInstance().addException( ioe );
}
changed = true;
}
}
private class RemoveFileAction extends AbstractAction {
/**
* Defines an <code>Action</code> object with a default description string and default icon.
*/
private RemoveFileAction() {
putValue( Action.NAME, Messages.getString( "BundledResourceEditor.Remove" ) );
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed( final ActionEvent e ) {
final String selectedEntry = getSelectedEntry();
if ( selectedEntry == null ) {
return;
}
try {
bundle.removeEntry( selectedEntry );
} catch ( IOException e1 ) {
e1.printStackTrace();
}
changed = true;
refreshBundleList();
}
}
private class EditFileAction extends AbstractAction {
/**
* Defines an <code>Action</code> object with a default description string and default icon.
*/
private EditFileAction() {
putValue( Action.NAME, Messages.getString( "BundledResourceEditor.Edit" ) );
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed( final ActionEvent e ) {
final String selectedEntry = getSelectedEntry();
if ( selectedEntry == null ) {
return;
}
final String mimeType = bundle.getEntryMimeType( selectedEntry );
final StringBufferWriter w = new StringBufferWriter( new StringBuffer() );
try {
final InputStream stream = bundle.getEntryAsStream( selectedEntry );
try {
final InputStreamReader r = new InputStreamReader( stream, "ISO-8859-1" ); // NON-NLS
IOUtils.getInstance().copyWriter( r, w );
} catch ( IOException ioe ) {
ioe.printStackTrace();
} finally {
stream.close();
}
} catch ( IOException ioe ) {
ioe.printStackTrace();
return;
}
final TextAreaPropertyEditorDialog editorDialog = new TextAreaPropertyEditorDialog( BundledResourceEditor.this );
final String originalValue = w.getBuffer().toString();
final String editedValue = editorDialog.performEdit( originalValue );
if ( ObjectUtilities.equal( originalValue, editedValue ) ) {
return;
}
try {
bundle.removeEntry( selectedEntry );
final OutputStream outputStream = bundle.createEntry( selectedEntry, mimeType );
try {
outputStream.write( editedValue.getBytes( "ISO-8859-1" ) ); // NON-NLS
} finally {
outputStream.close();
}
bundle.getWriteableDocumentMetaData().setEntryAttribute( selectedEntry, BundleUtilities.STICKY_FLAG, "true" );
} catch ( IOException ioe ) {
ioe.printStackTrace();
}
changed = true;
}
}
private class CreateFileAction extends AbstractAction {
/**
* Defines an <code>Action</code> object with a default description string and default icon.
*/
private CreateFileAction() {
putValue( Action.NAME, "Create" );
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed( final ActionEvent e ) {
final CreateBundleFileDialog dialog = new CreateBundleFileDialog( BundledResourceEditor.this );
if ( dialog.performCreateEntry( bundle ) == false ) {
return;
}
final String fileEntryName = dialog.getFileName();
if ( StringUtils.isEmpty( fileEntryName ) ) {
return;
}
try {
final OutputStream outputStream = bundle.createEntry( fileEntryName, dialog.getMimeType() );
outputStream.close();
bundle.getWriteableDocumentMetaData().setEntryAttribute( fileEntryName, BundleUtilities.STICKY_FLAG, "true" );
} catch ( IOException e1 ) {
e1.printStackTrace();
}
changed = true;
refreshBundleList();
}
}
private class CloseAction extends AbstractAction {
/**
* Defines an <code>Action</code> object with a default description string and default icon.
*/
private CloseAction() {
putValue( Action.NAME, Messages.getString( "BundledResourceEditor.Close" ) );
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed( final ActionEvent e ) {
dispose();
}
}
private class FileSelectionHandler implements ListSelectionListener {
/**
* Called whenever the value of the selection changes.
*
* @param e the event that characterizes the change.
*/
public void valueChanged( final ListSelectionEvent e ) {
final boolean enable = resourceList.isSelectionEmpty() == false;
removeFileAction.setEnabled( enable );
exportFileAction.setEnabled( enable );
if ( enable == false ) {
editFileAction.setEnabled( enable );
} else {
final String s = getSelectedEntry();
if ( s == null ) {
return;
}
if ( "text/plain".equals( bundle.getEntryMimeType( s ) ) || s.endsWith( ".properties" ) ) // NON-NLS
{
editFileAction.setEnabled( true );
} else {
editFileAction.setEnabled( false );
}
}
}
}
private ReportDesignerContext designerContext;
private CreateFileAction createFileAction;
private ImportFileAction importFileAction;
private EditFileAction editFileAction;
private RemoveFileAction removeFileAction;
private DefaultListModel fileModel;
private ExportFileAction exportFileAction;
private JList resourceList;
private boolean changed;
private WriteableDocumentBundle bundle;
public BundledResourceEditor( final ReportDesignerContext designerContext )
throws HeadlessException {
init( designerContext );
}
public BundledResourceEditor( final Frame owner, final ReportDesignerContext designerContext )
throws HeadlessException {
super( owner );
init( designerContext );
}
public BundledResourceEditor( final Dialog owner, final ReportDesignerContext designerContext )
throws HeadlessException {
super( owner );
init( designerContext );
}
private void init( final ReportDesignerContext designerContext ) {
if ( designerContext == null ) {
throw new NullPointerException();
}
this.designerContext = designerContext;
setModal( true );
setTitle( Messages.getString( "BundledResourceEditor.ResourceEditor" ) );
setDefaultCloseOperation( DISPOSE_ON_CLOSE );
createFileAction = new CreateFileAction();
importFileAction = new ImportFileAction();
editFileAction = new EditFileAction();
editFileAction.setEnabled( false );
removeFileAction = new RemoveFileAction();
removeFileAction.setEnabled( false );
exportFileAction = new ExportFileAction();
exportFileAction.setEnabled( false );
fileModel = new DefaultListModel();
resourceList = new JList( fileModel );
resourceList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
resourceList.setVisibleRowCount( 10 );
resourceList.addListSelectionListener( new FileSelectionHandler() );
final JPanel editorButtonsPanel = new JPanel();
editorButtonsPanel.setLayout( new GridLayout( 5, 1, 5, 5 ) );
editorButtonsPanel.add( new JButton( createFileAction ) );
editorButtonsPanel.add( new JButton( importFileAction ) );
editorButtonsPanel.add( new JButton( editFileAction ) );
editorButtonsPanel.add( new JButton( removeFileAction ) );
editorButtonsPanel.add( new JButton( exportFileAction ) );
final JPanel editorButtonCarrier = new JPanel();
editorButtonCarrier.setLayout( new BorderLayout() );
editorButtonCarrier.add( editorButtonsPanel, BorderLayout.NORTH );
final JPanel bottomButtonCarrier = new JPanel();
bottomButtonCarrier.setLayout( new FlowLayout( FlowLayout.TRAILING ) );
bottomButtonCarrier.add( new JButton( new CloseAction() ) );
final JPanel contentPane = new JPanel();
contentPane.setLayout( new BorderLayout() );
contentPane.setBorder( new EmptyBorder( 5, 5, 5, 5 ) );
contentPane.add( new JScrollPane( resourceList ), BorderLayout.CENTER );
contentPane.add( editorButtonCarrier, BorderLayout.EAST );
contentPane.add( bottomButtonCarrier, BorderLayout.SOUTH );
setContentPane( contentPane );
pack();
LibSwingUtil.centerDialogInParent( this );
final InputMap inputMap = contentPane.getInputMap();
final ActionMap actionMap = contentPane.getActionMap();
inputMap.put( KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0 ), "cancel" ); // NON-NLS
actionMap.put( "cancel", new CloseAction() ); // NON-NLS
}
public String getSelectedEntry() {
return (String) resourceList.getSelectedValue();
}
public boolean editResources() {
final ReportDocumentContext activeContext = designerContext.getActiveContext();
if ( activeContext == null ) {
throw new IllegalStateException();
}
bundle = (WriteableDocumentBundle) activeContext.getContextRoot().getBundle();
refreshBundleList();
changed = false;
setModal( true );
setVisible( true );
return changed;
}
private void refreshBundleList() {
final WriteableDocumentMetaData metaData = bundle.getWriteableDocumentMetaData();
final ArrayList<String> entries = new ArrayList<String>();
final String[] manifestEntryNames = metaData.getManifestEntryNames();
for ( int i = 0; i < manifestEntryNames.length; i++ ) {
final String manifestEntryName = manifestEntryNames[ i ];
final String stickyFlag = metaData.getEntryAttribute( manifestEntryName, BundleUtilities.STICKY_FLAG );
final String hiddenFlag = metaData.getEntryAttribute( manifestEntryName, BundleUtilities.HIDDEN_FLAG );
if ( "true".equals( stickyFlag ) && "true".equals( hiddenFlag ) == false ) // NON-NLS
{
entries.add( manifestEntryName );
}
}
Collections.sort( entries );
fileModel.clear();
final int length = entries.size();
for ( int i = 0; i < length; i++ ) {
fileModel.addElement( entries.get( i ) );
}
}
}