Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2011 DeepDiff Contributors
*
* Licensed 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 deepdiff.scope;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipInputStream;
import org.apache.log4j.Logger;
import deepdiff.core.DiffPointProcessor;
import deepdiff.core.DiffScope;
import deepdiff.core.DiffUnit;
import deepdiff.core.DiffUnitProcessor;
/**
* An implementation of {@link DiffScope} that compares two Zip files. These Zip files do not need
* to be physical files; any {@link InputStream} can be used. Thus, it is possible to process Zip
* files within Zip files.
*/
public class SortedZipDiffScope implements DiffScope {
private static final Logger log = Logger.getLogger(SortedZipDiffScope.class);
private SortedMap leftEntries;
private SortedMap rightEntries;
private InputStream isLeft;
private InputStream isRight;
private String path;
/**
* Initializes a new ZipDiffScope object.
*
* @param path the scoped path to the Zip files
* @param isLeft the {@link InputStream} for the Zip file on the left
* @param isRight the {@link InputStream} for the Zip file on the right
*/
public SortedZipDiffScope(String path, InputStream isLeft, InputStream isRight) {
this.path = path;
this.isLeft = isLeft;
this.isRight = isRight;
leftEntries = new TreeMap();
rightEntries = new TreeMap();
}
/**
* Scans the Zip archive for DiffUnits and processes them
*
* @param unitProcessor the unit processor to process the DiffUnits found in the scan
* @param pointProcessor the point processor to pass to the unit processor when processing units
*/
public void scan(DiffUnitProcessor unitProcessor, DiffPointProcessor pointProcessor) {
try {
log.debug("Starting to scan scope " + path);
loadEntries(isLeft, leftEntries);
loadEntries(isRight, rightEntries);
SortedSet keySet = new TreeSet();
keySet.addAll(leftEntries.keySet());
keySet.addAll(rightEntries.keySet());
for (String path : keySet) {
CachedZipEntry leftEntry = leftEntries.get(path);
CachedZipEntry rightEntry = rightEntries.get(path);
CachedZipDiffUnit diffUnit = new CachedZipDiffUnit(this, leftEntry, rightEntry);
unitProcessor.processDiffUnit(diffUnit, pointProcessor);
if (leftEntry != null) {
leftEntry.cleanup();
}
if (rightEntry != null) {
rightEntry.cleanup();
}
}
leftEntries.clear();
rightEntries.clear();
log.debug("Completed scan of scope " + path);
} finally {
if (isLeft != null) {
try {
isLeft.close();
} catch (Exception ex) {
// Ignore exception on close
}
}
if (isRight != null) {
try {
isRight.close();
} catch (Exception ex) {
// Ignore exception on close
}
}
}
}
/**
* Returns the scoped path to the Zip files
*
* @return the scoped path to the Zip files
*/
public String getPath() {
return path;
}
private void loadEntries(InputStream is, Map cachedEntries) {
ZipInputStream zis = new ZipInputStream(is);
ZipEntry entry = null;
boolean validEntry = false;
try {
while (!validEntry || entry != null) {
try {
entry = zis.getNextEntry();
validEntry = true;
if (entry != null) {
String path = entry.getName();
CachedZipEntry cachedEntry = new CachedZipEntry(entry, zis);
cachedEntries.put(path, cachedEntry);
}
} catch (ZipException ze) {
if ("encrypted ZIP entry not supported".equals(ze.getMessage())) {
log.warn(path
+ " contains encrypted ZIP entries; comparison of this file not supported");
} else {
log.error("Failure scanning scope: " + path, ze);
}
} catch (IOException ioe) {
validEntry = false;
log.error("Failure scanning scope: " + path, ioe);
}
}
} finally {
try {
zis.close();
} catch (Exception ex) {
// Ignore exception on close
}
}
}
private static class CachedZipEntry extends ZipEntry {
private String name;
private boolean directory;
private File tmpFile;
private byte[] data;
int length;
public CachedZipEntry(ZipEntry ze, ZipInputStream zis) throws IOException {
super(ze.getName());
this.name = ze.getName();
this.directory = ze.isDirectory();
if (!this.directory) {
readAll(zis, ze);
}
}
public void cleanup() {
if (tmpFile != null) {
if (!tmpFile.delete()) {
tmpFile.deleteOnExit();
}
} else {
data = null;
}
}
public InputStream getStream() throws IOException {
if (tmpFile != null) {
return new FileInputStream(tmpFile);
} else {
return new ByteArrayInputStream(data, 0, length);
}
}
@Override
public String getName() {
return name;
}
@Override
public boolean isDirectory() {
return directory;
}
private void readAll(ZipInputStream zis, ZipEntry entry) throws IOException {
final int maxMemSize = 100000;
long totalSize = entry.getSize();
if (totalSize >= maxMemSize || totalSize < 0) {
tmpFile = File.createTempFile("ZipContent", null);
FileOutputStream fos = new FileOutputStream(tmpFile);
byte[] buf = new byte[1024];
int size = zis.read(buf);
while (size != -1) {
fos.write(buf, 0, size);
size = zis.read(buf);
}
fos.close();
} else if (totalSize == 0) {
length = 0;
data = new byte[length];
} else {
length = (int) totalSize;
// Allow an extra byte in the buffer so we can request an extra
// byte at the end, to get confirmation that there's no more data
// left
data = new byte[length + 1];
int off = 0;
int size = zis.read(data, off, data.length - off);
while (size != -1) {
off += size;
size = zis.read(data, off, data.length - off);
}
}
}
}
public static class CachedZipDiffUnit implements DiffUnit {
private CachedZipEntry e1;
private CachedZipEntry e2;
private SortedZipDiffScope scope;
CachedZipDiffUnit(SortedZipDiffScope scope, CachedZipEntry e1, CachedZipEntry e2) {
this.scope = scope;
this.e1 = e1;
this.e2 = e2;
}
/**
* Returns whether the left entry exists
*
* @return whether the left entry exists
*/
public boolean leftExists() {
return e1 != null;
}
/**
* Returns whether the right entry exists
*
* @return whether the right entry exists
*/
public boolean rightExists() {
return e2 != null;
}
/**
* Returns whether the left entry represents a directory
*
* @return whether the left entry represents a directory
*/
public boolean leftIsDir() {
return leftExists() && e1.isDirectory();
}
/**
* Returns whether the right entry represents a directory
*
* @return whether the right entry represents a directory
*/
public boolean rightIsDir() {
return rightExists() && e2.isDirectory();
}
/**
* Returns a stream to access the content of the left entry
*
* @return a stream to access the content of the left entry
*
* @throws IOException if there was an error creating the stream
*/
public InputStream getLeftInputStream() throws IOException {
return e1.getStream();
}
/**
* Returns a stream to access the content of the right entry
*
* @return a stream to access the content of the right entry
*
* @throws IOException if there was an error creating the stream
*/
public InputStream getRightInputStream() throws IOException {
return e2.getStream();
}
/**
* Returns the scoped path for the unit. This is the path of the Zip scope, followed by the
* path of the entry within the Zip scope
*
* @return the scoped path for the unit
*/
public String getScopedPath() {
String scopePath = scope.getPath();
String relativePath = null;
if (e1 != null) {
relativePath = e1.getName();
} else if (e2 != null) {
relativePath = e2.getName();
}
return scopePath + "!" + relativePath;
}
}
}