Merged BRANCHES/DEV/BRIAN/PUBLISHING to HEAD:

29482: Publishing:
   - Added support for LinkedIn status updates
 29486: Social Publishing UI Updates, including:
   - Dialogue: Complete UI rework
   - Publishing History: display of unpublish event support
   - Created Alfresco.util.toggleClass function
 29491: Publishing:
   - Added correct list of supported MIME types the the YouTube channel type
 29493: Publishing:
   - Added video/mp4 to YouTube supported MIME types
 29496: ChannelsGet now filters out channels that are not authorised. Added a space before the node URL on status updates. Extended unit tests to check behaviour for non-Admin users.
 29513: Adds specific http client libraries to prevent the mac falling back to it's buggy default implementation (which, e.g. doesn't send Content-Length headers if the content length is zero). Required for Flickr support (their publish API requires both a content length header and zero length content. It returns a 411 error using the default Mac libs).
 29534: Fixed PublishingEventsGet REST method. ChannelService getChannels() methods now support filtering by publish permissions.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29542 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Brian Remmington
2011-08-04 08:26:41 +00:00
parent 34585f5f2e
commit 7ceaf0a9b0
39 changed files with 1114 additions and 384 deletions

View File

@@ -13,7 +13,7 @@
<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">
<bean class="org.alfresco.repo.publishing.linkedin.springsocial.connect.LinkedInConnectionFactory">
<constructor-arg value="l0a39tvf6v4x" />
<constructor-arg value="veWjLwlnJmu7IyFs" />
</bean>

View File

@@ -32,16 +32,7 @@
<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>
<parent>pub:AssetAspect</parent>
</aspect>
</aspects>
</model>

View File

@@ -282,23 +282,23 @@
<association name="pub:lastPublishingEvent">
<source>
<mandatory>false</mandatory>
<many>false</many>
<many>true</many>
</source>
<target>
<class>pub:PublishingEvent</class>
<mandatory>false</mandatory>
<many>true</many>
<many>false</many>
</target>
</association>
<association name="pub:publishedChannel">
<source>
<mandatory>false</mandatory>
<many>false</many>
<many>true</many>
</source>
<target>
<class>pub:DeliveryChannel</class>
<mandatory>false</mandatory>
<many>true</many>
<many>false</many>
</target>
</association>
</associations>

View File

@@ -30,7 +30,6 @@ import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVa
import static org.alfresco.repo.invitation.WorkflowModelNominatedInvitation.wfVarServerPath;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
@@ -66,7 +65,6 @@ import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.util.ModelUtil;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

View File

@@ -139,7 +139,7 @@ public abstract class AbstractChannelType implements ChannelType, InitializingBe
@Override
public int getMaximumStatusLength()
{
return -1;
return 0;
}
@Override

View File

@@ -19,22 +19,17 @@
package org.alfresco.repo.publishing;
import static org.alfresco.repo.publishing.PublishingModel.TYPE_DELIVERY_CHANNEL;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import javax.transaction.Status;
import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.person.TestPersonManager;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.publishing.channels.ChannelType;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.publishing.PublishingService;
import org.alfresco.service.cmr.publishing.channels.ChannelService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.cmr.site.SiteVisibility;
import org.alfresco.util.BaseSpringTest;
import org.alfresco.util.GUID;
import org.junit.After;
@@ -49,50 +44,42 @@ public abstract class AbstractPublishingIntegrationTest extends BaseSpringTest
{
protected static final String channelTypeId = "MockChannelType";
protected PublishingRootObject rootObject;
protected ServiceRegistry serviceRegistry;
protected SiteService siteService;
protected FileFolderService fileFolderService;
protected NodeService nodeService;
protected PublishingTestHelper testHelper;
protected TestPersonManager personManager;
protected String username;
protected String siteId;
protected PublishingQueueImpl queue;
protected Environment environment;
protected NodeRef docLib;
@Override
@Before
public void onSetUp() throws Exception
{
super.onSetUp();
this.rootObject = (PublishingRootObject) getApplicationContext().getBean("publishingRootObject");
serviceRegistry = (ServiceRegistry) getApplicationContext().getBean("ServiceRegistry");
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
this.siteService = serviceRegistry.getSiteService();
this.fileFolderService = serviceRegistry.getFileFolderService();
this.nodeService = serviceRegistry.getNodeService();
this.siteId = GUID.generate();
siteService.createSite("test", siteId,
"Site created by publishing test",
"Site created by publishing test",
SiteVisibility.PUBLIC);
this.docLib = siteService.createContainer(siteId, SiteService.DOCUMENT_LIBRARY, ContentModel.TYPE_FOLDER, null);
this.environment = rootObject.getEnvironment();
this.queue = rootObject.getPublishingQueue();
serviceRegistry = (ServiceRegistry) getApplicationContext().getBean(ServiceRegistry.SERVICE_REGISTRY);
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
SiteService siteService = serviceRegistry.getSiteService();
FileFolderService fileFolderService = serviceRegistry.getFileFolderService();
PermissionService permissionService = serviceRegistry.getPermissionService();
this.nodeService = serviceRegistry.getNodeService();
ChannelService channelService = (ChannelService) getApplicationContext().getBean(ChannelServiceImpl.NAME);
PublishingService publishingService = (PublishingService) getApplicationContext().getBean(PublishServiceImpl.NAME);
MutableAuthenticationService authenticationService= (MutableAuthenticationService) getApplicationContext().getBean(ServiceRegistry.AUTHENTICATION_SERVICE.getLocalName());
PersonService personService= (PersonService) getApplicationContext().getBean(ServiceRegistry.PERSON_SERVICE.getLocalName());
this.personManager = new TestPersonManager(authenticationService, personService, nodeService);
this.testHelper = new PublishingTestHelper(channelService, publishingService, siteService, fileFolderService, permissionService);
this.username = GUID.generate();
personManager.createPerson(username);
}
@After
public void onTearDown() throws Exception
{
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
try
{
siteService.deleteSite(siteId);
testHelper.tearDown();
}
finally
{
@@ -100,17 +87,4 @@ public abstract class AbstractPublishingIntegrationTest extends BaseSpringTest
}
}
protected ChannelType mockChannelType()
{
ChannelType channelType = mock(ChannelType.class);
mockChannelTypeBehaviour(channelType);
return channelType;
}
protected void mockChannelTypeBehaviour(ChannelType channelType)
{
when(channelType.getId()).thenReturn(channelTypeId);
when(channelType.getChannelNodeType()).thenReturn(TYPE_DELIVERY_CHANNEL);
}
}

View File

@@ -93,15 +93,14 @@ public class ChannelHelper
nodeService.createNode(parent, ASSOC_CONTAINS, channelQName, channelNodeType, props);
NodeRef channelNode = channelAssoc.getChildRef();
// Allow any user to read Channel permissions.
permissionService.setPermission(channelNode, PermissionService.ALL_AUTHORITIES, PermissionService.READ_PERMISSIONS, true);
permissionService.setPermission(channelNode, PermissionService.ALL_AUTHORITIES, PermissionService.READ_ASSOCIATIONS, true);
return channelNode;
}
public Channel buildChannelObject(NodeRef nodeRef, ChannelService channelService)
{
if(nodeRef == null ||
nodeService.exists(nodeRef)==false ||
permissionService.hasPermission(nodeRef, PermissionService.ADD_CHILDREN)!= AccessStatus.ALLOWED)
nodeService.exists(nodeRef)==false)
{
return null;
}
@@ -259,16 +258,40 @@ public class ChannelHelper
return null;
}
public List<Channel> getChannels(NodeRef channelContainer, final ChannelService channelService)
public List<Channel> getAllChannels(NodeRef channelContainer, final ChannelService channelService)
{
List<ChildAssociationRef> channelAssocs = getChannelAssocs(channelContainer);
return CollectionUtils.transform(channelAssocs, getChannelTransformer(channelService));
return CollectionUtils.transform(channelAssocs, getChannelTransformer(channelService, false));
}
public List<Channel> getChannelsByType(NodeRef containerNode, String channelTypeId, ChannelService channelService)
public List<Channel> getChannelsForTypes(final NodeRef containerNode, List<ChannelType> types, final ChannelService channelService, final boolean checkPermissions)
{
return CollectionUtils.transformFlat(types, new Function<ChannelType, List<Channel>>()
{
public List<Channel> apply(ChannelType channelType)
{
return getChannelsByType(containerNode, channelType.getId(), channelService, checkPermissions);
}
});
}
public List<Channel> getChannelsByType(NodeRef containerNode, String channelTypeId, ChannelService channelService, boolean checkPermissions)
{
List<ChildAssociationRef> channelAssocs = getChannelAssocsByType(containerNode, channelTypeId);
return CollectionUtils.transform(channelAssocs, getChannelTransformer(channelService));
return CollectionUtils.transform(channelAssocs, getChannelTransformer(channelService, checkPermissions));
}
public List<Channel> filterAuthorisedChannels(Collection<Channel> channels)
{
return CollectionUtils.filter(channels, new Filter<Channel>()
{
@Override
public Boolean apply(Channel value)
{
return value.isAuthorised();
}
});
}
public List<ChannelType> getReleventChannelTypes(final NodeRef nodeToPublish, Collection<ChannelType> channelTypes)
@@ -334,18 +357,28 @@ public class ChannelHelper
return null;
}
private Function<ChildAssociationRef, Channel> getChannelTransformer(final ChannelService channelService)
private Function<ChildAssociationRef, Channel> getChannelTransformer(final ChannelService channelService, final boolean checkPermissions)
{
return new Function<ChildAssociationRef, Channel>()
{
public Channel apply(ChildAssociationRef value)
{
NodeRef channelNode = value.getChildRef();
if(checkPermissions && hasPublishPermissions(channelNode)==false)
{
return null;
}
return buildChannelObject(channelNode, channelService);
}
};
}
public boolean hasPublishPermissions(NodeRef channelNode)
{
AccessStatus access = permissionService.hasPermission(channelNode, PermissionService.ADD_CHILDREN);
return AccessStatus.ALLOWED == access;
}
public boolean isChannelAuthorised(NodeRef channelNode)
{
Boolean isAuthorised = Boolean.FALSE;

View File

@@ -29,7 +29,8 @@ import org.alfresco.service.namespace.QName;
/**
* @author Brian
*
* @author Nick Smith
* @since 4.0
*/
public class ChannelImpl implements Channel
{
@@ -38,11 +39,6 @@ public class ChannelImpl implements Channel
private final String name;
private final ChannelHelper channelHelper;
/**
* @param channelType
* @param name
* @param channelService
*/
public ChannelImpl(ChannelType channelType, NodeRef nodeRef, String name, ChannelHelper channelHelper)
{
this.nodeRef = nodeRef;
@@ -57,7 +53,6 @@ public class ChannelImpl implements Channel
@Override
public String getId()
{
// TODO Auto-generated method stub
return nodeRef.toString();
}
@@ -134,8 +129,41 @@ public class ChannelImpl implements Channel
return channelType.getNodeUrl(mappedNode);
}
/**
* {@inheritDoc}
*/
public boolean isAuthorised()
{
return channelHelper.isChannelAuthorised(nodeRef);
}
/**
* {@inheritDoc}
*/
public boolean canPublish()
{
return channelType.canPublish() &&
isAuthorised() &&
channelHelper.hasPublishPermissions(nodeRef);
}
/**
* {@inheritDoc}
*/
public boolean canUnpublish()
{
return channelType.canPublish() &&
isAuthorised() &&
channelHelper.hasPublishPermissions(nodeRef);
}
/**
* {@inheritDoc}
*/
public boolean canPublishStatusUpdates()
{
return channelType.canPublish() &&
isAuthorised() &&
channelHelper.hasPublishPermissions(nodeRef);
}
}

View File

@@ -46,7 +46,6 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck;
import org.alfresco.util.collections.CollectionUtils;
import org.alfresco.util.collections.Filter;
import org.alfresco.util.collections.Function;
/**
* @author Nick Smith
@@ -159,7 +158,7 @@ public class ChannelServiceImpl implements ChannelService
public List<Channel> getChannels()
{
NodeRef channelContainer = getChannelContainer();
return channelHelper.getChannels(channelContainer, this);
return channelHelper.getAllChannels(channelContainer, this);
}
/**
@@ -201,13 +200,14 @@ public class ChannelServiceImpl implements ChannelService
{
NodeRef containerNode = getChannelContainer();
List<ChannelType> types = channelHelper.getReleventChannelTypes(nodeToPublish, channelTypes.values());
return getChannelsForTypes(containerNode, types);
List<Channel> channels = channelHelper.getChannelsForTypes(containerNode, types, this, true);
return channelHelper.filterAuthorisedChannels(channels);
}
/**
* {@inheritDoc}
*/
public List<Channel> getPublishingChannels()
public List<Channel> getPublishingChannels(boolean filterByPublishPermission)
{
final NodeRef containerNode = getChannelContainer();
if(containerNode != null)
@@ -219,7 +219,7 @@ public class ChannelServiceImpl implements ChannelService
return type.canPublish();
}
});
return getChannelsForTypes(containerNode, types);
return channelHelper.getChannelsForTypes(containerNode, types, this, filterByPublishPermission);
}
return Collections.emptyList();
}
@@ -227,16 +227,24 @@ public class ChannelServiceImpl implements ChannelService
/**
* {@inheritDoc}
*/
public List<Channel> getStatusUpdateChannels()
public List<Channel> getStatusUpdateChannels(boolean filterByPublishPermission)
{
final NodeRef containerNode = getChannelContainer();
if (containerNode != null)
{
List<ChannelType> types = channelHelper.getStatusUpdateChannelTypes(channelTypes.values());
return getChannelsForTypes(containerNode, types);
return channelHelper.getChannelsForTypes(containerNode, types, this, filterByPublishPermission);
}
return Collections.emptyList();
}
/**
* {@inheritDoc}
*/
public List<Channel> getAuthorisedStatusUpdateChannels()
{
return channelHelper.filterAuthorisedChannels(getStatusUpdateChannels(false));
}
/**
* {@inheritDoc}
@@ -246,21 +254,10 @@ public class ChannelServiceImpl implements ChannelService
SiteInfo site = siteService.getSite(nodeToPublish);
if(site!=null)
{
return getStatusUpdateChannels();
return getStatusUpdateChannels(false);
}
return Collections.emptyList();
}
private List<Channel> getChannelsForTypes(final NodeRef containerNode, List<ChannelType> types)
{
return CollectionUtils.transformFlat(types, new Function<ChannelType, List<Channel>>()
{
public List<Channel> apply(ChannelType channelType)
{
return channelHelper.getChannelsByType(containerNode, channelType.getId(), ChannelServiceImpl.this);
}
});
}
private NodeRef getChannelContainer()
{
@@ -306,14 +303,9 @@ public class ChannelServiceImpl implements ChannelService
}
}
/*
* (non-Javadoc)
*
* @see
* org.alfresco.service.cmr.publishing.channels.ChannelService#updateChannel
* (java.lang.String, java.lang.String, java.util.Map)
/**
* {@inheritDoc}
*/
@Override
public void updateChannel(Channel channel, Map<QName, Serializable> properties)
{
HashMap<QName, Serializable> actualProps = new HashMap<QName, Serializable>(properties);
@@ -328,7 +320,6 @@ public class ChannelServiceImpl implements ChannelService
/**
* {@inheritDoc}
*/
@Override
public Channel getChannelById(String id)
{
if(id!=null&& NodeRef.isNodeRef(id))
@@ -338,5 +329,5 @@ public class ChannelServiceImpl implements ChannelService
}
return null;
}
}

View File

@@ -19,9 +19,6 @@
package org.alfresco.repo.publishing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
@@ -32,14 +29,10 @@ import javax.annotation.Resource;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.person.TestPersonManager;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.publishing.channels.Channel;
import org.alfresco.service.cmr.publishing.channels.ChannelType;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.GUID;
import org.alfresco.util.collections.CollectionUtils;
@@ -54,29 +47,51 @@ import org.junit.Test;
public class ChannelServiceImplIntegratedTest extends AbstractPublishingIntegrationTest
{
private static final String channelName = GUID.generate();
private static final String channelTypeName = "MockedChannelType";
private static boolean channelTypeRegistered = false;
@Resource(name="channelService")
private ChannelServiceImpl channelService;
private PermissionService permissionService;
private TestPersonManager personManager;
private ChannelType mockedChannelType = mock(ChannelType.class);
@Test
public void testCreateChannel() throws Exception
{
personManager.setUser(username);
try
{
createChannel();
fail("Only Admin user can create channels!");
}
catch(AccessDeniedException e)
{
// NOOP
}
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
Channel channel = createChannel();
assertEquals(channelTypeName, channel.getChannelType().getId());
assertEquals(channelName, channel.getName());
assertTrue(nodeService.exists(channel.getNodeRef()));
assertEquals(channelTypeId, channel.getChannelType().getId());
assertNotNull(channelName, channel.getName());
NodeRef channelNode = new NodeRef(channel.getId());
assertTrue(nodeService.exists(channelNode));
}
@Test
public void testDeleteChannel() throws Exception
{
Channel channel = createChannel();
assertNotNull("The channel should exist! Id: "+channel.getId(), channelService.getChannelById(channel.getId()));
assertNotNull("The channel should exist! Name: "+channelName, channelService.getChannelByName(channelName));
personManager.setUser(username);
try
{
channelService.deleteChannel(channel);
fail("Only Admin users should be able to delete channels.");
}
catch(AccessDeniedException e)
{
//NOOP
}
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
channelService.deleteChannel(channel);
assertNull("The channel should have been deleed! Id: "+channel.getId(), channelService.getChannelById(channel.getId()));
@@ -88,11 +103,26 @@ public class ChannelServiceImplIntegratedTest extends AbstractPublishingIntegrat
{
String newChannelName = "New Channel Name";
Channel channel = createChannel();
channelService.renameChannel(channel, newChannelName);
personManager.setUser(username);
try
{
channelService.renameChannel(channel, newChannelName);
fail("Only Admin user can rename Channel.");
}
catch(AccessDeniedException e)
{
//NOOP
}
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
channelService.renameChannel(channel, newChannelName);
Channel renamedChannel = channelService.getChannelById(channel.getId());
assertNotNull(renamedChannel);
assertEquals(newChannelName, renamedChannel.getName());
assertNotNull(channelService.getChannelByName(newChannelName));
assertNotNull(channelService.getChannelById(channel.getId()));
assertNull(channelService.getChannelByName(channelName));
}
@Test
@@ -105,8 +135,20 @@ public class ChannelServiceImplIntegratedTest extends AbstractPublishingIntegrat
assertNull(props.get(ContentModel.PROP_TITLE));
props.put(ContentModel.PROP_TITLE, newTitle);
channelService.updateChannel(channel, props);
personManager.setUser(username);
try
{
channelService.updateChannel(channel, props);
fail("Only Admin user can rename Channel.");
}
catch(AccessDeniedException e)
{
//NOOP
}
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
channelService.updateChannel(channel, props);
Channel updatedChannel = channelService.getChannelById(channel.getId());
Serializable title = updatedChannel.getProperties().get(ContentModel.PROP_TITLE);
assertNotNull(title);
@@ -119,21 +161,20 @@ public class ChannelServiceImplIntegratedTest extends AbstractPublishingIntegrat
int startingSize = channelService.getChannels().size();
int channelCount = 7;
Set<String> channelNames = new HashSet<String>();
Set<String> ids = new HashSet<String>();
for (int i = 0; i < channelCount; ++i)
{
String name = GUID.generate();
channelNames.add(name);
channelService.createChannel(channelTypeName, name, null);
Channel newChannel = testHelper.createChannel(channelTypeId);
ids.add(newChannel.getId());
List<Channel> channels = channelService.getChannels();
assertEquals(i + 1 + startingSize, channels.size());
Set<String> names = new HashSet<String>(channelNames);
Set<String> idsToCheck = new HashSet<String>(ids);
for (Channel channel : channels)
{
names.remove(channel.getName());
idsToCheck.remove(channel.getId());
}
assertTrue(names.isEmpty());
assertTrue(idsToCheck.isEmpty());
}
}
@@ -142,7 +183,6 @@ public class ChannelServiceImplIntegratedTest extends AbstractPublishingIntegrat
{
// Create Channel as Admin user.
Channel channel = createChannel();
NodeRef channelNode = new NodeRef(channel.getId());
// Create User1 and set as FullyAuthenticatedUser.
String user1 = GUID.generate();
@@ -155,12 +195,8 @@ public class ChannelServiceImplIntegratedTest extends AbstractPublishingIntegrat
List<Channel> channels = channelService.getChannels();
assertFalse("Result of getChannels() should not contain the channel!", checkContainsChannel(channel.getId(), channels));
// Set authentication to Admin
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
//Add Read permissions to User1.
permissionService.setPermission(channelNode, user1, PermissionService.READ, true);
// Set authentication to User1
personManager.setUser(user1);
testHelper.setChannelPermission(user1, channel.getId(), PermissionService.READ);
// Read permissions should not allow access to the Channel.
channelById = channelService.getChannelById(channel.getId());
@@ -168,12 +204,8 @@ public class ChannelServiceImplIntegratedTest extends AbstractPublishingIntegrat
channels = channelService.getChannels();
assertFalse("Result of getChannels() should not contain the channel!", checkContainsChannel(channel.getId(), channels));
// Set authentication to Admin
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
//Add ADD_CHILD permissions to User1.
permissionService.setPermission(channelNode, user1, PermissionService.ADD_CHILDREN, true);
// Set authentication to User1
personManager.setUser(user1);
testHelper.setChannelPermission(user1, channel.getId(), PermissionService.ADD_CHILDREN);
// Add Child permissions should allow access to the Channel.
channelById = channelService.getChannelById(channel.getId());
@@ -183,26 +215,39 @@ public class ChannelServiceImplIntegratedTest extends AbstractPublishingIntegrat
}
@Test
public void testGetChannel() throws Exception
public void testGetChannelByName() throws Exception
{
try
{
channelService.getChannelByName(null);
fail("Should throw an Exception if channelName is null!");
}
catch (IllegalArgumentException e) {
// NOOP
}
Channel channel = channelService.getChannelByName(channelName);
Channel channel = channelService.getChannelById(null);
assertNull("Should return null if unknown channelName", channel);
channel = channelService.getChannelByName(channelName);
assertNull("Should return null if null channelName", channel);
Channel createdChannel = createChannel();
channel = channelService.getChannelByName(channelName);
assertNotNull("Should return created channel!", channel);
assertEquals(channelName, channel.getName());
assertEquals(createdChannel.getChannelType().getId(), channel.getChannelType().getId());
assertEquals(createdChannel.getNodeRef(), channel.getNodeRef());
assertEquals(createdChannel.getId(), channel.getId());
}
@Test
public void testGetChannelById() throws Exception
{
Channel channel = channelService.getChannelById(null);
assertNull("Should return null if null channelId", channel);
channel = channelService.getChannelById("test://channel/id");
assertNull("Should return null if unknown channelId", channel);
Channel createdChannel = createChannel();
channel = channelService.getChannelById(createdChannel.getId());
assertNotNull("Should return created channel!", channel);
assertEquals(createdChannel.getId(), channel.getId());
assertEquals(channelName, channel.getName());
assertEquals(createdChannel.getChannelType().getId(), channel.getChannelType().getId());
}
private boolean checkContainsChannel(final String id, List<Channel> channels)
@@ -217,54 +262,18 @@ public class ChannelServiceImplIntegratedTest extends AbstractPublishingIntegrat
Channel result = CollectionUtils.findFirst(channels, acceptor);
return result != null;
}
private Channel createChannel()
{
return channelService.createChannel(channelTypeName, channelName, null);
return testHelper.createChannel(channelTypeId, channelName);
}
@Before
@Override
public void onSetUp() throws Exception
{
super.onSetUp();
this.channelService = (ChannelServiceImpl) getApplicationContext().getBean("channelService");
this.permissionService = (PermissionService) getApplicationContext().getBean(ServiceRegistry.PERMISSIONS_SERVICE.getLocalName());
MutableAuthenticationService authenticationService= (MutableAuthenticationService) getApplicationContext().getBean(ServiceRegistry.AUTHENTICATION_SERVICE.getLocalName());
PersonService personService= (PersonService) getApplicationContext().getBean(ServiceRegistry.PERSON_SERVICE.getLocalName());
this.personManager = new TestPersonManager(authenticationService, personService, nodeService);
when(mockedChannelType.getId()).thenReturn(channelTypeName);
when(mockedChannelType.getChannelNodeType()).thenReturn(PublishingModel.TYPE_DELIVERY_CHANNEL);
if (!channelTypeRegistered)
{
channelService.register(mockedChannelType);
channelTypeRegistered = true;
}
}
/**
* {@inheritDoc}
*/
@Override
public void onTearDown() throws Exception
{
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
try
{
Channel channel = channelService.getChannelByName(channelName);
if (channel != null)
{
channelService.deleteChannel(channel);
}
}
finally
{
super.onTearDown();
}
testHelper.mockChannelType(channelTypeId);
}
}

View File

@@ -96,6 +96,12 @@ public class JaxbHttpMessageConverter extends AbstractXmlHttpMessageConverter<Ob
throw new UnsupportedOperationException();
}
@Override
protected boolean canWrite(MediaType mediaType)
{
return super.canWrite(mediaType) || MediaType.TEXT_XML.equals(mediaType);
}
@Override
protected Object readFromSource(Class<?> clazz, HttpHeaders headers, Source source) throws IOException
{

View File

@@ -36,7 +36,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -48,22 +47,17 @@ import javax.annotation.Resource;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.publishing.MutablePublishingPackage;
import org.alfresco.service.cmr.publishing.PublishingPackage;
import org.alfresco.service.cmr.publishing.PublishingService;
import org.alfresco.service.cmr.publishing.Status;
import org.alfresco.service.cmr.publishing.StatusUpdate;
import org.alfresco.service.cmr.publishing.channels.Channel;
import org.alfresco.service.cmr.publishing.channels.ChannelService;
import org.alfresco.service.cmr.publishing.channels.ChannelType;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ContentReader;
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.namespace.QName;
import org.alfresco.util.GUID;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
/**
@@ -79,9 +73,6 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
@Resource(name="publishingService")
private PublishingService publishingService;
@Resource(name="channelService")
private ChannelService channelService;
@Resource(name="contentService")
private ContentService contentService;
@@ -93,14 +84,13 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
private Channel channel;
private NodeRef channelNode;
private String eventId;
private ChannelType channelType;
@Test
public void testPublishNodes() throws Exception
{
// Create content node with appropriate aspects added.
NodeRef source = createContentNode(contentNodeName, content);
NodeRef source = testHelper.createContentNode(contentNodeName, content, MimetypeMap.MIMETYPE_TEXT_PLAIN);
double lattitude = 0.25;
double longtitude = 0.75;
@@ -139,9 +129,9 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
public void testUpdatePublishedNode() throws Exception
{
// Create content node without aspects
NodeRef source = createContentNode(contentNodeName, content);
NodeRef source = testHelper.createContentNode(contentNodeName, content, MimetypeMap.MIMETYPE_TEXT_PLAIN);
NodeRef publishEventNode = publishNode(source);
// Check published node exists
NodeRef publishedNode = channelHelper.mapSourceToEnvironment(source, channelNode);
assertNotNull(publishedNode);
@@ -170,7 +160,7 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
String newName = "NewName";
nodeService.setProperty(source, PROP_NAME, newName);
String newContent = "The new content";
writeContent(source, newContent);
testHelper.writeContent(source, newContent, MimetypeMap.MIMETYPE_TEXT_PLAIN);
// Update published node.
publishEventNode = publishNode(source);
@@ -219,7 +209,7 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
public void testChannelTypePublishIsCalledOnPublish() throws Exception
{
// Create content node with appropriate aspects added.
NodeRef source = createContentNode(contentNodeName, content);
NodeRef source = testHelper.createContentNode(contentNodeName, content, MimetypeMap.MIMETYPE_TEXT_PLAIN);
// Enable publishing on ChannelType.
when(channelType.canPublish()).thenReturn(true);
@@ -235,7 +225,7 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
public void testChannelTypePublishIsCalledOnUpdate() throws Exception
{
// Create content node with appropriate aspects added.
NodeRef source = createContentNode(contentNodeName, content);
NodeRef source = testHelper.createContentNode(contentNodeName, content, MimetypeMap.MIMETYPE_TEXT_PLAIN);
// Publish source node but dont' call ChannelType.publish().
publishNode(source);
@@ -259,7 +249,7 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
public void testSupportedContentTypes() throws Exception
{
// Create content node with appropriate aspects added.
NodeRef source = createContentNode(contentNodeName, content);
NodeRef source = testHelper.createContentNode(contentNodeName, content, MimetypeMap.MIMETYPE_TEXT_PLAIN);
// Enable publishing on ChannelType.
when(channelType.canPublish()).thenReturn(true);
@@ -298,7 +288,7 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
public void testSupportedMimeTypes() throws Exception
{
// Create content node with appropriate aspects added.
NodeRef source = createContentNode(contentNodeName, content);
NodeRef source = testHelper.createContentNode(contentNodeName, content, MimetypeMap.MIMETYPE_TEXT_PLAIN);
// Enable publishing on ChannelType.
when(channelType.canPublish()).thenReturn(true);
@@ -326,11 +316,11 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
@SuppressWarnings("unchecked")
public void testStatusUpdate() throws Exception
{
NodeRef source = createContentNode(contentNodeName, content);
NodeRef source = testHelper.createContentNode(contentNodeName, content, MimetypeMap.MIMETYPE_TEXT_PLAIN);
// Create Status Update
String message = "Here is the message ";
StatusUpdate status = queue.createStatusUpdate(message, source, channel.getId());
StatusUpdate status = publishingService.getPublishingQueue().createStatusUpdate(message, source, channel.getId());
String url = "http://test/url";
when(channelType.getNodeUrl(any(NodeRef.class))).thenReturn(url);
@@ -349,9 +339,9 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
private NodeRef publishNode(NodeRef source, StatusUpdate statusUpdate)
{
MutablePublishingPackage pckg = queue.createPublishingPackage();
MutablePublishingPackage pckg = publishingService.getPublishingQueue().createPublishingPackage();
pckg.addNodesToPublish(source);
scheduleEvent(pckg, statusUpdate);
String eventId = testHelper.scheduleEvent1Year(pckg, channel.getId(), null, statusUpdate);
assertNotNull(eventId);
NodeRef eventNode = new NodeRef(eventId);
@@ -368,36 +358,14 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
return eventNode;
}
private void scheduleEvent(PublishingPackage publishPckg, StatusUpdate statusUpdate)
{
Calendar schedule = Calendar.getInstance();
schedule.add(Calendar.YEAR, 1);
this.eventId = queue.scheduleNewEvent(publishPckg, channel.getId(), schedule, null, statusUpdate);
}
private void addGeographicAspect(NodeRef source, double lattitude, double longtitude)
{
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
props.put(PROP_LATITUDE, lattitude);
props.put(PROP_LONGITUDE, longtitude);
nodeService.addAspect(source, ASPECT_GEOGRAPHIC, props);
serviceRegistry.getNodeService().addAspect(source, ASPECT_GEOGRAPHIC, props);
}
private NodeRef createContentNode(String name, String theContent)
{
NodeRef source = fileFolderService.create(docLib, name, TYPE_CONTENT).getNodeRef();
writeContent(source, theContent);
return source;
}
private void writeContent(NodeRef source, String theContent)
{
ContentWriter writer = contentService.getWriter(source, PROP_CONTENT, true);
writer.setEncoding("UTF-8");
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.putContent(theContent);
}
private String readContent(NodeRef source)
{
ContentReader reader = contentService.getReader(source, PROP_CONTENT);
@@ -409,33 +377,13 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
{
super.onSetUp();
this.publishingService = (PublishingService) getApplicationContext().getBean("publishingService");
channelService = (ChannelServiceImpl) getApplicationContext().getBean("channelService");
contentService = (ContentService) getApplicationContext().getBean("ContentService");
channelHelper = (ChannelHelper) getApplicationContext().getBean("channelHelper");
action = (PublishEventAction) getApplicationContext().getBean("pub_publishEvent");
this.channelType = channelService.getChannelType(channelTypeId);
if(channelType == null)
{
this.channelType = mockChannelType();
channelService.register(channelType);
}
else
{
Mockito.reset(channelType);
mockChannelTypeBehaviour(channelType);
}
this.channel = channelService.createChannel(channelTypeId, GUID.generate(), null);
this.channelNode = channel.getNodeRef();
this.contentService = (ContentService) getApplicationContext().getBean("ContentService");
this.channelHelper = (ChannelHelper) getApplicationContext().getBean("channelHelper");
this.action = (PublishEventAction) getApplicationContext().getBean("pub_publishEvent");
this.channelType = testHelper.mockChannelType(channelTypeId);
this.channel = testHelper.createChannel(channelTypeId);
this.channelNode = new NodeRef(channel.getId());
}
@Override
public void onTearDown() throws Exception
{
if(eventId !=null)
{
publishingService.cancelPublishingEvent(eventId);
}
super.onTearDown();
}
}

View File

@@ -50,6 +50,8 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.GUID;
import org.alfresco.util.ParameterCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author Nick Smith
@@ -58,6 +60,8 @@ import org.alfresco.util.ParameterCheck;
*/
public class PublishingEventProcessor
{
private static final Log log = LogFactory.getLog(PublishingEventProcessor.class);
private PublishingEventHelper eventHelper;
private ChannelHelper channelHelper;
private ChannelService channelService;
@@ -91,6 +95,7 @@ public class PublishingEventProcessor
}
catch(Exception e)
{
log.error("Caught exception while processing publishing event " + eventNode, e);
fail(eventNode, e.getMessage());
}
finally
@@ -112,7 +117,7 @@ public class PublishingEventProcessor
String nodeUrl = publishChannel.getUrl(node);
if(nodeUrl != null)
{
message += urlShortener.shortenUrl(nodeUrl);
message += " " + urlShortener.shortenUrl(nodeUrl);
}
}
Set<String> channels = update.getChannelIds();
@@ -148,9 +153,9 @@ public class PublishingEventProcessor
}
public void fail(NodeRef eventNode, String msg)
{
log.error("Failed to process publishing event " + eventNode + ": " + msg);
String completedStatus = Status.FAILED.name();
nodeService.setProperty(eventNode, PublishingModel.PROP_PUBLISHING_EVENT_STATUS, completedStatus);
}

View File

@@ -33,11 +33,7 @@ import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.security.person.TestPersonManager;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.publishing.MutablePublishingPackage;
import org.alfresco.service.cmr.publishing.PublishingEvent;
import org.alfresco.service.cmr.publishing.PublishingPackage;
@@ -48,9 +44,7 @@ import org.alfresco.service.cmr.publishing.StatusUpdate;
import org.alfresco.service.cmr.publishing.channels.Channel;
import org.alfresco.service.cmr.publishing.channels.ChannelType;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowService;
@@ -70,11 +64,6 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
private PublishingService publishingService;
private WorkflowService workflowService;
private PermissionService permissionService;
private TestPersonManager personManager;
private ChannelServiceImpl channelService;
private String eventId;
@Test
public void testScheduleNewPublishingEvent() throws Exception
@@ -84,7 +73,7 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
assertNull(nodeService.getProperty(firstNode, PROP_VERSION_LABEL));
assertNull(nodeService.getProperty(firstNode, PROP_VERSION_LABEL));
MutablePublishingPackage publishingPackage = queue.createPublishingPackage();
MutablePublishingPackage publishingPackage = publishingService.getPublishingQueue().createPublishingPackage();
publishingPackage.addNodesToPublish(firstNode, secondNode);
//TODO Implement Unpublish
@@ -94,7 +83,7 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
Calendar schedule = Calendar.getInstance();
schedule.add(Calendar.HOUR, 2);
this.eventId = queue.scheduleNewEvent(publishingPackage, channelId, schedule, comment, null);
String eventId = publishingService.getPublishingQueue().scheduleNewEvent(publishingPackage, channelId, schedule, comment, null);
//Check schedule triggered versioning.
Serializable version = nodeService.getProperty(firstNode, PROP_VERSION_LABEL);
@@ -156,14 +145,14 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
List<String> channelNames = Arrays.asList("test://channel/Channel1", "test://channel/Channel2", "test://channel/Channel3" );
String message = "The message";
StatusUpdate update = queue.createStatusUpdate(message, secondNode, channelNames);
StatusUpdate update = publishingService.getPublishingQueue().createStatusUpdate(message, secondNode, channelNames);
// Publish an event with the StatusUpdate
MutablePublishingPackage publishingPackage = queue.createPublishingPackage();
MutablePublishingPackage publishingPackage = publishingService.getPublishingQueue().createPublishingPackage();
publishingPackage.addNodesToPublish(firstNode, secondNode);
Calendar schedule = Calendar.getInstance();
schedule.add(Calendar.HOUR, 2);
this.eventId = queue.scheduleNewEvent(publishingPackage, channelId, schedule, comment, update);
String eventId = testHelper.scheduleEvent1Year(publishingPackage, channelId, comment, update);
PublishingEvent event = publishingService.getPublishingEvent(eventId);
StatusUpdate actualUpdate = event.getStatusUpdate();
@@ -178,12 +167,9 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
public void testScheduleNewEventPermissions() throws Exception
{
// Create Channels as Admin
ChannelType channelType = mockChannelType();
channelService.register(channelType);
Channel publishChannel = channelService.createChannel(channelType.getId(), "Channel1", null);
NodeRef publishChannelNode = new NodeRef(publishChannel.getId());
Channel statusChannel = channelService.createChannel(channelType.getId(), "Channel2", null);
NodeRef statusChannelNode = new NodeRef(statusChannel.getId());
ChannelType channelType = testHelper.mockChannelType(channelTypeId);
Channel publishChannel = testHelper.createChannel(channelTypeId);
Channel statusChannel = testHelper.createChannel(channelTypeId);
NodeRef firstNode = createContent("First");
NodeRef secondNode = createContent("Second");
@@ -191,18 +177,16 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
// Create User1, add read permissions and set as current user.
String user1 = GUID.generate();
personManager.createPerson(user1);
permissionService.setPermission(publishChannelNode, user1, PermissionService.READ, true);
permissionService.setPermission(statusChannelNode, user1, PermissionService.READ, true);
testHelper.setChannelPermission(user1, publishChannel.getId(), PermissionService.READ);
testHelper.setChannelPermission(user1, statusChannel.getId(), PermissionService.READ);
personManager.setUser(user1);
// Publish an event
MutablePublishingPackage publishingPackage = queue.createPublishingPackage();
MutablePublishingPackage publishingPackage = publishingService.getPublishingQueue().createPublishingPackage();
publishingPackage.addNodesToPublish(firstNode, secondNode);
Calendar schedule = Calendar.getInstance();
schedule.add(Calendar.HOUR, 2);
try
{
this.eventId = queue.scheduleNewEvent(publishingPackage, publishChannel.getId(), schedule, comment, null);
testHelper.scheduleEvent1Year(publishingPackage, publishChannel.getId(), null, null);
fail("shceduleNewEvent should have thrown an AccessDeniedException!");
}
catch(AlfrescoRuntimeException e)
@@ -211,20 +195,17 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
}
// Set Add Child permission on publish channel.
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
permissionService.setPermission(publishChannelNode, user1, PermissionService.ADD_CHILDREN, true);
personManager.setUser(user1);
testHelper.allowChannelAccess(user1, publishChannel.getId());
// Check publish works now.
this.eventId = queue.scheduleNewEvent(publishingPackage, publishChannel.getId(), schedule, comment, null);
String eventId = testHelper.scheduleEvent1Year(publishingPackage, publishChannel.getId(), null, null);
assertNotNull(eventId);
publishingService.cancelPublishingEvent(eventId);
String message = "The message";
StatusUpdate update = queue.createStatusUpdate(message, secondNode, statusChannel.getId());
StatusUpdate update = publishingService.getPublishingQueue().createStatusUpdate(message, secondNode, statusChannel.getId());
try
{
this.eventId = queue.scheduleNewEvent(publishingPackage, publishChannel.getId(), schedule, comment, update);
eventId = testHelper.scheduleEvent1Year(publishingPackage, publishChannel.getId(), null, update);
fail("shceduleNewEvent with status update should have thrown an AccessDeniedException!");
}
catch(AlfrescoRuntimeException e)
@@ -233,18 +214,16 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
}
// Set Add Child permission on status channel.
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
permissionService.setPermission(statusChannelNode, user1, PermissionService.ADD_CHILDREN, true);
personManager.setUser(user1);
testHelper.allowChannelAccess(user1, statusChannel.getId());
// Check publish works now.
this.eventId = queue.scheduleNewEvent(publishingPackage, publishChannel.getId(), schedule, comment, null);
eventId = testHelper.scheduleEvent1Year(publishingPackage, publishChannel.getId(), null, update);
assertNotNull(eventId);
}
private NodeRef createContent(String name)
{
return fileFolderService.create(docLib, name, ContentModel.TYPE_CONTENT).getNodeRef();
return testHelper.createContentNode(name);
}
/**
@@ -256,34 +235,6 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
super.onSetUp();
this.workflowService = serviceRegistry.getWorkflowService();
this.publishingService = (PublishingService) getApplicationContext().getBean("publishingService");
this.channelService = (ChannelServiceImpl) getApplicationContext().getBean("channelService");
this.permissionService = (PermissionService) getApplicationContext().getBean(ServiceRegistry.PERMISSIONS_SERVICE.getLocalName());
MutableAuthenticationService authenticationService= (MutableAuthenticationService) getApplicationContext().getBean(ServiceRegistry.AUTHENTICATION_SERVICE.getLocalName());
PersonService personService= (PersonService) getApplicationContext().getBean(ServiceRegistry.PERSON_SERVICE.getLocalName());
this.personManager = new TestPersonManager(authenticationService, personService, nodeService);
}
/**
* {@inheritDoc}
* @throws Exception
*/
@Override
public void onTearDown() throws Exception
{
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
if(eventId!=null)
{
try
{
publishingService.cancelPublishingEvent(eventId);
}
catch(Exception e)
{
//NOOP
}
}
super.onTearDown();
}
}

View File

@@ -28,7 +28,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.junit.Test;
/**
* @author Brian
* @author Nick Smith
*
*/
public class PublishingRootObjectTest extends AbstractPublishingIntegrationTest
@@ -36,13 +36,6 @@ public class PublishingRootObjectTest extends AbstractPublishingIntegrationTest
@Resource(name="publishingRootObject")
private PublishingRootObject rootObject;
@Override
public void onSetUp() throws Exception
{
super.onSetUp();
this.rootObject = (PublishingRootObject) getApplicationContext().getBean(PublishingRootObject.NAME);
}
@Test
public void testGetEnvironment() throws Exception
{
@@ -77,4 +70,11 @@ public class PublishingRootObjectTest extends AbstractPublishingIntegrationTest
assertEquals(rootObject.getEnvironment().getNodeRef(), parentAssoc.getParentRef());
}
@Override
public void onSetUp() throws Exception
{
super.onSetUp();
this.rootObject = (PublishingRootObject) getApplicationContext().getBean(PublishingRootObject.NAME);
}
}

View File

@@ -0,0 +1,276 @@
/*
* 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;
import static org.alfresco.model.ContentModel.TYPE_CONTENT;
import static org.alfresco.repo.publishing.PublishingModel.TYPE_DELIVERY_CHANNEL;
import static org.alfresco.repo.publishing.PublishingModel.PROP_AUTHORISATION_COMPLETE;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.publishing.PublishingPackage;
import org.alfresco.service.cmr.publishing.PublishingQueue;
import org.alfresco.service.cmr.publishing.PublishingService;
import org.alfresco.service.cmr.publishing.StatusUpdate;
import org.alfresco.service.cmr.publishing.channels.Channel;
import org.alfresco.service.cmr.publishing.channels.ChannelService;
import org.alfresco.service.cmr.publishing.channels.ChannelType;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.cmr.site.SiteVisibility;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.GUID;
import org.alfresco.util.collections.CollectionUtils;
/**
* @author Nick Smith
* @since 4.0
*
*/
public class PublishingTestHelper
{
private final ChannelService channelService;
private final PublishingService publishingService;
private final SiteService siteService;
private final FileFolderService fileFolderService;
private final PermissionService permissionService;
private final NodeRef docLib;
private final String siteId = GUID.generate();
private final List<Channel> channels = new LinkedList<Channel>();
private final List<String> events = new LinkedList<String>();
public PublishingTestHelper(ChannelService channelService,
PublishingService publishingService,
SiteService siteService,
FileFolderService fileFolderService,
PermissionService permissionService)
{
this.channelService = channelService;
this.publishingService = publishingService;
this.siteService = siteService;
this.fileFolderService = fileFolderService;
this.permissionService = permissionService;
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
siteService.createSite("test", siteId,
"Test site created by ChannelServiceImplIntegratedTest",
"Test site created by ChannelServiceImplIntegratedTest",
SiteVisibility.PUBLIC);
this.docLib = siteService.createContainer(siteId, SiteService.DOCUMENT_LIBRARY, ContentModel.TYPE_FOLDER, null);
}
public void tearDown() throws Exception
{
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
try
{
cancelAllEvents();
}
finally
{
try
{
deleteAllChannels();
}
finally
{
deleteSite();
}
}
}
private void deleteSite()
{
try
{
siteService.deleteSite(siteId);
}
catch(Throwable t)
{
//NOOP
}
}
private void deleteAllChannels()
{
for (Channel channel : channels)
{
try
{
channelService.deleteChannel(channel);
}
catch(Throwable t)
{
//NOOP
}
}
}
private void cancelAllEvents()
{
for (String event : events)
{
try
{
publishingService.cancelPublishingEvent(event);
}
catch(Throwable t)
{
//NOOP
}
}
}
public ChannelType mockChannelType(String channelTypeId)
{
ChannelType channelType = channelService.getChannelType(channelTypeId);
if(channelType != null)
{
reset(channelType);
when(channelType.getId()).thenReturn(channelTypeId);
}
else
{
channelType = mock(ChannelType.class);
when(channelType.getId()).thenReturn(channelTypeId);
channelService.register(channelType);
}
when(channelType.getChannelNodeType()).thenReturn(TYPE_DELIVERY_CHANNEL);
return channelType;
}
public Channel createChannel(String typeId)
{
String channelName = GUID.generate();
return createChannel(typeId, channelName);
}
public Channel createChannel(String typeId, String channelName)
{
return createChannel(typeId, channelName, true);
}
public Channel createChannel(String typeId, String channelName, boolean isAuthorised)
{
Channel channel = channelService.createChannel(typeId, channelName, null);
channels.add(channel);
Map<QName, Serializable> properties = Collections.singletonMap(PROP_AUTHORISATION_COMPLETE, (Serializable)isAuthorised);
channelService.updateChannel(channel, properties);
return channel;
}
public void allowChannelAccess(String username, String channelId)
{
setChannelPermission(username, channelId, PermissionService.ADD_CHILDREN);
}
public void setChannelPermission(final String username, String channelId, final String permission)
{
final NodeRef channel = new NodeRef(channelId);
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
permissionService.setPermission(channel, username, permission, true);
return null;
}
}, AuthenticationUtil.getSystemUserName());
}
public String scheduleEvent1Year(PublishingPackage pckg, String channelId, String comment, StatusUpdate statusUpdate)
{
Calendar schedule = Calendar.getInstance();
schedule.add(Calendar.YEAR, 1);
return scheduleEvent(pckg, channelId, schedule, comment, statusUpdate);
}
public String scheduleEvent(PublishingPackage pckg, String channelId, Calendar schedule, String comment, StatusUpdate statusUpdate)
{
PublishingQueue queue = publishingService.getPublishingQueue();
String eventId = queue.scheduleNewEvent(pckg, channelId, schedule, comment, statusUpdate);
events.add(eventId);
return eventId;
}
public void addEvent(String eventId)
{
events.add(eventId);
}
public void addEvents(Collection<String> eventIds)
{
events.addAll(eventIds);
}
public NodeRef createContentNode(String name)
{
return fileFolderService.create(docLib, name, TYPE_CONTENT).getNodeRef();
}
public NodeRef createContentNode(String name, File theContent, String mimetype)
{
NodeRef source = createContentNode(name);
writeContent(source, theContent, mimetype);
return source;
}
public NodeRef createContentNode(String name, String theContent, String mimetype)
{
NodeRef source = fileFolderService.create(docLib, name, TYPE_CONTENT).getNodeRef();
writeContent(source, theContent, mimetype);
return source;
}
public void writeContent(NodeRef source, String theContent, String mimetype)
{
ContentWriter writer = fileFolderService.getWriter(source);
writer.setEncoding("UTF-8");
writer.putContent(theContent);
writer.setMimetype(mimetype);
}
public void writeContent(NodeRef source, File theContent, String mimetype)
{
ContentWriter writer = fileFolderService.getWriter(source);
writer.setMimetype(mimetype);
writer.setEncoding("UTF-8");
writer.putContent(theContent);
}
}

View File

@@ -40,7 +40,7 @@ import org.springframework.social.oauth2.OAuth2Parameters;
public class FacebookChannelType extends AbstractChannelType
{
public final static String ID = "facebook";
public final static String DEFAULT_REDIRECT_URI = "http://cognite.net";
public final static String DEFAULT_REDIRECT_URI = "http://cognite.net/alfresco/stand-alone-auth-return.html";
private FacebookPublishingHelper publishingHelper;
private String redirectUri = DEFAULT_REDIRECT_URI;

View File

@@ -105,10 +105,6 @@ public class FlickrChannelType extends AbstractOAuth1ChannelType<Flickr>
@Override
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);
actionService.executeAction(publishAction, nodeToPublish);
}
@@ -116,7 +112,8 @@ public class FlickrChannelType extends AbstractOAuth1ChannelType<Flickr>
@Override
public void unpublish(NodeRef nodeToUnpublish, Map<QName, Serializable> properties)
{
//NOOP
Action action = actionService.createAction(FlickrUnpublishAction.NAME);
actionService.executeAction(action, nodeToUnpublish);
}
@Override

View File

@@ -73,7 +73,6 @@ public class FlickrUnpublishAction extends ActionExecuterAbstractBase
@Override
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
{
// TODO Auto-generated method stub
//Deliberately empty
}
}

View File

@@ -26,22 +26,22 @@ import java.util.Map;
import java.util.Set;
import org.alfresco.repo.publishing.AbstractOAuth1ChannelType;
import org.alfresco.repo.publishing.linkedin.springsocial.api.AlfrescoLinkedIn;
import org.alfresco.service.cmr.publishing.channels.Channel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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 class LinkedInChannelType extends AbstractOAuth1ChannelType<AlfrescoLinkedIn>
{
public final static String ID = "linkedIn";
private final static Log log = LogFactory.getLog(LinkedInChannelType.class);
public final static String ID = "linkedin";
@Override
public boolean canPublish()
@@ -97,12 +97,22 @@ public class LinkedInChannelType extends AbstractOAuth1ChannelType<LinkedIn>
//NO-OP
}
@Override
public int getMaximumStatusLength()
{
return 700;
}
@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
Connection<AlfrescoLinkedIn> connection = getConnectionForChannel(channelNode);
if (log.isInfoEnabled())
{
log.info("Posting update to LinkedIn channel " + channel.getName() + ": " + status);
}
connection.getApi().shareComment(status);
}
@Override
@@ -110,13 +120,4 @@ public class LinkedInChannelType extends AbstractOAuth1ChannelType<LinkedIn>
{
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

@@ -33,6 +33,4 @@ public interface LinkedInPublishingModel
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

@@ -0,0 +1,16 @@
package org.alfresco.repo.publishing.linkedin.springsocial.api;
public interface Activity
{
public String getContentType();
public void setContentType(String value);
public String getBody();
public void setBody(String value);
public String getLocale();
public void setLocale(String value);
}

View File

@@ -0,0 +1,28 @@
/*
* 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.springsocial.api;
import org.springframework.social.linkedin.api.LinkedIn;
public interface AlfrescoLinkedIn extends LinkedIn
{
void postNetworkUpdate(String update);
void shareComment(String comment);
}

View File

@@ -0,0 +1,13 @@
package org.alfresco.repo.publishing.linkedin.springsocial.api;
public interface Share
{
public String getComment();
public void setComment(String comment);
public ShareVisibility getVisibility();
public void setVisibility(ShareVisibility visibility);
}

View File

@@ -0,0 +1,7 @@
package org.alfresco.repo.publishing.linkedin.springsocial.api;
public interface ShareVisibility
{
ShareVisibilityCode getCode();
void setCode(ShareVisibilityCode code);
}

View File

@@ -0,0 +1,40 @@
package org.alfresco.repo.publishing.linkedin.springsocial.api;
import javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlEnumValue;
@XmlEnum
public enum ShareVisibilityCode
{
@XmlEnumValue("anyone")
ANYONE("anyone"),
@XmlEnumValue("connections-only")
CONNECTIONS_ONLY("connections-only");
private final String value;
ShareVisibilityCode(String value)
{
this.value = value;
}
public String value()
{
return value;
}
public static ShareVisibilityCode fromValue(String value)
{
for (ShareVisibilityCode validCode : ShareVisibilityCode.values())
{
if (validCode.value.equals(value))
{
return validCode;
}
}
throw new IllegalArgumentException(value);
}
}

View File

@@ -0,0 +1,91 @@
/*
* 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.springsocial.api.impl;
import java.util.List;
import org.alfresco.repo.publishing.JaxbHttpMessageConverter;
import org.alfresco.repo.publishing.linkedin.springsocial.api.Activity;
import org.alfresco.repo.publishing.linkedin.springsocial.api.AlfrescoLinkedIn;
import org.alfresco.repo.publishing.linkedin.springsocial.api.Share;
import org.alfresco.repo.publishing.linkedin.springsocial.api.impl.xml.JaxbActivityImpl;
import org.alfresco.repo.publishing.linkedin.springsocial.api.impl.xml.JaxbShareImpl;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.social.linkedin.api.impl.LinkedInTemplate;
import org.springframework.social.support.URIBuilder;
public class AlfrescoLinkedInTemplate extends LinkedInTemplate implements AlfrescoLinkedIn
{
private static String JAXB_CONTEXT_PATH = "org.alfresco.repo.publishing.linkedin.springsocial.api.impl.xml:"
+ "org.alfresco.repo.publishing.linkedin.springsocial.api";
public AlfrescoLinkedInTemplate(String consumerKey, String consumerSecret, String accessToken,
String accessTokenSecret)
{
super(consumerKey, consumerSecret, accessToken, accessTokenSecret);
}
protected List<HttpMessageConverter<?>> getMessageConverters()
{
List<HttpMessageConverter<?>> messageConverters = super.getMessageConverters();
messageConverters.add(new JaxbHttpMessageConverter(JAXB_CONTEXT_PATH));
return messageConverters;
}
@Override
public void postNetworkUpdate(String update)
{
if (update == null || update.trim().length() == 0)
return;
URIBuilder uriBuilder = URIBuilder.fromUri("http://api.linkedin.com/v1/people/~/person-activities");
Activity activity = new JaxbActivityImpl();
activity.setBody(update);
HttpEntity<?> entity = buildEntity(activity);
getRestTemplate().postForObject(uriBuilder.build(), entity, String.class);
}
@Override
public void shareComment(String comment)
{
if (comment == null || comment.trim().length() == 0)
return;
URIBuilder uriBuilder = URIBuilder.fromUri("http://api.linkedin.com/v1/people/~/shares");
Share share = new JaxbShareImpl();
share.setComment(comment);
HttpEntity<?> entity = buildEntity(share);
getRestTemplate().postForLocation(uriBuilder.build(), entity);
}
private HttpEntity<?> buildEntity(Object body)
{
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_XML);
return new HttpEntity<Object>(body, headers);
}
}

View File

@@ -0,0 +1,55 @@
package org.alfresco.repo.publishing.linkedin.springsocial.api.impl.xml;
import java.util.Locale;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.alfresco.repo.publishing.linkedin.springsocial.api.Activity;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"contentType", "body"})
@XmlRootElement(name = "activity")
public class JaxbActivityImpl implements Activity
{
@XmlElement(name = "content-type")
protected String contentType = "linkedin-html";
@XmlElement(required = true)
protected String body;
@XmlAttribute(required = true)
protected String locale = Locale.getDefault().toString();
public String getContentType()
{
return contentType;
}
public void setContentType(String value)
{
this.contentType = value;
}
public String getBody()
{
return body;
}
public void setBody(String value)
{
this.body = value;
}
public String getLocale()
{
return locale;
}
public void setLocale(String value)
{
this.locale = value;
}
}

View File

@@ -0,0 +1,44 @@
package org.alfresco.repo.publishing.linkedin.springsocial.api.impl.xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.alfresco.repo.publishing.linkedin.springsocial.api.Share;
import org.alfresco.repo.publishing.linkedin.springsocial.api.ShareVisibility;
import org.alfresco.repo.publishing.linkedin.springsocial.api.ShareVisibilityCode;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "comment", "visibility" })
@XmlRootElement(name = "share")
public class JaxbShareImpl implements Share
{
@XmlElement(required = true, name = "comment")
protected String comment;
@XmlElement(required = true, name = "visibility")
protected JaxbShareVisibilityImpl visibility = new JaxbShareVisibilityImpl(ShareVisibilityCode.ANYONE);
public String getComment()
{
return comment;
}
public void setComment(String comment)
{
this.comment = comment;
}
public ShareVisibility getVisibility()
{
return visibility;
}
public void setVisibility(ShareVisibility visibility)
{
this.visibility = new JaxbShareVisibilityImpl(visibility.getCode());
}
}

View File

@@ -0,0 +1,41 @@
package org.alfresco.repo.publishing.linkedin.springsocial.api.impl.xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.alfresco.repo.publishing.linkedin.springsocial.api.ShareVisibility;
import org.alfresco.repo.publishing.linkedin.springsocial.api.ShareVisibilityCode;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "code" })
@XmlRootElement(name = "visibility")
public class JaxbShareVisibilityImpl implements ShareVisibility
{
@XmlElement(required = true)
protected ShareVisibilityCode code;
public JaxbShareVisibilityImpl()
{
super();
}
public JaxbShareVisibilityImpl(ShareVisibilityCode code)
{
super();
this.code = code;
}
public ShareVisibilityCode getCode()
{
return code;
}
public void setCode(ShareVisibilityCode value)
{
this.code = value;
}
}

View File

@@ -0,0 +1,3 @@
JaxbShareImpl
JaxbShareVisibilityImpl
JaxbActivityImpl

View File

@@ -0,0 +1 @@
ShareVisibilityCode

View File

@@ -0,0 +1,58 @@
/*
* 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.springsocial.connect;
import org.alfresco.repo.publishing.linkedin.springsocial.api.AlfrescoLinkedIn;
import org.springframework.social.connect.ApiAdapter;
import org.springframework.social.connect.ConnectionValues;
import org.springframework.social.connect.UserProfile;
import org.springframework.social.connect.UserProfileBuilder;
import org.springframework.social.linkedin.api.LinkedInProfile;
import org.springframework.web.client.HttpClientErrorException;
public class LinkedInAdapter implements ApiAdapter<AlfrescoLinkedIn>
{
public boolean test(AlfrescoLinkedIn linkedin) {
try {
linkedin.getUserProfile();
return true;
} catch (HttpClientErrorException e) {
// TODO: Have api throw more specific exception and trigger off of that.
return false;
}
}
public void setConnectionValues(AlfrescoLinkedIn linkedin, ConnectionValues values) {
LinkedInProfile profile = linkedin.getUserProfile();
values.setProviderUserId(profile.getId());
values.setDisplayName(profile.getFirstName() + " " + profile.getLastName());
values.setProfileUrl(profile.getPublicProfileUrl());
values.setImageUrl(profile.getProfilePictureUrl());
}
public UserProfile fetchUserProfile(AlfrescoLinkedIn linkedin) {
LinkedInProfile profile = linkedin.getUserProfile();
return new UserProfileBuilder().setName(profile.getFirstName() + " " + profile.getLastName()).build();
}
public void updateStatus(AlfrescoLinkedIn linkedin, String message) {
// not supported yet
}
}

View File

@@ -0,0 +1,30 @@
/*
* 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.springsocial.connect;
import org.alfresco.repo.publishing.linkedin.springsocial.api.AlfrescoLinkedIn;
import org.springframework.social.connect.support.OAuth1ConnectionFactory;
public class LinkedInConnectionFactory extends OAuth1ConnectionFactory<AlfrescoLinkedIn>{
public LinkedInConnectionFactory(String consumerKey, String consumerSecret) {
super("linkedin", new LinkedInServiceProvider(consumerKey, consumerSecret), new LinkedInAdapter());
}
}

View File

@@ -0,0 +1,41 @@
/*
* 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.springsocial.connect;
import org.alfresco.repo.publishing.linkedin.springsocial.api.AlfrescoLinkedIn;
import org.alfresco.repo.publishing.linkedin.springsocial.api.impl.AlfrescoLinkedInTemplate;
import org.springframework.social.oauth1.AbstractOAuth1ServiceProvider;
import org.springframework.social.oauth1.OAuth1Template;
public class LinkedInServiceProvider extends AbstractOAuth1ServiceProvider<AlfrescoLinkedIn> {
public LinkedInServiceProvider(String consumerKey, String consumerSecret) {
super(consumerKey, consumerSecret, new OAuth1Template(consumerKey, consumerSecret,
"https://api.linkedin.com/uas/oauth/requestToken",
"https://www.linkedin.com/uas/oauth/authorize",
"https://www.linkedin.com/uas/oauth/authenticate",
"https://api.linkedin.com/uas/oauth/accessToken"));
}
public AlfrescoLinkedIn getApi(String accessToken, String secret) {
return new AlfrescoLinkedInTemplate(getConsumerKey(), getConsumerSecret(), accessToken, secret);
}
}

View File

@@ -27,11 +27,14 @@ 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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.social.connect.Connection;
import org.springframework.social.twitter.api.Twitter;
public class TwitterChannelType extends AbstractOAuth1ChannelType<Twitter>
{
private final static Log log = LogFactory.getLog(TwitterChannelType.class);
public final static String ID = "twitter";
@Override
@@ -88,10 +91,20 @@ public class TwitterChannelType extends AbstractOAuth1ChannelType<Twitter>
//NO-OP
}
@Override
public int getMaximumStatusLength()
{
return 140;
}
@Override
public void updateStatus(Channel channel, String status, Map<QName, Serializable> properties)
{
Connection<Twitter> connection = getConnectionForChannel(channel.getNodeRef());
if (log.isInfoEnabled())
{
log.info("Posting update to Twitter channel " + channel.getName() + ": " + status);
}
connection.getApi().timelineOperations().updateStatus(status);
}

View File

@@ -22,7 +22,9 @@ 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.repo.publishing.PublishingModel;
import org.alfresco.service.cmr.action.Action;
@@ -31,9 +33,22 @@ 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.collections.CollectionUtils;
public class YouTubeChannelType extends AbstractChannelType
{
private final static Set<String> DEFAULT_SUPPORTED_MIME_TYPES = CollectionUtils.unmodifiableSet(
MimetypeMap.MIMETYPE_VIDEO_MPG,
MimetypeMap.MIMETYPE_VIDEO_MP4,
MimetypeMap.MIMETYPE_VIDEO_FLV,
MimetypeMap.MIMETYPE_VIDEO_3GP,
MimetypeMap.MIMETYPE_VIDEO_AVI,
MimetypeMap.MIMETYPE_VIDEO_QUICKTIME,
MimetypeMap.MIMETYPE_VIDEO_WMV
);
private Set<String> supportedMimeTypes = DEFAULT_SUPPORTED_MIME_TYPES;
public final static String ID = "youtube";
private NodeService nodeService;
private ActionService actionService;
@@ -48,6 +63,11 @@ public class YouTubeChannelType extends AbstractChannelType
this.actionService = actionService;
}
public void setSupportedMimeTypes(Set<String> supportedMimeTypes)
{
this.supportedMimeTypes = Collections.unmodifiableSet(new TreeSet<String>(supportedMimeTypes));
}
@Override
public boolean canPublish()
{
@@ -87,7 +107,7 @@ public class YouTubeChannelType extends AbstractChannelType
@Override
public Set<String> getSupportedMimeTypes()
{
return Collections.emptySet();
return supportedMimeTypes;
}
@Override

View File

@@ -76,4 +76,26 @@ public interface Channel
* @return true if this channel has been authorised and is ready for use.
*/
boolean isAuthorised();
/**
* Returns <code>true</code> only if the currently authenticated user can publish content to this {@link Channel}.
* If the {@link ChannelType} does not support publishing, if the {@link Channel} is not authorised or if the currently authenticated user does not have permission to publish to this {@link Channel} then this method will return <code>false</code>.
* @return
*/
boolean canPublish();
/**
* Returns <code>true</code> only if the currently authenticated user can unpublish content from this {@link Channel}.
* If the {@link ChannelType} does not support unpublishing, if the {@link Channel} is not authorised or if the currently authenticated user does not have permission to publish to this {@link Channel} then this method will return <code>false</code>.
* @return
*/
boolean canUnpublish();
/**
* Returns <code>true</code> only if the currently authenticated user can unpublish status updates to this {@link Channel}.
* If the {@link ChannelType} does not support publishing of status updates, if the {@link Channel} is not authorised or if the currently authenticated user does not have permission to publish to this {@link Channel} then this method will return <code>false</code>.
* @return
*/
boolean canPublishStatusUpdates();
}

View File

@@ -113,14 +113,16 @@ public interface ChannelService
/**
* Returns a list of all the channels that are capable of publishing in the specified Share site.
* @param filterByPublishPermission TODO
* @return
*/
List<Channel> getPublishingChannels();
List<Channel> getPublishingChannels(boolean filterByPublishPermission);
/**
* Returns all {@link Channel}s cpaable of performing a status update for the given Share Site.
* @param filterByPublishPermission TODO
* @return
*/
List<Channel> getStatusUpdateChannels();
List<Channel> getStatusUpdateChannels(boolean filterByPublishPermission);
}