From 85d5c89f25bed4fc3002eaaaa98e7ca4992fa2d6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Sat, 29 Sep 2007 12:11:36 +0000 Subject: [PATCH] try to close all streams as soon as possible to prevent leaks (inserting large sites is not a problem anymore) update about dialog to 2007 --- .../jsite/application/ProjectInserter.java | 67 ++++---- src/de/todesbaum/jsite/i18n/jSite.properties | 2 +- src/de/todesbaum/jsite/i18n/jSite_de.properties | 2 +- src/de/todesbaum/jsite/i18n/jSite_fr.properties | 2 +- src/de/todesbaum/jsite/main/Main.java | 3 - src/de/todesbaum/jsite/main/Version.java | 2 +- .../util/freenet/fcp2/ClientPutComplexDir.java | 50 +++++- src/de/todesbaum/util/freenet/fcp2/Connection.java | 9 +- src/de/todesbaum/util/io/Closer.java | 189 +++++++++++++++++++++ 9 files changed, 275 insertions(+), 51 deletions(-) create mode 100644 src/de/todesbaum/util/io/Closer.java diff --git a/src/de/todesbaum/jsite/application/ProjectInserter.java b/src/de/todesbaum/jsite/application/ProjectInserter.java index b51dd0c..1b0021a 100644 --- a/src/de/todesbaum/jsite/application/ProjectInserter.java +++ b/src/de/todesbaum/jsite/application/ProjectInserter.java @@ -43,6 +43,7 @@ import de.todesbaum.util.freenet.fcp2.FileEntry; import de.todesbaum.util.freenet.fcp2.Message; import de.todesbaum.util.freenet.fcp2.RedirectFileEntry; import de.todesbaum.util.freenet.fcp2.Verbosity; +import de.todesbaum.util.io.Closer; import de.todesbaum.util.io.ReplacingOutputStream; import de.todesbaum.util.io.StreamCopier; @@ -131,15 +132,19 @@ public class ProjectInserter implements FileScannerListener, Runnable { ByteArrayOutputStream filteredByteOutputStream = new ByteArrayOutputStream(Math.min(Integer.MAX_VALUE, (int) length[0])); ReplacingOutputStream outputStream = new ReplacingOutputStream(filteredByteOutputStream); FileInputStream fileInput = new FileInputStream(file); - outputStream.addReplacement("$[EDITION]", String.valueOf(edition)); - outputStream.addReplacement("$[URI]", project.getFinalRequestURI(0)); - for (int index = 1; index <= fileOption.getEditionRange(); index++) { - outputStream.addReplacement("$[URI+" + index + "]", project.getFinalRequestURI(index)); - outputStream.addReplacement("$[EDITION+" + index + "]", String.valueOf(edition + index)); + try { + outputStream.addReplacement("$[EDITION]", String.valueOf(edition)); + outputStream.addReplacement("$[URI]", project.getFinalRequestURI(0)); + for (int index = 1; index <= fileOption.getEditionRange(); index++) { + outputStream.addReplacement("$[URI+" + index + "]", project.getFinalRequestURI(index)); + outputStream.addReplacement("$[EDITION+" + index + "]", String.valueOf(edition + index)); + } + StreamCopier.copy(fileInput, outputStream, length[0]); + } finally { + Closer.close(fileInput); + Closer.close(outputStream); + Closer.close(filteredByteOutputStream); } - StreamCopier.copy(fileInput, outputStream, length[0]); - outputStream.close(); - filteredByteOutputStream.close(); byte[] filteredBytes = filteredByteOutputStream.toByteArray(); length[0] = filteredBytes.length; return new ByteArrayInputStream(filteredBytes); @@ -150,35 +155,27 @@ public class ProjectInserter implements FileScannerListener, Runnable { tempFile.deleteOnExit(); FileOutputStream fileOutputStream = new FileOutputStream(tempFile); ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream); - for (String filename: containerFiles.get(containerName)) { - File dataFile = new File(project.getLocalPath(), filename); - if (dataFile.exists()) { - ZipEntry zipEntry = new ZipEntry(filename); - long[] fileLength = new long[1]; - InputStream wrappedInputStream = createFileInputStream(filename, project.getFileOption(filename), edition, fileLength); - zipOutputStream.putNextEntry(zipEntry); - StreamCopier.copy(wrappedInputStream, zipOutputStream, fileLength[0]); - zipOutputStream.closeEntry(); - wrappedInputStream.close(); + try { + for (String filename: containerFiles.get(containerName)) { + File dataFile = new File(project.getLocalPath(), filename); + if (dataFile.exists()) { + ZipEntry zipEntry = new ZipEntry(filename); + long[] fileLength = new long[1]; + InputStream wrappedInputStream = createFileInputStream(filename, project.getFileOption(filename), edition, fileLength); + try { + zipOutputStream.putNextEntry(zipEntry); + StreamCopier.copy(wrappedInputStream, zipOutputStream, fileLength[0]); + } finally { + zipOutputStream.closeEntry(); + wrappedInputStream.close(); + } + } } + } finally { + zipOutputStream.closeEntry(); + Closer.close(zipOutputStream); + Closer.close(fileOutputStream); } - zipOutputStream.closeEntry(); - - /* FIXME - create metadata */ - // ZipEntry metadataEntry = new ZipEntry("metadata"); - // zipOutputStream.putNextEntry(metadataEntry); - // Metadata zipMetadata = new Metadata(); - // for (String filename: containerFiles.get(containerName)) { - // if (new File(project.getLocalPath(), filename).exists()) { - // DocumentMetadata zipEntryMetadata = new DocumentMetadata(); - // zipEntryMetadata.setName(filename); - // zipEntryMetadata.setFormat(project.getFileOption(filename).getMimeType()); - // zipMetadata.addDocument(zipEntryMetadata); - // } - // } - // zipOutputStream.write(zipMetadata.toByteArray()); - // zipOutputStream.closeEntry(); - zipOutputStream.close(); containerLength[0] = tempFile.length(); return new FileInputStream(tempFile); diff --git a/src/de/todesbaum/jsite/i18n/jSite.properties b/src/de/todesbaum/jsite/i18n/jSite.properties index f3a0f2a..8bf151c 100644 --- a/src/de/todesbaum/jsite/i18n/jSite.properties +++ b/src/de/todesbaum/jsite/i18n/jSite.properties @@ -38,7 +38,7 @@ jsite.menu.nodes.manage-nodes=Manage nodes jsite.menu.help=Help jsite.menu.help.about=About -jsite.about.message=jSite {0}

Copyright \u00a9 2006 David Roden
Released under the GNU General Public License +jsite.about.message=jSite {0}

Copyright \u00a9 2006, 2007 David Roden
Released under the GNU General Public License jsite.node-manager.heading=Node Manager jsite.node-manager.description=Manage your nodes here. diff --git a/src/de/todesbaum/jsite/i18n/jSite_de.properties b/src/de/todesbaum/jsite/i18n/jSite_de.properties index 11b7519..12607f8 100644 --- a/src/de/todesbaum/jsite/i18n/jSite_de.properties +++ b/src/de/todesbaum/jsite/i18n/jSite_de.properties @@ -38,7 +38,7 @@ jsite.menu.nodes.manage-nodes=Nodes verwalten jsite.menu.help=Hilfe jsite.menu.help.about=Über -jsite.about.message=jSite {0}

Copyright \u00a9 2006 David Roden
Veröffentlicht unter der GNU General Public License +jsite.about.message=jSite {0}

Copyright \u00a9 2006, 2007 David Roden
Veröffentlicht unter der GNU General Public License jsite.node-manager.heading=Nodeverwaltung jsite.node-manager.description=Verwalten Sie hier Ihre Nodes. diff --git a/src/de/todesbaum/jsite/i18n/jSite_fr.properties b/src/de/todesbaum/jsite/i18n/jSite_fr.properties index c298090..51357b6 100644 --- a/src/de/todesbaum/jsite/i18n/jSite_fr.properties +++ b/src/de/todesbaum/jsite/i18n/jSite_fr.properties @@ -38,7 +38,7 @@ jsite.menu.nodes.manage-nodes=G jsite.menu.help=Aide jsite.menu.help.about=A propos de jSite -jsite.about.message=jSite {0}

Copyright \u00a9 2006 David Roden
Released under the GNU General Public License +jsite.about.message=jSite {0}

Copyright \u00a9 2006, 2007 David Roden
Released under the GNU General Public License jsite.node-manager.heading=Gestionnaire de noeud jsite.node-manager.description=Gérez vos noeuds. diff --git a/src/de/todesbaum/jsite/main/Main.java b/src/de/todesbaum/jsite/main/Main.java index 3a62d9a..2ed3bfd 100644 --- a/src/de/todesbaum/jsite/main/Main.java +++ b/src/de/todesbaum/jsite/main/Main.java @@ -415,9 +415,6 @@ public class Main implements ActionListener, ListSelectionListener, WizardListen // MAIN METHOD // public static void main(String[] args) { - System.setProperty("swing.plaf.metal.userFont", "Tahoma"); - System.setProperty("swing.plaf.metal.controlFont", "Tahoma"); - System.setProperty("swing.aatext", "true"); String configFilename = null; boolean nextIsConfigFilename = false; for (String argument: args) { diff --git a/src/de/todesbaum/jsite/main/Version.java b/src/de/todesbaum/jsite/main/Version.java index 9f02248..44c724a 100644 --- a/src/de/todesbaum/jsite/main/Version.java +++ b/src/de/todesbaum/jsite/main/Version.java @@ -25,7 +25,7 @@ package de.todesbaum.jsite.main; */ public class Version { - private static final String VERSION = "0.4.8.1"; + private static final String VERSION = "0.4.8.2-pre-1"; public static final String getVersion() { return VERSION; diff --git a/src/de/todesbaum/util/freenet/fcp2/ClientPutComplexDir.java b/src/de/todesbaum/util/freenet/fcp2/ClientPutComplexDir.java index 2feec72..d645bb1 100644 --- a/src/de/todesbaum/util/freenet/fcp2/ClientPutComplexDir.java +++ b/src/de/todesbaum/util/freenet/fcp2/ClientPutComplexDir.java @@ -19,13 +19,17 @@ package de.todesbaum.util.freenet.fcp2; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.SequenceInputStream; import java.io.Writer; import java.util.ArrayList; import java.util.List; -import java.util.Vector; + +import de.todesbaum.util.io.Closer; /** * Implementation of the ClientPutComplexDir command. This @@ -43,7 +47,7 @@ public class ClientPutComplexDir extends ClientPutDir { private boolean hasPayload = false; /** The input streams for the payload. */ - private List payloadInputStreams = new ArrayList(); + private File payloadFile; /** The total number of bytes of the payload. */ private long payloadLength = 0; @@ -62,7 +66,33 @@ public class ClientPutComplexDir extends ClientPutDir { * @param fileEntry The file entry to add to the directory */ public void addFileEntry(FileEntry fileEntry) { - fileEntries.add(fileEntry); + if (payloadFile == null){ + try { + payloadFile = File.createTempFile("payload", ".dat"); + payloadFile.deleteOnExit(); + } catch (IOException e) { + } + } + if (payloadFile != null) { + InputStream payloadInputStream = ((DirectFileEntry) fileEntry).getDataInputStream(); + FileOutputStream payloadOutputStream = null; + try { + payloadOutputStream = new FileOutputStream(payloadFile, true); + byte[] buffer = new byte[65536]; + int read = 0; + while ((read = payloadInputStream.read(buffer)) != -1) { + payloadOutputStream.write(buffer, 0, read); + System.out.println("writing " + read + " bytes"); + } + payloadOutputStream.flush(); + fileEntries.add(fileEntry); + } catch (IOException ioe1) { + /* hmm, ignore? */ + } finally { + Closer.close(payloadOutputStream); + Closer.close(payloadInputStream); + } + } } /** @@ -82,7 +112,6 @@ public class ClientPutComplexDir extends ClientPutDir { hasPayload = true; writer.write("Files." + fileIndex + ".DataLength=" + ((DirectFileEntry) fileEntry).getDataLength() + LINEFEED); payloadLength += ((DirectFileEntry) fileEntry).getDataLength(); - payloadInputStreams.add(((DirectFileEntry) fileEntry).getDataInputStream()); } else if (fileEntry instanceof DiskFileEntry) { writer.write("Files." + fileIndex + ".Filename=" + ((DiskFileEntry) fileEntry).getFilename() + LINEFEED); } else if (fileEntry instanceof RedirectFileEntry) { @@ -113,9 +142,14 @@ public class ClientPutComplexDir extends ClientPutDir { */ @Override protected InputStream getPayload() { - /* grr. use Vector here because it returns an Enumeration. */ - Vector inputStreams = new Vector(payloadInputStreams); - return new SequenceInputStream(inputStreams.elements()); + if (payloadFile != null) { + try { + return new FileInputStream(payloadFile); + } catch (FileNotFoundException e) { + /* shouldn't occur. */ + } + } + return null; } } diff --git a/src/de/todesbaum/util/freenet/fcp2/Connection.java b/src/de/todesbaum/util/freenet/fcp2/Connection.java index 848ee86..9932d25 100644 --- a/src/de/todesbaum/util/freenet/fcp2/Connection.java +++ b/src/de/todesbaum/util/freenet/fcp2/Connection.java @@ -31,6 +31,7 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; +import de.todesbaum.util.io.Closer; import de.todesbaum.util.io.LineInputStream; import de.todesbaum.util.io.StreamCopier; import de.todesbaum.util.io.TempFileInputStream; @@ -253,7 +254,13 @@ public class Connection { nodeWriter.write("EndMessage" + Command.LINEFEED); nodeWriter.flush(); if (command.hasPayload()) { - StreamCopier.copy(command.getPayload(), nodeOutputStream, command.getPayloadLength()); + InputStream payloadInputStream = null; + try { + payloadInputStream = command.getPayload(); + StreamCopier.copy(payloadInputStream, nodeOutputStream, command.getPayloadLength()); + } finally { + Closer.close(payloadInputStream); + } nodeOutputStream.flush(); } } diff --git a/src/de/todesbaum/util/io/Closer.java b/src/de/todesbaum/util/io/Closer.java new file mode 100644 index 0000000..b4481ac --- /dev/null +++ b/src/de/todesbaum/util/io/Closer.java @@ -0,0 +1,189 @@ +/* + * todesbaum-lib - Copyright (C) 2006 David Roden + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU 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 General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package de.todesbaum.util.io; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.net.ServerSocket; +import java.net.Socket; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * Helper class that can close all kinds of resources without throwing exception + * so that clean-up code can be written with less code. All methods check that + * the given resource is not null before invoking the close() + * method of the respective type. + * + * @author David ‘Bombe&squo; + * Roden + * @version $Id$ + */ +public class Closer { + + /** + * Closes the given result set. + * + * @param resultSet + * The result set to close + * @see ResultSet#close() + */ + public static void close(ResultSet resultSet) { + if (resultSet != null) { + try { + resultSet.close(); + } catch (SQLException ioe1) { + } + } + } + + /** + * Closes the given statement. + * + * @param statement + * The statement to close + * @see Statement#close() + */ + public static void close(Statement statement) { + if (statement != null) { + try { + statement.close(); + } catch (SQLException ioe1) { + } + } + } + + /** + * Closes the given connection. + * + * @param connection + * The connection to close + * @see Connection#close() + */ + public static void close(Connection connection) { + if (connection != null) { + try { + connection.close(); + } catch (SQLException ioe1) { + } + } + } + + /** + * Closes the given server socket. + * + * @param serverSocket + * The server socket to close + * @see ServerSocket#close() + */ + public static void close(ServerSocket serverSocket) { + if (serverSocket != null) { + try { + serverSocket.close(); + } catch (IOException ioe1) { + } + } + } + + /** + * Closes the given socket. + * + * @param socket + * The socket to close + * @see Socket#close() + */ + public static void close(Socket socket) { + if (socket != null) { + try { + socket.close(); + } catch (IOException ioe1) { + } + } + } + + /** + * Closes the given input stream. + * + * @param inputStream + * The input stream to close + * @see InputStream#close() + */ + public static void close(InputStream inputStream) { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException ioe1) { + } + } + } + + /** + * Closes the given output stream. + * + * @param outputStream + * The output stream to close + * @see OutputStream#close() + */ + public static void close(OutputStream outputStream) { + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException ioe1) { + } + } + } + + /** + * Closes the given reader. + * + * @param reader + * The reader to close + * @see Reader#close() + */ + public static void close(Reader reader) { + if (reader != null) { + try { + reader.close(); + } catch (IOException ioe1) { + } + } + } + + /** + * Closes the given writer. + * + * @param writer + * The write to close + * @see Writer#close() + */ + public static void close(Writer writer) { + if (writer != null) { + try { + writer.close(); + } catch (IOException ioe1) { + } + } + } + +} -- 2.7.4