From 3a8e5b4cfe0e3bfdef3f72914690fe8674b7cead Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Fri, 30 Apr 2010 13:35:52 +0000 Subject: [PATCH] GoogleDoc integration - sharing email for a person is now first taken from the googleusername property on the person object, if thisn't set it falls back to the user's email - if google rejects the email (with a server error) when setting the permissions on a document, this no longer rolls back the transaction, but logs the error instead - unit tests git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@20061 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../googledocs/default/testBook.xls | Bin 0 -> 16896 bytes .../java/org/alfresco/model/ContentModel.java | 1 + .../googledocs/GoogleDocsServiceImpl.java | 88 +++++++++++++----- .../googledocs/GoogleDocumentServiceTest.java | 60 ++++++++---- 4 files changed, 106 insertions(+), 43 deletions(-) create mode 100644 config/alfresco/subsystems/googledocs/default/testBook.xls diff --git a/config/alfresco/subsystems/googledocs/default/testBook.xls b/config/alfresco/subsystems/googledocs/default/testBook.xls new file mode 100644 index 0000000000000000000000000000000000000000..15d493339dbc3334390062fa609379cf9218a706 GIT binary patch literal 16896 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 literal 0 HcmV?d00001 diff --git a/source/java/org/alfresco/model/ContentModel.java b/source/java/org/alfresco/model/ContentModel.java index 85830415a7..d31499c992 100644 --- a/source/java/org/alfresco/model/ContentModel.java +++ b/source/java/org/alfresco/model/ContentModel.java @@ -192,6 +192,7 @@ public interface ContentModel static final QName PROP_COMPANYFAX = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companyfax"); static final QName PROP_COMPANYEMAIL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companyemail"); static final QName PROP_SKYPE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "skype"); + static final QName PROP_GOOGLEUSERNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "googleusername"); static final QName PROP_INSTANTMSG = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "instantmsg"); static final QName PROP_SIZE_CURRENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "sizeCurrent"); diff --git a/source/java/org/alfresco/repo/googledocs/GoogleDocsServiceImpl.java b/source/java/org/alfresco/repo/googledocs/GoogleDocsServiceImpl.java index 8d8d44927f..377ef481db 100755 --- a/source/java/org/alfresco/repo/googledocs/GoogleDocsServiceImpl.java +++ b/source/java/org/alfresco/repo/googledocs/GoogleDocsServiceImpl.java @@ -68,13 +68,14 @@ import com.google.gdata.util.ContentType; import com.google.gdata.util.ServiceException; /** - * + * Google docs integration service implementation */ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel { @SuppressWarnings("unused") private static Log logger = LogFactory.getLog(GoogleDocsServiceImpl.class); + /** Google document types */ public static final String TYPE_DOCUMENT = "document"; public static final String TYPE_SPREADSHEET = "spreadsheet"; public static final String TYPE_PRESENTATION = "presentation"; @@ -99,6 +100,7 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel private String username; private String password; + /** Permission map */ private Map permissionMap; /** @@ -157,7 +159,7 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel this.permissionService = permissionService; } - /* + /** * @param ownableService ownable service */ public void setOwnableService(OwnableService ownableService) @@ -340,10 +342,11 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel } /** + * Set a google permission on a specified resource * - * @param nodeRef - * @param resourceId - * @param permissionContext + * @param nodeRef node reference + * @param resource document resource + * @param permissionContext permission context */ private void setGoogleResourcePermissions(NodeRef nodeRef, DocumentListEntry resource, GoogleDocsPermissionContext permissionContext) { @@ -387,11 +390,12 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel } /** + * Set a google permission on a specified resource * - * @param resourceId - * @param authorityType - * @param authorityName - * @param role + * @param resource document resource + * @param authorityType authority type + * @param authorityName authority name + * @param role role */ private void setGoogleResourcePermission(DocumentListEntry resource, AuthorityType authorityType, String authorityName, String role) { @@ -415,9 +419,10 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel } /** + * Gets the users email used to identify their google account. * - * @param userName - * @return + * @param userName user name + * @return String google account email, null if none */ private String getUserEMail(String userName) { @@ -425,15 +430,23 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel NodeRef personNodeRef = personService.getPerson(userName); if (personNodeRef != null) { - email = (String) nodeService.getProperty(personNodeRef, ContentModel.PROP_EMAIL); + // First see if the google user information has been set + email = (String)nodeService.getProperty(personNodeRef, ContentModel.PROP_GOOGLEUSERNAME); + + // If no google user information then default back to the user's email + if (email == null || email.length() == 0) + { + email = (String) nodeService.getProperty(personNodeRef, ContentModel.PROP_EMAIL); + } } return email; } /** + * Gets the nodes parent folder google resource. * - * @param nodeRef - * @return + * @param nodeRef node reference + * @return DocumentList Entry folder resource */ private DocumentListEntry getParentFolder(NodeRef nodeRef) { @@ -636,12 +649,13 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel } /** + * Create a google document * - * @param name - * @param mimetype - * @param parentFolder - * @param is - * @return + * @param name document name + * @param mimetype mime type + * @param parentFolder parent folder resource + * @param is input stream for content + * @return DocumentListEntry resource for created document */ private DocumentListEntry createGoogleDocument(String name, String mimetype, DocumentListEntry parentFolder, InputStream is) { @@ -697,10 +711,11 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel } /** + * Updates the content of a google document * - * @param docResourceId - * @param mimeType - * @param is + * @param document document resource + * @param mimeType mimetype + * @param is input stream */ private void updateGoogleDocContent(DocumentListEntry document, String mimeType, InputStream is) { @@ -774,6 +789,12 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel ParameterCheck.mandatory("resource", resource); ParameterCheck.mandatory("email", email); ParameterCheck.mandatory("role", role); + + // Log details of failure + if (logger.isDebugEnabled() == true) + { + logger.debug("Setting the role " + role + " on the google resource " + resource.getResourceId() + " for email " + email + "."); + } try { @@ -801,6 +822,7 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel } } + // Set the permission details if (aclEntry == null) { aclEntry = new AclEntry(); @@ -808,6 +830,15 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel aclEntry.setScope(scope); googleDocumentService.insert(aclFeedLinkURL, aclEntry); } + else + { + // Log details of failure + if (logger.isDebugEnabled() == true) + { + logger.debug("Unable to the role " + role + " on the google resource " + resource.getResourceId() + " for email " + email + "." + + " This user already has a role on this document."); + } + } // TODO for now we will not 'update' the permissions if they have already been set .... // @@ -823,7 +854,18 @@ public class GoogleDocsServiceImpl implements GoogleDocsService, GoogleDocsModel } catch (ServiceException e) { - throw new AlfrescoRuntimeException("Unable to set premissions on google document", e); + // Ignore this exception since we don't want to roll back the entire transaction because + // a single users permissions can not be set. + // It seems the google API will return a server exception if the email does not correspond to + // a google account, so catching this exception in this indiscriminate way is the best thing to + // do for now. + + // Log details of failure + if (logger.isDebugEnabled() == true) + { + logger.debug("Unable to the role " + role + " on the google resource " + resource.getResourceId() + " for email " + email + "." + + " Check that this is a valid google account."); + } } catch (IOException e) { diff --git a/source/java/org/alfresco/repo/googledocs/GoogleDocumentServiceTest.java b/source/java/org/alfresco/repo/googledocs/GoogleDocumentServiceTest.java index 3c8ee521b4..d86a86f970 100755 --- a/source/java/org/alfresco/repo/googledocs/GoogleDocumentServiceTest.java +++ b/source/java/org/alfresco/repo/googledocs/GoogleDocumentServiceTest.java @@ -70,6 +70,10 @@ public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsMod 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 USER_FIVE = "GoogleDocUserFive"; + private static final String USER_SIX = "GoogleDocUserSix"; + private static final String USER_SEVEN = "GoogleDocUserSeven"; + //private static final String EMAIL_DOMAIN = "@alfresco.com"; private NodeRef folder = null; @@ -112,10 +116,13 @@ public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsMod 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"); + createUser(USER_ONE, "rwetherall@alfresco.com", null); + createUser(USER_TWO, "admin@alfresco.com", "rwetherall@activiti.com"); + createUser(USER_THREE, "roy.wetherall@alfresco.com", null); + createUser(USER_FOUR, "roy.wetherall@activiti.com", null); + createUser(USER_FIVE, "admin@alfresco.com", "admin@alfresco.com"); + createUser(USER_SIX, "admin@alfresco.com", null); + createUser(USER_SEVEN, null, null); // Authenticate as user one AuthenticationUtil.setFullyAuthenticatedUser(USER_ONE); @@ -130,13 +137,17 @@ public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsMod 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); // 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); + //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); // Create an empty content node (simulate creation of a new google doc in UI) nodeRef2 = fileFolderService.create(folder, "mygoogledoc.doc", ContentModel.TYPE_CONTENT).getNodeRef(); @@ -154,7 +165,7 @@ public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsMod return nodeRef; } - private void createUser(String userName, String email) + private void createUser(String userName, String email, String googleEmail) { if (authenticationService.authenticationExists(userName) == false) { @@ -163,10 +174,19 @@ public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsMod 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_LASTNAME, "lastName"); ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle"); + if (email != null) + { + ppOne.put(ContentModel.PROP_EMAIL, email); + } + + if (googleEmail != null) + { + ppOne.put(ContentModel.PROP_GOOGLEUSERNAME, googleEmail); + } + personService.createPerson(ppOne); } } @@ -211,18 +231,18 @@ public class GoogleDocumentServiceTest extends TestCase implements GoogleDocsMod 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); + googleDocsService.createGoogleDoc(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); } }