Return-Path: Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: (qmail 15822 invoked from network); 9 Apr 2009 11:15:58 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 9 Apr 2009 11:15:58 -0000 Received: (qmail 9546 invoked by uid 500); 9 Apr 2009 11:15:57 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 9464 invoked by uid 500); 9 Apr 2009 11:15:57 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 9455 invoked by uid 99); 9 Apr 2009 11:15:57 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 09 Apr 2009 11:15:57 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 09 Apr 2009 11:15:54 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 551952388A1B; Thu, 9 Apr 2009 11:15:33 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r763604 - in /commons/proper/compress/trunk/src: main/java/org/apache/commons/compress/changes/ test/java/org/apache/commons/compress/changes/ Date: Thu, 09 Apr 2009 11:15:33 -0000 To: commits@commons.apache.org From: grobmeier@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090409111533.551952388A1B@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: grobmeier Date: Thu Apr 9 11:15:32 2009 New Revision: 763604 URL: http://svn.apache.org/viewvc?rev=763604&view=rev Log: COMPRESS-60: extracted ChangeSetPerformer class for more thread safety. Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/changes/ChangeSetPerformer.java Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/changes/ChangeSet.java commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/changes/ChangeSetTestCase.java Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/changes/ChangeSet.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/changes/ChangeSet.java?rev=763604&r1=763603&r2=763604&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/changes/ChangeSet.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/changes/ChangeSet.java Thu Apr 9 11:15:32 2009 @@ -18,16 +18,12 @@ */ package org.apache.commons.compress.changes; -import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; import org.apache.commons.compress.archivers.ArchiveEntry; -import org.apache.commons.compress.archivers.ArchiveInputStream; -import org.apache.commons.compress.archivers.ArchiveOutputStream; -import org.apache.commons.compress.utils.IOUtils; /** * ChangeSet collects and performs changes to an archive. @@ -42,8 +38,8 @@ /** * Deletes the file with the filename from the archive. - * This method is not thread safe. * + * @NotThreadSafe * @param pFilename * the filename of the file to delete */ @@ -64,61 +60,9 @@ } /** - * Performs all changes collected in this ChangeSet on the input stream and - * streams the result to the output stream. Since this method works on a copy - * of the actual ChangSet, perform may be called more than once. - * - * @param in - * the InputStream to perform the changes on - * @param out - * the resulting OutputStream with all modifications - * @throws IOException - * if an read/write error occurs - */ - public void perform(ArchiveInputStream in, ArchiveOutputStream out) - throws IOException { - Set workingSet = new LinkedHashSet(changes); - for (Iterator it = workingSet.iterator(); it.hasNext();) { - Change change = (Change) it.next(); - - if (change.type() == Change.TYPE_ADD) { - copyStream(change.getInput(), out, change.getEntry()); - it.remove(); - } - } - - ArchiveEntry entry = null; - while ((entry = in.getNextEntry()) != null) { - boolean copy = true; - - for (Iterator it = workingSet.iterator(); it.hasNext();) { - Change change = (Change) it.next(); - - if (change.type() == Change.TYPE_DELETE - && entry.getName() != null) { - if (entry.getName().equals(change.targetFile())) { - copy = false; - it.remove(); - break; - } else if (entry.getName().matches( - change.targetFile() + "/.*")) { - copy = false; - break; - } - } - } - - if (copy) { - if (!isDeletedLater(workingSet, entry)) { - copyStream(in, out, entry); - } - } - } - } - - /** - * Adds an delete change. This method is not thread safe. + * Adds an delete change. * + * @NotThreadSafe * @param pChange * the change which should result in a deletion */ @@ -148,50 +92,11 @@ } /** - * Checks if an ArchiveEntry is deleted later in the ChangeSet. This is - * necessary if an file is added with this ChangeSet, but later became - * deleted in the same set. - * - * @param entry - * the entry to check - * @return true, if this entry has an deletion change later, false otherwise - */ - private boolean isDeletedLater(Set workingSet, ArchiveEntry entry) { - String source = entry.getName(); - - if (!workingSet.isEmpty()) { - for (Iterator it = workingSet.iterator(); it.hasNext();) { - Change change = (Change) it.next(); - if (change.type() == Change.TYPE_DELETE) { - String target = change.targetFile(); - - if (source.equals(target)) { - return true; - } - - return source.matches(target + "/.*"); - } - } - } - return false; - } - - /** - * Copies the ArchiveEntry to the Output stream - * - * @param in - * the stream to read the data from - * @param out - * the stream to write the data to - * @param entry - * the entry to write - * @throws IOException - * if data cannot be read or written + * Returns the list of changes as a copy. Changes on this set + * are not reflected on this ChangeSet and vice versa. + * @return the changes as a copy */ - private static void copyStream(InputStream in, ArchiveOutputStream out, - ArchiveEntry entry) throws IOException { - out.putArchiveEntry(entry); - IOUtils.copy(in, out); - out.closeArchiveEntry(); + Set getChanges() { + return new LinkedHashSet(changes); } } Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/changes/ChangeSetPerformer.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/changes/ChangeSetPerformer.java?rev=763604&view=auto ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/changes/ChangeSetPerformer.java (added) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/changes/ChangeSetPerformer.java Thu Apr 9 11:15:32 2009 @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.commons.compress.changes; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.ArchiveInputStream; +import org.apache.commons.compress.archivers.ArchiveOutputStream; +import org.apache.commons.compress.utils.IOUtils; + +/** + * Performs ChangeSet operations on a stream. + * This class is thread safe and can be used multiple times. + * It operates on a copy of the ChangeSet. If the ChangeSet changes, + * a new Performer must be created. + * + * @Threadsafe + * @Immutable + */ +public class ChangeSetPerformer { + private Set changes = null; + + /** + * Constructs a ChangeSetPerformer with the changes from this ChangeSet + * @param changeSet the ChangeSet which operations are used for performing + */ + public ChangeSetPerformer(final ChangeSet changeSet) { + changes = changeSet.getChanges(); + } + + /** + * Performs all changes collected in this ChangeSet on the input stream and + * streams the result to the output stream. Perform may be called more than once. + * + * @param in + * the InputStream to perform the changes on + * @param out + * the resulting OutputStream with all modifications + * @throws IOException + * if an read/write error occurs + */ + public void perform(ArchiveInputStream in, ArchiveOutputStream out) + throws IOException { + Set workingSet = new LinkedHashSet(changes); + + for (Iterator it = workingSet.iterator(); it.hasNext();) { + Change change = (Change) it.next(); + + if (change.type() == Change.TYPE_ADD) { + copyStream(change.getInput(), out, change.getEntry()); + it.remove(); + } + } + + ArchiveEntry entry = null; + while ((entry = in.getNextEntry()) != null) { + boolean copy = true; + + for (Iterator it = workingSet.iterator(); it.hasNext();) { + Change change = (Change) it.next(); + + if (change.type() == Change.TYPE_DELETE + && entry.getName() != null) { + if (entry.getName().equals(change.targetFile())) { + copy = false; + it.remove(); + break; + } else if (entry.getName().matches( + change.targetFile() + "/.*")) { + copy = false; + break; + } + } + } + + if (copy) { + if (!isDeletedLater(workingSet, entry)) { + copyStream(in, out, entry); + } + } + } + } + + /** + * Checks if an ArchiveEntry is deleted later in the ChangeSet. This is + * necessary if an file is added with this ChangeSet, but later became + * deleted in the same set. + * + * @param entry + * the entry to check + * @return true, if this entry has an deletion change later, false otherwise + */ + private boolean isDeletedLater(Set workingSet, ArchiveEntry entry) { + String source = entry.getName(); + + if (!workingSet.isEmpty()) { + for (Iterator it = workingSet.iterator(); it.hasNext();) { + Change change = (Change) it.next(); + if (change.type() == Change.TYPE_DELETE) { + String target = change.targetFile(); + + if (source.equals(target)) { + return true; + } + + return source.matches(target + "/.*"); + } + } + } + return false; + } + + /** + * Copies the ArchiveEntry to the Output stream + * + * @param in + * the stream to read the data from + * @param out + * the stream to write the data to + * @param entry + * the entry to write + * @throws IOException + * if data cannot be read or written + */ + private void copyStream(InputStream in, ArchiveOutputStream out, + ArchiveEntry entry) throws IOException { + out.putArchiveEntry(entry); + IOUtils.copy(in, out); + out.closeArchiveEntry(); + } +} Modified: commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/changes/ChangeSetTestCase.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/changes/ChangeSetTestCase.java?rev=763604&r1=763603&r2=763604&view=diff ============================================================================== --- commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/changes/ChangeSetTestCase.java (original) +++ commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/changes/ChangeSetTestCase.java Thu Apr 9 11:15:32 2009 @@ -77,7 +77,8 @@ ChangeSet changes = new ChangeSet(); changes.delete("bla"); archiveListDelete("bla"); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); is.close(); } finally { @@ -115,7 +116,9 @@ ChangeSet changes = new ChangeSet(); changes.delete("bla/test5.xml"); archiveListDelete("bla/test5.xml"); - changes.perform(ais, out); + + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); is.close(); } finally { @@ -160,7 +163,8 @@ changes.add(entry, new FileInputStream(file1)); archiveList.add("bla/test.txt"); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); is.close(); } finally { @@ -203,7 +207,8 @@ changes.delete("testdata/test1.xml"); archiveListDelete("testdata/test1.xml"); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); is.close(); } finally { @@ -247,7 +252,9 @@ changes.delete("blub"); archiveListDelete("blub"); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); + is.close(); } finally { @@ -293,7 +300,9 @@ changes.delete("bla"); archiveListDelete("bla"); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); + is.close(); } finally { @@ -328,7 +337,9 @@ out = factory.createArchiveOutputStream("zip", new FileOutputStream(temp)); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); + } finally { if (out != null) out.close(); @@ -363,7 +374,9 @@ out = factory.createArchiveOutputStream("tar", new FileOutputStream(temp)); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); + } finally { if (out != null) out.close(); @@ -399,7 +412,9 @@ out = factory.createArchiveOutputStream("jar", new FileOutputStream(temp)); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); + } finally { if (out != null) out.close(); @@ -441,7 +456,9 @@ out = factory.createArchiveOutputStream("tar", new FileOutputStream(temp)); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); + } finally { if (out != null) out.close(); @@ -483,7 +500,9 @@ out = factory.createArchiveOutputStream("jar", new FileOutputStream(temp)); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); + } finally { if (out != null) out.close(); @@ -517,7 +536,9 @@ out = factory.createArchiveOutputStream("ar", new FileOutputStream(temp)); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); + } finally { if (out != null) out.close(); @@ -558,7 +579,9 @@ out = factory.createArchiveOutputStream("ar", new FileOutputStream(temp)); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); + } finally { if (out != null) out.close(); @@ -622,7 +645,8 @@ ArchiveEntry entry = new ZipArchiveEntry("bla/test.txt"); changes.add(entry, new FileInputStream(file1)); archiveList.add("bla/test.txt"); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); is.close(); } finally { @@ -669,7 +693,8 @@ changes.add(entry, new FileInputStream(file)); archiveList.add("bla/test.txt"); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); is.close(); } finally { @@ -716,7 +741,8 @@ changes.delete("test1.xml"); archiveListDelete("test1.xml"); - changes.perform(ais, out); + ChangeSetPerformer performer = new ChangeSetPerformer(changes); + performer.perform(ais, out); is.close(); } finally {