Roy Wetherall f9b7237eab 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
2010-05-13 09:32:35 +00:00

1047 lines
39 KiB
Java
Executable File

/*
* 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.ArrayList;
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.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;
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.SpreadsheetEntry;
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;
/**
* Google docs integration service implementation
*/
public class GoogleDocsServiceImpl extends TransactionListenerAdapter
implements GoogleDocsService, GoogleDocsModel
{
/** Log */
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";
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;
private DictionaryService dictionaryService;
/** 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;
/** Permission map */
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 dictionaryService dictionary service
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* @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 initialise() throws GoogleDocsServiceInitException
{
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 GoogleDocsServiceInitException("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 GoogleDocsServiceInitException("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
try
{
initialise();
}
catch (GoogleDocsServiceInitException e)
{
throw new AlfrescoRuntimeException("Unable to create google doc, because service could not be initialised.", e);
}
// 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
try
{
initialise();
}
catch (GoogleDocsServiceInitException e)
{
throw new AlfrescoRuntimeException("Unable to create google doc, because service could not be initialised.", e);
}
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());
}
// Perminantly delete the entry
googleDocumentService.delete(new URL(entry.getEditLink().getHref() + "?delete=true"), entry.getEtag());
// 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());
}
}
/**
* Set a google permission on a specified resource
*
* @param nodeRef node reference
* @param resource document resource
* @param permissionContext permission context
*/
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);
}
}
}
}
}
/**
* Set a google permission on a specified resource
*
* @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)
{
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);
}
}
}
/**
* Gets the users email used to identify their google account.
*
* @param userName user name
* @return String google account email, null if none
*/
private String getUserEMail(String userName)
{
String email = null;
NodeRef personNodeRef = personService.getPerson(userName);
if (personNodeRef != null)
{
// 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 node reference
* @return DocumentList Entry folder resource
*/
private DocumentListEntry getParentFolder(final 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);
if (logger.isDebugEnabled() == true)
{
logger.debug("Found existing google folder + " + resourceId);
}
}
else
{
// 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)
{
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);
}
}
return folder;
}
/**
* Sets the resource details on the node reference
*
* @param nodeRef node reference
* @param documentListEntry document list entry
*/
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
try
{
initialise();
}
catch (GoogleDocsServiceInitException e)
{
throw new AlfrescoRuntimeException("Unable to create google doc, because service could not be initialised.", e);
}
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;
}
/**
* Gets the document list entry that corresponds to the google resource
* related to the node reference provided.
*
* @param docNodeRef node reference
* @return DocumentListEntry document list entry
*/
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);
}
/**
* Gets the document resource entry for a document resource id
*
* @param docResourceId document resource id
* @return DocumentListEntry document list entry
*/
private DocumentListEntry getDocumentListEntry(String docResourceId)
{
return getEntry(docResourceId, DocumentListEntry.class);
}
/**
* Gets the entry for a given resource id.
*
* @param <E> Entry class
* @param resourceId resource id
* @param entryClass entry class
* @return E entry instance
*/
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;
}
/**
* Create a google document
*
* @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)
{
DocumentListEntry document = null;
// Log details
if (logger.isDebugEnabled() == true)
{
logger.debug("Creating google document with name " + name);
}
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 SpreadsheetEntry();
}
else
{
docEntry = new DocumentEntry();
}
// Set the content and the title of the document
docEntry.setContent(mediaContent);
docEntry.setTitle(new PlainTextConstruct(name));
// Upload the document into the parent folder
document = googleDocumentService.insert(
new URL(parentFolderUrl),
docEntry);
// Mark create entry
markCreated(document.getResourceId());
}
catch (IOException e)
{
// Log details of exception
if (logger.isDebugEnabled() == true)
{
logger.debug("Unable to create google document with name " + name + ", because " + e.getMessage());
}
// Rethrow as runtime exception
throw new AlfrescoRuntimeException("Unable to create google document", e);
}
catch (ServiceException e)
{
// Log details of exception
if (logger.isDebugEnabled() == true)
{
logger.debug("Unable to create google document with name " + name + ", because " + e.getMessage());
}
// Rethrow as runtime exception
throw new AlfrescoRuntimeException("Unable to create google document", e);
}
return document;
}
/**
* Updates the content of a google document
*
* @param document document resource
* @param mimeType mimetype
* @param is input stream
*/
private void updateGoogleDocContent(DocumentListEntry document, String mimeType, InputStream is)
{
// Log details
if (logger.isDebugEnabled() == true)
{
logger.debug("Updating content of document " + document.getResourceId());
}
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)
{
// Log details of the error
if (logger.isDebugEnabled() == true)
{
logger.debug("Unable to update the content of document " + document.getResourceId() + ", because " + e.getMessage());
}
// Rethrow as runtime exception
throw new AlfrescoRuntimeException("Unable to update documents content in google docs", e);
}
catch (IOException e)
{
// Log details of the error
if (logger.isDebugEnabled() == true)
{
logger.debug("Unable to update the content of document " + document.getResourceId() + ", because " + e.getMessage());
}
// Rethrow as runtime exception
throw new AlfrescoRuntimeException("Unable to update documents content in google docs", e);
}
}
/**
* Creates a google folder, returning the folder resource.
*
* @param folderName folder name
* @param parentFolder parent folder resource
* @return DocumentListEntry created folder resource
*/
private DocumentListEntry createGoogleFolder(String folderName, DocumentListEntry parentFolder)
{
DocumentListEntry folderEntry = null;
try
{
// Log details
if (logger.isDebugEnabled() == true)
{
logger.debug("Creating folder " + folderName);
}
// 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);
// Mark create entry
markCreated(folderEntry.getResourceId());
}
catch (IOException e)
{
// Log details of the failure
if (logger.isDebugEnabled() == true)
{
logger.debug("Unable to create folder " + folderName + ", because " + e.getMessage());
}
// Rethrow as runtime exception
throw new AlfrescoRuntimeException("Unable to create Google Folder", e);
}
catch (ServiceException e)
{
// Log details of the failure
if (logger.isDebugEnabled() == true)
{
logger.debug("Unable to create folder " + folderName + ", because " + e.getMessage());
}
// Rethrow as runtime exception
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)
{
// Check mandatory parameters have been set
ParameterCheck.mandatory("resource", resource);
ParameterCheck.mandatory("email", email);
ParameterCheck.mandatory("role", role);
// Log details
if (logger.isDebugEnabled() == true)
{
logger.debug("Setting the role " + role + " on the google resource " + resource.getResourceId() + " for email " + email + ".");
}
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;
}
}
}
// Set the permission details
if (aclEntry == null)
{
aclEntry = new AclEntry();
aclEntry.setRole(aclRole);
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 ....
//
//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)
{
// 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)
{
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<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
}
}
}
}
}