mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Publishing:
- Added start of the Flickr channel. Channel creation and authorisation is complete (written as a new Spring Social module). API not currently working. - Fixed a problem with SlideShare API: it relies on the file extension to determine the type of the file, so needed to alter the way the files are sent. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29085 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -27,5 +27,6 @@
|
||||
<import resource="classpath*:alfresco/youtube-publishing-context.xml" />
|
||||
<import resource="classpath*:alfresco/twitter-publishing-context.xml" />
|
||||
<import resource="classpath*:alfresco/slideshare-publishing-context.xml" />
|
||||
<import resource="classpath*:alfresco/flickr-publishing-context.xml" />
|
||||
<import resource="classpath*:alfresco/domain/*-context.xml" />
|
||||
</beans>
|
||||
|
36
config/alfresco/flickr-publishing-context.xml
Normal file
36
config/alfresco/flickr-publishing-context.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?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/flickrPublishingModel.xml</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="flickrDeliveryChannelType" class="org.alfresco.repo.publishing.flickr.FlickrChannelType" parent="baseChannelType" >
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="publishingHelper" ref="flickrPublishingHelper" />
|
||||
<property name="actionService" ref="ActionService" />
|
||||
</bean>
|
||||
|
||||
<bean id="flickrPublishingHelper" class="org.alfresco.repo.publishing.flickr.FlickrPublishingHelper">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="connectionFactory">
|
||||
<bean class="org.springframework.social.flickr.connect.FlickrConnectionFactory">
|
||||
<constructor-arg value="cc61f5d37569cec8c04fce8b4db3f37d" />
|
||||
<constructor-arg value="75f29c6fc18a1b0c" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="publish_flickr" parent="action-executer" class="org.alfresco.repo.publishing.flickr.FlickrPublishAction">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="taggingService" ref="TaggingService" />
|
||||
<property name="contentService" ref="ContentService" />
|
||||
<property name="flickrHelper" ref="flickrPublishingHelper" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
47
config/alfresco/model/flickrPublishingModel.xml
Normal file
47
config/alfresco/model/flickrPublishingModel.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<model name="flickr:publishingmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
|
||||
|
||||
<description>Alfresco Flickr Publishing Content Model</description>
|
||||
<author>Alfresco</author>
|
||||
<published>2011-07-13</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/flickr/1.0" prefix="flickr" />
|
||||
</namespaces>
|
||||
|
||||
<types>
|
||||
<type name="flickr:DeliveryChannel">
|
||||
<title>Flickr Delivery Channel</title>
|
||||
<description>Node type used to represent Flickr delivery channels</description>
|
||||
<parent>pub:DeliveryChannel</parent>
|
||||
<mandatory-aspects>
|
||||
<aspect>pub:OAuth1DeliveryChannelAspect</aspect>
|
||||
</mandatory-aspects>
|
||||
</type>
|
||||
|
||||
</types>
|
||||
|
||||
<aspects>
|
||||
<aspect name="flickr:AssetAspect">
|
||||
<title>Flickr Asset</title>
|
||||
<description>Applied to a node that has been published to Flickr</description>
|
||||
<properties>
|
||||
<property name="flickr:assetId">
|
||||
<title>Flickr asset Id</title>
|
||||
<type>d:text</type>
|
||||
</property>
|
||||
<property name="flickr:assetUrl">
|
||||
<title>Flickr Asset URL</title>
|
||||
<type>d:text</type>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
</aspects>
|
||||
</model>
|
@@ -30,6 +30,7 @@
|
||||
<bean id="slideshareDeliveryChannelType" class="org.alfresco.repo.publishing.slideshare.SlideShareChannelType" parent="baseChannelType" >
|
||||
<property name="actionService" ref="ActionService" />
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="publishingHelper" ref="slidesharePublishingHelper" />
|
||||
</bean>
|
||||
|
||||
|
||||
|
@@ -107,7 +107,6 @@
|
||||
<bean id="urlShortener" class="org.alfresco.repo.urlshortening.BitlyUrlShortenerImpl" >
|
||||
<property name="username" value="${urlshortening.bitly.username}" />
|
||||
<property name="apiKey" value="${urlshortening.bitly.api.key}" />
|
||||
<property name="urlLength" value="${urlshortening.bitly.url.length}" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
BIN
config/test/alfresco/TestImageFile.png
Normal file
BIN
config/test/alfresco/TestImageFile.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 83 KiB |
@@ -175,16 +175,18 @@ public class ChannelServiceImpl implements ChannelService
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void deleteChannel(String siteId, String channelName)
|
||||
public void deleteChannel(Channel channel)
|
||||
{
|
||||
Set<NodeRef> containers = getAllChannelContainers(siteId);
|
||||
for (NodeRef channelContainer : containers)
|
||||
List<NodeRef> allChannelNodes = new ArrayList<NodeRef>();
|
||||
NodeRef editorialNode = channel.getNodeRef();
|
||||
allChannelNodes.add(editorialNode);
|
||||
for (AssociationRef assoc : nodeService.getSourceAssocs(editorialNode, PublishingModel.ASSOC_EDITORIAL_CHANNEL))
|
||||
{
|
||||
NodeRef channel = nodeService.getChildByName(channelContainer, ContentModel.ASSOC_CONTAINS, channelName);
|
||||
if (channel != null)
|
||||
{
|
||||
nodeService.deleteNode(channel);
|
||||
allChannelNodes.add(assoc.getSourceRef());
|
||||
}
|
||||
for (NodeRef channelNode : allChannelNodes)
|
||||
{
|
||||
nodeService.deleteNode(channelNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -97,7 +97,8 @@ public class ChannelServiceImplIntegratedTest extends AbstractPublishingIntegrat
|
||||
{
|
||||
testCreateChannel();
|
||||
|
||||
channelService.deleteChannel(siteId, channelName);
|
||||
Channel channel = channelService.getChannel(siteId, channelName);
|
||||
channelService.deleteChannel(channel);
|
||||
|
||||
List<Channel> channels = channelService.getChannels(siteId);
|
||||
assertTrue(channels.isEmpty());
|
||||
|
@@ -24,10 +24,7 @@ import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.springframework.social.connect.Connection;
|
||||
import org.springframework.social.facebook.api.Facebook;
|
||||
import org.springframework.social.facebook.connect.FacebookConnectionFactory;
|
||||
import org.springframework.social.oauth1.OAuthToken;
|
||||
import org.springframework.social.oauth2.AccessGrant;
|
||||
import org.springframework.social.twitter.api.Twitter;
|
||||
import org.springframework.social.twitter.connect.TwitterConnectionFactory;
|
||||
|
||||
public class FacebookPublishingHelper
|
||||
{
|
||||
|
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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.flickr;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.publishing.AbstractChannelType;
|
||||
import org.alfresco.repo.publishing.PublishingModel;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.publishing.channels.Channel;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.springframework.social.oauth1.AuthorizedRequestToken;
|
||||
import org.springframework.social.oauth1.OAuth1Operations;
|
||||
import org.springframework.social.oauth1.OAuth1Parameters;
|
||||
import org.springframework.social.oauth1.OAuthToken;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
public class FlickrChannelType extends AbstractChannelType
|
||||
{
|
||||
public final static String ID = "flickr";
|
||||
private NodeService nodeService;
|
||||
private FlickrPublishingHelper publishingHelper;
|
||||
private ActionService actionService;
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setPublishingHelper(FlickrPublishingHelper flickrPublishingHelper)
|
||||
{
|
||||
this.publishingHelper = flickrPublishingHelper;
|
||||
}
|
||||
|
||||
public void setActionService(ActionService actionService)
|
||||
{
|
||||
this.actionService = actionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPublish()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPublishStatusUpdates()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUnpublish()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QName getChannelNodeType()
|
||||
{
|
||||
return FlickrPublishingModel.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)
|
||||
{
|
||||
Action publishAction = actionService.createAction(FlickrPublishAction.NAME);
|
||||
actionService.executeAction(publishAction, nodeToPublish);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unpublish(NodeRef nodeToUnpublish, Map<QName, Serializable> properties)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(Channel channel, String status, Map<QName, Serializable> properties)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNodeUrl(NodeRef node)
|
||||
{
|
||||
String url = null;
|
||||
if (node != null && nodeService.exists(node) && nodeService.hasAspect(node, FlickrPublishingModel.ASPECT_ASSET))
|
||||
{
|
||||
url = (String)nodeService.getProperty(node, FlickrPublishingModel.PROP_ASSET_URL);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorisationUrl(Channel channel, String callbackUrl)
|
||||
{
|
||||
ParameterCheck.mandatory("channel", channel);
|
||||
ParameterCheck.mandatory("callbackUrl", callbackUrl);
|
||||
if (!ID.equals(channel.getChannelType().getId()))
|
||||
{
|
||||
throw new IllegalArgumentException("Invalid channel type: " + channel.getChannelType().getId());
|
||||
}
|
||||
OAuth1Operations oauthOperations = publishingHelper.getConnectionFactory().getOAuthOperations();
|
||||
OAuthToken requestToken = oauthOperations.fetchRequestToken(callbackUrl, null);
|
||||
|
||||
NodeRef channelNodeRef = channel.getNodeRef();
|
||||
nodeService.setProperty(channelNodeRef, PublishingModel.PROP_OAUTH1_TOKEN_SECRET, requestToken.getSecret());
|
||||
nodeService.setProperty(channelNodeRef, PublishingModel.PROP_OAUTH1_TOKEN_VALUE, requestToken.getValue());
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
|
||||
params.add("perms", "delete");
|
||||
OAuth1Parameters oauthParams = new OAuth1Parameters(callbackUrl, params);
|
||||
return oauthOperations.buildAuthorizeUrl(requestToken.getValue(), oauthParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptAuthorisationCallback(Channel channel, Map<String, String[]> callbackHeaders,
|
||||
Map<String, String[]> callbackParams)
|
||||
{
|
||||
boolean authorised = false;
|
||||
String[] verifier = callbackParams.get("oauth_verifier");
|
||||
if (verifier != null)
|
||||
{
|
||||
OAuth1Operations oauthOperations = publishingHelper.getConnectionFactory().getOAuthOperations();
|
||||
NodeRef channelNodeRef = channel.getNodeRef();
|
||||
|
||||
Map<QName, Serializable> currentProps = nodeService.getProperties(channelNodeRef);
|
||||
String tokenValue = (String) currentProps.get(PublishingModel.PROP_OAUTH1_TOKEN_VALUE);
|
||||
String tokenSecret = (String) currentProps.get(PublishingModel.PROP_OAUTH1_TOKEN_SECRET);
|
||||
OAuthToken token = new OAuthToken(tokenValue, tokenSecret);
|
||||
OAuthToken accessToken = oauthOperations.exchangeForAccessToken(new AuthorizedRequestToken(token, verifier[0]), null);
|
||||
|
||||
Map<QName, Serializable> newProps = new HashMap<QName, Serializable>();
|
||||
newProps.put(PublishingModel.PROP_OAUTH1_TOKEN_VALUE, accessToken.getValue());
|
||||
newProps.put(PublishingModel.PROP_OAUTH1_TOKEN_SECRET, accessToken.getSecret());
|
||||
getChannelService().updateChannel(channel, newProps);
|
||||
authorised = true;
|
||||
}
|
||||
return authorised;
|
||||
}
|
||||
}
|
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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.flickr;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
|
||||
import org.alfresco.repo.content.filestore.FileContentReader;
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.Flickr;
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.MediaOperations;
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.PhotoMetadata;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ParameterDefinition;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.tagging.TaggingService;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.social.connect.Connection;
|
||||
|
||||
public class FlickrPublishAction extends ActionExecuterAbstractBase
|
||||
{
|
||||
private final static Log log = LogFactory.getLog(FlickrPublishAction.class);
|
||||
|
||||
public static final String NAME = "publish_flickr";
|
||||
|
||||
private NodeService nodeService;
|
||||
private ContentService contentService;
|
||||
private TaggingService taggingService;
|
||||
private FlickrPublishingHelper flickrHelper;
|
||||
|
||||
public void setFlickrHelper(FlickrPublishingHelper helper)
|
||||
{
|
||||
this.flickrHelper = helper;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
public void setTaggingService(TaggingService taggingService)
|
||||
{
|
||||
this.taggingService = taggingService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void executeImpl(Action action, NodeRef nodeToPublish)
|
||||
{
|
||||
ContentReader reader = contentService.getReader(nodeToPublish, ContentModel.PROP_CONTENT);
|
||||
if (reader.exists())
|
||||
{
|
||||
File contentFile;
|
||||
boolean deleteContentFileOnCompletion = false;
|
||||
if (FileContentReader.class.isAssignableFrom(reader.getClass()))
|
||||
{
|
||||
// Grab the content straight from the content store if we can...
|
||||
contentFile = ((FileContentReader) reader).getFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...otherwise copy it to a temp file and use the copy...
|
||||
File tempDir = TempFileProvider.getLongLifeTempDir("flickr");
|
||||
contentFile = TempFileProvider.createTempFile("flickr", "", tempDir);
|
||||
reader.getContent(contentFile);
|
||||
deleteContentFileOnCompletion = true;
|
||||
}
|
||||
try
|
||||
{
|
||||
Resource res = new FileSystemResource(contentFile);
|
||||
Connection<Flickr> connection = flickrHelper.getConnectionForPublishNode(nodeToPublish);
|
||||
|
||||
String name = (String) nodeService.getProperty(nodeToPublish, ContentModel.PROP_NAME);
|
||||
String title = (String) nodeService.getProperty(nodeToPublish, ContentModel.PROP_TITLE);
|
||||
if (title == null || title.length() == 0)
|
||||
{
|
||||
title = name;
|
||||
}
|
||||
String description = (String) nodeService.getProperty(nodeToPublish, ContentModel.PROP_DESCRIPTION);
|
||||
if (description == null || description.length() == 0)
|
||||
{
|
||||
description = title;
|
||||
}
|
||||
|
||||
MediaOperations mediaOps = connection.getApi().mediaOperations();
|
||||
PhotoMetadata metadata = mediaOps.createPhotoMetadata();
|
||||
metadata.setTitle(title);
|
||||
metadata.setDescription(description);
|
||||
String id = mediaOps.postPhoto(res, metadata);
|
||||
log.info("Posted image " + name + " to Flickr with id " + id);
|
||||
nodeService.setProperty(nodeToPublish, FlickrPublishingModel.PROP_ASSET_ID, id);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (deleteContentFileOnCompletion)
|
||||
{
|
||||
contentFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.flickr;
|
||||
|
||||
import org.alfresco.repo.publishing.PublishingModel;
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.Flickr;
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.connect.FlickrConnectionFactory;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.springframework.social.connect.Connection;
|
||||
import org.springframework.social.oauth1.OAuthToken;
|
||||
|
||||
public class FlickrPublishingHelper
|
||||
{
|
||||
private NodeService nodeService;
|
||||
private FlickrConnectionFactory connectionFactory;
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setConnectionFactory(FlickrConnectionFactory connectionFactory)
|
||||
{
|
||||
this.connectionFactory = connectionFactory;
|
||||
}
|
||||
|
||||
public FlickrConnectionFactory getConnectionFactory()
|
||||
{
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
public Connection<Flickr> getConnectionForPublishNode(NodeRef publishNode)
|
||||
{
|
||||
Connection<Flickr> connection = null;
|
||||
NodeRef channelNode = nodeService.getPrimaryParent(publishNode).getParentRef();
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@@ -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.flickr;
|
||||
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* @author Brian
|
||||
*
|
||||
*/
|
||||
public interface FlickrPublishingModel
|
||||
{
|
||||
public static final String NAMESPACE = "http://www.alfresco.org/model/publishing/flickr/1.0";
|
||||
public static final String PREFIX = "flickr";
|
||||
|
||||
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");
|
||||
}
|
158
source/java/org/alfresco/repo/publishing/flickr/FlickrTest.java
Normal file
158
source/java/org/alfresco/repo/publishing/flickr/FlickrTest.java
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 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.flickr;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.publishing.EnvironmentImpl;
|
||||
import org.alfresco.repo.publishing.PublishingModel;
|
||||
import org.alfresco.repo.publishing.PublishingQueueImpl;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.publishing.channels.Channel;
|
||||
import org.alfresco.service.cmr.publishing.channels.ChannelService;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.cmr.site.SiteVisibility;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.apache.commons.fileupload.MultipartStream;
|
||||
import org.junit.Assert;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* @author Brian
|
||||
*
|
||||
*/
|
||||
public class FlickrTest extends BaseSpringTest
|
||||
{
|
||||
protected ServiceRegistry serviceRegistry;
|
||||
protected SiteService siteService;
|
||||
protected FileFolderService fileFolderService;
|
||||
protected NodeService nodeService;
|
||||
protected String siteId;
|
||||
protected PublishingQueueImpl queue;
|
||||
protected EnvironmentImpl environment;
|
||||
protected NodeRef docLib;
|
||||
|
||||
private ChannelService channelService;
|
||||
|
||||
private RetryingTransactionHelper transactionHelper;
|
||||
|
||||
public void onSetUp() throws Exception
|
||||
{
|
||||
serviceRegistry = (ServiceRegistry) getApplicationContext().getBean("ServiceRegistry");
|
||||
channelService = (ChannelService) getApplicationContext().getBean("channelService");
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
|
||||
siteService = serviceRegistry.getSiteService();
|
||||
fileFolderService = serviceRegistry.getFileFolderService();
|
||||
nodeService = serviceRegistry.getNodeService();
|
||||
transactionHelper = serviceRegistry.getRetryingTransactionHelper();
|
||||
|
||||
siteId = GUID.generate();
|
||||
siteService.createSite("test", siteId, "Site created by publishing test", "Site created by publishing test",
|
||||
SiteVisibility.PUBLIC);
|
||||
docLib = siteService.createContainer(siteId, SiteService.DOCUMENT_LIBRARY, ContentModel.TYPE_FOLDER, null);
|
||||
}
|
||||
|
||||
public void onTearDown()
|
||||
{
|
||||
siteService.deleteSite(siteId);
|
||||
}
|
||||
|
||||
public void testBlank()
|
||||
{
|
||||
}
|
||||
|
||||
//Note that this test isn't normally run, as it requires a valid Flickr OAuth token.
|
||||
//To run it, remove the initial 'x' from the method name and set the appropriate values where the
|
||||
//text "YOUR_OAUTH_TOKEN_VALUE" and "YOUR_OAUTH_TOKEN_SECRET" appear. Note that these can be quite tricky to obtain...
|
||||
public void xtestFlickrPublishAndUnpublishActions() throws Exception
|
||||
{
|
||||
final NodeRef contentNode = transactionHelper.doInTransaction(new RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(PublishingModel.PROP_OAUTH1_TOKEN_VALUE, "YOUR_OAUTH_TOKEN_VALUE");
|
||||
props.put(PublishingModel.PROP_OAUTH1_TOKEN_SECRET, "YOUR_OAUTH_TOKEN_SECRET");
|
||||
props.put(PublishingModel.PROP_AUTHORISATION_COMPLETE, Boolean.TRUE);
|
||||
|
||||
Channel channel = channelService.createChannel(siteId, FlickrChannelType.ID, "FlickrTestChannel", props);
|
||||
//This looks a little odd, but a new channel always has its "authorisation complete" flag
|
||||
//forced off initially. This will force it on for this channel...
|
||||
channelService.updateChannel(channel, props);
|
||||
|
||||
NodeRef channelNode = channel.getNodeRef();
|
||||
Resource file = new ClassPathResource("test/alfresco/TestImageFile.png");
|
||||
Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>();
|
||||
contentProps.put(ContentModel.PROP_NAME, "Test Image");
|
||||
NodeRef contentNode = nodeService.createNode(channelNode, ContentModel.ASSOC_CONTAINS,
|
||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "testImage"),
|
||||
ContentModel.TYPE_CONTENT, contentProps).getChildRef();
|
||||
ContentService contentService = serviceRegistry.getContentService();
|
||||
ContentWriter writer = contentService.getWriter(contentNode, ContentModel.PROP_CONTENT, true);
|
||||
writer.setMimetype(MimetypeMap.MIMETYPE_IMAGE_PNG);
|
||||
writer.putContent(file.getFile());
|
||||
return contentNode;
|
||||
}
|
||||
});
|
||||
MultipartStream stream = new MultipartStream(null, null);
|
||||
transactionHelper.doInTransaction(new RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
ActionService actionService = serviceRegistry.getActionService();
|
||||
Action publishAction = actionService.createAction(FlickrPublishAction.NAME);
|
||||
actionService.executeAction(publishAction, contentNode);
|
||||
Map<QName, Serializable> props = nodeService.getProperties(contentNode);
|
||||
Assert.assertTrue(nodeService.hasAspect(contentNode, FlickrPublishingModel.ASPECT_ASSET));
|
||||
Assert.assertNotNull(props.get(FlickrPublishingModel.PROP_ASSET_ID));
|
||||
|
||||
System.out.println("Asset id: " + props.get(FlickrPublishingModel.PROP_ASSET_ID));
|
||||
|
||||
// Action unpublishAction = actionService.createAction(YouTubeUnpublishAction.NAME);
|
||||
// actionService.executeAction(unpublishAction, contentNode);
|
||||
// props = nodeService.getProperties(contentNode);
|
||||
// Assert.assertFalse(nodeService.hasAspect(contentNode, YouTubePublishingModel.ASPECT_ASSET));
|
||||
// Assert.assertNull(props.get(YouTubePublishingModel.PROP_ASSET_ID));
|
||||
// Assert.assertNull(props.get(YouTubePublishingModel.PROP_PLAYER_URL));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.alfresco.repo.publishing.flickr.springsocial.api;
|
||||
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.MediaOperations;
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.impl.FlickrTemplate;
|
||||
import org.springframework.social.ApiBinding;
|
||||
|
||||
/**
|
||||
* Interface specifying a basic set of operations for interacting with Facebook.
|
||||
* Implemented by {@link FlickrTemplate}.
|
||||
*
|
||||
* @author Craig Walls
|
||||
*/
|
||||
public interface Flickr extends ApiBinding
|
||||
{
|
||||
boolean test();
|
||||
|
||||
/**
|
||||
* API for performing operations on albums, photos, and videos.
|
||||
*/
|
||||
MediaOperations mediaOperations();
|
||||
}
|
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2011 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.alfresco.repo.publishing.flickr.springsocial.api;
|
||||
|
||||
import org.springframework.social.facebook.api.ImageType;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.ResponseExtractor;
|
||||
|
||||
/**
|
||||
* Defines low-level operations against Facebook's Graph API
|
||||
* @author Craig Walls
|
||||
*/
|
||||
public interface GraphApi {
|
||||
|
||||
/**
|
||||
* Fetches an object, extracting it into the type via the given {@link ResponseExtractor}.
|
||||
* Requires appropriate permission to fetch the object.
|
||||
* @param objectId the Facebook object's ID
|
||||
* @param type the Java type to fetch
|
||||
* @return an Java object representing the requested Facebook object.
|
||||
*/
|
||||
<T> T fetchObject(String objectId, Class<T> type);
|
||||
|
||||
/**
|
||||
* Fetches an object, extracting it into the type via the given {@link ResponseExtractor}.
|
||||
* Requires appropriate permission to fetch the object.
|
||||
* @param objectId the Facebook object's ID
|
||||
* @param type the Java type to fetch
|
||||
* @param queryParameters query parameters to include in the request
|
||||
* @return an Java object representing the requested Facebook object.
|
||||
*/
|
||||
<T> T fetchObject(String objectId, Class<T> type, MultiValueMap<String, String> queryParameters);
|
||||
|
||||
/**
|
||||
* Fetches connections, extracting them into a Java type via the given {@link ResponseExtractor}.
|
||||
* Requires appropriate permission to fetch the object connection.
|
||||
* @param objectId the ID of the object to retrieve the connections for.
|
||||
* @param connectionType the connection type.
|
||||
* @param type the Java type to fetch
|
||||
* @param fields the fields to include in the response.
|
||||
* @return a list of Java objects representing the Facebook objects in the connections.
|
||||
*/
|
||||
<T> T fetchConnections(String objectId, String connectionType, Class<T> type, String... fields);
|
||||
|
||||
/**
|
||||
* Fetches connections, extracting them into a Java type via the given {@link ResponseExtractor}.
|
||||
* Requires appropriate permission to fetch the object connection.
|
||||
* @param objectId the ID of the object to retrieve the connections for.
|
||||
* @param connectionType the connection type.
|
||||
* @param type the Java type to fetch
|
||||
* @param queryParameters query parameters to include in the request
|
||||
* @return a list of Java objects representing the Facebook objects in the connections.
|
||||
*/
|
||||
<T> T fetchConnections(String objectId, String connectionType, Class<T> type, MultiValueMap<String, String> queryParameters);
|
||||
|
||||
/**
|
||||
* Fetches an image as an array of bytes.
|
||||
* @param objectId the object ID
|
||||
* @param connectionType the connection type
|
||||
* @param imageType the type of image to retrieve (eg., small, normal, large, or square)
|
||||
* @return an image as an array of bytes.
|
||||
*/
|
||||
byte[] fetchImage(String objectId, String connectionType, ImageType imageType);
|
||||
|
||||
/**
|
||||
* Publishes data to an object's connection.
|
||||
* Requires appropriate permission to publish to the object connection.
|
||||
* @param objectId the object ID to publish to.
|
||||
* @param connectionType the connection type to publish to.
|
||||
* @param data the data to publish to the connection.
|
||||
* @return the ID of the newly published object.
|
||||
*/
|
||||
String publish(String objectId, String connectionType, MultiValueMap<String, Object> data);
|
||||
|
||||
/**
|
||||
* Publishes data to an object's connection.
|
||||
* Requires appropriate permission to publish to the object connection.
|
||||
* This differs from publish() only in that it doesn't attempt to extract the ID from the response.
|
||||
* This is because some publish operations do not return an ID in the response.
|
||||
* @param objectId the object ID to publish to.
|
||||
* @param connectionType the connection type to publish to.
|
||||
* @param data the data to publish to the connection.
|
||||
*/
|
||||
void post(String objectId, String connectionType, MultiValueMap<String, String> data);
|
||||
|
||||
/**
|
||||
* Deletes an object.
|
||||
* Requires appropriate permission to delete the object.
|
||||
* @param objectId the object ID
|
||||
*/
|
||||
void delete(String objectId);
|
||||
|
||||
/**
|
||||
* Deletes an object connection.
|
||||
* Requires appropriate permission to delete the object connection.
|
||||
* @param objectId the object ID
|
||||
* @param connectionType the connection type
|
||||
*/
|
||||
void delete(String objectId, String connectionType);
|
||||
|
||||
static final String GRAPH_API_URL = "https://graph.facebook.com/";
|
||||
|
||||
static final String OBJECT_URL = GRAPH_API_URL + "{objectId}";
|
||||
|
||||
static final String CONNECTION_URL = OBJECT_URL + "/{connection}";
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2011 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.alfresco.repo.publishing.flickr.springsocial.api;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.social.ApiException;
|
||||
import org.springframework.social.InsufficientPermissionException;
|
||||
import org.springframework.social.MissingAuthorizationException;
|
||||
|
||||
|
||||
public interface MediaOperations {
|
||||
|
||||
PhotoMetadata createPhotoMetadata();
|
||||
|
||||
/**
|
||||
* Uploads a photo to an album created specifically for the application.
|
||||
* Requires "publish_stream" permission.
|
||||
* If no album exists for the application, it will be created.
|
||||
* @param photo A {@link Resource} for the photo data. The given Resource must implement the getFilename() method (such as {@link FileSystemResource} or {@link ClassPathResource}).
|
||||
* @return the ID of the photo.
|
||||
* @throws ApiException if there is an error while communicating with Facebook.
|
||||
* @throws InsufficientPermissionException if the user has not granted "publish_stream" permission.
|
||||
* @throws MissingAuthorizationException if FacebookTemplate was not created with an access token.
|
||||
*/
|
||||
String postPhoto(Resource photo, PhotoMetadata metadata);
|
||||
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package org.alfresco.repo.publishing.flickr.springsocial.api;
|
||||
|
||||
public interface PhotoMetadata
|
||||
{
|
||||
|
||||
void setDescription(String description);
|
||||
|
||||
void setTitle(String title);
|
||||
|
||||
String getDescription();
|
||||
|
||||
String getTitle();
|
||||
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2011 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.alfresco.repo.publishing.flickr.springsocial.api;
|
||||
|
||||
|
||||
|
||||
|
||||
public interface UserOperations {
|
||||
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2011 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.alfresco.repo.publishing.flickr.springsocial.api.impl;
|
||||
|
||||
import org.springframework.social.MissingAuthorizationException;
|
||||
|
||||
class AbstractFlickrOperations {
|
||||
|
||||
private final boolean isAuthorized;
|
||||
|
||||
public AbstractFlickrOperations(boolean isAuthorized) {
|
||||
this.isAuthorized = isAuthorized;
|
||||
}
|
||||
|
||||
protected void requireAuthorization() {
|
||||
if (!isAuthorized) {
|
||||
throw new MissingAuthorizationException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2011 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.alfresco.repo.publishing.flickr.springsocial.api.impl;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.social.ExpiredAuthorizationException;
|
||||
import org.springframework.social.InsufficientPermissionException;
|
||||
import org.springframework.social.InternalServerErrorException;
|
||||
import org.springframework.social.InvalidAuthorizationException;
|
||||
import org.springframework.social.MissingAuthorizationException;
|
||||
import org.springframework.social.NotAuthorizedException;
|
||||
import org.springframework.social.OperationNotPermittedException;
|
||||
import org.springframework.social.ResourceNotFoundException;
|
||||
import org.springframework.social.RevokedAuthorizationException;
|
||||
import org.springframework.social.UncategorizedApiException;
|
||||
import org.springframework.social.facebook.api.NotAFriendException;
|
||||
import org.springframework.social.facebook.api.ResourceOwnershipException;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
|
||||
/**
|
||||
* Subclass of {@link DefaultResponseErrorHandler} that handles errors from Facebook's
|
||||
* Graph API, interpreting them into appropriate exceptions.
|
||||
* @author Craig Walls
|
||||
*/
|
||||
class FlickrErrorHandler extends DefaultResponseErrorHandler {
|
||||
|
||||
@Override
|
||||
public void handleError(ClientHttpResponse response) throws IOException {
|
||||
Map<String, String> errorDetails = extractErrorDetailsFromResponse(response);
|
||||
if (errorDetails == null) {
|
||||
handleUncategorizedError(response, errorDetails);
|
||||
}
|
||||
|
||||
handleFacebookError(response.getStatusCode(), errorDetails);
|
||||
|
||||
// if not otherwise handled, do default handling and wrap with UncategorizedApiException
|
||||
handleUncategorizedError(response, errorDetails);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasError(ClientHttpResponse response) throws IOException {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getBody()));
|
||||
return super.hasError(response) || (reader.ready() && reader.readLine().startsWith("{\"error\":"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Examines the error data returned from Facebook and throws the most applicable exception.
|
||||
* @param errorDetails a Map containing a "type" and a "message" corresponding to the Graph API's error response structure.
|
||||
*/
|
||||
void handleFacebookError(HttpStatus statusCode, Map<String, String> errorDetails) {
|
||||
// Can't trust the type to be useful. It's often OAuthException, even for things not OAuth-related.
|
||||
// Can rely only on the message (which itself isn't very consistent).
|
||||
String message = errorDetails.get("message");
|
||||
|
||||
if (statusCode == HttpStatus.OK) {
|
||||
if (message.contains("Some of the aliases you requested do not exist")) {
|
||||
throw new ResourceNotFoundException(message);
|
||||
}
|
||||
} else if (statusCode == HttpStatus.BAD_REQUEST) {
|
||||
if (message.contains("Unknown path components")) {
|
||||
throw new ResourceNotFoundException(message);
|
||||
} else if (message.equals("An access token is required to request this resource.")) {
|
||||
throw new MissingAuthorizationException();
|
||||
} else if (message.equals("An active access token must be used to query information about the current user.")) {
|
||||
throw new MissingAuthorizationException();
|
||||
} else if (message.startsWith("Error validating access token")) {
|
||||
if (message.contains("Session has expired at unix time")) {
|
||||
throw new ExpiredAuthorizationException();
|
||||
} else if (message.contains("The session has been invalidated because the user has changed the password.")) {
|
||||
throw new RevokedAuthorizationException();
|
||||
} else if (message.contains("The session is invalid because the user logged out.")) {
|
||||
throw new RevokedAuthorizationException();
|
||||
} else if (message.contains("has not authorized application")) {
|
||||
// Per https://developers.facebook.com/blog/post/500/, this could be in the message when the user removes the application.
|
||||
// In reality, "The session has been invalidated because the user has changed the password." is what you get in that case.
|
||||
// Leaving this check in place in case there FB does return this message (could be a bug in FB?)
|
||||
throw new RevokedAuthorizationException();
|
||||
} else {
|
||||
throw new InvalidAuthorizationException(message);
|
||||
}
|
||||
} else if (message.equals("Error validating application.")) { // Access token with incorrect app ID
|
||||
throw new InvalidAuthorizationException(message);
|
||||
} else if (message.equals("Invalid access token signature.")) { // Access token that fails signature validation
|
||||
throw new InvalidAuthorizationException(message);
|
||||
}
|
||||
} else if (statusCode == HttpStatus.UNAUTHORIZED) {
|
||||
throw new NotAuthorizedException(message);
|
||||
} else if (statusCode == HttpStatus.FORBIDDEN) {
|
||||
if (message.contains("Requires extended permission")) {
|
||||
String requiredPermission = message.split(": ")[1];
|
||||
throw new InsufficientPermissionException(requiredPermission);
|
||||
} else {
|
||||
throw new OperationNotPermittedException(message);
|
||||
}
|
||||
} else if (statusCode == HttpStatus.INTERNAL_SERVER_ERROR) {
|
||||
if (message.equals("User must be an owner of the friendlist")) { // watch for pattern in similar message in other resources
|
||||
throw new ResourceOwnershipException(message);
|
||||
} else if (message.equals("The member must be a friend of the current user.")) {
|
||||
throw new NotAFriendException(message);
|
||||
} else {
|
||||
throw new InternalServerErrorException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleUncategorizedError(ClientHttpResponse response, Map<String, String> errorDetails) {
|
||||
try {
|
||||
super.handleError(response);
|
||||
} catch (Exception e) {
|
||||
if (errorDetails != null) {
|
||||
throw new UncategorizedApiException(errorDetails.get("message"), e);
|
||||
} else {
|
||||
throw new UncategorizedApiException("No error details from Facebook", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempts to extract Facebook error details from the response.
|
||||
* Returns null if the response doesn't match the expected JSON error response.
|
||||
*/
|
||||
private Map<String, String> extractErrorDetailsFromResponse(ClientHttpResponse response) throws IOException {
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.alfresco.repo.publishing.flickr.springsocial.api.impl;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.Flickr;
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.MediaOperations;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.social.NotAuthorizedException;
|
||||
import org.springframework.social.oauth1.AbstractOAuth1ApiBinding;
|
||||
import org.springframework.social.support.ClientHttpRequestFactorySelector;
|
||||
import org.springframework.social.support.URIBuilder;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* <p>This is the central class for interacting with Facebook.</p>
|
||||
* <p>
|
||||
* There are some operations, such as searching, that do not require OAuth
|
||||
* authentication. In those cases, you may use a {@link FlickrTemplate} that is
|
||||
* created through the default constructor and without any OAuth details.
|
||||
* Attempts to perform secured operations through such an instance, however,
|
||||
* will result in {@link NotAuthorizedException} being thrown.
|
||||
* </p>
|
||||
* @author Craig Walls
|
||||
*/
|
||||
public class FlickrTemplate extends AbstractOAuth1ApiBinding implements Flickr {
|
||||
private final String REST_ENDPOINT = "http://api.flickr.com/services/rest/";
|
||||
private String consumerKey;
|
||||
|
||||
private MediaOperations mediaOperations;
|
||||
|
||||
/**
|
||||
* Create a new instance of FacebookTemplate.
|
||||
* This constructor creates a new FacebookTemplate able to perform unauthenticated operations against Facebook's Graph API.
|
||||
* Some operations do not require OAuth authentication.
|
||||
* For example, retrieving a specified user's profile or feed does not require authentication (although the data returned will be limited to what is publicly available).
|
||||
* A FacebookTemplate created with this constructor will support those operations.
|
||||
* Those operations requiring authentication will throw {@link NotAuthorizedException}.
|
||||
*/
|
||||
public FlickrTemplate() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of FacebookTemplate.
|
||||
* This constructor creates the FacebookTemplate using a given access token.
|
||||
* @param accessToken An access token given by Facebook after a successful OAuth 2 authentication (or through Facebook's JS library).
|
||||
*/
|
||||
public FlickrTemplate(String consumerKey, String consumerSecret, String accessToken, String accessTokenSecret) {
|
||||
super(consumerKey, consumerSecret, accessToken, accessTokenSecret);
|
||||
this.consumerKey = consumerKey;
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initSubApis() {
|
||||
mediaOperations = new MediaTemplate(consumerKey, getRestTemplate(), isAuthorized());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
|
||||
// Wrap the request factory with a BufferingClientHttpRequestFactory so that the error handler can do repeat reads on the response.getBody()
|
||||
super.setRequestFactory(ClientHttpRequestFactorySelector.bufferRequests(requestFactory));
|
||||
}
|
||||
|
||||
public MediaOperations mediaOperations() {
|
||||
return mediaOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<HttpMessageConverter<?>> getMessageConverters() {
|
||||
List<HttpMessageConverter<?>> messageConverters = super.getMessageConverters();
|
||||
messageConverters.add(new ByteArrayHttpMessageConverter());
|
||||
return messageConverters;
|
||||
}
|
||||
|
||||
// private helpers
|
||||
private void initialize() {
|
||||
getRestTemplate().setErrorHandler(new FlickrErrorHandler());
|
||||
// Wrap the request factory with a BufferingClientHttpRequestFactory so that the error handler can do repeat reads on the response.getBody()
|
||||
super.setRequestFactory(ClientHttpRequestFactorySelector.bufferRequests(getRestTemplate().getRequestFactory()));
|
||||
initSubApis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test()
|
||||
{
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
|
||||
params.add("api_key", consumerKey);
|
||||
params.add("format", "json");
|
||||
params.add("method", "flickr.test.login");
|
||||
params.add("nojsoncallback", "1");
|
||||
URI uri = URIBuilder.fromUri(REST_ENDPOINT).queryParams(params).build();
|
||||
getRestTemplate().getForObject(uri, String.class);
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2011 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.alfresco.repo.publishing.flickr.springsocial.api.impl;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.MediaOperations;
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.PhotoMetadata;
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.impl.AbstractFlickrOperations;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.social.support.URIBuilder;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
class MediaTemplate extends AbstractFlickrOperations implements MediaOperations
|
||||
{
|
||||
private final RestTemplate restTemplate;
|
||||
private String consumerKey;
|
||||
|
||||
public MediaTemplate(String consumerKey, RestTemplate restTemplate, boolean isAuthorizedForUser)
|
||||
{
|
||||
super(isAuthorizedForUser);
|
||||
this.restTemplate = restTemplate;
|
||||
this.consumerKey = consumerKey;
|
||||
}
|
||||
|
||||
public String postPhoto(Resource photo, PhotoMetadata metadata)
|
||||
{
|
||||
requireAuthorization();
|
||||
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
|
||||
parts.set("api_key", consumerKey);
|
||||
if (metadata.getDescription() != null)
|
||||
parts.set("description", metadata.getDescription());
|
||||
parts.set("photo", photo);
|
||||
if (metadata.getTitle() != null)
|
||||
parts.set("title", metadata.getTitle());
|
||||
URI uri = URIBuilder.fromUri("http://api.flickr.com/services/upload/").build();
|
||||
String response = restTemplate.postForObject(uri, parts, String.class);
|
||||
return (String) response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhotoMetadata createPhotoMetadata()
|
||||
{
|
||||
return new PhotoMetadataImpl();
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package org.alfresco.repo.publishing.flickr.springsocial.api.impl;
|
||||
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.PhotoMetadata;
|
||||
|
||||
public class PhotoMetadataImpl implements PhotoMetadata
|
||||
{
|
||||
private String title;
|
||||
private String description;
|
||||
|
||||
public String getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description)
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2011 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.alfresco.repo.publishing.flickr.springsocial.api.impl;
|
||||
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.UserOperations;
|
||||
|
||||
class UserTemplate extends AbstractFlickrOperations implements UserOperations {
|
||||
|
||||
public UserTemplate(boolean isAuthorized)
|
||||
{
|
||||
super(isAuthorized);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2011 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.alfresco.repo.publishing.flickr.springsocial.connect;
|
||||
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.Flickr;
|
||||
import org.springframework.social.ApiException;
|
||||
import org.springframework.social.connect.ApiAdapter;
|
||||
import org.springframework.social.connect.ConnectionValues;
|
||||
import org.springframework.social.connect.UserProfile;
|
||||
import org.springframework.social.connect.UserProfileBuilder;
|
||||
|
||||
/**
|
||||
* Facebook ApiAdapter implementation.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class FlickrAdapter implements ApiAdapter<Flickr>
|
||||
{
|
||||
|
||||
public boolean test(Flickr flickr)
|
||||
{
|
||||
try
|
||||
{
|
||||
flickr.test();
|
||||
return true;
|
||||
}
|
||||
catch (ApiException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setConnectionValues(Flickr facebook, ConnectionValues values)
|
||||
{
|
||||
}
|
||||
|
||||
public UserProfile fetchUserProfile(Flickr facebook)
|
||||
{
|
||||
return new UserProfileBuilder().setName("Brian").setFirstName("Brian").setLastName(
|
||||
"Brian").setEmail("Brian").setUsername("Brian").build();
|
||||
}
|
||||
|
||||
public void updateStatus(Flickr facebook, String message)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2011 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.alfresco.repo.publishing.flickr.springsocial.connect;
|
||||
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.Flickr;
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.connect.FlickrAdapter;
|
||||
import org.springframework.social.connect.support.OAuth1ConnectionFactory;
|
||||
|
||||
public class FlickrConnectionFactory extends OAuth1ConnectionFactory<Flickr> {
|
||||
|
||||
public FlickrConnectionFactory(String consumerKey, String consumerSecret) {
|
||||
super("flickr", new FlickrServiceProvider(consumerKey, consumerSecret), new FlickrAdapter());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.alfresco.repo.publishing.flickr.springsocial.connect;
|
||||
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.Flickr;
|
||||
import org.alfresco.repo.publishing.flickr.springsocial.api.impl.FlickrTemplate;
|
||||
import org.springframework.social.oauth1.AbstractOAuth1ServiceProvider;
|
||||
import org.springframework.social.oauth1.OAuth1Template;
|
||||
|
||||
public class FlickrServiceProvider extends AbstractOAuth1ServiceProvider<Flickr> {
|
||||
|
||||
public FlickrServiceProvider(String consumerKey, String consumerSecret) {
|
||||
super(consumerKey, consumerSecret, new OAuth1Template(consumerKey, consumerSecret,
|
||||
"http://www.flickr.com/services/oauth/request_token",
|
||||
"http://www.flickr.com/services/oauth/authorize",
|
||||
"http://www.flickr.com/services/oauth/access_token"));
|
||||
}
|
||||
|
||||
public Flickr getApi(String accessToken, String secret) {
|
||||
return new FlickrTemplate(getConsumerKey(), getConsumerSecret(), accessToken, secret);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Flickr service provider connection repository and API adapter implementations.
|
||||
*/
|
||||
package org.alfresco.repo.publishing.flickr.springsocial.connect;
|
@@ -22,9 +22,7 @@ import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.publishing.AbstractChannelType;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
@@ -36,27 +34,10 @@ import org.alfresco.service.namespace.QName;
|
||||
public class SlideShareChannelType extends AbstractChannelType
|
||||
{
|
||||
public final static String ID = "slideshare";
|
||||
private final static Set<String> DEFAULT_MIME_TYPES = new TreeSet<String>();
|
||||
|
||||
private NodeService nodeService;
|
||||
private ActionService actionService;
|
||||
private Set<String> permittedMimeTypes = Collections.unmodifiableSet(DEFAULT_MIME_TYPES);
|
||||
|
||||
static
|
||||
{
|
||||
DEFAULT_MIME_TYPES.add(MimetypeMap.MIMETYPE_PPT);
|
||||
DEFAULT_MIME_TYPES.add(MimetypeMap.MIMETYPE_PDF);
|
||||
DEFAULT_MIME_TYPES.add(MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION);
|
||||
DEFAULT_MIME_TYPES.add(MimetypeMap.MIMETYPE_OPENXML_PRESENTATION);
|
||||
DEFAULT_MIME_TYPES.add(MimetypeMap.MIMETYPE_IWORK_KEYNOTE);
|
||||
DEFAULT_MIME_TYPES.add(MimetypeMap.MIMETYPE_IWORK_PAGES);
|
||||
DEFAULT_MIME_TYPES.add(MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||
DEFAULT_MIME_TYPES.add(MimetypeMap.MIMETYPE_OPENDOCUMENT_TEXT);
|
||||
DEFAULT_MIME_TYPES.add(MimetypeMap.MIMETYPE_TEXT_CSV);
|
||||
DEFAULT_MIME_TYPES.add(MimetypeMap.MIMETYPE_EXCEL);
|
||||
DEFAULT_MIME_TYPES.add(MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING);
|
||||
DEFAULT_MIME_TYPES.add(MimetypeMap.MIMETYPE_OPENDOCUMENT_SPREADSHEET);
|
||||
}
|
||||
private SlideSharePublishingHelper publishingHelper;
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
@@ -68,13 +49,9 @@ public class SlideShareChannelType extends AbstractChannelType
|
||||
this.actionService = actionService;
|
||||
}
|
||||
|
||||
public void setPermittedMimeTypes(Set<String> permittedMimeTypes)
|
||||
public void setPublishingHelper(SlideSharePublishingHelper publishingHelper)
|
||||
{
|
||||
if (permittedMimeTypes == null)
|
||||
{
|
||||
permittedMimeTypes = Collections.emptySet();
|
||||
}
|
||||
this.permittedMimeTypes = Collections.unmodifiableSet(permittedMimeTypes);
|
||||
this.publishingHelper = publishingHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,7 +93,7 @@ public class SlideShareChannelType extends AbstractChannelType
|
||||
@Override
|
||||
public Set<String> getSupportedMimetypes()
|
||||
{
|
||||
return permittedMimeTypes;
|
||||
return publishingHelper.getAllowedMimeTypes().keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -24,7 +24,6 @@ import java.util.List;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
|
||||
import org.alfresco.repo.content.filestore.FileContentReader;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ParameterDefinition;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
@@ -38,6 +37,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.benfante.jslideshare.SlideShareAPI;
|
||||
import com.benfante.jslideshare.messages.Slideshow;
|
||||
|
||||
public class SlideSharePublishAction extends ActionExecuterAbstractBase
|
||||
{
|
||||
@@ -84,20 +84,19 @@ public class SlideSharePublishAction extends ActionExecuterAbstractBase
|
||||
if (reader.exists())
|
||||
{
|
||||
File contentFile;
|
||||
String mime = reader.getMimetype();
|
||||
|
||||
String extension = slideShareHelper.getAllowedMimeTypes().get(mime);
|
||||
if (extension == null) extension = "";
|
||||
|
||||
boolean deleteContentFileOnCompletion = false;
|
||||
if (FileContentReader.class.isAssignableFrom(reader.getClass()))
|
||||
{
|
||||
//Grab the content straight from the content store if we can...
|
||||
contentFile = ((FileContentReader)reader).getFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
//...otherwise copy it to a temp file and use the copy...
|
||||
|
||||
//SlideShare seems to work entirely off file extension, so we always copy onto the
|
||||
//file system and upload from there.
|
||||
File tempDir = TempFileProvider.getLongLifeTempDir("slideshare");
|
||||
contentFile = TempFileProvider.createTempFile("slideshare", "", tempDir);
|
||||
contentFile = TempFileProvider.createTempFile("slideshare", extension, tempDir);
|
||||
reader.getContent(contentFile);
|
||||
deleteContentFileOnCompletion = true;
|
||||
}
|
||||
|
||||
String name = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||
String title = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE);
|
||||
@@ -121,8 +120,17 @@ public class SlideSharePublishAction extends ActionExecuterAbstractBase
|
||||
|
||||
String assetId = api.uploadSlideshow(usernamePassword.getFirst(), usernamePassword.getSecond(), title,
|
||||
contentFile, description, tags.toString(), false, false, false, false, false);
|
||||
// String url = api.getSlideshow(assetId).getPermalink();
|
||||
|
||||
String url = null;
|
||||
Slideshow slides = api.getSlideshow(assetId);
|
||||
if (slides != null)
|
||||
{
|
||||
url = slides.getPermalink();
|
||||
if (log.isInfoEnabled())
|
||||
{
|
||||
log.info("SlideShare has provided a URL for asset " + assetId + ": " + url);
|
||||
}
|
||||
}
|
||||
if (log.isInfoEnabled())
|
||||
{
|
||||
log.info("File " + name + " has been published to SlideShare with id " + assetId + " at URL " + url);
|
||||
|
@@ -18,6 +18,11 @@
|
||||
*/
|
||||
package org.alfresco.repo.publishing.slideshare;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.publishing.PublishingModel;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
@@ -28,6 +33,24 @@ import com.benfante.jslideshare.SlideShareConnector;
|
||||
|
||||
public class SlideSharePublishingHelper
|
||||
{
|
||||
private final static Map<String,String> DEFAULT_MIME_TYPES = new TreeMap<String,String>();
|
||||
static
|
||||
{
|
||||
DEFAULT_MIME_TYPES.put(MimetypeMap.MIMETYPE_PPT, ".ppt");
|
||||
DEFAULT_MIME_TYPES.put(MimetypeMap.MIMETYPE_PDF, ".pdf");
|
||||
DEFAULT_MIME_TYPES.put(MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION, ".odp");
|
||||
DEFAULT_MIME_TYPES.put(MimetypeMap.MIMETYPE_OPENXML_PRESENTATION, ".pptx");
|
||||
DEFAULT_MIME_TYPES.put(MimetypeMap.MIMETYPE_IWORK_KEYNOTE, "");
|
||||
DEFAULT_MIME_TYPES.put(MimetypeMap.MIMETYPE_IWORK_PAGES, "");
|
||||
DEFAULT_MIME_TYPES.put(MimetypeMap.MIMETYPE_TEXT_PLAIN, ".txt");
|
||||
DEFAULT_MIME_TYPES.put(MimetypeMap.MIMETYPE_OPENDOCUMENT_TEXT, ".odt");
|
||||
DEFAULT_MIME_TYPES.put(MimetypeMap.MIMETYPE_TEXT_CSV, ".csv");
|
||||
DEFAULT_MIME_TYPES.put(MimetypeMap.MIMETYPE_EXCEL, ".xls");
|
||||
DEFAULT_MIME_TYPES.put(MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING, ".docx");
|
||||
DEFAULT_MIME_TYPES.put(MimetypeMap.MIMETYPE_OPENDOCUMENT_SPREADSHEET, ".ods");
|
||||
}
|
||||
|
||||
private Map<String, String> allowedMimeTypes = Collections.unmodifiableMap(DEFAULT_MIME_TYPES);
|
||||
private NodeService nodeService;
|
||||
private SlideShareConnector slideshareConnector;
|
||||
|
||||
@@ -41,6 +64,16 @@ public class SlideSharePublishingHelper
|
||||
this.slideshareConnector = slideshareConnector;
|
||||
}
|
||||
|
||||
public Map<String, String> getAllowedMimeTypes()
|
||||
{
|
||||
return allowedMimeTypes;
|
||||
}
|
||||
|
||||
public void setAllowedMimeTypes(Map<String, String> allowedMimeTypes)
|
||||
{
|
||||
this.allowedMimeTypes = Collections.unmodifiableMap(allowedMimeTypes);
|
||||
}
|
||||
|
||||
public SlideShareAPI getSlideShareApi()
|
||||
{
|
||||
return createApiObject();
|
||||
|
@@ -17,7 +17,7 @@ public class BitlyUrlShortenerImpl implements UrlShortener
|
||||
{
|
||||
private static final Log log = LogFactory.getLog(BitlyUrlShortenerImpl.class);
|
||||
|
||||
private int urlLength;
|
||||
private int urlLength = 20;
|
||||
private String username;
|
||||
private String apiKey = "R_ca15c6c89e9b25ccd170bafd209a0d4f";
|
||||
private HttpClient httpClient;
|
||||
|
@@ -64,11 +64,10 @@ public interface ChannelService
|
||||
Channel createChannel(String siteId, String channelTypeId, String name, Map<QName, Serializable> properties);
|
||||
|
||||
/**
|
||||
* Remove the channel with the specified name on the specified Share site.
|
||||
* @param siteId The identifier of the Share site that contains the channel to be deleted.
|
||||
* @param channelName The name of the channel that is to be deleted.
|
||||
* Remove the specified channel.
|
||||
* @param channel The channel to delete.
|
||||
*/
|
||||
void deleteChannel(String siteId, String channelName);
|
||||
void deleteChannel(Channel channel);
|
||||
|
||||
/**
|
||||
* Rename the specified channel
|
||||
|
Reference in New Issue
Block a user