ALF-5060: Google Docs - Transformation failure

- Fixed up working. but slightly incorrect download URL (was downloading as HTML instead of Word format hence the transformation was broken)
- Added download root URL to configuration
- Unit test to show bug fixed



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@22847 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2010-10-04 12:09:57 +00:00
parent 8ed8d3b459
commit 04629bbf04
4 changed files with 205 additions and 91 deletions

View File

@@ -36,6 +36,7 @@
<property name="authorityService" ref="AuthorityService"/>
<property name="dictionaryService" ref="DictionaryService"/>
<property name="url" value="${googledocs.url}"/>
<property name="downloadUrl" value="${googledocs.downloadurl}"/>
<property name="username" value="${googledocs.username}"/>
<property name="password" value="${googledocs.password}"/>
<property name="permissionMap">

View File

@@ -7,6 +7,7 @@ googledocs.application.name=Alfresco ECM system
# Google docs URL
googledocs.url=http://docs.google.com/feeds/default/private/full
googledocs.downloadurl=https://docs.google.com/feeds/download
# System google docs authentication credentials
#googledocs.username=

View File

@@ -107,6 +107,7 @@ public class GoogleDocsServiceImpl extends TransactionListenerAdapter
/** GoogleDoc base feed url */
private String url = "http://docs.google.com/feeds/default/private/full";
private String downloadUrl = "https://docs.google.com/feeds/download";
/** Authentication credentials */
private boolean initialised = false;
@@ -204,6 +205,14 @@ public class GoogleDocsServiceImpl extends TransactionListenerAdapter
this.url = url;
}
/**
* @param downloadUrl root download URL
*/
public void setDownloadUrl(String downloadUrl)
{
this.downloadUrl = downloadUrl;
}
/**
* @param username google service user name
*/
@@ -309,6 +318,11 @@ public class GoogleDocsServiceImpl extends TransactionListenerAdapter
// Get the parent folder id
DocumentListEntry parentFolder = getParentFolder(nodeRef);
if (logger.isDebugEnabled() == true)
{
logger.debug("Creating google document (" + name + "," + mimetype + ")");
}
// Create the new google document
DocumentListEntry document = createGoogleDocument(name, mimetype, parentFolder, is);
@@ -482,27 +496,30 @@ public class GoogleDocsServiceImpl extends TransactionListenerAdapter
// Get the parent folder
DocumentListEntry parentFolder = getParentFolder(parentNodeRef);
// Determine the name of the new google folder
String name = null;
QName parentNodeType = nodeService.getType(parentNodeRef);
if (dictionaryService.isSubClass(parentNodeType, ContentModel.TYPE_STOREROOT) == true)
if (parentFolder != null)
{
name = parentNodeRef.getStoreRef().getIdentifier();
// 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);
// Set the owner of the document
setGoogleResourcePermission(folder, AuthorityType.USER, username, "owner");
// Set the owner of the document
setGoogleResourcePermission(folder, AuthorityType.USER, username, "owner");
}
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);
// Set the owner of the document
setGoogleResourcePermission(folder, AuthorityType.USER, username, "owner");
// Set the owner of the document
setGoogleResourcePermission(folder, AuthorityType.USER, username, "owner");
}
}
@@ -563,60 +580,74 @@ public class GoogleDocsServiceImpl extends TransactionListenerAdapter
{
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"))
if (document != null)
{
fileExtension = "doc";
}
String docType = document.getType();
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"))
ContentData contentData = (ContentData) nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
String fileExtension = mimetypeService.getExtension(contentData.getMimetype());
if (fileExtension.equals("docx"))
{
downloadUrl += "&gid=0"; // gid=0 will download only the first sheet
fileExtension = "doc";
}
}
else if (docType.equals(TYPE_PDF))
{
MediaContent mc = (MediaContent)document.getContent();
downloadUrl = mc.getUri();
if (docType.equals(TYPE_DOCUMENT) || docType.equals(TYPE_PRESENTATION))
{
downloadUrl = this.downloadUrl + "/" + docType + "s/Export?docId=" + document.getDocId() +
"&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);
}
// Log the download URI
if (logger.isDebugEnabled() == true)
{
logger.debug("Download URL for " + docType + " is " + downloadUrl);
}
// TODO need to verify that download of a spreadsheet works before we delete this historical code ...
UserToken docsToken = null;
if (docType.equals(TYPE_SPREADSHEET) == true)
{
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 (docType.equals(TYPE_SPREADSHEET) == true)
{
googleDocumentService.setUserToken(docsToken.getValue());
}
result = ms.getInputStream();
}
else
{
throw new AlfrescoRuntimeException("Unsuported document type: " + docType);
throw new AlfrescoRuntimeException("Can not download google doc content since no corresponsing google resource could be found");
}
// TODO need to verify that download of a spreadsheet works before we delete this historical code ...
UserToken docsToken = null;
if (docType.equals(TYPE_SPREADSHEET) == true)
{
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 (docType.equals(TYPE_SPREADSHEET) == true)
{
googleDocumentService.setUserToken(docsToken.getValue());
}
result = ms.getInputStream();
}
else
{
@@ -684,11 +715,19 @@ public class GoogleDocsServiceImpl extends TransactionListenerAdapter
}
catch (ServiceException e)
{
throw new AlfrescoRuntimeException("Unable to get document list entry for resource " + resourceId, e);
if (logger.isDebugEnabled() == true)
{
logger.debug("Unable to get document list entry for resource " + resourceId + " because " + e.getMessage());
}
result = null;
}
catch (IOException e)
{
throw new AlfrescoRuntimeException("Unable to get document list entry for resource " + resourceId, e);
if (logger.isDebugEnabled() == true)
{
logger.debug("Unable to get document list entry for resource " + resourceId + " because " + e.getMessage());
}
result = null;
}
return result;
}
@@ -1083,7 +1122,17 @@ public class GoogleDocsServiceImpl extends TransactionListenerAdapter
try
{
DocumentListEntry entry = getDocumentListEntry(resourceId);
googleDocumentService.delete(new URL(entry.getEditLink().getHref() + "?delete=true"), entry.getEtag());
if (entry != null)
{
googleDocumentService.delete(new URL(entry.getEditLink().getHref() + "?delete=true"), entry.getEtag());
}
else
{
if (logger.isDebugEnabled() == true)
{
logger.debug("Unable to delete resource " + resourceId + " during commit.");
}
}
}
catch (Throwable e)
{
@@ -1123,7 +1172,17 @@ public class GoogleDocsServiceImpl extends TransactionListenerAdapter
try
{
DocumentListEntry entry = getDocumentListEntry(resourceId);
googleDocumentService.delete(new URL(entry.getEditLink().getHref() + "?delete=true"), entry.getEtag());
if (entry != null)
{
googleDocumentService.delete(new URL(entry.getEditLink().getHref() + "?delete=true"), entry.getEtag());
}
else
{
if (logger.isDebugEnabled() == true)
{
logger.debug("Unable to delete resource " + resourceId + " during rollback.");
}
}
}
catch (Throwable e)
{

View File

@@ -31,11 +31,16 @@ import junit.framework.TestCase;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
import org.alfresco.repo.management.subsystems.ApplicationContextFactory;
import org.alfresco.repo.rendition.executer.AbstractRenderingEngine;
import org.alfresco.repo.rendition.executer.ReformatRenderingEngine;
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.rendition.RenditionDefinition;
import org.alfresco.service.cmr.rendition.RenditionService;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
@@ -46,10 +51,13 @@ 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.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.GUID;
import org.alfresco.util.PropertyMap;
import org.apache.axis.wsdl.toJava.NamespaceSelector;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
@@ -75,6 +83,7 @@ public class GoogleDocumentServiceSystemTest extends TestCase implements GoogleD
private MutableAuthenticationService authenticationService;
private PersonService personService;
private ApplicationContextFactory subsystem;
private RenditionService renditionService;
private static final String USER_ONE = "GoogleDocUserOne";
private static final String USER_TWO = "GoogleDocUserTwo";
@@ -84,13 +93,14 @@ public class GoogleDocumentServiceSystemTest extends TestCase implements GoogleD
private static final String USER_SIX = "GoogleDocUserSix";
private static final String USER_SEVEN = "GoogleDocUserSeven";
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;
private NodeRef folder;
private NodeRef nodeRefDoc;
private NodeRef nodeRefSpread;
private NodeRef nodeRefPres;
private NodeRef nodeRefPdf;
private NodeRef nodeRef2;
private UserTransaction userTransaction;
private String siteId;
@Override
protected void setUp() throws Exception
@@ -105,6 +115,7 @@ public class GoogleDocumentServiceSystemTest extends TestCase implements GoogleD
checkOutCheckInService = (CheckOutCheckInService)appContext.getBean("checkOutCheckInService");
authenticationService = (MutableAuthenticationService)appContext.getBean("authenticationService");
personService = (PersonService)appContext.getBean("personService");
renditionService = (RenditionService)appContext.getBean("renditionService");
// Start the user transaction
userTransaction = transactionService.getUserTransaction();
@@ -135,22 +146,22 @@ public class GoogleDocumentServiceSystemTest extends TestCase implements GoogleD
// Authenticate as user one
AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE);
String id = GUID.generate();
siteId = 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);
siteService.createSite("sitePreset", siteId, "My Title", "My Description", SiteVisibility.PUBLIC);
NodeRef container = siteService.createContainer(siteId, "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);
siteService.setMembership(id, USER_FIVE, SiteServiceImpl.SITE_COLLABORATOR);
siteService.setMembership(id, USER_SIX, SiteServiceImpl.SITE_COLLABORATOR);
siteService.setMembership(id, USER_SEVEN, SiteServiceImpl.SITE_COLLABORATOR);
siteService.setMembership(siteId, USER_TWO, SiteServiceImpl.SITE_COLLABORATOR);
siteService.setMembership(siteId, USER_THREE, SiteServiceImpl.SITE_CONTRIBUTOR);
siteService.setMembership(siteId, USER_FOUR, SiteServiceImpl.SITE_CONSUMER);
siteService.setMembership(siteId, USER_FIVE, SiteServiceImpl.SITE_COLLABORATOR);
siteService.setMembership(siteId, USER_SIX, SiteServiceImpl.SITE_COLLABORATOR);
siteService.setMembership(siteId, USER_SEVEN, SiteServiceImpl.SITE_COLLABORATOR);
// Create a folder in our site container
folder = fileFolderService.create(container, "myfolder", ContentModel.TYPE_FOLDER).getNodeRef();
folder = fileFolderService.create(container, "myfolder" + GUID.generate(), ContentModel.TYPE_FOLDER).getNodeRef();
// Create test documents
nodeRefDoc = createTestDocument("mydoc.docx", "alfresco/subsystems/googledocs/default/test.docx", MimetypeMap.MIMETYPE_WORD);
@@ -206,9 +217,11 @@ public class GoogleDocumentServiceSystemTest extends TestCase implements GoogleD
@Override
protected void tearDown() throws Exception
{
siteService.deleteSite(siteId);
if (userTransaction != null)
{
userTransaction.rollback();
userTransaction.commit();
}
}
@@ -289,6 +302,46 @@ public class GoogleDocumentServiceSystemTest extends TestCase implements GoogleD
}
}
/**
* http://issues.alfresco.com/jira/browse/ALF-5060
*/
public void testALF5060() throws Exception
{
if (isGoogleServiceAvailable() == true)
{
// Create a rendition definition (doc -> pdf)
RenditionDefinition def = renditionService.createRenditionDefinition(
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "myDef"),
ReformatRenderingEngine.NAME);
def.setExecuteAsynchronously(false);
def.setParameterValue(AbstractRenderingEngine.PARAM_MIME_TYPE, MimetypeMap.MIMETYPE_FLASH);
// Create a word document
File fileDoc = AbstractContentTransformerTest.loadQuickTestFile("doc");
NodeRef nodeRef = fileFolderService.create(folder, "testing.doc", ContentModel.TYPE_CONTENT).getNodeRef();
nodeService.addAspect(nodeRef, ASPECT_GOOGLEEDITABLE, null);
ContentWriter contentWriter = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
contentWriter.setEncoding("UTF-8");
contentWriter.setMimetype(MimetypeMap.MIMETYPE_WORD);
contentWriter.putContent(fileDoc);
renditionService.render(nodeRef, def);
NodeRef workingCopy = checkOutCheckInService.checkout(nodeRef);
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);
renditionService.render(nodeRef, def);
}
}
/**
* Utility method to download input stream to a file for inspection
*