/* * HomeFileRecorder.java 30 aout 2006 * * Sweet Home 3D, Copyright (c) 2006 Emmanuel PUYBARET / eTeks <info@eteks.com> * * 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 com.eteks.sweethome3d.io; 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.InterruptedIOException; import java.io.OutputStream; import com.eteks.sweethome3d.model.Home; import com.eteks.sweethome3d.model.HomeRecorder; import com.eteks.sweethome3d.model.InterruptedRecorderException; import com.eteks.sweethome3d.model.RecorderException; import com.eteks.sweethome3d.tools.OperatingSystem; /** * Recorder that stores homes in files with {@link DefaultHomeOutputStream} and * {@link DefaultHomeInputStream}. * @author Emmanuel Puybaret */ public class HomeFileRecorder implements HomeRecorder { private final int compressionLevel; private final boolean includeOnlyTemporaryContent; /** * Creates a home recorder able to write and read homes in uncompressed files. */ public HomeFileRecorder() { this(0); } /** * Creates a home recorder able to write and read homes in files compressed * at a level from 0 to 9. * @param compressionLevel 0 (uncompressed) to 9 (compressed). */ public HomeFileRecorder(int compressionLevel) { this(compressionLevel, false); } /** * Creates a home recorder able to write and read homes in files compressed * at a level from 0 to 9. * @param compressionLevel 0-9 * @param includeOnlyTemporaryContent if <code>true</code>, content instances of * <code>TemporaryURLContent</code> class referenced by the saved home * as well as the content previously saved with it will be written. * If <code>false</code>, all the content instances * referenced by the saved home will be written in the zip stream. */ public HomeFileRecorder(int compressionLevel, boolean includeOnlyTemporaryContent) { this.compressionLevel = compressionLevel; this.includeOnlyTemporaryContent = includeOnlyTemporaryContent; } /** * Writes home data. * @throws RecorderException if a problem occurred while writing home. */ public void writeHome(Home home, String name) throws RecorderException { File homeFile = new File(name); if (homeFile.exists() && !homeFile.canWrite()) { throw new RecorderException("Can't write over file " + name); } DefaultHomeOutputStream homeOut = null; File tempFile = null; try { // Open a stream on a temporary file tempFile = OperatingSystem.createTemporaryFile("save", ".sweethome3d"); homeOut = new DefaultHomeOutputStream(new FileOutputStream(tempFile), this.compressionLevel, this.includeOnlyTemporaryContent); // Write home with HomeOuputStream homeOut.writeHome(home); } catch (InterruptedIOException ex) { throw new InterruptedRecorderException("Save " + name + " interrupted"); } catch (IOException ex) { throw new RecorderException("Can't save home " + name, ex); } finally { try { if (homeOut != null) { homeOut.close(); } } catch (IOException ex) { throw new RecorderException("Can't close temporary file " + name, ex); } } // Open destination file OutputStream out; try { out = new FileOutputStream(homeFile); } catch (FileNotFoundException ex) { if (tempFile != null) { tempFile.delete(); } throw new RecorderException("Can't save file " + name, ex); } // Copy temporary file to home file // Overwriting home file will ensure that its rights are kept byte [] buffer = new byte [8192]; InputStream in = null; try { in = new FileInputStream(tempFile); int size; while ((size = in.read(buffer)) != -1) { out.write(buffer, 0, size); } } catch (IOException ex) { throw new RecorderException("Can't copy file " + tempFile + " to " + name); } finally { try { if (out != null) { out.close(); } } catch (IOException ex) { throw new RecorderException("Can't close file " + name, ex); } try { if (in != null) { in.close(); tempFile.delete(); } } catch (IOException ex) { // Forget exception } } } /** * Returns a home instance read from its file <code>name</code>. * @throws RecorderException if a problem occurred while reading home, * or if file <code>name</code> doesn't exist. */ public Home readHome(String name) throws RecorderException { DefaultHomeInputStream in = null; try { // Open a stream on file in = new DefaultHomeInputStream(new FileInputStream(name)); // Read home with HomeInputStream Home home = in.readHome(); return home; } catch (InterruptedIOException ex) { throw new InterruptedRecorderException("Read " + name + " interrupted"); } catch (IOException ex) { throw new RecorderException("Can't read home from " + name, ex); } catch (ClassNotFoundException ex) { throw new RecorderException("Missing classes to read home from " + name, ex); } finally { try { if (in != null) { in.close(); } } catch (IOException ex) { throw new RecorderException("Can't close file " + name, ex); } } } /** * Returns <code>true</code> if the file <code>name</code> exists. */ public boolean exists(String name) throws RecorderException { return new File(name).exists(); } }