/*******************************************************************************
* Copyright (c) 2015 IBM Corp.
*
* 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.ibm.ws.lars.testutils.clients;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import com.ibm.ws.repository.transport.client.DirectoryUtils;
import com.ibm.ws.repository.transport.client.ZipClient;
import com.ibm.ws.repository.transport.exceptions.BadVersionException;
import com.ibm.ws.repository.transport.exceptions.RequestFailureException;
import com.ibm.ws.repository.transport.model.Asset;
import com.ibm.ws.repository.transport.model.Attachment;
import com.ibm.ws.repository.transport.model.AttachmentSummary;
/**
*
*/
public class ZipWriteableClient extends AbstractFileWriteableClient {
private final File _zip;
public ZipWriteableClient(File root) {
_zip = root;
_readClient = new ZipClient(_zip);
}
/**
*
* @param zip
* @param pathToWriteTo Do not include this file when making a copy of the zip as the calling
* code is about to write a new vesion of it
* @return
* @throws IOException
*/
public static ZipOutputStream appendToZip(final File zip, String pathToWriteTo) throws IOException {
if (!zip.exists()) {
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
zos.putNextEntry(new ZipEntry("dummy"));
zos.write((byte) 1);
return zos;
}
File temp = File.createTempFile("tempRepo", ".zip", zip.getParentFile());
if (!temp.delete()) {
throw new IOException("Unable to delete temp file " + temp.getAbsolutePath());
}
org.apache.commons.io.FileUtils.moveFile(zip, temp);
// Copy contents into new zip file
ZipInputStream readFrom = new ZipInputStream(new FileInputStream(temp));
ZipOutputStream writeTo = new ZipOutputStream(new FileOutputStream(zip));
ZipEntry readEntry = readFrom.getNextEntry();
byte[] buffer = new byte[1024];
while (readEntry != null) {
boolean copyFile = true;
if (pathToWriteTo.endsWith("*")) {
// Ignore this file as the called is about to replace it (if this is the asset itself then all attachments will be deleted too
// as they all startWith the asset name). If pathToWrite to is an attachment then only that attachment should be deleted.
copyFile = !readEntry.getName().startsWith(pathToWriteTo.substring(0, pathToWriteTo.length() - 1));
} else {
// Non wild card ignore so only delete the one file
copyFile = !readEntry.getName().equals(pathToWriteTo);
}
if (copyFile) {
writeTo.putNextEntry(new ZipEntry(readEntry.getName()));
if (!readEntry.isDirectory()) {
int bytesRead;
while ((bytesRead = readFrom.read(buffer)) > 0) {
writeTo.write(buffer, 0, bytesRead);
}
}
}
readEntry = readFrom.getNextEntry();
}
// We've finished reading so can close the input stream now...still need output one
readFrom.close();
temp.delete();
return writeTo;
}
public static void writeDiskRepoJSONToFile(final Asset asset, final File zip, final String path) throws IllegalArgumentException, IllegalAccessException, IOException {
ZipOutputStream zos = appendToZip(zip, path + ".json");
try {
zos.putNextEntry(new ZipEntry(path + ".json"));
asset.dumpMinimalAsset(zos);
} finally {
if (null != zos) {
zos.close();
}
}
}
@Override
public void writeJson(Asset asset, String path) throws IllegalArgumentException, IllegalAccessException, IOException {
writeDiskRepoJSONToFile(asset, _zip, path);
}
public void downloadToFile(InputStream is, final String pathToWriteTo) throws IOException {
// TODO: THIS BLATS THE ZIP FILE, FIND A WAY TO APPEND
System.out.println("Writing " + pathToWriteTo);
ZipOutputStream zos = appendToZip(_zip, pathToWriteTo);
try {
zos.putNextEntry(new ZipEntry(pathToWriteTo));
byte[] buffer = new byte[1024];
int read = 0;
while ((read = is.read(buffer)) != -1) {
zos.write(buffer, 0, read);
}
} finally {
if (null != zos) {
zos.close();
}
if (null != is) {
is.close();
}
}
}
/** {@inheritDoc} */
@Override
public Attachment addAttachment(String assetId, AttachmentSummary attSummary) throws IOException, BadVersionException, RequestFailureException, SecurityException {
File source = attSummary.getFile();
Attachment att = attSummary.getAttachment();
StringBuffer targetPath = new StringBuffer(assetId);
switch (attSummary.getAttachment().getType()) {
case CONTENT:
// target path is right for the main attachment
break;
case DOCUMENTATION:
case ILLUSTRATION:
case THUMBNAIL:
targetPath.append(".");
targetPath.append(attSummary.getAttachment().getType().toString());
targetPath.append(File.separator);
targetPath.append(attSummary.getName());
break;
case LICENSE:
case LICENSE_AGREEMENT:
case LICENSE_INFORMATION:
targetPath.append(".licenses");
targetPath.append(File.separator);
targetPath.append(attSummary.getName());
break;
}
att.setAssetId(assetId);
att.set_id(targetPath.toString());
// We don't really use the URL but to be consistent with massive we can set it to the supplied value or create one if not specified
att.setUrl(attSummary.getURL() == null ? targetPath.toString() : attSummary.getURL());
att.setUploadOn(Calendar.getInstance());
// This is done to give a random value to the attachment, it is only used as a way of ensuring that each time this method is called
// there is some unique value stored in the attachment.
att.setGridFSId("" + Math.random());
InputStream is = DirectoryUtils.createFileInputStream(source);
downloadToFile(is, targetPath.toString());
return att;
}
/** {@inheritDoc} */
@Override
public void deleteAttachment(String assetId, String attachmentId) throws IOException, RequestFailureException {
ZipOutputStream zos = appendToZip(_zip, attachmentId);
zos.close();
}
/** {@inheritDoc} */
@Override
public void deleteAssetAndAttachments(String assetId) throws IOException, RequestFailureException {
ZipOutputStream zos = appendToZip(_zip, assetId + "*");
zos.close();
}
}