/*
* eXist Open Source Native XML Database
* Copyright (C) 2008-2010 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* $Id: ExportGUI.java 14933 2011-07-21 20:49:58Z wolfgang_m $
*/
package org.exist.backup;
import org.exist.EXistException;
import org.exist.security.SecurityManager;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.util.Configuration;
import org.exist.util.MimeTable;
import org.exist.util.MimeType;
import org.exist.xquery.TerminatedException;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;
/**
* DOCUMENT ME!
*
* @author wolf
*/
public class ExportGUI extends javax.swing.JFrame
{
private static final long serialVersionUID = -8104424554660744639L;
private BrokerPool pool = null;
private int documentCount = 0;
private PrintWriter logWriter = null;
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnChangeDir;
private javax.swing.JButton btnConfSelect;
private javax.swing.JLabel currentTask;
private javax.swing.JTextField dbConfig;
private javax.swing.JButton exportBtn;
private javax.swing.JCheckBox zipBtn;
private javax.swing.JCheckBox incrementalBtn;
private JCheckBox directAccessBtn;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JMenu jMenu1;
private javax.swing.JMenuBar jMenuBar1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JToolBar jToolBar1;
private javax.swing.JMenuItem menuQuit;
private javax.swing.JTextArea messages;
private javax.swing.JTextField outputDir;
private javax.swing.JProgressBar progress;
private javax.swing.JButton startBtn;
// End of variables declaration//GEN-END:variables
/**
* Creates new form CheckerGUI.
*/
public ExportGUI()
{
super( "Consistency Check and Repair" );
initComponents();
String existHome = System.getProperty( "exist.home", "./" );
File home = new File( existHome );
dbConfig.setText( new File( home, "conf.xml" ).getAbsolutePath() );
outputDir.setText( new File( home, "export" ).getAbsolutePath() );
}
protected boolean checkOutputDir()
{
File dir = new File( outputDir.getText() );
if( !dir.exists() ) {
if( JOptionPane.showConfirmDialog( this, "The output directory " + dir.getAbsolutePath() + " does not exist. Create it?", "Confirm", JOptionPane.YES_NO_OPTION ) == JOptionPane.YES_OPTION ) {
dir.mkdirs();
} else {
return( false );
}
}
return( true );
}
protected boolean startDB()
{
if( pool != null ) {
return( true );
}
File confFile = new File( dbConfig.getText() );
if( !( confFile.exists() && confFile.canRead() ) ) {
JOptionPane.showMessageDialog( this, "The selected database configuration file " + confFile.getAbsolutePath() + " does not exist or is not readable.", "Configuration Error", JOptionPane.ERROR_MESSAGE );
return( false );
}
try {
Configuration config = new Configuration( confFile.getAbsolutePath(), null );
BrokerPool.configure( 1, 5, config );
pool = BrokerPool.getInstance();
return( true );
}
catch( Exception e ) {
JOptionPane.showMessageDialog( this, "Could not start the database instance. Please remember\n" + "that this tool tries to launch an embedded db instance. No other db instance should\n" + "be running on the same data.", "DB Error", JOptionPane.ERROR_MESSAGE );
e.printStackTrace();
System.err.println( "ERROR: Failed to open database: " + e.getMessage() );
}
return( false );
}
/**
* This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated
// Code">//GEN-BEGIN:initComponents
private void initComponents()
{
java.awt.GridBagConstraints gridBagConstraints;
currentTask = new javax.swing.JLabel();
progress = new javax.swing.JProgressBar();
jScrollPane2 = new javax.swing.JScrollPane();
messages = new javax.swing.JTextArea();
jToolBar1 = new javax.swing.JToolBar();
startBtn = new javax.swing.JButton();
exportBtn = new javax.swing.JButton();
incrementalBtn = new JCheckBox( "Incremental backup" );
directAccessBtn = new JCheckBox( "Direct access" );
zipBtn = new JCheckBox("Create ZIP");
outputDir = new javax.swing.JTextField();
jLabel1 = new javax.swing.JLabel();
btnChangeDir = new javax.swing.JButton();
dbConfig = new javax.swing.JTextField();
jLabel2 = new javax.swing.JLabel();
btnConfSelect = new javax.swing.JButton();
jMenuBar1 = new javax.swing.JMenuBar();
jMenu1 = new javax.swing.JMenu();
menuQuit = new javax.swing.JMenuItem();
setDefaultCloseOperation( javax.swing.WindowConstants.EXIT_ON_CLOSE );
addWindowListener( new java.awt.event.WindowAdapter() {
public void windowClosed( java.awt.event.WindowEvent evt )
{
formWindowClosed( evt );
}
} );
getContentPane().setLayout( new java.awt.GridBagLayout() );
currentTask.setText( " " );
currentTask.setMinimumSize( new java.awt.Dimension( 0, 25 ) );
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 3;
gridBagConstraints.gridwidth = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets( 5, 5, 5, 5 );
getContentPane().add( currentTask, gridBagConstraints );
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 4;
gridBagConstraints.gridwidth = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets( 5, 5, 5, 5 );
getContentPane().add( progress, gridBagConstraints );
jScrollPane2.setBorder( javax.swing.BorderFactory.createTitledBorder( "Messages" ) );
jScrollPane2.setPreferredSize( new java.awt.Dimension( 400, 200 ) );
messages.setColumns( 20 );
messages.setLineWrap( true );
messages.setRows( 5 );
messages.setBorder( javax.swing.BorderFactory.createEmptyBorder( 1, 1, 1, 1 ) );
jScrollPane2.setViewportView( messages );
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 5;
gridBagConstraints.gridwidth = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets( 5, 5, 5, 5 );
getContentPane().add( jScrollPane2, gridBagConstraints );
jToolBar1.setRollover( true );
startBtn.setText( "Check" );
startBtn.setFocusable( false );
startBtn.setHorizontalTextPosition( javax.swing.SwingConstants.CENTER );
startBtn.setVerticalTextPosition( javax.swing.SwingConstants.BOTTOM );
startBtn.addActionListener( new java.awt.event.ActionListener() {
public void actionPerformed( java.awt.event.ActionEvent evt )
{
startBtncheck( evt );
}
} );
jToolBar1.add( startBtn );
exportBtn.setText( "Check & Export" );
exportBtn.setFocusable( false );
exportBtn.setHorizontalTextPosition( javax.swing.SwingConstants.CENTER );
exportBtn.setVerticalTextPosition( javax.swing.SwingConstants.BOTTOM );
exportBtn.addActionListener( new java.awt.event.ActionListener() {
public void actionPerformed( java.awt.event.ActionEvent evt )
{
exportBtnActionPerformed( evt );
}
} );
jToolBar1.add( exportBtn );
jToolBar1.add( incrementalBtn );
jToolBar1.add( directAccessBtn );
jToolBar1.add( zipBtn );
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridwidth = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
getContentPane().add( jToolBar1, gridBagConstraints );
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets( 5, 5, 5, 5 );
getContentPane().add( outputDir, gridBagConstraints );
jLabel1.setText( "Output Directory:" );
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets( 5, 5, 5, 5 );
getContentPane().add( jLabel1, gridBagConstraints );
btnChangeDir.setText( "Change" );
btnChangeDir.addActionListener( new java.awt.event.ActionListener() {
public void actionPerformed( java.awt.event.ActionEvent evt )
{
btnChangeDirActionPerformed( evt );
}
} );
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.insets = new java.awt.Insets( 5, 5, 5, 5 );
getContentPane().add( btnChangeDir, gridBagConstraints );
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets( 5, 5, 5, 5 );
getContentPane().add( dbConfig, gridBagConstraints );
jLabel2.setText( "DB Configuration:" );
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets( 5, 5, 5, 5 );
getContentPane().add( jLabel2, gridBagConstraints );
btnConfSelect.setText( "Select" );
btnConfSelect.setMaximumSize( new java.awt.Dimension( 75, 24 ) );
btnConfSelect.setMinimumSize( new java.awt.Dimension( 75, 24 ) );
btnConfSelect.setPreferredSize( new java.awt.Dimension( 75, 24 ) );
btnConfSelect.addActionListener( new java.awt.event.ActionListener() {
public void actionPerformed( java.awt.event.ActionEvent evt )
{
btnConfSelectActionPerformed( evt );
}
} );
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.insets = new java.awt.Insets( 5, 5, 5, 5 );
getContentPane().add( btnConfSelect, gridBagConstraints );
jMenu1.setText( "File" );
menuQuit.setAccelerator( javax.swing.KeyStroke.getKeyStroke( java.awt.event.KeyEvent.VK_Q, java.awt.event.InputEvent.CTRL_MASK ) );
menuQuit.setText( "Quit" );
menuQuit.addActionListener( new java.awt.event.ActionListener() {
public void actionPerformed( java.awt.event.ActionEvent evt )
{
menuQuitActionPerformed( evt );
}
} );
jMenu1.add( menuQuit );
jMenuBar1.add( jMenu1 );
setJMenuBar( jMenuBar1 );
pack();
} // </editor-fold>//GEN-END:initComponents
private void formWindowClosed( java.awt.event.WindowEvent evt )
{ // GEN-FIRST:event_formWindowClosed
BrokerPool.stopAll( false );
} // GEN-LAST:event_formWindowClosed
private void startBtncheck( java.awt.event.ActionEvent evt )
{ // GEN-FIRST:event_startBtncheck
if( !checkOutputDir() ) {
return;
}
Runnable checkRun = new Runnable() {
public void run()
{
openLog( outputDir.getText() );
try {
checkDB();
}
finally {
closeLog();
}
}
};
new Thread( checkRun ).start();
} // GEN-LAST:event_startBtncheck
private void exportBtnActionPerformed( java.awt.event.ActionEvent evt )
{ // GEN-FIRST:event_exportBtnActionPerformed
if( !checkOutputDir() ) {
return;
}
Runnable th = new Runnable() {
public void run()
{
openLog( outputDir.getText() );
try {
currentTask.setText( "Checking database consistency ..." );
List<ErrorReport> errors = checkDB();
currentTask.setText( "Exporting data ..." );
exportDB( outputDir.getText(), errors );
}
finally {
closeLog();
}
}
};
new Thread( th ).start();
} // GEN-LAST:event_exportBtnActionPerformed
private void btnChangeDirActionPerformed( java.awt.event.ActionEvent evt )
{ // GEN-FIRST:event_btnChangeDirActionPerformed
File dir = new File( outputDir.getText() );
final JFileChooser chooser = new JFileChooser();
chooser.setMultiSelectionEnabled( false );
chooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY );
chooser.setSelectedFile( new File( dir, "export" ) );
chooser.setCurrentDirectory( dir );
if( chooser.showDialog( this, "Export" ) == JFileChooser.APPROVE_OPTION ) {
outputDir.setText( chooser.getSelectedFile().getAbsolutePath() );
}
} // GEN-LAST:event_btnChangeDirActionPerformed
private void menuQuitActionPerformed( java.awt.event.ActionEvent evt )
{ // GEN-FIRST:event_menuQuitActionPerformed
BrokerPool.stopAll( false );
System.exit( 0 );
} // GEN-LAST:event_menuQuitActionPerformed
private void btnConfSelectActionPerformed( java.awt.event.ActionEvent evt )
{ // GEN-FIRST:event_btnConfSelectActionPerformed
File dir = new File( dbConfig.getText() ).getParentFile();
final JFileChooser chooser = new JFileChooser();
chooser.setMultiSelectionEnabled( false );
chooser.setFileSelectionMode( JFileChooser.FILES_ONLY );
chooser.setSelectedFile( new File( dir, "conf.xml" ) );
chooser.setCurrentDirectory( dir );
chooser.setFileFilter( new FileFilter() {
public boolean accept( File f )
{
if( f.isDirectory() ) {
return( true );
}
MimeType mime = MimeTable.getInstance().getContentTypeFor( f.getName() );
if( mime == null ) {
return( false );
}
return( mime.isXMLType() );
}
public String getDescription()
{
return( "Database XML configuration file" );
}
} );
if( chooser.showDialog( this, "Select" ) == JFileChooser.APPROVE_OPTION ) {
dbConfig.setText( chooser.getSelectedFile().getAbsolutePath() );
}
} // GEN-LAST:event_btnConfSelectActionPerformed
private void exportDB( String exportTarget, List<ErrorReport> errorList )
{
if( !startDB() ) {
return;
}
DBBroker broker = null;
try {
broker = pool.get( SecurityManager.SYSTEM_USER );
SystemExport.StatusCallback callback = new SystemExport.StatusCallback() {
public void startCollection( String path )
{
progress.setString( path );
}
public void startDocument( String name, int current, int count )
{
progress.setString( name );
progress.setValue( progress.getValue() + 1 );
}
public void error( String message, Throwable exception )
{
displayMessage( message );
if( exception != null ) {
displayMessage( exception.toString() );
}
displayMessage( "---------------------------------------------------" );
}
};
progress.setIndeterminate( false );
progress.setValue( 0 );
progress.setStringPainted( true );
progress.setMinimum( 0 );
progress.setMaximum( documentCount );
Object[] selected = directAccessBtn.getSelectedObjects();
boolean directAccess = ( selected != null ) && ( selected[0] != null );
selected = incrementalBtn.getSelectedObjects();
boolean incremental = ( selected != null ) && ( selected[0] != null );
selected = zipBtn.getSelectedObjects();
boolean zip = ( selected != null ) && ( selected[0] != null );
displayMessage( "Starting export ..." );
SystemExport sysexport = new SystemExport( broker, callback, null, directAccess );
File file = sysexport.export( exportTarget, incremental, zip, errorList );
displayMessage( "Export to " + file.getAbsolutePath() + " completed successfully." );
progress.setString( "" );
}
catch( EXistException e ) {
System.err.println( "ERROR: Failed to retrieve database broker: " + e.getMessage() );
}
finally {
pool.release( broker );
progress.setValue( 0 );
currentTask.setText( " " );
}
}
private List<ErrorReport> checkDB()
{
if( !startDB() ) {
return( null );
}
DBBroker broker = null;
try {
broker = pool.get( SecurityManager.SYSTEM_USER );
Object[] selected = directAccessBtn.getSelectedObjects();
boolean directAccess = ( selected != null ) && ( selected[0] != null );
ConsistencyCheck checker = new ConsistencyCheck( broker, directAccess );
org.exist.backup.ConsistencyCheck.ProgressCallback cb = new ConsistencyCheck.ProgressCallback() {
public void startDocument( String path, int current, int count )
{
progress.setString( path );
progress.setValue( progress.getValue() + 1 );
}
public void error( ErrorReport error )
{
displayMessage( error.toString() );
displayMessage( "---------------------------------------------------" );
}
public void startCollection( String path )
{
progress.setString( path );
}
};
progress.setIndeterminate( true );
messages.setText( "" );
displayMessage( "Checking collections ..." );
List<ErrorReport> errors = checker.checkCollectionTree( cb );
if( errors.size() == 0 ) {
displayMessage( "No errors found." );
} else {
displayMessage( "Errors found." );
}
progress.setStringPainted( true );
progress.setString( "Counting documents ..." );
documentCount = checker.getDocumentCount();
progress.setIndeterminate( false );
progress.setValue( 0 );
progress.setMinimum( 0 );
progress.setMaximum( documentCount );
displayMessage( "Checking documents ..." );
checker.checkDocuments( cb, errors );
if( errors.size() == 0 ) {
displayMessage( "No errors found." );
} else {
displayMessage( "Errors found." );
}
progress.setString( "" );
return( errors );
}
catch( EXistException e ) {
System.err.println( "ERROR: Failed to retrieve database broker: " + e.getMessage() );
}
catch( TerminatedException e ) {
System.err.println( "WARN: Check terminated by db." );
}
finally {
pool.release( broker );
progress.setValue( 0 );
currentTask.setText( " " );
}
return( null );
}
public void displayMessage( String message )
{
messages.append( message + '\n' );
messages.setCaretPosition( messages.getDocument().getLength() );
if( logWriter != null ) {
logWriter.println( message );
}
}
private void openLog( String dir )
{
try {
File file = SystemExport.getUniqueFile( "report", ".log", dir );
OutputStream os = new BufferedOutputStream( new FileOutputStream( file ) );
logWriter = new PrintWriter( new OutputStreamWriter( os, "UTF-8" ) );
}
catch( UnsupportedEncodingException e ) {
}
catch( FileNotFoundException e ) {
System.err.println( "ERROR: failed to create log file" );
}
}
private void closeLog()
{
if( logWriter != null ) {
logWriter.close();
}
}
/**
* DOCUMENT ME!
*
* @param args the command line arguments
*/
public static void main( String[] args )
{
java.awt.EventQueue.invokeLater( new Runnable() {
public void run()
{
new ExportGUI().setVisible( true );
}
} );
}
}