mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Publishing:
- Add latest gdata libs (1.45.0) with source code - cleaned the publishing context files out of the top-level application context - removed the notion of "content root" from publishing channels - added YouTube publishing channel with actions to publish and unpublish - added dummy channel types to ease UI development git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28575 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -21,5 +21,8 @@
|
||||
<import resource="classpath:alfresco/opencmis-context.xml" />
|
||||
<import resource="classpath:alfresco/period-type-context.xml" />
|
||||
<import resource="classpath*:alfresco/node-locator-context.xml" />
|
||||
<import resource="classpath*:alfresco/transfer-service-context.xml"/>
|
||||
<import resource="classpath*:alfresco/web-publishing-context.xml" />
|
||||
<import resource="classpath*:alfresco/social-publishing-context.xml" />
|
||||
<import resource="classpath*:alfresco/domain/*-context.xml" />
|
||||
</beans>
|
||||
|
@@ -16,10 +16,6 @@
|
||||
-->
|
||||
<import resource="classpath:alfresco/application-context-highlevel.xml" />
|
||||
|
||||
<import resource="classpath*:alfresco/transfer-service-context.xml"/>
|
||||
<import resource="classpath*:alfresco/web-publishing-context.xml" />
|
||||
<!-- <import resource="classpath*:alfresco/social-publishing-context.xml" /> -->
|
||||
|
||||
<!--
|
||||
Import activation extensions for Multi-Tenancy.
|
||||
-->
|
||||
|
@@ -240,13 +240,6 @@
|
||||
</types>
|
||||
|
||||
<aspects>
|
||||
|
||||
<aspect name="pub:ContentRoot">
|
||||
<title>Content Root Aspect</title>
|
||||
<description>Applied to a node that represents the root of a delivery channel's content
|
||||
hierarchy</description>
|
||||
</aspect>
|
||||
|
||||
<aspect name="pub:channelInfo">
|
||||
<title>Channel Info</title>
|
||||
<description>Applied to a node that exists within a Delivery Channel</description>
|
||||
|
64
config/alfresco/model/youtubePublishingModel.xml
Normal file
64
config/alfresco/model/youtubePublishingModel.xml
Normal file
@@ -0,0 +1,64 @@
|
||||
<model name="youtube:publishingmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
|
||||
|
||||
<description>Alfresco YouTube Publishing Content Model</description>
|
||||
<author>Alfresco</author>
|
||||
<published>2011-06-15</published>
|
||||
<version>1.0</version>
|
||||
|
||||
<imports>
|
||||
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d" />
|
||||
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys" />
|
||||
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm" />
|
||||
<import uri="http://www.alfresco.org/model/publishing/1.0" prefix="pub" />
|
||||
</imports>
|
||||
|
||||
<namespaces>
|
||||
<namespace uri="http://www.alfresco.org/model/publishing/youtube/1.0" prefix="youtube" />
|
||||
</namespaces>
|
||||
|
||||
<types>
|
||||
<type name="youtube:DeliveryChannel">
|
||||
<title>YouTube Delivery Channel</title>
|
||||
<description>Node type used to represent YouTube delivery channels</description>
|
||||
<parent>pub:DeliveryChannel</parent>
|
||||
<mandatory-aspects>
|
||||
<aspect>youtube:DeliveryChannelAspect</aspect>
|
||||
</mandatory-aspects>
|
||||
</type>
|
||||
|
||||
</types>
|
||||
|
||||
<aspects>
|
||||
<aspect name="youtube:DeliveryChannelAspect">
|
||||
<title>YouTube Delivery Channel</title>
|
||||
<description>Applied to a node that represents a YouTube delivery channel</description>
|
||||
<properties>
|
||||
<property name="youtube:username">
|
||||
<title>YouTube User Name</title>
|
||||
<type>d:text</type>
|
||||
<multiple>false</multiple>
|
||||
</property>
|
||||
<property name="youtube:password">
|
||||
<title>YouTube Password</title>
|
||||
<type>d:text</type>
|
||||
<multiple>false</multiple>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
|
||||
<aspect name="youtube:AssetAspect">
|
||||
<title>YouTube Asset</title>
|
||||
<description>Applied to a node that has been published to YouTube</description>
|
||||
<properties>
|
||||
<property name="youtube:assetId">
|
||||
<title>YouTube Video Id</title>
|
||||
<type>d:text</type>
|
||||
</property>
|
||||
<property name="youtube:playerUrl">
|
||||
<title>YouTube Player URL</title>
|
||||
<type>d:text</type>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
</aspects>
|
||||
</model>
|
@@ -47,7 +47,7 @@
|
||||
</bean>
|
||||
|
||||
<!-- Channel Type Implementations -->
|
||||
<bean id="baseChannelType" class="org.alfresco.repo.publishing.AbstractChannelType" abstract="true" >
|
||||
<bean id="baseChannelType" class="org.alfresco.repo.publishing.AbstractChannelType" abstract="true">
|
||||
<property name="channelService" ref="channelService" />
|
||||
<property name="serviceRegistry" ref="ServiceRegistry" />
|
||||
</bean>
|
||||
@@ -74,11 +74,10 @@
|
||||
</bean>
|
||||
|
||||
<!-- Check Publishing Dependencies Action -->
|
||||
<bean id="pub_checkPublishingDependencies"
|
||||
class="org.alfresco.repo.publishing.CheckPublishingDependenciesAction" />
|
||||
<bean id="pub_checkPublishingDependencies" class="org.alfresco.repo.publishing.CheckPublishingDependenciesAction" />
|
||||
|
||||
<!-- Publish Event Action -->
|
||||
<bean id="pub_publishEvent" class="org.alfresco.repo.publishing.PublishEventAction" >
|
||||
<bean id="pub_publishEvent" class="org.alfresco.repo.publishing.PublishEventAction">
|
||||
<property name="publishingEventProcessor" ref="publishingEventProcessor" />
|
||||
</bean>
|
||||
|
||||
@@ -105,4 +104,5 @@
|
||||
|
||||
<bean id="publishingPackageSerializer" class="org.alfresco.repo.publishing.StandardPublishingPackageSerializer" />
|
||||
|
||||
<import resource="classpath:alfresco/youtube-publishing-context.xml" />
|
||||
</beans>
|
||||
|
32
config/alfresco/youtube-publishing-context.xml
Normal file
32
config/alfresco/youtube-publishing-context.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||
|
||||
<beans>
|
||||
<bean parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
|
||||
<property name="models">
|
||||
<list>
|
||||
<value>alfresco/model/youtubePublishingModel.xml</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="youtubePublishingHelper" class="org.alfresco.repo.publishing.youtube.YouTubePublishingHelper">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
</bean>
|
||||
|
||||
<bean id="publish_youtube" parent="action-executer" class="org.alfresco.repo.publishing.youtube.YouTubePublishAction">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="taggingService" ref="TaggingService" />
|
||||
<property name="contentService" ref="ContentService" />
|
||||
<property name="youTubeHelper" ref="youtubePublishingHelper" />
|
||||
</bean>
|
||||
|
||||
<bean id="unpublish_youtube" parent="action-executer" class="org.alfresco.repo.publishing.youtube.YouTubeUnpublishAction">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="youTubeHelper" ref="youtubePublishingHelper" />
|
||||
</bean>
|
||||
|
||||
<bean id="youtubeDeliveryChannelType" class="org.alfresco.repo.publishing.youtube.YouTubeChannelType" parent="baseChannelType" />
|
||||
|
||||
|
||||
</beans>
|
BIN
config/test/alfresco/TestVideoFile.MP4
Normal file
BIN
config/test/alfresco/TestVideoFile.MP4
Normal file
Binary file not shown.
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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<ChildAssociationRef> 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<ChildAssociationRef> 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;
|
||||
}
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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");
|
||||
|
||||
|
90
source/java/org/alfresco/repo/publishing/test/SiteType.java
Normal file
90
source/java/org/alfresco/repo/publishing/test/SiteType.java
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<QName> getSupportedContentTypes()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedMimetypes()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(NodeRef nodeToPublish, Map<QName, Serializable> properties)
|
||||
{
|
||||
//Deliberately blank
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unpublish(NodeRef nodeToUnpublish, Map<QName, Serializable> properties)
|
||||
{
|
||||
//Deliberately blank
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(String status, Map<QName, Serializable> properties)
|
||||
{
|
||||
//Deliberately blank
|
||||
}
|
||||
|
||||
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<QName> getSupportedContentTypes()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedMimetypes()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(NodeRef nodeToPublish, Map<QName, Serializable> properties)
|
||||
{
|
||||
//Deliberately blank
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unpublish(NodeRef nodeToUnpublish, Map<QName, Serializable> properties)
|
||||
{
|
||||
//Deliberately blank
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(String status, Map<QName, Serializable> properties)
|
||||
{
|
||||
//Deliberately blank
|
||||
}
|
||||
|
||||
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<QName> getSupportedContentTypes()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedMimetypes()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(NodeRef nodeToPublish, Map<QName, Serializable> properties)
|
||||
{
|
||||
//Deliberately blank
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unpublish(NodeRef nodeToUnpublish, Map<QName, Serializable> properties)
|
||||
{
|
||||
//Deliberately blank
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(String status, Map<QName, Serializable> properties)
|
||||
{
|
||||
//Deliberately blank
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||
|
||||
<beans>
|
||||
<bean class="org.alfresco.repo.publishing.test.TestChannelType1" parent="baseChannelType" />
|
||||
<bean class="org.alfresco.repo.publishing.test.TestChannelType2" parent="baseChannelType" />
|
||||
<bean class="org.alfresco.repo.publishing.test.TestChannelType3" parent="baseChannelType" />
|
||||
|
||||
<bean class="org.alfresco.repo.publishing.test.SiteType" init-method="init">
|
||||
<property name="policyComponent" ref="policyComponent" />
|
||||
<property name="channelService" ref="channelService" />
|
||||
</bean>
|
||||
</beans>
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<QName> getSupportedContentTypes()
|
||||
{
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getSupportedMimetypes()
|
||||
{
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(NodeRef nodeToPublish, Map<QName, Serializable> properties)
|
||||
{
|
||||
Action youtubePublishAction = actionService.createAction(YouTubePublishAction.NAME);
|
||||
actionService.executeAction(youtubePublishAction, nodeToPublish);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unpublish(NodeRef nodeToUnpublish, Map<QName, Serializable> properties)
|
||||
{
|
||||
Action youtubeUnpublishAction = actionService.createAction(YouTubeUnpublishAction.NAME);
|
||||
actionService.executeAction(youtubeUnpublishAction, nodeToUnpublish);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(String status, Map<QName, Serializable> properties)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNodeUrl(NodeRef node)
|
||||
{
|
||||
String url = null;
|
||||
if (node != null && nodeService.exists(node) && nodeService.hasAspect(node, YouTubePublishingModel.ASPECT_ASSET))
|
||||
{
|
||||
url = (String)nodeService.getProperty(node, YouTubePublishingModel.PROP_PLAYER_URL);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<String> 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<ParameterDefinition> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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");
|
||||
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
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<QName, Serializable> vidProps = new HashMap<QName, Serializable>();
|
||||
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<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
ActionService actionService = serviceRegistry.getActionService();
|
||||
Action publishAction = actionService.createAction(YouTubePublishAction.NAME);
|
||||
actionService.executeAction(publishAction, vidNode);
|
||||
Map<QName, Serializable> 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<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
nodeService.deleteNode(vidNode);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.publishing.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<ParameterDefinition> paramList)
|
||||
{
|
||||
}
|
||||
}
|
@@ -36,7 +36,6 @@ public interface ChannelType
|
||||
{
|
||||
String getId();
|
||||
QName getChannelNodeType();
|
||||
QName getContentRootNodeType();
|
||||
NodeFinder getNodeFinder();
|
||||
NodeFilter getNodeFilter();
|
||||
void publish(NodeRef nodeToPublish, Map<QName, Serializable> properties);
|
||||
|
Reference in New Issue
Block a user