/**
* Copyright (c) 2008-2012 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sakaiproject.profile2.logic;
import java.util.HashMap;
import java.util.Map;
import lombok.Setter;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.sakaiproject.profile2.dao.ProfileDao;
import org.sakaiproject.profile2.model.ExternalIntegrationInfo;
import org.sakaiproject.profile2.util.ProfileConstants;
import org.sakaiproject.profile2.util.ProfileUtils;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
/**
* Implementation of ProfileExternalIntegrationLogic API
*
* @author Steve Swinsburg (steve.swinsburg@gmail.com)
*
*/
public class ProfileExternalIntegrationLogicImpl implements ProfileExternalIntegrationLogic {
private static final Logger log = Logger.getLogger(ProfileExternalIntegrationLogicImpl.class);
/**
* OAuth Consumer registration details for Profile2.
*/
@Deprecated private final String TWITTER_OAUTH_CONSUMER_KEY="XzSPZIj0LxNaaoBz8XrgZQ";
@Deprecated private final String TWITTER_OAUTH_CONSUMER_SECRET="FSChsnmTufYi3X9H25YdFRxBhPXgnh2H0lMnLh7ZVG4";
/**
* {@inheritDoc}
*/
public ExternalIntegrationInfo getExternalIntegrationInfo(String userUuid) {
ExternalIntegrationInfo info = dao.getExternalIntegrationInfo(userUuid);
if(info != null) {
return info;
}
return getDefaultExternalIntegrationInfo(userUuid);
}
/**
* {@inheritDoc}
*/
public boolean updateExternalIntegrationInfo(ExternalIntegrationInfo info) {
if(dao.updateExternalIntegrationInfo(info)){
log.info("ExternalIntegrationInfo updated for user: " + info.getUserUuid());
return true;
}
return false;
}
/**
* {@inheritDoc}
*/
public Map<String,String> getTwitterOAuthConsumerDetails() {
Map<String,String> map = new HashMap<String,String>();
map.put("key", sakaiProxy.getServerConfigurationParameter("profile2.twitter.oauth.key", TWITTER_OAUTH_CONSUMER_KEY));
map.put("secret", sakaiProxy.getServerConfigurationParameter("profile2.twitter.oauth.secret", TWITTER_OAUTH_CONSUMER_SECRET));
return map;
}
/**
* {@inheritDoc}
*/
public String getTwitterName(ExternalIntegrationInfo info) {
if(info == null){
return null;
}
//get values
String token = info.getTwitterToken();
String secret = info.getTwitterSecret();
if(StringUtils.isNotBlank(token) && StringUtils.isNotBlank(secret)) {
//global config
Map<String,String> config = getTwitterOAuthConsumerDetails();
//token for user
AccessToken accessToken = new AccessToken(token, secret);
//setup
TwitterFactory factory = new TwitterFactory();
Twitter twitter = factory.getInstance();
twitter.setOAuthConsumer(config.get("key"), config.get("secret"));
twitter.setOAuthAccessToken(accessToken);
//check
try {
return twitter.verifyCredentials().getScreenName();
} catch (TwitterException e) {
log.error("Error retrieving Twitter credentials: " + e.getClass() + ": " + e.getMessage());
}
}
return null;
}
/**
* {@inheritDoc}
*/
public boolean validateTwitterCredentials(ExternalIntegrationInfo info) {
return StringUtils.isNotBlank(getTwitterName(info));
}
/**
* {@inheritDoc}
*/
public void sendMessageToTwitter(final String userUuid, String message){
//setup class thread to call later
class TwitterUpdater implements Runnable{
private Thread runner;
private String userUuid;
private String userToken;
private String userSecret;
private String message;
public TwitterUpdater(String userUuid, String userToken, String userSecret, String message) {
this.userUuid=userUuid;
this.userToken=userToken;
this.userSecret=userSecret;
this.message=message;
runner = new Thread(this,"Profile2 TwitterUpdater thread");
runner.start();
}
//do it!
public synchronized void run() {
//global config
Map<String,String> config = getTwitterOAuthConsumerDetails();
//token for user
AccessToken accessToken = new AccessToken(userToken, userSecret);
//setup
TwitterFactory factory = new TwitterFactory();
Twitter twitter = factory.getInstance();
twitter.setOAuthConsumer(config.get("key"), config.get("secret"));
twitter.setOAuthAccessToken(accessToken);
try {
twitter.updateStatus(message);
log.info("Twitter status updated for: " + userUuid);
//post update event
sakaiProxy.postEvent(ProfileConstants.EVENT_TWITTER_UPDATE, "/profile/"+userUuid, true);
}
catch (TwitterException e) {
log.error("ProfileLogic.sendMessageToTwitter() failed. " + e.getClass() + ": " + e.getMessage());
}
}
}
//is twitter enabled
if(!sakaiProxy.isTwitterIntegrationEnabledGlobally()){
return;
}
//get user info
ExternalIntegrationInfo info = getExternalIntegrationInfo(userUuid);
String token = info.getTwitterToken();
String secret = info.getTwitterSecret();
if(StringUtils.isBlank(token) || StringUtils.isBlank(secret)) {
return;
}
//PRFL-423 limit to 140 chars
//Hardcoded limit because 140 is the Twitter requirement so no need to make configurable
message = ProfileUtils.truncate(message, 140, false);
//instantiate class to send the data
new TwitterUpdater(userUuid, token, secret, message);
}
/**
* {@inheritDoc}
*/
public String getGoogleAuthenticationUrl() {
String clientId = sakaiProxy.getServerConfigurationParameter("profile2.integration.google.client-id", null);
if(StringUtils.isBlank(clientId)){
log.error("Google integration not properly configured. Please set the client id");
return null;
}
StringBuilder sb = new StringBuilder();
sb.append("https://accounts.google.com/o/oauth2/auth?");
sb.append("client_id=");
sb.append(clientId);
sb.append("&redirect_uri=");
sb.append(ProfileConstants.GOOGLE_REDIRECT_URI);
sb.append("&response_type=code");
sb.append("&scope=");
sb.append(ProfileConstants.GOOGLE_DOCS_SCOPE);
return sb.toString();
}
/**
* Get a default record, will only contain the userUuid
* @param userUuid
* @return
*/
private ExternalIntegrationInfo getDefaultExternalIntegrationInfo(String userUuid) {
ExternalIntegrationInfo info = new ExternalIntegrationInfo();
info.setUserUuid(userUuid);
return info;
}
@Setter
private ProfileDao dao;
@Setter
private SakaiProxy sakaiProxy;
}