mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged DEV/GDOCS to HEAD
Google Doc Integration - The following configuration must be added to your alfresco-global.properties in order to enable the googleeditable repository behaviour: googledocs.username=myuser@bob.com googledocs.password=pwd123pwd googledocs.googleeditable.enabled=true Google Docs Share Integration - Enabled via share-config (see share-config-custom.xml.sample for details) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@20018 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -506,6 +506,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- GoogleDocs subsystem -->
|
||||||
|
<bean id="googledocs" class="org.alfresco.repo.management.subsystems.ChildApplicationContextFactory" parent="abstractPropertyBackedBean">
|
||||||
|
<property name="autoStart">
|
||||||
|
<value>true</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<!-- Start the quartz scheduler -->
|
<!-- Start the quartz scheduler -->
|
||||||
|
|
||||||
<bean id="schedulerStarter" class="org.alfresco.util.SchedulerStarterBean" >
|
<bean id="schedulerStarter" class="org.alfresco.util.SchedulerStarterBean" >
|
||||||
|
@@ -1152,7 +1152,7 @@
|
|||||||
<!-- CheckOut/CheckIn Service -->
|
<!-- CheckOut/CheckIn Service -->
|
||||||
<!-- -->
|
<!-- -->
|
||||||
|
|
||||||
<bean id="checkOutCheckInService" class="org.alfresco.repo.coci.CheckOutCheckInServiceImpl">
|
<bean id="checkOutCheckInService" class="org.alfresco.repo.coci.CheckOutCheckInServiceImpl" init-method="init">
|
||||||
<property name="nodeService">
|
<property name="nodeService">
|
||||||
<ref bean="nodeService" />
|
<ref bean="nodeService" />
|
||||||
</property>
|
</property>
|
||||||
@@ -1177,6 +1177,9 @@
|
|||||||
<property name="versionableAspect">
|
<property name="versionableAspect">
|
||||||
<ref bean="versionableAspect" />
|
<ref bean="versionableAspect" />
|
||||||
</property>
|
</property>
|
||||||
|
<property name="policyComponent">
|
||||||
|
<ref bean="policyComponent" />
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="workingCopyAspect" class="org.alfresco.repo.coci.WorkingCopyAspect" init-method="init">
|
<bean id="workingCopyAspect" class="org.alfresco.repo.coci.WorkingCopyAspect" init-method="init">
|
||||||
|
@@ -256,7 +256,7 @@
|
|||||||
<mimetype mimetype="image/x-portable-pixmap" display="Pixmap Image">
|
<mimetype mimetype="image/x-portable-pixmap" display="Pixmap Image">
|
||||||
<extension>ppm</extension>
|
<extension>ppm</extension>
|
||||||
</mimetype>
|
</mimetype>
|
||||||
<mimetype mimetype="application/vnd.powerpoint" display="Microsoft PowerPoint">
|
<mimetype mimetype="application/vnd.ms-powerpoint" display="Microsoft PowerPoint">
|
||||||
<extension>ppt</extension>
|
<extension>ppt</extension>
|
||||||
<extension>pps</extension>
|
<extension>pps</extension>
|
||||||
<extension>pot</extension>
|
<extension>pot</extension>
|
||||||
@@ -338,7 +338,7 @@
|
|||||||
<mimetype mimetype="image/x-xbitmap" display="XBitmap Image">
|
<mimetype mimetype="image/x-xbitmap" display="XBitmap Image">
|
||||||
<extension>xbm</extension>
|
<extension>xbm</extension>
|
||||||
</mimetype>
|
</mimetype>
|
||||||
<mimetype mimetype="application/vnd.excel" display="Microsoft Excel">
|
<mimetype mimetype="application/vnd.ms-excel" display="Microsoft Excel">
|
||||||
<extension>xls</extension>
|
<extension>xls</extension>
|
||||||
</mimetype>
|
</mimetype>
|
||||||
<mimetype mimetype="image/x-xpixmap" display="XPixmap Image">
|
<mimetype mimetype="image/x-xpixmap" display="XPixmap Image">
|
||||||
|
57
config/alfresco/subsystems/googledocs/default/googledocs-context.xml
Executable file
57
config/alfresco/subsystems/googledocs/default/googledocs-context.xml
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd ">
|
||||||
|
|
||||||
|
<bean id="googledocs_dictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
|
||||||
|
<property name="models">
|
||||||
|
<list>
|
||||||
|
<value>alfresco/subsystems/googledocs/default/googledocs-model.xml</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="googleDocsServiceDelegate" class="com.google.gdata.client.docs.DocsService">
|
||||||
|
<constructor-arg>
|
||||||
|
<value>${googledocs.application.name}</value>
|
||||||
|
</constructor-arg>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="spreadsheetsServiceDelegate" class="com.google.gdata.client.GoogleService">
|
||||||
|
<constructor-arg index="0">
|
||||||
|
<value>${googledocs.spreadsheet.service.name}</value>
|
||||||
|
</constructor-arg>
|
||||||
|
<constructor-arg index="1">
|
||||||
|
<value>${googledocs.application.name}</value>
|
||||||
|
</constructor-arg>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="googleDocsService" class="org.alfresco.repo.googledocs.GoogleDocsServiceImpl">
|
||||||
|
<property name="googleDocumentService" ref="googleDocsServiceDelegate"/>
|
||||||
|
<property name="spreadsheetsService" ref="spreadsheetsServiceDelegate"/>
|
||||||
|
<property name="nodeService" ref="NodeService"/>
|
||||||
|
<property name="contentService" ref="ContentService"/>
|
||||||
|
<property name="personService" ref="PersonService"/>
|
||||||
|
<property name="mimetypeService" ref="mimetypeService"/>
|
||||||
|
<property name="permissionService" ref="PermissionService"/>
|
||||||
|
<property name="ownableService" ref="OwnableService"/>
|
||||||
|
<property name="authorityService" ref="AuthorityService"/>
|
||||||
|
<property name="url" value="${googledocs.url}"/>
|
||||||
|
<property name="username" value="${googledocs.username}"/>
|
||||||
|
<property name="password" value="${googledocs.password}"/>
|
||||||
|
<property name="permissionMap">
|
||||||
|
<map>
|
||||||
|
<!-- TODO this is not a complete list, needs to be expanded to cover other use cases -->
|
||||||
|
<entry key="SiteManager" value="writer"/>
|
||||||
|
<entry key="SiteCollaborator" value="writer"/>
|
||||||
|
</map>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="googleEditableAspect" class="org.alfresco.repo.googledocs.GoogleEditableAspect" init-method="init">
|
||||||
|
<property name="policyComponent" ref="policyComponent"/>
|
||||||
|
<property name="googleDocsService" ref="googleDocsService"/>
|
||||||
|
<property name="nodeService" ref="NodeService"/>
|
||||||
|
<property name="contentService" ref="ContentService"/>
|
||||||
|
<property name="dictionaryService" ref="DictionaryService"/>
|
||||||
|
<property name="enabled" value="${googledocs.googleeditable.enabled}"/>
|
||||||
|
</bean>
|
||||||
|
</beans>
|
71
config/alfresco/subsystems/googledocs/default/googledocs-model.xml
Executable file
71
config/alfresco/subsystems/googledocs/default/googledocs-model.xml
Executable file
@@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!-- Definition of Google Docs Model -->
|
||||||
|
|
||||||
|
<model name="gd:googledocs" xmlns="http://www.alfresco.org/model/dictionary/1.0">
|
||||||
|
|
||||||
|
<!-- Meta-data about the model -->
|
||||||
|
<description>Google Docs Model</description>
|
||||||
|
<author>unknown</author>
|
||||||
|
<version>1.0</version>
|
||||||
|
|
||||||
|
<!-- Imports are required to allow references to definitions in other models -->
|
||||||
|
<imports>
|
||||||
|
<!-- Import Alfresco Dictionary Definitions -->
|
||||||
|
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
|
||||||
|
</imports>
|
||||||
|
|
||||||
|
<!-- GoogleDocs Namespace -->
|
||||||
|
<namespaces>
|
||||||
|
<namespace uri="http://www.alfresco.org/model/googledocs/1.0" prefix="gd"/>
|
||||||
|
</namespaces>
|
||||||
|
|
||||||
|
<aspects>
|
||||||
|
|
||||||
|
<aspect name="gd:googleEditable">
|
||||||
|
<title>Google Editable</title>
|
||||||
|
<properties>
|
||||||
|
<property name="gd:googleEditable">
|
||||||
|
<title>Property who's only purpose is to allow the marker aspect to be automatically added.</title>
|
||||||
|
<type>d:boolean</type>
|
||||||
|
<protected>true</protected>
|
||||||
|
<default>true</default>
|
||||||
|
</property>
|
||||||
|
</properties>
|
||||||
|
</aspect>
|
||||||
|
|
||||||
|
<aspect name="gd:googleResource">
|
||||||
|
<title>Google Document</title>
|
||||||
|
<properties>
|
||||||
|
<property name="gd:url">
|
||||||
|
<title>GoogleDocs URL</title>
|
||||||
|
<type>d:text</type>
|
||||||
|
<mandatory>false</mandatory>
|
||||||
|
</property>
|
||||||
|
<property name="gd:resourceId">
|
||||||
|
<title>GoogleDocs id</title>
|
||||||
|
<type>d:text</type>
|
||||||
|
<mandatory>false</mandatory>
|
||||||
|
</property>
|
||||||
|
<property name="gd:resourceType">
|
||||||
|
<title>GoogleDocs Type</title>
|
||||||
|
<type>d:text</type>
|
||||||
|
<mandatory>false</mandatory>
|
||||||
|
</property>
|
||||||
|
</properties>
|
||||||
|
</aspect>
|
||||||
|
|
||||||
|
<!-- <aspect name="gd:googlefolder">
|
||||||
|
<title>Google Folder</title>
|
||||||
|
<properties>
|
||||||
|
<property name="gd:folderId">
|
||||||
|
<title>Google Folder Id</title>
|
||||||
|
<type>d:text</type>
|
||||||
|
<mandatory>false</mandatory>
|
||||||
|
</property>
|
||||||
|
</properties>
|
||||||
|
</aspect> -->
|
||||||
|
|
||||||
|
</aspects>
|
||||||
|
|
||||||
|
</model>
|
16
config/alfresco/subsystems/googledocs/default/googledocs.properties
Executable file
16
config/alfresco/subsystems/googledocs/default/googledocs.properties
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
# Enables google editable functionality
|
||||||
|
googledocs.googleeditable.enabled=false
|
||||||
|
|
||||||
|
# Google docs application name
|
||||||
|
googledocs.application.name=Alfresco ECM system
|
||||||
|
|
||||||
|
# Google docs URL
|
||||||
|
googledocs.url=http://docs.google.com/feeds/default/private/full
|
||||||
|
|
||||||
|
# System google docs authentication credentials
|
||||||
|
#googledocs.username=
|
||||||
|
#googledocs.password=
|
||||||
|
|
||||||
|
# Google docs spreadsheet service name
|
||||||
|
googledocs.spreadsheet.service.name=wise
|
BIN
config/alfresco/subsystems/googledocs/default/test.docx
Executable file
BIN
config/alfresco/subsystems/googledocs/default/test.docx
Executable file
Binary file not shown.
BIN
config/alfresco/subsystems/googledocs/default/test.xlsx
Normal file
BIN
config/alfresco/subsystems/googledocs/default/test.xlsx
Normal file
Binary file not shown.
@@ -19,11 +19,23 @@
|
|||||||
package org.alfresco.repo.coci;
|
package org.alfresco.repo.coci;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.BeforeCancelCheckOut;
|
||||||
|
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.BeforeCheckIn;
|
||||||
|
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.BeforeCheckOut;
|
||||||
|
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.OnCancelCheckOut;
|
||||||
|
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.OnCheckIn;
|
||||||
|
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.OnCheckOut;
|
||||||
|
import org.alfresco.repo.policy.ClassPolicyDelegate;
|
||||||
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.version.VersionableAspect;
|
import org.alfresco.repo.version.VersionableAspect;
|
||||||
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||||
@@ -48,7 +60,7 @@ import org.alfresco.service.namespace.QName;
|
|||||||
import org.springframework.extensions.surf.util.I18NUtil;
|
import org.springframework.extensions.surf.util.I18NUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Version operations service implementation
|
* Check out check in service implementation
|
||||||
*
|
*
|
||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
*/
|
*/
|
||||||
@@ -66,6 +78,14 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
|
|||||||
private static final String MSG_ALREADY_CHECKEDOUT = "coci_service.err_already_checkedout";
|
private static final String MSG_ALREADY_CHECKEDOUT = "coci_service.err_already_checkedout";
|
||||||
private static final String MSG_ERR_CANNOT_RENAME = "coci_service.err_cannot_rename";
|
private static final String MSG_ERR_CANNOT_RENAME = "coci_service.err_cannot_rename";
|
||||||
|
|
||||||
|
/** Class policy delegate's */
|
||||||
|
private ClassPolicyDelegate<BeforeCheckOut> beforeCheckOut;
|
||||||
|
private ClassPolicyDelegate<OnCheckOut> onCheckOut;
|
||||||
|
private ClassPolicyDelegate<BeforeCheckIn> beforeCheckIn;
|
||||||
|
private ClassPolicyDelegate<OnCheckIn> onCheckIn;
|
||||||
|
private ClassPolicyDelegate<BeforeCancelCheckOut> beforeCancelCheckOut;
|
||||||
|
private ClassPolicyDelegate<OnCancelCheckOut> onCancelCheckOut;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extension character, used to recalculate the working copy names
|
* Extension character, used to recalculate the working copy names
|
||||||
*/
|
*/
|
||||||
@@ -101,6 +121,9 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
|
|||||||
*/
|
*/
|
||||||
private SearchService searchService;
|
private SearchService searchService;
|
||||||
|
|
||||||
|
/** Policy component */
|
||||||
|
private PolicyComponent policyComponent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The authentication service
|
* The authentication service
|
||||||
*/
|
*/
|
||||||
@@ -147,8 +170,7 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
|
|||||||
*
|
*
|
||||||
* @param copyService the copy service
|
* @param copyService the copy service
|
||||||
*/
|
*/
|
||||||
public void setCopyService(
|
public void setCopyService(CopyService copyService)
|
||||||
CopyService copyService)
|
|
||||||
{
|
{
|
||||||
this.copyService = copyService;
|
this.copyService = copyService;
|
||||||
}
|
}
|
||||||
@@ -158,8 +180,7 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
|
|||||||
*
|
*
|
||||||
* @param authenticationService the authentication service
|
* @param authenticationService the authentication service
|
||||||
*/
|
*/
|
||||||
public void setAuthenticationService(
|
public void setAuthenticationService(AuthenticationService authenticationService)
|
||||||
AuthenticationService authenticationService)
|
|
||||||
{
|
{
|
||||||
this.authenticationService = authenticationService;
|
this.authenticationService = authenticationService;
|
||||||
}
|
}
|
||||||
@@ -194,6 +215,174 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
|
|||||||
this.versionableAspect = versionableAspect;
|
this.versionableAspect = versionableAspect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param policyComponent policy component
|
||||||
|
*/
|
||||||
|
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||||
|
{
|
||||||
|
this.policyComponent = policyComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise method
|
||||||
|
*/
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
// Register the policies
|
||||||
|
beforeCheckOut = policyComponent.registerClassPolicy(CheckOutCheckInServicePolicies.BeforeCheckOut.class);
|
||||||
|
onCheckOut = policyComponent.registerClassPolicy(CheckOutCheckInServicePolicies.OnCheckOut.class);
|
||||||
|
beforeCheckIn = policyComponent.registerClassPolicy(CheckOutCheckInServicePolicies.BeforeCheckIn.class);
|
||||||
|
onCheckIn = policyComponent.registerClassPolicy(CheckOutCheckInServicePolicies.OnCheckIn.class);
|
||||||
|
beforeCancelCheckOut = policyComponent.registerClassPolicy(CheckOutCheckInServicePolicies.BeforeCancelCheckOut.class);
|
||||||
|
onCancelCheckOut = policyComponent.registerClassPolicy(CheckOutCheckInServicePolicies.OnCancelCheckOut.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the classes of a node, including its type and aspects.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @return List<QName> list of classes
|
||||||
|
*/
|
||||||
|
private List<QName> getInvokeClasses(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
List<QName> result = new ArrayList<QName>(10);
|
||||||
|
result.add(nodeService.getType(nodeRef));
|
||||||
|
Set<QName> aspects = nodeService.getAspects(nodeRef);
|
||||||
|
for (QName aspect : aspects)
|
||||||
|
{
|
||||||
|
result.add(aspect);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke the before check out policy
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
* @param destinationParentNodeRef
|
||||||
|
* @param destinationAssocTypeQName
|
||||||
|
* @param destinationAssocQName
|
||||||
|
*/
|
||||||
|
private void invokeBeforeCheckOut(
|
||||||
|
NodeRef nodeRef,
|
||||||
|
NodeRef destinationParentNodeRef,
|
||||||
|
QName destinationAssocTypeQName,
|
||||||
|
QName destinationAssocQName)
|
||||||
|
{
|
||||||
|
List<QName> classes = getInvokeClasses(nodeRef);
|
||||||
|
for (QName invokeClass : classes)
|
||||||
|
{
|
||||||
|
Collection<BeforeCheckOut> policies = beforeCheckOut.getList(invokeClass);
|
||||||
|
for (BeforeCheckOut policy : policies)
|
||||||
|
{
|
||||||
|
policy.beforeCheckOut(nodeRef, destinationParentNodeRef, destinationAssocTypeQName, destinationAssocQName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke on the on check out policy
|
||||||
|
*
|
||||||
|
* @param workingCopy
|
||||||
|
*/
|
||||||
|
private void invokeOnCheckOut(NodeRef workingCopy)
|
||||||
|
{
|
||||||
|
List<QName> classes = getInvokeClasses(workingCopy);
|
||||||
|
for (QName invokeClass : classes)
|
||||||
|
{
|
||||||
|
Collection<OnCheckOut> policies = onCheckOut.getList(invokeClass);
|
||||||
|
for (OnCheckOut policy : policies)
|
||||||
|
{
|
||||||
|
policy.onCheckOut(workingCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke before check in policy
|
||||||
|
*
|
||||||
|
* @param workingCopyNodeRef
|
||||||
|
* @param versionProperties
|
||||||
|
* @param contentUrl
|
||||||
|
* @param keepCheckedOut
|
||||||
|
*/
|
||||||
|
private void invokeBeforeCheckIn(
|
||||||
|
NodeRef workingCopyNodeRef,
|
||||||
|
Map<String,Serializable> versionProperties,
|
||||||
|
String contentUrl,
|
||||||
|
boolean keepCheckedOut)
|
||||||
|
{
|
||||||
|
List<QName> classes = getInvokeClasses(workingCopyNodeRef);
|
||||||
|
for (QName invokeClass : classes)
|
||||||
|
{
|
||||||
|
Collection<BeforeCheckIn> policies = beforeCheckIn.getList(invokeClass);
|
||||||
|
for (BeforeCheckIn policy : policies)
|
||||||
|
{
|
||||||
|
policy.beforeCheckIn(workingCopyNodeRef, versionProperties, contentUrl, keepCheckedOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke on check in policy
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
*/
|
||||||
|
private void invokeOnCheckIn(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
List<QName> classes = getInvokeClasses(nodeRef);
|
||||||
|
for (QName invokeClass : classes)
|
||||||
|
{
|
||||||
|
Collection<OnCheckIn> policies = onCheckIn.getList(invokeClass);
|
||||||
|
for (OnCheckIn policy : policies)
|
||||||
|
{
|
||||||
|
policy.onCheckIn(nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke before cancel check out
|
||||||
|
*
|
||||||
|
* @param workingCopy
|
||||||
|
*/
|
||||||
|
private void invokeBeforeCancelCheckOut(NodeRef workingCopy)
|
||||||
|
{
|
||||||
|
List<QName> classes = getInvokeClasses(workingCopy);
|
||||||
|
for (QName invokeClass : classes)
|
||||||
|
{
|
||||||
|
Collection<BeforeCancelCheckOut> policies = beforeCancelCheckOut.getList(invokeClass);
|
||||||
|
for (BeforeCancelCheckOut policy : policies)
|
||||||
|
{
|
||||||
|
policy.beforeCancelCheckOut(workingCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke on cancel check out
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
*/
|
||||||
|
private void invokeOnCancelCheckOut(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
List<QName> classes = getInvokeClasses(nodeRef);
|
||||||
|
for (QName invokeClass : classes)
|
||||||
|
{
|
||||||
|
Collection<OnCancelCheckOut> policies = onCancelCheckOut.getList(invokeClass);
|
||||||
|
for (OnCancelCheckOut policy : policies)
|
||||||
|
{
|
||||||
|
policy.onCancelCheckOut(nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.service.cmr.coci.CheckOutCheckInService#checkout(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, org.alfresco.service.namespace.QName)
|
* @see org.alfresco.service.cmr.coci.CheckOutCheckInService#checkout(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, org.alfresco.service.namespace.QName)
|
||||||
*/
|
*/
|
||||||
@@ -221,6 +410,9 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
|
|||||||
this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_LOCKABLE, null);
|
this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_LOCKABLE, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Invoke before check out policy
|
||||||
|
invokeBeforeCheckOut(nodeRef, destinationParentNodeRef, destinationAssocTypeQName, destinationAssocQName);
|
||||||
|
|
||||||
// Rename the working copy
|
// Rename the working copy
|
||||||
String copyName = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
String copyName = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||||
copyName = createWorkingCopyName(copyName);
|
copyName = createWorkingCopyName(copyName);
|
||||||
@@ -251,9 +443,12 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
|
|||||||
workingCopyProperties.put(ContentModel.PROP_WORKING_COPY_OWNER, userName);
|
workingCopyProperties.put(ContentModel.PROP_WORKING_COPY_OWNER, userName);
|
||||||
this.nodeService.addAspect(workingCopy, ContentModel.ASPECT_WORKING_COPY, workingCopyProperties);
|
this.nodeService.addAspect(workingCopy, ContentModel.ASPECT_WORKING_COPY, workingCopyProperties);
|
||||||
|
|
||||||
// Lock the origional node
|
// Lock the original node
|
||||||
this.lockService.lock(nodeRef, LockType.READ_ONLY_LOCK);
|
this.lockService.lock(nodeRef, LockType.READ_ONLY_LOCK);
|
||||||
|
|
||||||
|
// Invoke on check out policy
|
||||||
|
invokeOnCheckOut(workingCopy);
|
||||||
|
|
||||||
// Return the working copy
|
// Return the working copy
|
||||||
return workingCopy;
|
return workingCopy;
|
||||||
}
|
}
|
||||||
@@ -309,115 +504,111 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
|
|||||||
// Check that the working node still has the copy aspect applied
|
// Check that the working node still has the copy aspect applied
|
||||||
if (this.nodeService.hasAspect(workingCopyNodeRef, ContentModel.ASPECT_COPIEDFROM) == true)
|
if (this.nodeService.hasAspect(workingCopyNodeRef, ContentModel.ASPECT_COPIEDFROM) == true)
|
||||||
{
|
{
|
||||||
// Disable versionable behaviours since we don't want the auto version policy behaviour to execute when we check-in
|
// Invoke policy
|
||||||
//this.versionableAspect.disableAutoVersion();
|
invokeBeforeCheckIn(workingCopyNodeRef, versionProperties, contentUrl, keepCheckedOut);
|
||||||
//try
|
|
||||||
//{
|
|
||||||
Map<QName, Serializable> workingCopyProperties = nodeService.getProperties(workingCopyNodeRef);
|
|
||||||
// Try and get the original node reference
|
|
||||||
nodeRef = (NodeRef) workingCopyProperties.get(ContentModel.PROP_COPY_REFERENCE);
|
|
||||||
if(nodeRef == null)
|
|
||||||
{
|
|
||||||
// Error since the original node can not be found
|
|
||||||
throw new CheckOutCheckInServiceException(MSG_ERR_BAD_COPY);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
Map<QName, Serializable> workingCopyProperties = nodeService.getProperties(workingCopyNodeRef);
|
||||||
{
|
// Try and get the original node reference
|
||||||
// Release the lock
|
nodeRef = (NodeRef) workingCopyProperties.get(ContentModel.PROP_COPY_REFERENCE);
|
||||||
this.lockService.unlock(nodeRef);
|
if(nodeRef == null)
|
||||||
}
|
{
|
||||||
catch (UnableToReleaseLockException exception)
|
// Error since the original node can not be found
|
||||||
{
|
throw new CheckOutCheckInServiceException(MSG_ERR_BAD_COPY);
|
||||||
throw new CheckOutCheckInServiceException(MSG_ERR_NOT_OWNER, exception);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (contentUrl != null)
|
try
|
||||||
{
|
{
|
||||||
ContentData contentData = (ContentData) workingCopyProperties.get(ContentModel.PROP_CONTENT);
|
// Release the lock
|
||||||
if (contentData == null)
|
this.lockService.unlock(nodeRef);
|
||||||
{
|
}
|
||||||
throw new AlfrescoRuntimeException(MSG_ERR_WORKINGCOPY_HAS_NO_MIMETYPE, new Object[]{workingCopyNodeRef});
|
catch (UnableToReleaseLockException exception)
|
||||||
}
|
{
|
||||||
else
|
throw new CheckOutCheckInServiceException(MSG_ERR_NOT_OWNER, exception);
|
||||||
{
|
}
|
||||||
contentData = new ContentData(
|
|
||||||
contentUrl,
|
|
||||||
contentData.getMimetype(),
|
|
||||||
contentData.getSize(),
|
|
||||||
contentData.getEncoding());
|
|
||||||
}
|
|
||||||
// Set the content url value onto the working copy
|
|
||||||
this.nodeService.setProperty(
|
|
||||||
workingCopyNodeRef,
|
|
||||||
ContentModel.PROP_CONTENT,
|
|
||||||
contentData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the contents of the working copy onto the original
|
if (contentUrl != null)
|
||||||
this.copyService.copy(workingCopyNodeRef, nodeRef);
|
{
|
||||||
|
ContentData contentData = (ContentData) workingCopyProperties.get(ContentModel.PROP_CONTENT);
|
||||||
// Handle name change on working copy (only for folders/files)
|
if (contentData == null)
|
||||||
if (fileFolderService.getFileInfo(workingCopyNodeRef) != null)
|
|
||||||
{
|
{
|
||||||
String origName = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
throw new AlfrescoRuntimeException(MSG_ERR_WORKINGCOPY_HAS_NO_MIMETYPE, new Object[]{workingCopyNodeRef});
|
||||||
String name = (String)this.nodeService.getProperty(workingCopyNodeRef, ContentModel.PROP_NAME);
|
|
||||||
if (hasWorkingCopyNameChanged(name, origName))
|
|
||||||
{
|
|
||||||
// ensure working copy has working copy label in its name to avoid name clash
|
|
||||||
if (!name.contains(" " + getWorkingCopyLabel()))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
fileFolderService.rename(workingCopyNodeRef, createWorkingCopyName(name));
|
|
||||||
}
|
|
||||||
catch (FileExistsException e)
|
|
||||||
{
|
|
||||||
throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, name, createWorkingCopyName(name));
|
|
||||||
}
|
|
||||||
catch (FileNotFoundException e)
|
|
||||||
{
|
|
||||||
throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, name, createWorkingCopyName(name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// rename original to changed working name
|
|
||||||
fileFolderService.rename(nodeRef, getNameFromWorkingCopyName(name));
|
|
||||||
}
|
|
||||||
catch (FileExistsException e)
|
|
||||||
{
|
|
||||||
throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, origName, getNameFromWorkingCopyName(name));
|
|
||||||
}
|
|
||||||
catch (FileNotFoundException e)
|
|
||||||
{
|
|
||||||
throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, name, getNameFromWorkingCopyName(name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (versionProperties != null && this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) == true)
|
|
||||||
{
|
|
||||||
// Create the new version
|
|
||||||
this.versionService.createVersion(nodeRef, versionProperties);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keepCheckedOut == false)
|
|
||||||
{
|
|
||||||
// Delete the working copy
|
|
||||||
this.nodeService.deleteNode(workingCopyNodeRef);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Re-lock the original node
|
contentData = new ContentData(
|
||||||
this.lockService.lock(nodeRef, LockType.READ_ONLY_LOCK);
|
contentUrl,
|
||||||
|
contentData.getMimetype(),
|
||||||
|
contentData.getSize(),
|
||||||
|
contentData.getEncoding());
|
||||||
}
|
}
|
||||||
//}
|
// Set the content url value onto the working copy
|
||||||
//finally
|
this.nodeService.setProperty(
|
||||||
//{
|
workingCopyNodeRef,
|
||||||
// this.versionableAspect.enableAutoVersion();
|
ContentModel.PROP_CONTENT,
|
||||||
//}
|
contentData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the contents of the working copy onto the original
|
||||||
|
this.copyService.copy(workingCopyNodeRef, nodeRef);
|
||||||
|
|
||||||
|
// Handle name change on working copy (only for folders/files)
|
||||||
|
if (fileFolderService.getFileInfo(workingCopyNodeRef) != null)
|
||||||
|
{
|
||||||
|
String origName = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||||
|
String name = (String)this.nodeService.getProperty(workingCopyNodeRef, ContentModel.PROP_NAME);
|
||||||
|
if (hasWorkingCopyNameChanged(name, origName))
|
||||||
|
{
|
||||||
|
// ensure working copy has working copy label in its name to avoid name clash
|
||||||
|
if (!name.contains(" " + getWorkingCopyLabel()))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
fileFolderService.rename(workingCopyNodeRef, createWorkingCopyName(name));
|
||||||
|
}
|
||||||
|
catch (FileExistsException e)
|
||||||
|
{
|
||||||
|
throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, name, createWorkingCopyName(name));
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException e)
|
||||||
|
{
|
||||||
|
throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, name, createWorkingCopyName(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// rename original to changed working name
|
||||||
|
fileFolderService.rename(nodeRef, getNameFromWorkingCopyName(name));
|
||||||
|
}
|
||||||
|
catch (FileExistsException e)
|
||||||
|
{
|
||||||
|
throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, origName, getNameFromWorkingCopyName(name));
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException e)
|
||||||
|
{
|
||||||
|
throw new CheckOutCheckInServiceException(e, MSG_ERR_CANNOT_RENAME, name, getNameFromWorkingCopyName(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (versionProperties != null && this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) == true)
|
||||||
|
{
|
||||||
|
// Create the new version
|
||||||
|
this.versionService.createVersion(nodeRef, versionProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keepCheckedOut == false)
|
||||||
|
{
|
||||||
|
// Delete the working copy
|
||||||
|
this.nodeService.deleteNode(workingCopyNodeRef);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Re-lock the original node
|
||||||
|
this.lockService.lock(nodeRef, LockType.READ_ONLY_LOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoke policy
|
||||||
|
invokeOnCheckIn(nodeRef);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -466,6 +657,9 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
|
|||||||
// Ensure that the node has the copy aspect
|
// Ensure that the node has the copy aspect
|
||||||
if (this.nodeService.hasAspect(workingCopyNodeRef, ContentModel.ASPECT_COPIEDFROM) == true)
|
if (this.nodeService.hasAspect(workingCopyNodeRef, ContentModel.ASPECT_COPIEDFROM) == true)
|
||||||
{
|
{
|
||||||
|
// Invoke policy
|
||||||
|
invokeBeforeCancelCheckOut(workingCopyNodeRef);
|
||||||
|
|
||||||
// Get the original node
|
// Get the original node
|
||||||
nodeRef = (NodeRef)this.nodeService.getProperty(workingCopyNodeRef, ContentModel.PROP_COPY_REFERENCE);
|
nodeRef = (NodeRef)this.nodeService.getProperty(workingCopyNodeRef, ContentModel.PROP_COPY_REFERENCE);
|
||||||
if (nodeRef == null)
|
if (nodeRef == null)
|
||||||
@@ -479,6 +673,9 @@ public class CheckOutCheckInServiceImpl implements CheckOutCheckInService
|
|||||||
|
|
||||||
// Delete the working copy
|
// Delete the working copy
|
||||||
this.nodeService.deleteNode(workingCopyNodeRef);
|
this.nodeService.deleteNode(workingCopyNodeRef);
|
||||||
|
|
||||||
|
// Invoke policy
|
||||||
|
invokeOnCancelCheckOut(nodeRef);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
130
source/java/org/alfresco/repo/coci/CheckOutCheckInServicePolicies.java
Executable file
130
source/java/org/alfresco/repo/coci/CheckOutCheckInServicePolicies.java
Executable file
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* 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.coci;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.repo.policy.ClassPolicy;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Policy interfaces for the check in/check out service
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
*/
|
||||||
|
public interface CheckOutCheckInServicePolicies
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface BeforeCheckOut extends ClassPolicy
|
||||||
|
{
|
||||||
|
static final QName QNAME = QName.createQName(NamespaceService.ALFRESCO_URI, "beforeCheckOut");
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
*/
|
||||||
|
void beforeCheckOut(
|
||||||
|
NodeRef nodeRef,
|
||||||
|
NodeRef destinationParentNodeRef,
|
||||||
|
QName destinationAssocTypeQName,
|
||||||
|
QName destinationAssocQName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface OnCheckOut extends ClassPolicy
|
||||||
|
{
|
||||||
|
static final QName QNAME = QName.createQName(NamespaceService.ALFRESCO_URI, "onCheckOut");
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
*/
|
||||||
|
void onCheckOut(NodeRef workingCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface BeforeCheckIn extends ClassPolicy
|
||||||
|
{
|
||||||
|
static final QName QNAME = QName.createQName(NamespaceService.ALFRESCO_URI, "beforeCheckIn");
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param workingCopyNodeRef
|
||||||
|
* @param versionProperties
|
||||||
|
* @param contentUrl
|
||||||
|
* @param keepCheckedOut
|
||||||
|
*/
|
||||||
|
void beforeCheckIn(
|
||||||
|
NodeRef workingCopyNodeRef,
|
||||||
|
Map<String,Serializable> versionProperties,
|
||||||
|
String contentUrl,
|
||||||
|
boolean keepCheckedOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface OnCheckIn extends ClassPolicy
|
||||||
|
{
|
||||||
|
static final QName QNAME = QName.createQName(NamespaceService.ALFRESCO_URI, "onCheckIn");
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
*/
|
||||||
|
void onCheckIn(NodeRef nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface BeforeCancelCheckOut extends ClassPolicy
|
||||||
|
{
|
||||||
|
static final QName QNAME = QName.createQName(NamespaceService.ALFRESCO_URI, "beforeCancelCheckOut");
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
*/
|
||||||
|
void beforeCancelCheckOut(NodeRef workingCopyNodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface OnCancelCheckOut extends ClassPolicy
|
||||||
|
{
|
||||||
|
static final QName QNAME = QName.createQName(NamespaceService.ALFRESCO_URI, "onCancelCheckOut");
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
*/
|
||||||
|
void onCancelCheckOut(NodeRef nodeRef);
|
||||||
|
}
|
||||||
|
}
|
@@ -29,7 +29,6 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.springframework.extensions.surf.util.I18NUtil;
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.action.ActionServiceImpl;
|
import org.alfresco.repo.action.ActionServiceImpl;
|
||||||
import org.alfresco.repo.copy.CopyBehaviourCallback.ChildAssocCopyAction;
|
import org.alfresco.repo.copy.CopyBehaviourCallback.ChildAssocCopyAction;
|
||||||
@@ -38,7 +37,6 @@ import org.alfresco.repo.copy.CopyBehaviourCallback.CopyChildAssociationDetails;
|
|||||||
import org.alfresco.repo.policy.ClassPolicyDelegate;
|
import org.alfresco.repo.policy.ClassPolicyDelegate;
|
||||||
import org.alfresco.repo.policy.JavaBehaviour;
|
import org.alfresco.repo.policy.JavaBehaviour;
|
||||||
import org.alfresco.repo.policy.PolicyComponent;
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
||||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
|
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
|
||||||
@@ -54,17 +52,16 @@ import org.alfresco.service.cmr.repository.NodeService;
|
|||||||
import org.alfresco.service.cmr.rule.RuleService;
|
import org.alfresco.service.cmr.rule.RuleService;
|
||||||
import org.alfresco.service.cmr.search.ResultSet;
|
import org.alfresco.service.cmr.search.ResultSet;
|
||||||
import org.alfresco.service.cmr.search.SearchService;
|
import org.alfresco.service.cmr.search.SearchService;
|
||||||
import org.alfresco.service.cmr.security.AccessPermission;
|
|
||||||
import org.alfresco.service.cmr.security.AccessStatus;
|
|
||||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||||
import org.alfresco.service.cmr.security.PermissionService;
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
import org.alfresco.util.GUID;
|
import org.alfresco.util.GUID;
|
||||||
import org.springframework.extensions.surf.util.ParameterCheck;
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.extensions.surf.util.I18NUtil;
|
||||||
|
import org.springframework.extensions.surf.util.ParameterCheck;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node operations service implmentation.
|
* Node operations service implmentation.
|
||||||
|
37
source/java/org/alfresco/repo/googledocs/GoogleDocsModel.java
Executable file
37
source/java/org/alfresco/repo/googledocs/GoogleDocsModel.java
Executable file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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.googledocs;
|
||||||
|
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Google docs model constants
|
||||||
|
*/
|
||||||
|
public interface GoogleDocsModel
|
||||||
|
{
|
||||||
|
static final String GOOGLE_DOCS_PREFIX = "gd";
|
||||||
|
static final String GOOGLE_DOCS_MODEL_1_0_URI = "http://www.alfresco.org/model/googledocs/1.0";
|
||||||
|
|
||||||
|
static final QName ASPECT_GOOGLEEDITABLE = QName.createQName(GOOGLE_DOCS_MODEL_1_0_URI, "googleEditable");
|
||||||
|
|
||||||
|
static final QName ASPECT_GOOGLERESOURCE = QName.createQName(GOOGLE_DOCS_MODEL_1_0_URI, "googleResource");
|
||||||
|
static final QName PROP_URL = QName.createQName(GOOGLE_DOCS_MODEL_1_0_URI, "url");
|
||||||
|
static final QName PROP_RESOURCE_ID = QName.createQName(GOOGLE_DOCS_MODEL_1_0_URI, "resourceId");
|
||||||
|
static final QName PROP_RESOURCE_TYPE = QName.createQName(GOOGLE_DOCS_MODEL_1_0_URI, "resourceType");
|
||||||
|
}
|
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.googledocs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Google docs permission context
|
||||||
|
*/
|
||||||
|
public enum GoogleDocsPermissionContext
|
||||||
|
{
|
||||||
|
PRIVATE,
|
||||||
|
SHARE_READ,
|
||||||
|
SHARE_WRITE,
|
||||||
|
SHARE_READWRITE
|
||||||
|
}
|
43
source/java/org/alfresco/repo/googledocs/GoogleDocsService.java
Executable file
43
source/java/org/alfresco/repo/googledocs/GoogleDocsService.java
Executable file
@@ -0,0 +1,43 @@
|
|||||||
|
package org.alfresco.repo.googledocs;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Google docs integration service interface
|
||||||
|
*/
|
||||||
|
public interface GoogleDocsService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a google doc from a given node. The content of the node will be used
|
||||||
|
* as a basis of the associated google doc. If the node has no content a new, empty google
|
||||||
|
* doc of the correct type will be created.
|
||||||
|
*
|
||||||
|
* The permission context provides information about how google sharing permissions should be
|
||||||
|
* set on the created google doc.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @param permissionContext permission context
|
||||||
|
*/
|
||||||
|
void createGoogleDoc(NodeRef nodeRef, GoogleDocsPermissionContext permissionContext);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the google resource associated with the node reference. This could be a folder or
|
||||||
|
* document.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
*/
|
||||||
|
void deleteGoogleResource(NodeRef nodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the content as an input stream of google doc associated with the given node. The
|
||||||
|
* node must have the google resource aspect and the associated resource should not be a
|
||||||
|
* folder.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @return InputStream the content of the associated google doc
|
||||||
|
*/
|
||||||
|
InputStream getGoogleDocContent(NodeRef nodeRef);
|
||||||
|
|
||||||
|
}
|
814
source/java/org/alfresco/repo/googledocs/GoogleDocsServiceImpl.java
Executable file
814
source/java/org/alfresco/repo/googledocs/GoogleDocsServiceImpl.java
Executable file
@@ -0,0 +1,814 @@
|
|||||||
|
/*
|
||||||
|
* 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.googledocs;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
|
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.security.AccessPermission;
|
||||||
|
import org.alfresco.service.cmr.security.AuthorityService;
|
||||||
|
import org.alfresco.service.cmr.security.AuthorityType;
|
||||||
|
import org.alfresco.service.cmr.security.OwnableService;
|
||||||
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.ParameterCheck;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import com.google.gdata.client.GoogleService;
|
||||||
|
import com.google.gdata.client.docs.DocsService;
|
||||||
|
import com.google.gdata.data.IEntry;
|
||||||
|
import com.google.gdata.data.MediaContent;
|
||||||
|
import com.google.gdata.data.PlainTextConstruct;
|
||||||
|
import com.google.gdata.data.acl.AclEntry;
|
||||||
|
import com.google.gdata.data.acl.AclFeed;
|
||||||
|
import com.google.gdata.data.acl.AclRole;
|
||||||
|
import com.google.gdata.data.acl.AclScope;
|
||||||
|
import com.google.gdata.data.docs.DocumentEntry;
|
||||||
|
import com.google.gdata.data.docs.DocumentListEntry;
|
||||||
|
import com.google.gdata.data.docs.FolderEntry;
|
||||||
|
import com.google.gdata.data.docs.PresentationEntry;
|
||||||
|
import com.google.gdata.data.media.MediaSource;
|
||||||
|
import com.google.gdata.data.media.MediaStreamSource;
|
||||||
|
import com.google.gdata.util.AuthenticationException;
|
||||||
|
import com.google.gdata.util.ContentType;
|
||||||
|
import com.google.gdata.util.ServiceException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel
|
||||||
|
{
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static Log logger = LogFactory.getLog(GoogleDocsServiceImpl.class);
|
||||||
|
|
||||||
|
public static final String TYPE_DOCUMENT = "document";
|
||||||
|
public static final String TYPE_SPREADSHEET = "spreadsheet";
|
||||||
|
public static final String TYPE_PRESENTATION = "presentation";
|
||||||
|
public static final String TYPE_PDF = "pdf";
|
||||||
|
|
||||||
|
/** Services */
|
||||||
|
private DocsService googleDocumentService;
|
||||||
|
private GoogleService spreadsheetsService;
|
||||||
|
private NodeService nodeService;
|
||||||
|
private ContentService contentService;
|
||||||
|
private PersonService personService;
|
||||||
|
private MimetypeService mimetypeService;
|
||||||
|
private PermissionService permissionService;
|
||||||
|
private OwnableService ownableService;
|
||||||
|
private AuthorityService authorityService;
|
||||||
|
|
||||||
|
/** GoogleDoc base feed url */
|
||||||
|
private String url = "http://docs.google.com/feeds/default/private/full";
|
||||||
|
|
||||||
|
/** Authentication credentials */
|
||||||
|
private boolean initialised = false;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private Map<String, String> permissionMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param googleDocumentService google document service
|
||||||
|
*/
|
||||||
|
public void setGoogleDocumentService(DocsService googleDocumentService)
|
||||||
|
{
|
||||||
|
this.googleDocumentService = googleDocumentService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param spreadsheetsService spread sheets service
|
||||||
|
*/
|
||||||
|
public void setSpreadsheetsService(GoogleService spreadsheetsService)
|
||||||
|
{
|
||||||
|
this.spreadsheetsService = spreadsheetsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nodeService node service
|
||||||
|
*/
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param contentService content service
|
||||||
|
*/
|
||||||
|
public void setContentService(ContentService contentService)
|
||||||
|
{
|
||||||
|
this.contentService = contentService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param personService person service
|
||||||
|
*/
|
||||||
|
public void setPersonService(PersonService personService)
|
||||||
|
{
|
||||||
|
this.personService = personService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mimetypeService mime type service
|
||||||
|
*/
|
||||||
|
public void setMimetypeService(MimetypeService mimetypeService)
|
||||||
|
{
|
||||||
|
this.mimetypeService = mimetypeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param permissionService permission service
|
||||||
|
*/
|
||||||
|
public void setPermissionService(PermissionService permissionService)
|
||||||
|
{
|
||||||
|
this.permissionService = permissionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param ownableService ownable service
|
||||||
|
*/
|
||||||
|
public void setOwnableService(OwnableService ownableService)
|
||||||
|
{
|
||||||
|
this.ownableService = ownableService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param authorityService authority service
|
||||||
|
*/
|
||||||
|
public void setAuthorityService(AuthorityService authorityService)
|
||||||
|
{
|
||||||
|
this.authorityService = authorityService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param url root googleDoc URL
|
||||||
|
*/
|
||||||
|
public void setUrl(String url)
|
||||||
|
{
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param username google service user name
|
||||||
|
*/
|
||||||
|
public void setUsername(String username)
|
||||||
|
{
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param password google service password
|
||||||
|
*/
|
||||||
|
public void setPassword(String password)
|
||||||
|
{
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param permissionMap permission map
|
||||||
|
*/
|
||||||
|
public void setPermissionMap(Map<String, String> permissionMap)
|
||||||
|
{
|
||||||
|
this.permissionMap = permissionMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise google docs services
|
||||||
|
*/
|
||||||
|
public void initialiseGoogleDocsService()
|
||||||
|
{
|
||||||
|
if (initialised == false)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled() == true)
|
||||||
|
{
|
||||||
|
logger.debug("Trying to initialise google docs service for user " + username);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (username == null ||username.length() == 0 || password == null)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("No Goolge Docs credentials found. Please set the Google Docs authentication configuration.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
googleDocumentService.setUserCredentials(username, password);
|
||||||
|
spreadsheetsService.setUserCredentials(username, password);
|
||||||
|
googleDocumentService.setChunkedMediaUpload(-1);
|
||||||
|
}
|
||||||
|
catch (AuthenticationException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to connect to Google Docs. Please check the Google Docs authentication configuration.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialised = true;
|
||||||
|
if (logger.isDebugEnabled() == true)
|
||||||
|
{
|
||||||
|
logger.debug("Successfully initialised google docs service for user " + username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.google.docs.GoogleDocsService#upload(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
public void createGoogleDoc(NodeRef nodeRef, GoogleDocsPermissionContext permissionContext)
|
||||||
|
{
|
||||||
|
// Check for mandatory parameters
|
||||||
|
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||||
|
|
||||||
|
// Initialise google doc services
|
||||||
|
initialiseGoogleDocsService();
|
||||||
|
|
||||||
|
// Get property values
|
||||||
|
String name = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||||
|
|
||||||
|
// TODO should be checking to make sure this doesn't already have an associated google doc
|
||||||
|
|
||||||
|
// Get content reader
|
||||||
|
String mimetype = null;
|
||||||
|
InputStream is = null;
|
||||||
|
ContentReader contentReader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
||||||
|
if (contentReader == null)
|
||||||
|
{
|
||||||
|
// Determine the mimetype from the file extension
|
||||||
|
mimetype = mimetypeService.guessMimetype(name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get the mime type and input stream from the content reader
|
||||||
|
mimetype = contentReader.getMimetype();
|
||||||
|
is = contentReader.getContentInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the parent folder id
|
||||||
|
DocumentListEntry parentFolder = getParentFolder(nodeRef);
|
||||||
|
|
||||||
|
// Create the new google document
|
||||||
|
DocumentListEntry document = createGoogleDocument(name, mimetype, parentFolder, is);
|
||||||
|
|
||||||
|
// Set permissions
|
||||||
|
setGoogleResourcePermissions(nodeRef, document, permissionContext);
|
||||||
|
|
||||||
|
// Set the google document details
|
||||||
|
setResourceDetails(nodeRef, document);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.google.docs.GoogleDocsService#deleteGoogleResource(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
public void deleteGoogleResource(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
// Check for mandatory parameters
|
||||||
|
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||||
|
|
||||||
|
// Initialise google doc services
|
||||||
|
initialiseGoogleDocsService();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (nodeService.hasAspect(nodeRef, ASPECT_GOOGLERESOURCE) == true)
|
||||||
|
{
|
||||||
|
// Get the entry
|
||||||
|
DocumentListEntry entry = getDocumentListEntry(nodeRef);
|
||||||
|
if (entry == null)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to find google resource to delete for node " + nodeRef.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the entry
|
||||||
|
entry.delete();
|
||||||
|
|
||||||
|
// Remove the aspect from the node
|
||||||
|
nodeService.removeAspect(nodeRef, ASPECT_GOOGLERESOURCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ServiceException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to delete google resource for the node "+ nodeRef.toString());
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to delete google resource for the node "+ nodeRef.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
* @param resourceId
|
||||||
|
* @param permissionContext
|
||||||
|
*/
|
||||||
|
private void setGoogleResourcePermissions(NodeRef nodeRef, DocumentListEntry resource, GoogleDocsPermissionContext permissionContext)
|
||||||
|
{
|
||||||
|
// Set the owner of the document
|
||||||
|
String owner = ownableService.getOwner(nodeRef);
|
||||||
|
setGoogleResourcePermission(resource, AuthorityType.USER, owner, "owner");
|
||||||
|
|
||||||
|
if (GoogleDocsPermissionContext.PRIVATE.equals(permissionContext) == false)
|
||||||
|
{
|
||||||
|
Set<AccessPermission> accessPermissions = permissionService.getAllSetPermissions(nodeRef);
|
||||||
|
for (AccessPermission accessPermission : accessPermissions)
|
||||||
|
{
|
||||||
|
String authorityName = accessPermission.getAuthority();
|
||||||
|
AuthorityType authorityType = accessPermission.getAuthorityType();
|
||||||
|
String permission = accessPermission.getPermission();
|
||||||
|
if (permissionMap.containsKey(permission) == true)
|
||||||
|
{
|
||||||
|
String aclRole = permissionMap.get(permission);
|
||||||
|
if (GoogleDocsPermissionContext.SHARE_READ.equals(permissionContext) == true &&
|
||||||
|
("reader".equals(aclRole) == true || "writer".equals(aclRole) == true))
|
||||||
|
{
|
||||||
|
// Set the permission to read
|
||||||
|
setGoogleResourcePermission(resource, authorityType, authorityName, "reader");
|
||||||
|
}
|
||||||
|
else if (GoogleDocsPermissionContext.SHARE_WRITE.equals(permissionContext) == true &&
|
||||||
|
"writer".equals(aclRole) == true)
|
||||||
|
{
|
||||||
|
// Set the permission to write
|
||||||
|
setGoogleResourcePermission(resource, authorityType, authorityName, "writer");
|
||||||
|
}
|
||||||
|
else if (GoogleDocsPermissionContext.SHARE_READWRITE.equals(permissionContext) == true &&
|
||||||
|
("reader".equals(aclRole) == true || "writer".equals(aclRole) == true))
|
||||||
|
{
|
||||||
|
// Set the permission to the current acl
|
||||||
|
setGoogleResourcePermission(resource, authorityType, authorityName, aclRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param resourceId
|
||||||
|
* @param authorityType
|
||||||
|
* @param authorityName
|
||||||
|
* @param role
|
||||||
|
*/
|
||||||
|
private void setGoogleResourcePermission(DocumentListEntry resource, AuthorityType authorityType, String authorityName, String role)
|
||||||
|
{
|
||||||
|
if (AuthorityType.USER.equals(authorityType) == true)
|
||||||
|
{
|
||||||
|
// Set the user permissions on the resource
|
||||||
|
String userEMail = getUserEMail(authorityName);
|
||||||
|
if (userEMail != null && userEMail.length() != 0)
|
||||||
|
{
|
||||||
|
setGoogleResourcePermission(resource, userEMail, role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (AuthorityType.GROUP.equals(authorityType) == true)
|
||||||
|
{
|
||||||
|
Set<String> childAuthorities = authorityService.getContainedAuthorities(AuthorityType.USER, authorityName, false);
|
||||||
|
for (String childAuthority : childAuthorities)
|
||||||
|
{
|
||||||
|
setGoogleResourcePermission(resource, AuthorityType.USER, childAuthority, role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param userName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getUserEMail(String userName)
|
||||||
|
{
|
||||||
|
String email = null;
|
||||||
|
NodeRef personNodeRef = personService.getPerson(userName);
|
||||||
|
if (personNodeRef != null)
|
||||||
|
{
|
||||||
|
email = (String) nodeService.getProperty(personNodeRef, ContentModel.PROP_EMAIL);
|
||||||
|
}
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private DocumentListEntry getParentFolder(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
DocumentListEntry folder = null;
|
||||||
|
|
||||||
|
NodeRef parentNodeRef = nodeService.getPrimaryParent(nodeRef).getParentRef();
|
||||||
|
if (parentNodeRef != null)
|
||||||
|
{
|
||||||
|
if (nodeService.hasAspect(parentNodeRef, ASPECT_GOOGLERESOURCE) == true)
|
||||||
|
{
|
||||||
|
String resourceType = (String)nodeService.getProperty(parentNodeRef, PROP_RESOURCE_TYPE);
|
||||||
|
String resourceId = (String)nodeService.getProperty(parentNodeRef, PROP_RESOURCE_ID);
|
||||||
|
folder = getDocumentListEntry(resourceType + ":" + resourceId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DocumentListEntry parentFolder = getParentFolder(parentNodeRef);
|
||||||
|
String name = (String)nodeService.getProperty(parentNodeRef, ContentModel.PROP_NAME);
|
||||||
|
folder = createGoogleFolder(name, parentFolder);
|
||||||
|
|
||||||
|
setResourceDetails(parentNodeRef, folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
* @param folderId
|
||||||
|
*/
|
||||||
|
private void setResourceDetails(final NodeRef nodeRef, final DocumentListEntry documentListEntry)
|
||||||
|
{
|
||||||
|
AuthenticationUtil.RunAsWork<Object> runAsWork = new AuthenticationUtil.RunAsWork<Object>()
|
||||||
|
{
|
||||||
|
public Object doWork() throws Exception
|
||||||
|
{
|
||||||
|
// Create a map of the property values
|
||||||
|
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1);
|
||||||
|
props.put(GoogleDocsModel.PROP_RESOURCE_ID, documentListEntry.getDocId());
|
||||||
|
props.put(GoogleDocsModel.PROP_RESOURCE_TYPE, documentListEntry.getType());
|
||||||
|
props.put(GoogleDocsModel.PROP_URL, documentListEntry.getDocumentLink().getHref());
|
||||||
|
|
||||||
|
// Add the google resource aspect
|
||||||
|
nodeService.addAspect(nodeRef, GoogleDocsModel.ASPECT_GOOGLERESOURCE, props);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run as admin
|
||||||
|
AuthenticationUtil.runAs(runAsWork, AuthenticationUtil.getAdminUserName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.google.docs.GoogleDocsService#getGoogleDocContent(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
public InputStream getGoogleDocContent(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
InputStream result = null;
|
||||||
|
|
||||||
|
// Check for mandatory parameters
|
||||||
|
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||||
|
|
||||||
|
// Initialise google doc services
|
||||||
|
initialiseGoogleDocsService();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (nodeService.hasAspect(nodeRef, ASPECT_GOOGLERESOURCE) == true)
|
||||||
|
{
|
||||||
|
String downloadUrl = null;
|
||||||
|
DocumentListEntry document = getDocumentListEntry(nodeRef);
|
||||||
|
String docType = document.getType();
|
||||||
|
|
||||||
|
ContentData contentData = (ContentData) nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
|
||||||
|
String fileExtension = mimetypeService.getExtension(contentData.getMimetype());
|
||||||
|
if (fileExtension.equals("docx"))
|
||||||
|
{
|
||||||
|
fileExtension = "doc";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (docType.equals(TYPE_DOCUMENT) || docType.equals(TYPE_PRESENTATION))
|
||||||
|
{
|
||||||
|
downloadUrl = ((MediaContent)document.getContent()).getUri() + "&exportFormat=" + fileExtension;
|
||||||
|
}
|
||||||
|
else if (docType.equals(TYPE_SPREADSHEET))
|
||||||
|
{
|
||||||
|
downloadUrl = ((MediaContent)document.getContent()).getUri() + "&exportFormat=" + fileExtension;
|
||||||
|
|
||||||
|
// If exporting to .csv or .tsv, add the gid parameter to specify which sheet to export
|
||||||
|
if (fileExtension.equals("csv") || fileExtension.equals("tsv"))
|
||||||
|
{
|
||||||
|
downloadUrl += "&gid=0"; // gid=0 will download only the first sheet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (docType.equals(TYPE_PDF))
|
||||||
|
{
|
||||||
|
MediaContent mc = (MediaContent)document.getContent();
|
||||||
|
downloadUrl = mc.getUri();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unsuported document type: " + docType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO need to verify that download of a spreadsheet works before we delete this historical code ...
|
||||||
|
|
||||||
|
// UserToken docsToken = null;
|
||||||
|
// if (isSpreadSheet)
|
||||||
|
// {
|
||||||
|
// docsToken = (UserToken) googleDocumentService.getAuthTokenFactory().getAuthToken();
|
||||||
|
// UserToken spreadsheetsToken = (UserToken) spreadsheetsService.getAuthTokenFactory().getAuthToken();
|
||||||
|
// googleDocumentService.setUserToken(spreadsheetsToken.getValue());
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
MediaContent mc = new MediaContent();
|
||||||
|
mc.setUri(downloadUrl);
|
||||||
|
MediaSource ms = googleDocumentService.getMedia(mc);
|
||||||
|
|
||||||
|
// if (isSpreadSheet)
|
||||||
|
// {
|
||||||
|
// googleDocumentService.setUserToken(docsToken.getValue());
|
||||||
|
// }
|
||||||
|
|
||||||
|
result = ms.getInputStream();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// error since we are trying to download a non-google resource
|
||||||
|
throw new AlfrescoRuntimeException("Can not download google doc content since no corresponsing google resource could be found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ServiceException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to get google document stream.", e);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to get google document stream.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param docNodeRef
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private DocumentListEntry getDocumentListEntry(NodeRef docNodeRef)
|
||||||
|
{
|
||||||
|
String docType = (String)nodeService.getProperty(docNodeRef, PROP_RESOURCE_TYPE);
|
||||||
|
String docId = (String)nodeService.getProperty(docNodeRef, PROP_RESOURCE_ID);
|
||||||
|
return getDocumentListEntry(docType + ":" + docId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param docResourceId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private DocumentListEntry getDocumentListEntry(String docResourceId)
|
||||||
|
{
|
||||||
|
return getEntry(docResourceId, DocumentListEntry.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param <E>
|
||||||
|
* @param resourceId
|
||||||
|
* @param entryClass
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private <E extends IEntry> E getEntry(String resourceId, Class<E> entryClass)
|
||||||
|
{
|
||||||
|
E result = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
URL docEntryURL = new URL(url + "/" + resourceId);
|
||||||
|
result = googleDocumentService.getEntry(docEntryURL, entryClass);
|
||||||
|
}
|
||||||
|
catch (ServiceException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to get document list entry for resource " + resourceId, e);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to get document list entry for resource " + resourceId, e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @param mimetype
|
||||||
|
* @param parentFolder
|
||||||
|
* @param is
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private DocumentListEntry createGoogleDocument(String name, String mimetype, DocumentListEntry parentFolder, InputStream is)
|
||||||
|
{
|
||||||
|
DocumentListEntry document = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Create the media content object
|
||||||
|
MediaContent mediaContent = new MediaContent();
|
||||||
|
mediaContent.setMimeType(new ContentType(mimetype));
|
||||||
|
|
||||||
|
if (is != null)
|
||||||
|
{
|
||||||
|
mediaContent.setMediaSource(new MediaStreamSource(is, mimetype));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parent folder url
|
||||||
|
String parentFolderUrl = url;
|
||||||
|
if (parentFolder != null)
|
||||||
|
{
|
||||||
|
parentFolderUrl = ((MediaContent)parentFolder.getContent()).getUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the document entry object
|
||||||
|
DocumentListEntry docEntry = null;
|
||||||
|
if (MimetypeMap.MIMETYPE_EXCEL.equals(mimetype) == true)
|
||||||
|
{
|
||||||
|
docEntry = new PresentationEntry();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
docEntry = new DocumentEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
docEntry.setContent(mediaContent);
|
||||||
|
docEntry.setTitle(new PlainTextConstruct(name));
|
||||||
|
|
||||||
|
// Upload the document into the parent folder
|
||||||
|
document = googleDocumentService.insert(
|
||||||
|
new URL(parentFolderUrl),
|
||||||
|
docEntry);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to create google document", e);
|
||||||
|
}
|
||||||
|
catch (ServiceException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to create google document", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param docResourceId
|
||||||
|
* @param mimeType
|
||||||
|
* @param is
|
||||||
|
*/
|
||||||
|
private void updateGoogleDocContent(DocumentListEntry document, String mimeType, InputStream is)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Update the existing content
|
||||||
|
googleDocumentService.getRequestFactory().setHeader("If-Match", "*");
|
||||||
|
document.setMediaSource(new MediaStreamSource(is, mimeType));
|
||||||
|
document.updateMedia(false);
|
||||||
|
googleDocumentService.getRequestFactory().setHeader("If-Match", null);
|
||||||
|
}
|
||||||
|
catch (ServiceException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to update documents content in google docs", e);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to update documents content in google docs", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param folderName
|
||||||
|
* @param parentFolderId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private DocumentListEntry createGoogleFolder(String folderName, DocumentListEntry parentFolder)
|
||||||
|
{
|
||||||
|
DocumentListEntry folderEntry = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Parent folder url
|
||||||
|
String parentFolderUrl = url;
|
||||||
|
if (parentFolder != null)
|
||||||
|
{
|
||||||
|
parentFolderUrl = ((MediaContent)parentFolder.getContent()).getUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the folder entry
|
||||||
|
FolderEntry folder = new FolderEntry();
|
||||||
|
folder.setTitle(new PlainTextConstruct(folderName));
|
||||||
|
|
||||||
|
// Create the folder
|
||||||
|
folderEntry = googleDocumentService.insert(
|
||||||
|
new URL(parentFolderUrl),
|
||||||
|
folder);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to create Google Folder", e);
|
||||||
|
}
|
||||||
|
catch (ServiceException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to create Google Folder", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return folderEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set permissions on a googleDoc resource
|
||||||
|
*
|
||||||
|
* @param resourceId
|
||||||
|
* @param email
|
||||||
|
* @param role
|
||||||
|
*/
|
||||||
|
private void setGoogleResourcePermission(DocumentListEntry resource, String email, String role)
|
||||||
|
{
|
||||||
|
ParameterCheck.mandatory("resource", resource);
|
||||||
|
ParameterCheck.mandatory("email", email);
|
||||||
|
ParameterCheck.mandatory("role", role);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AclRole aclRole = new AclRole(role);
|
||||||
|
AclScope scope = new AclScope(AclScope.Type.USER, email);
|
||||||
|
|
||||||
|
// Get the URL
|
||||||
|
URL aclFeedLinkURL = new URL(resource.getAclFeedLink().getHref());
|
||||||
|
|
||||||
|
// See if we have already set this permission or not
|
||||||
|
AclEntry aclEntry = null;
|
||||||
|
AclFeed aclFeed = googleDocumentService.getFeed(aclFeedLinkURL, AclFeed.class);
|
||||||
|
if (aclFeed != null)
|
||||||
|
{
|
||||||
|
List<AclEntry> aclEntries = aclFeed.getEntries();
|
||||||
|
for (AclEntry tempAclEntry : aclEntries)
|
||||||
|
{
|
||||||
|
AclScope tempScope = tempAclEntry.getScope();
|
||||||
|
if (tempScope.equals(scope) == true)
|
||||||
|
{
|
||||||
|
// Existing ACL entry found
|
||||||
|
aclEntry = tempAclEntry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aclEntry == null)
|
||||||
|
{
|
||||||
|
aclEntry = new AclEntry();
|
||||||
|
aclEntry.setRole(aclRole);
|
||||||
|
aclEntry.setScope(scope);
|
||||||
|
googleDocumentService.insert(aclFeedLinkURL, aclEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO for now we will not 'update' the permissions if they have already been set ....
|
||||||
|
//
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// AclRole currentAclRole = aclEntry.getRole();
|
||||||
|
// if (currentAclRole.toString().equals(aclRole.toString()) == false)
|
||||||
|
// {
|
||||||
|
// aclEntry.setRole(aclRole);
|
||||||
|
// googleDocumentService.update(new URL(aclEntry.getEditLink().getHref()), aclEntry);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
catch (ServiceException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to set premissions on google document", e);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to set premissions on google document", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
278
source/java/org/alfresco/repo/googledocs/GoogleDocumentServiceTest.java
Executable file
278
source/java/org/alfresco/repo/googledocs/GoogleDocumentServiceTest.java
Executable file
@@ -0,0 +1,278 @@
|
|||||||
|
/*
|
||||||
|
* 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.googledocs;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
|
||||||
|
import javax.transaction.UserTransaction;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
|
import org.alfresco.repo.management.subsystems.ApplicationContextFactory;
|
||||||
|
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.site.SiteServiceImpl;
|
||||||
|
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||||
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
||||||
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
|
import org.alfresco.service.cmr.site.SiteService;
|
||||||
|
import org.alfresco.service.cmr.site.SiteVisibility;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
|
import org.alfresco.util.GUID;
|
||||||
|
import org.alfresco.util.PropertyMap;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
|
import com.google.gdata.util.ServiceException;
|
||||||
|
|
||||||
|
public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsModel
|
||||||
|
{
|
||||||
|
private NodeService nodeService;
|
||||||
|
private GoogleDocsService googleDocsService;
|
||||||
|
private SiteService siteService;
|
||||||
|
private TransactionService transactionService;
|
||||||
|
private FileFolderService fileFolderService;
|
||||||
|
private ContentService contentService;
|
||||||
|
private CheckOutCheckInService checkOutCheckInService;
|
||||||
|
private MutableAuthenticationService authenticationService;
|
||||||
|
private PersonService personService;
|
||||||
|
private ApplicationContextFactory subsystem;
|
||||||
|
|
||||||
|
private static final String USER_ONE = "GoogleDocUserOne";
|
||||||
|
private static final String USER_TWO = "GoogleDocUserTwo";
|
||||||
|
private static final String USER_THREE = "GoogleDocUserThree";
|
||||||
|
private static final String USER_FOUR = "GoogleDocUserFour";
|
||||||
|
//private static final String EMAIL_DOMAIN = "@alfresco.com";
|
||||||
|
|
||||||
|
private NodeRef folder = null;
|
||||||
|
private NodeRef nodeRefDoc = null;
|
||||||
|
private NodeRef nodeRefSpread = null;
|
||||||
|
private NodeRef nodeRefPres = null;
|
||||||
|
private NodeRef nodeRefPdf = null;
|
||||||
|
private NodeRef nodeRef2 = null;
|
||||||
|
private UserTransaction userTransaction = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
ApplicationContext appContext = ApplicationContextHelper.getApplicationContext();
|
||||||
|
|
||||||
|
nodeService = (NodeService)appContext.getBean("nodeService");
|
||||||
|
siteService = (SiteService)appContext.getBean("siteService");
|
||||||
|
transactionService = (TransactionService)appContext.getBean("transactionService");
|
||||||
|
fileFolderService = (FileFolderService)appContext.getBean("fileFolderService");
|
||||||
|
contentService = (ContentService)appContext.getBean("contentService");
|
||||||
|
checkOutCheckInService = (CheckOutCheckInService)appContext.getBean("checkOutCheckInService");
|
||||||
|
authenticationService = (MutableAuthenticationService)appContext.getBean("authenticationService");
|
||||||
|
personService = (PersonService)appContext.getBean("personService");
|
||||||
|
|
||||||
|
// Start the user transaction
|
||||||
|
userTransaction = transactionService.getUserTransaction();
|
||||||
|
userTransaction.begin();
|
||||||
|
|
||||||
|
// Get the sub-system and make sure the googleeditable feature is turned on
|
||||||
|
subsystem = (ApplicationContextFactory)appContext.getBean("googledocs");
|
||||||
|
if (subsystem.getProperty("googledocs.googleeditable.enabled").equals("false") == true)
|
||||||
|
{
|
||||||
|
subsystem.stop();
|
||||||
|
subsystem.setProperty("googledocs.googleeditable.enabled", "true");
|
||||||
|
subsystem.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the google docs service
|
||||||
|
ConfigurableApplicationContext childContext = (ConfigurableApplicationContext)subsystem.getApplicationContext();
|
||||||
|
googleDocsService = (GoogleDocsService)childContext.getBean("googleDocsService");
|
||||||
|
|
||||||
|
// Create the test users
|
||||||
|
createUser(USER_ONE, "rwetherall@alfresco.com");
|
||||||
|
createUser(USER_TWO, "rwetherall@activiti.com");
|
||||||
|
createUser(USER_THREE, "roy.wetherall@alfresco.com");
|
||||||
|
createUser(USER_FOUR, "roy.wetherall@activiti.com");
|
||||||
|
|
||||||
|
// Authenticate as user one
|
||||||
|
AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE);
|
||||||
|
|
||||||
|
String id = GUID.generate();
|
||||||
|
|
||||||
|
// Create a site to use as holder for our test google documents
|
||||||
|
siteService.createSite("sitePreset", id, "My Title", "My Description", SiteVisibility.PUBLIC);
|
||||||
|
NodeRef container = siteService.createContainer(id, "testComponent", null, null);
|
||||||
|
|
||||||
|
// Add some memberships to the site
|
||||||
|
siteService.setMembership(id, USER_TWO, SiteServiceImpl.SITE_COLLABORATOR);
|
||||||
|
siteService.setMembership(id, USER_THREE, SiteServiceImpl.SITE_CONTRIBUTOR);
|
||||||
|
siteService.setMembership(id, USER_FOUR, SiteServiceImpl.SITE_CONSUMER);
|
||||||
|
|
||||||
|
// Create a folder in our site container
|
||||||
|
folder = fileFolderService.create(container, "myfolder", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||||
|
|
||||||
|
// Create test documents
|
||||||
|
nodeRefDoc = createTestDocument("mydoc.docx", "alfresco/subsystems/googledocs/default/test.docx", MimetypeMap.MIMETYPE_WORD);
|
||||||
|
nodeRefSpread = createTestDocument("mydoc.xlsx", "alfresco/subsystems/googledocs/default/test.xlsx", MimetypeMap.MIMETYPE_EXCEL);
|
||||||
|
|
||||||
|
// Create an empty content node (simulate creation of a new google doc in UI)
|
||||||
|
nodeRef2 = fileFolderService.create(folder, "mygoogledoc.doc", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
|
nodeService.addAspect(nodeRef2, ASPECT_GOOGLEEDITABLE, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeRef createTestDocument(String name, String contentPath, String mimetype)
|
||||||
|
{
|
||||||
|
NodeRef nodeRef = fileFolderService.create(folder, name, ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
|
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||||
|
writer.setEncoding("UTF-8");
|
||||||
|
writer.setMimetype(mimetype);
|
||||||
|
InputStream is = getClass().getClassLoader().getResourceAsStream(contentPath);
|
||||||
|
writer.putContent(is);
|
||||||
|
return nodeRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createUser(String userName, String email)
|
||||||
|
{
|
||||||
|
if (authenticationService.authenticationExists(userName) == false)
|
||||||
|
{
|
||||||
|
authenticationService.createAuthentication(userName, "PWD".toCharArray());
|
||||||
|
|
||||||
|
PropertyMap ppOne = new PropertyMap(4);
|
||||||
|
ppOne.put(ContentModel.PROP_USERNAME, userName);
|
||||||
|
ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName");
|
||||||
|
ppOne.put(ContentModel.PROP_LASTNAME, "lastName");
|
||||||
|
ppOne.put(ContentModel.PROP_EMAIL, email);
|
||||||
|
ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle");
|
||||||
|
|
||||||
|
personService.createPerson(ppOne);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
if (userTransaction != null)
|
||||||
|
{
|
||||||
|
userTransaction.rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGoogleDocUploadDownload() throws Exception
|
||||||
|
{
|
||||||
|
googleDocsService.createGoogleDoc(nodeRefDoc, GoogleDocsPermissionContext.SHARE_WRITE);
|
||||||
|
|
||||||
|
assertTrue(nodeService.hasAspect(nodeRefDoc, ASPECT_GOOGLERESOURCE));
|
||||||
|
assertNotNull(nodeService.getProperty(nodeRefDoc, PROP_URL));
|
||||||
|
assertNotNull(nodeService.getProperty(nodeRefDoc, PROP_RESOURCE_ID));
|
||||||
|
assertNotNull(nodeService.getProperty(nodeRefDoc, PROP_RESOURCE_TYPE));
|
||||||
|
|
||||||
|
System.out.println("Google doc URL: " + nodeService.getProperty(nodeRefDoc, PROP_URL));
|
||||||
|
System.out.println("Google doc type: " + nodeService.getProperty(nodeRefDoc, PROP_RESOURCE_TYPE));
|
||||||
|
System.out.println("Google doc id: " + nodeService.getProperty(nodeRefDoc, PROP_RESOURCE_ID));
|
||||||
|
String downloadFile = downloadFile(googleDocsService.getGoogleDocContent(nodeRefDoc), ".doc");
|
||||||
|
System.out.println("Download file: " + downloadFile);
|
||||||
|
|
||||||
|
// googleDocsService.upload(nodeRefSpread, GoogleDocsPermissionContext.SHARE_WRITE);
|
||||||
|
//
|
||||||
|
// assertTrue(nodeService.hasAspect(nodeRefSpread, ASPECT_GOOGLERESOURCE));
|
||||||
|
// assertNotNull(nodeService.getProperty(nodeRefSpread, PROP_URL));
|
||||||
|
// assertNotNull(nodeService.getProperty(nodeRefSpread, PROP_RESOURCE_ID));
|
||||||
|
// assertNotNull(nodeService.getProperty(nodeRefSpread, PROP_RESOURCE_TYPE));
|
||||||
|
//
|
||||||
|
// System.out.println("Google doc URL: " + nodeService.getProperty(nodeRefSpread, PROP_URL));
|
||||||
|
// System.out.println("Google doc type: " + nodeService.getProperty(nodeRefSpread, PROP_RESOURCE_TYPE));
|
||||||
|
// System.out.println("Google doc id: " + nodeService.getProperty(nodeRefSpread, PROP_RESOURCE_ID));
|
||||||
|
// downloadFile = downloadFile(googleDocsService.download(nodeRefSpread), ".xls");
|
||||||
|
// System.out.println("Download file: " + downloadFile);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCheckOutCheckIn() throws Exception
|
||||||
|
{
|
||||||
|
ContentReader contentReader = contentService.getReader(nodeRef2, ContentModel.PROP_CONTENT);
|
||||||
|
assertNull(contentReader);
|
||||||
|
|
||||||
|
// Check out the empty google document
|
||||||
|
NodeRef workingCopy = checkOutCheckInService.checkout(nodeRef2);
|
||||||
|
|
||||||
|
assertTrue(nodeService.hasAspect(workingCopy, ASPECT_GOOGLERESOURCE));
|
||||||
|
assertNotNull(nodeService.getProperty(workingCopy, PROP_URL));
|
||||||
|
assertNotNull(nodeService.getProperty(workingCopy, PROP_RESOURCE_ID));
|
||||||
|
assertNotNull(nodeService.getProperty(workingCopy, PROP_RESOURCE_TYPE));
|
||||||
|
|
||||||
|
System.out.println("Google doc URL: " + nodeService.getProperty(workingCopy, PROP_URL));
|
||||||
|
System.out.println("Google doc type: " + nodeService.getProperty(workingCopy, PROP_RESOURCE_TYPE));
|
||||||
|
System.out.println("Google doc id: " + nodeService.getProperty(workingCopy, PROP_RESOURCE_ID));
|
||||||
|
|
||||||
|
checkOutCheckInService.checkin(workingCopy, null);
|
||||||
|
|
||||||
|
assertFalse(nodeService.hasAspect(nodeRefDoc, ASPECT_GOOGLERESOURCE));
|
||||||
|
contentReader = contentService.getReader(nodeRef2, ContentModel.PROP_CONTENT);
|
||||||
|
assertNotNull(contentReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility method to download input stream to a file for inspection
|
||||||
|
*
|
||||||
|
* @param inStream
|
||||||
|
* @param ext
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
* @throws MalformedURLException
|
||||||
|
* @throws ServiceException
|
||||||
|
*/
|
||||||
|
private String downloadFile(InputStream inStream, String ext) throws IOException, MalformedURLException, ServiceException
|
||||||
|
{
|
||||||
|
File file = File.createTempFile("googleDocTest", ext);
|
||||||
|
String filePath = file.getAbsolutePath();
|
||||||
|
FileOutputStream outStream = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
outStream = new FileOutputStream(filePath);
|
||||||
|
|
||||||
|
int c;
|
||||||
|
while ((c = inStream.read()) != -1)
|
||||||
|
{
|
||||||
|
outStream.write(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (inStream != null)
|
||||||
|
{
|
||||||
|
inStream.close();
|
||||||
|
}
|
||||||
|
if (outStream != null)
|
||||||
|
{
|
||||||
|
outStream.flush();
|
||||||
|
outStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
}
|
206
source/java/org/alfresco/repo/googledocs/GoogleEditableAspect.java
Executable file
206
source/java/org/alfresco/repo/googledocs/GoogleEditableAspect.java
Executable file
@@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* 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.googledocs;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies;
|
||||||
|
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.BeforeCancelCheckOut;
|
||||||
|
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.OnCheckIn;
|
||||||
|
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.OnCheckOut;
|
||||||
|
import org.alfresco.repo.node.NodeServicePolicies;
|
||||||
|
import org.alfresco.repo.node.NodeServicePolicies.OnAddAspectPolicy;
|
||||||
|
import org.alfresco.repo.policy.JavaBehaviour;
|
||||||
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
|
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
|
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.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Behaviour associated with google editable documents
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class GoogleEditableAspect implements NodeServicePolicies.OnAddAspectPolicy,
|
||||||
|
CheckOutCheckInServicePolicies.OnCheckOut,
|
||||||
|
CheckOutCheckInServicePolicies.OnCheckIn,
|
||||||
|
CheckOutCheckInServicePolicies.BeforeCancelCheckOut
|
||||||
|
{
|
||||||
|
/** Indicates whether behaviour is enabled or not */
|
||||||
|
boolean enabled = false;
|
||||||
|
|
||||||
|
/** Policy component */
|
||||||
|
private PolicyComponent policyComponent;
|
||||||
|
|
||||||
|
/** Google docs service */
|
||||||
|
private GoogleDocsService googleDocsService;
|
||||||
|
|
||||||
|
/** Node service */
|
||||||
|
private NodeService nodeService;
|
||||||
|
|
||||||
|
/** Dictionary service */
|
||||||
|
private DictionaryService dictionaryService;
|
||||||
|
|
||||||
|
/** Content service */
|
||||||
|
private ContentService contentService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param enabled true if behaviour enabled, false otherwise
|
||||||
|
*/
|
||||||
|
public void setEnabled(boolean enabled)
|
||||||
|
{
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param policyComponent policy component
|
||||||
|
*/
|
||||||
|
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||||
|
{
|
||||||
|
this.policyComponent = policyComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param googleDocsService google docs service
|
||||||
|
*/
|
||||||
|
public void setGoogleDocsService(GoogleDocsService googleDocsService)
|
||||||
|
{
|
||||||
|
this.googleDocsService = googleDocsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nodeService node service
|
||||||
|
*/
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dictionaryService dictionary service
|
||||||
|
*/
|
||||||
|
public void setDictionaryService(DictionaryService dictionaryService)
|
||||||
|
{
|
||||||
|
this.dictionaryService = dictionaryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param contentService content service
|
||||||
|
*/
|
||||||
|
public void setContentService(ContentService contentService)
|
||||||
|
{
|
||||||
|
this.contentService = contentService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise method
|
||||||
|
*/
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
if (enabled == true)
|
||||||
|
{
|
||||||
|
// Register behaviour with policy component
|
||||||
|
policyComponent.bindClassBehaviour(OnAddAspectPolicy.QNAME,
|
||||||
|
GoogleDocsModel.ASPECT_GOOGLEEDITABLE ,
|
||||||
|
new JavaBehaviour(this, "onAddAspect", NotificationFrequency.FIRST_EVENT));
|
||||||
|
policyComponent.bindClassBehaviour(OnCheckOut.QNAME,
|
||||||
|
GoogleDocsModel.ASPECT_GOOGLEEDITABLE,
|
||||||
|
new JavaBehaviour(this, "onCheckOut", NotificationFrequency.FIRST_EVENT));
|
||||||
|
policyComponent.bindClassBehaviour(OnCheckIn.QNAME,
|
||||||
|
GoogleDocsModel.ASPECT_GOOGLEEDITABLE,
|
||||||
|
new JavaBehaviour(this, "onCheckIn", NotificationFrequency.FIRST_EVENT));
|
||||||
|
policyComponent.bindClassBehaviour(BeforeCancelCheckOut.QNAME,
|
||||||
|
GoogleDocsModel.ASPECT_GOOGLEEDITABLE,
|
||||||
|
new JavaBehaviour(this, "beforeCancelCheckOut", NotificationFrequency.FIRST_EVENT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.repo.node.NodeServicePolicies.OnAddAspectPolicy#onAddAspect(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName)
|
||||||
|
*/
|
||||||
|
public void onAddAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||||
|
{
|
||||||
|
if (nodeService.exists(nodeRef) == true)
|
||||||
|
{
|
||||||
|
// Can only make cm:content descendant google editable
|
||||||
|
QName type = nodeService.getType(nodeRef);
|
||||||
|
if (dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) == false)
|
||||||
|
{
|
||||||
|
// Prevent aspect from being applied
|
||||||
|
throw new AlfrescoRuntimeException("The node (" + nodeRef.toString() + ") can not be made google editable, because it is not a sub type of cm:content.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.repo.coci.CheckOutCheckInServicePolicies.OnCheckOut#onCheckOut(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
public void onCheckOut(NodeRef workingCopy)
|
||||||
|
{
|
||||||
|
if (nodeService.exists(workingCopy) == true)
|
||||||
|
{
|
||||||
|
// Remove the google editable aspect from the working copy
|
||||||
|
nodeService.removeAspect(workingCopy, GoogleDocsModel.ASPECT_GOOGLEEDITABLE);
|
||||||
|
|
||||||
|
// Upload the content of the working copy to google docs
|
||||||
|
googleDocsService.createGoogleDoc(workingCopy, GoogleDocsPermissionContext.SHARE_WRITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.repo.coci.CheckOutCheckInServicePolicies.OnCheckIn#onCheckIn(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
public void onCheckIn(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
if (nodeService.exists(nodeRef) == true &&
|
||||||
|
nodeService.hasAspect(nodeRef, GoogleDocsModel.ASPECT_GOOGLERESOURCE) == true)
|
||||||
|
{
|
||||||
|
// Get input stream for the google doc
|
||||||
|
InputStream is = googleDocsService.getGoogleDocContent(nodeRef);
|
||||||
|
if (is == null)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Unable to complete check in, because the working copy content could not be retrieved from google docs.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the google content into the node
|
||||||
|
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||||
|
writer.putContent(is);
|
||||||
|
|
||||||
|
// Delete the associated google resource
|
||||||
|
googleDocsService.deleteGoogleResource(nodeRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.repo.coci.CheckOutCheckInServicePolicies.BeforeCancelCheckOut#beforeCancelCheckOut(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
public void beforeCancelCheckOut(NodeRef workingCopyNodeRef)
|
||||||
|
{
|
||||||
|
if (nodeService.exists(workingCopyNodeRef) == true)
|
||||||
|
{
|
||||||
|
// Delete the associated google resource
|
||||||
|
googleDocsService.deleteGoogleResource(workingCopyNodeRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -858,6 +858,12 @@ public class SiteServiceImpl implements SiteService, SiteModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the site implementation given a short name
|
||||||
|
*
|
||||||
|
* @param shortName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private SiteInfo getSiteImpl(String shortName)
|
private SiteInfo getSiteImpl(String shortName)
|
||||||
{
|
{
|
||||||
SiteInfo result = null;
|
SiteInfo result = null;
|
||||||
@@ -874,6 +880,45 @@ public class SiteServiceImpl implements SiteService, SiteModel
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.service.cmr.site.SiteService#getSite(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
public SiteInfo getSite(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
SiteInfo siteInfo = null;
|
||||||
|
NodeRef siteNodeRef = getSiteNodeRef(nodeRef);
|
||||||
|
if (siteNodeRef != null)
|
||||||
|
{
|
||||||
|
siteInfo = createSiteInfo(siteNodeRef);
|
||||||
|
}
|
||||||
|
return siteInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the site node reference for a particular node reference
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @return NodeRef site node reference or null if node is not in a site
|
||||||
|
*/
|
||||||
|
private NodeRef getSiteNodeRef(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
NodeRef siteNodeRef = null;
|
||||||
|
QName nodeRefType = nodeService.getType(nodeRef);
|
||||||
|
if (dictionaryService.isSubClass(TYPE_SITE, nodeRefType) == true)
|
||||||
|
{
|
||||||
|
siteNodeRef = nodeRef;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ChildAssociationRef primaryParent = nodeService.getPrimaryParent(nodeRef);
|
||||||
|
if (primaryParent != null && primaryParent.getParentRef() != null)
|
||||||
|
{
|
||||||
|
siteNodeRef = getSiteNodeRef(primaryParent.getParentRef());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return siteNodeRef;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the site's node reference based on its short name
|
* Gets the site's node reference based on its short name
|
||||||
*
|
*
|
||||||
|
@@ -98,6 +98,13 @@ public interface SiteService
|
|||||||
*/
|
*/
|
||||||
SiteInfo getSite(String shortName);
|
SiteInfo getSite(String shortName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
SiteInfo getSite(NodeRef nodeRef);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the site information.
|
* Update the site information.
|
||||||
* <P>
|
* <P>
|
||||||
|
Reference in New Issue
Block a user