/*******************************************************************************
*
* Copyright (c) 2010-2011 Sonatype, Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*
*
*
*
*******************************************************************************/
package org.hudsonci.maven.plugin.builder;
import org.hudsonci.maven.plugin.builder.internal.BuildConfigurationExtractor;
import org.hudsonci.maven.plugin.documents.DocumentManager;
import org.hudsonci.maven.plugin.install.MavenInstallation;
import org.hudsonci.service.SecurityService;
import org.hudsonci.utils.plugin.ui.JellyAccessible;
import org.hudsonci.utils.plugin.ui.RenderableEnum;
import org.hudsonci.maven.model.PropertiesDTO;
import org.hudsonci.maven.model.config.BuildConfigurationDTO;
import org.hudsonci.maven.model.config.ChecksumModeDTO;
import org.hudsonci.maven.model.config.DocumentDTO;
import org.hudsonci.maven.model.config.DocumentTypeDTO;
import org.hudsonci.maven.model.config.FailModeDTO;
import org.hudsonci.maven.model.config.MakeModeDTO;
import org.hudsonci.maven.model.config.SnapshotUpdateModeDTO;
import org.hudsonci.maven.model.config.VerbosityDTO;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import hudson.XmlFile;
import hudson.model.AbstractProject;
import hudson.model.Descriptor;
import hudson.model.Hudson;
import hudson.security.ACL;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Builder;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
import javax.enterprise.inject.Typed;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.hudsonci.maven.model.ModelUtil.renderList;
import static org.hudsonci.maven.model.ModelUtil.renderProperties;
import static org.hudsonci.maven.model.config.DocumentTypeDTO.SETTINGS;
import static org.hudsonci.maven.model.config.DocumentTypeDTO.TOOLCHAINS;
/**
* {@link MavenBuilder} descriptor.
*
* Contains configuration information about the builder. When adding new
* options update {@link #DEFAULTS} and {@link #createConfiguration(JSONObject)}
* with the default and UI translator.
*
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
* @since 2.1.0
*/
@Named
@Singleton
@Typed(Descriptor.class)
@XStreamAlias("maven-builder-descriptor")
public class MavenBuilderDescriptor
extends BuildStepDescriptor<Builder>
{
public static final BuildConfigurationDTO DEFAULTS = new BuildConfigurationDTO()
.withGoals("clean install")
.withPomFile("pom.xml")
.withPrivateRepository(false) // may take up a lot of disk space if many jobs, so leave off by default
.withPrivateTmpdir(false) // may cause problems with paths with spaces, so leave off by default
.withOffline(false)
.withRecursive(true)
.withErrors(false)
.withVerbosity(VerbosityDTO.NORMAL)
.withChecksumMode(ChecksumModeDTO.NORMAL)
.withFailMode(FailModeDTO.NORMAL)
.withMakeMode(MakeModeDTO.NONE)
.withSnapshotUpdateMode(SnapshotUpdateModeDTO.NORMAL);
public static final String DESCRIPTOR_FILE_NAME = "maven-builder-descriptor.xml";
@XStreamOmitField
private final SecurityService security;
@XStreamOmitField
private final DocumentManager documents;
@XStreamOmitField
private final MavenInstallation.DescriptorImpl installationDescriptor;
private BuildConfigurationDTO defaults = DEFAULTS;
@Inject
public MavenBuilderDescriptor(final SecurityService security,
final DocumentManager documents,
final MavenInstallation.DescriptorImpl installationDescriptor)
{
super(MavenBuilder.class);
this.security = checkNotNull(security);
this.documents = checkNotNull(documents);
this.installationDescriptor = checkNotNull(installationDescriptor);
load();
}
@Override
public String getDisplayName() {
return "Invoke Maven 3";
}
@Override
public boolean isApplicable(final Class<? extends AbstractProject> type) {
return true;
}
@Override
public XmlFile getConfigFile() {
return new XmlFile(new File(Hudson.getInstance().getRootDir(), DESCRIPTOR_FILE_NAME));
}
@JellyAccessible
public BuildConfigurationDTO getDefaults() {
return defaults;
}
public DocumentManager getDocuments() {
return documents;
}
public void setDefaults(final BuildConfigurationDTO defaults) {
this.defaults = checkNotNull(defaults);
save();
}
@JellyAccessible
public RenderableEnum[] getVerbosityValues() {
return RenderableEnum.forEnum(VerbosityDTO.class);
}
@JellyAccessible
public RenderableEnum[] getChecksumModeValues() {
return RenderableEnum.forEnum(ChecksumModeDTO.class);
}
@JellyAccessible
public RenderableEnum[] getFailModeValues() {
return RenderableEnum.forEnum(FailModeDTO.class);
}
@JellyAccessible
public RenderableEnum[] getMakeModeValues() {
return RenderableEnum.forEnum(MakeModeDTO.class);
}
@JellyAccessible
public RenderableEnum[] getSnapshotUpdateModeValues() {
return RenderableEnum.forEnum(SnapshotUpdateModeDTO.class);
}
@JellyAccessible
public Collection<DocumentDTO> getSettingsDocuments() {
return getDocuments(SETTINGS);
}
@JellyAccessible
public Collection<DocumentDTO> getToolChainsDocuments() {
return getDocuments(TOOLCHAINS);
}
private Collection<DocumentDTO> getDocuments(final DocumentTypeDTO type) {
checkNotNull(type);
// Need to run as SYSTEM when fetching the documents to be used
return security.callAs2(ACL.SYSTEM, new Callable<Collection<DocumentDTO>>()
{
public Collection<DocumentDTO> call() {
return documents.getDocuments(type, true);
}
});
}
/**
* Determine if a value is selected. If the value equals the configured value or the configured
* value is null and value equals the default value, then it is selected.
*
* @param value The value, from an enum items or something; never null.
* @param configValue The instance configuration value; may be null.
* @param defaultValue The descriptor default value; may be null.
* @return True if the value is selected.
*/
@JellyAccessible
public boolean isSelected(final Object value, final Object configValue, final Object defaultValue) {
assert value != null;
return value.equals(configValue) || (configValue == null && value.equals(defaultValue));
}
/**
* Determine the value to be used. If the given value is non-null then it will be used, else the default value will be used.
* For use when jelly tag does not expose a default attribute, only a value attribute.
*/
@JellyAccessible
public Object valueOf(final Object value, final Object defaultValue) {
return value != null ? value : defaultValue;
}
/**
* Determine the value to be used for the given properties and render.
*/
@JellyAccessible
public String valueOf(final PropertiesDTO value, final PropertiesDTO defaultValue) {
return renderProperties(value != null ? value : defaultValue);
}
/**
* Determine the value to be used for the given lists and render.
*/
@JellyAccessible
public String valueOf(final List<String> value, final List<String> defaultValue) {
return renderList(value != null ? value : defaultValue);
}
@JellyAccessible
public MavenInstallation[] getInstallations() {
return checkNotNull(installationDescriptor).getInstallations();
}
/**
* Configure the defaults.
*/
@Override
public boolean configure(final StaplerRequest req, final JSONObject data) throws FormException {
setDefaults(createConfiguration(data));
return true;
}
/**
* Create a new instance.
*/
@Override
public Builder newInstance(final StaplerRequest req, final JSONObject data) throws FormException {
return new MavenBuilder(createConfiguration(data));
}
/**
* Create a configuration object from the given JSON data.
*/
private BuildConfigurationDTO createConfiguration(final JSONObject data) {
return new BuildConfigurationExtractor(data).extract();
}
}