diff --git a/config/alfresco/subsystems/googledocs/default/googledocs-context.xml b/config/alfresco/subsystems/googledocs/default/googledocs-context.xml index 589a57d690..903156e5bc 100755 --- a/config/alfresco/subsystems/googledocs/default/googledocs-context.xml +++ b/config/alfresco/subsystems/googledocs/default/googledocs-context.xml @@ -33,7 +33,8 @@ - + + diff --git a/source/java/org/alfresco/repo/googledocs/GoogleDocsServiceImpl.java b/source/java/org/alfresco/repo/googledocs/GoogleDocsServiceImpl.java index 9bb49f9525..a882885599 100755 --- a/source/java/org/alfresco/repo/googledocs/GoogleDocsServiceImpl.java +++ b/source/java/org/alfresco/repo/googledocs/GoogleDocsServiceImpl.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.net.URL; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -31,6 +32,9 @@ 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.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.ContentReader; 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.DocumentListEntry; 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.MediaStreamSource; import com.google.gdata.util.AuthenticationException; @@ -70,9 +74,10 @@ import com.google.gdata.util.ServiceException; /** * 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); /** Google document types */ @@ -91,7 +96,8 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel private PermissionService permissionService; private OwnableService ownableService; private AuthorityService authorityService; - + private DictionaryService dictionaryService; + /** GoogleDoc base feed url */ private String url = "http://docs.google.com/feeds/default/private/full"; @@ -175,6 +181,14 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel this.authorityService = authorityService; } + /** + * @param dictionaryService dictionary service + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + /** * @param url root googleDoc URL */ @@ -448,7 +462,7 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel * @param nodeRef node reference * @return DocumentList Entry folder resource */ - private DocumentListEntry getParentFolder(NodeRef nodeRef) + private DocumentListEntry getParentFolder(final NodeRef nodeRef) { DocumentListEntry folder = null; @@ -460,14 +474,32 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel String resourceType = (String)nodeService.getProperty(parentNodeRef, PROP_RESOURCE_TYPE); String resourceId = (String)nodeService.getProperty(parentNodeRef, PROP_RESOURCE_ID); folder = getDocumentListEntry(resourceType + ":" + resourceId); + + if (logger.isDebugEnabled() == true) + { + logger.debug("Found existing google folder + " + resourceId); + } } else { + // Get the parent folder DocumentListEntry parentFolder = getParentFolder(parentNodeRef); - String name = (String)nodeService.getProperty(parentNodeRef, ContentModel.PROP_NAME); - folder = createGoogleFolder(name, parentFolder); - - setResourceDetails(parentNodeRef, folder); + + // 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); } } @@ -694,13 +726,14 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel DocumentListEntry docEntry = null; if (MimetypeMap.MIMETYPE_EXCEL.equals(mimetype) == true) { - docEntry = new PresentationEntry(); + docEntry = new SpreadsheetEntry(); } else { docEntry = new DocumentEntry(); } + // Set the content and the title of the document docEntry.setContent(mediaContent); docEntry.setTitle(new PlainTextConstruct(name)); @@ -708,6 +741,9 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel document = googleDocumentService.insert( new URL(parentFolderUrl), docEntry); + + // Mark create entry + markCreated(document.getResourceId()); } catch (IOException e) { @@ -816,6 +852,9 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel folderEntry = googleDocumentService.insert( new URL(parentFolderUrl), folder); + + // Mark create entry + markCreated(folderEntry.getResourceId()); } catch (IOException e) { @@ -938,7 +977,70 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel { throw new AlfrescoRuntimeException("Unable to set premissions on google document", e); } + } + + private final static String KEY_MARKED_RESOURCES = "GoogleDocService.marked_resources"; + + @SuppressWarnings("unchecked") + private void markCreated(String resourceId) + { + List resources = (List)AlfrescoTransactionSupport.getResource(KEY_MARKED_RESOURCES); + if (resources == null) + { + // bind pending rules to the current transaction + resources = new ArrayList(); + 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 resources = (List)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 + } + } + } + } } diff --git a/source/java/org/alfresco/repo/googledocs/GoogleDocumentServiceTest.java b/source/java/org/alfresco/repo/googledocs/GoogleDocumentServiceTest.java index d86a86f970..2e59a7c567 100755 --- a/source/java/org/alfresco/repo/googledocs/GoogleDocumentServiceTest.java +++ b/source/java/org/alfresco/repo/googledocs/GoogleDocumentServiceTest.java @@ -23,6 +23,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; +import java.net.URL; import javax.transaction.UserTransaction; @@ -51,6 +52,10 @@ import org.alfresco.util.PropertyMap; import org.springframework.context.ApplicationContext; 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; public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsModel @@ -147,7 +152,7 @@ public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsMod // Create test documents 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("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) 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_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 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); + 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); 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 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); + downloadFile = downloadFile(googleDocsService.getGoogleDocContent(nodeRefSpread), ".xls"); + 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 { if (isGoogleServiceAvailable() == true)