INT-1553, Initial overhaul and simplification to the OAuth package, tests
This commit is contained in:
@@ -18,13 +18,10 @@ package org.springframework.integration.twitter.config;
|
||||
|
||||
import static org.springframework.integration.twitter.config.TwitterNamespaceHandler.BASE_PACKAGE;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for the 'twitter-connection' element.
|
||||
@@ -37,7 +34,7 @@ public class ConnectionParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
return BASE_PACKAGE + ".oauth.OAuthConfigurationFactoryBean";
|
||||
return BASE_PACKAGE + ".oauth.OAuthTwitterFactoryBean";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,15 +44,22 @@ public class ConnectionParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
String ref = element.getAttribute("twitter-connection");
|
||||
if (StringUtils.hasText(ref)) {
|
||||
builder.addPropertyReference("twitterConnection", ref);
|
||||
}
|
||||
else {
|
||||
for (String attribute : new String[] { "consumer-key", "consumer-secret", "access-token", "access-token-secret" }) {
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attribute);
|
||||
}
|
||||
}
|
||||
// String ref = element.getAttribute("twitter-connection");
|
||||
// if (StringUtils.hasText(ref)) {
|
||||
// builder.addPropertyReference("twitterConnection", ref);
|
||||
// }
|
||||
// else {
|
||||
// for (String attribute : new String[] { "consumer-key", "consumer-secret", "access-token", "access-token-secret" }) {
|
||||
// IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attribute);
|
||||
// }
|
||||
// }
|
||||
|
||||
BeanDefinitionBuilder accessTokenBuilder = BeanDefinitionBuilder.genericBeanDefinition("twitter4j.http.AccessToken");
|
||||
accessTokenBuilder.addConstructorArgValue(element.getAttribute("access-token"));
|
||||
accessTokenBuilder.addConstructorArgValue(element.getAttribute("access-token-secret"));
|
||||
builder.addConstructorArgValue(element.getAttribute("consumer-key"));
|
||||
builder.addConstructorArgValue(element.getAttribute("consumer-secret"));
|
||||
builder.addConstructorArgValue(accessTokenBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class TwitterReceivingMessageSourceParser extends AbstractPollingInboundC
|
||||
parserContext.getReaderContext().error("element '" + elementName + "' is not supported by this parser.", element);
|
||||
}
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(className);
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "twitter-connection", "configuration");
|
||||
builder.addConstructorArgReference(element.getAttribute("twitter-connection"));
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup");
|
||||
String name = BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry());
|
||||
return new RuntimeBeanReference(name);
|
||||
|
||||
@@ -46,7 +46,7 @@ public class TwitterSendingMessageHandlerParser extends AbstractOutboundChannelA
|
||||
className = BASE_PACKAGE + ".outbound.DirectMessageSendingMessageHandler";
|
||||
}
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(className);
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "twitter-connection", "configuration");
|
||||
builder.addConstructorArgReference(element.getAttribute("twitter-connection"));
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.springframework.integration.history.TrackableComponent;
|
||||
import org.springframework.integration.store.MetadataStore;
|
||||
import org.springframework.integration.store.SimpleMetadataStore;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.twitter.oauth.OAuthConfiguration;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -62,15 +61,13 @@ public abstract class AbstractTwitterMessageSource<T> extends AbstractEndpoint
|
||||
|
||||
private volatile String metadataKey;
|
||||
|
||||
protected volatile OAuthConfiguration configuration;
|
||||
|
||||
protected final Queue<Object> tweets = new LinkedBlockingQueue<Object>();
|
||||
|
||||
protected volatile int prefetchThreshold = 0;
|
||||
|
||||
protected volatile long markerId = -1;
|
||||
|
||||
protected Twitter twitter;
|
||||
protected final Twitter twitter;
|
||||
|
||||
private final Object markerGuard = new Object();
|
||||
|
||||
@@ -78,10 +75,13 @@ public abstract class AbstractTwitterMessageSource<T> extends AbstractEndpoint
|
||||
|
||||
private final HistoryWritingMessagePostProcessor historyWritingPostProcessor = new HistoryWritingMessagePostProcessor();
|
||||
|
||||
|
||||
public void setConfiguration(OAuthConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
public AbstractTwitterMessageSource(Twitter twitter){
|
||||
this.twitter = twitter;
|
||||
}
|
||||
//
|
||||
// public void setConfiguration(OAuthConfiguration configuration) {
|
||||
// this.configuration = configuration;
|
||||
// }
|
||||
|
||||
public void setShouldTrack(boolean shouldTrack) {
|
||||
this.historyWritingPostProcessor.setShouldTrack(shouldTrack);
|
||||
@@ -98,7 +98,7 @@ public abstract class AbstractTwitterMessageSource<T> extends AbstractEndpoint
|
||||
@Override
|
||||
protected void onInit() throws Exception{
|
||||
super.onInit();
|
||||
Assert.notNull(this.configuration, "'configuration' can't be null");
|
||||
//Assert.notNull(this.configuration, "'configuration' can't be null");
|
||||
if (this.metadataStore == null) {
|
||||
// first try to look for a 'messageStore' in the context
|
||||
BeanFactory beanFactory = this.getBeanFactory();
|
||||
@@ -122,7 +122,7 @@ public abstract class AbstractTwitterMessageSource<T> extends AbstractEndpoint
|
||||
else if (logger.isWarnEnabled()) {
|
||||
logger.warn(this.getClass().getSimpleName() + " has no name. MetadataStore key might not be unique.");
|
||||
}
|
||||
metadataKeyBuilder.append(this.configuration.getConsumerKey());
|
||||
//metadataKeyBuilder.append(this.configuration.getConsumerKey());
|
||||
this.metadataKey = metadataKeyBuilder.toString();
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ public abstract class AbstractTwitterMessageSource<T> extends AbstractEndpoint
|
||||
|
||||
@Override
|
||||
protected void doStart(){
|
||||
this.twitter = this.configuration.getTwitter();
|
||||
//this.twitter = this.configuration.getTwitter();
|
||||
Assert.notNull(this.twitter, "'twitter' instance can't be null");
|
||||
historyWritingPostProcessor.setTrackableComponent(this);
|
||||
RateLimitStatusTrigger trigger = new RateLimitStatusTrigger(this.twitter);
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.integration.MessagingException;
|
||||
|
||||
import twitter4j.DirectMessage;
|
||||
import twitter4j.Paging;
|
||||
import twitter4j.Twitter;
|
||||
|
||||
/**
|
||||
* This class handles support for receiving DMs (direct messages) using Twitter.
|
||||
@@ -32,6 +33,10 @@ import twitter4j.Paging;
|
||||
*/
|
||||
public class DirectMessageReceivingMessageSource extends AbstractTwitterMessageSource<DirectMessage> {
|
||||
|
||||
public DirectMessageReceivingMessageSource(Twitter twitter){
|
||||
super(twitter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComponentType() {
|
||||
return "twitter:inbound-dm-channel-adapter";
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.springframework.integration.MessagingException;
|
||||
|
||||
import twitter4j.Paging;
|
||||
import twitter4j.Status;
|
||||
import twitter4j.Twitter;
|
||||
|
||||
/**
|
||||
* Handles forwarding all new {@link twitter4j.Status} that are 'replies' or 'mentions' to some other tweet.
|
||||
@@ -30,6 +31,9 @@ import twitter4j.Status;
|
||||
*/
|
||||
public class MentionReceivingMessageSource extends AbstractTwitterMessageSource<Status> {
|
||||
|
||||
public MentionReceivingMessageSource(Twitter twitter){
|
||||
super(twitter);
|
||||
}
|
||||
@Override
|
||||
public String getComponentType() {
|
||||
return "twitter:inbound-mention-channel-adapter";
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.springframework.integration.MessagingException;
|
||||
|
||||
import twitter4j.Paging;
|
||||
import twitter4j.Status;
|
||||
import twitter4j.Twitter;
|
||||
|
||||
|
||||
/**
|
||||
@@ -30,7 +31,10 @@ import twitter4j.Status;
|
||||
* @since 2.0
|
||||
*/
|
||||
public class TimelineUpdateReceivingMessageSource extends AbstractTwitterMessageSource<Status> {
|
||||
|
||||
|
||||
public TimelineUpdateReceivingMessageSource(Twitter twitter){
|
||||
super(twitter);
|
||||
}
|
||||
@Override
|
||||
public String getComponentType() {
|
||||
return "twitter:inbound-update-channel-adapter";
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.integration.twitter.oauth;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import twitter4j.http.AccessToken;
|
||||
import twitter4j.http.RequestToken;
|
||||
|
||||
|
||||
/**
|
||||
* base-class for {@link org.springframework.integration.twitter.oauth.OAuthAccessTokenBasedTwitterFactoryBean}.
|
||||
* <p/>
|
||||
* Provides hooks so that subclasses able to reference a concrete implementation of the generic type parameter can call methods for us. Most hooks are to handle the case
|
||||
* of the first time subscription, where no accessToken is present.
|
||||
*
|
||||
* @author Josh Long
|
||||
* @param <T>
|
||||
* @see org.springframework.integration.twitter.oauth.OAuthAccessTokenBasedTwitterFactoryBean
|
||||
* @since 2.0
|
||||
*/
|
||||
abstract public class AbstractOAuthAccessTokenBasedFactoryBean<T> implements InitializingBean, FactoryBean<T> {
|
||||
protected OAuthConfiguration configuration;
|
||||
protected final Object monitor = new Object();
|
||||
protected volatile T twitter;
|
||||
protected volatile boolean initialized = false;
|
||||
|
||||
/**
|
||||
* Standard {@link org.springframework.beans.factory.FactoryBean} method. Implementations may override if there's a specific method
|
||||
*
|
||||
* @return whether or not this is a singleton
|
||||
*/
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rubber meets the road: builds up a reference to the twitter4j.(Async)Twitter instance
|
||||
*
|
||||
* @return the instance
|
||||
* @throws Exception thrown in case some condition isn't met correctly in construction
|
||||
*/
|
||||
public T getObject() throws Exception {
|
||||
if (!initialized) {
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
return this.twitter;
|
||||
}
|
||||
/**
|
||||
* provides lifecycle for initiation of the reference. By the time this method is left we should have a fully configured twitter connection that can connect and make calls
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
synchronized (this.monitor) {
|
||||
|
||||
Assert.notNull(this.configuration.getConsumerKey(), "'consumerKey' mustn't be null");
|
||||
Assert.notNull(this.configuration.getConsumerSecret(), "'consumerSecret' mustn't be null");
|
||||
|
||||
AccessToken accessTokenObj=null;
|
||||
establishTwitterObject(accessTokenObj);
|
||||
if (StringUtils.hasText(this.configuration.getAccessToken()) && StringUtils.hasText(this.configuration.getAccessTokenSecret())) {
|
||||
accessTokenObj = new AccessToken(this.configuration.getAccessToken(), this.configuration.getAccessTokenSecret());
|
||||
}
|
||||
establishTwitterObject(accessTokenObj);
|
||||
|
||||
Assert.notNull(accessTokenObj, "'accessTokenObj' can't be null");
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Nasty little bit of circular indirection here: the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration} hosts the String values for authentication,
|
||||
* which we need to build up this instance, but the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration} in turn needs references to the instances provided by
|
||||
* this {@link org.springframework.beans.factory.FactoryBean}. So, they collaborate and guard each others state. Ultimately, clients should use {@link org.springframework.integration.twitter.oauth.OAuthConfiguration}
|
||||
* to correctly any implementations of this factory bean as well as the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration} reference itself.
|
||||
*
|
||||
* @param configuration the configuration object
|
||||
*/
|
||||
protected AbstractOAuthAccessTokenBasedFactoryBean(OAuthConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* This probably doesn't belong here. It's more for support for running the {@link OAuthAccessTokenBasedTwitterFactoryBean} or
|
||||
* {@link OAuthAccessTokenBasedTwitterFactoryBean} methods that run the user through a command line tool to approve a user for the first
|
||||
* time if the user hasn't obtained her {@code accessToken } yet
|
||||
*
|
||||
* @param resource the resource where properties file lives
|
||||
* @return returns a fully configured {@link java.util.Properties} instance
|
||||
* @throws Exception thrown if anythign goes wrong
|
||||
*/
|
||||
protected static Properties fromResource(Resource resource)
|
||||
throws Exception {
|
||||
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
|
||||
propertiesFactoryBean.setLocation(resource);
|
||||
propertiesFactoryBean.setSingleton(true);
|
||||
propertiesFactoryBean.afterPropertiesSet();
|
||||
|
||||
return propertiesFactoryBean.getObject();
|
||||
}
|
||||
|
||||
public abstract void establishTwitterObject(AccessToken accessToken)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* because we are not able to dereference the {@link twitter4j.Twitter} or {@link twitter4j.AsyncTwitter} instances, we need to ask subclasses to call
|
||||
* us how to call {@link twitter4j.AsyncTwitter#getOAuthRequestToken()} or {@link twitter4j.Twitter#getOAuthRequestToken()} for us.This method
|
||||
* will never be evaluated as long as the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration#accessToken}
|
||||
* and {@link org.springframework.integration.twitter.oauth.OAuthConfiguration#accessTokenSecret} beans are not null.
|
||||
*
|
||||
* @return the {@link twitter4j.http.RequestToken} as vended by the service. Ths will contain a verification URl required to obtain an access key and secret.
|
||||
* @throws Exception thrown if anything should go wrong
|
||||
*/
|
||||
public abstract RequestToken getOAuthRequestToken()
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Only used if the impementation is trying to get an {@link twitter4j.http.AccessToken} for the first time. This method
|
||||
* will never be evaluated as long as the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration#accessToken}
|
||||
* and {@link org.springframework.integration.twitter.oauth.OAuthConfiguration#accessTokenSecret} beans are not null.
|
||||
*
|
||||
* @param token the initiating {@link twitter4j.http.RequestToken}
|
||||
* @param pin the string returned from the verification URL
|
||||
* @return returns the {@link twitter4j.http.AccessToken} fetched from the twitter service.
|
||||
* @throws Exception thrown if anything should go wrong
|
||||
*/
|
||||
public abstract AccessToken getOAuthAccessToken(RequestToken token, String pin)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Only used if the impementation is trying to get an {@link twitter4j.http.AccessToken} for the first time. This method
|
||||
* will never be evaluated as long as the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration#accessToken}
|
||||
* and {@link org.springframework.integration.twitter.oauth.OAuthConfiguration#accessTokenSecret} beans are not null.
|
||||
*
|
||||
* @return returns the {@link twitter4j.http.AccessToken} fetched from the twitter service.
|
||||
* @throws Exception thrown if anything should go wrong
|
||||
*/
|
||||
public abstract AccessToken getOAuthAccessToken() throws Exception;
|
||||
|
||||
/**
|
||||
* Responsibility of subclasses to call this because we cant dereference the generic type appropriately. The responsibility is
|
||||
* to call {@link twitter4j.Twitter#verifyCredentials()} or {@link twitter4j.AsyncTwitter#verifyCredentials()} as appropriate
|
||||
*
|
||||
* @throws Exception if there's an inability to authenticate
|
||||
*/
|
||||
public abstract void verifyCredentials() throws Exception;
|
||||
|
||||
/**
|
||||
* this method is delegated to implementations because we can't correctly dereference the generic type's class
|
||||
*
|
||||
* @return a class
|
||||
*/
|
||||
abstract public Class<?> getObjectType();
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.integration.twitter.oauth;
|
||||
|
||||
import twitter4j.http.AccessToken;
|
||||
|
||||
|
||||
/**
|
||||
* if the factory bean isn't provided a 'accesstoken' and 'accesstokensecret', then it will try to obtain those bits of informatio on the users behalf.
|
||||
* <p/>
|
||||
* In doing so it will need input fro the user (automatic or human intervention is required)
|
||||
*
|
||||
* @author Josh Long
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface AccessTokenInitialRequestProcessListener {
|
||||
|
||||
String openUrlAndReturnPin(String urlToOpen) throws Exception;
|
||||
|
||||
void persistReturnedAccessToken(AccessToken accessToken) throws Exception;
|
||||
|
||||
void failure(Throwable t);
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.integration.twitter.oauth;
|
||||
|
||||
import twitter4j.Twitter;
|
||||
import twitter4j.TwitterFactory;
|
||||
import twitter4j.http.AccessToken;
|
||||
import twitter4j.http.RequestToken;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Josh Long
|
||||
* @since 2.0
|
||||
*/
|
||||
public class OAuthAccessTokenBasedTwitterFactoryBean extends AbstractOAuthAccessTokenBasedFactoryBean<Twitter> {
|
||||
protected OAuthAccessTokenBasedTwitterFactoryBean(OAuthConfiguration configuration) {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void establishTwitterObject(AccessToken accessToken)
|
||||
throws Exception {
|
||||
this.twitter = new TwitterFactory().getOAuthAuthorizedInstance(this.configuration.getConsumerKey(), this.configuration.getConsumerSecret(), accessToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestToken getOAuthRequestToken() throws Exception {
|
||||
return twitter.getOAuthRequestToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verifyCredentials() throws Exception {
|
||||
this.twitter.verifyCredentials();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessToken getOAuthAccessToken(RequestToken token, String pin)
|
||||
throws Exception {
|
||||
return this.twitter.getOAuthAccessToken(token, pin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessToken getOAuthAccessToken() throws Exception {
|
||||
return this.twitter.getOAuthAccessToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Twitter.class;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.integration.twitter.oauth;
|
||||
|
||||
import twitter4j.Twitter;
|
||||
|
||||
|
||||
/**
|
||||
* Simple bean we can use to store the configuration and store shared references to both an {@link twitter4j.AsyncTwitter}
|
||||
* and an {@link twitter4j.Twitter} instance.
|
||||
* <p/>
|
||||
* client should store this bean and simply lookup the Twitter configuration from there
|
||||
* @author Josh Long
|
||||
* @since 2.0
|
||||
*/
|
||||
public class OAuthConfiguration {
|
||||
|
||||
private Twitter twitter;
|
||||
private volatile String consumerKey;
|
||||
private volatile String consumerSecret;
|
||||
private volatile String accessToken;
|
||||
private volatile String accessTokenSecret;
|
||||
|
||||
public OAuthConfiguration(String consumerKey, String consumerSecret, String accessToken, String accessTokenSecret) {
|
||||
this.consumerKey = consumerKey;
|
||||
this.consumerSecret = consumerSecret;
|
||||
this.accessToken = accessToken;
|
||||
this.accessTokenSecret = accessTokenSecret;
|
||||
}
|
||||
|
||||
void setTwitter(Twitter twitter) {
|
||||
this.twitter = twitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public Twitter getTwitter() {
|
||||
return twitter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getConsumerKey() {
|
||||
return consumerKey;
|
||||
}
|
||||
|
||||
public void setConsumerKey(String consumerKey) {
|
||||
this.consumerKey = consumerKey;
|
||||
}
|
||||
|
||||
public String getConsumerSecret() {
|
||||
return consumerSecret;
|
||||
}
|
||||
|
||||
public void setConsumerSecret(String consumerSecret) {
|
||||
this.consumerSecret = consumerSecret;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public String getAccessTokenSecret() {
|
||||
return accessTokenSecret;
|
||||
}
|
||||
|
||||
public void setAccessTokenSecret(String accessTokenSecret) {
|
||||
this.accessTokenSecret = accessTokenSecret;
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.integration.twitter.oauth;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.util.Assert;
|
||||
import twitter4j.Twitter;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
* Center piece for configuration for all the twitter adapters
|
||||
*
|
||||
* @author Josh Long
|
||||
* @since 2.0
|
||||
*/
|
||||
public class OAuthConfigurationFactoryBean implements FactoryBean<OAuthConfiguration> {
|
||||
public static final String WELL_KNOWN_CONSUMER_KEY = "twitter.oauth.consumerKey";
|
||||
public static final String WELL_KNOWN_CONSUMER_KEY_SECRET = "twitter.oauth.consumerSecret";
|
||||
public static final String WELL_KNOWN_CONSUMER_ACCESS_TOKEN = "twitter.oauth.accessToken";
|
||||
public static final String WELL_KNOWN_CONSUMER_ACCESS_TOKEN_SECRET = "twitter.oauth.accessTokenSecret";
|
||||
private volatile String consumerKey;
|
||||
private volatile String consumerSecret;
|
||||
private volatile String accessToken;
|
||||
private volatile String accessTokenSecret;
|
||||
private Twitter twitter;
|
||||
private volatile OAuthConfiguration oAuthConfiguration;
|
||||
private final Object guard = new Object();
|
||||
|
||||
private Twitter twitter(OAuthConfiguration oAuthConfiguration)
|
||||
throws Exception {
|
||||
OAuthAccessTokenBasedTwitterFactoryBean twitterFactoryBean = new OAuthAccessTokenBasedTwitterFactoryBean(oAuthConfiguration);
|
||||
twitterFactoryBean.afterPropertiesSet();
|
||||
twitterFactoryBean.verifyCredentials();
|
||||
|
||||
return twitterFactoryBean.getObject();
|
||||
}
|
||||
|
||||
protected void bootstrapFromProperties(Properties props)
|
||||
throws Throwable {
|
||||
Assert.notNull(props, "'properties' must not be null");
|
||||
this.setAccessToken(props.getProperty(WELL_KNOWN_CONSUMER_ACCESS_TOKEN));
|
||||
this.setAccessTokenSecret(props.getProperty(WELL_KNOWN_CONSUMER_ACCESS_TOKEN_SECRET));
|
||||
this.setConsumerKey(props.getProperty(WELL_KNOWN_CONSUMER_KEY));
|
||||
this.setConsumerSecret(props.getProperty(WELL_KNOWN_CONSUMER_KEY_SECRET));
|
||||
}
|
||||
|
||||
public OAuthConfiguration getObject() throws Exception {
|
||||
return build();
|
||||
}
|
||||
|
||||
public Class<?> getObjectType() {
|
||||
return OAuthConfiguration.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setConsumerKey(String consumerKey) {
|
||||
this.consumerKey = consumerKey;
|
||||
}
|
||||
|
||||
public void setConsumerSecret(String consumerSecret) {
|
||||
this.consumerSecret = consumerSecret;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public void setAccessTokenSecret(String accessTokenSecret) {
|
||||
this.accessTokenSecret = accessTokenSecret;
|
||||
}
|
||||
|
||||
private OAuthConfiguration build() throws Exception {
|
||||
synchronized (this.guard) {
|
||||
if (oAuthConfiguration == null) {
|
||||
oAuthConfiguration = new OAuthConfiguration(this.consumerKey, this.consumerSecret, this.accessToken, this.accessTokenSecret);
|
||||
twitter = this.twitter(oAuthConfiguration);
|
||||
oAuthConfiguration.setTwitter(twitter);
|
||||
}
|
||||
}
|
||||
|
||||
return this.oAuthConfiguration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.integration.twitter.oauth;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import twitter4j.Twitter;
|
||||
import twitter4j.TwitterFactory;
|
||||
import twitter4j.http.AccessToken;
|
||||
|
||||
/**
|
||||
* Will create an OAuth-Authorized instance of Twitter object.
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class OAuthTwitterFactoryBean implements FactoryBean<Twitter>, InitializingBean {
|
||||
private final String consumerKey;
|
||||
private final String consumerSecret;
|
||||
private final AccessToken accessToken;
|
||||
|
||||
private volatile Twitter twitter;
|
||||
|
||||
public OAuthTwitterFactoryBean(String consumerKey, String consumerSecret, AccessToken accessToken){
|
||||
Assert.hasText(consumerKey, "'consumerKey' must be provided");
|
||||
Assert.hasText(consumerSecret, "'consumerSecret' must be provided");
|
||||
Assert.notNull(accessToken, "'accessToken' must be provided");
|
||||
this.consumerKey = consumerKey;
|
||||
this.consumerSecret = consumerSecret;
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
@Override
|
||||
public Twitter getObject() throws Exception {
|
||||
Assert.notNull(this.twitter, "OAuthTwitterFactoryBean must be initialized. Invoke afterPropertiesSet() method");
|
||||
return twitter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Twitter.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.twitter = new TwitterFactory().getOAuthAuthorizedInstance(consumerKey, consumerSecret, accessToken);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
package org.springframework.integration.twitter.outbound;
|
||||
|
||||
import org.springframework.integration.handler.AbstractMessageHandler;
|
||||
import org.springframework.integration.twitter.oauth.OAuthConfiguration;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import twitter4j.Twitter;
|
||||
@@ -29,19 +28,23 @@ import twitter4j.Twitter;
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractOutboundTwitterEndpointSupport extends AbstractMessageHandler {
|
||||
protected volatile OAuthConfiguration configuration;
|
||||
protected volatile Twitter twitter;
|
||||
//protected volatile OAuthConfiguration configuration;
|
||||
protected final Twitter twitter;
|
||||
protected final OutboundStatusUpdateMessageMapper supportStatusUpdate = new OutboundStatusUpdateMessageMapper();
|
||||
|
||||
public void setConfiguration(OAuthConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
public AbstractOutboundTwitterEndpointSupport(Twitter twitter){
|
||||
Assert.notNull(twitter, "'twitter' must not be null");
|
||||
this.twitter = twitter;
|
||||
}
|
||||
// public void setConfiguration(OAuthConfiguration configuration) {
|
||||
// this.configuration = configuration;
|
||||
// }
|
||||
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
Assert.notNull(this.configuration, "'configuration' can't be null");
|
||||
this.twitter = this.configuration.getTwitter();
|
||||
Assert.notNull(this.twitter, "'twitter' can't be null");
|
||||
}
|
||||
// @Override
|
||||
// protected void onInit() throws Exception {
|
||||
// Assert.notNull(this.configuration, "'configuration' can't be null");
|
||||
// this.twitter = this.configuration.getTwitter();
|
||||
// Assert.notNull(this.twitter, "'twitter' can't be null");
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.twitter.core.TwitterHeaders;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import twitter4j.Twitter;
|
||||
import twitter4j.TwitterException;
|
||||
|
||||
/**
|
||||
@@ -32,6 +33,10 @@ import twitter4j.TwitterException;
|
||||
*/
|
||||
public class DirectMessageSendingMessageHandler extends AbstractOutboundTwitterEndpointSupport {
|
||||
|
||||
public DirectMessageSendingMessageHandler(Twitter twitter){
|
||||
super(twitter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleMessageInternal(Message<?> message) throws Exception {
|
||||
if (this.twitter == null) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.springframework.integration.Message;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import twitter4j.StatusUpdate;
|
||||
import twitter4j.Twitter;
|
||||
|
||||
|
||||
/**
|
||||
@@ -28,6 +29,11 @@ import twitter4j.StatusUpdate;
|
||||
* @since 2.0
|
||||
*/
|
||||
public class TimelineUpdateSendingMessageHandler extends AbstractOutboundTwitterEndpointSupport {
|
||||
|
||||
public TimelineUpdateSendingMessageHandler(Twitter twitter){
|
||||
super(twitter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleMessageInternal(Message<?> message) throws Exception {
|
||||
StatusUpdate statusUpdate = this.supportStatusUpdate.fromMessage(message);
|
||||
|
||||
@@ -17,27 +17,29 @@
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd http://www.springframework.org/schema/integration/twitter http://www.springframework.org/schema/integration/twitter/spring-integration-twitter.xsd">
|
||||
|
||||
|
||||
<beans:bean id="tc" class="org.mockito.Mockito" factory-method="mock">
|
||||
<beans:constructor-arg value="org.springframework.integration.twitter.oauth.OAuthConfiguration"/>
|
||||
</beans:bean>
|
||||
<twitter:twitter-connection id="twitter"
|
||||
consumer-key="consumerKey"
|
||||
consumer-secret="consumerSecret"
|
||||
access-token="accessToken"
|
||||
access-token-secret="accessTokenSecret"/>
|
||||
|
||||
<channel id="inbound_mentions"/>
|
||||
|
||||
<twitter:inbound-mention-channel-adapter id="mentionAdapter"
|
||||
twitter-connection="tc"
|
||||
twitter-connection="twitter"
|
||||
channel="inbound_mentions"
|
||||
auto-startup="false">
|
||||
<poller fixed-rate="5000" max-messages-per-poll="3"/>
|
||||
</twitter:inbound-mention-channel-adapter>
|
||||
|
||||
<twitter:inbound-dm-channel-adapter id="dmAdapter"
|
||||
twitter-connection="tc"
|
||||
twitter-connection="twitter"
|
||||
channel="inbound_mentions"
|
||||
auto-startup="false">
|
||||
<poller fixed-rate="5000" max-messages-per-poll="3"/>
|
||||
</twitter:inbound-dm-channel-adapter>
|
||||
<twitter:inbound-update-channel-adapter id="updateAdapter"
|
||||
twitter-connection="tc"
|
||||
twitter-connection="twitter"
|
||||
channel="inbound_mentions"
|
||||
auto-startup="false">
|
||||
<poller fixed-rate="5000" max-messages-per-poll="3"/>
|
||||
|
||||
@@ -14,18 +14,23 @@
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
|
||||
http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool-3.0.xsd
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd http://www.springframework.org/schema/integration/twitter http://www.springframework.org/schema/integration/twitter/spring-integration-twitter.xsd">
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd
|
||||
http://www.springframework.org/schema/integration/twitter http://www.springframework.org/schema/integration/twitter/spring-integration-twitter-2.0.xsd">
|
||||
|
||||
|
||||
<beans:bean id="tc" class="org.springframework.integration.twitter.config.TestSendingMessageHandlerParserTests.MockOathConfigurationFactoryBean"/>
|
||||
|
||||
<twitter:twitter-connection id="twitter"
|
||||
consumer-key="consumerKey"
|
||||
consumer-secret="consumerSecret"
|
||||
access-token="accessToken"
|
||||
access-token-secret="accessTokenSecret"/>
|
||||
|
||||
<channel id="inbound_mentions"/>
|
||||
|
||||
<channel id="inputChannel"/>
|
||||
|
||||
<twitter:outbound-dm-channel-adapter twitter-connection="tc" channel="inputChannel"/>
|
||||
<twitter:outbound-dm-channel-adapter twitter-connection="twitter" channel="inputChannel" />
|
||||
|
||||
<twitter:outbound-update-channel-adapter twitter-connection="tc" channel="inputChannel"/>
|
||||
<twitter:outbound-update-channel-adapter twitter-connection="twitter" channel="inputChannel" />
|
||||
|
||||
</beans:beans>
|
||||
|
||||
|
||||
@@ -15,15 +15,8 @@
|
||||
*/
|
||||
package org.springframework.integration.twitter.config;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.twitter.oauth.OAuthConfiguration;
|
||||
|
||||
import twitter4j.Twitter;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
@@ -36,22 +29,4 @@ public class TestSendingMessageHandlerParserTests {
|
||||
new ClassPathXmlApplicationContext("TestSendingMessageHandlerParser-context.xml", this.getClass());
|
||||
// the fact that no exception was thrown satisfies this test
|
||||
}
|
||||
|
||||
public static class MockOathConfigurationFactoryBean implements FactoryBean<OAuthConfiguration>{
|
||||
|
||||
public OAuthConfiguration getObject() throws Exception {
|
||||
OAuthConfiguration config = mock(OAuthConfiguration.class);
|
||||
Twitter twitter = mock(Twitter.class);
|
||||
when(config.getTwitter()).thenReturn(twitter);
|
||||
return config;
|
||||
}
|
||||
|
||||
public Class<?> getObjectType() {
|
||||
return OAuthConfiguration.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:twitter="http://www.springframework.org/schema/integration/twitter"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd
|
||||
http://www.springframework.org/schema/integration/twitter http://www.springframework.org/schema/integration/twitter/spring-integration-twitter-2.0.xsd">
|
||||
|
||||
|
||||
<twitter:twitter-connection id="twitter"
|
||||
consumer-key="consumerKey"
|
||||
consumer-secret="consumerSecret"
|
||||
access-token="accessToken"
|
||||
access-token-secret="accessTokenSecret"/>
|
||||
|
||||
</beans:beans>
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.integration.twitter.config;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.twitter.oauth.OAuthTwitterFactoryBean;
|
||||
|
||||
import twitter4j.Twitter;
|
||||
import twitter4j.http.AccessToken;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public class TwitterConnectionParserTests {
|
||||
|
||||
@Test
|
||||
public void testOAuthTwitterFactoryBean(){
|
||||
ApplicationContext ac = new ClassPathXmlApplicationContext("TwitterConnectionParserTests-context.xml", this.getClass());
|
||||
OAuthTwitterFactoryBean twitterFb = ac.getBean("&twitter", OAuthTwitterFactoryBean.class);
|
||||
assertEquals("consumerKey", TestUtils.getPropertyValue(twitterFb, "consumerKey"));
|
||||
assertEquals("consumerSecret", TestUtils.getPropertyValue(twitterFb, "consumerSecret"));
|
||||
AccessToken accessToken = (AccessToken) TestUtils.getPropertyValue(twitterFb, "accessToken");
|
||||
assertEquals("accessToken", accessToken.getToken());
|
||||
assertEquals("accessTokenSecret", accessToken.getTokenSecret());
|
||||
Twitter twitter = ac.getBean("twitter", Twitter.class);
|
||||
assertTrue(twitter.isOAuthEnabled());
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.integration.twitter.inbound;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -30,11 +27,6 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.twitter.oauth.OAuthConfiguration;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
|
||||
import twitter4j.DirectMessage;
|
||||
import twitter4j.Paging;
|
||||
import twitter4j.RateLimitStatus;
|
||||
@@ -86,24 +78,24 @@ public class InboundDirectMessageStatusEndpointTests {
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private OAuthConfiguration getTestConfigurationForDirectMessages() throws Exception{
|
||||
OAuthConfiguration configuration = mock(OAuthConfiguration.class);
|
||||
RateLimitStatus rateLimitStatus = mock(RateLimitStatus.class);
|
||||
when(twitter.getRateLimitStatus()).thenReturn(rateLimitStatus);
|
||||
when(configuration.getTwitter()).thenReturn(twitter);
|
||||
when(rateLimitStatus.getSecondsUntilReset()).thenReturn(2464);
|
||||
when(rateLimitStatus.getRemainingHits()).thenReturn(250);
|
||||
|
||||
ResponseList<DirectMessage> responses = mock(ResponseList.class);
|
||||
List<DirectMessage> testMessages = new ArrayList<DirectMessage>();
|
||||
testMessages.add(firstMessage);
|
||||
testMessages.add(secondMessage);
|
||||
|
||||
when(responses.iterator()).thenReturn(testMessages.iterator());
|
||||
when(twitter.getDirectMessages()).thenReturn(responses);
|
||||
when(twitter.getDirectMessages(Mockito.any(Paging.class))).thenReturn(responses);
|
||||
return configuration;
|
||||
}
|
||||
// @SuppressWarnings("unchecked")
|
||||
// private OAuthConfiguration getTestConfigurationForDirectMessages() throws Exception{
|
||||
// OAuthConfiguration configuration = mock(OAuthConfiguration.class);
|
||||
// RateLimitStatus rateLimitStatus = mock(RateLimitStatus.class);
|
||||
// when(twitter.getRateLimitStatus()).thenReturn(rateLimitStatus);
|
||||
// when(configuration.getTwitter()).thenReturn(twitter);
|
||||
// when(rateLimitStatus.getSecondsUntilReset()).thenReturn(2464);
|
||||
// when(rateLimitStatus.getRemainingHits()).thenReturn(250);
|
||||
//
|
||||
// ResponseList<DirectMessage> responses = mock(ResponseList.class);
|
||||
// List<DirectMessage> testMessages = new ArrayList<DirectMessage>();
|
||||
// testMessages.add(firstMessage);
|
||||
// testMessages.add(secondMessage);
|
||||
//
|
||||
// when(responses.iterator()).thenReturn(testMessages.iterator());
|
||||
// when(twitter.getDirectMessages()).thenReturn(responses);
|
||||
// when(twitter.getDirectMessages(Mockito.any(Paging.class))).thenReturn(responses);
|
||||
// return configuration;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.springframework.integration.twitter.oauth;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
||||
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
|
||||
import twitter4j.Twitter;
|
||||
import twitter4j.TwitterException;
|
||||
import twitter4j.TwitterFactory;
|
||||
|
||||
import twitter4j.http.AccessToken;
|
||||
import twitter4j.http.RequestToken;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
* Default System.(out|in) based implementation of the {@link org.springframework.integration.twitter.oauth.AccessTokenInitialRequestProcessListener} interface
|
||||
*
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class ConsoleBasedAccessTokenInitialRequestProcessListener implements AccessTokenInitialRequestProcessListener {
|
||||
public String openUrlAndReturnPin(String urlToOpen)
|
||||
throws Exception {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
|
||||
System.out.println("Open the following URL and grant access to your account:");
|
||||
System.out.println(urlToOpen);
|
||||
System.out.print("Enter the PIN(if aviailable) or just hit enter.[PIN]:");
|
||||
|
||||
return StringUtils.trim(br.readLine());
|
||||
}
|
||||
|
||||
public void persistReturnedAccessToken(AccessToken accessToken)
|
||||
throws Exception {
|
||||
Map<String, String> output = new HashMap<String, String>();
|
||||
output.put(OAuthConfigurationFactoryBean.WELL_KNOWN_CONSUMER_ACCESS_TOKEN, accessToken.getToken());
|
||||
output.put(OAuthConfigurationFactoryBean.WELL_KNOWN_CONSUMER_ACCESS_TOKEN_SECRET, accessToken.getTokenSecret());
|
||||
|
||||
File accessTokenCreds = new File(SystemUtils.getJavaIoTmpDir(), "twitter-accesstoken.properties");
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(accessTokenCreds);
|
||||
Properties props = new Properties();
|
||||
props.putAll(output);
|
||||
props.store(fileOutputStream, "oauth-access-token");
|
||||
IOUtils.closeQuietly(fileOutputStream);
|
||||
|
||||
System.out.println("The oauth accesstoken credentials have been written to " + accessTokenCreds.getAbsolutePath());
|
||||
}
|
||||
|
||||
public void failure(Throwable t) {
|
||||
System.err.println("Exception occurred when trying to retrieve credentials: " + ExceptionUtils.getFullStackTrace(t));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
File twitterProps = new File(SystemUtils.getUserHome(), "Desktop/twitter.properties");
|
||||
|
||||
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
|
||||
propertiesFactoryBean.setLocation(new FileSystemResource(twitterProps));
|
||||
propertiesFactoryBean.afterPropertiesSet() ;
|
||||
Properties props = propertiesFactoryBean.getObject();
|
||||
|
||||
String key = StringUtils.trim(props.getProperty("twitter.oauth.consumerKey"));
|
||||
String secret = StringUtils.trim( props.getProperty("twitter.oauth.consumerSecret") ) ;
|
||||
|
||||
ConsoleBasedAccessTokenInitialRequestProcessListener consoleBasedAccessTokenInitialRequestProcessListener =
|
||||
new ConsoleBasedAccessTokenInitialRequestProcessListener();
|
||||
|
||||
Twitter twitter = new TwitterFactory().getOAuthAuthorizedInstance( key, secret);
|
||||
|
||||
RequestToken requestToken = twitter.getOAuthRequestToken();
|
||||
AccessToken accessToken = null;
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
|
||||
|
||||
while (null == accessToken) {
|
||||
String pin = consoleBasedAccessTokenInitialRequestProcessListener.openUrlAndReturnPin(requestToken.getAuthorizationURL());
|
||||
|
||||
try {
|
||||
if (pin.length() > 0) {
|
||||
accessToken = twitter.getOAuthAccessToken(requestToken, pin);
|
||||
} else {
|
||||
accessToken = twitter.getOAuthAccessToken();
|
||||
}
|
||||
} catch (TwitterException te) {
|
||||
if (401 == te.getStatusCode()) {
|
||||
System.out.println("Unable to get the access token.");
|
||||
} else {
|
||||
te.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
consoleBasedAccessTokenInitialRequestProcessListener.persistReturnedAccessToken(accessToken);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -19,22 +19,22 @@ package org.springframework.integration.twitter.outbound;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.twitter.core.TwitterHeaders;
|
||||
import org.springframework.integration.twitter.oauth.OAuthConfiguration;
|
||||
import org.springframework.integration.twitter.oauth.OAuthTwitterFactoryBean;
|
||||
|
||||
import twitter4j.GeoLocation;
|
||||
import twitter4j.Twitter;
|
||||
import twitter4j.http.AccessToken;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class OutboundDirectMessageMessageHandlerTests {
|
||||
|
||||
private Twitter twitter;
|
||||
private Twitter twitter = mock(Twitter.class);
|
||||
|
||||
@Test
|
||||
public void validateSendDirectMessage() throws Exception{
|
||||
@@ -43,8 +43,7 @@ public class OutboundDirectMessageMessageHandlerTests {
|
||||
.setHeader(TwitterHeaders.DISPLAY_COORDINATES, true)
|
||||
.setHeader(TwitterHeaders.DM_TARGET_USER_ID, "foo");
|
||||
|
||||
DirectMessageSendingMessageHandler handler = new DirectMessageSendingMessageHandler();
|
||||
handler.setConfiguration(this.getTestConfiguration());
|
||||
DirectMessageSendingMessageHandler handler = new DirectMessageSendingMessageHandler(twitter);
|
||||
handler.afterPropertiesSet();
|
||||
|
||||
handler.handleMessage(mb.build());
|
||||
@@ -59,12 +58,4 @@ public class OutboundDirectMessageMessageHandlerTests {
|
||||
verify(twitter, times(1)).sendDirectMessage(123, "hello");
|
||||
}
|
||||
|
||||
|
||||
private OAuthConfiguration getTestConfiguration() throws Exception {
|
||||
twitter = mock(Twitter.class);
|
||||
OAuthConfiguration configuration = mock(OAuthConfiguration.class);
|
||||
when(configuration.getTwitter()).thenReturn(twitter);
|
||||
return configuration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user