org.exist.client.DocumentView Maven / Gradle / Ivy
/*
* eXist-db Open Source Native XML Database
* Copyright (C) 2001 The eXist-db Authors
*
* [email protected]
* http://www.exist-db.org
*
* This library 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.1 of the License, or (at your option) any later version.
*
* This library 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 Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.exist.client;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Observable;
import java.util.Observer;
import java.util.Properties;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.border.BevelBorder;
import javax.xml.transform.OutputKeys;
import org.exist.security.Account;
import org.exist.storage.ElementIndex;
import org.exist.util.ProgressIndicator;
import org.exist.xmldb.UserManagementService;
import org.exist.xmldb.XmldbURI;
import org.exist.xquery.util.URIUtils;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.Resource;
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.XMLResource;
import static java.nio.charset.StandardCharsets.UTF_8;
class DocumentView extends JFrame {
private static final long serialVersionUID = 1L;
protected InteractiveClient client;
private XmldbURI resourceName;
protected Resource resource;
protected Collection collection;
protected boolean readOnly = false;
protected RSyntaxTextArea text;
protected RTextScrollPane textScrollPane;
protected JButton saveButton;
protected JButton saveAsButton;
protected JTextField statusMessage;
protected JTextField positionDisplay;
protected JProgressBar progress;
protected JPopupMenu popup;
protected Properties properties;
public DocumentView(InteractiveClient client, XmldbURI resourceName, Resource resource, Properties properties) throws XMLDBException {
super(URIUtils.urlDecodeUtf8(resourceName.lastSegment()));
this.resourceName = resourceName;
this.resource = resource;
this.client = client;
this.setIconImage(InteractiveClient.getExistIcon(getClass()).getImage());
this.collection = client.getCollection();
this.properties = properties;
getContentPane().setLayout(new BorderLayout());
setupComponents();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent ev) {
close();
}
});
pack();
}
public void viewDocument() {
try {
if ("XMLResource".equals(resource.getResourceType())) //$NON-NLS-1$
{
setText((String) resource.getContent());
} else {
setText(new String((byte[]) resource.getContent()));
}
// lock the resource for editing
final UserManagementService service = (UserManagementService)
client.current.getService("UserManagementService", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$
final Account user = service.getAccount(properties.getProperty("user")); //$NON-NLS-1$
final String lockOwner = service.hasUserLock(resource);
if (lockOwner != null) {
if (JOptionPane.showConfirmDialog(this,
Messages.getString("DocumentView.6") + lockOwner + //$NON-NLS-1$
Messages.getString("DocumentView.7"), //$NON-NLS-1$
Messages.getString("DocumentView.8"), //$NON-NLS-1$
JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) {
dispose();
this.setCursor(Cursor.getDefaultCursor());
return;
}
}
try {
service.lockResource(resource, user);
} catch (final XMLDBException ex) {
System.out.println(ex.getMessage());
JOptionPane.showMessageDialog(this,
Messages.getString("DocumentView.9")); //$NON-NLS-1$
setReadOnly();
}
setVisible(true);
} catch (final XMLDBException ex) {
showErrorMessage(Messages.getString("DocumentView.10") + ex.getMessage(), ex); //$NON-NLS-1$
}
}
private static void showErrorMessage(String message, Throwable t) {
JScrollPane scroll = null;
final JTextArea msgArea = new JTextArea(message);
msgArea.setBorder(BorderFactory.createTitledBorder("Message:")); //$NON-NLS-1$
msgArea.setEditable(false);
msgArea.setBackground(null);
if (t != null) {
final StringWriter out = new StringWriter();
final PrintWriter writer = new PrintWriter(out);
t.printStackTrace(writer);
final JTextArea stacktrace = new JTextArea(out.toString(), 20, 50);
stacktrace.setBackground(null);
stacktrace.setEditable(false);
scroll = new JScrollPane(stacktrace);
scroll.setPreferredSize(new Dimension(250, 300));
scroll.setBorder(BorderFactory
.createTitledBorder("Exception Stacktrace:")); //$NON-NLS-1$
}
final JOptionPane optionPane = new JOptionPane();
optionPane.setMessage(new Object[]{msgArea, scroll});
optionPane.setMessageType(JOptionPane.ERROR_MESSAGE);
final JDialog dialog = optionPane.createDialog(null, Messages.getString("DocumentView.13")); //$NON-NLS-1$
dialog.setResizable(true);
dialog.pack();
dialog.setVisible(true);
return;
}
public void setReadOnly() {
text.setEditable(false);
saveButton.setEnabled(false);
readOnly = true;
}
private void close() {
unlockView();
}
private void unlockView() {
if (readOnly) {
return;
}
try {
final UserManagementService service = (UserManagementService) collection
.getService("UserManagementService", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$
service.unlockResource(resource);
} catch (final XMLDBException e) {
e.printStackTrace();
}
}
private void setupComponents() throws XMLDBException {
/* start of menubar */
final JMenuBar menubar = new JMenuBar();
final JMenu fileMenu = new JMenu(Messages.getString("DocumentView.16")); //$NON-NLS-1$
fileMenu.setMnemonic(KeyEvent.VK_F);
menubar.add(fileMenu);
JMenuItem item;
// Save to database
item = new JMenuItem(Messages.getString("DocumentView.17"), KeyEvent.VK_S); //$NON-NLS-1$
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
item.addActionListener(e -> save());
fileMenu.add(item);
/*
// Refresh
item = new JMenuItem("Refresh", KeyEvent.VK_R);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R,
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
refresh() ;
} catch (XMLDBException u) {
u.printStackTrace();
}
}
});
fileMenu.add(item);
*/
setJMenuBar(menubar);
/* end of menubar */
/* The icon toolbar */
final JToolBar toolbar = new JToolBar();
//Save button
URL url = getClass().getResource("icons/Save24.gif"); //$NON-NLS-1$
saveButton = new JButton(new ImageIcon(url));
saveButton
.setToolTipText(Messages.getString("DocumentView.20")); //$NON-NLS-1$
saveButton.addActionListener(e -> save());
toolbar.add(saveButton);
//Save As button
url = getClass().getResource("icons/SaveAs24.gif"); //$NON-NLS-1$
saveAsButton = new JButton(new ImageIcon(url));
saveAsButton
.setToolTipText(Messages.getString("DocumentView.22")); //$NON-NLS-1$
saveAsButton.addActionListener(e -> saveAs());
toolbar.add(saveAsButton);
//Export button
url = getClass().getResource("icons/Export24.gif"); //$NON-NLS-1$
JButton button = new JButton(new ImageIcon(url));
button.setToolTipText(Messages.getString("DocumentView.24")); //$NON-NLS-1$
button.addActionListener(e -> {
try {
export();
} catch (final XMLDBException u) {
u.printStackTrace();
}
});
toolbar.add(button);
toolbar.addSeparator();
//Copy button
url = getClass().getResource("icons/Copy24.gif"); //$NON-NLS-1$
button = new JButton(new ImageIcon(url));
button.setToolTipText(Messages.getString("DocumentView.26")); //$NON-NLS-1$
button.addActionListener(e -> text.copy());
toolbar.add(button);
//Cut button
url = getClass().getResource("icons/Cut24.gif"); //$NON-NLS-1$
button = new JButton(new ImageIcon(url));
button.setToolTipText(Messages.getString("DocumentView.28")); //$NON-NLS-1$
button.addActionListener(e -> text.cut());
toolbar.add(button);
//Paste button
url = getClass().getResource("icons/Paste24.gif"); //$NON-NLS-1$
button = new JButton(new ImageIcon(url));
button.setToolTipText(Messages.getString("DocumentView.30")); //$NON-NLS-1$
button.addActionListener(e -> text.paste());
toolbar.add(button);
toolbar.addSeparator();
//Refresh button
url = getClass().getResource("icons/Refresh24.gif"); //$NON-NLS-1$
button = new JButton(new ImageIcon(url));
button.setToolTipText(Messages.getString("DocumentView.32")); //$NON-NLS-1$
button.addActionListener(e -> {
try {
refresh();
} catch (final XMLDBException u) {
u.printStackTrace();
}
});
toolbar.add(button);
getContentPane().add(toolbar, BorderLayout.NORTH);
text = new RSyntaxTextArea(14, 80);
text.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML);
text.setCodeFoldingEnabled(true);
textScrollPane = new RTextScrollPane(text);
getContentPane().add(textScrollPane, BorderLayout.CENTER);
final Box statusbar = Box.createHorizontalBox();
statusbar.setBorder(BorderFactory
.createBevelBorder(BevelBorder.LOWERED));
statusMessage = new JTextField(20);
statusMessage.setEditable(false);
statusMessage.setFocusable(false);
statusMessage.setText(Messages.getString("DocumentView.34") + URIUtils.urlDecodeUtf8(resource.getId()) + Messages.getString("DocumentView.35")); //$NON-NLS-1$ //$NON-NLS-2$
statusbar.add(statusMessage);
progress = new JProgressBar();
progress.setPreferredSize(new Dimension(200, 30));
progress.setVisible(false);
statusbar.add(progress);
positionDisplay = new JTextField(5);
positionDisplay.setEditable(false);
positionDisplay.setFocusable(true);
statusbar.add(positionDisplay);
text.addCaretListener(e -> {
final RSyntaxTextArea txt = (RSyntaxTextArea) e.getSource();
positionDisplay.setText("Line: " + (txt.getCaretLineNumber() + 1) + " Column:" + (txt.getCaretOffsetFromLineStart() + 1));
});
getContentPane().add(statusbar, BorderLayout.SOUTH);
}
private void save() {
final Runnable saveTask = () -> {
try {
statusMessage.setText(Messages.getString("DocumentView.36") + URIUtils.urlDecodeUtf8(resource.getId())); //$NON-NLS-1$
if (collection instanceof Observable) {
((Observable) collection)
.addObserver(new ProgressObserver());
}
progress.setIndeterminate(true);
progress.setVisible(true);
resource.setContent(text.getText());
collection.storeResource(resource);
if (collection instanceof Observable) {
((Observable) collection).deleteObservers();
}
} catch (final XMLDBException e) {
ClientFrame.showErrorMessage(Messages.getString("DocumentView.37") //$NON-NLS-1$
+ e.getMessage(), e);
} finally {
progress.setVisible(false);
}
};
client.newClientThread("save", saveTask).start();
}
private void saveAs() {
final Runnable saveAsTask = () -> {
//Get the name to save the resource as
final String nameres = JOptionPane.showInputDialog(null, Messages.getString("DocumentView.38")); //$NON-NLS-1$
if (nameres != null) {
try {
//Change status message and display a progress dialog
statusMessage.setText(Messages.getString("DocumentView.39") + nameres); //$NON-NLS-1$
if (collection instanceof Observable) {
((Observable) collection).addObserver(new ProgressObserver());
}
progress.setIndeterminate(true);
progress.setVisible(true);
//Create a new resource as named, set the content, store the resource
XMLResource result = null;
result = (XMLResource) collection.createResource(URIUtils.encodeXmldbUriFor(nameres).toString(), XMLResource.RESOURCE_TYPE);
result.setContent(text.getText());
collection.storeResource(result);
client.reloadCollection(); //reload the client collection
if (collection instanceof Observable) {
((Observable) collection).deleteObservers();
}
} catch (final XMLDBException e) {
ClientFrame.showErrorMessage(Messages.getString("DocumentView.40") + e.getMessage(), e); //$NON-NLS-1$
} catch (final URISyntaxException e) {
ClientFrame.showErrorMessage(Messages.getString("DocumentView.41") + e.getMessage(), e); //$NON-NLS-1$
} finally {
//hide the progress dialog
progress.setVisible(false);
}
}
};
client.newClientThread("save-as", saveAsTask).start();
}
private void export() throws XMLDBException {
final String workDir = properties.getProperty("working-dir", System.getProperty("user.dir"));
final JFileChooser chooser = new JFileChooser(workDir);
chooser.setMultiSelectionEnabled(false);
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.setSelectedFile(Paths.get(resource.getId()).toFile());
if (chooser.showDialog(this, Messages.getString("DocumentView.44")) == JFileChooser.APPROVE_OPTION) {
final File file = chooser.getSelectedFile();
if (file.exists()
&& JOptionPane.showConfirmDialog(this,
Messages.getString("DocumentView.45"), Messages.getString("DocumentView.46"),
JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
return;
}
final Charset encoding = Charset.forName(properties.getProperty("encoding"));
try (final Writer writer = Files.newBufferedWriter(file.toPath(), encoding)) {
writer.write(text.getText());
} catch (final IOException e) {
ClientFrame.showErrorMessage(Messages.getString("DocumentView.48") + e.getMessage(), e);
}
final File selectedDir = chooser.getCurrentDirectory();
properties.setProperty("working-dir", selectedDir.getAbsolutePath());
}
}
private void refresh() throws XMLDBException {
//First unlock the resource
unlockView();
//Reload the resource
this.resource = client.retrieve(resourceName, properties.getProperty(OutputKeys.INDENT, "yes")); //$NON-NLS-1$
//View and lock the resource
viewDocument();
}
public void setText(String content) throws XMLDBException {
text.setText(content);
text.setCaretPosition(0);
statusMessage.setText(Messages.getString("DocumentView.52") + XmldbURI.create(client.getCollection().getName()).append(resourceName) + Messages.getString("DocumentView.53") + properties.getProperty("uri")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
class ProgressObserver implements Observer {
public void update(Observable o, Object arg) {
progress.setIndeterminate(false);
final ProgressIndicator ind = (ProgressIndicator) arg;
progress.setValue(ind.getPercentage());
if (o instanceof ElementIndex) {
progress.setString("Storing elements"); //$NON-NLS-1$
} else {
progress.setString("Storing nodes"); //$NON-NLS-1$
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy