478 lines
14 KiB
Java
478 lines
14 KiB
Java
package org.openoffice.idesupport.zip;
|
|
|
|
import java.io.*;
|
|
import java.util.Enumeration;
|
|
import java.util.zip.*;
|
|
import java.beans.PropertyVetoException;
|
|
|
|
import org.openoffice.idesupport.filter.FileFilter;
|
|
import org.openoffice.idesupport.filter.BinaryOnlyFilter;
|
|
import org.openoffice.idesupport.filter.ExceptParcelFilter;
|
|
|
|
import org.openoffice.idesupport.xml.XMLParser;
|
|
import org.openoffice.idesupport.xml.Manifest;
|
|
|
|
public class ParcelZipper
|
|
{
|
|
public static final String PARCEL_PREFIX_DIR = "Scripts/java/";
|
|
public static final String PARCEL_EXTENSION = "sxp";
|
|
public static final String CONTENTS_DIRNAME = "Contents";
|
|
public static final String PARCEL_DESCRIPTOR_XML = "parcel-descriptor.xml";
|
|
|
|
private static ParcelZipper zipper = null;
|
|
private static XMLParser parser = null;
|
|
|
|
private static final FileFilter DEFAULT_FILTER =
|
|
BinaryOnlyFilter.getInstance();
|
|
|
|
private ParcelZipper() {
|
|
}
|
|
|
|
public static ParcelZipper getParcelZipper() {
|
|
if (zipper == null) {
|
|
synchronized(ParcelZipper.class) {
|
|
if (zipper == null)
|
|
zipper = new ParcelZipper();
|
|
}
|
|
}
|
|
return zipper;
|
|
}
|
|
|
|
public static void setXMLParser(XMLParser parser) {
|
|
getParcelZipper().parser = parser;
|
|
}
|
|
|
|
public String zipParcel(File basedir) throws IOException {
|
|
File targetfile, targetdir;
|
|
|
|
if (basedir.getName().equals(CONTENTS_DIRNAME))
|
|
targetdir = basedir.getParentFile();
|
|
else
|
|
targetdir = basedir;
|
|
|
|
targetfile = new File(targetdir, targetdir.getName() + "." + PARCEL_EXTENSION);
|
|
|
|
return zipParcel(basedir, targetfile, DEFAULT_FILTER);
|
|
}
|
|
|
|
public String zipParcel(File basedir, File targetfile) throws IOException {
|
|
return zipParcel(basedir, targetfile, DEFAULT_FILTER);
|
|
}
|
|
|
|
public String zipParcel(File basedir, FileFilter filter) throws IOException {
|
|
File targetfile, targetdir;
|
|
|
|
if (basedir.getName().equals(CONTENTS_DIRNAME))
|
|
targetdir = basedir.getParentFile();
|
|
else
|
|
targetdir = basedir;
|
|
|
|
targetfile = new File(targetdir, targetdir.getName() + "." + PARCEL_EXTENSION);
|
|
|
|
return zipParcel(basedir, targetfile, filter);
|
|
}
|
|
|
|
public String zipParcel(File basedir, File targetfile, FileFilter filter)
|
|
throws IOException {
|
|
String realpath, tmppath;
|
|
|
|
realpath = targetfile.getPath();
|
|
tmppath = realpath + ".tmp";
|
|
|
|
File tmpfile = new File(tmppath);
|
|
try {
|
|
if (tmpfile.exists() == true)
|
|
tmpfile.delete();
|
|
|
|
ZipOutputStream out =
|
|
new ZipOutputStream(new FileOutputStream(tmpfile));
|
|
|
|
File[] children = basedir.listFiles();
|
|
for (int i = 0; i < children.length; i++)
|
|
addFileToParcel(children[i], "", out, filter);
|
|
|
|
out.close();
|
|
}
|
|
catch (IOException ioe) {
|
|
tmpfile.delete();
|
|
throw ioe;
|
|
}
|
|
|
|
if (targetfile.exists() == true)
|
|
targetfile.delete();
|
|
tmpfile.renameTo(targetfile);
|
|
return targetfile.getAbsolutePath();
|
|
}
|
|
|
|
private void addFileToParcel(File root, String path, ZipOutputStream out, FileFilter filter)
|
|
throws IOException {
|
|
ZipEntry ze;
|
|
|
|
if (root.isDirectory() == true) {
|
|
ze = new ZipEntry(/* PARCEL_PREFIX_DIR + */ path + root.getName() + "/");
|
|
out.putNextEntry(ze);
|
|
out.closeEntry();
|
|
File[] children = root.listFiles();
|
|
|
|
for (int i = 0; i < children.length; i++)
|
|
addFileToParcel(children[i], path + root.getName() + "/", out, filter);
|
|
}
|
|
else {
|
|
if (filter.validate(root.getName()) == false &&
|
|
root.getName().equals("parcel-descriptor.xml") == false)
|
|
return;
|
|
|
|
ze = new ZipEntry(/* PARCEL_PREFIX_DIR + */ path + root.getName());
|
|
out.putNextEntry(ze);
|
|
|
|
byte[] bytes = new byte[1024];
|
|
int len;
|
|
FileInputStream fis = new FileInputStream(root);
|
|
|
|
while ((len = fis.read(bytes)) != -1)
|
|
out.write(bytes, 0, len);
|
|
|
|
out.closeEntry();
|
|
}
|
|
}
|
|
|
|
public boolean isOverwriteNeeded(File parcel, File target) {
|
|
boolean result;
|
|
|
|
if (target.isDirectory())
|
|
result = isDirectoryOverwriteNeeded(parcel, target);
|
|
else
|
|
result = isDocumentOverwriteNeeded(parcel, target);
|
|
|
|
return result;
|
|
}
|
|
|
|
private boolean isDirectoryOverwriteNeeded(File parcel, File target) {
|
|
String parcelDir = getParcelDirFromParcelZip(parcel.getName());
|
|
File[] children = target.listFiles();
|
|
|
|
for (int i = 0; i < children.length; i++)
|
|
if (children[i].getName().equals(parcelDir))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
private boolean isDocumentOverwriteNeeded(File parcel, File document) {
|
|
ZipFile documentZip;
|
|
|
|
try {
|
|
documentZip = new ZipFile(document);
|
|
}
|
|
catch (IOException ioe) {
|
|
return false;
|
|
}
|
|
|
|
String name =
|
|
PARCEL_PREFIX_DIR + getParcelDirFromParcelZip(parcel.getName()) +
|
|
"/" + PARCEL_DESCRIPTOR_XML;
|
|
|
|
if (documentZip.getEntry(name) != null)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
public String deployParcel(File parcel, File target)
|
|
throws IOException {
|
|
|
|
String output = null;
|
|
if (target.isDirectory())
|
|
output = unzipToDirectory(parcel, target);
|
|
else
|
|
output = unzipToZip(parcel, target);
|
|
return output;
|
|
}
|
|
|
|
private String getParcelDirFromParcelZip(String zipname) {
|
|
String result = zipname.substring(0, zipname.lastIndexOf("."));
|
|
return result;
|
|
}
|
|
|
|
private String unzipToDirectory(File parcel, File targetDirectory)
|
|
throws IOException {
|
|
|
|
ZipInputStream in;
|
|
File parcelDir = new File(targetDirectory,
|
|
getParcelDirFromParcelZip(parcel.getName()));
|
|
|
|
if (isDirectoryOverwriteNeeded(parcel, targetDirectory)) {
|
|
if (deleteDir(parcelDir) == false) {
|
|
throw new IOException("Could not overwrite: " +
|
|
parcelDir.getAbsolutePath());
|
|
}
|
|
}
|
|
|
|
in = new ZipInputStream(new FileInputStream(parcel));
|
|
|
|
File outFile;
|
|
ZipEntry inEntry = in.getNextEntry();
|
|
byte[] bytes = new byte[1024];
|
|
int len;
|
|
|
|
while (inEntry != null) {
|
|
outFile = new File(parcelDir, inEntry.getName());
|
|
if (inEntry.isDirectory()) {
|
|
//System.err.println("Creating directory: " + outFile.getAbsolutePath());
|
|
outFile.mkdir();
|
|
}
|
|
else {
|
|
if (outFile.getParentFile().exists() != true)
|
|
outFile.getParentFile().mkdirs();
|
|
|
|
FileOutputStream out = new FileOutputStream(outFile);
|
|
// System.out.println("Writing file: " + outFile.getAbsolutePath());
|
|
while ((len = in.read(bytes)) != -1)
|
|
out.write(bytes, 0, len);
|
|
out.close();
|
|
}
|
|
|
|
inEntry = in.getNextEntry();
|
|
}
|
|
in.close();
|
|
return parcelDir.getAbsolutePath();
|
|
}
|
|
|
|
private boolean deleteDir(File basedir) {
|
|
if (basedir.isDirectory()) {
|
|
String[] children = basedir.list();
|
|
for (int i=0; i<children.length; i++) {
|
|
boolean success = deleteDir(new File(basedir, children[i]));
|
|
if (!success) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return basedir.delete();
|
|
}
|
|
|
|
private String unzipToZip(File parcel, File targetDocument)
|
|
throws IOException {
|
|
|
|
ZipInputStream documentStream, parcelStream;
|
|
ZipOutputStream outStream;
|
|
Manifest manifest;
|
|
|
|
if (isDocumentOverwriteNeeded(parcel, targetDocument)) {
|
|
String parcelName = getParcelDirFromParcelZip(parcel.getName());
|
|
unzipToZipExceptParcel(targetDocument, parcelName);
|
|
}
|
|
|
|
// first write contents of document to tmpfile
|
|
File tmpfile = new File(targetDocument.getAbsolutePath() + ".tmp");
|
|
|
|
manifest = addParcelToManifest(targetDocument, parcel);
|
|
|
|
documentStream =
|
|
new ZipInputStream(new FileInputStream(targetDocument));
|
|
parcelStream = new ZipInputStream(new FileInputStream(parcel));
|
|
outStream = new ZipOutputStream(new FileOutputStream(tmpfile));
|
|
|
|
try {
|
|
copyParcelToZip(parcelStream, outStream, PARCEL_PREFIX_DIR +
|
|
getParcelDirFromParcelZip(parcel.getName()));
|
|
copyDocumentToZip(documentStream, outStream, manifest);
|
|
documentStream.close();
|
|
parcelStream.close();
|
|
outStream.close();
|
|
}
|
|
catch (IOException ioe) {
|
|
tmpfile.delete();
|
|
throw ioe;
|
|
}
|
|
|
|
if (targetDocument.delete() == false) {
|
|
tmpfile.delete();
|
|
throw new IOException("Could not overwrite " + targetDocument);
|
|
}
|
|
else
|
|
tmpfile.renameTo(targetDocument);
|
|
|
|
return targetDocument.getAbsolutePath();
|
|
}
|
|
|
|
private void copyParcelToZip(ZipInputStream in, ZipOutputStream out,
|
|
String parcelName) throws IOException {
|
|
|
|
ZipEntry outEntry;
|
|
ZipEntry inEntry = in.getNextEntry();
|
|
byte[] bytes = new byte[1024];
|
|
int len;
|
|
|
|
while (inEntry != null) {
|
|
if(parcelName!=null)
|
|
outEntry = new ZipEntry(parcelName + "/" + inEntry.getName());
|
|
else
|
|
outEntry = new ZipEntry(inEntry);
|
|
out.putNextEntry(outEntry);
|
|
|
|
if (inEntry.isDirectory() == false)
|
|
while ((len = in.read(bytes)) != -1)
|
|
out.write(bytes, 0, len);
|
|
|
|
out.closeEntry();
|
|
inEntry = in.getNextEntry();
|
|
}
|
|
}
|
|
|
|
private void copyDocumentToZip(ZipInputStream in, ZipOutputStream out,
|
|
Manifest manifest) throws IOException {
|
|
|
|
ZipEntry outEntry;
|
|
ZipEntry inEntry;
|
|
byte[] bytes = new byte[1024];
|
|
int len;
|
|
|
|
while ((inEntry = in.getNextEntry()) != null) {
|
|
|
|
outEntry = new ZipEntry(inEntry);
|
|
out.putNextEntry(outEntry);
|
|
|
|
if(inEntry.getName().equals("META-INF/manifest.xml") &&
|
|
manifest != null) {
|
|
InputStream manifestStream = manifest.getInputStream();
|
|
while ((len = manifestStream.read(bytes)) != -1)
|
|
out.write(bytes, 0, len);
|
|
}
|
|
else if (inEntry.isDirectory() == false) {
|
|
while ((len = in.read(bytes)) != -1)
|
|
out.write(bytes, 0, len);
|
|
}
|
|
|
|
out.closeEntry();
|
|
}
|
|
}
|
|
|
|
public String unzipToZipExceptParcel(File document, String parcelName)
|
|
throws IOException {
|
|
|
|
ZipInputStream documentStream;
|
|
ZipOutputStream outStream;
|
|
Manifest manifest = null;
|
|
|
|
parcelName = PARCEL_PREFIX_DIR + parcelName;
|
|
manifest = removeParcelFromManifest(document, parcelName);
|
|
|
|
// first write contents of document to tmpfile
|
|
File tmpfile = new File(document.getAbsolutePath() + ".tmp");
|
|
|
|
documentStream = new ZipInputStream(new FileInputStream(document));
|
|
outStream = new ZipOutputStream(new FileOutputStream(tmpfile));
|
|
|
|
try {
|
|
ZipEntry outEntry;
|
|
ZipEntry inEntry;
|
|
byte[] bytes = new byte[1024];
|
|
int len;
|
|
|
|
while ((inEntry = documentStream.getNextEntry()) != null) {
|
|
|
|
if(inEntry.getName().startsWith(parcelName))
|
|
continue;
|
|
|
|
outEntry = new ZipEntry(inEntry);
|
|
outStream.putNextEntry(outEntry);
|
|
|
|
if(inEntry.getName().equals("META-INF/manifest.xml") &&
|
|
manifest != null) {
|
|
InputStream manifestStream = manifest.getInputStream();
|
|
while ((len = manifestStream.read(bytes)) != -1)
|
|
outStream.write(bytes, 0, len);
|
|
}
|
|
else if (inEntry.isDirectory() == false) {
|
|
while ((len = documentStream.read(bytes)) != -1)
|
|
outStream.write(bytes, 0, len);
|
|
}
|
|
|
|
outStream.closeEntry();
|
|
}
|
|
}
|
|
catch (IOException ioe) {
|
|
tmpfile.delete();
|
|
throw ioe;
|
|
}
|
|
finally {
|
|
documentStream.close();
|
|
outStream.close();
|
|
}
|
|
|
|
if (document.delete() == false) {
|
|
tmpfile.delete();
|
|
throw new IOException("Could not overwrite " + document);
|
|
}
|
|
else
|
|
tmpfile.renameTo(document);
|
|
|
|
return document.getAbsolutePath();
|
|
}
|
|
|
|
private Manifest getManifestFromDocument(File document) {
|
|
ZipFile documentZip;
|
|
Manifest result = null;
|
|
|
|
try {
|
|
documentZip = new ZipFile(document);
|
|
}
|
|
catch (IOException ioe) {
|
|
return null;
|
|
}
|
|
|
|
ZipEntry original = documentZip.getEntry("META-INF/manifest.xml");
|
|
if (original == null) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
result = new Manifest(documentZip.getInputStream(original), parser);
|
|
}
|
|
catch (IOException ioe) {
|
|
return null;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private Manifest addParcelToManifest(File document, File parcel) {
|
|
ZipFile documentZip, parcelZip;
|
|
Manifest result = null;
|
|
|
|
result = getManifestFromDocument(document);
|
|
if (result == null)
|
|
return null;
|
|
|
|
try {
|
|
parcelZip = new ZipFile(parcel);
|
|
}
|
|
catch (IOException ioe) {
|
|
return null;
|
|
}
|
|
|
|
String prefix = PARCEL_PREFIX_DIR +
|
|
getParcelDirFromParcelZip(parcel.getName()) + "/";
|
|
|
|
Enumeration entries = parcelZip.entries();
|
|
while (entries.hasMoreElements()) {
|
|
ZipEntry entry = (ZipEntry)entries.nextElement();
|
|
result.add(prefix + entry.getName());
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private Manifest removeParcelFromManifest(File document, String name) {
|
|
Manifest result = null;
|
|
|
|
result = getManifestFromDocument(document);
|
|
if (result == null)
|
|
return null;
|
|
|
|
result.remove(name);
|
|
return result;
|
|
}
|
|
}
|