blob: 5d8eaadcab05983edaf71fdbce6b073af64508b3 [file] [log] [blame]
/*
* Copyright 2009 Google Inc.
*
* 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 com.google.gwt.dev.util;
import com.google.gwt.dev.util.NullOutputFileSet.NullOutputStream;
import com.google.gwt.dev.util.collect.HashSet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Set;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* An {@link OutputFileSet} on a jar file.
*/
public class OutputFileSetOnJar extends OutputFileSet {
/**
* An output stream on a jar entry for <code>jar</code>. It is assumed that
* the entry has already been written, so this class only has to forward the
* writes.
*/
private final class OutputStreamOnJarEntry extends OutputStream {
@Override
public void close() throws IOException {
jar.closeEntry();
}
@Override
public void write(byte b[], int off, int len) throws IOException {
jar.write(b, off, len);
}
@Override
public void write(int b) throws IOException {
jar.write(b);
}
}
/**
* Returns the parent path of forward-slash based partial path. Assumes the
* given path does not end with a trailing slash.
*/
private static String getParentPath(String path) {
assert !path.endsWith("/");
int pos = path.lastIndexOf('/');
return (pos >= 0) ? path.substring(0, pos) : null;
}
private Set<String> createdDirs = new HashSet<String>();
private final JarOutputStream jar;
private final String pathPrefix;
private final Set<String> seenEntries = new HashSet<String>();
public OutputFileSetOnJar(File jarFile, String pathPrefix) throws IOException {
super(jarFile.getAbsolutePath());
jarFile.delete();
jar = new JarOutputStream(new FileOutputStream(jarFile));
this.pathPrefix = pathPrefix;
}
@Override
public void close() throws IOException {
jar.close();
}
@Override
public OutputStream createNewOutputStream(String path, long lastModifiedTime)
throws IOException {
String fullPath = pathPrefix + path;
if (seenEntries.contains(fullPath)) {
return new NullOutputStream();
}
seenEntries.add(fullPath);
mkzipDirs(getParentPath(fullPath));
ZipEntry zipEntry = new ZipEntry(fullPath);
if (lastModifiedTime >= 0) {
zipEntry.setTime(lastModifiedTime);
}
jar.putNextEntry(zipEntry);
return new OutputStreamOnJarEntry();
}
/**
* Creates directory entries within a zip archive. Uses
* <code>createdDirs</code> to avoid creating entries for the same path twice.
*
* @param path the path of a directory within the archive to create
*/
private void mkzipDirs(String path) throws IOException {
if (path == null) {
return;
}
if (createdDirs.contains(path)) {
return;
}
mkzipDirs(getParentPath(path));
ZipEntry entry = new ZipEntry(path + '/');
entry.setSize(0);
entry.setCompressedSize(0);
entry.setCrc(0);
entry.setMethod(ZipOutputStream.STORED);
jar.putNextEntry(entry);
createdDirs.add(path);
}
}