/********************************************************************************
* CruiseControl, a Continuous Integration Toolkit
* Copyright (c) 2007, ThoughtWorks, Inc.
* 200 E. Randolph, 25th Floor
* Chicago, IL 60601 USA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* + Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* + Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
********************************************************************************/
package net.sourceforge.cruisecontrol.publishers;
import java.io.File;
import net.sourceforge.cruisecontrol.CruiseControlException;
import net.sourceforge.cruisecontrol.Publisher;
import net.sourceforge.cruisecontrol.util.ValidationHelper;
import net.sourceforge.cruisecontrol.util.XMLLogHelper;
import org.apache.log4j.Logger;
import org.jdom.Element;
import ymsg.network.Session;
import ymsg.network.StatusConstants;
import ymsg.network.AccountLockedException;
import ymsg.network.LoginRefusedException;
/**
* Publisher which establishes this transport to publish build results via Yahoo
* Instant Messaging framework.
*
* Parameters are: username - required - YahooId (should not be an eMail
* address) password - required - Password for YahooId recipient - required -
* YahooId (no eMail, please), to which the message should be send
* buildResultsURL - required - You know... proxyHost - not required - since we
* are using HTTP connection, a HTTP Proxy proxyPort - not required - the port
* for the HTTP Proxy
*
* @author <a href="mailto:mmay@gmx.net">Markus M. May</a>
* @version 1.0
*/
public class YahooPublisher implements Publisher {
private static final Logger LOG = Logger.getLogger(YahooPublisher.class);
private static Session connection;
private String username;
private String password;
private String recipient;
private String buildResultsURL;
private String proxyHost = null;
private String proxyPort = null;
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setRecipient(String recipient) {
this.recipient = recipient;
}
public void setBuildResultsURL(String buildResultsURL) {
this.buildResultsURL = buildResultsURL;
}
/**
* Setter for proxyHost
*
* @param pProxyHost
* proxyHost
*/
public void setProxyHost(String pProxyHost) {
this.proxyHost = pProxyHost;
}
/**
* Setter for proxyPort
*
* @param pProxyPort
* proxyPort
*/
public void setProxyPort(String pProxyPort) {
this.proxyPort = pProxyPort;
}
/**
* Validate that all the mandatory parameters were specified in order to
* properly initial the Yahoo client service. Note that this is called after
* the configuration file is read.
*
* @throws CruiseControlException
* if there was a configuration error.
*/
public void validate() throws CruiseControlException {
ValidationHelper
.assertIsSet(this.username, "username", this.getClass());
ValidationHelper
.assertFalse(
this.isEmail(this.username),
"'username' is not in correct format. "
+ "'username' should not be of the form user@domain.com");
ValidationHelper
.assertIsSet(this.password, "password", this.getClass());
ValidationHelper.assertIsSet(this.recipient, "recipient", this
.getClass());
ValidationHelper
.assertFalse(
this.isEmail(this.recipient),
"'recipient' is not in correct format. "
+ "'recipient' should not be of the form user@domain.com");
}
private boolean isEmail(final String name) {
return name.indexOf("@") != -1;
}
/**
* Publish the results to the Yahoo transport via an instant message.
*/
public void publish(Element cruisecontrolLog) throws CruiseControlException {
boolean status = this.connect();
XMLLogHelper helper = new XMLLogHelper(cruisecontrolLog);
String message = createMessage(helper);
if (status) {
try {
YahooPublisher.connection.sendMessage(recipient, message);
Thread.sleep(5 * 1000);
} catch (Exception e) {
LOG.error("Error sending message to buddy: " + e.getMessage());
}
}
}
/**
* connect to the server and set necessary info.
*/
public synchronized boolean connect() {
boolean result = false;
// Set proxy-information, when needed
if (this.proxyHost != null) {
System.setProperty("http.proxyHost", this.proxyHost);
}
if (this.proxyPort != null) {
System.setProperty("http.proxyPort", this.proxyPort);
}
// Check if connection already exists
if (YahooPublisher.connection != null
&& YahooPublisher.connection.getSessionStatus() == StatusConstants.MESSAGING) {
result = true;
} else {
// Create new connection with given parameters
YahooPublisher.connection = new Session();
try {
YahooPublisher.connection.login(this.username, this.password);
// Did we successfully log in?
if (YahooPublisher.connection.getSessionStatus() == StatusConstants.MESSAGING) {
result = true;
LOG.debug("User " + this.username
+ " sucessfully connected");
} else {
LOG.error("Error logging " + this.username
+ " in to the Yahoo-system");
}
} catch (AccountLockedException e) {
LOG.error("The account " + this.username
+ " seems to be locked.");
} catch (LoginRefusedException e) {
LOG
.error("Yahoo refused the connection. Username/password incorrect?");
} catch (Exception e) {
LOG.error("Error logging in: " + e.getMessage());
}
if (result) {
LOG.debug(this.username + " connected...");
try {
YahooPublisher.connection
.setStatus(StatusConstants.STATUS_INVISIBLE);
} catch (Exception e) {
LOG.error("Error setting status: " + e.getMessage());
}
}
}
return result;
}
/**
* Creates the IM message body. This currently creates a message that is a
* link to a web page with the details of the build.
*
* @return <code>String</code> the link that makes up the body of the IM
* message
*/
protected String createMessage(XMLLogHelper logHelper)
throws CruiseControlException {
String logFileName = logHelper.getLogFileName();
String baseLogFileName = logFileName.substring(logFileName
.lastIndexOf(File.separator) + 1, logFileName.lastIndexOf("."));
StringBuffer message = new StringBuffer();
message.append("Build results for ");
message.append(logHelper.isBuildSuccessful() ? "successful" : "failed");
message.append(" build of project ");
message.append(logHelper.getProjectName());
message.append(": ");
message.append(this.buildResultsURL);
if (this.buildResultsURL.indexOf("?") == -1) {
message.append("?");
} else {
message.append("&");
}
message.append("log=");
message.append(baseLogFileName);
return message.toString();
}
}