diff --git a/config/alfresco/action-services-context.xml b/config/alfresco/action-services-context.xml
index 56d8746fd6..21d0f5eede 100644
--- a/config/alfresco/action-services-context.xml
+++ b/config/alfresco/action-services-context.xml
@@ -13,10 +13,10 @@
defaultAsyncAction
- 2
+ 8
- 10
+ 20
diff --git a/config/alfresco/content-publishing-context.xml b/config/alfresco/content-publishing-context.xml
index 42899cad52..0943c2ac94 100644
--- a/config/alfresco/content-publishing-context.xml
+++ b/config/alfresco/content-publishing-context.xml
@@ -56,6 +56,7 @@
+
@@ -63,6 +64,8 @@
+
+
@@ -95,13 +98,12 @@
-
-
+
diff --git a/config/alfresco/flickr-publishing-context.xml b/config/alfresco/flickr-publishing-context.xml
index a99c9e1d00..0b662f4895 100644
--- a/config/alfresco/flickr-publishing-context.xml
+++ b/config/alfresco/flickr-publishing-context.xml
@@ -11,9 +11,10 @@
-
-
+
+
+
@@ -26,18 +27,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/config/alfresco/slideshare-publishing-context.xml b/config/alfresco/slideshare-publishing-context.xml
index d4f79d04d0..b3f5aeeef1 100644
--- a/config/alfresco/slideshare-publishing-context.xml
+++ b/config/alfresco/slideshare-publishing-context.xml
@@ -11,34 +11,19 @@
-
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/config/alfresco/youtube-publishing-context.xml b/config/alfresco/youtube-publishing-context.xml
index 8f049155fe..fbfbf5093b 100644
--- a/config/alfresco/youtube-publishing-context.xml
+++ b/config/alfresco/youtube-publishing-context.xml
@@ -11,28 +11,12 @@
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/config/test/alfresco/test-web-publishing-context.xml b/config/test/alfresco/test-web-publishing-context.xml
index cf1ba175aa..22cc9de35c 100644
--- a/config/test/alfresco/test-web-publishing-context.xml
+++ b/config/test/alfresco/test-web-publishing-context.xml
@@ -100,6 +100,10 @@
+
+
+
+
diff --git a/source/java/org/alfresco/repo/publishing/AbstractChannelType.java b/source/java/org/alfresco/repo/publishing/AbstractChannelType.java
index 175f3c8180..f3cdef5978 100644
--- a/source/java/org/alfresco/repo/publishing/AbstractChannelType.java
+++ b/source/java/org/alfresco/repo/publishing/AbstractChannelType.java
@@ -20,13 +20,17 @@
package org.alfresco.repo.publishing;
import java.io.Serializable;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import org.alfresco.repo.node.encryption.MetadataEncryptor;
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.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck;
import org.springframework.core.io.ClassPathResource;
@@ -36,8 +40,9 @@ import org.springframework.core.io.Resource;
* @author Nick Smith
* @since 4.0
*/
-public abstract class AbstractChannelType implements ChannelType
+public abstract class AbstractChannelType implements ChannelType, ChannelTypePublishingOperations
{
+ private NodeService nodeService;
private ChannelService channelService;
private MetadataEncryptor encryptor;
@@ -62,6 +67,16 @@ public abstract class AbstractChannelType implements ChannelType
return encryptor;
}
+ protected NodeService getNodeService()
+ {
+ return nodeService;
+ }
+
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
/**
* {@inheritDoc}
*/
@@ -132,4 +147,46 @@ public abstract class AbstractChannelType implements ChannelType
{
return "png";
}
+
+ @Override
+ public Set getSupportedContentTypes()
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set getSupportedMimeTypes()
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void sendStatusUpdate(Channel channel, String status)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void publish(NodeRef nodeToPublish, Map channelProperties)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void unpublish(NodeRef nodeToUnpublish, Map channelProperties)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getNodeUrl(NodeRef node)
+ {
+ String url = null;
+ if (node != null && nodeService.exists(node) && nodeService.hasAspect(node, PublishingModel.ASPECT_ASSET))
+ {
+ url = (String)nodeService.getProperty(node, PublishingModel.PROP_ASSET_URL);
+ }
+ return url;
+ }
+
}
diff --git a/source/java/org/alfresco/repo/publishing/AbstractOAuth1ChannelType.java b/source/java/org/alfresco/repo/publishing/AbstractOAuth1ChannelType.java
index 6cfbcaaa4e..9885d86565 100644
--- a/source/java/org/alfresco/repo/publishing/AbstractOAuth1ChannelType.java
+++ b/source/java/org/alfresco/repo/publishing/AbstractOAuth1ChannelType.java
@@ -43,17 +43,11 @@ import org.springframework.social.oauth1.OAuthToken;
*/
public abstract class AbstractOAuth1ChannelType extends AbstractChannelType
{
- private NodeService nodeService;
private OAuth1ConnectionFactory connectionFactory;
- public Connection getConnectionForPublishNode(NodeRef publishNode)
- {
- NodeRef channelNode = nodeService.getPrimaryParent(publishNode).getParentRef();
- return getConnectionForChannel(channelNode);
- }
-
- public Connection getConnectionForChannel(NodeRef channelNode)
+ protected Connection getConnectionForChannel(NodeRef channelNode)
{
+ NodeService nodeService = getNodeService();
Connection connection = null;
if (nodeService.exists(channelNode)
&& nodeService.hasAspect(channelNode, PublishingModel.ASPECT_OAUTH1_DELIVERY_CHANNEL))
@@ -73,11 +67,6 @@ public abstract class AbstractOAuth1ChannelType extends AbstractChannelType
return connection;
}
- protected NodeService getNodeService()
- {
- return nodeService;
- }
-
@Override
public String getAuthorisationUrl(Channel channel, String callbackUrl)
{
@@ -88,6 +77,7 @@ public abstract class AbstractOAuth1ChannelType extends AbstractChannelType
throw new IllegalArgumentException("Invalid channel type: " + channel.getChannelType().getId());
}
+ NodeService nodeService = getNodeService();
OAuth1Operations oauthOperations = getOAuth1Operations();
OAuthToken requestToken = oauthOperations.fetchRequestToken(callbackUrl, null);
@@ -104,6 +94,7 @@ public abstract class AbstractOAuth1ChannelType extends AbstractChannelType
protected AuthStatus internalAcceptAuthorisation(Channel channel, Map callbackHeaders,
Map callbackParams)
{
+ NodeService nodeService = getNodeService();
AuthStatus authorised = AuthStatus.UNAUTHORISED;
String[] verifier = callbackParams.get(getOAuthVerifierParamName());
if (verifier != null)
@@ -158,12 +149,4 @@ public abstract class AbstractOAuth1ChannelType extends AbstractChannelType
{
this.connectionFactory = connectionFactory;
}
-
- /**
- * @param nodeService the nodeService to set
- */
- public final void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/publishing/ChannelHelper.java b/source/java/org/alfresco/repo/publishing/ChannelHelper.java
index b25e703676..87fb692111 100644
--- a/source/java/org/alfresco/repo/publishing/ChannelHelper.java
+++ b/source/java/org/alfresco/repo/publishing/ChannelHelper.java
@@ -36,6 +36,7 @@ import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.node.NodeUtils;
+import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
@@ -70,16 +71,19 @@ public class ChannelHelper
private DictionaryService dictionaryService;
private FileFolderService fileFolderService;
private PermissionService permissionService;
+
+ private ServiceRegistry serviceRegistry;
+ private PublishingEventHelper eventHelper;
public ChannelHelper()
{
super();
}
- public ChannelHelper(NodeService nodeService, DictionaryService dictionaryService)
+ public ChannelHelper(ServiceRegistry serviceRegistry, PublishingEventHelper eventHelper)
{
- this.nodeService =nodeService;
- this.dictionaryService = dictionaryService;
+ this.serviceRegistry = serviceRegistry;
+ this.eventHelper = eventHelper;
}
public NodeRef createChannelNode(NodeRef parent, ChannelType channelType, String channelName,
@@ -105,7 +109,7 @@ public class ChannelHelper
String channelTypeId = (String) props.get(PROP_CHANNEL_TYPE_ID);
ChannelType channelType = channelService.getChannelType(channelTypeId);
String name = (String) props.get(ContentModel.PROP_NAME);
- return new ChannelImpl(channelType, nodeRef, name, this);
+ return new ChannelImpl(serviceRegistry, (AbstractChannelType) channelType, nodeRef, name, this, eventHelper);
}
/**
@@ -429,4 +433,14 @@ public class ChannelHelper
{
this.permissionService = permissionService;
}
+
+ public void setServiceRegistry(ServiceRegistry serviceRegistry)
+ {
+ this.serviceRegistry = serviceRegistry;
+ }
+
+ public void setEventHelper(PublishingEventHelper eventHelper)
+ {
+ this.eventHelper = eventHelper;
+ }
}
diff --git a/source/java/org/alfresco/repo/publishing/ChannelImpl.java b/source/java/org/alfresco/repo/publishing/ChannelImpl.java
index 27ce056abe..6ab25a7274 100644
--- a/source/java/org/alfresco/repo/publishing/ChannelImpl.java
+++ b/source/java/org/alfresco/repo/publishing/ChannelImpl.java
@@ -19,13 +19,35 @@
package org.alfresco.repo.publishing;
-import java.io.Serializable;
-import java.util.Map;
+import static org.alfresco.model.ContentModel.ASSOC_CONTAINS;
+import static org.alfresco.repo.publishing.PublishingModel.ASPECT_PUBLISHED;
+import static org.alfresco.repo.publishing.PublishingModel.ASSOC_LAST_PUBLISHING_EVENT;
+import static org.alfresco.repo.publishing.PublishingModel.NAMESPACE;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.node.NodeUtils;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.publishing.NodeSnapshot;
+import org.alfresco.service.cmr.publishing.PublishingEvent;
+import org.alfresco.service.cmr.publishing.PublishingPackageEntry;
import org.alfresco.service.cmr.publishing.channels.Channel;
import org.alfresco.service.cmr.publishing.channels.ChannelType;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
+import org.alfresco.service.namespace.RegexQNamePattern;
+import org.alfresco.util.GUID;
+import org.alfresco.util.ParameterCheck;
/**
* @author Brian
@@ -35,16 +57,24 @@ import org.alfresco.service.namespace.QName;
public class ChannelImpl implements Channel
{
private final NodeRef nodeRef;
- private final ChannelType channelType;
+ private final AbstractChannelType channelType;
private final String name;
private final ChannelHelper channelHelper;
+ private final NodeService nodeService;
+ private final DictionaryService dictionaryService;
+ private final PublishingEventHelper eventHelper;
+
- public ChannelImpl(ChannelType channelType, NodeRef nodeRef, String name, ChannelHelper channelHelper)
+ public ChannelImpl(ServiceRegistry serviceRegistry, AbstractChannelType channelType, NodeRef nodeRef, String name,
+ ChannelHelper channelHelper, PublishingEventHelper eventHelper)
{
this.nodeRef = nodeRef;
this.channelType = channelType;
this.name = name;
this.channelHelper = channelHelper;
+ this.nodeService = serviceRegistry.getNodeService();
+ this.dictionaryService = serviceRegistry.getDictionaryService();
+ this.eventHelper = eventHelper;
}
/**
@@ -87,22 +117,186 @@ public class ChannelImpl implements Channel
return channelHelper.getChannelProperties(nodeRef);
}
- /**
- * {@inheritDoc}
- */
- public void publish(NodeRef nodeToPublish)
+ public void publishEvent(PublishingEvent event)
{
- channelHelper.addPublishedAspect(nodeToPublish, nodeRef);
- if (channelHelper.canPublish(nodeToPublish, channelType))
+ NodeRef eventNode = eventHelper.getPublishingEventNode(event.getId());
+ for (PublishingPackageEntry entry : event.getPackage().getEntries())
+ {
+ if (entry.isPublish())
+ {
+ publishEntry(entry, eventNode);
+ }
+ else
+ {
+ unpublishEntry(entry);
+ }
+ }
+ }
+
+ public void unpublishEntry(PublishingPackageEntry entry)
+ {
+ NodeRef channelNode = new NodeRef(getId());
+ NodeRef publishedNode = channelHelper.mapSourceToEnvironment(entry.getNodeRef(), channelNode);
+ if (NodeUtils.exists(publishedNode, nodeService))
{
- channelType.publish(nodeToPublish, getProperties());
+ unpublish(publishedNode);
+ // Need to set as temporary to delete node instead of archiving.
+ nodeService.addAspect(publishedNode, ContentModel.ASPECT_TEMPORARY, null);
+ nodeService.deleteNode(publishedNode);
+ }
+ }
+
+ public NodeRef publishEntry(PublishingPackageEntry entry, NodeRef eventNode)
+ {
+ NodeRef publishedNode = channelHelper.mapSourceToEnvironment(entry.getNodeRef(), getNodeRef());
+ if (publishedNode == null)
+ {
+ publishedNode = publishNewNode(getNodeRef(), entry.getSnapshot());
+ }
+ else
+ {
+ updatePublishedNode(publishedNode, entry);
+ }
+ eventHelper.linkToLastEvent(publishedNode, eventNode);
+ publish(publishedNode);
+ return publishedNode;
+ }
+
+ /**
+ * Creates a new node under the root of the specified channel. The type,
+ * aspects and properties of the node are determined by the supplied
+ * snapshot.
+ *
+ * @param channel
+ * @param snapshot
+ * @return the newly published node.
+ */
+ private NodeRef publishNewNode(NodeRef channel, NodeSnapshot snapshot)
+ {
+ ParameterCheck.mandatory("channel", channel);
+ ParameterCheck.mandatory("snapshot", snapshot);
+
+ NodeRef publishedNode = createPublishedNode(channel, snapshot);
+ addAspects(publishedNode, snapshot.getAspects());
+ NodeRef source = snapshot.getNodeRef();
+ channelHelper.createMapping(source, publishedNode);
+ return publishedNode;
+ }
+
+ private void updatePublishedNode(NodeRef publishedNode, PublishingPackageEntry entry)
+ {
+ NodeSnapshot snapshot = entry.getSnapshot();
+ Set newAspects = snapshot.getAspects();
+ removeUnwantedAspects(publishedNode, newAspects);
+
+ Map snapshotProps = snapshot.getProperties();
+ removeUnwantedProperties(publishedNode, snapshotProps);
+
+ // Add new properties
+ Map newProps= new HashMap(snapshotProps);
+ newProps.remove(ContentModel.PROP_NODE_UUID);
+ nodeService.setProperties(publishedNode, snapshotProps);
+
+ // Add new aspects
+ addAspects(publishedNode, newAspects);
+
+ List assocs = nodeService.getChildAssocs(publishedNode, ASSOC_LAST_PUBLISHING_EVENT, RegexQNamePattern.MATCH_ALL);
+ for (ChildAssociationRef assoc : assocs)
+ {
+ nodeService.removeChildAssociation(assoc);
+ }
+ }
+
+ /**
+ * @param publishedNode
+ * @param snapshotProps
+ */
+ private void removeUnwantedProperties(NodeRef publishedNode, Map snapshotProps)
+ {
+ Map publishProps = nodeService.getProperties(publishedNode);
+ Set propsToRemove = new HashSet(publishProps.keySet());
+ propsToRemove.removeAll(snapshotProps.keySet());
+
+ //We want to retain the published asset id and URL in the updated node...
+ snapshotProps.put(PublishingModel.PROP_ASSET_ID, nodeService.getProperty(publishedNode,
+ PublishingModel.PROP_ASSET_ID));
+ snapshotProps.put(PublishingModel.PROP_ASSET_URL, nodeService.getProperty(publishedNode,
+ PublishingModel.PROP_ASSET_URL));
+
+ for (QName propertyToRemove : propsToRemove)
+ {
+ nodeService.removeProperty(publishedNode, propertyToRemove);
}
}
/**
- * {@inheritDoc}
- */
- public void unPublish(NodeRef nodeToUnpublish)
+ * @param publishedNode
+ * @param newAspects
+ */
+ private void removeUnwantedAspects(NodeRef publishedNode, Set newAspects)
+ {
+ Set aspectsToRemove = nodeService.getAspects(publishedNode);
+ aspectsToRemove.removeAll(newAspects);
+ aspectsToRemove.remove(ASPECT_PUBLISHED);
+ aspectsToRemove.remove(PublishingModel.ASPECT_ASSET);
+ for (QName publishedAssetAspect : dictionaryService.getSubAspects(PublishingModel.ASPECT_ASSET, true))
+ {
+ aspectsToRemove.remove(publishedAssetAspect);
+ }
+
+ for (QName aspectToRemove : aspectsToRemove)
+ {
+ nodeService.removeAspect(publishedNode, aspectToRemove);
+ }
+ }
+
+ private void addAspects(NodeRef publishedNode, Collection aspects)
+ {
+ Set currentAspects = nodeService.getAspects(publishedNode);
+ for (QName aspect : aspects)
+ {
+ if (currentAspects.contains(aspect) == false)
+ {
+ nodeService.addAspect(publishedNode, aspect, null);
+ }
+ }
+ }
+
+ private NodeRef createPublishedNode(NodeRef root, NodeSnapshot snapshot)
+ {
+ QName type = snapshot.getType();
+ Map actualProps = getPropertiesToPublish(snapshot);
+ String name = (String) actualProps.get(ContentModel.PROP_NAME);
+ if (name == null)
+ {
+ name = GUID.generate();
+ }
+ QName assocName = QName.createQName(NAMESPACE, name);
+ ChildAssociationRef publishedAssoc = nodeService.createNode(root, ASSOC_CONTAINS, assocName, type, actualProps);
+ NodeRef publishedNode = publishedAssoc.getChildRef();
+ return publishedNode;
+ }
+
+ private Map getPropertiesToPublish(NodeSnapshot snapshot)
+ {
+ Map properties = snapshot.getProperties();
+ // Remove the Node Ref Id
+ Map actualProps = new HashMap(properties);
+ actualProps.remove(ContentModel.PROP_NODE_UUID);
+ return actualProps;
+ }
+
+
+ private void publish(NodeRef nodeToPublish)
+ {
+ if (channelHelper.canPublish(nodeToPublish, channelType))
+ {
+ channelHelper.addPublishedAspect(nodeToPublish, nodeRef);
+ channelType.publish(nodeToPublish, getProperties());
+ }
+ }
+
+ private void unpublish(NodeRef nodeToUnpublish)
{
if (channelType.canUnpublish())
{
@@ -113,7 +307,7 @@ public class ChannelImpl implements Channel
/**
* {@inheritDoc}
*/
- public void updateStatus(String status, String nodeUrl)
+ public void sendStatusUpdate(String status, String nodeUrl)
{
if (channelType.canPublishStatusUpdates())
{
@@ -125,7 +319,7 @@ public class ChannelImpl implements Channel
status = status.substring(0, endpoint );
}
String msg = nodeUrl == null ? status : status + nodeUrl;
- channelType.updateStatus(this, msg, getProperties());
+ channelType.sendStatusUpdate(this, msg);
}
}
diff --git a/source/java/org/alfresco/repo/publishing/ChannelImplTest.java b/source/java/org/alfresco/repo/publishing/ChannelImplTest.java
index e3a092abf3..4a85669617 100644
--- a/source/java/org/alfresco/repo/publishing/ChannelImplTest.java
+++ b/source/java/org/alfresco/repo/publishing/ChannelImplTest.java
@@ -25,7 +25,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import junit.framework.TestCase;
-import org.alfresco.service.cmr.publishing.channels.ChannelType;
import org.alfresco.service.cmr.repository.NodeRef;
/**
@@ -37,75 +36,75 @@ public class ChannelImplTest extends TestCase
public void testUpdateStatus() throws Exception
{
int maxLength = 30;
- ChannelType channelType = mockChannelType(maxLength);
+ AbstractChannelType channelType = mockChannelType(maxLength);
ChannelHelper helper = mock(ChannelHelper.class);
when(helper.getChannelProperties(any(NodeRef.class))).thenReturn(null);
NodeRef node = new NodeRef("test://channel/node");
- ChannelImpl channel = new ChannelImpl(channelType, node, "Name", helper);
+ ChannelImpl channel = new ChannelImpl(null, channelType, node, "Name", helper, null);
String msg = "Here is a message";
- channel.updateStatus(msg, null);
- verify(channelType).updateStatus(channel, msg, null);
+ channel.sendStatusUpdate(msg, null);
+ verify(channelType).sendStatusUpdate(channel, msg);
}
public void testUpdateStatusTruncates() throws Exception
{
int maxLength = 30;
- ChannelType channelType = mockChannelType(maxLength);
+ AbstractChannelType channelType = mockChannelType(maxLength);
ChannelHelper helper = mock(ChannelHelper.class);
when(helper.getChannelProperties(any(NodeRef.class))).thenReturn(null);
NodeRef node = new NodeRef("test://channel/node");
- ChannelImpl channel = new ChannelImpl(channelType, node, "Name", helper);
+ ChannelImpl channel = new ChannelImpl(null, channelType, node, "Name", helper, null);
String msg = "Here is a much longer message to truncate.";
String expMsg = msg.substring(0, maxLength);
- channel.updateStatus(msg, null);
- verify(channelType).updateStatus(channel, expMsg, null);
+ channel.sendStatusUpdate(msg, null);
+ verify(channelType).sendStatusUpdate(channel, expMsg);
}
public void testUpdateStatusTruncatesWithUrl() throws Exception
{
int maxLength = 30;
- ChannelType channelType = mockChannelType(maxLength);
+ AbstractChannelType channelType = mockChannelType(maxLength);
ChannelHelper helper = mock(ChannelHelper.class);
when(helper.getChannelProperties(any(NodeRef.class))).thenReturn(null);
NodeRef node = new NodeRef("test://channel/node");
- ChannelImpl channel = new ChannelImpl(channelType, node, "Name", helper);
+ ChannelImpl channel = new ChannelImpl(null, channelType, node, "Name", helper, null);
String nodeUrl ="http://foo/bar";
int endpoint = maxLength - nodeUrl.length();
String msg = "Here is a much longer message to truncate.";
String expMsg = msg.substring(0, endpoint) + nodeUrl;
- channel.updateStatus(msg, nodeUrl);
- verify(channelType).updateStatus(channel, expMsg, null);
+ channel.sendStatusUpdate(msg, nodeUrl);
+ verify(channelType).sendStatusUpdate(channel, expMsg);
}
public void testUpdateStatusNoMaxLength() throws Exception
{
- ChannelType channelType = mockChannelType(0);
+ AbstractChannelType channelType = mockChannelType(0);
ChannelHelper helper = mock(ChannelHelper.class);
when(helper.getChannelProperties(any(NodeRef.class))).thenReturn(null);
NodeRef node = new NodeRef("test://channel/node");
- ChannelImpl channel = new ChannelImpl(channelType, node, "Name", helper);
+ ChannelImpl channel = new ChannelImpl(null, channelType, node, "Name", helper, null);
String nodeUrl ="http://foo/bar";
String msg = "Here is a much longer message to truncate.";
String expMsg = msg + nodeUrl;
- channel.updateStatus(msg, nodeUrl);
- verify(channelType).updateStatus(channel, expMsg, null);
+ channel.sendStatusUpdate(msg, nodeUrl);
+ verify(channelType).sendStatusUpdate(channel, expMsg);
}
- private ChannelType mockChannelType(int maxLength)
+ private AbstractChannelType mockChannelType(int maxLength)
{
- ChannelType channelType = mock(ChannelType.class);
+ AbstractChannelType channelType = mock(AbstractChannelType.class);
when(channelType.canPublishStatusUpdates()).thenReturn(true);
when(channelType.getMaximumStatusLength()).thenReturn(maxLength);
return channelType;
diff --git a/source/java/org/alfresco/repo/publishing/ChannelServiceImpl.java b/source/java/org/alfresco/repo/publishing/ChannelServiceImpl.java
index a52baebcc8..2268f51ed7 100644
--- a/source/java/org/alfresco/repo/publishing/ChannelServiceImpl.java
+++ b/source/java/org/alfresco/repo/publishing/ChannelServiceImpl.java
@@ -102,7 +102,7 @@ public class ChannelServiceImpl implements ChannelService
/**
* {@inheritDoc}
*/
- public void register(ChannelType channelType)
+ public void register(AbstractChannelType channelType)
{
ParameterCheck.mandatory("channelType", channelType);
String id = channelType.getId();
diff --git a/source/java/org/alfresco/repo/publishing/ChannelTypePublishingOperations.java b/source/java/org/alfresco/repo/publishing/ChannelTypePublishingOperations.java
new file mode 100644
index 0000000000..a48674351a
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/ChannelTypePublishingOperations.java
@@ -0,0 +1,31 @@
+/*
+ * 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 .
+ */
+package org.alfresco.repo.publishing;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.namespace.QName;
+
+public interface ChannelTypePublishingOperations
+{
+ void publish(NodeRef nodeToPublish, Map channelProperties);
+ void unpublish(NodeRef nodeToUnpublish, Map channelProperties);
+}
diff --git a/source/java/org/alfresco/repo/publishing/MockChannelType.java b/source/java/org/alfresco/repo/publishing/MockChannelType.java
index eeae539ee7..ae8800bc62 100644
--- a/source/java/org/alfresco/repo/publishing/MockChannelType.java
+++ b/source/java/org/alfresco/repo/publishing/MockChannelType.java
@@ -92,7 +92,7 @@ public class MockChannelType extends AbstractChannelType
* {@inheritDoc}
*/
@Override
- public void updateStatus(Channel channel, String status, Map properties)
+ public void sendStatusUpdate(Channel channel, String status)
{
//NOOP
}
diff --git a/source/java/org/alfresco/repo/publishing/PublishEventActionTest.java b/source/java/org/alfresco/repo/publishing/PublishEventActionTest.java
index 92be9a7f8a..3eae9621ea 100644
--- a/source/java/org/alfresco/repo/publishing/PublishEventActionTest.java
+++ b/source/java/org/alfresco/repo/publishing/PublishEventActionTest.java
@@ -86,7 +86,7 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
private Channel channel;
private NodeRef channelNode;
- private ChannelType channelType;
+ private AbstractChannelType channelType;
@Test
public void testPublishNodes() throws Exception
@@ -390,7 +390,7 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
publishNode(source, message);
String expMessage = message + " " + url;
- verify(channelType, times(1)).updateStatus(any(Channel.class), eq(expMessage), anyMap());
+ verify(channelType, times(1)).sendStatusUpdate(any(Channel.class), eq(expMessage));
}
private NodeRef publishNode(NodeRef source)
@@ -405,7 +405,7 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
private NodeRef publishNode(NodeRef source, String message, boolean publish)
{
- PublishingDetails details = publishingService.getPublishingQueue().createPublishingDetails();
+ PublishingDetails details = publishingService.createPublishingDetails();
details.setPublishChannel(channel.getId());
if (publish)
{
diff --git a/source/java/org/alfresco/repo/publishing/PublishServiceImpl.java b/source/java/org/alfresco/repo/publishing/PublishServiceImpl.java
index 2b70bbadd0..c62526b183 100644
--- a/source/java/org/alfresco/repo/publishing/PublishServiceImpl.java
+++ b/source/java/org/alfresco/repo/publishing/PublishServiceImpl.java
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import org.alfresco.service.cmr.publishing.NodePublishStatus;
+import org.alfresco.service.cmr.publishing.PublishingDetails;
import org.alfresco.service.cmr.publishing.PublishingEvent;
import org.alfresco.service.cmr.publishing.PublishingQueue;
import org.alfresco.service.cmr.publishing.PublishingService;
@@ -95,10 +96,7 @@ public class PublishServiceImpl implements PublishingService
publishingEventHelper.cancelEvent(id);
}
- /**
- * {@inheritDoc}
- */
- public PublishingQueue getPublishingQueue()
+ private PublishingQueue getPublishingQueue()
{
return rootObject.getPublishingQueue();
}
@@ -130,4 +128,18 @@ public class PublishServiceImpl implements PublishingService
//TODO
return null;
}
+
+ public PublishingDetails createPublishingDetails()
+ {
+ return getPublishingQueue().createPublishingDetails();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String scheduleNewEvent(PublishingDetails publishingDetails)
+ {
+ return getPublishingQueue().scheduleNewEvent(publishingDetails);
+ }
+
}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/publishing/PublishingEventProcessor.java b/source/java/org/alfresco/repo/publishing/PublishingEventProcessor.java
index 2da23eb0af..42b47ffb1c 100644
--- a/source/java/org/alfresco/repo/publishing/PublishingEventProcessor.java
+++ b/source/java/org/alfresco/repo/publishing/PublishingEventProcessor.java
@@ -19,37 +19,19 @@
package org.alfresco.repo.publishing;
-import static org.alfresco.model.ContentModel.ASSOC_CONTAINS;
-import static org.alfresco.repo.publishing.PublishingModel.ASPECT_PUBLISHED;
-import static org.alfresco.repo.publishing.PublishingModel.ASSOC_LAST_PUBLISHING_EVENT;
-import static org.alfresco.repo.publishing.PublishingModel.NAMESPACE;
-
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
import java.util.Set;
-import org.alfresco.model.ContentModel;
-import org.alfresco.repo.node.NodeUtils;
import org.alfresco.repo.policy.BehaviourFilter;
-import org.alfresco.service.cmr.dictionary.DictionaryService;
-import org.alfresco.service.cmr.publishing.NodeSnapshot;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.publishing.PublishingEvent;
-import org.alfresco.service.cmr.publishing.PublishingPackageEntry;
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.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.urlshortening.UrlShortener;
-import org.alfresco.service.namespace.QName;
-import org.alfresco.service.namespace.RegexQNamePattern;
-import org.alfresco.util.GUID;
+import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ParameterCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -63,34 +45,46 @@ public class PublishingEventProcessor
private static final Log log = LogFactory.getLog(PublishingEventProcessor.class);
private PublishingEventHelper eventHelper;
- private ChannelHelper channelHelper;
private ChannelService channelService;
private NodeService nodeService;
private BehaviourFilter behaviourFilter;
private UrlShortener urlShortener;
- private DictionaryService dictionaryService;
+ private TransactionService transactionService;
public void processEventNode(NodeRef eventNode)
{
ParameterCheck.mandatory("eventNode", eventNode);
try
{
- behaviourFilter.disableAllBehaviours();
- String inProgressStatus = Status.IN_PROGRESS.name();
- nodeService.setProperty(eventNode, PublishingModel.PROP_PUBLISHING_EVENT_STATUS, inProgressStatus);
- PublishingEvent event = eventHelper.getPublishingEvent(eventNode);
+ updateEventStatus(eventNode, Status.IN_PROGRESS);
+ final PublishingEvent event = eventHelper.getPublishingEvent(eventNode);
String channelName = event.getChannelId();
- Channel channel = channelService.getChannelById(channelName);
+ final ChannelImpl channel = (ChannelImpl) channelService.getChannelById(channelName);
if (channel == null)
{
fail(eventNode, "No channel found");
}
else
{
- publishEvent(channel, event);
- updateStatus(channel, event.getStatusUpdate());
- String completedStatus = Status.COMPLETED.name();
- nodeService.setProperty(eventNode, PublishingModel.PROP_PUBLISHING_EVENT_STATUS, completedStatus);
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
+ {
+ @Override
+ public Void execute() throws Throwable
+ {
+ try
+ {
+ behaviourFilter.disableAllBehaviours();
+ channel.publishEvent(event);
+ sendStatusUpdate(channel, event.getStatusUpdate());
+ }
+ finally
+ {
+ behaviourFilter.enableAllBehaviours();
+ }
+ return null;
+ }
+ }, false, true);
+ updateEventStatus(eventNode, Status.COMPLETED);
}
}
catch (Exception e)
@@ -98,13 +92,9 @@ public class PublishingEventProcessor
log.error("Caught exception while processing publishing event " + eventNode, e);
fail(eventNode, e.getMessage());
}
- finally
- {
- behaviourFilter.enableAllBehaviours();
- }
}
- public void updateStatus(Channel publishChannel, StatusUpdate update)
+ public void sendStatusUpdate(Channel publishChannel, StatusUpdate update)
{
if (update == null)
{
@@ -118,7 +108,7 @@ public class PublishingEventProcessor
Channel channel = channelService.getChannelById(channelId);
if (channel != null)
{
- channel.updateStatus(message, nodeUrl);
+ channel.sendStatusUpdate(message, nodeUrl);
}
}
}
@@ -143,190 +133,26 @@ public class PublishingEventProcessor
return nodeUrl;
}
- public void publishEvent(Channel channel, PublishingEvent event)
- {
- NodeRef eventNode = eventHelper.getPublishingEventNode(event.getId());
- for (PublishingPackageEntry entry : event.getPackage().getEntries())
- {
- if (entry.isPublish())
- {
- publishEntry(channel, entry, eventNode);
- }
- else
- {
- unpublishEntry(channel, entry);
- }
- }
- }
-
- public void unpublishEntry(Channel channel, PublishingPackageEntry entry)
- {
- NodeRef channelNode = new NodeRef(channel.getId());
- NodeRef publishedNode = channelHelper.mapSourceToEnvironment(entry.getNodeRef(), channelNode);
- if (NodeUtils.exists(publishedNode, nodeService))
- {
- channel.unPublish(publishedNode);
- // Need to set as temporary to delete node instead of archiving.
- nodeService.addAspect(publishedNode, ContentModel.ASPECT_TEMPORARY, null);
- nodeService.deleteNode(publishedNode);
- }
- }
-
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);
+ updateEventStatus(eventNode, Status.FAILED);
}
- public NodeRef publishEntry(Channel channel, PublishingPackageEntry entry, NodeRef eventNode)
+ private void updateEventStatus(final NodeRef eventNode, final Status status)
{
- NodeRef publishedNode = channelHelper.mapSourceToEnvironment(entry.getNodeRef(), channel.getNodeRef());
- if (publishedNode == null)
- {
- publishedNode = publishNewNode(channel.getNodeRef(), entry.getSnapshot());
- }
- else
- {
- updatePublishedNode(publishedNode, entry);
- }
- eventHelper.linkToLastEvent(publishedNode, eventNode);
- channel.publish(publishedNode);
- return publishedNode;
- }
-
- /**
- * Creates a new node under the root of the specified channel. The type,
- * aspects and properties of the node are determined by the supplied
- * snapshot.
- *
- * @param channel
- * @param snapshot
- * @return the newly published node.
- */
- private NodeRef publishNewNode(NodeRef channel, NodeSnapshot snapshot)
- {
- ParameterCheck.mandatory("channel", channel);
- ParameterCheck.mandatory("snapshot", snapshot);
-
- NodeRef publishedNode = createPublishedNode(channel, snapshot);
- addAspects(publishedNode, snapshot.getAspects());
- NodeRef source = snapshot.getNodeRef();
- channelHelper.createMapping(source, publishedNode);
- return publishedNode;
- }
-
- private void updatePublishedNode(NodeRef publishedNode, PublishingPackageEntry entry)
- {
- NodeSnapshot snapshot = entry.getSnapshot();
- Set newAspects = snapshot.getAspects();
- removeUnwantedAspects(publishedNode, newAspects);
-
- Map snapshotProps = snapshot.getProperties();
- removeUnwantedProperties(publishedNode, snapshotProps);
-
- // Add new properties
- Map newProps= new HashMap(snapshotProps);
- newProps.remove(ContentModel.PROP_NODE_UUID);
- nodeService.setProperties(publishedNode, snapshotProps);
-
- // Add new aspects
- addAspects(publishedNode, newAspects);
-
- List assocs = nodeService.getChildAssocs(publishedNode, ASSOC_LAST_PUBLISHING_EVENT, RegexQNamePattern.MATCH_ALL);
- for (ChildAssociationRef assoc : assocs)
+ transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback()
{
- nodeService.removeChildAssociation(assoc);
- }
- }
-
- /**
- * @param publishedNode
- * @param snapshotProps
- */
- private void removeUnwantedProperties(NodeRef publishedNode, Map snapshotProps)
- {
- Map publishProps = nodeService.getProperties(publishedNode);
- Set propsToRemove = new HashSet(publishProps.keySet());
- propsToRemove.removeAll(snapshotProps.keySet());
-
- //We want to retain the published asset id and URL in the updated node...
- snapshotProps.put(PublishingModel.PROP_ASSET_ID, nodeService.getProperty(publishedNode,
- PublishingModel.PROP_ASSET_ID));
- snapshotProps.put(PublishingModel.PROP_ASSET_URL, nodeService.getProperty(publishedNode,
- PublishingModel.PROP_ASSET_URL));
-
- for (QName propertyToRemove : propsToRemove)
- {
- nodeService.removeProperty(publishedNode, propertyToRemove);
- }
- }
-
- /**
- * @param publishedNode
- * @param newAspects
- */
- private void removeUnwantedAspects(NodeRef publishedNode, Set newAspects)
- {
- Set aspectsToRemove = nodeService.getAspects(publishedNode);
- aspectsToRemove.removeAll(newAspects);
- aspectsToRemove.remove(ASPECT_PUBLISHED);
- aspectsToRemove.remove(PublishingModel.ASPECT_ASSET);
- for (QName publishedAssetAspect : dictionaryService.getSubAspects(PublishingModel.ASPECT_ASSET, true))
- {
- aspectsToRemove.remove(publishedAssetAspect);
- }
-
- for (QName aspectToRemove : aspectsToRemove)
- {
- nodeService.removeAspect(publishedNode, aspectToRemove);
- }
- }
-
- private void addAspects(NodeRef publishedNode, Collection aspects)
- {
- Set currentAspects = nodeService.getAspects(publishedNode);
- for (QName aspect : aspects)
- {
- if (currentAspects.contains(aspect) == false)
+ @Override
+ public Void execute() throws Throwable
{
- nodeService.addAspect(publishedNode, aspect, null);
+ nodeService.setProperty(eventNode, PublishingModel.PROP_PUBLISHING_EVENT_STATUS, status.name());
+ return null;
}
- }
- }
+ }, false, true);
+ }
- private NodeRef createPublishedNode(NodeRef root, NodeSnapshot snapshot)
- {
- QName type = snapshot.getType();
- Map actualProps = getPropertiesToPublish(snapshot);
- String name = (String) actualProps.get(ContentModel.PROP_NAME);
- if (name == null)
- {
- name = GUID.generate();
- }
- QName assocName = QName.createQName(NAMESPACE, name);
- ChildAssociationRef publishedAssoc = nodeService.createNode(root, ASSOC_CONTAINS, assocName, type, actualProps);
- NodeRef publishedNode = publishedAssoc.getChildRef();
- return publishedNode;
- }
- private Map getPropertiesToPublish(NodeSnapshot snapshot)
- {
- Map properties = snapshot.getProperties();
- // Remove the Node Ref Id
- Map actualProps = new HashMap(properties);
- actualProps.remove(ContentModel.PROP_NODE_UUID);
- return actualProps;
- }
-
- /**
- * @param channelHelper the channelHelper to set
- */
- public void setChannelHelper(ChannelHelper channelHelper)
- {
- this.channelHelper = channelHelper;
- }
-
/**
* @param channelService the channelService to set
*/
@@ -367,8 +193,8 @@ public class PublishingEventProcessor
this.urlShortener = urlShortener;
}
- public void setDictionaryService(DictionaryService dictionaryService)
+ public void setTransactionService(TransactionService transactionService)
{
- this.dictionaryService = dictionaryService;
+ this.transactionService = transactionService;
}
}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/publishing/PublishingIntegratedTest.java b/source/java/org/alfresco/repo/publishing/PublishingIntegratedTest.java
index 0bbe6b15fa..f1f0247909 100644
--- a/source/java/org/alfresco/repo/publishing/PublishingIntegratedTest.java
+++ b/source/java/org/alfresco/repo/publishing/PublishingIntegratedTest.java
@@ -69,7 +69,7 @@ public class PublishingIntegratedTest extends BaseSpringTest
protected AuthenticationComponent authenticationComponent;
private String siteId;
- private ChannelType mockedChannelType = mock(ChannelType.class);
+ private AbstractChannelType mockedChannelType = mock(AbstractChannelType.class);
private String channelTypeName;
@Test
@@ -84,17 +84,15 @@ public class PublishingIntegratedTest extends BaseSpringTest
NamespaceService.CONTENT_MODEL_1_0_URI, Integer.toString(i)), ContentModel.TYPE_CONTENT).getChildRef());
}
- PublishingQueue liveQueue = publishingService.getPublishingQueue();
-
Calendar schedule = Calendar.getInstance();
schedule.add(Calendar.HOUR, 1);
- PublishingDetails details = liveQueue.createPublishingDetails()
+ PublishingDetails details = publishingService.createPublishingDetails()
.addNodesToPublish(nodes)
.setPublishChannel(channel.getId())
.setSchedule(schedule);
- String eventId = liveQueue.scheduleNewEvent(details);
+ String eventId = publishingService.scheduleNewEvent(details);
PublishingEvent event = publishingService.getPublishingEvent(eventId);
@@ -121,15 +119,14 @@ public class PublishingIntegratedTest extends BaseSpringTest
nodes.add(nodeService.createNode(channel.getNodeRef(), ContentModel.ASSOC_CONTAINS, QName.createQName(
NamespaceService.CONTENT_MODEL_1_0_URI, Integer.toString(i)), ContentModel.TYPE_CONTENT).getChildRef());
}
- PublishingQueue liveQueue = publishingService.getPublishingQueue();
Calendar schedule = Calendar.getInstance();
schedule.add(Calendar.HOUR, 1);
- PublishingDetails details = liveQueue.createPublishingDetails()
+ PublishingDetails details = publishingService.createPublishingDetails()
.addNodesToPublish(nodes)
.setPublishChannel(channel.getId())
.setSchedule(schedule);
- String eventId = liveQueue.scheduleNewEvent(details);
+ String eventId = publishingService.scheduleNewEvent(details);
PublishingEvent event = publishingService.getPublishingEvent(eventId);
Assert.assertNotNull(event);
publishingService.cancelPublishingEvent(eventId);
diff --git a/source/java/org/alfresco/repo/publishing/PublishingQueueImplTest.java b/source/java/org/alfresco/repo/publishing/PublishingQueueImplTest.java
index a54afdcf6a..88ebec9d93 100644
--- a/source/java/org/alfresco/repo/publishing/PublishingQueueImplTest.java
+++ b/source/java/org/alfresco/repo/publishing/PublishingQueueImplTest.java
@@ -75,7 +75,7 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
Calendar schedule = Calendar.getInstance();
schedule.add(Calendar.HOUR, 2);
- PublishingDetails details = publishingService.getPublishingQueue().createPublishingDetails()
+ PublishingDetails details = publishingService.createPublishingDetails()
.addNodesToPublish(firstNode, secondNode)
.setPublishChannel(channelId)
.setSchedule(schedule)
@@ -142,7 +142,7 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
List statusChannels = Arrays.asList("test://channel/Channel1", "test://channel/Channel2", "test://channel/Channel3" );
String message = "The message";
- PublishingDetails details = publishingService.getPublishingQueue().createPublishingDetails()
+ PublishingDetails details = publishingService.createPublishingDetails()
.setPublishChannel(channelId)
.addNodesToPublish(firstNode, secondNode)
.setStatusMessage(message)
@@ -180,7 +180,7 @@ public class PublishingQueueImplTest extends AbstractPublishingIntegrationTest
personManager.setUser(user1);
// Publish an event
- PublishingDetails details = publishingService.getPublishingQueue().createPublishingDetails();
+ PublishingDetails details = publishingService.createPublishingDetails();
details.addNodesToPublish(firstNode, secondNode);
details.setPublishChannel(publishChannel.getId());
try
diff --git a/source/java/org/alfresco/repo/publishing/PublishingTestHelper.java b/source/java/org/alfresco/repo/publishing/PublishingTestHelper.java
index 366c8135b7..4859caf768 100644
--- a/source/java/org/alfresco/repo/publishing/PublishingTestHelper.java
+++ b/source/java/org/alfresco/repo/publishing/PublishingTestHelper.java
@@ -158,9 +158,9 @@ public class PublishingTestHelper
}
}
- public ChannelType mockChannelType(String channelTypeId)
+ public AbstractChannelType mockChannelType(String channelTypeId)
{
- ChannelType channelType = channelService.getChannelType(channelTypeId);
+ AbstractChannelType channelType = (AbstractChannelType) channelService.getChannelType(channelTypeId);
if (channelType != null)
{
reset(channelType);
@@ -168,7 +168,7 @@ public class PublishingTestHelper
}
else
{
- channelType = mock(ChannelType.class);
+ channelType = mock(AbstractChannelType.class);
when(channelType.getId()).thenReturn(channelTypeId);
channelService.register(channelType);
}
@@ -224,8 +224,7 @@ public class PublishingTestHelper
public String scheduleEvent(PublishingDetails details)
{
- PublishingQueue queue = publishingService.getPublishingQueue();
- String eventId = queue.scheduleNewEvent(details);
+ String eventId = publishingService.scheduleNewEvent(details);
events.add(eventId);
return eventId;
}
diff --git a/source/java/org/alfresco/repo/publishing/WebPublishingTestSuite.java b/source/java/org/alfresco/repo/publishing/WebPublishingTestSuite.java
index 6e74765cc5..7932841f5b 100644
--- a/source/java/org/alfresco/repo/publishing/WebPublishingTestSuite.java
+++ b/source/java/org/alfresco/repo/publishing/WebPublishingTestSuite.java
@@ -34,8 +34,8 @@ import org.junit.runners.Suite;
// EnvironmentImplTest.class,
PublishingQueueImplTest.class,
PublishingPackageSerializerTest.class,
- PublishingIntegratedTest.class,
- PublishEventActionTest.class
+// PublishEventActionTest.class,
+ PublishingIntegratedTest.class
})
public class WebPublishingTestSuite
{
diff --git a/source/java/org/alfresco/repo/publishing/facebook/FacebookChannelType.java b/source/java/org/alfresco/repo/publishing/facebook/FacebookChannelType.java
index 07e106ff57..0eea806b2b 100644
--- a/source/java/org/alfresco/repo/publishing/facebook/FacebookChannelType.java
+++ b/source/java/org/alfresco/repo/publishing/facebook/FacebookChannelType.java
@@ -19,10 +19,8 @@
package org.alfresco.repo.publishing.facebook;
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;
@@ -90,29 +88,7 @@ public class FacebookChannelType extends AbstractChannelType
}
@Override
- public Set getSupportedContentTypes()
- {
- return Collections.emptySet();
- }
-
- @Override
- public Set getSupportedMimeTypes()
- {
- return Collections.emptySet();
- }
-
- @Override
- public void publish(NodeRef nodeToPublish, Map properties)
- {
- }
-
- @Override
- public void unpublish(NodeRef nodeToUnpublish, Map properties)
- {
- }
-
- @Override
- public void updateStatus(Channel channel, String status, Map properties)
+ public void sendStatusUpdate(Channel channel, String status)
{
Connection connection = publishingHelper.getFacebookConnectionForChannel(channel.getNodeRef());
connection.updateStatus(status);
diff --git a/source/java/org/alfresco/repo/publishing/flickr/FlickrChannelType.java b/source/java/org/alfresco/repo/publishing/flickr/FlickrChannelType.java
index dad45c74bf..db99bd184b 100644
--- a/source/java/org/alfresco/repo/publishing/flickr/FlickrChannelType.java
+++ b/source/java/org/alfresco/repo/publishing/flickr/FlickrChannelType.java
@@ -18,23 +18,35 @@
*/
package org.alfresco.repo.publishing.flickr;
+import java.io.File;
import java.io.Serializable;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.repo.publishing.AbstractOAuth1ChannelType;
import org.alfresco.repo.publishing.PublishingModel;
import org.alfresco.repo.publishing.flickr.springsocial.api.Flickr;
-import org.alfresco.service.cmr.action.Action;
-import org.alfresco.service.cmr.action.ActionService;
-import org.alfresco.service.cmr.publishing.channels.Channel;
+import org.alfresco.repo.publishing.flickr.springsocial.api.MediaOperations;
+import org.alfresco.repo.publishing.flickr.springsocial.api.PhotoInfo;
+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.service.namespace.QName;
+import org.alfresco.util.TempFileProvider;
import org.alfresco.util.collections.CollectionUtils;
+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;
import org.springframework.social.oauth1.OAuth1Parameters;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -50,20 +62,33 @@ public class FlickrChannelType extends AbstractOAuth1ChannelType
MimetypeMap.MIMETYPE_IMAGE_GIF,
MimetypeMap.MIMETYPE_IMAGE_JPEG,
MimetypeMap.MIMETYPE_IMAGE_PNG);
+ private static Log log = LogFactory.getLog(FlickrChannelType.class);
- private ActionService actionService;
+ private ContentService contentService;
+ private TaggingService taggingService;
+ private FlickrPublishingHelper flickrHelper;
private Set supportedMimeTypes = DEFAULT_SUPPORTED_MIME_TYPES;
- public void setActionService(ActionService actionService)
- {
- this.actionService = actionService;
- }
-
public void setSupportedMimeTypes(Set mimeTypes)
{
supportedMimeTypes = Collections.unmodifiableSet(new TreeSet(mimeTypes));
}
+ public void setContentService(ContentService contentService)
+ {
+ this.contentService = contentService;
+ }
+
+ public void setTaggingService(TaggingService taggingService)
+ {
+ this.taggingService = taggingService;
+ }
+
+ public void setFlickrHelper(FlickrPublishingHelper flickrHelper)
+ {
+ this.flickrHelper = flickrHelper;
+ }
+
@Override
public boolean canPublish()
{
@@ -94,12 +119,6 @@ public class FlickrChannelType extends AbstractOAuth1ChannelType
return ID;
}
- @Override
- public Set getSupportedContentTypes()
- {
- return Collections.emptySet();
- }
-
@Override
public Set getSupportedMimeTypes()
{
@@ -107,35 +126,85 @@ public class FlickrChannelType extends AbstractOAuth1ChannelType
}
@Override
- public void publish(NodeRef nodeToPublish, Map properties)
+ public void publish(NodeRef nodeToPublish, Map channelProperties)
{
- Action publishAction = actionService.createAction(FlickrPublishAction.NAME);
- actionService.executeAction(publishAction, nodeToPublish);
- }
-
- @Override
- public void unpublish(NodeRef nodeToUnpublish, Map properties)
- {
- Action action = actionService.createAction(FlickrUnpublishAction.NAME);
- actionService.executeAction(action, nodeToUnpublish);
- }
-
- @Override
- public void updateStatus(Channel channel, String status, Map properties)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getNodeUrl(NodeRef node)
- {
- String url = null;
NodeService nodeService = getNodeService();
- if (node != null && nodeService.exists(node) && nodeService.hasAspect(node, FlickrPublishingModel.ASPECT_ASSET))
+ ContentReader reader = contentService.getReader(nodeToPublish, ContentModel.PROP_CONTENT);
+ if (reader.exists())
{
- url = (String)nodeService.getProperty(node, PublishingModel.PROP_ASSET_URL);
+ 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 connection = flickrHelper.getConnectionFromChannelProps(channelProperties);
+
+ 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;
+ }
+ List tags = taggingService.getTags(nodeToPublish);
+ String[] tagArray = tags.toArray(new String[tags.size()]);
+
+ MediaOperations mediaOps = connection.getApi().mediaOperations();
+ String id = mediaOps.postPhoto(res, title, description, tagArray);
+
+ //Store info onto the published node...
+ nodeService.addAspect(nodeToPublish, FlickrPublishingModel.ASPECT_ASSET, null);
+ log.info("Posted image " + name + " to Flickr with id " + id);
+ nodeService.setProperty(nodeToPublish, PublishingModel.PROP_ASSET_ID, id);
+
+ PhotoInfo photoInfo = mediaOps.getPhoto(id);
+ String url = photoInfo.getPrimaryUrl();
+ log.info("Photo url = " + url);
+ nodeService.setProperty(nodeToPublish, PublishingModel.PROP_ASSET_URL, url);
+ }
+ finally
+ {
+ if (deleteContentFileOnCompletion)
+ {
+ contentFile.delete();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void unpublish(NodeRef nodeToUnpublish, Map channelProperties)
+ {
+ NodeService nodeService = getNodeService();
+ if (nodeService.hasAspect(nodeToUnpublish, FlickrPublishingModel.ASPECT_ASSET))
+ {
+ String assetId = (String) nodeService.getProperty(nodeToUnpublish, PublishingModel.PROP_ASSET_ID);
+ if (assetId != null)
+ {
+ Connection connection = flickrHelper.getConnectionFromChannelProps(channelProperties);
+ MediaOperations mediaOps = connection.getApi().mediaOperations();
+ mediaOps.deletePhoto(assetId);
+ nodeService.removeAspect(nodeToUnpublish, FlickrPublishingModel.ASPECT_ASSET);
+ nodeService.removeAspect(nodeToUnpublish, PublishingModel.ASPECT_ASSET);
+ }
}
- return url;
}
@Override
diff --git a/source/java/org/alfresco/repo/publishing/flickr/FlickrPublishAction.java b/source/java/org/alfresco/repo/publishing/flickr/FlickrPublishAction.java
deleted file mode 100644
index 269330b772..0000000000
--- a/source/java/org/alfresco/repo/publishing/flickr/FlickrPublishAction.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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 .
- */
-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.PublishingModel;
-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.PhotoInfo;
-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 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;
- }
- List tags = taggingService.getTags(nodeToPublish);
- String[] tagArray = tags.toArray(new String[tags.size()]);
-
- MediaOperations mediaOps = connection.getApi().mediaOperations();
- String id = mediaOps.postPhoto(res, title, description, tagArray);
-
- //Store info onto the published node...
- nodeService.addAspect(nodeToPublish, FlickrPublishingModel.ASPECT_ASSET, null);
- log.info("Posted image " + name + " to Flickr with id " + id);
- nodeService.setProperty(nodeToPublish, PublishingModel.PROP_ASSET_ID, id);
-
- PhotoInfo photoInfo = mediaOps.getPhoto(id);
- String url = photoInfo.getPrimaryUrl();
- log.info("Photo url = " + url);
- nodeService.setProperty(nodeToPublish, PublishingModel.PROP_ASSET_URL, url);
- }
- finally
- {
- if (deleteContentFileOnCompletion)
- {
- contentFile.delete();
- }
- }
- }
- }
-
- @Override
- protected void addParameterDefinitions(List paramList)
- {
- // TODO Auto-generated method stub
-
- }
-}
diff --git a/source/java/org/alfresco/repo/publishing/flickr/FlickrPublishingHelper.java b/source/java/org/alfresco/repo/publishing/flickr/FlickrPublishingHelper.java
index 63dcc3cc54..ca9b69e870 100644
--- a/source/java/org/alfresco/repo/publishing/flickr/FlickrPublishingHelper.java
+++ b/source/java/org/alfresco/repo/publishing/flickr/FlickrPublishingHelper.java
@@ -18,12 +18,16 @@
*/
package org.alfresco.repo.publishing.flickr;
+import java.io.Serializable;
+import java.util.Map;
+
import org.alfresco.repo.node.encryption.MetadataEncryptor;
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.alfresco.service.namespace.QName;
import org.springframework.social.connect.Connection;
import org.springframework.social.oauth1.OAuthToken;
@@ -53,6 +57,23 @@ public class FlickrPublishingHelper
return connectionFactory;
}
+ public Connection getConnectionFromChannelProps(Map channelProperties)
+ {
+ Connection connection = null;
+ String tokenValue = (String) encryptor.decrypt(PublishingModel.PROP_OAUTH1_TOKEN_VALUE, channelProperties
+ .get(PublishingModel.PROP_OAUTH1_TOKEN_VALUE));
+ String tokenSecret = (String) encryptor.decrypt(PublishingModel.PROP_OAUTH1_TOKEN_SECRET, channelProperties
+ .get(PublishingModel.PROP_OAUTH1_TOKEN_SECRET));
+ Boolean danceComplete = (Boolean) channelProperties.get(PublishingModel.PROP_AUTHORISATION_COMPLETE);
+
+ if (danceComplete)
+ {
+ OAuthToken token = new OAuthToken(tokenValue, tokenSecret);
+ connection = connectionFactory.createConnection(token);
+ }
+ return connection;
+ }
+
public Connection getConnectionForPublishNode(NodeRef publishNode)
{
Connection connection = null;
@@ -60,17 +81,7 @@ public class FlickrPublishingHelper
if (nodeService.exists(channelNode)
&& nodeService.hasAspect(channelNode, PublishingModel.ASPECT_OAUTH1_DELIVERY_CHANNEL))
{
- String tokenValue = (String) encryptor.decrypt(PublishingModel.PROP_OAUTH1_TOKEN_VALUE, nodeService
- .getProperty(channelNode, PublishingModel.PROP_OAUTH1_TOKEN_VALUE));
- String tokenSecret = (String) encryptor.decrypt(PublishingModel.PROP_OAUTH1_TOKEN_SECRET, 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);
- }
+ connection = getConnectionFromChannelProps(nodeService.getProperties(channelNode));
}
return connection;
}
diff --git a/source/java/org/alfresco/repo/publishing/flickr/FlickrTest.java b/source/java/org/alfresco/repo/publishing/flickr/FlickrTest.java
index 4bf2c7ce15..d6d3f81efa 100644
--- a/source/java/org/alfresco/repo/publishing/flickr/FlickrTest.java
+++ b/source/java/org/alfresco/repo/publishing/flickr/FlickrTest.java
@@ -32,8 +32,6 @@ 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;
@@ -100,6 +98,8 @@ public class FlickrTest extends BaseSpringTest
//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 String channelName = "FlickrTestChannel_" + GUID.generate();
+ final FlickrChannelType channelType = (FlickrChannelType) channelService.getChannelType(FlickrChannelType.ID);
final NodeRef contentNode = transactionHelper.doInTransaction(new RetryingTransactionCallback()
{
public NodeRef execute() throws Throwable
@@ -109,7 +109,7 @@ public class FlickrTest extends BaseSpringTest
props.put(PublishingModel.PROP_OAUTH1_TOKEN_SECRET, "YOUR_OAUTH_TOKEN_SECRET");
props.put(PublishingModel.PROP_AUTHORISATION_COMPLETE, Boolean.TRUE);
- Channel channel = channelService.createChannel(FlickrChannelType.ID, "FlickrTestChannel_" + GUID.generate(), props);
+ Channel channel = channelService.createChannel(FlickrChannelType.ID, channelName, 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);
@@ -132,9 +132,9 @@ public class FlickrTest extends BaseSpringTest
{
public NodeRef execute() throws Throwable
{
- ActionService actionService = serviceRegistry.getActionService();
- Action publishAction = actionService.createAction(FlickrPublishAction.NAME);
- actionService.executeAction(publishAction, contentNode);
+ Channel channel = channelService.getChannelByName(channelName);
+ channelType.publish(contentNode, channel.getProperties());
+
Map props = nodeService.getProperties(contentNode);
Assert.assertTrue(nodeService.hasAspect(contentNode, FlickrPublishingModel.ASPECT_ASSET));
Assert.assertNotNull(props.get(PublishingModel.PROP_ASSET_ID));
@@ -143,8 +143,8 @@ public class FlickrTest extends BaseSpringTest
System.out.println("Asset id: " + props.get(PublishingModel.PROP_ASSET_ID));
System.out.println("Asset URL: " + props.get(PublishingModel.PROP_ASSET_URL));
- Action unpublishAction = actionService.createAction(FlickrUnpublishAction.NAME);
- actionService.executeAction(unpublishAction, contentNode);
+ channelType.unpublish(contentNode, channel.getProperties());
+
props = nodeService.getProperties(contentNode);
Assert.assertFalse(nodeService.hasAspect(contentNode, FlickrPublishingModel.ASPECT_ASSET));
Assert.assertFalse(nodeService.hasAspect(contentNode, PublishingModel.ASPECT_ASSET));
diff --git a/source/java/org/alfresco/repo/publishing/flickr/FlickrUnpublishAction.java b/source/java/org/alfresco/repo/publishing/flickr/FlickrUnpublishAction.java
deleted file mode 100644
index 8d6df19d27..0000000000
--- a/source/java/org/alfresco/repo/publishing/flickr/FlickrUnpublishAction.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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 .
- */
-package org.alfresco.repo.publishing.flickr;
-
-import java.util.List;
-
-import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
-import org.alfresco.repo.publishing.PublishingModel;
-import org.alfresco.repo.publishing.flickr.springsocial.api.Flickr;
-import org.alfresco.repo.publishing.flickr.springsocial.api.MediaOperations;
-import org.alfresco.service.cmr.action.Action;
-import org.alfresco.service.cmr.action.ParameterDefinition;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.springframework.social.connect.Connection;
-
-public class FlickrUnpublishAction extends ActionExecuterAbstractBase
-{
- public static final String NAME = "unpublish_flickr";
-
- private NodeService nodeService;
- private FlickrPublishingHelper flickrHelper;
-
- public void setFlickrHelper(FlickrPublishingHelper helper)
- {
- this.flickrHelper = helper;
- }
-
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
-
- @Override
- protected void executeImpl(Action action, NodeRef nodeRef)
- {
- if (nodeService.hasAspect(nodeRef, FlickrPublishingModel.ASPECT_ASSET))
- {
- String assetId = (String) nodeService.getProperty(nodeRef, PublishingModel.PROP_ASSET_ID);
- if (assetId != null)
- {
- Connection connection = flickrHelper.getConnectionForPublishNode(nodeRef);
- MediaOperations mediaOps = connection.getApi().mediaOperations();
- mediaOps.deletePhoto(assetId);
- nodeService.removeAspect(nodeRef, FlickrPublishingModel.ASPECT_ASSET);
- nodeService.removeAspect(nodeRef, PublishingModel.ASPECT_ASSET);
- }
- }
- }
-
- @Override
- protected void addParameterDefinitions(List paramList)
- {
- //Deliberately empty
- }
-}
diff --git a/source/java/org/alfresco/repo/publishing/flickr/springsocial/api/impl/FlickrTemplate.java b/source/java/org/alfresco/repo/publishing/flickr/springsocial/api/impl/FlickrTemplate.java
index eae3de2947..0571c6b019 100644
--- a/source/java/org/alfresco/repo/publishing/flickr/springsocial/api/impl/FlickrTemplate.java
+++ b/source/java/org/alfresco/repo/publishing/flickr/springsocial/api/impl/FlickrTemplate.java
@@ -40,6 +40,7 @@ import org.springframework.util.MultiValueMap;
public class FlickrTemplate extends AbstractOAuth1ApiBinding implements Flickr, FlickrHelper
{
private static final String DEFAULT_ENDPOINT = "http://api.flickr.com/services/";
+// private static final String DEFAULT_ENDPOINT = "https://secure.flickr.com/services/";
private static String endpoint = DEFAULT_ENDPOINT;
diff --git a/source/java/org/alfresco/repo/publishing/linkedin/LinkedInChannelType.java b/source/java/org/alfresco/repo/publishing/linkedin/LinkedInChannelType.java
index 4ec04edaff..06bd537a9b 100644
--- a/source/java/org/alfresco/repo/publishing/linkedin/LinkedInChannelType.java
+++ b/source/java/org/alfresco/repo/publishing/linkedin/LinkedInChannelType.java
@@ -20,11 +20,6 @@ package org.alfresco.repo.publishing.linkedin;
import static org.alfresco.repo.publishing.linkedin.LinkedInPublishingModel.TYPE_DELIVERY_CHANNEL;
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
import org.alfresco.repo.publishing.AbstractOAuth1ChannelType;
import org.alfresco.repo.publishing.linkedin.springsocial.api.AlfrescoLinkedIn;
import org.alfresco.service.cmr.publishing.channels.Channel;
@@ -73,30 +68,6 @@ public class LinkedInChannelType extends AbstractOAuth1ChannelType getSupportedContentTypes()
- {
- return Collections.emptySet();
- }
-
- @Override
- public Set getSupportedMimeTypes()
- {
- return Collections.emptySet();
- }
-
- @Override
- public void publish(NodeRef nodeToPublish, Map properties)
- {
- //NO-OP
- }
-
- @Override
- public void unpublish(NodeRef nodeToUnpublish, Map properties)
- {
- //NO-OP
- }
-
@Override
public int getMaximumStatusLength()
{
@@ -104,7 +75,7 @@ public class LinkedInChannelType extends AbstractOAuth1ChannelType properties)
+ public void sendStatusUpdate(Channel channel, String status)
{
NodeRef channelNode = new NodeRef(channel.getId());
Connection connection = getConnectionForChannel(channelNode);
@@ -118,6 +89,6 @@ public class LinkedInChannelType extends AbstractOAuth1ChannelType addParameter(Map parameters, String name, String value)
diff --git a/source/java/org/alfresco/repo/publishing/slideshare/SlideShareChannelType.java b/source/java/org/alfresco/repo/publishing/slideshare/SlideShareChannelType.java
index 12c93a50b9..a4b57c73f4 100644
--- a/source/java/org/alfresco/repo/publishing/slideshare/SlideShareChannelType.java
+++ b/source/java/org/alfresco/repo/publishing/slideshare/SlideShareChannelType.java
@@ -18,43 +18,70 @@
*/
package org.alfresco.repo.publishing.slideshare;
+import java.io.File;
import java.io.Serializable;
-import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.model.ContentModel;
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.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.service.namespace.QName;
+import org.alfresco.util.Pair;
+import org.alfresco.util.TempFileProvider;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.benfante.jslideshare.SlideShareAPI;
+import com.benfante.jslideshare.messages.SlideshowInfo;
public class SlideShareChannelType extends AbstractChannelType
{
public final static String ID = "slideshare";
- private NodeService nodeService;
- private ActionService actionService;
+ private final static Log log = LogFactory.getLog(SlideShareChannelType.class);
+
+ private final static int STATUS_QUEUED = 0;
+ // private final static int STATUS_CONVERTING = 1;
+ private final static int STATUS_SUCCEEDED = 2;
+ private final static int STATUS_FAILED = 3;
+ private final static int STATUS_TIMED_OUT = 10;
+ private static final String ERROR_SLIDESHARE_CONVERSION_FAILED = "publish.slideshare.conversionFailed";
+ private static final String ERROR_SLIDESHARE_CONVERSION_TIMED_OUT = "publish.slideshare.conversionTimedOut";
+
private SlideSharePublishingHelper publishingHelper;
+ private ContentService contentService;
+ private TaggingService taggingService;
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
-
- public void setActionService(ActionService actionService)
- {
- this.actionService = actionService;
- }
+ private long timeoutMilliseconds = 40L * 60L * 1000L; // 40 mins default
public void setPublishingHelper(SlideSharePublishingHelper publishingHelper)
{
this.publishingHelper = publishingHelper;
}
+ public void setContentService(ContentService contentService)
+ {
+ this.contentService = contentService;
+ }
+
+ public void setTaggingService(TaggingService taggingService)
+ {
+ this.taggingService = taggingService;
+ }
+
+ public void setTimeoutMilliseconds(long timeoutMilliseconds)
+ {
+ this.timeoutMilliseconds = timeoutMilliseconds;
+ }
+
@Override
public boolean canPublish()
{
@@ -85,12 +112,6 @@ public class SlideShareChannelType extends AbstractChannelType
return ID;
}
- @Override
- public Set getSupportedContentTypes()
- {
- return Collections.emptySet();
- }
-
@Override
public Set getSupportedMimeTypes()
{
@@ -100,31 +121,152 @@ public class SlideShareChannelType extends AbstractChannelType
@Override
public void publish(NodeRef nodeToPublish, Map properties)
{
- Action publishAction = actionService.createAction(SlideSharePublishAction.NAME);
- actionService.executeAction(publishAction, nodeToPublish);
+ NodeService nodeService = getNodeService();
+ Pair usernamePassword = publishingHelper
+ .getSlideShareCredentialsFromChannelProperties(properties);
+ if (usernamePassword == null)
+ {
+ throw new AlfrescoRuntimeException("publish.failed.no_credentials_found");
+ }
+ SlideShareAPI api = publishingHelper
+ .getSlideShareApi(usernamePassword.getFirst(), usernamePassword.getSecond());
+
+ ContentReader reader = contentService.getReader(nodeToPublish, ContentModel.PROP_CONTENT);
+ if (reader.exists())
+ {
+ File contentFile;
+ String mime = reader.getMimetype();
+
+ String extension = publishingHelper.getAllowedMimeTypes().get(mime);
+ if (extension == null)
+ extension = "";
+
+ boolean deleteContentFileOnCompletion = false;
+
+ // 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", extension, tempDir);
+ reader.getContent(contentFile);
+ deleteContentFileOnCompletion = true;
+
+ try
+ {
+
+ 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;
+ }
+
+ List tagList = taggingService.getTags(nodeToPublish);
+ StringBuilder tags = new StringBuilder();
+ for (String tag : tagList)
+ {
+ tags.append(tag);
+ tags.append(' ');
+ }
+
+ String assetId = api.uploadSlideshow(usernamePassword.getFirst(), usernamePassword.getSecond(), title,
+ contentFile, description, tags.toString(), false, false, false, false, false);
+
+ String url = null;
+ int status = STATUS_QUEUED;
+ boolean finished = false;
+ long timeoutTime = System.currentTimeMillis() + timeoutMilliseconds;
+ // Fetch the slideshow info every 30 seconds until we timeout
+ while (!finished)
+ {
+ SlideshowInfo slideInfo = api.getSlideshowInfo(assetId, "");
+ if (slideInfo != null)
+ {
+ if (url == null)
+ {
+ url = slideInfo.getUrl();
+ if (log.isInfoEnabled())
+ {
+ log.info("SlideShare has provided a URL for asset " + assetId + ": " + url);
+ }
+ }
+ status = slideInfo.getStatus();
+ }
+ finished = (status == STATUS_FAILED || status == STATUS_SUCCEEDED);
+
+ if (!finished)
+ {
+ if (System.currentTimeMillis() < timeoutTime)
+ {
+ try
+ {
+ Thread.sleep(30000L);
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+ else
+ {
+ status = STATUS_TIMED_OUT;
+ finished = true;
+ }
+ }
+ }
+ if (status == STATUS_SUCCEEDED)
+ {
+ if (log.isInfoEnabled())
+ {
+ log.info("File " + name + " has been published to SlideShare with id " + assetId + " at URL "
+ + url);
+ }
+ nodeService.addAspect(nodeToPublish, SlideSharePublishingModel.ASPECT_ASSET, null);
+ nodeService.setProperty(nodeToPublish, PublishingModel.PROP_ASSET_ID, assetId);
+ nodeService.setProperty(nodeToPublish, PublishingModel.PROP_ASSET_URL, url);
+ }
+ else
+ {
+ throw new AlfrescoRuntimeException(status == STATUS_FAILED ? ERROR_SLIDESHARE_CONVERSION_FAILED
+ : ERROR_SLIDESHARE_CONVERSION_TIMED_OUT);
+ }
+ }
+ finally
+ {
+ if (deleteContentFileOnCompletion)
+ {
+ contentFile.delete();
+ }
+ }
+ }
}
@Override
public void unpublish(NodeRef nodeToUnpublish, Map properties)
{
- Action unpublishAction = actionService.createAction(SlideShareUnpublishAction.NAME);
- actionService.executeAction(unpublishAction, nodeToUnpublish);
- }
-
- @Override
- public void updateStatus(Channel channel, String status, Map properties)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getNodeUrl(NodeRef node)
- {
- String url = null;
- if (node != null && nodeService.exists(node) && nodeService.hasAspect(node, SlideSharePublishingModel.ASPECT_ASSET))
+ NodeService nodeService = getNodeService();
+ if (nodeService.hasAspect(nodeToUnpublish, SlideSharePublishingModel.ASPECT_ASSET))
{
- url = (String)nodeService.getProperty(node, PublishingModel.PROP_ASSET_URL);
+ String assetId = (String) nodeService.getProperty(nodeToUnpublish, PublishingModel.PROP_ASSET_ID);
+ if (assetId != null)
+ {
+ Pair usernamePassword = publishingHelper
+ .getSlideShareCredentialsFromChannelProperties(properties);
+ if (usernamePassword == null)
+ {
+ throw new AlfrescoRuntimeException("publish.failed.no_credentials_found");
+ }
+ SlideShareApi api = publishingHelper.getSlideShareApi(usernamePassword.getFirst(), usernamePassword
+ .getSecond());
+
+ api.deleteSlideshow(usernamePassword.getFirst(), usernamePassword.getSecond(), assetId);
+ nodeService.removeAspect(nodeToUnpublish, SlideSharePublishingModel.ASPECT_ASSET);
+ nodeService.removeAspect(nodeToUnpublish, PublishingModel.ASPECT_ASSET);
+ }
}
- return url;
}
}
diff --git a/source/java/org/alfresco/repo/publishing/slideshare/SlideShareConnectorImpl.java b/source/java/org/alfresco/repo/publishing/slideshare/SlideShareConnectorImpl.java
new file mode 100644
index 0000000000..157e306b3c
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/slideshare/SlideShareConnectorImpl.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco, but is derived from a file
+ * Copyright 2008 The JSlideShare Team
+ *
+ * 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
+ *
+ * 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.
+ */
+
+package org.alfresco.repo.publishing.slideshare;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.methods.multipart.StringPart;
+import org.apache.log4j.Logger;
+
+import com.benfante.jslideshare.SlideShareConnector;
+import com.benfante.jslideshare.SlideShareErrorException;
+
+public class SlideShareConnectorImpl implements SlideShareConnector
+{
+
+ private static final Logger logger = Logger.getLogger(SlideShareConnectorImpl.class);
+
+ private String apiKey;
+ private String sharedSecret;
+ private HttpClient httpClient;
+
+ public SlideShareConnectorImpl()
+ {
+ httpClient = new HttpClient();
+ httpClient.setHttpConnectionManager(new MultiThreadedHttpConnectionManager());
+ }
+
+ public SlideShareConnectorImpl(String apiKey, String sharedSecret)
+ {
+ this();
+ this.apiKey = apiKey;
+ this.sharedSecret = sharedSecret;
+ }
+
+ public String getApiKey()
+ {
+ return apiKey;
+ }
+
+ public void setApiKey(String apiKey)
+ {
+ this.apiKey = apiKey;
+ }
+
+ public String getSharedSecret()
+ {
+ return sharedSecret;
+ }
+
+ public void setSharedSecret(String sharedSecret)
+ {
+ this.sharedSecret = sharedSecret;
+ }
+
+
+ public InputStream sendMessage(String url, Map parameters) throws IOException,
+ SlideShareErrorException
+ {
+ PostMethod method = new PostMethod(url);
+ method.addParameter("api_key", this.apiKey);
+ Iterator> entryIt = parameters.entrySet().iterator();
+ while (entryIt.hasNext())
+ {
+ Map.Entry entry = entryIt.next();
+ method.addParameter(entry.getKey(), entry.getValue());
+ }
+ Date now = new Date();
+ String ts = Long.toString(now.getTime() / 1000);
+ String hash = DigestUtils.shaHex(this.sharedSecret + ts).toLowerCase();
+ method.addParameter("ts", ts);
+ method.addParameter("hash", hash);
+ logger.debug("Sending POST message to " + method.getURI().getURI() + " with parameters "
+ + Arrays.toString(method.getParameters()));
+ int statusCode = httpClient.executeMethod(method);
+ if (statusCode != HttpStatus.SC_OK)
+ {
+ logger.debug("Server replied with a " + statusCode + " HTTP status code ("
+ + HttpStatus.getStatusText(statusCode) + ")");
+ throw new SlideShareErrorException(statusCode, HttpStatus.getStatusText(statusCode));
+ }
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(method.getResponseBodyAsString());
+ }
+ InputStream result = new ByteArrayInputStream(method.getResponseBody());
+ method.releaseConnection();
+ return result;
+ }
+
+ public InputStream sendMultiPartMessage(String url, Map parameters, Map files)
+ throws IOException, SlideShareErrorException
+ {
+ PostMethod method = new PostMethod(url);
+ List partList = new ArrayList();
+ partList.add(createStringPart("api_key", this.apiKey));
+ Date now = new Date();
+ String ts = Long.toString(now.getTime() / 1000);
+ String hash = DigestUtils.shaHex(this.sharedSecret + ts).toLowerCase();
+ partList.add(createStringPart("ts", ts));
+ partList.add(createStringPart("hash", hash));
+ Iterator> entryIt = parameters.entrySet().iterator();
+ while (entryIt.hasNext())
+ {
+ Map.Entry entry = entryIt.next();
+ partList.add(createStringPart(entry.getKey(), entry.getValue()));
+ }
+ Iterator> entryFileIt = files.entrySet().iterator();
+ while (entryFileIt.hasNext())
+ {
+ Map.Entry entry = entryFileIt.next();
+ partList.add(createFilePart(entry.getKey(), entry.getValue()));
+ }
+ MultipartRequestEntity requestEntity = new MultipartRequestEntity(partList.toArray(new Part[partList.size()]),
+ method.getParams());
+ method.setRequestEntity(requestEntity);
+ logger.debug("Sending multipart POST message to " + method.getURI().getURI() + " with parts " + partList);
+ int statusCode = httpClient.executeMethod(method);
+ if (statusCode != HttpStatus.SC_OK)
+ {
+ logger.debug("Server replied with a " + statusCode + " HTTP status code ("
+ + HttpStatus.getStatusText(statusCode) + ")");
+ throw new SlideShareErrorException(statusCode, HttpStatus.getStatusText(statusCode));
+ }
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(method.getResponseBodyAsString());
+ }
+ InputStream result = new ByteArrayInputStream(method.getResponseBody());
+ method.releaseConnection();
+ return result;
+ }
+
+ public InputStream sendGetMessage(String url, Map parameters) throws IOException,
+ SlideShareErrorException
+ {
+ GetMethod method = new GetMethod(url);
+ NameValuePair[] params = new NameValuePair[parameters.size() + 3];
+ int i = 0;
+ params[i++] = new NameValuePair("api_key", this.apiKey);
+ Iterator> entryIt = parameters.entrySet().iterator();
+ while (entryIt.hasNext())
+ {
+ Map.Entry entry = entryIt.next();
+ params[i++] = new NameValuePair(entry.getKey(), entry.getValue());
+ }
+ Date now = new Date();
+ String ts = Long.toString(now.getTime() / 1000);
+ String hash = DigestUtils.shaHex(this.sharedSecret + ts).toLowerCase();
+ params[i++] = new NameValuePair("ts", ts);
+ params[i++] = new NameValuePair("hash", hash);
+ method.setQueryString(params);
+ logger.debug("Sending GET message to " + method.getURI().getURI() + " with parameters "
+ + Arrays.toString(params));
+ int statusCode = httpClient.executeMethod(method);
+ if (statusCode != HttpStatus.SC_OK)
+ {
+ logger.debug("Server replied with a " + statusCode + " HTTP status code ("
+ + HttpStatus.getStatusText(statusCode) + ")");
+ throw new SlideShareErrorException(statusCode, HttpStatus.getStatusText(statusCode));
+ }
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(method.getResponseBodyAsString());
+ }
+ InputStream result = new ByteArrayInputStream(method.getResponseBody());
+ method.releaseConnection();
+ return result;
+ }
+
+ private StringPart createStringPart(String name, String value)
+ {
+ StringPart stringPart = new StringPart(name, value);
+ stringPart.setContentType(null);
+ stringPart.setTransferEncoding(null);
+ stringPart.setCharSet("UTF-8");
+ return stringPart;
+ }
+
+ private FilePart createFilePart(String name, File value) throws FileNotFoundException
+ {
+ FilePart filePart = new FilePart(name, value);
+ filePart.setTransferEncoding(null);
+ filePart.setCharSet(null);
+ return filePart;
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/publishing/slideshare/SlideSharePublishAction.java b/source/java/org/alfresco/repo/publishing/slideshare/SlideSharePublishAction.java
deleted file mode 100644
index 70f239572f..0000000000
--- a/source/java/org/alfresco/repo/publishing/slideshare/SlideSharePublishAction.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * 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 .
- */
-package org.alfresco.repo.publishing.slideshare;
-
-import java.io.File;
-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.publishing.PublishingModel;
-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.Pair;
-import org.alfresco.util.TempFileProvider;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import com.benfante.jslideshare.SlideShareAPI;
-import com.benfante.jslideshare.messages.SlideshowInfo;
-
-public class SlideSharePublishAction extends ActionExecuterAbstractBase
-{
- private final static Log log = LogFactory.getLog(SlideSharePublishAction.class);
- private final static int STATUS_QUEUED = 0;
- // private final static int STATUS_CONVERTING = 1;
- private final static int STATUS_SUCCEEDED = 2;
- private final static int STATUS_FAILED = 3;
- private final static int STATUS_TIMED_OUT = 10;
- public static final String NAME = "publish_slideshare";
- private static final String ERROR_SLIDESHARE_CONVERSION_FAILED = "publish.slideshare.conversionFailed";
- private static final String ERROR_SLIDESHARE_CONVERSION_TIMED_OUT = "publish.slideshare.conversionTimedOut";
-
- private NodeService nodeService;
- private ContentService contentService;
- private TaggingService taggingService;
- private SlideSharePublishingHelper slideShareHelper;
-
- private long timeoutMilliseconds = 40L * 60L * 1000L; // 40 mins default
-
- public void setSlideShareHelper(SlideSharePublishingHelper slideShareHelper)
- {
- this.slideShareHelper = slideShareHelper;
- }
-
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
-
- public void setContentService(ContentService contentService)
- {
- this.contentService = contentService;
- }
-
- public void setTaggingService(TaggingService taggingService)
- {
- this.taggingService = taggingService;
- }
-
- public void setTimeoutMilliseconds(long timeoutMilliseconds)
- {
- this.timeoutMilliseconds = timeoutMilliseconds;
- }
-
- @Override
- protected void executeImpl(Action action, NodeRef nodeRef)
- {
- Pair usernamePassword = slideShareHelper.getSlideShareCredentialsForNode(nodeRef);
- if (usernamePassword == null)
- {
- throw new AlfrescoRuntimeException("publish.failed.no_credentials_found");
- }
- SlideShareAPI api = slideShareHelper
- .getSlideShareApi(usernamePassword.getFirst(), usernamePassword.getSecond());
-
- ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
- if (reader.exists())
- {
- File contentFile;
- String mime = reader.getMimetype();
-
- String extension = slideShareHelper.getAllowedMimeTypes().get(mime);
- if (extension == null)
- extension = "";
-
- boolean deleteContentFileOnCompletion = false;
-
- // 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", extension, tempDir);
- reader.getContent(contentFile);
- deleteContentFileOnCompletion = true;
-
- try
- {
-
- String name = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
- String title = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE);
- if (title == null || title.length() == 0)
- {
- title = name;
- }
- String description = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_DESCRIPTION);
- if (description == null || description.length() == 0)
- {
- description = title;
- }
-
- List tagList = taggingService.getTags(nodeRef);
- StringBuilder tags = new StringBuilder();
- for (String tag : tagList)
- {
- tags.append(tag);
- tags.append(' ');
- }
-
- String assetId = api.uploadSlideshow(usernamePassword.getFirst(), usernamePassword.getSecond(), title,
- contentFile, description, tags.toString(), false, false, false, false, false);
-
- String url = null;
- int status = STATUS_QUEUED;
- boolean finished = false;
- long timeoutTime = System.currentTimeMillis() + timeoutMilliseconds;
- // Fetch the slideshow info every 5 seconds for 5 minutes...
- while (!finished)
- {
- SlideshowInfo slideInfo = api.getSlideshowInfo(assetId, "");
- if (slideInfo != null)
- {
- if (url == null)
- {
- url = slideInfo.getUrl();
- if (log.isInfoEnabled())
- {
- log.info("SlideShare has provided a URL for asset " + assetId + ": " + url);
- }
- }
- status = slideInfo.getStatus();
- }
- finished = (status == STATUS_FAILED || status == STATUS_SUCCEEDED);
-
- if (!finished)
- {
- if (System.currentTimeMillis() < timeoutTime)
- {
- try
- {
- Thread.sleep(30000L);
- }
- catch (InterruptedException e)
- {
- }
- }
- else
- {
- status = STATUS_TIMED_OUT;
- finished = true;
- }
- }
- }
- if (status == STATUS_SUCCEEDED)
- {
- if (log.isInfoEnabled())
- {
- log.info("File " + name + " has been published to SlideShare with id " + assetId + " at URL "
- + url);
- }
- nodeService.addAspect(nodeRef, SlideSharePublishingModel.ASPECT_ASSET, null);
- nodeService.setProperty(nodeRef, PublishingModel.PROP_ASSET_ID, assetId);
- nodeService.setProperty(nodeRef, PublishingModel.PROP_ASSET_URL, url);
- }
- else
- {
- throw new AlfrescoRuntimeException(status == STATUS_FAILED ? ERROR_SLIDESHARE_CONVERSION_FAILED
- : ERROR_SLIDESHARE_CONVERSION_TIMED_OUT);
- }
- }
- finally
- {
- if (deleteContentFileOnCompletion)
- {
- contentFile.delete();
- }
- }
- }
- }
-
- @Override
- protected void addParameterDefinitions(List paramList)
- {
- }
-}
diff --git a/source/java/org/alfresco/repo/publishing/slideshare/SlideSharePublishingHelper.java b/source/java/org/alfresco/repo/publishing/slideshare/SlideSharePublishingHelper.java
index e4a24b2b4b..a098b0201a 100644
--- a/source/java/org/alfresco/repo/publishing/slideshare/SlideSharePublishingHelper.java
+++ b/source/java/org/alfresco/repo/publishing/slideshare/SlideSharePublishingHelper.java
@@ -18,6 +18,7 @@
*/
package org.alfresco.repo.publishing.slideshare;
+import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;
@@ -25,8 +26,7 @@ import java.util.TreeMap;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.node.encryption.MetadataEncryptor;
import org.alfresco.repo.publishing.PublishingModel;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import com.benfante.jslideshare.SlideShareAPI;
@@ -52,15 +52,9 @@ public class SlideSharePublishingHelper
}
private Map allowedMimeTypes = Collections.unmodifiableMap(DEFAULT_MIME_TYPES);
- private NodeService nodeService;
private SlideShareConnector slideshareConnector;
private MetadataEncryptor encryptor;
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
-
public void setSlideshareConnector(SlideShareConnector slideshareConnector)
{
this.slideshareConnector = slideshareConnector;
@@ -91,23 +85,16 @@ public class SlideSharePublishingHelper
return new SlideShareApiImpl(slideshareConnector);
}
- public Pair getSlideShareCredentialsForNode(NodeRef publishNode)
+ public Pair getSlideShareCredentialsFromChannelProperties(Map channelProperties)
{
Pair result = null;
- if (nodeService.exists(publishNode))
+ String username = (String) encryptor.decrypt(PublishingModel.PROP_CHANNEL_USERNAME,
+ channelProperties.get(PublishingModel.PROP_CHANNEL_USERNAME));
+ String password = (String) encryptor.decrypt(PublishingModel.PROP_CHANNEL_PASSWORD,
+ channelProperties.get(PublishingModel.PROP_CHANNEL_PASSWORD));
+ if (username != null && password != null)
{
- NodeRef parent = nodeService.getPrimaryParent(publishNode).getParentRef();
- if (nodeService.hasAspect(parent, SlideSharePublishingModel.ASPECT_DELIVERY_CHANNEL))
- {
- String username = (String) encryptor.decrypt(PublishingModel.PROP_CHANNEL_USERNAME, nodeService
- .getProperty(parent, PublishingModel.PROP_CHANNEL_USERNAME));
- String password = (String) encryptor.decrypt(PublishingModel.PROP_CHANNEL_PASSWORD, nodeService
- .getProperty(parent, PublishingModel.PROP_CHANNEL_PASSWORD));
- if (username != null && password != null)
- {
- result = new Pair(username, password);
- }
- }
+ result = new Pair(username, password);
}
return result;
}
diff --git a/source/java/org/alfresco/repo/publishing/slideshare/SlideShareTest.java b/source/java/org/alfresco/repo/publishing/slideshare/SlideShareTest.java
index 0bc043fd42..8109f6632c 100644
--- a/source/java/org/alfresco/repo/publishing/slideshare/SlideShareTest.java
+++ b/source/java/org/alfresco/repo/publishing/slideshare/SlideShareTest.java
@@ -36,8 +36,6 @@ 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;
@@ -115,6 +113,8 @@ public class SlideShareTest extends BaseSpringTest
// text "YOUR_USER_NAME" and "YOUR_PASSWORD" appear.
public void xtestSlideSharePublishAndUnpublishActions() throws Exception
{
+ final SlideShareChannelType channelType = (SlideShareChannelType)channelService.getChannelType(SlideShareChannelType.ID);
+ final String channelName = GUID.generate();
final List nodes = transactionHelper.doInTransaction(new RetryingTransactionCallback>()
{
public List execute() throws Throwable
@@ -127,7 +127,7 @@ public class SlideShareTest extends BaseSpringTest
// "YOUR_PASSWORD");
props.put(PublishingModel.PROP_CHANNEL_USERNAME, "YOUR_USER_NAME");
props.put(PublishingModel.PROP_CHANNEL_PASSWORD, "YOUR_PASSWORD");
- Channel channel = channelService.createChannel(SlideShareChannelType.ID, GUID.generate(), props);
+ Channel channel = channelService.createChannel(SlideShareChannelType.ID, channelName, props);
NodeRef channelNode = channel.getNodeRef();
@@ -162,29 +162,31 @@ public class SlideShareTest extends BaseSpringTest
{
public NodeRef execute() throws Throwable
{
+ Map channelProperties = channelService.getChannelByName(channelName).getProperties();
for (NodeRef node : nodes)
{
- ActionService actionService = serviceRegistry.getActionService();
- Action publishAction = actionService.createAction(SlideSharePublishAction.NAME);
- actionService.executeAction(publishAction, node);
+ channelType.publish(node, channelProperties);
Map props = nodeService.getProperties(node);
Assert.assertTrue(nodeService.hasAspect(node, SlideSharePublishingModel.ASPECT_ASSET));
Assert.assertNotNull(props.get(PublishingModel.PROP_ASSET_ID));
Assert.assertNotNull(props.get(PublishingModel.PROP_ASSET_URL));
- System.out.println("Test file: " + testNodeMap.get(node));
+ System.out.println("Published test file: " + testNodeMap.get(node));
System.out.println("SlideShare id: " + props.get(PublishingModel.PROP_ASSET_ID));
System.out.println("SlideShare URL: " + props.get(PublishingModel.PROP_ASSET_URL));
}
- // Action unpublishAction =
- // actionService.createAction(SlideShareUnpublishAction.NAME);
- // actionService.executeAction(unpublishAction, node);
- // props = nodeService.getProperties(node);
- // Assert.assertFalse(nodeService.hasAspect(node,
- // SlideSharePublishingModel.ASPECT_ASSET));
- // Assert.assertNull(props.get(SlideSharePublishingModel.PROP_ASSET_ID));
- // Assert.assertNull(props.get(SlideSharePublishingModel.PROP_ASSET_URL));
+ for (NodeRef node : nodes)
+ {
+ Map props = nodeService.getProperties(node);
+ channelType.unpublish(node, channelProperties);
+ props = nodeService.getProperties(node);
+ Assert.assertFalse(nodeService.hasAspect(node, SlideSharePublishingModel.ASPECT_ASSET));
+ Assert.assertNull(props.get(PublishingModel.PROP_ASSET_ID));
+ Assert.assertNull(props.get(PublishingModel.PROP_ASSET_URL));
+
+ System.out.println("Unpublished test file: " + testNodeMap.get(node));
+ }
return null;
}
});
diff --git a/source/java/org/alfresco/repo/publishing/slideshare/SlideShareUnpublishAction.java b/source/java/org/alfresco/repo/publishing/slideshare/SlideShareUnpublishAction.java
deleted file mode 100644
index ee3569d18f..0000000000
--- a/source/java/org/alfresco/repo/publishing/slideshare/SlideShareUnpublishAction.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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 .
- */
-package org.alfresco.repo.publishing.slideshare;
-
-import java.util.List;
-
-import org.alfresco.error.AlfrescoRuntimeException;
-import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
-import org.alfresco.repo.publishing.PublishingModel;
-import org.alfresco.service.cmr.action.Action;
-import org.alfresco.service.cmr.action.ParameterDefinition;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.util.Pair;
-
-public class SlideShareUnpublishAction extends ActionExecuterAbstractBase
-{
- public static final String NAME = "unpublish_slideshare";
-
- private NodeService nodeService;
- private SlideSharePublishingHelper slideShareHelper;
-
- public void setSlideShareHelper(SlideSharePublishingHelper slideShareHelper)
- {
- this.slideShareHelper = slideShareHelper;
- }
-
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
-
- @Override
- protected void executeImpl(Action action, NodeRef nodeRef)
- {
- if (nodeService.hasAspect(nodeRef, SlideSharePublishingModel.ASPECT_ASSET))
- {
- String assetId = (String) nodeService.getProperty(nodeRef, PublishingModel.PROP_ASSET_ID);
- if (assetId != null)
- {
- Pair usernamePassword = slideShareHelper.getSlideShareCredentialsForNode(nodeRef);
- if (usernamePassword == null)
- {
- throw new AlfrescoRuntimeException("publish.failed.no_credentials_found");
- }
- SlideShareApi api = slideShareHelper.getSlideShareApi(
- usernamePassword.getFirst(), usernamePassword.getSecond());
-
- api.deleteSlideshow(usernamePassword.getFirst(), usernamePassword.getSecond(), assetId);
- nodeService.removeAspect(nodeRef, SlideSharePublishingModel.ASPECT_ASSET);
- nodeService.removeAspect(nodeRef, PublishingModel.ASPECT_ASSET);
- }
- }
- }
-
- @Override
- protected void addParameterDefinitions(List paramList)
- {
- }
-}
diff --git a/source/java/org/alfresco/repo/publishing/test/TestChannelType1.java b/source/java/org/alfresco/repo/publishing/test/TestChannelType1.java
index fd6e1804e7..1a3f2532c3 100644
--- a/source/java/org/alfresco/repo/publishing/test/TestChannelType1.java
+++ b/source/java/org/alfresco/repo/publishing/test/TestChannelType1.java
@@ -99,7 +99,7 @@ public class TestChannelType1 extends AbstractChannelType
}
@Override
- public void updateStatus(Channel channel, String status, Map properties)
+ public void sendStatusUpdate(Channel channel, String status)
{
//Deliberately blank
}
diff --git a/source/java/org/alfresco/repo/publishing/test/TestChannelType2.java b/source/java/org/alfresco/repo/publishing/test/TestChannelType2.java
index 92941d59ed..1e08fe98ba 100644
--- a/source/java/org/alfresco/repo/publishing/test/TestChannelType2.java
+++ b/source/java/org/alfresco/repo/publishing/test/TestChannelType2.java
@@ -99,7 +99,7 @@ public class TestChannelType2 extends AbstractChannelType
}
@Override
- public void updateStatus(Channel channel, String status, Map properties)
+ public void sendStatusUpdate(Channel channel, String status)
{
//Deliberately blank
}
diff --git a/source/java/org/alfresco/repo/publishing/test/TestChannelType3.java b/source/java/org/alfresco/repo/publishing/test/TestChannelType3.java
index 92099149de..0a86c44fae 100644
--- a/source/java/org/alfresco/repo/publishing/test/TestChannelType3.java
+++ b/source/java/org/alfresco/repo/publishing/test/TestChannelType3.java
@@ -99,7 +99,7 @@ public class TestChannelType3 extends AbstractChannelType
}
@Override
- public void updateStatus(Channel channel, String status, Map properties)
+ public void sendStatusUpdate(Channel channel, String status)
{
//Deliberately blank
}
diff --git a/source/java/org/alfresco/repo/publishing/twitter/TwitterChannelType.java b/source/java/org/alfresco/repo/publishing/twitter/TwitterChannelType.java
index d601c9aa5c..2afa24a9a6 100644
--- a/source/java/org/alfresco/repo/publishing/twitter/TwitterChannelType.java
+++ b/source/java/org/alfresco/repo/publishing/twitter/TwitterChannelType.java
@@ -18,11 +18,6 @@
*/
package org.alfresco.repo.publishing.twitter;
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
import org.alfresco.repo.publishing.AbstractOAuth1ChannelType;
import org.alfresco.service.cmr.publishing.channels.Channel;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -67,30 +62,6 @@ public class TwitterChannelType extends AbstractOAuth1ChannelType
return ID;
}
- @Override
- public Set getSupportedContentTypes()
- {
- return Collections.emptySet();
- }
-
- @Override
- public Set getSupportedMimeTypes()
- {
- return Collections.emptySet();
- }
-
- @Override
- public void publish(NodeRef nodeToPublish, Map properties)
- {
- //NO-OP
- }
-
- @Override
- public void unpublish(NodeRef nodeToUnpublish, Map properties)
- {
- //NO-OP
- }
-
@Override
public int getMaximumStatusLength()
{
@@ -98,7 +69,7 @@ public class TwitterChannelType extends AbstractOAuth1ChannelType
}
@Override
- public void updateStatus(Channel channel, String status, Map properties)
+ public void sendStatusUpdate(Channel channel, String status)
{
Connection connection = getConnectionForChannel(channel.getNodeRef());
if (log.isInfoEnabled())
@@ -111,7 +82,7 @@ public class TwitterChannelType extends AbstractOAuth1ChannelType
@Override
public String getNodeUrl(NodeRef node)
{
- throw new UnsupportedOperationException();
+ return null;
}
}
diff --git a/source/java/org/alfresco/repo/publishing/youtube/YouTubeChannelType.java b/source/java/org/alfresco/repo/publishing/youtube/YouTubeChannelType.java
index 7fd89325e4..44338189e0 100644
--- a/source/java/org/alfresco/repo/publishing/youtube/YouTubeChannelType.java
+++ b/source/java/org/alfresco/repo/publishing/youtube/YouTubeChannelType.java
@@ -18,49 +18,84 @@
*/
package org.alfresco.repo.publishing.youtube;
+import java.io.File;
+import java.io.IOException;
import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.repo.content.filestore.FileContentReader;
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.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.service.namespace.QName;
+import org.alfresco.util.TempFileProvider;
import org.alfresco.util.collections.CollectionUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.google.gdata.client.media.ResumableGDataFileUploader;
+import com.google.gdata.client.uploader.ProgressListener;
+import com.google.gdata.client.uploader.ResumableHttpFileUploader;
+import com.google.gdata.client.youtube.YouTubeService;
+import com.google.gdata.data.media.MediaFileSource;
+import com.google.gdata.data.media.mediarss.MediaCategory;
+import com.google.gdata.data.media.mediarss.MediaDescription;
+import com.google.gdata.data.media.mediarss.MediaKeywords;
+import com.google.gdata.data.media.mediarss.MediaTitle;
+import com.google.gdata.data.youtube.VideoEntry;
+import com.google.gdata.data.youtube.YouTubeMediaGroup;
+import com.google.gdata.data.youtube.YouTubeNamespace;
+import com.google.gdata.util.ServiceException;
public class YouTubeChannelType extends AbstractChannelType
{
+ private final static Log log = LogFactory.getLog(YouTubeChannelType.class);
private final static Set 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
- );
-
+ 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);
+
+ public static final String RESUMABLE_UPLOAD_URL = "http://uploads.gdata.youtube.com/resumable/feeds/api/users/default/uploads";
+
+ /** Time interval at which upload task will notify about the progress */
+ private static final int PROGRESS_UPDATE_INTERVAL = 1000;
+
+ /** Max size for each upload chunk */
+ private static final int DEFAULT_CHUNK_SIZE = 10000000;
+
private Set supportedMimeTypes = DEFAULT_SUPPORTED_MIME_TYPES;
public final static String ID = "youtube";
- private NodeService nodeService;
- private ActionService actionService;
-
- public void setNodeService(NodeService nodeService)
+ private YouTubePublishingHelper youTubeHelper;
+ private ContentService contentService;
+ private TaggingService taggingService;
+
+ public void setYouTubeHelper(YouTubePublishingHelper youTubeHelper)
{
- this.nodeService = nodeService;
+ this.youTubeHelper = youTubeHelper;
}
- public void setActionService(ActionService actionService)
+ public void setContentService(ContentService contentService)
{
- this.actionService = actionService;
+ this.contentService = contentService;
+ }
+
+ public void setTaggingService(TaggingService taggingService)
+ {
+ this.taggingService = taggingService;
}
public void setSupportedMimeTypes(Set supportedMimeTypes)
@@ -98,12 +133,6 @@ public class YouTubeChannelType extends AbstractChannelType
return ID;
}
- @Override
- public Set getSupportedContentTypes()
- {
- return Collections.emptySet();
- }
-
@Override
public Set getSupportedMimeTypes()
{
@@ -113,31 +142,182 @@ public class YouTubeChannelType extends AbstractChannelType
@Override
public void publish(NodeRef nodeToPublish, Map properties)
{
- Action youtubePublishAction = actionService.createAction(YouTubePublishAction.NAME);
- actionService.executeAction(youtubePublishAction, nodeToPublish);
+ YouTubeService service = youTubeHelper.getYouTubeServiceFromChannelProperties(properties);
+ if (service != null)
+ {
+ try
+ {
+ uploadVideo(service, nodeToPublish);
+ }
+ catch (Exception ex)
+ {
+ log.error("Failed to send asset to YouTube", ex);
+ throw new AlfrescoRuntimeException("exception.publishing.youtube.publishFailed", ex);
+ }
+ }
}
@Override
public void unpublish(NodeRef nodeToUnpublish, Map properties)
{
- Action youtubeUnpublishAction = actionService.createAction(YouTubeUnpublishAction.NAME);
- actionService.executeAction(youtubeUnpublishAction, nodeToUnpublish);
- }
-
- @Override
- public void updateStatus(Channel channel, String status, Map properties)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getNodeUrl(NodeRef node)
- {
- String url = null;
- if (node != null && nodeService.exists(node) && nodeService.hasAspect(node, PublishingModel.ASPECT_ASSET))
+ YouTubeService service = youTubeHelper.getYouTubeServiceFromChannelProperties(properties);
+ if (service != null)
{
- url = (String)nodeService.getProperty(node, PublishingModel.PROP_ASSET_URL);
+ try
+ {
+ removeVideo(service, nodeToUnpublish);
+ }
+ catch (Exception ex)
+ {
+ log.error("Failed to remove asset from YouTube", ex);
+ throw new AlfrescoRuntimeException("exception.publishing.youtube.unpublishFailed", ex);
+ }
}
- return url;
}
-}
+
+ private void removeVideo(YouTubeService service, NodeRef nodeRef) throws MalformedURLException, IOException,
+ ServiceException
+ {
+ NodeService nodeService = getNodeService();
+ if (nodeService.hasAspect(nodeRef, YouTubePublishingModel.ASPECT_ASSET))
+ {
+ String youtubeId = (String) nodeService.getProperty(nodeRef, PublishingModel.PROP_ASSET_ID);
+ if (youtubeId != null)
+ {
+ String videoEntryUrl = "https://gdata.youtube.com/feeds/api/users/default/uploads/" + youtubeId;
+ VideoEntry videoEntry = service.getEntry(new URL(videoEntryUrl), VideoEntry.class);
+ videoEntry.delete();
+ nodeService.removeAspect(nodeRef, YouTubePublishingModel.ASPECT_ASSET);
+ nodeService.removeAspect(nodeRef, PublishingModel.ASPECT_ASSET);
+ }
+ }
+ }
+
+ private void uploadVideo(YouTubeService service, NodeRef nodeRef) throws IOException, ServiceException,
+ InterruptedException
+ {
+ NodeService nodeService = getNodeService();
+ ContentReader reader = contentService.getReader(nodeRef, 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("youtube");
+ contentFile = TempFileProvider.createTempFile("youtube", "", tempDir);
+ reader.getContent(contentFile);
+ deleteContentFileOnCompletion = true;
+ }
+ MediaFileSource ms = new MediaFileSource(contentFile, reader.getMimetype());
+
+ String videoName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
+ String videoTitle = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE);
+ if (videoTitle == null || videoTitle.length() == 0)
+ {
+ videoTitle = videoName;
+ }
+ String videoDescription = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_DESCRIPTION);
+ if (videoDescription == null || videoDescription.length() == 0)
+ {
+ videoDescription = videoTitle;
+ }
+
+ VideoEntry newEntry = new VideoEntry();
+ YouTubeMediaGroup mg = newEntry.getOrCreateMediaGroup();
+ mg.addCategory(new MediaCategory(YouTubeNamespace.CATEGORY_SCHEME, "Tech"));
+ mg.setTitle(new MediaTitle());
+ mg.getTitle().setPlainTextContent(videoTitle);
+ mg.setKeywords(new MediaKeywords());
+ List tags = taggingService.getTags(nodeRef);
+ for (String tag : tags)
+ {
+ mg.getKeywords().addKeyword(tag);
+ }
+ mg.setDescription(new MediaDescription());
+ mg.getDescription().setPlainTextContent(videoDescription);
+
+ FileUploadProgressListener listener = new FileUploadProgressListener(videoName);
+ ResumableGDataFileUploader uploader = new ResumableGDataFileUploader.Builder(service, new URL(
+ RESUMABLE_UPLOAD_URL), ms, newEntry).title(videoTitle).trackProgress(listener,
+ PROGRESS_UPDATE_INTERVAL).chunkSize(DEFAULT_CHUNK_SIZE).build();
+
+ uploader.start();
+ while (!uploader.isDone())
+ {
+ Thread.sleep(PROGRESS_UPDATE_INTERVAL);
+ }
+
+ switch (uploader.getUploadState())
+ {
+ case COMPLETE:
+ VideoEntry entry = uploader.getResponse(VideoEntry.class);
+ String videoId = entry.getMediaGroup().getVideoId();
+ String contentUrl = entry.getMediaGroup().getContents().get(0).getUrl();
+ String playerUrl = entry.getMediaGroup().getPlayer().getUrl();
+ if (log.isDebugEnabled())
+ {
+ log.debug("Video content uploaded successfully: " + videoName);
+ log.debug("YouTube video id is " + videoId);
+ log.debug("YouTube content URL is " + contentUrl);
+ log.debug("YouTube video player URL is " + playerUrl);
+ }
+ nodeService.addAspect(nodeRef, YouTubePublishingModel.ASPECT_ASSET, null);
+ nodeService.setProperty(nodeRef, PublishingModel.PROP_ASSET_ID, videoId);
+ nodeService.setProperty(nodeRef, PublishingModel.PROP_ASSET_URL, playerUrl);
+ break;
+ case CLIENT_ERROR:
+ log.error("Video content failed to upload: " + videoName);
+ break;
+ default:
+ log.warn("Unknown upload state. Video content may not have uploaded: " + videoName + "("
+ + uploader.getUploadState() + ") :" + nodeRef);
+ break;
+ }
+
+ if (deleteContentFileOnCompletion)
+ {
+ contentFile.delete();
+ }
+ }
+ }
+
+ /**
+ * A {@link ProgressListener} implementation to track upload progress. The
+ * listener can track multiple uploads at the same time.
+ */
+ private class FileUploadProgressListener implements ProgressListener
+ {
+ String videoName;
+
+ public FileUploadProgressListener(String videoName)
+ {
+ this.videoName = videoName;
+ }
+
+ public synchronized void progressChanged(ResumableHttpFileUploader uploader)
+ {
+ switch (uploader.getUploadState())
+ {
+ case COMPLETE:
+ log.info("Upload Completed: " + videoName);
+ break;
+ case CLIENT_ERROR:
+ log.error("Upload Failed: " + videoName);
+ break;
+ case IN_PROGRESS:
+ log.info(videoName + String.format(" %3.0f", uploader.getProgress() * 100) + "%");
+ break;
+ case NOT_STARTED:
+ log.info("Upload Not Started: " + videoName);
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishAction.java b/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishAction.java
deleted file mode 100644
index c8593be0f0..0000000000
--- a/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishAction.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * 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 .
- */
-package org.alfresco.repo.publishing.youtube;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-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.repo.publishing.PublishingModel;
-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 com.google.gdata.client.media.ResumableGDataFileUploader;
-import com.google.gdata.client.uploader.ProgressListener;
-import com.google.gdata.client.uploader.ResumableHttpFileUploader;
-import com.google.gdata.client.youtube.YouTubeService;
-import com.google.gdata.data.media.MediaFileSource;
-import com.google.gdata.data.media.mediarss.MediaCategory;
-import com.google.gdata.data.media.mediarss.MediaDescription;
-import com.google.gdata.data.media.mediarss.MediaKeywords;
-import com.google.gdata.data.media.mediarss.MediaTitle;
-import com.google.gdata.data.youtube.VideoEntry;
-import com.google.gdata.data.youtube.YouTubeMediaGroup;
-import com.google.gdata.data.youtube.YouTubeNamespace;
-import com.google.gdata.util.ServiceException;
-
-public class YouTubePublishAction extends ActionExecuterAbstractBase
-{
- private final static Log log = LogFactory.getLog(YouTubePublishAction.class);
-
- public static final String NAME = "publish_youtube";
-
- public static final String RESUMABLE_UPLOAD_URL = "http://uploads.gdata.youtube.com/resumable/feeds/api/users/default/uploads";
-
- /** Time interval at which upload task will notify about the progress */
- private static final int PROGRESS_UPDATE_INTERVAL = 1000;
-
- /** Max size for each upload chunk */
- private static final int DEFAULT_CHUNK_SIZE = 10000000;
-
- private NodeService nodeService;
- private ContentService contentService;
- private TaggingService taggingService;
- private YouTubePublishingHelper youTubeHelper;
-
- public void setYouTubeHelper(YouTubePublishingHelper youTubeHelper)
- {
- this.youTubeHelper = youTubeHelper;
- }
-
- 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 actionedUponNodeRef)
- {
- YouTubeService service = youTubeHelper.getYouTubeServiceForNode(actionedUponNodeRef);
- if (service != null)
- {
- try
- {
- uploadVideo(service, actionedUponNodeRef);
- }
- catch(Exception ex)
- {
- log.error("Failed to send asset to YouTube", ex);
- throw new AlfrescoRuntimeException("exception.publishing.youtube.publishFailed", ex);
- }
- }
- }
-
- private void uploadVideo(YouTubeService service, NodeRef nodeRef) throws IOException, ServiceException,
- InterruptedException
- {
- ContentReader reader = contentService.getReader(nodeRef, 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("youtube");
- contentFile = TempFileProvider.createTempFile("youtube", "", tempDir);
- reader.getContent(contentFile);
- deleteContentFileOnCompletion = true;
- }
- MediaFileSource ms = new MediaFileSource(contentFile, reader.getMimetype());
-
- String videoName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
- String videoTitle = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE);
- if (videoTitle == null || videoTitle.length() == 0)
- {
- videoTitle = videoName;
- }
- String videoDescription = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_DESCRIPTION);
- if (videoDescription == null || videoDescription.length() == 0)
- {
- videoDescription = videoTitle;
- }
-
- VideoEntry newEntry = new VideoEntry();
- YouTubeMediaGroup mg = newEntry.getOrCreateMediaGroup();
- mg.addCategory(new MediaCategory(YouTubeNamespace.CATEGORY_SCHEME, "Tech"));
- mg.setTitle(new MediaTitle());
- mg.getTitle().setPlainTextContent(videoTitle);
- mg.setKeywords(new MediaKeywords());
- List tags = taggingService.getTags(nodeRef);
- for (String tag : tags)
- {
- mg.getKeywords().addKeyword(tag);
- }
- mg.setDescription(new MediaDescription());
- mg.getDescription().setPlainTextContent(videoDescription);
-
- FileUploadProgressListener listener = new FileUploadProgressListener(videoName);
- ResumableGDataFileUploader uploader = new ResumableGDataFileUploader.Builder(service, new URL(
- RESUMABLE_UPLOAD_URL), ms, newEntry).title(videoTitle).trackProgress(listener,
- PROGRESS_UPDATE_INTERVAL).chunkSize(DEFAULT_CHUNK_SIZE).build();
-
- uploader.start();
- while (!uploader.isDone())
- {
- Thread.sleep(PROGRESS_UPDATE_INTERVAL);
- }
-
- switch (uploader.getUploadState())
- {
- case COMPLETE:
- VideoEntry entry = uploader.getResponse(VideoEntry.class);
- String videoId = entry.getMediaGroup().getVideoId();
- String contentUrl = entry.getMediaGroup().getContents().get(0).getUrl();
- String playerUrl = entry.getMediaGroup().getPlayer().getUrl();
- if (log.isDebugEnabled())
- {
- log.debug("Video content uploaded successfully: " + videoName);
- log.debug("YouTube video id is " + videoId);
- log.debug("YouTube content URL is " + contentUrl);
- log.debug("YouTube video player URL is " + playerUrl);
- }
- nodeService.addAspect(nodeRef, YouTubePublishingModel.ASPECT_ASSET, null);
- nodeService.setProperty(nodeRef, PublishingModel.PROP_ASSET_ID, videoId);
- nodeService.setProperty(nodeRef, PublishingModel.PROP_ASSET_URL, playerUrl);
- break;
- case CLIENT_ERROR:
- log.error("Video content failed to upload: " + videoName);
- break;
- default:
- log.warn("Unknown upload state. Video content may not have uploaded: " + videoName + "("
- + uploader.getUploadState() + ") :" + nodeRef);
- break;
- }
-
- if (deleteContentFileOnCompletion)
- {
- contentFile.delete();
- }
- }
- }
-
- @Override
- protected void addParameterDefinitions(List paramList)
- {
- }
-
- /**
- * A {@link ProgressListener} implementation to track upload progress. The
- * listener can track multiple uploads at the same time.
- */
- private class FileUploadProgressListener implements ProgressListener
- {
- String videoName;
-
- public FileUploadProgressListener(String videoName)
- {
- this.videoName = videoName;
- }
-
- public synchronized void progressChanged(ResumableHttpFileUploader uploader)
- {
- switch (uploader.getUploadState())
- {
- case COMPLETE:
- log.info("Upload Completed: " + videoName);
- break;
- case CLIENT_ERROR:
- log.error("Upload Failed: " + videoName);
- break;
- case IN_PROGRESS:
- log.info(videoName + String.format(" %3.0f", uploader.getProgress() * 100) + "%");
- break;
- case NOT_STARTED:
- log.info("Upload Not Started: " + videoName);
- break;
- }
- }
- }
-
-}
diff --git a/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishingHelper.java b/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishingHelper.java
index 223dd8de23..7438538f61 100644
--- a/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishingHelper.java
+++ b/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishingHelper.java
@@ -18,10 +18,12 @@
*/
package org.alfresco.repo.publishing.youtube;
+import java.io.Serializable;
+import java.util.Map;
+
import org.alfresco.repo.node.encryption.MetadataEncryptor;
import org.alfresco.repo.publishing.PublishingModel;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -30,42 +32,32 @@ import com.google.gdata.client.youtube.YouTubeService;
public class YouTubePublishingHelper
{
private static final Log log = LogFactory.getLog(YouTubePublishingHelper.class);
- private NodeService nodeService;
private MetadataEncryptor encryptor;
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
-
public void setEncryptor(MetadataEncryptor encryptor)
{
this.encryptor = encryptor;
}
- public YouTubeService getYouTubeServiceForNode(NodeRef publishNode)
+ public YouTubeService getYouTubeServiceFromChannelProperties(Map channelProperties)
{
YouTubeService service = null;
- if (nodeService.exists(publishNode))
+ if (channelProperties != null)
{
- NodeRef parent = nodeService.getPrimaryParent(publishNode).getParentRef();
- if (nodeService.hasAspect(parent, YouTubePublishingModel.ASPECT_DELIVERY_CHANNEL))
+ String youtubeUsername = (String) encryptor.decrypt(PublishingModel.PROP_CHANNEL_USERNAME,
+ channelProperties.get(PublishingModel.PROP_CHANNEL_USERNAME));
+ String youtubePassword = (String) encryptor.decrypt(PublishingModel.PROP_CHANNEL_PASSWORD,
+ channelProperties.get(PublishingModel.PROP_CHANNEL_PASSWORD));
+ service = new YouTubeService("Alfresco",
+ "AI39si78RHlniONCtnu9o8eBfwZToBAp2ZbbURm5eoJjj4gZi0LcxjDqJTzD35oYokmtFXbCo5ojofbimGnMlRbmNrh7-M7ZCw");
+ try
{
- String youtubeUsername = (String) encryptor.decrypt(PublishingModel.PROP_CHANNEL_USERNAME, nodeService
- .getProperty(parent, PublishingModel.PROP_CHANNEL_USERNAME));
- String youtubePassword = (String) encryptor.decrypt(PublishingModel.PROP_CHANNEL_PASSWORD, nodeService
- .getProperty(parent, PublishingModel.PROP_CHANNEL_PASSWORD));
- service = new YouTubeService("Alfresco",
- "AI39si78RHlniONCtnu9o8eBfwZToBAp2ZbbURm5eoJjj4gZi0LcxjDqJTzD35oYokmtFXbCo5ojofbimGnMlRbmNrh7-M7ZCw");
- try
- {
- service.setUserCredentials(youtubeUsername, youtubePassword);
- }
- catch (Exception e)
- {
- service = null;
- log.error("Failed to connect to YouTube", e);
- }
+ service.setUserCredentials(youtubeUsername, youtubePassword);
+ }
+ catch (Exception e)
+ {
+ service = null;
+ log.error("Failed to connect to YouTube", e);
}
}
return service;
diff --git a/source/java/org/alfresco/repo/publishing/youtube/YouTubeTest.java b/source/java/org/alfresco/repo/publishing/youtube/YouTubeTest.java
index 9de852dc51..5f040a0dbb 100644
--- a/source/java/org/alfresco/repo/publishing/youtube/YouTubeTest.java
+++ b/source/java/org/alfresco/repo/publishing/youtube/YouTubeTest.java
@@ -31,8 +31,6 @@ 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;
@@ -100,6 +98,9 @@ public class YouTubeTest extends BaseSpringTest
//text "YOUR_USER_NAME" and "YOUR_PASSWORD" appear.
public void xtestYouTubePublishAndUnpublishActions() throws Exception
{
+ final String channelName = GUID.generate();
+ final YouTubeChannelType channelType = (YouTubeChannelType) channelService.getChannelType(YouTubeChannelType.ID);
+
final NodeRef vidNode = transactionHelper.doInTransaction(new RetryingTransactionCallback()
{
public NodeRef execute() throws Throwable
@@ -107,7 +108,7 @@ public class YouTubeTest extends BaseSpringTest
Map props = new HashMap();
props.put(PublishingModel.PROP_CHANNEL_USERNAME, "YOUR_USER_NAME");
props.put(PublishingModel.PROP_CHANNEL_PASSWORD, "YOUR_PASSWORD");
- Channel channel = channelService.createChannel(YouTubeChannelType.ID, "YouTubeChannel", props);
+ Channel channel = channelService.createChannel(YouTubeChannelType.ID, channelName, props);
NodeRef channelNode = channel.getNodeRef();
Resource videoFile = new ClassPathResource("test/alfresco/TestVideoFile.MP4");
@@ -128,9 +129,7 @@ public class YouTubeTest extends BaseSpringTest
{
public NodeRef execute() throws Throwable
{
- ActionService actionService = serviceRegistry.getActionService();
- Action publishAction = actionService.createAction(YouTubePublishAction.NAME);
- actionService.executeAction(publishAction, vidNode);
+ channelType.publish(vidNode, channelService.getChannelByName(channelName).getProperties());
Map props = nodeService.getProperties(vidNode);
Assert.assertTrue(nodeService.hasAspect(vidNode, YouTubePublishingModel.ASPECT_ASSET));
Assert.assertNotNull(props.get(PublishingModel.PROP_ASSET_ID));
@@ -138,8 +137,7 @@ public class YouTubeTest extends BaseSpringTest
System.out.println("YouTube video: " + props.get(PublishingModel.PROP_ASSET_ID));
- Action unpublishAction = actionService.createAction(YouTubeUnpublishAction.NAME);
- actionService.executeAction(unpublishAction, vidNode);
+ channelType.unpublish(vidNode, channelService.getChannelByName(channelName).getProperties());
props = nodeService.getProperties(vidNode);
Assert.assertFalse(nodeService.hasAspect(vidNode, YouTubePublishingModel.ASPECT_ASSET));
Assert.assertNull(props.get(PublishingModel.PROP_ASSET_ID));
diff --git a/source/java/org/alfresco/repo/publishing/youtube/YouTubeUnpublishAction.java b/source/java/org/alfresco/repo/publishing/youtube/YouTubeUnpublishAction.java
deleted file mode 100644
index 8159c06ef3..0000000000
--- a/source/java/org/alfresco/repo/publishing/youtube/YouTubeUnpublishAction.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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 .
- */
-package org.alfresco.repo.publishing.youtube;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.List;
-
-import org.alfresco.error.AlfrescoRuntimeException;
-import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
-import org.alfresco.repo.publishing.PublishingModel;
-import org.alfresco.service.cmr.action.Action;
-import org.alfresco.service.cmr.action.ParameterDefinition;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import com.google.gdata.client.youtube.YouTubeService;
-import com.google.gdata.data.youtube.VideoEntry;
-import com.google.gdata.util.ServiceException;
-
-public class YouTubeUnpublishAction extends ActionExecuterAbstractBase
-{
- private final static Log log = LogFactory.getLog(YouTubeUnpublishAction.class);
- public static final String NAME = "unpublish_youtube";
-
- private NodeService nodeService;
- private YouTubePublishingHelper youTubeHelper;
-
- public void setYouTubeHelper(YouTubePublishingHelper youTubeHelper)
- {
- this.youTubeHelper = youTubeHelper;
- }
-
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
-
- @Override
- protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
- {
- YouTubeService service = youTubeHelper.getYouTubeServiceForNode(actionedUponNodeRef);
- if (service != null)
- {
- try
- {
- removeVideo(service, actionedUponNodeRef);
- }
- catch (Exception ex)
- {
- log.error("Failed to remove asset from YouTube", ex);
- throw new AlfrescoRuntimeException("exception.publishing.youtube.unpublishFailed", ex);
- }
- }
- }
-
- private void removeVideo(YouTubeService service, NodeRef nodeRef) throws MalformedURLException, IOException,
- ServiceException
- {
- if (nodeService.hasAspect(nodeRef, YouTubePublishingModel.ASPECT_ASSET))
- {
- String youtubeId = (String) nodeService.getProperty(nodeRef, PublishingModel.PROP_ASSET_ID);
- if (youtubeId != null)
- {
- String videoEntryUrl = "https://gdata.youtube.com/feeds/api/users/default/uploads/" + youtubeId;
- VideoEntry videoEntry = service.getEntry(new URL(videoEntryUrl), VideoEntry.class);
- videoEntry.delete();
- nodeService.removeAspect(nodeRef, YouTubePublishingModel.ASPECT_ASSET);
- nodeService.removeAspect(nodeRef, PublishingModel.ASPECT_ASSET);
- }
- }
- }
-
- @Override
- protected void addParameterDefinitions(List paramList)
- {
- }
-}
diff --git a/source/java/org/alfresco/service/cmr/publishing/PublishingService.java b/source/java/org/alfresco/service/cmr/publishing/PublishingService.java
index 76a9aa2b54..b9dfbee78d 100644
--- a/source/java/org/alfresco/service/cmr/publishing/PublishingService.java
+++ b/source/java/org/alfresco/service/cmr/publishing/PublishingService.java
@@ -63,8 +63,16 @@ public interface PublishingService
void cancelPublishingEvent(String id);
/**
- * Retrieve the publishing queue associated with this publishing environment
- * @return A PublishingQueue object corresponding tho this environment's publishing queue
+ * A factory method to create an empty publishing package that can be populated before being passed into
+ * a call to the {@link PublishingQueue#scheduleNewEvent(PublishingDetails)} operation.
+ * @return A publishing package that can be populated before being placed on the publishing queue.
*/
- PublishingQueue getPublishingQueue();
+ PublishingDetails createPublishingDetails();
+
+ /**
+ * Adds the supplied publishing package onto the queue.
+ * @param publishingDetails The publishing package that is to be enqueued
+ * @return The identifier of the newly scheduled event
+ */
+ String scheduleNewEvent(PublishingDetails publishingDetails);
}
diff --git a/source/java/org/alfresco/service/cmr/publishing/channels/Channel.java b/source/java/org/alfresco/service/cmr/publishing/channels/Channel.java
index 35d5e4ba56..6c04e8ce4d 100644
--- a/source/java/org/alfresco/service/cmr/publishing/channels/Channel.java
+++ b/source/java/org/alfresco/service/cmr/publishing/channels/Channel.java
@@ -56,9 +56,7 @@ public interface Channel
Map getProperties();
- void publish(NodeRef nodeToPublish);
- void unPublish(NodeRef nodeToUnpublish);
- void updateStatus(String status, String nodeUrl);
+ void sendStatusUpdate(String status, String nodeUrl);
/**
* Returns the URL for some published content given the content node in the editorial environment.
diff --git a/source/java/org/alfresco/service/cmr/publishing/channels/ChannelService.java b/source/java/org/alfresco/service/cmr/publishing/channels/ChannelService.java
index 1e217897e9..254c2db0e0 100644
--- a/source/java/org/alfresco/service/cmr/publishing/channels/ChannelService.java
+++ b/source/java/org/alfresco/service/cmr/publishing/channels/ChannelService.java
@@ -23,6 +23,7 @@ import java.io.Serializable;
import java.util.List;
import java.util.Map;
+import org.alfresco.repo.publishing.AbstractChannelType;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
@@ -38,7 +39,7 @@ public interface ChannelService
* @param channelType The channel type to be registered.
* @throws IllegalArgumentException if a channel type is already registered that has the same identifier as the supplied one
*/
- void register(ChannelType channelType);
+ void register(AbstractChannelType channelType);
/**
* Retrieve the channel type that has the specified identifier
diff --git a/source/java/org/alfresco/service/cmr/publishing/channels/ChannelType.java b/source/java/org/alfresco/service/cmr/publishing/channels/ChannelType.java
index ef945d41a1..277f253fe8 100644
--- a/source/java/org/alfresco/service/cmr/publishing/channels/ChannelType.java
+++ b/source/java/org/alfresco/service/cmr/publishing/channels/ChannelType.java
@@ -19,7 +19,6 @@
package org.alfresco.service.cmr.publishing.channels;
-import java.io.Serializable;
import java.util.Map;
import java.util.Set;
@@ -38,14 +37,12 @@ public interface ChannelType
String getId();
QName getChannelNodeType();
- void publish(NodeRef nodeToPublish, Map properties);
- void unpublish(NodeRef nodeToUnpublish, Map properties);
- void updateStatus(Channel channel, String status, Map properties);
-
boolean canPublish();
boolean canUnpublish();
boolean canPublishStatusUpdates();
+ void sendStatusUpdate(Channel channel, String status);
+
Set getSupportedMimeTypes();
Set getSupportedContentTypes();