mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
ALF-2703: Incorrect folder sctructure is created in Google Docs
If the transaction within which folders or documents are created within Google Docs fails then the created items will be rolledback as if part of the Alfresco transaction. This prevents the behaviour reported in this issue. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@20216 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -34,6 +34,7 @@
|
|||||||
<property name="permissionService" ref="PermissionService"/>
|
<property name="permissionService" ref="PermissionService"/>
|
||||||
<property name="ownableService" ref="OwnableService"/>
|
<property name="ownableService" ref="OwnableService"/>
|
||||||
<property name="authorityService" ref="AuthorityService"/>
|
<property name="authorityService" ref="AuthorityService"/>
|
||||||
|
<property name="dictionaryService" ref="DictionaryService"/>
|
||||||
<property name="url" value="${googledocs.url}"/>
|
<property name="url" value="${googledocs.url}"/>
|
||||||
<property name="username" value="${googledocs.username}"/>
|
<property name="username" value="${googledocs.username}"/>
|
||||||
<property name="password" value="${googledocs.password}"/>
|
<property name="password" value="${googledocs.password}"/>
|
||||||
|
@@ -22,6 +22,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -31,6 +32,9 @@ import org.alfresco.error.AlfrescoRuntimeException;
|
|||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||||
|
import org.alfresco.repo.transaction.TransactionListenerAdapter;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.repository.ContentData;
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
@@ -60,7 +64,7 @@ import com.google.gdata.data.acl.AclScope;
|
|||||||
import com.google.gdata.data.docs.DocumentEntry;
|
import com.google.gdata.data.docs.DocumentEntry;
|
||||||
import com.google.gdata.data.docs.DocumentListEntry;
|
import com.google.gdata.data.docs.DocumentListEntry;
|
||||||
import com.google.gdata.data.docs.FolderEntry;
|
import com.google.gdata.data.docs.FolderEntry;
|
||||||
import com.google.gdata.data.docs.PresentationEntry;
|
import com.google.gdata.data.docs.SpreadsheetEntry;
|
||||||
import com.google.gdata.data.media.MediaSource;
|
import com.google.gdata.data.media.MediaSource;
|
||||||
import com.google.gdata.data.media.MediaStreamSource;
|
import com.google.gdata.data.media.MediaStreamSource;
|
||||||
import com.google.gdata.util.AuthenticationException;
|
import com.google.gdata.util.AuthenticationException;
|
||||||
@@ -70,9 +74,10 @@ import com.google.gdata.util.ServiceException;
|
|||||||
/**
|
/**
|
||||||
* Google docs integration service implementation
|
* Google docs integration service implementation
|
||||||
*/
|
*/
|
||||||
public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel
|
public class GoogleDocsServiceImpl extends TransactionListenerAdapter
|
||||||
|
implements GoogleDocsService, GoogleDocsModel
|
||||||
{
|
{
|
||||||
@SuppressWarnings("unused")
|
/** Log */
|
||||||
private static Log logger = LogFactory.getLog(GoogleDocsServiceImpl.class);
|
private static Log logger = LogFactory.getLog(GoogleDocsServiceImpl.class);
|
||||||
|
|
||||||
/** Google document types */
|
/** Google document types */
|
||||||
@@ -91,6 +96,7 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel
|
|||||||
private PermissionService permissionService;
|
private PermissionService permissionService;
|
||||||
private OwnableService ownableService;
|
private OwnableService ownableService;
|
||||||
private AuthorityService authorityService;
|
private AuthorityService authorityService;
|
||||||
|
private DictionaryService dictionaryService;
|
||||||
|
|
||||||
/** GoogleDoc base feed url */
|
/** GoogleDoc base feed url */
|
||||||
private String url = "http://docs.google.com/feeds/default/private/full";
|
private String url = "http://docs.google.com/feeds/default/private/full";
|
||||||
@@ -175,6 +181,14 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel
|
|||||||
this.authorityService = authorityService;
|
this.authorityService = authorityService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dictionaryService dictionary service
|
||||||
|
*/
|
||||||
|
public void setDictionaryService(DictionaryService dictionaryService)
|
||||||
|
{
|
||||||
|
this.dictionaryService = dictionaryService;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param url root googleDoc URL
|
* @param url root googleDoc URL
|
||||||
*/
|
*/
|
||||||
@@ -448,7 +462,7 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel
|
|||||||
* @param nodeRef node reference
|
* @param nodeRef node reference
|
||||||
* @return DocumentList Entry folder resource
|
* @return DocumentList Entry folder resource
|
||||||
*/
|
*/
|
||||||
private DocumentListEntry getParentFolder(NodeRef nodeRef)
|
private DocumentListEntry getParentFolder(final NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
DocumentListEntry folder = null;
|
DocumentListEntry folder = null;
|
||||||
|
|
||||||
@@ -460,13 +474,31 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel
|
|||||||
String resourceType = (String)nodeService.getProperty(parentNodeRef, PROP_RESOURCE_TYPE);
|
String resourceType = (String)nodeService.getProperty(parentNodeRef, PROP_RESOURCE_TYPE);
|
||||||
String resourceId = (String)nodeService.getProperty(parentNodeRef, PROP_RESOURCE_ID);
|
String resourceId = (String)nodeService.getProperty(parentNodeRef, PROP_RESOURCE_ID);
|
||||||
folder = getDocumentListEntry(resourceType + ":" + resourceId);
|
folder = getDocumentListEntry(resourceType + ":" + resourceId);
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled() == true)
|
||||||
|
{
|
||||||
|
logger.debug("Found existing google folder + " + resourceId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Get the parent folder
|
||||||
DocumentListEntry parentFolder = getParentFolder(parentNodeRef);
|
DocumentListEntry parentFolder = getParentFolder(parentNodeRef);
|
||||||
String name = (String)nodeService.getProperty(parentNodeRef, ContentModel.PROP_NAME);
|
|
||||||
folder = createGoogleFolder(name, parentFolder);
|
|
||||||
|
|
||||||
|
// Determine the name of the new google folder
|
||||||
|
String name = null;
|
||||||
|
QName parentNodeType = nodeService.getType(parentNodeRef);
|
||||||
|
if (dictionaryService.isSubClass(parentNodeType, ContentModel.TYPE_STOREROOT) == true)
|
||||||
|
{
|
||||||
|
name = parentNodeRef.getStoreRef().getIdentifier();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = (String)nodeService.getProperty(parentNodeRef, ContentModel.PROP_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the folder and set the meta data in Alfresco
|
||||||
|
folder = createGoogleFolder(name, parentFolder);
|
||||||
setResourceDetails(parentNodeRef, folder);
|
setResourceDetails(parentNodeRef, folder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -694,13 +726,14 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel
|
|||||||
DocumentListEntry docEntry = null;
|
DocumentListEntry docEntry = null;
|
||||||
if (MimetypeMap.MIMETYPE_EXCEL.equals(mimetype) == true)
|
if (MimetypeMap.MIMETYPE_EXCEL.equals(mimetype) == true)
|
||||||
{
|
{
|
||||||
docEntry = new PresentationEntry();
|
docEntry = new SpreadsheetEntry();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
docEntry = new DocumentEntry();
|
docEntry = new DocumentEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the content and the title of the document
|
||||||
docEntry.setContent(mediaContent);
|
docEntry.setContent(mediaContent);
|
||||||
docEntry.setTitle(new PlainTextConstruct(name));
|
docEntry.setTitle(new PlainTextConstruct(name));
|
||||||
|
|
||||||
@@ -708,6 +741,9 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel
|
|||||||
document = googleDocumentService.insert(
|
document = googleDocumentService.insert(
|
||||||
new URL(parentFolderUrl),
|
new URL(parentFolderUrl),
|
||||||
docEntry);
|
docEntry);
|
||||||
|
|
||||||
|
// Mark create entry
|
||||||
|
markCreated(document.getResourceId());
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
@@ -816,6 +852,9 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel
|
|||||||
folderEntry = googleDocumentService.insert(
|
folderEntry = googleDocumentService.insert(
|
||||||
new URL(parentFolderUrl),
|
new URL(parentFolderUrl),
|
||||||
folder);
|
folder);
|
||||||
|
|
||||||
|
// Mark create entry
|
||||||
|
markCreated(folderEntry.getResourceId());
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
@@ -940,5 +979,68 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final static String KEY_MARKED_RESOURCES = "GoogleDocService.marked_resources";
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void markCreated(String resourceId)
|
||||||
|
{
|
||||||
|
List<String> resources = (List<String>)AlfrescoTransactionSupport.getResource(KEY_MARKED_RESOURCES);
|
||||||
|
if (resources == null)
|
||||||
|
{
|
||||||
|
// bind pending rules to the current transaction
|
||||||
|
resources = new ArrayList<String>();
|
||||||
|
AlfrescoTransactionSupport.bindResource(KEY_MARKED_RESOURCES, resources);
|
||||||
|
// bind the rule transaction listener
|
||||||
|
AlfrescoTransactionSupport.bindListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resources.contains(resourceId) == false)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled() == true)
|
||||||
|
{
|
||||||
|
logger.debug("Marking created resource " + resourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
resources.add(resourceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterCommit()
|
||||||
|
{
|
||||||
|
// TODO go ahead and delete any resources that have be queued up for deletion ....
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void afterRollback()
|
||||||
|
{
|
||||||
|
List<String> resources = (List<String>)AlfrescoTransactionSupport.getResource(KEY_MARKED_RESOURCES);
|
||||||
|
if (resources != null)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled() == true)
|
||||||
|
{
|
||||||
|
logger.debug("Transaction rolled back, manually deleting created Google Resources");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String resourceId : resources)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled() == true)
|
||||||
|
{
|
||||||
|
logger.debug("Deleting created resource " + resourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete resource
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DocumentListEntry entry = getDocumentListEntry(resourceId);
|
||||||
|
googleDocumentService.delete(new URL(entry.getEditLink().getHref() + "?delete=true"), entry.getEtag());
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,7 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
import javax.transaction.UserTransaction;
|
import javax.transaction.UserTransaction;
|
||||||
|
|
||||||
@@ -51,6 +52,10 @@ import org.alfresco.util.PropertyMap;
|
|||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
|
import com.google.gdata.client.DocumentQuery;
|
||||||
|
import com.google.gdata.client.docs.DocsService;
|
||||||
|
import com.google.gdata.data.docs.DocumentListEntry;
|
||||||
|
import com.google.gdata.data.docs.DocumentListFeed;
|
||||||
import com.google.gdata.util.ServiceException;
|
import com.google.gdata.util.ServiceException;
|
||||||
|
|
||||||
public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsModel
|
public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsModel
|
||||||
@@ -147,7 +152,7 @@ public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsMod
|
|||||||
// Create test documents
|
// Create test documents
|
||||||
nodeRefDoc = createTestDocument("mydoc.docx", "alfresco/subsystems/googledocs/default/test.docx", MimetypeMap.MIMETYPE_WORD);
|
nodeRefDoc = createTestDocument("mydoc.docx", "alfresco/subsystems/googledocs/default/test.docx", MimetypeMap.MIMETYPE_WORD);
|
||||||
//nodeRefSpread = createTestDocument("mydoc.xls", "alfresco/subsystems/googledocs/default/testBook.xls", MimetypeMap.MIMETYPE_EXCEL);
|
//nodeRefSpread = createTestDocument("mydoc.xls", "alfresco/subsystems/googledocs/default/testBook.xls", MimetypeMap.MIMETYPE_EXCEL);
|
||||||
nodeRefSpread = createTestDocument("mydoc2.docx", "alfresco/subsystems/googledocs/default/test.docx", MimetypeMap.MIMETYPE_WORD);
|
nodeRefSpread = createTestDocument("mydoc2.xlsx", "alfresco/subsystems/googledocs/default/test.xlsx", MimetypeMap.MIMETYPE_EXCEL);
|
||||||
|
|
||||||
// Create an empty content node (simulate creation of a new google doc in UI)
|
// Create an empty content node (simulate creation of a new google doc in UI)
|
||||||
nodeRef2 = fileFolderService.create(folder, "mygoogledoc.doc", ContentModel.TYPE_CONTENT).getNodeRef();
|
nodeRef2 = fileFolderService.create(folder, "mygoogledoc.doc", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
@@ -225,12 +230,24 @@ public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsMod
|
|||||||
assertNotNull(nodeService.getProperty(nodeRefDoc, PROP_RESOURCE_ID));
|
assertNotNull(nodeService.getProperty(nodeRefDoc, PROP_RESOURCE_ID));
|
||||||
assertNotNull(nodeService.getProperty(nodeRefDoc, PROP_RESOURCE_TYPE));
|
assertNotNull(nodeService.getProperty(nodeRefDoc, PROP_RESOURCE_TYPE));
|
||||||
|
|
||||||
|
System.out.println("For node ref " + nodeRefDoc.toString());
|
||||||
System.out.println("Google doc URL: " + nodeService.getProperty(nodeRefDoc, PROP_URL));
|
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 type: " + nodeService.getProperty(nodeRefDoc, PROP_RESOURCE_TYPE));
|
||||||
System.out.println("Google doc id: " + nodeService.getProperty(nodeRefDoc, PROP_RESOURCE_ID));
|
System.out.println("Google doc id: " + nodeService.getProperty(nodeRefDoc, PROP_RESOURCE_ID));
|
||||||
String downloadFile = downloadFile(googleDocsService.getGoogleDocContent(nodeRefDoc), ".doc");
|
String downloadFile = downloadFile(googleDocsService.getGoogleDocContent(nodeRefDoc), ".doc");
|
||||||
System.out.println("Download file: " + downloadFile);
|
System.out.println("Download file: " + downloadFile);
|
||||||
|
|
||||||
|
DocsService client = new DocsService("Alfresco");
|
||||||
|
client.setUserCredentials("rwetherall@alfresco.com", "123test123");
|
||||||
|
|
||||||
|
URL feedUri = new URL("https://docs.google.com/feeds/default/private/full/");
|
||||||
|
DocumentQuery query = new DocumentQuery(feedUri);
|
||||||
|
query.setTitleExact(true);
|
||||||
|
query.setTitleQuery((String)nodeService.getProperty(nodeRefDoc, ContentModel.PROP_NAME));
|
||||||
|
DocumentListFeed feed = client.getFeed(query, DocumentListFeed.class);
|
||||||
|
printDocuments(feed);
|
||||||
|
|
||||||
|
|
||||||
googleDocsService.createGoogleDoc(nodeRefSpread, GoogleDocsPermissionContext.SHARE_WRITE);
|
googleDocsService.createGoogleDoc(nodeRefSpread, GoogleDocsPermissionContext.SHARE_WRITE);
|
||||||
|
|
||||||
assertTrue(nodeService.hasAspect(nodeRefSpread, ASPECT_GOOGLERESOURCE));
|
assertTrue(nodeService.hasAspect(nodeRefSpread, ASPECT_GOOGLERESOURCE));
|
||||||
@@ -241,12 +258,24 @@ public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsMod
|
|||||||
System.out.println("Google doc URL: " + nodeService.getProperty(nodeRefSpread, PROP_URL));
|
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 type: " + nodeService.getProperty(nodeRefSpread, PROP_RESOURCE_TYPE));
|
||||||
System.out.println("Google doc id: " + nodeService.getProperty(nodeRefSpread, PROP_RESOURCE_ID));
|
System.out.println("Google doc id: " + nodeService.getProperty(nodeRefSpread, PROP_RESOURCE_ID));
|
||||||
// // downloadFile = downloadFile(googleDocsService.download(nodeRefSpread), ".xls");
|
downloadFile = downloadFile(googleDocsService.getGoogleDocContent(nodeRefSpread), ".xls");
|
||||||
// // System.out.println("Download file: " + downloadFile);
|
System.out.println("Download file: " + downloadFile);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void printDocuments(DocumentListFeed feed)
|
||||||
|
{
|
||||||
|
for (DocumentListEntry entry : feed.getEntries() )
|
||||||
|
{
|
||||||
|
String resourceId = entry.getResourceId();
|
||||||
|
System.out.println(" -- Document(" + resourceId + "/" + entry.getTitle().getPlainText() + ") ");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void testCheckOutCheckIn() throws Exception
|
public void testCheckOutCheckIn() throws Exception
|
||||||
{
|
{
|
||||||
if (isGoogleServiceAvailable() == true)
|
if (isGoogleServiceAvailable() == true)
|
||||||
|
Reference in New Issue
Block a user