Java tutorial
/** * Copyright (C) 2000 - 2012 Silverpeas * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * As a special exception to the terms and conditions of version 3.0 of the GPL, you may * redistribute this Program in connection with Free/Libre Open Source Software ("FLOSS") * applications as described in Silverpeas's FLOSS exception. You should have received a copy of the * text describing the FLOSS exception, and it is also available here: * "http://www.silverpeas.org/docs/core/legal/floss_exception.html" * * 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 * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see <http://www.gnu.org/licenses/>. */ package org.silverpeas.applicationbuilder; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.jar.JarOutputStream; import java.util.zip.ZipEntry; import org.apache.commons.io.IOUtils; import org.silverpeas.util.Console; /** * Convenient class for building archive * * @author Silverpeas * @version 1.0/B * @since 1.0/B */ public class WriteOnlyArchive extends ApplicationBuilderItem { protected Console console; protected static final String MANIFEST_PATH = "META-INF" + File.separator + "MANIFEST.MF"; private Set<String> alreadyAddedDirs = new HashSet<String>(); private Map<String, String> alreadyAddedFiles = new HashMap<String, String>(); private JarOutputStream jarOut = null; /** * Builder for a write only archive. * * @param directory The absolute path to the directory hosting the archive * @param fileName The name of the archive in the file system * @since 1.0 */ public WriteOnlyArchive(File directory, String fileName, Console sonsole) throws AppBuilderException { super(directory, fileName); this.console = console; setOutputStream(); } /** * Adds an XML file in the archive by the means of streams. * * @param xmlDoc the XML document to add in the archive * @since 1.0 * @roseuid 3AAF4D630303 */ public void add(XmlDocument xmlDoc) throws AppBuilderException { try { addDirectory(xmlDoc.getLocation()); ZipEntry entry = getNormalizedEntry(xmlDoc.getArchivePath()); entry.setSize(xmlDoc.getDocumentSize()); jarOut.putNextEntry(entry); xmlDoc.saveTo(getOutputStream()); getOutputStream().flush(); getOutputStream().closeEntry(); } catch (Exception e) { throw new AppBuilderException( getName() + " : impossible to add the document \"" + xmlDoc.getArchivePath() + '"', e); } } /** * Adds an entry to the archive. The entry added is fetched from the file system * * @param entry the file to add * @since 1.0 * @roseuid 3AAF55F2017D */ public void add(ApplicationBuilderItem entry) throws AppBuilderException { try { add(entry, entry.getPath().toURI().toURL().openStream()); } catch (MalformedURLException mue) { throw new AppBuilderException(getName() + " : could not add \"" + entry.getName() + '"', mue); } catch (IOException ioe) { throw new AppBuilderException(getName() + " : could not add \"" + entry.getName() + '"', ioe); } } /** * Merges an archive with this archive. * * @param archive the archive to merge * @since 1.0 */ public void mergeWith(ReadOnlyArchive archive) throws AppBuilderException { mergeWith(archive, (Set) null); } /** * Merges an archive with this archive filtering the entries to exclude one of them. * * @param archive the archive to merge * @param entryToExclude the entry to exclude from merge. Contains the archive path of the entry * to exclude. * @since 1.0 */ public void mergeWith(ReadOnlyArchive archive, String entryToExclude) throws AppBuilderException { Set<String> excludeSet = new HashSet<String>(1); excludeSet.add(entryToExclude); mergeWith(archive, excludeSet); } /** * Merges an archive with this archive filtering the entries to exclude some of them. * * @param archive the archive to merge * @param entriesToExclude the entries to exclude from merge. Contains the archive paths of the * entries to exclude. * @throws AppBuilderException */ public void mergeWith(ReadOnlyArchive archive, Set<String> entriesToExclude) throws AppBuilderException { ApplicationBuilderItem[] entries = archive.getEntries(); boolean filterOn = ((entriesToExclude != null) && (!entriesToExclude.isEmpty())); for (ApplicationBuilderItem myEntry : entries) { if (!filterOn || !entriesToExclude.contains(myEntry.getArchivePath())) { if (alreadyAddedFiles.containsKey(myEntry.getArchivePath())) { console.printMessage( getName() + " : already added from \"" + alreadyAddedFiles.get(myEntry.getArchivePath()) + "\" : \"" + archive.getName() + '!' + myEntry.getArchivePath() + "\" "); } else { alreadyAddedFiles.put(myEntry.getArchivePath(), archive.getName()); InputStream contents = archive.getEntry(myEntry); try { add(myEntry, contents); } finally { IOUtils.closeQuietly(contents); } } } } } /** * When all entries have been added, call this method to close the archive * * @roseuid 3AB1EAFE02FD */ public void close() throws AppBuilderException { try { getOutputStream().close(); } catch (Exception e) { throw new AppBuilderException("Impossible to close the stream", e); } } /** * Adds a new entry from a stream. The entry is placed and named according to the entry. It can be * usefull when merging two archives. * * @param entry the description of the new entry * @param in the stream carrying the contents of the new entry * @since 1.0 */ public void add(ApplicationBuilderItem entry, InputStream contents) throws AppBuilderException { try { addDirectory(entry.getLocation()); ZipEntry destEntry = getNormalizedEntry(entry.getArchivePath()); destEntry.setSize(entry.getSize()); getOutputStream().putNextEntry(destEntry); } catch (Exception e) { throw new AppBuilderException( getName() + " : impossible to create new entry \"" + entry.getArchivePath() + '"', e); } try { IOUtils.copy(contents, getOutputStream()); contents.close(); getOutputStream().flush(); getOutputStream().closeEntry(); } catch (Exception e) { throw new AppBuilderException( getName() + " : impossible to write contents of \"" + entry.getArchivePath() + '"', e); } finally { IOUtils.closeQuietly(contents); } } private JarOutputStream getOutputStream() { return jarOut; } private void setOutputStream() throws AppBuilderException { try { OutputStream out = new FileOutputStream(getPath().getAbsolutePath()); jarOut = new JarOutputStream(out); jarOut.setMethod(JarOutputStream.DEFLATED); } catch (Exception e) { throw new AppBuilderException(getPath().getAbsolutePath() + " : impossible to create", e); } } private void addDirectory(String directory) throws IOException { if (directory == null) { return; } if (alreadyAddedDirs.contains(directory)) { return; } if (directory.lastIndexOf(File.separator) != -1) { addDirectory(directory.substring(0, directory.lastIndexOf(File.separator))); } getOutputStream().putNextEntry(getNormalizedEntry(directory + File.separator)); alreadyAddedDirs.add(directory); } private ZipEntry getNormalizedEntry(String sysDependantPath) { String pathOK = sysDependantPath.replace(File.separatorChar, '/'); return new ZipEntry(pathOK); } }