/*
* Sonar Twitter Plugin
* Copyright (C) 2010 SonarSource
* dev@sonar.codehaus.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.plugins.twitter;
import static org.sonar.plugins.twitter.TwitterPlugin.HOST_DEFAULT_VALUE;
import static org.sonar.plugins.twitter.TwitterPlugin.HOST_PROPERTY;
import static org.sonar.plugins.twitter.TwitterPlugin.PASSWORD_PROPERTY;
import static org.sonar.plugins.twitter.TwitterPlugin.TWITTER_TOKEN;
import static org.sonar.plugins.twitter.TwitterPlugin.TWITTER_TOKEN_ID;
import static org.sonar.plugins.twitter.TwitterPlugin.TWITTER_TOKEN_SECRET;
import static org.sonar.plugins.twitter.TwitterPlugin.USERNAME_PROPERTY;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.commons.configuration.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.PostJob;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.Project;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.http.AccessToken;
import twitter4j.http.RequestToken;
/**
* @author Evgeny Mandrikov
* @author Akram Ben Aissi
*/
public class TwitterPublisher implements PostJob {
private static final String PROJECT_INDEX_URI = "/project/index/";
private final static Logger LOG = LoggerFactory.getLogger(TwitterPublisher.class);
private final static TwitterFactory FACTORY = new TwitterFactory();
private final Twitter twitter = FACTORY.getInstance();
public final void executeOn(Project project, SensorContext context) {
Configuration configuration = project.getConfiguration();
String hostUrl = configuration.getString(HOST_PROPERTY, HOST_DEFAULT_VALUE);
try {
AccessToken accessToken = loadAccessToken(configuration);
if (accessToken.getToken() == null || accessToken.getTokenSecret() == null) {
authenticate(configuration);
accessToken = loadAccessToken(configuration);
}
StringBuilder url = new StringBuilder(hostUrl).append(PROJECT_INDEX_URI).append(project.getKey());
String status = String.format("Sonar analysis of %s is available at %s", project.getName(), url);
updateStatus(status);
} catch (TwitterException e) {
LOG.error("Exception updating Twitter status: " + e.getMessage());
} catch (IOException e) {
LOG.error("Exception updating Twitter status: " + e.getMessage());
}
}
protected void updateStatus(String message) throws TwitterException {
LOG.info("Updating Twitter status to: '{}'", message);
Status status = twitter.updateStatus(message);
LOG.info("Successfully updated the status to [" + status.getText() + "].");
}
private void authenticate(Configuration configuration) throws TwitterException, IOException {
String key = configuration.getString(USERNAME_PROPERTY);
String secret = configuration.getString(PASSWORD_PROPERTY);
twitter.setOAuthConsumer(key, secret);
RequestToken requestToken = twitter.getOAuthRequestToken();
AccessToken accessToken = null;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (null == accessToken) {
LOG.info("Open the following URL and grant access to your account:");
LOG.info(requestToken.getAuthorizationURL());
LOG.info("Enter the PIN(if aviailable) or just hit enter.[PIN]:");
String pin = br.readLine();
try {
if (pin.length() > 0) {
accessToken = twitter.getOAuthAccessToken(requestToken, pin);
} else {
accessToken = twitter.getOAuthAccessToken();
}
} catch (TwitterException te) {
if (401 == te.getStatusCode()) {
LOG.error("Unable to get the access token.");
} else {
LOG.error("Unexpected Twitter error: " + te.getMessage(), te);
}
}
}
int id = twitter.verifyCredentials().getId();
// persist to the accessToken for future reference.
storeAccessToken(configuration, id, accessToken);
// unset clear password on the configuration
configuration.setProperty(USERNAME_PROPERTY, null);
configuration.setProperty(PASSWORD_PROPERTY, null);
}
private void storeAccessToken(Configuration configuration, int id, AccessToken accessToken) {
configuration.setProperty(TWITTER_TOKEN, accessToken.getToken());
configuration.setProperty(TWITTER_TOKEN_SECRET, accessToken.getTokenSecret());
configuration.setProperty(TWITTER_TOKEN_ID, id);
}
private AccessToken loadAccessToken(Configuration configuration) {
String token = configuration.getString(TWITTER_TOKEN);
String tokenSecret = configuration.getString(TWITTER_TOKEN_SECRET);
return new AccessToken(token, tokenSecret);
}
}