Refactored AbstractOAuth1ChannelType. Partially implemented LinkedInChannelType.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29425 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
N Smith
2011-07-28 10:30:06 +00:00
parent 2baa73cf31
commit ed739a5b7e
11 changed files with 312 additions and 59 deletions

View File

@@ -26,6 +26,7 @@
<import resource="classpath*:alfresco/web-publishing-context.xml" /> <import resource="classpath*:alfresco/web-publishing-context.xml" />
<import resource="classpath*:alfresco/youtube-publishing-context.xml" /> <import resource="classpath*:alfresco/youtube-publishing-context.xml" />
<import resource="classpath*:alfresco/twitter-publishing-context.xml" /> <import resource="classpath*:alfresco/twitter-publishing-context.xml" />
<import resource="classpath*:alfresco/linkedin-publishing-context.xml" />
<import resource="classpath*:alfresco/slideshare-publishing-context.xml" /> <import resource="classpath*:alfresco/slideshare-publishing-context.xml" />
<import resource="classpath*:alfresco/flickr-publishing-context.xml" /> <import resource="classpath*:alfresco/flickr-publishing-context.xml" />
<import resource="classpath*:alfresco/facebook-publishing-context.xml" /> <import resource="classpath*:alfresco/facebook-publishing-context.xml" />

View File

@@ -12,19 +12,19 @@
<bean id="flickrDeliveryChannelType" class="org.alfresco.repo.publishing.flickr.FlickrChannelType" parent="baseChannelType" > <bean id="flickrDeliveryChannelType" class="org.alfresco.repo.publishing.flickr.FlickrChannelType" parent="baseChannelType" >
<property name="nodeService" ref="NodeService" /> <property name="nodeService" ref="NodeService" />
<property name="publishingHelper" ref="flickrPublishingHelper" />
<property name="actionService" ref="ActionService" /> <property name="actionService" ref="ActionService" />
<property name="connectionFactory" ref="flickrConnectionFactory" />
</bean> </bean>
<bean id="flickrPublishingHelper" class="org.alfresco.repo.publishing.flickr.FlickrPublishingHelper"> <bean id="flickrPublishingHelper" class="org.alfresco.repo.publishing.flickr.FlickrPublishingHelper">
<property name="nodeService" ref="NodeService" /> <property name="nodeService" ref="NodeService" />
<property name="connectionFactory"> <property name="connectionFactory" ref="flickrConnectionFactory" />
<bean class="org.alfresco.repo.publishing.flickr.springsocial.connect.FlickrConnectionFactory"> </bean>
<bean id="flickrConnectionFactory" class="org.alfresco.repo.publishing.flickr.springsocial.connect.FlickrConnectionFactory">
<constructor-arg value="cc61f5d37569cec8c04fce8b4db3f37d" /> <constructor-arg value="cc61f5d37569cec8c04fce8b4db3f37d" />
<constructor-arg value="75f29c6fc18a1b0c" /> <constructor-arg value="75f29c6fc18a1b0c" />
</bean> </bean>
</property>
</bean>
<bean id="publish_flickr" parent="action-executer" class="org.alfresco.repo.publishing.flickr.FlickrPublishAction"> <bean id="publish_flickr" parent="action-executer" class="org.alfresco.repo.publishing.flickr.FlickrPublishAction">
<property name="nodeService" ref="NodeService" /> <property name="nodeService" ref="NodeService" />

View File

@@ -0,0 +1,23 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<bean parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
<property name="models">
<list>
<value>alfresco/model/linkedInPublishingModel.xml</value>
</list>
</property>
</bean>
<bean id="linkedInDeliveryChannelType" class="org.alfresco.repo.publishing.linkedin.LinkedInChannelType" parent="baseChannelType" >
<property name="nodeService" ref="NodeService" />
<property name="connectionFactory">
<bean class="org.springframework.social.linkedin.connect.LinkedInConnectionFactory">
<constructor-arg value="l0a39tvf6v4x" />
<constructor-arg value="veWjLwlnJmu7IyFs" />
</bean>
</property>
</bean>
</beans>

View File

@@ -0,0 +1,47 @@
<model name="linkedin:publishingmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<description>Alfresco LinkedIn Publishing Content Model</description>
<author>Alfresco</author>
<published>2011-06-27</published>
<version>1.0</version>
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d" />
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys" />
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm" />
<import uri="http://www.alfresco.org/model/publishing/1.0" prefix="pub" />
</imports>
<namespaces>
<namespace uri="http://www.alfresco.org/model/publishing/linkedin/1.0" prefix="linkedin" />
</namespaces>
<types>
<type name="linkedin:DeliveryChannel">
<title>LinkedIn Delivery Channel</title>
<description>Node type used to represent LinkedIn delivery channels</description>
<parent>pub:DeliveryChannel</parent>
<mandatory-aspects>
<aspect>pub:OAuth1DeliveryChannelAspect</aspect>
</mandatory-aspects>
</type>
</types>
<aspects>
<aspect name="linkedin:AssetAspect">
<title>LinkedIn Asset</title>
<description>Applied to a node that has been published to LinkedIn</description>
<properties>
<property name="linkedin:assetId">
<title>LinkedIn Status Id</title>
<type>d:text</type>
</property>
<property name="linkedin:assetUrl">
<title>LinkedIn Status URL</title>
<type>d:text</type>
</property>
</properties>
</aspect>
</aspects>
</model>

View File

@@ -11,11 +11,6 @@
</bean> </bean>
<bean id="twitterDeliveryChannelType" class="org.alfresco.repo.publishing.twitter.TwitterChannelType" parent="baseChannelType" > <bean id="twitterDeliveryChannelType" class="org.alfresco.repo.publishing.twitter.TwitterChannelType" parent="baseChannelType" >
<property name="nodeService" ref="NodeService" />
<property name="publishingHelper" ref="twitterPublishingHelper" />
</bean>
<bean id="twitterPublishingHelper" class="org.alfresco.repo.publishing.twitter.TwitterPublishingHelper">
<property name="nodeService" ref="NodeService" /> <property name="nodeService" ref="NodeService" />
<property name="connectionFactory"> <property name="connectionFactory">
<bean class="org.springframework.social.twitter.connect.TwitterConnectionFactory"> <bean class="org.springframework.social.twitter.connect.TwitterConnectionFactory">

View File

@@ -27,18 +27,48 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.support.OAuth1ConnectionFactory;
import org.springframework.social.oauth1.AuthorizedRequestToken; import org.springframework.social.oauth1.AuthorizedRequestToken;
import org.springframework.social.oauth1.OAuth1Operations; import org.springframework.social.oauth1.OAuth1Operations;
import org.springframework.social.oauth1.OAuth1Parameters; import org.springframework.social.oauth1.OAuth1Parameters;
import org.springframework.social.oauth1.OAuthToken; import org.springframework.social.oauth1.OAuthToken;
public abstract class AbstractOAuth1ChannelType extends AbstractChannelType /**
* @author Brian
* @author Nick Smith
* @since 4.0
*
* @param <A> The API type, e.g. Twitter, Flickr, LinkedIn, etc.
*/
public abstract class AbstractOAuth1ChannelType<A> extends AbstractChannelType
{ {
private NodeService nodeService; private NodeService nodeService;
private OAuth1ConnectionFactory<A> connectionFactory;
public final void setNodeService(NodeService nodeService) public Connection<A> getConnectionForPublishNode(NodeRef publishNode)
{ {
this.nodeService = nodeService; NodeRef channelNode = nodeService.getPrimaryParent(publishNode).getParentRef();
return getConnectionForChannel(channelNode);
}
public Connection<A> getConnectionForChannel(NodeRef channelNode)
{
Connection<A> connection = null;
if (nodeService.exists(channelNode)
&& nodeService.hasAspect(channelNode, PublishingModel.ASPECT_OAUTH1_DELIVERY_CHANNEL))
{
String tokenValue = (String) nodeService.getProperty(channelNode, PublishingModel.PROP_OAUTH1_TOKEN_VALUE);
String tokenSecret = (String) nodeService.getProperty(channelNode, PublishingModel.PROP_OAUTH1_TOKEN_SECRET);
Boolean danceComplete = (Boolean) nodeService.getProperty(channelNode, PublishingModel.PROP_AUTHORISATION_COMPLETE);
if (danceComplete)
{
OAuthToken token = new OAuthToken(tokenValue, tokenSecret);
connection = connectionFactory.createConnection(token);
}
}
return connection;
} }
protected NodeService getNodeService() protected NodeService getNodeService()
@@ -92,8 +122,6 @@ public abstract class AbstractOAuth1ChannelType extends AbstractChannelType
return authorised; return authorised;
} }
protected abstract OAuth1Operations getOAuth1Operations();
/** /**
* Override this method to add additonal parameters onto the URL that the user is redirected to * Override this method to add additonal parameters onto the URL that the user is redirected to
* to authorise access to their account. By default, no parameters are added, but this may be useful to * to authorise access to their account. By default, no parameters are added, but this may be useful to
@@ -110,4 +138,25 @@ public abstract class AbstractOAuth1ChannelType extends AbstractChannelType
{ {
return "oauth_verifier"; return "oauth_verifier";
} }
private OAuth1Operations getOAuth1Operations()
{
return connectionFactory.getOAuthOperations();
}
/**
* @param connectionFactory the connectionFactory to set
*/
public void setConnectionFactory(OAuth1ConnectionFactory<A> connectionFactory)
{
this.connectionFactory = connectionFactory;
}
/**
* @param nodeService the nodeService to set
*/
public final void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
} }

View File

@@ -27,37 +27,28 @@ import java.util.TreeSet;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.publishing.AbstractOAuth1ChannelType; import org.alfresco.repo.publishing.AbstractOAuth1ChannelType;
import org.alfresco.repo.publishing.PublishingModel; import org.alfresco.repo.publishing.PublishingModel;
import org.alfresco.repo.publishing.flickr.springsocial.api.Flickr;
import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionService; import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.publishing.channels.Channel; import org.alfresco.service.cmr.publishing.channels.Channel;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.springframework.social.oauth1.OAuth1Operations; import org.alfresco.util.collections.CollectionUtils;
import org.springframework.social.oauth1.OAuth1Parameters; import org.springframework.social.oauth1.OAuth1Parameters;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
public class FlickrChannelType extends AbstractOAuth1ChannelType public class FlickrChannelType extends AbstractOAuth1ChannelType<Flickr>
{ {
public final static String ID = "flickr"; public final static String ID = "flickr";
private final static Set<String> DEFAULT_SUPPORTED_MIME_TYPES = new TreeSet<String>(); private final static Set<String> DEFAULT_SUPPORTED_MIME_TYPES = CollectionUtils.unmodifiableSet(
MimetypeMap.MIMETYPE_IMAGE_GIF,
MimetypeMap.MIMETYPE_IMAGE_JPEG,
MimetypeMap.MIMETYPE_IMAGE_PNG);
static
{
DEFAULT_SUPPORTED_MIME_TYPES.add(MimetypeMap.MIMETYPE_IMAGE_GIF);
DEFAULT_SUPPORTED_MIME_TYPES.add(MimetypeMap.MIMETYPE_IMAGE_JPEG);
DEFAULT_SUPPORTED_MIME_TYPES.add(MimetypeMap.MIMETYPE_IMAGE_PNG);
}
private FlickrPublishingHelper publishingHelper;
private ActionService actionService; private ActionService actionService;
private Set<String> supportedMimeTypes = Collections.unmodifiableSet(DEFAULT_SUPPORTED_MIME_TYPES); private Set<String> supportedMimeTypes = DEFAULT_SUPPORTED_MIME_TYPES;
public void setPublishingHelper(FlickrPublishingHelper flickrPublishingHelper)
{
this.publishingHelper = flickrPublishingHelper;
}
public void setActionService(ActionService actionService) public void setActionService(ActionService actionService)
{ {
@@ -114,6 +105,10 @@ public class FlickrChannelType extends AbstractOAuth1ChannelType
@Override @Override
public void publish(NodeRef nodeToPublish, Map<QName, Serializable> properties) public void publish(NodeRef nodeToPublish, Map<QName, Serializable> properties)
{ {
// TODO Nick S: Not sure it is very useful to use an Action hee.
// The Action assumes the nodeToPublish is under a properly configured DeliveryChannel.
// Ie. the action assumes the node was generated via the Publishing Service.
// The Action only really has value if it can be called independant of the Publishing Service IMO.
Action publishAction = actionService.createAction(FlickrPublishAction.NAME); Action publishAction = actionService.createAction(FlickrPublishAction.NAME);
actionService.executeAction(publishAction, nodeToPublish); actionService.executeAction(publishAction, nodeToPublish);
} }
@@ -121,6 +116,7 @@ public class FlickrChannelType extends AbstractOAuth1ChannelType
@Override @Override
public void unpublish(NodeRef nodeToUnpublish, Map<QName, Serializable> properties) public void unpublish(NodeRef nodeToUnpublish, Map<QName, Serializable> properties)
{ {
//NOOP
} }
@Override @Override
@@ -149,10 +145,4 @@ public class FlickrChannelType extends AbstractOAuth1ChannelType
return new OAuth1Parameters(callbackUrl, params); return new OAuth1Parameters(callbackUrl, params);
} }
@Override
protected OAuth1Operations getOAuth1Operations()
{
return publishingHelper.getConnectionFactory().getOAuthOperations();
}
} }

View File

@@ -0,0 +1,122 @@
/*
* Copyright (C) 2005-2011 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco 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.
*
* Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.publishing.linkedin;
import static org.alfresco.repo.publishing.linkedin.LinkedInPublishingModel.TYPE_DELIVERY_CHANNEL;
import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.alfresco.repo.publishing.AbstractOAuth1ChannelType;
import org.alfresco.service.cmr.publishing.channels.Channel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.springframework.social.connect.Connection;
import org.springframework.social.linkedin.api.LinkedIn;
import org.springframework.social.oauth1.OAuth1Parameters;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
/**
* @author Nick Smith
* @since 4.0
*/
public class LinkedInChannelType extends AbstractOAuth1ChannelType<LinkedIn>
{
public final static String ID = "linkedIn";
@Override
public boolean canPublish()
{
return false;
}
@Override
public boolean canPublishStatusUpdates()
{
return true;
}
@Override
public boolean canUnpublish()
{
return false;
}
@Override
public QName getChannelNodeType()
{
return TYPE_DELIVERY_CHANNEL;
}
@Override
public String getId()
{
return ID;
}
@Override
public Set<QName> getSupportedContentTypes()
{
return Collections.emptySet();
}
@Override
public Set<String> getSupportedMimeTypes()
{
return Collections.emptySet();
}
@Override
public void publish(NodeRef nodeToPublish, Map<QName, Serializable> properties)
{
//NO-OP
}
@Override
public void unpublish(NodeRef nodeToUnpublish, Map<QName, Serializable> properties)
{
//NO-OP
}
@Override
public void updateStatus(Channel channel, String status, Map<QName, Serializable> properties)
{
NodeRef channelNode = new NodeRef(channel.getId());
Connection<LinkedIn> connection = getConnectionForChannel(channelNode);
// TODO update status
}
@Override
public String getNodeUrl(NodeRef node)
{
throw new UnsupportedOperationException();
}
@Override
protected OAuth1Parameters getOAuth1Parameters(String callbackUrl)
{
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
params.add("perms", "delete");
return new OAuth1Parameters(callbackUrl, params);
}
}

View File

@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.alfresco.repo.publishing.twitter; package org.alfresco.repo.publishing.linkedin;
import org.alfresco.repo.publishing.PublishingModel; import org.alfresco.repo.publishing.PublishingModel;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -26,7 +26,7 @@ import org.springframework.social.oauth1.OAuthToken;
import org.springframework.social.twitter.api.Twitter; import org.springframework.social.twitter.api.Twitter;
import org.springframework.social.twitter.connect.TwitterConnectionFactory; import org.springframework.social.twitter.connect.TwitterConnectionFactory;
public class TwitterPublishingHelper public class LinkedInPublishingHelper
{ {
private NodeService nodeService; private NodeService nodeService;
private TwitterConnectionFactory connectionFactory; private TwitterConnectionFactory connectionFactory;

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2005-2011 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco 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.
*
* Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.publishing.linkedin;
import org.alfresco.service.namespace.QName;
/**
* @author Nick Smith
* @since 4.0
*/
public interface LinkedInPublishingModel
{
public static final String NAMESPACE = "http://www.alfresco.org/model/publishing/linkedin/1.0";
public static final String PREFIX = "linkedin";
public static final QName TYPE_DELIVERY_CHANNEL = QName.createQName(NAMESPACE, "DeliveryChannel");
public static final QName ASPECT_ASSET = QName.createQName(NAMESPACE, "AssetAspect");
public static final QName PROP_ASSET_ID = QName.createQName(NAMESPACE, "assetId");
public static final QName PROP_ASSET_URL = QName.createQName(NAMESPACE, "assetUrl");
}

View File

@@ -28,18 +28,11 @@ import org.alfresco.service.cmr.publishing.channels.Channel;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.springframework.social.connect.Connection; import org.springframework.social.connect.Connection;
import org.springframework.social.oauth1.OAuth1Operations;
import org.springframework.social.twitter.api.Twitter; import org.springframework.social.twitter.api.Twitter;
public class TwitterChannelType extends AbstractOAuth1ChannelType public class TwitterChannelType extends AbstractOAuth1ChannelType<Twitter>
{ {
public final static String ID = "twitter"; public final static String ID = "twitter";
private TwitterPublishingHelper publishingHelper;
public void setPublishingHelper(TwitterPublishingHelper twitterPublishingHelper)
{
this.publishingHelper = twitterPublishingHelper;
}
@Override @Override
public boolean canPublish() public boolean canPublish()
@@ -98,7 +91,7 @@ public class TwitterChannelType extends AbstractOAuth1ChannelType
@Override @Override
public void updateStatus(Channel channel, String status, Map<QName, Serializable> properties) public void updateStatus(Channel channel, String status, Map<QName, Serializable> properties)
{ {
Connection<Twitter> connection = publishingHelper.getTwitterConnectionForChannel(channel.getNodeRef()); Connection<Twitter> connection = getConnectionForChannel(channel.getNodeRef());
connection.getApi().timelineOperations().updateStatus(status); connection.getApi().timelineOperations().updateStatus(status);
} }
@@ -108,9 +101,4 @@ public class TwitterChannelType extends AbstractOAuth1ChannelType
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
protected OAuth1Operations getOAuth1Operations()
{
return publishingHelper.getConnectionFactory().getOAuthOperations();
}
} }