diff --git a/config/alfresco/application-context-highlevel.xml b/config/alfresco/application-context-highlevel.xml
index cfd3125057..758d8ec80a 100644
--- a/config/alfresco/application-context-highlevel.xml
+++ b/config/alfresco/application-context-highlevel.xml
@@ -21,5 +21,8 @@
+
+
+
diff --git a/config/alfresco/application-context.xml b/config/alfresco/application-context.xml
index 2cdde0d023..3d5e0c6258 100644
--- a/config/alfresco/application-context.xml
+++ b/config/alfresco/application-context.xml
@@ -16,10 +16,6 @@
-->
-
-
-
-
diff --git a/config/alfresco/model/publishingModel.xml b/config/alfresco/model/publishingModel.xml
index 9e466b3ddf..4c6f6df52e 100644
--- a/config/alfresco/model/publishingModel.xml
+++ b/config/alfresco/model/publishingModel.xml
@@ -240,13 +240,6 @@
-
-
- Content Root Aspect
- Applied to a node that represents the root of a delivery channel's content
- hierarchy
-
-
Channel Info
Applied to a node that exists within a Delivery Channel
diff --git a/config/alfresco/model/youtubePublishingModel.xml b/config/alfresco/model/youtubePublishingModel.xml
new file mode 100644
index 0000000000..17d806b21d
--- /dev/null
+++ b/config/alfresco/model/youtubePublishingModel.xml
@@ -0,0 +1,64 @@
+
+
+ Alfresco YouTube Publishing Content Model
+ Alfresco
+ 2011-06-15
+ 1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ YouTube Delivery Channel
+ Node type used to represent YouTube delivery channels
+ pub:DeliveryChannel
+
+ youtube:DeliveryChannelAspect
+
+
+
+
+
+
+
+ YouTube Delivery Channel
+ Applied to a node that represents a YouTube delivery channel
+
+
+ YouTube User Name
+ d:text
+ false
+
+
+ YouTube Password
+ d:text
+ false
+
+
+
+
+
+ YouTube Asset
+ Applied to a node that has been published to YouTube
+
+
+ YouTube Video Id
+ d:text
+
+
+ YouTube Player URL
+ d:text
+
+
+
+
+
diff --git a/config/alfresco/web-publishing-context.xml b/config/alfresco/web-publishing-context.xml
index a683dd4079..2c4aae4ed0 100644
--- a/config/alfresco/web-publishing-context.xml
+++ b/config/alfresco/web-publishing-context.xml
@@ -2,7 +2,7 @@
-
+
alfresco/model/publishingModel.xml
@@ -10,7 +10,7 @@
-
+
@@ -29,80 +29,80 @@
-
-
-
- alfresco.messages.publishing-service
-
-
-
+
+
+
+ alfresco.messages.publishing-service
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
+
-
-
-
+
+
+
-
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/alfresco/youtube-publishing-context.xml b/config/alfresco/youtube-publishing-context.xml
new file mode 100644
index 0000000000..783f9c28bf
--- /dev/null
+++ b/config/alfresco/youtube-publishing-context.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+ alfresco/model/youtubePublishingModel.xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/test/alfresco/TestVideoFile.MP4 b/config/test/alfresco/TestVideoFile.MP4
new file mode 100644
index 0000000000..d35ffbbeb9
Binary files /dev/null and b/config/test/alfresco/TestVideoFile.MP4 differ
diff --git a/source/java/org/alfresco/repo/publishing/AbstractPublishingIntegrationTest.java b/source/java/org/alfresco/repo/publishing/AbstractPublishingIntegrationTest.java
index 34f73e159c..af1150fd54 100644
--- a/source/java/org/alfresco/repo/publishing/AbstractPublishingIntegrationTest.java
+++ b/source/java/org/alfresco/repo/publishing/AbstractPublishingIntegrationTest.java
@@ -29,6 +29,7 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileFolderService;
+import org.alfresco.service.cmr.publishing.PublishingService;
import org.alfresco.service.cmr.publishing.channels.ChannelType;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
@@ -54,8 +55,6 @@ import org.springframework.transaction.annotation.Transactional;
@Transactional
public abstract class AbstractPublishingIntegrationTest
{
- protected static final String environmentName = "live";
-
protected static final String channelTypeId = "MockChannelType";
@Resource(name="publishingObjectFactory")
@@ -83,12 +82,12 @@ public abstract class AbstractPublishingIntegrationTest
this.siteId = GUID.generate();
siteService.createSite("test", siteId,
- "Test site created by ChannelServiceImplIntegratedTest",
- "Test site created by ChannelServiceImplIntegratedTest",
+ "Site created by publishing test",
+ "Site created by publishing test",
SiteVisibility.PUBLIC);
this.docLib = siteService.createContainer(siteId, SiteService.DOCUMENT_LIBRARY, ContentModel.TYPE_FOLDER, null);
- this.environment = (EnvironmentImpl) factory.createEnvironmentObject(siteId, environmentName);
+ this.environment = (EnvironmentImpl) factory.createEnvironmentObject(siteId, PublishingService.LIVE_ENVIRONMENT_NAME);
this.queue = (PublishingQueueImpl) environment.getPublishingQueue();
}
@@ -103,7 +102,6 @@ public abstract class AbstractPublishingIntegrationTest
ChannelType channelType = mock(ChannelType.class);
when(channelType.getId()).thenReturn(channelTypeId);
when(channelType.getChannelNodeType()).thenReturn(TYPE_DELIVERY_CHANNEL);
- when(channelType.getContentRootNodeType()).thenReturn(ContentModel.TYPE_FOLDER);
return channelType;
}
diff --git a/source/java/org/alfresco/repo/publishing/ChannelHelper.java b/source/java/org/alfresco/repo/publishing/ChannelHelper.java
index 51fca08884..9d2f9422ac 100644
--- a/source/java/org/alfresco/repo/publishing/ChannelHelper.java
+++ b/source/java/org/alfresco/repo/publishing/ChannelHelper.java
@@ -20,7 +20,6 @@
package org.alfresco.repo.publishing;
import static org.alfresco.model.ContentModel.ASSOC_CONTAINS;
-import static org.alfresco.repo.publishing.PublishingModel.ASPECT_CONTENT_ROOT;
import static org.alfresco.repo.publishing.PublishingModel.ASPECT_PUBLISHED;
import static org.alfresco.repo.publishing.PublishingModel.ASSOC_SOURCE;
import static org.alfresco.repo.publishing.PublishingModel.NAMESPACE;
@@ -65,8 +64,6 @@ import org.alfresco.util.collections.Function;
*/
public class ChannelHelper
{
- private static final QName ROOT_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "root");
-
private NodeService nodeService;
private DictionaryService dictionaryService;
private FileFolderService fileFolderService;
@@ -90,10 +87,6 @@ public class ChannelHelper
ChildAssociationRef channelAssoc =
nodeService.createNode(parent, ASSOC_CONTAINS, channelQName, channelNodeType, props);
NodeRef channelNode = channelAssoc.getChildRef();
-
- QName rootNodeType = channelType.getContentRootNodeType();
- ChildAssociationRef rootAssoc = nodeService.createNode(channelNode, ASSOC_CONTAINS, ROOT_NAME, rootNodeType);
- nodeService.addAspect(rootAssoc.getChildRef(), ASPECT_CONTENT_ROOT, null);
return channelNode;
}
@@ -134,17 +127,6 @@ public class ChannelHelper
return getSingleValue(channelAssocs, true);
}
- public NodeRef getChannelRootNode(NodeRef channel)
- {
- List rootAssocs = nodeService.getChildAssocs(channel, ASSOC_CONTAINS, ROOT_NAME);
- NodeRef root = getSingleValue(rootAssocs, true);
- if(root ==null || nodeService.hasAspect(root, ASPECT_CONTENT_ROOT)==false)
- {
- throw new IllegalStateException("All channels must have a root folder!");
- }
- return root;
- }
-
/**
* Given a noderef from the editorial space (e.g. the doclib), this returns the corresponding noderef in the specified channel and environment.
* @param source
@@ -169,12 +151,11 @@ public class ChannelHelper
List parentAssocs = nodeService.getParentAssocs(source, ASSOC_SOURCE, RegexQNamePattern.MATCH_ALL);
if(parentAssocs != null)
{
- NodeRef root = getChannelRootNode(channel);
for (ChildAssociationRef parentAssoc : parentAssocs)
{
NodeRef publishedNode = parentAssoc.getParentRef();
NodeRef parent = nodeService.getPrimaryParent(publishedNode).getParentRef();
- if(root.equals(parent))
+ if(channel.equals(parent))
{
return publishedNode;
}
diff --git a/source/java/org/alfresco/repo/publishing/ChannelServiceImplIntegratedTest.java b/source/java/org/alfresco/repo/publishing/ChannelServiceImplIntegratedTest.java
index 0a16c0265d..916ae91b70 100644
--- a/source/java/org/alfresco/repo/publishing/ChannelServiceImplIntegratedTest.java
+++ b/source/java/org/alfresco/repo/publishing/ChannelServiceImplIntegratedTest.java
@@ -70,7 +70,6 @@ public class ChannelServiceImplIntegratedTest extends AbstractPublishingIntegrat
super.setUp();
when(mockedChannelType.getId()).thenReturn(channelTypeName);
when(mockedChannelType.getChannelNodeType()).thenReturn(PublishingModel.TYPE_DELIVERY_CHANNEL);
- when(mockedChannelType.getContentRootNodeType()).thenReturn(ContentModel.TYPE_FOLDER);
if (!channelTypeRegistered)
{
diff --git a/source/java/org/alfresco/repo/publishing/PublishEventActionTest.java b/source/java/org/alfresco/repo/publishing/PublishEventActionTest.java
index 52dcdc20fb..002486b867 100644
--- a/source/java/org/alfresco/repo/publishing/PublishEventActionTest.java
+++ b/source/java/org/alfresco/repo/publishing/PublishEventActionTest.java
@@ -93,7 +93,6 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
@Autowired
private PublishEventAction action;
- private NodeRef root;
private NodeRef channel;
private String eventId;
private ChannelType channelType;
@@ -115,7 +114,7 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
NodeRef publishedNode = channelHelper.mapSourceToEnvironment(source, channel);
assertNotNull(publishedNode);
assertTrue(nodeService.exists(publishedNode));
- assertEquals(root, nodeService.getPrimaryParent(publishedNode).getParentRef());
+ assertEquals(channel, nodeService.getPrimaryParent(publishedNode).getParentRef());
// Check published node type and aspects
assertEquals(TYPE_CONTENT, nodeService.getType(publishedNode));
@@ -410,8 +409,6 @@ public class PublishEventActionTest extends AbstractPublishingIntegrationTest
channelService.createChannel(siteId, channelTypeId, channelName, null);
this.channel = channelHelper.getChannelNodeForEnvironment(environment.getNodeRef(), channelName);
- this.root = channelHelper.getChannelRootNode(channel);
- assertNotNull(root);
}
@Override
diff --git a/source/java/org/alfresco/repo/publishing/PublishingEventProcessor.java b/source/java/org/alfresco/repo/publishing/PublishingEventProcessor.java
index a2fb9c47a2..5bf0bfc7b0 100644
--- a/source/java/org/alfresco/repo/publishing/PublishingEventProcessor.java
+++ b/source/java/org/alfresco/repo/publishing/PublishingEventProcessor.java
@@ -171,8 +171,7 @@ public class PublishingEventProcessor
ParameterCheck.mandatory("channel", channel);
ParameterCheck.mandatory("snapshot", snapshot);
- NodeRef root = channelHelper.getChannelRootNode(channel);
- NodeRef publishedNode = createPublishedNode(root, snapshot);
+ NodeRef publishedNode = createPublishedNode(channel, snapshot);
addAspects(publishedNode, snapshot.getAspects());
NodeRef source = snapshot.getNodeRef();
channelHelper.createMapping(source, publishedNode);
diff --git a/source/java/org/alfresco/repo/publishing/PublishingIntegratedTest.java b/source/java/org/alfresco/repo/publishing/PublishingIntegratedTest.java
index 18a2a46dd2..c8ac8853b6 100644
--- a/source/java/org/alfresco/repo/publishing/PublishingIntegratedTest.java
+++ b/source/java/org/alfresco/repo/publishing/PublishingIntegratedTest.java
@@ -112,7 +112,6 @@ public class PublishingIntegratedTest
channelTypeName = "MockedChannelType";
when(mockedChannelType.getId()).thenReturn(channelTypeName);
when(mockedChannelType.getChannelNodeType()).thenReturn(PublishingModel.TYPE_DELIVERY_CHANNEL);
- when(mockedChannelType.getContentRootNodeType()).thenReturn(ContentModel.TYPE_FOLDER);
if (channelService.getChannelType(channelTypeName)== null)
{
diff --git a/source/java/org/alfresco/repo/publishing/PublishingModel.java b/source/java/org/alfresco/repo/publishing/PublishingModel.java
index 7b185dfb52..1df86daaee 100644
--- a/source/java/org/alfresco/repo/publishing/PublishingModel.java
+++ b/source/java/org/alfresco/repo/publishing/PublishingModel.java
@@ -42,7 +42,6 @@ public interface PublishingModel
public static final QName TYPE_PUBLISHING_EVENT = QName.createQName(NAMESPACE, "PublishingEvent");
public static final QName TYPE_PUBLISHING_CONNECTION = QName.createQName(NAMESPACE, "Connection");
- public static final QName ASPECT_CONTENT_ROOT = QName.createQName(NAMESPACE, "ContentRoot");
public static final QName ASPECT_CHANNEL_INFO= QName.createQName(NAMESPACE, "channelInfo");
public static final QName ASPECT_PUBLISHED = QName.createQName(NAMESPACE, "published");
diff --git a/source/java/org/alfresco/repo/publishing/test/SiteType.java b/source/java/org/alfresco/repo/publishing/test/SiteType.java
new file mode 100644
index 0000000000..9fac4809eb
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/test/SiteType.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2005-2010 Alfresco Software Limited.
+ *
+ * This file is part of the Alfresco Web Quick Start module.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.alfresco.repo.publishing.test;
+
+import org.alfresco.repo.node.NodeServicePolicies;
+import org.alfresco.repo.policy.JavaBehaviour;
+import org.alfresco.repo.policy.PolicyComponent;
+import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
+import org.alfresco.repo.site.SiteModel;
+import org.alfresco.service.cmr.publishing.channels.ChannelService;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author Brian Remmington
+ */
+public class SiteType
+{
+ /** Log */
+ private final static Log log = LogFactory.getLog(SiteType.class);
+
+ private PolicyComponent policyComponent;
+ private ChannelService channelService;
+
+ /**
+ * This is the list of collections that will be created automatically for
+ * any new section.
+ */
+ /**
+ * Set the policy component
+ *
+ * @param policyComponent
+ * policy component
+ */
+ public void setPolicyComponent(PolicyComponent policyComponent)
+ {
+ this.policyComponent = policyComponent;
+ }
+
+ public void setChannelService(ChannelService channelService)
+ {
+ this.channelService = channelService;
+ }
+
+ /**
+ * Init method. Binds model behaviours to policies.
+ */
+ public void init()
+ {
+ // Register the association behaviours
+ policyComponent.bindClassBehaviour(NodeServicePolicies.OnCreateNodePolicy.QNAME, SiteModel.TYPE_SITE,
+ new JavaBehaviour(this, "onCreateNode", NotificationFrequency.TRANSACTION_COMMIT));
+ }
+
+ /**
+ * On create node behaviour
+ *
+ * @param childAssocRef
+ * child association reference
+ */
+ public void onCreateNode(ChildAssociationRef childAssocRef)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("onCreateNode " + childAssocRef);
+ }
+ String siteId = childAssocRef.getQName().getLocalName();
+ channelService.createChannel(siteId, "TestChannelType1", "Test Channel One", null);
+ channelService.createChannel(siteId, "TestChannelType2", "Test Channel Two", null);
+ channelService.createChannel(siteId, "TestChannelType3", "Test Channel Three", null);
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/publishing/test/TestChannelType1.java b/source/java/org/alfresco/repo/publishing/test/TestChannelType1.java
new file mode 100644
index 0000000000..a3c5d8ac59
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/test/TestChannelType1.java
@@ -0,0 +1,120 @@
+/*
+ * 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.test;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Set;
+
+import org.alfresco.repo.publishing.AbstractChannelType;
+import org.alfresco.repo.publishing.PublishingModel;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.transfer.NodeFilter;
+import org.alfresco.service.cmr.transfer.NodeFinder;
+import org.alfresco.service.namespace.QName;
+
+public class TestChannelType1 extends AbstractChannelType
+{
+
+ @Override
+ public boolean canPublish()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean canPublishStatusUpdates()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean canUnpublish()
+ {
+ return false;
+ }
+
+ @Override
+ public QName getChannelNodeType()
+ {
+ return PublishingModel.TYPE_DELIVERY_CHANNEL;
+ }
+
+ @Override
+ public String getId()
+ {
+ return "TestChannelType1";
+ }
+
+ @Override
+ public int getMaximumStatusLength()
+ {
+ return 0;
+ }
+
+ @Override
+ public NodeFilter getNodeFilter()
+ {
+ return null;
+ }
+
+ @Override
+ public NodeFinder getNodeFinder()
+ {
+ return null;
+ }
+
+ @Override
+ public String getNodeUrl(NodeRef node)
+ {
+ return node.getId();
+ }
+
+ @Override
+ public Set getSupportedContentTypes()
+ {
+ return null;
+ }
+
+ @Override
+ public Set getSupportedMimetypes()
+ {
+ return null;
+ }
+
+ @Override
+ public void publish(NodeRef nodeToPublish, Map properties)
+ {
+ //Deliberately blank
+ }
+
+ @Override
+ public void unpublish(NodeRef nodeToUnpublish, Map properties)
+ {
+ //Deliberately blank
+ }
+
+ @Override
+ public void updateStatus(String status, Map properties)
+ {
+ //Deliberately blank
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/publishing/test/TestChannelType2.java b/source/java/org/alfresco/repo/publishing/test/TestChannelType2.java
new file mode 100644
index 0000000000..c71e07411d
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/test/TestChannelType2.java
@@ -0,0 +1,120 @@
+/*
+ * 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.test;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Set;
+
+import org.alfresco.repo.publishing.AbstractChannelType;
+import org.alfresco.repo.publishing.PublishingModel;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.transfer.NodeFilter;
+import org.alfresco.service.cmr.transfer.NodeFinder;
+import org.alfresco.service.namespace.QName;
+
+public class TestChannelType2 extends AbstractChannelType
+{
+
+ @Override
+ public boolean canPublish()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean canPublishStatusUpdates()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean canUnpublish()
+ {
+ return false;
+ }
+
+ @Override
+ public QName getChannelNodeType()
+ {
+ return PublishingModel.TYPE_DELIVERY_CHANNEL;
+ }
+
+ @Override
+ public String getId()
+ {
+ return "TestChannelType2";
+ }
+
+ @Override
+ public int getMaximumStatusLength()
+ {
+ return 140;
+ }
+
+ @Override
+ public NodeFilter getNodeFilter()
+ {
+ return null;
+ }
+
+ @Override
+ public NodeFinder getNodeFinder()
+ {
+ return null;
+ }
+
+ @Override
+ public String getNodeUrl(NodeRef node)
+ {
+ return node.getId();
+ }
+
+ @Override
+ public Set getSupportedContentTypes()
+ {
+ return null;
+ }
+
+ @Override
+ public Set getSupportedMimetypes()
+ {
+ return null;
+ }
+
+ @Override
+ public void publish(NodeRef nodeToPublish, Map properties)
+ {
+ //Deliberately blank
+ }
+
+ @Override
+ public void unpublish(NodeRef nodeToUnpublish, Map properties)
+ {
+ //Deliberately blank
+ }
+
+ @Override
+ public void updateStatus(String status, Map properties)
+ {
+ //Deliberately blank
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/publishing/test/TestChannelType3.java b/source/java/org/alfresco/repo/publishing/test/TestChannelType3.java
new file mode 100644
index 0000000000..1c692aa4eb
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/test/TestChannelType3.java
@@ -0,0 +1,120 @@
+/*
+ * 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.test;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Set;
+
+import org.alfresco.repo.publishing.AbstractChannelType;
+import org.alfresco.repo.publishing.PublishingModel;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.transfer.NodeFilter;
+import org.alfresco.service.cmr.transfer.NodeFinder;
+import org.alfresco.service.namespace.QName;
+
+public class TestChannelType3 extends AbstractChannelType
+{
+
+ @Override
+ public boolean canPublish()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean canPublishStatusUpdates()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean canUnpublish()
+ {
+ return false;
+ }
+
+ @Override
+ public QName getChannelNodeType()
+ {
+ return PublishingModel.TYPE_DELIVERY_CHANNEL;
+ }
+
+ @Override
+ public String getId()
+ {
+ return "TestChannelType3";
+ }
+
+ @Override
+ public int getMaximumStatusLength()
+ {
+ return 200;
+ }
+
+ @Override
+ public NodeFilter getNodeFilter()
+ {
+ return null;
+ }
+
+ @Override
+ public NodeFinder getNodeFinder()
+ {
+ return null;
+ }
+
+ @Override
+ public String getNodeUrl(NodeRef node)
+ {
+ return node.getId();
+ }
+
+ @Override
+ public Set getSupportedContentTypes()
+ {
+ return null;
+ }
+
+ @Override
+ public Set getSupportedMimetypes()
+ {
+ return null;
+ }
+
+ @Override
+ public void publish(NodeRef nodeToPublish, Map properties)
+ {
+ //Deliberately blank
+ }
+
+ @Override
+ public void unpublish(NodeRef nodeToUnpublish, Map properties)
+ {
+ //Deliberately blank
+ }
+
+ @Override
+ public void updateStatus(String status, Map properties)
+ {
+ //Deliberately blank
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/publishing/test/publishing-test-context.xml b/source/java/org/alfresco/repo/publishing/test/publishing-test-context.xml
new file mode 100644
index 0000000000..4129e9e837
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/test/publishing-test-context.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/publishing/youtube/YouTubeChannelType.java b/source/java/org/alfresco/repo/publishing/youtube/YouTubeChannelType.java
new file mode 100644
index 0000000000..523be4f35e
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/youtube/YouTubeChannelType.java
@@ -0,0 +1,121 @@
+/*
+ * 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.Serializable;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.alfresco.repo.publishing.AbstractChannelType;
+import org.alfresco.service.cmr.action.Action;
+import org.alfresco.service.cmr.action.ActionService;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
+
+public class YouTubeChannelType extends AbstractChannelType
+{
+ public final static String ID = "youtube";
+ private NodeService nodeService;
+ private ActionService actionService;
+
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ public void setActionService(ActionService actionService)
+ {
+ this.actionService = actionService;
+ }
+
+ @Override
+ public boolean canPublish()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean canPublishStatusUpdates()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean canUnpublish()
+ {
+ return true;
+ }
+
+ @Override
+ public QName getChannelNodeType()
+ {
+ return YouTubePublishingModel.TYPE_DELIVERY_CHANNEL;
+ }
+
+ @Override
+ public String getId()
+ {
+ return ID;
+ }
+
+ @Override
+ public Set getSupportedContentTypes()
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set getSupportedMimetypes()
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void publish(NodeRef nodeToPublish, Map properties)
+ {
+ Action youtubePublishAction = actionService.createAction(YouTubePublishAction.NAME);
+ actionService.executeAction(youtubePublishAction, nodeToPublish);
+ }
+
+ @Override
+ public void unpublish(NodeRef nodeToUnpublish, Map properties)
+ {
+ Action youtubeUnpublishAction = actionService.createAction(YouTubeUnpublishAction.NAME);
+ actionService.executeAction(youtubeUnpublishAction, nodeToUnpublish);
+ }
+
+ @Override
+ public void updateStatus(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, YouTubePublishingModel.ASPECT_ASSET))
+ {
+ url = (String)nodeService.getProperty(node, YouTubePublishingModel.PROP_PLAYER_URL);
+ }
+ return url;
+ }
+}
diff --git a/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishAction.java b/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishAction.java
new file mode 100644
index 0000000000..fcbc57e663
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishAction.java
@@ -0,0 +1,243 @@
+/*
+ * 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.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.setProperty(nodeRef, YouTubePublishingModel.PROP_ASSET_ID, videoId);
+ nodeService.setProperty(nodeRef, YouTubePublishingModel.PROP_PLAYER_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
new file mode 100644
index 0000000000..83b6f8e0c7
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishingHelper.java
@@ -0,0 +1,65 @@
+/*
+ * 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 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;
+
+public class YouTubePublishingHelper
+{
+ private static final Log log = LogFactory.getLog(YouTubePublishingHelper.class);
+ private NodeService nodeService;
+
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+
+ public YouTubeService getYouTubeServiceForNode(NodeRef publishNode)
+ {
+ YouTubeService service = null;
+ if (nodeService.exists(publishNode))
+ {
+ NodeRef parent = nodeService.getPrimaryParent(publishNode).getParentRef();
+ if (nodeService.hasAspect(parent, YouTubePublishingModel.ASPECT_DELIVERY_CHANNEL))
+ {
+ String youtubeUsername = (String) nodeService.getProperty(parent, YouTubePublishingModel.PROP_USERNAME);
+ String youtubePassword = (String) nodeService.getProperty(parent, YouTubePublishingModel.PROP_PASSWORD);
+ service = new YouTubeService("Alfresco Kickoff Demo",
+ "AI39si71pRNHkfExcTpqcZewDtI4GHWuPAXyRPL2Xq-RQUBWlE1bqn77ANXEL5lZUWFDz6ZlS_XWCw8hlr2BJY1TnC-EMs4e4g");
+ try
+ {
+ 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/YouTubePublishingModel.java b/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishingModel.java
new file mode 100644
index 0000000000..219710fa8d
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/youtube/YouTubePublishingModel.java
@@ -0,0 +1,42 @@
+/*
+ * 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 org.alfresco.service.namespace.QName;
+
+/**
+ * @author Brian
+ *
+ */
+public interface YouTubePublishingModel
+{
+ public static final String NAMESPACE = "http://www.alfresco.org/model/publishing/youtube/1.0";
+ public static final String PREFIX = "youtube";
+
+ public static final QName TYPE_DELIVERY_CHANNEL = QName.createQName(NAMESPACE, "DeliveryChannel");
+
+ public static final QName ASPECT_DELIVERY_CHANNEL = QName.createQName(NAMESPACE, "DeliveryChannelAspect");
+ public static final QName PROP_USERNAME = QName.createQName(NAMESPACE, "username");
+ public static final QName PROP_PASSWORD = QName.createQName(NAMESPACE, "password");
+
+ public static final QName ASPECT_ASSET = QName.createQName(NAMESPACE, "AssetAspect");
+ public static final QName PROP_ASSET_ID = QName.createQName(NAMESPACE, "assetId");
+ public static final QName PROP_PLAYER_URL = QName.createQName(NAMESPACE, "playerUrl");
+}
diff --git a/source/java/org/alfresco/repo/publishing/youtube/YouTubeTest.java b/source/java/org/alfresco/repo/publishing/youtube/YouTubeTest.java
new file mode 100644
index 0000000000..4348c65005
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/youtube/YouTubeTest.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2005-2010 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+package org.alfresco.repo.publishing.youtube;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.publishing.EnvironmentImpl;
+import org.alfresco.repo.publishing.PublishingQueueImpl;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.action.Action;
+import org.alfresco.service.cmr.action.ActionService;
+import org.alfresco.service.cmr.model.FileFolderService;
+import org.alfresco.service.cmr.publishing.channels.Channel;
+import org.alfresco.service.cmr.publishing.channels.ChannelService;
+import org.alfresco.service.cmr.repository.ContentService;
+import org.alfresco.service.cmr.repository.ContentWriter;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.site.SiteService;
+import org.alfresco.service.cmr.site.SiteVisibility;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.util.GUID;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @author Brian
+ *
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "classpath:alfresco/application-context.xml" })
+public class YouTubeTest
+{
+ @javax.annotation.Resource(name = "ServiceRegistry")
+ protected ServiceRegistry serviceRegistry;
+
+ protected SiteService siteService;
+ protected FileFolderService fileFolderService;
+ protected NodeService nodeService;
+
+ protected String siteId;
+ protected PublishingQueueImpl queue;
+ protected EnvironmentImpl environment;
+ protected NodeRef docLib;
+
+ @javax.annotation.Resource(name = "channelService")
+ private ChannelService channelService;
+
+ private RetryingTransactionHelper transactionHelper;
+
+ @Before
+ public void setUp() throws Exception
+ {
+ AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
+ siteService = serviceRegistry.getSiteService();
+ fileFolderService = serviceRegistry.getFileFolderService();
+ nodeService = serviceRegistry.getNodeService();
+ transactionHelper = serviceRegistry.getRetryingTransactionHelper();
+
+ siteId = GUID.generate();
+ siteService.createSite("test", siteId, "Site created by publishing test", "Site created by publishing test",
+ SiteVisibility.PUBLIC);
+ docLib = siteService.createContainer(siteId, SiteService.DOCUMENT_LIBRARY, ContentModel.TYPE_FOLDER, null);
+ }
+
+ @Test
+ public void testBlank()
+ {
+
+ }
+
+ //Note that this test isn't normally run, as it requires valid YouTube credentials.
+ //To run it, add the Test annotation and set the appropriate YouTube credentials where the
+ //text "YOUR_USER_NAME" and "YOUR_PASSWORD" appear.
+ public void testYouTubePublishAndUnpublishActions() throws Exception
+ {
+ final NodeRef vidNode = transactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public NodeRef execute() throws Throwable
+ {
+ Map props = new HashMap();
+ props.put(YouTubePublishingModel.PROP_USERNAME, "YOUR_USER_NAME");
+ props.put(YouTubePublishingModel.PROP_PASSWORD, "YOUR_PASSWORD");
+ Channel channel = channelService.createChannel(siteId, YouTubeChannelType.ID, "YouTubeChannel", props);
+
+ NodeRef channelNode = channel.getNodeRef();
+ Resource videoFile = new ClassPathResource("test/alfresco/TestVideoFile.MP4");
+ Map vidProps = new HashMap();
+ vidProps.put(ContentModel.PROP_NAME, "Test Video");
+ NodeRef vidNode = nodeService.createNode(channelNode, ContentModel.ASSOC_CONTAINS,
+ QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "testVideo"),
+ ContentModel.TYPE_CONTENT, vidProps).getChildRef();
+ ContentService contentService = serviceRegistry.getContentService();
+ ContentWriter writer = contentService.getWriter(vidNode, ContentModel.PROP_CONTENT, true);
+ writer.setMimetype("video/mpg");
+ writer.putContent(videoFile.getFile());
+ return vidNode;
+ }
+ });
+
+ transactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public NodeRef execute() throws Throwable
+ {
+ ActionService actionService = serviceRegistry.getActionService();
+ Action publishAction = actionService.createAction(YouTubePublishAction.NAME);
+ actionService.executeAction(publishAction, vidNode);
+ Map props = nodeService.getProperties(vidNode);
+ Assert.assertTrue(nodeService.hasAspect(vidNode, YouTubePublishingModel.ASPECT_ASSET));
+ Assert.assertNotNull(props.get(YouTubePublishingModel.PROP_ASSET_ID));
+ Assert.assertNotNull(props.get(YouTubePublishingModel.PROP_PLAYER_URL));
+
+ System.out.println("YouTube video: " + props.get(YouTubePublishingModel.PROP_ASSET_ID));
+
+ Action unpublishAction = actionService.createAction(YouTubeUnpublishAction.NAME);
+ actionService.executeAction(unpublishAction, vidNode);
+ props = nodeService.getProperties(vidNode);
+ Assert.assertFalse(nodeService.hasAspect(vidNode, YouTubePublishingModel.ASPECT_ASSET));
+ Assert.assertNull(props.get(YouTubePublishingModel.PROP_ASSET_ID));
+ Assert.assertNull(props.get(YouTubePublishingModel.PROP_PLAYER_URL));
+ return null;
+ }
+ });
+
+ transactionHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public NodeRef execute() throws Throwable
+ {
+ nodeService.deleteNode(vidNode);
+ return null;
+ }
+ });
+
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/publishing/youtube/YouTubeUnpublishAction.java b/source/java/org/alfresco/repo/publishing/youtube/YouTubeUnpublishAction.java
new file mode 100644
index 0000000000..18a82e9d9e
--- /dev/null
+++ b/source/java/org/alfresco/repo/publishing/youtube/YouTubeUnpublishAction.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2005-2011 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+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.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
+ {
+ String youtubeId = (String) nodeService.getProperty(nodeRef, YouTubePublishingModel.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);
+ }
+ }
+
+ @Override
+ protected void addParameterDefinitions(List paramList)
+ {
+ }
+}
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 7b019ebabb..e5c5fd77aa 100644
--- a/source/java/org/alfresco/service/cmr/publishing/channels/ChannelType.java
+++ b/source/java/org/alfresco/service/cmr/publishing/channels/ChannelType.java
@@ -36,7 +36,6 @@ public interface ChannelType
{
String getId();
QName getChannelNodeType();
- QName getContentRootNodeType();
NodeFinder getNodeFinder();
NodeFilter getNodeFilter();
void publish(NodeRef nodeToPublish, Map properties);