blob: f4007715fa0c3c103ac5dc6ab95072fe6855ed4c [file] [log] [blame]
/*
* Copyright 2013 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.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import java.io.IOException;
import java.io.Serializable;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* Represents an entry in a ZipFile that contains the serialized form of a Serializable object.
*
* @param <T> the type of object serialized into the zip entry
*/
public class ZipEntryBackedObject<T extends Serializable> implements PersistenceBackedObject<T> {
private final Class<T> clazz;
private final String libraryPath;
private final String resourcePath;
private final ZipFile zipFile;
private final ZipOutputStream zipOutputStream;
/**
* Constructs a read-only instance that will dynamically open the provided resourcePath in the
* provided zipFile when requested.
*/
public ZipEntryBackedObject(
ZipFile zipFile, String libraryPath, String resourcePath, Class<T> clazz) {
this.zipFile = zipFile;
this.zipOutputStream = null;
this.libraryPath = libraryPath;
this.resourcePath = resourcePath;
this.clazz = clazz;
}
/**
* Constructs a write-only instance that will write a ZipEntry and bytes to the provided
* zipOutputStream when requested.<br />
*
* Cannot be used to overwrite an already existing entry. Brand new zip files that are being built
* manifest as empty files which can not be probed by ZipFile but which are legal for zip output
* stream writing and ZipOutputStreams can't be probed about existing entries. So it is left up to
* the user to avoid duplicate entry errors.
*/
public ZipEntryBackedObject(
ZipOutputStream zipOutputStream, String libraryPath, String resourcePath, Class<T> clazz) {
this.zipFile = null;
this.zipOutputStream = zipOutputStream;
this.libraryPath = libraryPath;
this.resourcePath = resourcePath;
this.clazz = clazz;
}
@Override
public boolean exists() {
return zipFile.getEntry(resourcePath) != null;
}
@Override
public String getPath() {
return "jar:file:" + libraryPath + "!/" + resourcePath;
}
@Override
public T newInstance(TreeLogger logger) throws UnableToCompleteException {
if (zipOutputStream != null) {
logger.log(TreeLogger.ERROR, "Tried to read from a write-only ZipEntryBackedObject");
throw new UnableToCompleteException();
}
try {
return Util.readStreamAsObject(zipFile.getInputStream(zipFile.getEntry(resourcePath)), clazz);
} catch (ClassNotFoundException e) {
logger.log(TreeLogger.ERROR, "Missing class definition", e);
throw new UnableToCompleteException();
} catch (IOException e) {
logger.log(TreeLogger.ERROR, "Unable to instantiate object", e);
throw new UnableToCompleteException();
}
}
@Override
public void set(TreeLogger logger, T object)
throws IllegalStateException, UnableToCompleteException {
assert clazz.isInstance(object);
if (zipOutputStream == null) {
logger.log(TreeLogger.ERROR, "Tried to write to a read-only ZipEntryBackedObject");
throw new UnableToCompleteException();
}
try {
// Inherently disallows duplicate entries.
zipOutputStream.putNextEntry(new ZipEntry(resourcePath));
Util.writeObjectToStream(zipOutputStream, object);
} catch (IOException e) {
logger.log(TreeLogger.ERROR, "Unable to write file: " + getPath(), e);
throw new UnableToCompleteException();
}
}
}