package com.slide.hudson.plugins;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.model.Result;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
import hudson.tasks.Publisher;
import hudson.util.CopyOnWriteList;
import hudson.util.FormValidation;
import java.io.IOException;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.sf.json.JSONObject;
import jcifs.smb.NtlmAuthenticator;
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import org.kohsuke.stapler.StaplerRequest;
/**
* <p>
* This class implements the ftp publisher process by using the {@link FTPSite}.
* </p>
* <p>
* HeadURL: $HeadURL: http://z-bld-02:8080/zxdev/zxant_test_environment/trunk/formatting/codeTemplates.xml $<br />
* Date: $Date: 2008-04-22 11:53:34 +0200 (Di, 22 Apr 2008) $<br />
* Revision: $Revision: 2451 $<br />
* </p>
*
* @author $Author: ZANOX-COM\fit $
*
*/
public class CIFSPublisher extends Notifier {
/**
* Hold an instance of the Descriptor implementation of this publisher.
*/
@Extension
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
private String shareName;
private final List<Entry> entries = new ArrayList<Entry>();
private String winsServer;
//private Boolean flatten = true;
// public void setFlatten(boolean flatten) {
// this.flatten = flatten;
// }
//
// public boolean isFlatten() {
// return flatten;
// }
public void setWinsServer(String winsServer) {
this.winsServer = winsServer;
}
public CIFSPublisher() {
}
/**
* The constructor which take a configured ftp site name to publishing the artifacts.
*
* @param siteName
* the name of the ftp site configuration to use
*/
public CIFSPublisher(String shareName) {
this.shareName = shareName;
}
/**
* The getter for the entries field. (this field is set by the UI part of this plugin see config.jelly file)
*
* @return the value of the entries field
*/
public List<Entry> getEntries() {
return entries;
}
/**
* This method returns the configured FTPSite object which match the siteName of the FTPPublisher instance. (see Manage Hudson and System
* Configuration point FTP)
*
* @return the matching FTPSite or null
*/
public CIFSShare getShare() {
CIFSShare[] shares = DESCRIPTOR.getShares();
if (shareName == null && shares.length > 0) {
// default
return shares[0];
}
for (CIFSShare share : shares) {
if (share.getServer().equals(shareName)) {
return share;
}
}
return null;
}
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.BUILD;
}
/**
* {@inheritDoc}
*
* @param build
* @param launcher
* @param listener
* @return
* @throws InterruptedException
* @throws IOException
* {@inheritDoc}
* @see hudson.tasks.BuildStep#perform(hudson.model.Build, hudson.Launcher, hudson.model.BuildListener)
*/
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
if (build.getResult() == Result.FAILURE || build.getResult() == Result.ABORTED) {
// build failed. don't post
return true;
}
CIFSShare share = null;
try {
share = getShare();
listener.getLogger().println("Connecting to " + share.getServer());
EntryCopier copier = new EntryCopier(build, listener, share);
if(winsServer != null && winsServer.length() > 0) {
System.setProperty("jcifs.netbios.wins", winsServer);
}
int copied = 0;
for (Entry e : entries) {
copied += copier.copy(e);
}
listener.getLogger().println("Transfered " + copied + " files.");
} catch (Throwable th) {
th.printStackTrace(listener.error("Failed to upload files"));
build.setResult(Result.UNSTABLE);
}
return true;
}
/**
* <p>
* This class holds the metadata for the FTPPublisher.
* </p>
*
* @author $Author: ZANOX-COM\fit $
* @see Descriptor
*/
public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {
private final CopyOnWriteList<CIFSShare> shares = new CopyOnWriteList<CIFSShare>();
/**
* The default constructor.
*/
public DescriptorImpl() {
super(CIFSPublisher.class);
load();
}
/**
* The name of the plugin to display them on the project configuration web page.
*
* {@inheritDoc}
*
* @return {@inheritDoc}
* @see hudson.model.Descriptor#getDisplayName()
*/
@Override
public String getDisplayName() {
return "Publish artifacts to CIFS";
}
/**
* Return the location of the help document for this publisher.
*
* {@inheritDoc}
*
* @return {@inheritDoc}
* @see hudson.model.Descriptor#getHelpFile()
*/
@Override
public String getHelpFile() {
return "/plugin/cifspublisher/help.html";
}
@Override
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}
/**
* This method is called by hudson if the user has clicked the add button of the CIFS share hosts point in the System Configuration
* web page. It's create a new instance of the {@link CIFSPublisher} class and added all configured CIFS shares to this instance by calling
* the method {@link CIFSPublisher#getEntries()} and on it's return value the addAll method is called.
*
* {@inheritDoc}
*
* @param req
* {@inheritDoc}
* @return {@inheritDoc}
* @see hudson.model.Descriptor#newInstance(org.kohsuke.stapler.StaplerRequest)
*/
@Override
public Publisher newInstance(StaplerRequest req, JSONObject formData) {
CIFSPublisher pub = new CIFSPublisher();
pub.setWinsServer(formData.getString("winsServer"));
//pub.setFlatten(formData.getBoolean("flatten"));
//pub.setUseTimestamps(formData.getBoolean("useTimestamps"));
req.bindParameters(pub, "publisher.");
req.bindParameters(pub, "cifs.");
pub.getEntries().addAll(req.bindParametersToList(Entry.class, "cifs.entry."));
return pub;
}
/**
* The getter of the sites field.
*
* @return the value of the sites field.
*/
public CIFSShare[] getShares() {
Iterator<CIFSShare> it = shares.iterator();
int size = 0;
while (it.hasNext()) {
it.next();
size++;
}
return shares.toArray(new CIFSShare[size]);
}
/**
* {@inheritDoc}
*
* @param req
* {@inheritDoc}
* @return {@inheritDoc}
* @see hudson.model.Descriptor#configure(org.kohsuke.stapler.StaplerRequest)
*/
@Override
public boolean configure(StaplerRequest req, JSONObject formData) {
shares.replaceBy(req.bindParametersToList(CIFSShare.class, "cifs."));
save();
return true;
}
/**
* This method validates the current entered CIFS configuration data. That is made by create a CIFS connection.
*
* @param request
* the current {@link javax.servlet.http.HttpServletRequest}
*/
public FormValidation doLoginCheck(StaplerRequest request) {
String server = Util.fixEmpty(request.getParameter("server"));
String domain = Util.fixEmptyAndTrim(request.getParameter("domain"));
String user = Util.fixEmptyAndTrim(request.getParameter("user"));
String password = Util.fixEmptyAndTrim(request.getParameter("pass"));
if (server == null) { // server is not entered yet
return FormValidation.ok();
}
CIFSShare share = new CIFSShare(server, request.getParameter("port"), request.getParameter("timeOut"), user,
password, domain);
share.setShareName(request.getParameter("shareDir"));
try {
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(domain,
user, password);
SmbFile serv = new SmbFile(share.getUrl());
if(serv.exists()) {
SmbFile file = new SmbFile(share.getUrl(), auth);
if(file.exists() && file.isFile()) {
return FormValidation.error("Destination is a file");
} else {
return FormValidation.ok();
}
} else {
return FormValidation.error("Server does not exist.");
}
} catch (Exception e) {
return FormValidation.error(e.getMessage());
}
}
}
}