# HG changeset patch # User matthias42@netbeans.org # Date 1324234389 -3600 # Node ID 6030c674e4f0d5e4228e9274dc28e54eea0de14f # Parent 766630c4d04adc3e89a43455f4fee9b78d219469 Add progress dialog for (estimated) long transfers when saving/loading BLOB/CLOB data diff --git a/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/BlobFieldTableCellEditor.java b/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/BlobFieldTableCellEditor.java --- a/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/BlobFieldTableCellEditor.java +++ b/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/BlobFieldTableCellEditor.java @@ -51,6 +51,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.sql.Blob; import java.sql.SQLException; import java.util.EventObject; @@ -62,8 +63,8 @@ import javax.swing.JTable; import javax.swing.SwingConstants; import javax.swing.table.TableCellEditor; +import org.netbeans.api.progress.ProgressUtils; import org.netbeans.modules.db.dataview.util.FileBackedBlob; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; public class BlobFieldTableCellEditor extends AbstractCellEditor @@ -181,30 +182,17 @@ try { is = b.getBinaryStream(); fos = new FileOutputStream(f); - int read = 0; - byte[] buffer = new byte[1024]; - while((read = is.read(buffer)) > 0) { - fos.write(buffer, 0, read); + if(! doTransfer(is, fos, (int) b.length(), "Saving to file: " + f.toString())) { + f.delete(); } } catch (IOException ex) { throw new RuntimeException(ex); } catch (SQLException ex) { throw new RuntimeException(ex); - } finally { - try { - if(fos != null) fos.close(); - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } - try { - if(is != null) is.close(); - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } } } } - + private Blob loadLobFromFile() { JFileChooser c = new JFileChooser(); Blob result = null; @@ -214,19 +202,38 @@ FileInputStream fis = null; try { fis = new FileInputStream(f); - result = new FileBackedBlob(fis); + result = new FileBackedBlob(); + if(! doTransfer(fis, result.setBinaryStream(1), (int) f.length(), "Loading file: " + f.toString())) { + result = null; + } } catch (IOException ex) { throw new RuntimeException(ex); } catch (SQLException ex) { throw new RuntimeException(ex); - } finally { - try { - if(fis != null) fis.close(); - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } } } return result; } + + /** + * @return true if transfer is complete and not iterrupted + */ + private boolean doTransfer(InputStream is, OutputStream os, Integer size, String title) throws IOException { + MonitorableStreamTransfer ft = new MonitorableStreamTransfer(is, os, size); + Throwable t = null; + // Only show dialog, if the filesize is large enougth and has a use for the user + if (size == null || size > (1024 * 1024)) { + t = ProgressUtils.showProgressDialogAndRun(ft, title, false); + } else { + t = ft.run(null); + } + if (t != null && t instanceof RuntimeException) { + throw (RuntimeException) t; + } else if (t != null && t instanceof IOException) { + throw (IOException) t; + } else if (t != null) { + throw new RuntimeException(t); + } + return !ft.isCancel(); + } } \ No newline at end of file diff --git a/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/ClobFieldTableCellEditor.java b/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/ClobFieldTableCellEditor.java --- a/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/ClobFieldTableCellEditor.java +++ b/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/ClobFieldTableCellEditor.java @@ -73,6 +73,7 @@ import javax.swing.JTable; import javax.swing.SwingConstants; import javax.swing.table.TableCellEditor; +import org.netbeans.api.progress.ProgressUtils; import org.netbeans.modules.db.dataview.util.FileBackedClob; import org.openide.util.Exceptions; import org.openide.util.NbBundle; @@ -83,7 +84,7 @@ private class CharsetSelector extends JPanel { private JComboBox charsetSelect; - + CharsetSelector() { List charset = new ArrayList(Charset.availableCharsets().values()); Collections.sort(charset, new Comparator() { @@ -106,7 +107,6 @@ charsetSelect.setSelectedItem(selectedCharset); } } - protected static final String EDIT = "edit"; protected Clob currentValue; protected JButton button; @@ -207,7 +207,7 @@ } return super.isCellEditable(anEvent); } - + private void saveLobToFile(Clob b) { CharsetSelector charset = new CharsetSelector(); JFileChooser c = new JFileChooser(); @@ -220,30 +220,17 @@ try { r = b.getCharacterStream(); w = new OutputStreamWriter(new FileOutputStream(f), charset.getSelectedCharset()); - int read = 0; - char[] buffer = new char[1024]; - while((read = r.read(buffer)) > 0) { - w.write(buffer, 0, read); + if(! doTransfer(r, w, (int) b.length(), "Save to file: " + f.toString(), false)) { + f.delete(); } } catch (IOException ex) { throw new RuntimeException(ex); } catch (SQLException ex) { throw new RuntimeException(ex); - } finally { - try { - if(w != null) w.close(); - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } - try { - if(r != null) r.close(); - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } } } } - + private Clob loadLobFromFile() { CharsetSelector charset = new CharsetSelector(); JFileChooser c = new JFileChooser(); @@ -254,20 +241,40 @@ File f = c.getSelectedFile(); Reader r = null; try { + result = new FileBackedClob(); r = new InputStreamReader(new FileInputStream(f), charset.getSelectedCharset()); - result = new FileBackedClob(r); + if(! doTransfer(r, result.setCharacterStream(1), (int) f.length() / 2, "Load from file: " + f.toString(), true)) { + result = null; + } } catch (IOException ex) { throw new RuntimeException(ex); } catch (SQLException ex) { throw new RuntimeException(ex); - } finally { - try { - if(r != null) r.close(); - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } } } return result; } + + /** + * @return true if transfer is complete and not iterrupted + */ + private boolean doTransfer(Reader in, Writer out, Integer size, String title, boolean sizeEstimated) throws IOException { + // Only pass size if it is _not_ estimated + MonitorableCharacterStreamTransfer ft = new MonitorableCharacterStreamTransfer(in, out, sizeEstimated ? null : size); + Throwable t = null; + // Only show dialog, if the filesize is large enougth and has a use for the user + if (size == null || size > (1024 * 1024)) { + t = ProgressUtils.showProgressDialogAndRun(ft, title, false); + } else { + t = ft.run(null); + } + if (t != null && t instanceof RuntimeException) { + throw (RuntimeException) t; + } else if (t != null && t instanceof IOException) { + throw (IOException) t; + } else if (t != null) { + throw new RuntimeException(t); + } + return ! ft.isCancel(); + } } diff --git a/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/MonitorableCharacterStreamTransfer.java b/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/MonitorableCharacterStreamTransfer.java new file mode 100644 --- /dev/null +++ b/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/MonitorableCharacterStreamTransfer.java @@ -0,0 +1,110 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.modules.db.dataview.table.celleditor; + +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import org.netbeans.api.progress.ProgressHandle; +import org.netbeans.api.progress.ProgressRunnable; +import org.openide.util.Cancellable; + +class MonitorableCharacterStreamTransfer implements ProgressRunnable, Cancellable { + + private Reader in; + private Writer out; + private int transfered; + private Integer size; + private boolean cancel; + + public MonitorableCharacterStreamTransfer(Reader in, Writer out, Integer knownsize) { + this.in = in; + this.out = out; + size = knownsize; + } + + @Override + public Exception run(ProgressHandle handle) { + Exception result = null; + if (handle != null && size != null) { + handle.switchToDeterminate(size); + } + try { + int read = 0; + char[] buffer = new char[128 * 1024]; + while ((read = in.read(buffer)) > 0 && !cancel) { + out.write(buffer, 0, read); + transfered += read; + if (handle != null && size != null) { + handle.progress(transfered); + } + } + } catch (IOException ex) { + try { + in.close(); + } catch (IOException ex2) { + } + try { + out.close(); + } catch (IOException ex2) { + } + return ex; + } + if (handle != null) { + handle.finish(); + } + return result; + } + + @Override + public boolean cancel() { + if (cancel) { + return false; + } + this.cancel = true; + return true; + } + + public boolean isCancel() { + return cancel; + } +} diff --git a/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/MonitorableStreamTransfer.java b/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/MonitorableStreamTransfer.java new file mode 100644 --- /dev/null +++ b/db.dataview/src/org/netbeans/modules/db/dataview/table/celleditor/MonitorableStreamTransfer.java @@ -0,0 +1,110 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.modules.db.dataview.table.celleditor; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import org.netbeans.api.progress.ProgressHandle; +import org.netbeans.api.progress.ProgressRunnable; +import org.openide.util.Cancellable; + +class MonitorableStreamTransfer implements ProgressRunnable, Cancellable { + + private InputStream is; + private OutputStream os; + private int transfered; + private Integer size; + private boolean cancel; + + public MonitorableStreamTransfer(InputStream is, OutputStream os, Integer knownsize) { + this.is = is; + this.os = os; + size = knownsize; + } + + @Override + public Exception run(ProgressHandle handle) { + Exception result = null; + if (handle != null && size != null) { + handle.switchToDeterminate(size); + } + try { + int read = 0; + byte[] buffer = new byte[256 * 1024]; + while ((read = is.read(buffer)) > 0 && !cancel) { + os.write(buffer, 0, read); + transfered += read; + if (handle != null && size != null) { + handle.progress(transfered); + } + } + } catch (IOException ex) { + try { + is.close(); + } catch (IOException ex2) { + } + try { + os.close(); + } catch (IOException ex2) { + } + return ex; + } + if (handle != null) { + handle.finish(); + } + return result; + } + + @Override + public boolean cancel() { + if (cancel) { + return false; + } + this.cancel = true; + return true; + } + + public boolean isCancel() { + return cancel; + } +}