Files
libreoffice/scripting/java/org/openoffice/idesupport/zip/ParcelZipper.java
Tomas O'Connor ebb5dbaabb Initial checkin of org.openoffice.idesupport java package for shared
classes supporting Office Scripting in Java in various IDEs
2002-11-12 13:22:58 +00:00

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;
}
}