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);