/*
* Copyright (C) 2010 JFrog Ltd.
*
* 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 org.jfrog.bamboo.builder;
import com.atlassian.bamboo.configuration.AdministrationConfiguration;
import com.atlassian.bamboo.configuration.AdministrationConfigurationAccessor;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.jfrog.bamboo.context.AbstractBuildContext;
import org.jfrog.bamboo.util.PluginProperties;
import java.io.*;
import java.util.Arrays;
import java.util.List;
/**
* @author Noam Y. Tenne
*/
public class BuilderDependencyHelper implements Serializable {
private AdministrationConfiguration administrationConfiguration;
private AdministrationConfigurationAccessor administrationConfigurationAccessor;
private String builderKey;
public BuilderDependencyHelper(String builderKey) {
this.builderKey = builderKey;
}
public String downloadDependenciesAndGetPath(File rootDir, AbstractBuildContext context, String dependencyName)
throws IOException {
String pluginKey = PluginProperties.getPluginKey();
String pluginDescriptorKey = PluginProperties.getPluginDescriptorKey();
if (rootDir == null) {
return null;
}
File rootDirParent = rootDir.getParentFile();
//Search for older plugin dirs and remove if any exist
for (File buildDirChild : rootDirParent.listFiles()) {
String buildDirChildName = buildDirChild.getName();
if (buildDirChildName.startsWith(pluginDescriptorKey) &&
(!buildDirChildName.equals(pluginKey) || buildDirChildName.endsWith("-SNAPSHOT"))) {
FileUtils.deleteQuietly(buildDirChild);
buildDirChild.delete();
}
}
File pluginDir = new File(rootDirParent, pluginKey);
File builderDependencyDir = new File(pluginDir, builderKey);
if (builderDependencyDir.isDirectory()) {
// Validates extractor existence
List<String> files = Arrays.asList(builderDependencyDir.list());
if (!files.isEmpty() && files.contains(dependencyName)) {
return builderDependencyDir.getCanonicalPath();
}
} else {
builderDependencyDir.mkdirs();
}
String bambooBaseUrl = getBambooBaseUrl(context);
bambooBaseUrl = StringUtils.stripEnd(bambooBaseUrl, "/");
if (StringUtils.isNotBlank(bambooBaseUrl)) {
StringBuilder builder = new StringBuilder(bambooBaseUrl);
if (!bambooBaseUrl.endsWith("/")) {
builder.append("/");
}
String dependencyBaseUrl = builder.append("download/resources/")
.append(pluginDescriptorKey).append("/builder/dependencies/").toString();
try {
downloadDependencies(dependencyBaseUrl, builderDependencyDir, dependencyName);
return builderDependencyDir.getCanonicalPath();
} catch (IOException ioe) {
FileUtils.deleteDirectory(builderDependencyDir);
throw ioe;
}
}
return null;
}
public void setAdministrationConfiguration(AdministrationConfiguration administrationConfiguration) {
this.administrationConfiguration = administrationConfiguration;
}
public void setAdministrationConfigurationAccessor(
AdministrationConfigurationAccessor administrationConfigurationAccessor) {
this.administrationConfigurationAccessor = administrationConfigurationAccessor;
}
/**
* Returns the base URL of this Bamboo instance.<br> This method is needed since we must download dependencies from
* the Bamboo server.<br> The URL can generally be found in {@link com.atlassian.bamboo.configuration.AdministrationConfiguration},
*
* @param context
* @return Bamboo base URL if found. Null if running in an un-recognized type of agent.
*/
private String getBambooBaseUrl(AbstractBuildContext context) {
if (administrationConfiguration != null) {
return administrationConfiguration.getBaseUrl();
} else if (administrationConfigurationAccessor != null) {
return administrationConfigurationAccessor.getAdministrationConfiguration().getBaseUrl();
} else if (StringUtils.isNotBlank(context.getBaseUrl())) {
return context.getBaseUrl();
}
return null;
}
private void downloadDependencies(String dependencyBaseUrl, File builderDependencyDir, String dependencyFileName)
throws IOException {
HttpClient client = new HttpClient();
String dependencyUrl = dependencyBaseUrl + dependencyFileName;
GetMethod getMethod = new GetMethod(dependencyUrl);
InputStream responseBodyAsStream = null;
FileOutputStream fileOutputStream = null;
try {
int responseStatus;
try {
responseStatus = client.executeMethod(getMethod);
} catch (IOException e) {
throw new IOException("Failed while invoking URL: " + dependencyUrl + " " + e.getMessage());
}
if (responseStatus == HttpStatus.SC_NOT_FOUND) {
throw new IOException("Unable to find required dependency: " + dependencyUrl);
} else if (responseStatus != HttpStatus.SC_OK) {
throw new IOException("Error while requesting required dependency: " + dependencyUrl + ". Status: "
+ responseStatus + ", Message: " + getMethod.getStatusText());
}
responseBodyAsStream = getMethod.getResponseBodyAsStream();
if (responseBodyAsStream == null) {
throw new IOException("Requested dependency: " + dependencyUrl +
", but received a null response stream.");
}
File file = new File(builderDependencyDir, dependencyFileName);
if (!file.isFile()) {
fileOutputStream = new FileOutputStream(file);
IOUtils.copy(responseBodyAsStream, fileOutputStream);
}
} finally {
getMethod.releaseConnection();
IOUtils.closeQuietly(responseBodyAsStream);
IOUtils.closeQuietly(fileOutputStream);
}
}
}