package hudson.plugins.promoted_builds.integrations.jobdsl; import java.util.Collection; import java.util.Map; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter; import com.thoughtworks.xstream.converters.reflection.ReflectionConverter; import com.thoughtworks.xstream.converters.reflection.ReflectionProvider; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.mapper.Mapper; import groovy.util.Node; import hudson.PluginManager; import hudson.PluginWrapper; import javax.annotation.CheckForNull; import jenkins.model.Jenkins; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; /** * XStream Converter for the PromotionProcess for the Job DSL Plugin * * @author Dennis Schulte */ public class JobDslPromotionProcessConverter extends ReflectionConverter { public JobDslPromotionProcessConverter(Mapper mapper, ReflectionProvider reflectionProvider) { super(mapper, reflectionProvider); } private String classOwnership; private PluginManager pm; @Override public boolean canConvert(@SuppressWarnings("rawtypes") Class type) { return type.equals(JobDslPromotionProcess.class); } @Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { JobDslPromotionProcess promotionProcess = (JobDslPromotionProcess) source; // attributes String plugin = obtainClassOwnership(); if (plugin != null) { writer.addAttribute("plugin", plugin); } // nodes if (promotionProcess != null) { if (promotionProcess.getName() != null) { writer.startNode("name"); writer.setValue(promotionProcess.getName()); writer.endNode(); } if (promotionProcess.getIcon() != null) { writer.startNode("icon"); writer.setValue(promotionProcess.getIcon()); writer.endNode(); } if (promotionProcess.getAssignedLabel() != null) { String assignedLabel = promotionProcess.getAssignedLabel(); if (assignedLabel != null) { writer.startNode("assignedLabel"); writer.setValue(assignedLabel); writer.endNode(); } } if (promotionProcess.getConditions() != null) { writer.startNode("conditions"); context.convertAnother(promotionProcess.getConditions()); writer.endNode(); } if (promotionProcess.getBuildSteps() != null) { writer.startNode("buildSteps"); for (Node node : promotionProcess.getBuildSteps()) { writer.startNode(node.name().toString()); if (node.value() instanceof Collection) { for (Object subNode : (Collection) node.value()) { convertNode((Node) subNode, writer); } } else { writer.setValue(node.value().toString()); } writer.endNode(); } writer.endNode(); } } } private void convertNode(Node node, HierarchicalStreamWriter writer) { writer.startNode(node.name().toString()); writeNodeAttributes(node, writer); if (node.value() instanceof Collection) { for (Object subNode : (Collection) node.value()) { convertNode((Node) subNode, writer); } } else { writer.setValue(node.value().toString()); } writer.endNode(); } private void writeNodeAttributes(Node node, HierarchicalStreamWriter writer) { Map<?,?> attributes = node.attributes(); if (attributes != null) { for (Map.Entry<?,?> entry : attributes.entrySet()) { String key = ObjectUtils.toString(entry.getKey()); String value = ObjectUtils.toString(entry.getValue()); writer.addAttribute(key, value); } } } @CheckForNull private String obtainClassOwnership() { if (this.classOwnership != null) { return this.classOwnership; } if (pm == null) { Jenkins j = Jenkins.getInstance(); if (j != null) { pm = j.getPluginManager(); } } if (pm == null) { return null; } // TODO: possibly recursively scan super class to discover dependencies PluginWrapper p = pm.whichPlugin(hudson.plugins.promoted_builds.PromotionProcess.class); this.classOwnership = p != null ? p.getShortName() + '@' + trimVersion(p.getVersion()) : null; return this.classOwnership; } static String trimVersion(String version) { // TODO seems like there should be some trick with VersionNumber to do // this return version.replaceFirst(" .+$", ""); } }