/**
* Copyright (C) 2015 Orange
* 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.francetelecom.clara.cloud.activation.plugin.cf.infrastructure;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.francetelecom.clara.cloud.commons.MavenReference;
import com.francetelecom.clara.cloud.commons.TechnicalException;
/**
* Utility class to centralize the fetching of app bits from MavenRef, InputStream or File, and
* provides it into a temp file for further processing
*/
public class FileFetcherUtil {
private static Logger logger = LoggerFactory.getLogger(FileFetcherUtil.class.getName());
/**
* Interface implemented by callers of {@link com.francetelecom.clara.cloud.activation.plugin.cf.infrastructure.FileFetcherUtil}
*/
public static interface FileProcessor {
void process(String filename, String filetype, File file);
}
public FileFetcherUtil() {
}
/**
* Typically invoked by ManageJEEDeploymentImpl.deployOnPaas() using an inputstream read from the SOAP request.
*
* @param filename the original name of the file (e.g. "myapp.ear")
* @param filetype optional file type (e.g. usually extension "jar" "ear" or "war") or null to try to detect it from filename
* @throws TechnicalException
*/
public void fetchInputStreamAndApplyProcessing(String filename, String filetype, InputStream filestream, FileProcessor fileProcessor) throws TechnicalException {
// define filetype regarding file extension
if (filetype == null) {
filetype = getDeployableType(filename);
}
File tempFile = null;
try {
// The CF SDK is requiring local files only, so we need to create a temp local file in a temp directory
tempFile = createTempFileFromInputStream(filename, filestream, filetype);
fileProcessor.process(filename, filetype, tempFile);
} catch (IOException e) {
throw new TechnicalException("IOException on cargo deployment : " + e.getMessage(), e);
} catch (Exception e) {
throw new TechnicalException("Error on stream processing : " + e.getMessage(), e);
} finally {
FileUtils.deleteQuietly(tempFile.getParentFile());
}
}
/**
* Typically invoked by CfPlugin for initial app push.
* @param ref
* @param fileProcessor
*/
void fetchMavenReferenceAndApplyProcessing(MavenReference ref, FileProcessor fileProcessor){
InputStream fileStream = null;
try {
final String filename = (new File(ref.getAccessUrl().getFile())).getName();
String fileType = ref.getExtension();
// file extension should match reference type (mainly ear or rar)
if (!filename.endsWith("." + fileType)) {
throw new TechnicalException("File (" + filename + ") is not a (" + fileType + ") file type");
}
fileStream = ref.getAccessUrl().openStream();
fetchInputStreamAndApplyProcessing(filename, fileType, fileStream, fileProcessor);
} catch (IOException e) {
throw new TechnicalException("URL " + ref.getAccessUrl() + " not available", e);
} finally {
IOUtils.closeQuietly(fileStream);
}
}
/**
* Useful for generated artifact
*/
public void readFileAndApplyProcessing(File file, FileProcessor fileProcessor) {
// Extract filename/extension/stream content from current MavenReference
String filename = file.getName();
fileProcessor.process(filename, null, file);
}
//
// Implementation
//
protected InputStream createInputStreamFromFile(File file) throws FileNotFoundException {
return new FileInputStream(file);
}
private File createTempFileFromInputStream(String filename, InputStream filestream, String filetype) throws IOException {
logger.debug("creating local temporary file for {} deployment", filetype);
File tempDir = this.createTempDirectory();
File tempFile = new File(tempDir, filename);
FileUtils.copyInputStreamToFile(new BufferedInputStream(filestream), tempFile);
logger.debug("temporary file name created : {}", tempFile.getAbsolutePath());
return tempFile;
}
/**
* create a temp file, delete it and create the corresponding directory
*
* @return the temporary directory
*
* @throws IOException
*/
// @TODO : move to utility package
public File createTempDirectory() throws IOException {
final File temp;
temp = File.createTempFile("deploy", "");
if (!(temp.delete())) {
throw new IOException("Could not delete temp file: " + temp.getAbsolutePath());
}
if (!(temp.mkdir())) {
throw new IOException("Could not create temp directory: " + temp.getAbsolutePath());
}
return (temp);
}
public String getDeployableType(String filename) {
String filetype;
try {
filetype = filename.substring(filename.lastIndexOf(".") + 1);
} catch (RuntimeException e) {
throw new TechnicalException("IAAS cargo deployment : incorrect file type, error=" + e.getMessage());
}
if ("xml".equals(filetype)) {
filetype = "file";
} else if ("jar".equals(filetype)) {
filetype = "bundle";
} else if (!"ear".equals(filetype) && !"rar".equals(filetype)) {
throw new TechnicalException("IAAS cargo deployment : incorrect file type (" + filetype + ")");
}
return filetype;
}
}