/*
* SoapUI, Copyright (C) 2004-2016 SmartBear Software
*
* Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the Licence for the specific language governing permissions and limitations
* under the Licence.
*/
package com.eviware.soapui.impl.wsdl.support;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.AttachmentConfig;
import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
import com.eviware.soapui.impl.wsdl.teststeps.BeanPathPropertySupport;
import com.eviware.soapui.support.Tools;
import com.eviware.soapui.support.editor.inspectors.attachments.ContentTypeHandler;
import com.eviware.soapui.support.resolver.ResolveContext;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.log4j.Logger;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* Attachments cached locally for each request
*
* @author Ole.Matzura
*/
public abstract class FileAttachment<T extends AbstractWsdlModelItem<?>> implements WsdlAttachment {
private AttachmentConfig config;
private final static Logger log = Logger.getLogger(FileAttachment.class);
private final T modelItem;
private BeanPathPropertySupport urlProperty;
public FileAttachment(T modelItem, AttachmentConfig config) {
this.modelItem = modelItem;
this.config = config;
if (config.getTempFilename() != null) {
try {
log.info("Moving locally cached file [" + config.getTempFilename() + "] to internal cache..");
File tempFile = new File(config.getTempFilename());
cacheFileLocally(tempFile);
} catch (IOException e) {
if (!config.isSetData()) {
config.setData(new byte[0]);
config.setSize(0);
}
SoapUI.logError(e);
}
}
if (isCached()) {
if (config.isSetTempFilename()) {
config.unsetTempFilename();
}
if (config.isSetUrl()) {
config.unsetUrl();
}
}
urlProperty = new BeanPathPropertySupport(modelItem, config, "url");
}
public FileAttachment(T modelItem, File file, boolean cache, AttachmentConfig config) throws IOException {
this(modelItem, config);
config.setName(file.getName());
config.setContentType(ContentTypeHandler.getContentTypeFromFilename(file.getName()));
config.setContentId(file.getName());
config.setId(UUID.randomUUID().toString());
// cache locally if specified
if (cache) {
cacheFileLocally(file);
}
urlProperty.set(file.getPath(), false);
}
public void setName(String value) {
config.setName(value);
}
public void setUrl(String url) {
urlProperty.set(url, true);
}
public void reload(File file, boolean cache) throws IOException {
config.setName(file.getName());
config.setContentType(ContentTypeHandler.getContentTypeFromFilename(file.getName()));
config.setContentId(file.getName());
// cache locally if specified
if (cache) {
cacheFileLocally(file);
} else {
urlProperty.set(file.getPath(), false);
config.unsetData();
}
}
public T getModelItem() {
return modelItem;
}
public void cacheFileLocally(File file) throws FileNotFoundException, IOException {
// write attachment-data to tempfile
ByteArrayOutputStream data = new ByteArrayOutputStream();
ZipOutputStream out = new ZipOutputStream(data);
out.putNextEntry(new ZipEntry(config.getName()));
InputStream in = new FileInputStream(file);
long sz = file.length();
config.setSize(sz);
Tools.writeAll(out, in);
in.close();
out.closeEntry();
out.finish();
out.close();
data.close();
config.setData(data.toByteArray());
}
public String getContentType() {
AttachmentEncoding encoding = getEncoding();
if (encoding == AttachmentEncoding.NONE) {
return config.getContentType();
} else {
return "application/octet-stream";
}
}
public InputStream getInputStream() throws IOException {
BufferedInputStream inputStream = null;
if (isCached()) {
ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(config.getData()));
zipInputStream.getNextEntry();
inputStream = new BufferedInputStream(zipInputStream);
} else {
String url = urlProperty.expand();
inputStream = new BufferedInputStream(url == null ? new ByteArrayInputStream(new byte[0])
: new FileInputStream(url));
}
AttachmentEncoding encoding = getEncoding();
if (encoding == AttachmentEncoding.BASE64) {
ByteArrayOutputStream data = Tools.readAll(inputStream, Tools.READ_ALL);
return new ByteArrayInputStream(Base64.encodeBase64(data.toByteArray()));
} else if (encoding == AttachmentEncoding.HEX) {
ByteArrayOutputStream data = Tools.readAll(inputStream, Tools.READ_ALL);
return new ByteArrayInputStream(new String(Hex.encodeHex(data.toByteArray())).getBytes());
}
return inputStream;
}
public String getName() {
return config.getName();
}
public long getSize() {
if (isCached()) {
return config.getSize();
} else {
String url = urlProperty.expand();
if (url != null) {
File file = new File(url);
if (file.exists()) {
return file.length();
}
}
}
return -1;
}
public void release() {
if (isCached()) {
new File(config.getTempFilename()).delete();
}
}
public String getPart() {
return config.getPart();
}
public void setContentType(String contentType) {
config.setContentType(contentType);
}
public void setPart(String part) {
config.setPart(part);
}
public void setData(byte[] data) {
try {
// write attachment-data to tempfile
ByteArrayOutputStream tempData = new ByteArrayOutputStream();
ZipOutputStream out = new ZipOutputStream(tempData);
out.putNextEntry(new ZipEntry(config.getName()));
config.setSize(data.length);
out.write(data);
out.closeEntry();
out.finish();
out.close();
config.setData(tempData.toByteArray());
} catch (Exception e) {
SoapUI.logError(e);
}
}
public byte[] getData() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Tools.writeAll(out, getInputStream());
return out.toByteArray();
}
public String getUrl() {
return urlProperty.get();
}
public boolean isCached() {
return config.isSetData();
}
abstract public AttachmentType getAttachmentType();
public void updateConfig(AttachmentConfig config) {
this.config = config;
urlProperty.setConfig(config);
}
public AttachmentConfig getConfig() {
return config;
}
public void setContentID(String contentID) {
if ((contentID == null || contentID.length() == 0) && config.isSetContentId()) {
config.unsetContentId();
} else {
config.setContentId(contentID);
}
}
public String getContentID() {
return config.getContentId();
}
public void resolve(ResolveContext<?> context) {
if (!isCached()) {
urlProperty.resolveFile(context, "Missing attachment [" + getName() + "]", null, null, false);
}
}
public String getContentEncoding() {
AttachmentEncoding encoding = getEncoding();
if (encoding == AttachmentEncoding.BASE64) {
return "base64";
} else if (encoding == AttachmentEncoding.HEX) {
return "hex";
} else {
return "binary";
}
}
public void addExternalDependency(List<ExternalDependency> dependencies) {
if (!isCached()) {
dependencies.add(new PathPropertyExternalDependency(urlProperty));
}
}
}