package com.amazonaws.eclipse.codedeploy.appspec.model;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import org.eclipse.core.runtime.FileLocator;
import org.osgi.framework.Bundle;
import com.amazonaws.eclipse.codedeploy.CodeDeployPlugin;
import com.amazonaws.eclipse.codedeploy.appspec.util.JacksonUtils;
import com.amazonaws.protocol.json.SdkJsonGenerator.JsonGenerationException;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
public class AppspecTemplateMetadataModel {
private final String metadataVersion;
private final String templateName;
private final String templateDescription;
private final String templateBasedir;
// Use boxed Boolean so that we can differentiate a non-specified boolean value
private final Boolean isCustomTemplate;
private final String warFileExportLocationWithinDeploymentArchive;
private final boolean useDefaultHttpPortParameter;
private final boolean useDefaultContextPathParameter;
private final List<AppspecTemplateParameter> parameters;
@JsonCreator
public AppspecTemplateMetadataModel(
@JsonProperty("metadataVersion") String metadataVersion,
@JsonProperty("templateName") String templateName,
@JsonProperty("templateDescription") String templateDescription,
@JsonProperty("templateBasedir") String templateBasedir,
@JsonProperty("isCustomTemplate") Boolean isCustomTemplate,
@JsonProperty("warFileExportLocationWithinDeploymentArchive") String warFileExportLocationWithinDeploymentArchive,
@JsonProperty("useDefaultHttpPortParameter") boolean useDefaultHttpPortParameter,
@JsonProperty("useDefaultContextPathParameter") boolean useDefaultContextPathParameter,
@JsonProperty("parameters") List<AppspecTemplateParameter> parameters) {
this.metadataVersion = metadataVersion;
this.templateName = templateName;
this.templateDescription = templateDescription;
this.templateBasedir = templateBasedir;
this.isCustomTemplate = isCustomTemplate;
this.warFileExportLocationWithinDeploymentArchive = warFileExportLocationWithinDeploymentArchive;
this.useDefaultHttpPortParameter = useDefaultHttpPortParameter;
this.useDefaultContextPathParameter = useDefaultContextPathParameter;
this.parameters = parameters;
}
public String getMetadataVersion() {
return metadataVersion;
}
public String getTemplateName() {
return templateName;
}
public String getTemplateDescription() {
return templateDescription;
}
public String getTemplateBasedir() {
return templateBasedir;
}
@JsonIgnore
public File getResolvedTemplateBasedir() {
if (isCustomTemplate) {
return new File(templateBasedir);
} else {
Bundle bundle = CodeDeployPlugin.getDefault().getBundle();
URL bundleBaseUrl;
try {
bundleBaseUrl = FileLocator.resolve(bundle.getEntry("/"));
} catch (IOException e) {
throw new RuntimeException(
"Failed to resolve root entry in the CodeDeploy plugin bundle", e);
}
// Relative to the bundle root
return new File(bundleBaseUrl.getFile(), templateBasedir);
}
}
public boolean getIsCustomTemplate() {
return isCustomTemplate;
}
public String getWarFileExportLocationWithinDeploymentArchive() {
return warFileExportLocationWithinDeploymentArchive;
}
public boolean isUseDefaultHttpPortParameter() {
return useDefaultHttpPortParameter;
}
public boolean isUseDefaultContextPathParameter() {
return useDefaultContextPathParameter;
}
public List<AppspecTemplateParameter> getParameters() {
return parameters;
}
/*
* Utility functions for loading or outputing the metadata model.
*/
public static AppspecTemplateMetadataModel loadFromFile(File metadataFile, boolean validateAfterLoaded) {
if ( !metadataFile.exists() ) {
throw new RuntimeException(String.format(
"The template metadata file [%s] doesn't exist.", metadataFile.getAbsolutePath()));
}
if ( !metadataFile.isFile() ) {
throw new RuntimeException(String.format(
"The specified location [%s] is not a file.", metadataFile.getAbsolutePath()));
}
try {
AppspecTemplateMetadataModel model = JacksonUtils.MAPPER.readValue(metadataFile, AppspecTemplateMetadataModel.class);
if (validateAfterLoaded) {
model.validate();
}
return model;
} catch (JsonParseException e) {
throw new RuntimeException(
"Failed to parse metadata file at " + metadataFile.getAbsolutePath(), e);
} catch (JsonMappingException e) {
throw new RuntimeException(
"Failed to parse metadata file at " + metadataFile.getAbsolutePath(), e);
} catch (IOException e) {
throw new RuntimeException(
"Failed to read metadata file at " + metadataFile.getAbsolutePath(), e);
}
}
public void writeToFile(File destination) {
try {
JacksonUtils.MAPPER.writeValue(destination, this);
} catch (JsonGenerationException e) {
throw new RuntimeException(
"Failed to serialize metadata model into JSON string.", e);
} catch (JsonMappingException e) {
throw new RuntimeException(
"Failed to serialize metadata model into JSON string.", e);
} catch (IOException e) {
throw new RuntimeException(
"Failed to write metadata to file " + destination.getAbsolutePath(), e);
}
}
/**
* @throw IllegalArgumentException if the template model is not valid
*/
@JsonIgnore
public void validate() {
checkRequiredFields();
checkVersion();
checkTemplateBaseDir();
checkTemplateParameters();
}
private void checkRequiredFields() {
if (metadataVersion == null)
throw new IllegalArgumentException("metadataVersion is not specified.");
if (templateName == null)
throw new IllegalArgumentException("templateName is not specified.");
if (templateDescription == null)
throw new IllegalArgumentException("templateDescription is not specified.");
if (templateBasedir == null)
throw new IllegalArgumentException("templateBasedir is not specified.");
if (isCustomTemplate == null)
throw new IllegalArgumentException("isCustomTemplate is not specified.");
if (warFileExportLocationWithinDeploymentArchive == null)
throw new IllegalArgumentException("warFileExportLocationWithinDeploymentArchive is not specified.");
}
private void checkVersion() {
if ( !"1.0".equals(metadataVersion) )
throw new IllegalArgumentException("Unsupported metadata version: " + metadataVersion);
}
private void checkTemplateBaseDir() {
checkTemplateBaseDir(getResolvedTemplateBasedir());
}
private void checkTemplateBaseDir(File basedir) {
if ( !basedir.exists() ) {
throw new IllegalArgumentException(String.format(
"The template base directory[%s] doesn't exist.", basedir.getAbsolutePath()));
}
if ( !basedir.isDirectory() ) {
throw new IllegalArgumentException(String.format(
"The specified location[%s] is not a directory.", basedir.getAbsolutePath()));
}
File appspecFile = new File(basedir, "appspec.yml");
if ( !appspecFile.exists() || !appspecFile.isFile() ) {
throw new IllegalArgumentException(String.format(
"The appspec file doesn't exist at the specified location[%s].", appspecFile.getAbsolutePath()));
}
}
private void checkTemplateParameters() {
if (parameters != null) {
for (AppspecTemplateParameter parameter : parameters) {
parameter.validate();
}
}
}
@Override
public String toString() {
try {
return JacksonUtils.MAPPER.writeValueAsString(this);
} catch (Exception e) {
throw new RuntimeException(
"Failed to serialize metadata model into JSON string.", e);
}
}
}