5. Projects (Cont.)
•Spring Social Dropbox (Fork)
•Spring Social Google Docs
•Spring Social Alfresco
Contributed
•oAuth1/2 Persistence Service
•PDF Toolkit
•Share Extras
•Maven AMP Plugin
•Java CORS Filter
•Welsh Language Pack
8. Jive Toolkit
What is it?
A set of pre-built components that allows Jive to store documents in Alfresco while
still offering all of the same social features as “native” Jive documents (commenting,
rating, discussions, etc.)
Availability?
Released Early 2012
Current supported release version 1.0.5 for Alfresco 3.4.11
Support Portal
Current community release version 1.1 for Alfresco 4.1
http://code.google.com/p/alfresco-jive-toolkit/
9. Jive Toolkit (Cont.)
Future?
•The community project is looking for help.
•SolutionSet is taking ownership of the project.
•Looking for
o Developers
o Testers
o Users!
o Documentation
10. Alfresco Dropbox Connector
What is it?
The Alfresco Dropbox Connector allows a user to sync content/folders to their
Dropbox Account. Content can be synced to multiple users accounts. When the
content is updated in Alfresco it will be synced across all synced Dropbox Accounts.
It supports manual updates back to Alfresco from Dropbox.
Availability?
It is current available from Google Code (
http://code.google.com/p/alfresco-dropbox-integration/). It is available as a
community supported project. It requires at least Alfresco 4.1 (Enterprise) or 4.2
(Community)
11. Alfresco Dropbox Connector (Cont.)
Status?
We are looking for Contributors, Testers, Documentation, Users.
What happened?
Sync.
Automatic sync between multiple sources is a complicated issue. It is even more
complicated when one of the sources doesn't have a full understanding of content
lifecycle....or managing it.
12. Alfresco Dropbox Connector (Cont.)
Issue 1: One to Many
Content in Alfresco is shared across multiple users but maintains a single source of
truth.
When synced to Dropbox .... we have many sources.
Sharing content is explicit: a user has to initiate it. No API support.
13. Alfresco Dropbox Connector (Cont.)
Issue 2: Versioning
Dropbox has poor version support.
•
Revision created with each save
•
Revisions only available for the past 30 days
•
Revisions number are non sequential alphanumeric sequences
•
Modification dates can't be trusted
One to Many + Versioning = Nightmare.
14. Alfresco Dropbox Connector (Cont.)
Issue 3: File Changes (1)
Dropbox provides a delta api.
"A way of letting you keep up with changes to files and folders in a user's Dropbox.
You can periodically call /delta to get a list of "delta entries", which are instructions on
how to update your local state to match the server's state."
In reality, an entry in the delta list means the files is:
...New...Update...Move...Copied...Renamed...
an entry with no file metadata means the file has been
...Deleted...Moved...Renamed...
15. Alfresco Dropbox Connector (Cont.)
Issue 3: File Changes (2)
It is polling...
...which is expensive...
...which drains already costly resources...
17. Alfresco Dropbox Connector (Cont.)
Are we without options?
No.
Our proposed approach
Out of process polling
CMIS Client to Alfresco
RESTful client of Dropbox
Complicated ordering of content changes out of process
18. Maven
3.0.4 or 3.0.5-SNAPSHOT
Add to pom or settings.xml:
<pluginRepositories>
<pluginRepository>
<id>alfresco-public</id>
<name>Alfresco</name>
<url>https://artifacts.alfresco.com/nexus/content/repositories/releases</url>
</pluginRepository>
<pluginRepository>
<id>alfresco-public-snapshots</id>
<name>Alfresco</name>
<url>https://artifacts.alfresco.com/nexus/content/groups/public-snapshots/</url>
</pluginRepository>
</pluginRepositories>
19. Maven
Alfresco dependencies can be found at
https://artifacts.alfresco.com
Add the amp packaging decleration to your pom.xml
<packaging>amp</packaging>
23. Maven
Build command
mvn clean package [-DskipTests]
Amp location
in target directory
Validate amp content in directory of same name as amp (minus amp extension)
24. Google Docs V2
• Complete rewrite
o
Usability
o
Functionality
• No Shared Account
o
Create and Edit content in their account
• Google is used as an editor, not persistance
• Add-on not part of core
• Cloud, Enterprise, Community
[Talk about Drive here :-)]
27. Google Docs V2
OAuth Credentials Store
Provide Token Persistence for oAuth1 and oAuth2
Leverages Remote Credentials Service
Dropbox Integrations and Google Docs V2 this service
28. Google Docs V2
How To
private static OAuth2CredentialsStoreService oauth2CredentialsStoreService;
//Store Credentials. RemoteSystemId should be Unique
oauth2CredentialsStoreService.storePersonalOAuth2Credentials(RemoteSystemId,
AccessToken, RefreshToken, ExpiresAt, IssuedAt);
//Retrieve Credentials by RemoteSystemId
OAuth2CredentialsInfo oAuth2CredentialsInfo =
oauth2CredentialsStoreService.getPersonalOAuth2Credentials(RemoteSystemId);
//Update Credentials the same way you add new ones...make sure the RemoteSystemId is the
same
oauth2CredentialsStoreService.storePersonalOAuth2Credentials(RemoteSystemId,
UpdatedAccessToken, UpdatedRefreshToken, UpdatedExpiresAt, UpdatedIssuedAt);
29. Google Docs V2
//Store Shared Credentials. Recomendation: Unqiue RemoteSystemId
oauth2CredentialsStoreService.storeSharedOAuth2Credentials(RemoteSystemId,
AccessToken, RefreshToken, ExpiresAt, IssuedAt);
//Retrieve by RemoteSystemId Note: this returns a list
List<OAuth2CredentialsInfo> sharedCredentials =
oauth2CredentialsStoreService.listSharedOAuth2Credentials(RemoteSystemId);
//Update Share Credentials. Note the specifics method for updating shared
credentials
oauth2CredentialsStoreService.updateSharedOAuth2Credentials(oAuth2CredentialsI
nfo, RemoteSystemId, UpdatedAccessToken, UpdatedRefreshToken,
UpdatedExpiresAt, UpdatedIssuedAt);
30. Google Docs V2
//Delete Personal Credentials by RemoteSystemId
oauth2CredentialsStoreService.deletePersonalOAuth2Credentials(RemoteSystemId)
;
//Delete Share Credentials requires RemoteSystemId and the oAuth2CredentialsInfo
instance of the specific credentials
List<OAuth2CredentialsInfo> sharedCredentials =
oauth2CredentialsStoreService.listSharedOAuth2Credentials(RemoteSystemId);
//find the ones you need in the list
oauth2CredentialsStoreService.deleteSharedOAuth2Credentials(RemoteSystemId,
oAuth2CredentialsInfo);
31. Google Docs V2
Create Content Action
Add to your share-config-custom.xml
<config evaluator="string-compare" condition="DocumentLibrary">
<create-content>
<content id="google-docs" label="create-content.googledocs.document"
icon="document" index="50" type="javascript">
<param name="function">onGoogledocsActionCreateDocument</param>
</content>
</create-content>
</config>
32. Google Docs V2
It supports 3 different actions: link, pagelink or javascript:
* "link" - accepts a "href" param that will be passed a nodeRef token for
substitution, used for external links
* "pagelink" - accepts a "page" param that will be passed a nodeRef token for
substitution, used for Share links
* "javascript" - accepts & "function" param of an action that will get the current
folder item as first argument.
Evaluators are not currently supported, but permission checks are.
33. Google Docs V2
(function() {
YAHOO.Bubbling.fire("registerAction", {
actionName : "onGoogledocsActionCreateDocument",
fn: function dlA_onGoogledocsActionCreateDocument(record)
{
//Do Work Here
createGoogleDoc.call(this, record, "document");
}
})
})();
34. Google Docs V2
DocLib Actions: Evaluators, Custom Responses
Two actions:
Edit Content
Resume Editing Content
Edit Content
Only a specific set of content can be edited by Google Docs
Content that is currently being edited can't be "edited"
User must have write access to the node
Document Size Limits
Google Docs Service can be turned off
35. Google Docs V2
Editing Action
<action id="google-docs-edit-action-link" type="javascript"
icon="google-edit" label="googledocs.actions.edit">
<param name="function">onGoogledocsActionEdit</param>
</action>
JavaScript or PageLink?
Debugging
http://localhost:8080/alfresco/service/slingshot/doclib2/node/workspace/SpacesSt
ore/8759ce08-acaa-4d69-807e-23c98a53fd17
36. Google Docs V2
User must have write access to the node
<permissions>
<permission allow="true">Write</permission>
</permissions>
Possible Permissions
CancelCheckOut
ChangePermissions
CreateChildren
Delete
Write
37. Google Docs V2
Content that is currently being edited can't be "edited"
Content being edited has the gd2:editingInGoogle aspect applied
<bean id="evaluator.doclib.google.docs.doesnothaveaspect"
parent="evaluator.doclib.metadata.doesNotHaveAspect">
<property name="aspects">
<list>
<value>gd2:editingInGoogle</value>
</list>
</property>
<property name="negateOutput" value="true" />
</bean>
38. Google Docs V2
Document Size Limits
Google Docs has a complex set of sizes (
http://support.google.com/drive/bin/answer.py?hl=en&answer=37603)
<bean id="evaluator.doclib.metadata.sizeLimit"
class="org.alfresco.integrations.web.evaluator.SizeLimitEvaluator">
<property name="maxDocumentSize" value="2097152"/>
<property name="maxSpreadsheetSize" value="20971520"/>
<property name="maxPresentationSize" value="52428800"/>
</bean>
39. Google Docs V2
Remember!
Numeric values in json are doubles.
long size = ((Double)node.get("size")).longValue();
String contentType = getContentType(node.get("mimetype").toString());
if (contentType == null || size > getMaxFileSize(contentType))
{
return false;
}
40. Google Docs V2
Only a specific set of content can be edited by Google Docs
application/vnd.openxmlformats-officedocument.presentationml.presentation
application/vnd.ms-powerpoint
text/tab-separated-values
application/vnd.sun.xml.writer
application/vnd.ms-excel
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/rtf
application/msword
application/vnd.oasis.opendocument.text
text/plain
text/csv
application/x-vnd.oasis.opendocument.spreadsheet
application/vnd.oasis.opendocument.spreadsheet <!-- GOOGLEDOCS-71 -->
application/vnd.openxmlformats-officedocument.wordprocessingml.document
45. Google Docs V2
Google Docs Service can be turned off
googledocs.enabled=true
public Serializable populate()
{
Map<String, Serializable> map = new LinkedHashMap<String, Serializable>(2);
map.put("enabled", (Serializable)googledocsService.isEnabled());
map.put("importFormats", (Serializable)googledocsService.getImportFormats());
return (Serializable)map;
}
49. Google Docs V2
OAuth Workflow
Authentication is a challenge no matter what the authentication type.
oAuth is only part of the solution for Google Docs...but we leverage it to solve
other issues as well
We leveraged our own spring-social-google-docs.
spring-social-google was not compatible
spring-social-google-docs is a wrapper for gdata
Newer google client did not provide a client api for Google Docs
51. Google Docs V2
Components
Two Web Scripts
1. Provides the Authentication URL
2. Completes the Authentication
-Persists the Tokens
Client Side JS
Initiate the Flow
Calls to Repo
Opens ModalDialog or new Window
Secret Sauce: Callback page, browser redirect the auth token to
repo
52. Google Docs V2
Rollback Callback
Used to handle additional clean up work when a transaction is rolled back. Could
be used to perform work in another system or in Alfresco.
Clean up
Notifications
Some Unit of Work
53. Google Docs V2
catch (SomeException e)
{
AlfrescoTransactionSupport.bindListener(new TransactionListenerAdapter() {
public void afterRollback() {
transactionService.getRetryingTransactionHelper().doInTransaction(new
RetryingTransactionCallback<Object>() {
public Object execute() throws Throwable
{
//do work here
}
}, false, true);
}
});
//Something maybe needed here like
throw new SomeOtherException(e.getMessage(), e);
}
54. Google Docs V2
JMX
Any properties you add to for your custom beans to pick up are made read-only in
JMX. If you want read write, make a subsystem.
Define your ChildApplicationContextFactory bean in your AMPs
module.properties file.
Create a directory structure in your resource directory
alfresco.subsystems.<category>[.<instance>]
Add your systems <name>-context.xml and <name>.properties files
56. Google Docs V2
Best Practices
Keep your model in you subsystem.
Web Scripts Cannot be defined in your subsystem
Test what happens when you unload your subsystem
--Subsystems can be automatically reloaded
--If you don't want that to happen,
Add programmatic controls to keep its beans from being
called