Date post: | 12-Jul-2015 |
Category: |
Technology |
Upload: | angel-borroy |
View: | 186 times |
Download: | 1 times |
Agenda
http://www.keensoft.es!!!!!!!!http://orderofthebee.org!Addons committee
Introduction
CE EE
eSign!LTA!RM!
Preliminary thoughts
From a newbie’s point of view
Alfresco is hard to learn
Some new words (for newbies)
AMP!WebScript! Spring Surf!
Aikau! Activiti!
FreeMarker!
CMIS! Content Model!
Is there another life?
!"With even a few lines of code, you can easily add useful functionality to Alfresco." !
(April 4, 2014 by Jeff Potts)!
Disclaimer
!Source code based on Alfresco CE 4.2.f !
and available at GitHub !!
WARNING!!Code for teaching purposes. !
Don’t try to compile it on your head.!
Countdown
Real questions from real persons
10. Add a download button
Motivation. "When I get a shared document link by email and click on it, the result may not be accessible: sometimes the preview is not working, sometimes I can only see a simple picture, sometimes my computer has no Flash Player... How can I get the content of a document shared with me?"!
Quick Share!
10. Add a download button
1.
2.
10. Add a download button <div class="document-download">
<a title="Download" class="simple-link"
download="${displayName?html}"
href="${url.context}/proxy/alfresco-noauth/api/internal/
shared/node/content/${args.shareId}?a=true">Download</a>
</div>
web-extension/site-webscripts/org/alfresco/components/quickshare/node-header.get.html.ftl
2 lines!Not all browsers supported *!!Danger zone!Alfresco default FTL!should not be !overwritten!!
!
10. Add a download button
web-extension
FTL
WebScript CE 5.0.a
9. Site creation ability
Motivation. "I don't want all the users creating sites without control, our organization is being directed by our own Process Map and no one should create content out of its limits."!
9. Site creation ability
1.
2.
3.
9. Site creation ability (share) var sitesMenu = widgetUtils.findObject(model.jsonModel, "id",
"HEADER_SITES_MENU");
if (sitesMenu) {
sitesMenu.config.showCreateSite = user.isAdmin;
}
web-extension/site-webscripts/es/keensoft/share/header/share-header.get.js
4. model.showCreateSite = user.isAdmin;
web-extension/site-webscripts/es/keensoft/components/dashlets/my-sites.get.js
9. Site creation ability (share) <extension>
<modules>
<module>
<id>Hide Create Site</id>
<customizations>
<customization>
<targetPackageRoot>org.alfresco</targetPackageRoot>
<sourcePackageRoot>es.keensoft</sourcePackageRoot>
</customization>
</customizations>
</module>
</modules>
</extension>
web-extension/site-data/extensions/hide-create-site-extensions.xml
9. Site creation ability (share) <!-- Required from 5.0.a -->
<customization>
<targetPackageRoot>org.alfresco.share.pages
</targetPackageRoot>
<sourcePackageRoot>es.keensoft.share.header
</sourcePackageRoot>
<alwaysApply>
<webscript>share-header</webscript>
</alwaysApply>
</customization>
web-extension/site-data/extensions/hide-create-site-extensions.xml
CE >= 5.0.a (aikau)!
9. Site creation ability (repo)
function main(){
var user = people.getPerson(person.properties.userName);
if (!people.isAdmin(user)) {
status.setCode(status.STATUS_FORBIDDEN, "error.noPermissions");
return;
}
config/alfresco/extension/templates/webscripts/org/alfresco/repository/site/ sites.post.json.js
5.
6.
7.
8.
9. Site creation ability
web-extension 8 lines!No Alfresco repository!permissions modified *!but!repo webscript overridden!
WebScript
* http://wiki.alfresco.com/wiki/Site_Service#Controlling_who_can_create_sites
aikau
Alfresco JS API
Other dashlets could be extended: dynamic-welcome, my-meeting-workspaces, my-workspaces
8. Changing document extension
Motivation. "We are elaborating documents on Microsoft Word, once the document is closed we are uploading a final version in PDF. Surprisingly, final document has the same extension as original (.DOC) although mimetype is right. Users can't open PDF document by downloading or by editing online because local programs are associated by file extension."!
8. Changing document extension
1.
2.
3.
4.
5.
6.
7.
8. Changing document extension public class ContentBehaviour implements
ContentServicePolicies.OnContentPropertyUpdatePolicy {
@Override
public void onContentPropertyUpdate(NodeRef nodeRef, QName propertyQName,
ContentData beforeValue, ContentData afterValue) {
if (beforeValue != null &&
!beforeValue.getMimetype().equals(afterValue.getMimetype())) {
String name = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
String nameNoExt = FilenameUtils.getBaseName(name);
String newExt = mimetypeService.getExtension(afterValue.getMimetype());
nodeService.setProperty(nodeRef, ContentModel.PROP_NAME,
nameNoExt + "." + newExt);
}
}
}
es.keensoft.alfresco.behaviour.ContentBehaviour.java
8. Changing document extension <beans>
<bean id="${project.artifactId}-ContentBehavior"
class="es.keensoft.alfresco.behaviour.ContentBehaviour"
init-method="init">
<property name="policyComponent" ref="policyComponent" />
<property name="nodeService" ref="NodeService" />
<property name="mimetypeService" ref="MimetypeService" />
</bean>
</beans>
config/alfresco/module/context/service-context.xml
8. Changing document extension
behavior 7 lines!Alfresco Java
API
7. Setting create missing person
Motivation. "I have configured our LDAP for identification because I don't want to take care of passwords, but I don't want everyone on this LDAP to have access to Alfresco.!
7. Setting create missing person # Some authentication mechanisms may need to create people # in the repository on demand. This enables that feature. # If disabled an error will be generated for missing # people. If enabled then a person will be created and # persisted. create.missing.people=${server.transaction.allow-writes}!! From 4.2.d!! From 4.2!
CE
EE
7. Setting create missing person 1.
2.
3.
4.
public class CustomSpringBeanPostProcessor implements
BeanFactoryPostProcessor, ApplicationContextAware {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
bd.getPropertyValues().add(propertyName, propertyValue);
}
}
es.keensoft.alfresco.behaviour.ContentBehaviour.java
CE EE < 4.2.d < 4.2
7. Setting create missing person <beans>
<bean id="customSpringBeanPostProcessor"
class="es.keensoft.repo.CustomSpringBeanPostProcessor">
<property name="beanName" value="personService" />
<property name="propertyName”
value="createMissingPeople" />
<property name="propertyValue" value="false" />
</bean>
</beans>
config/alfresco/module/context/service-context.xml
7. Setting create missing person
Spring bean post-processor 4 lines!
!Updating Alfresco properties after Spring initialization phase!
6. Custom LDAP identification
Motivation. "We have several LDAP branches, one for each mail subdomain, but mail attribute is not bindable. The only attribute bindable is an UID which can be repeated on every branch. How can I identify my users?"!
1.
2.
3.
4.
5.
6.
7.
8.
9.
6. Custom LDAP identification public class CustomDNLDAPAuthenticationComponentImpl extends
LDAPAuthenticationComponentImpl {
protected void authenticateImpl(String userName, char[] password)
throws AuthenticationException {
if (userName.indexOf("@") != -1) {
String mailDomain = userName.substring(userName.indexOf("@") + 1);
String patchedUserName = userName.substring(0, userName.indexOf("@"));
String dnPattern = (mailDomain == null ? null :
mailDomainLdapMapping.get(mailDomain));
if (mailDomain != null && dnPattern != null &&
userNameFormat.indexOf(dnPattern) != -1) {
userName = patchedUserName;
}
}
super.authenticateImpl(userName, password);
}
}
es.keensoft.repo.security.authentication.ldap. CustomDNLDAPAuthenticationComponentImpl
6. Custom LDAP identification <beans>
<bean id="authenticationComponent"
class="es.keensoft.repo.security.authentication.ldap.
CustomDNLDAPAuthenticationComponentImpl"
parent="authenticationComponentBase">
...
<!-- mailDomain, targeted DN pattern -->
<property name="mailDomainLdapMapping">
<map>
<entry key="sales.mail.com" value="o=sales,o=isp"/>
<entry key="mkt.mail.com" value="o=mkt,o=isp"/>
</map>
</property>
</bean>
</beans>
config/alfresco/module/context/service-context.xml
6. Custom LDAP identification
Alfresco bean override 9 lines!
!Danger zone!Alfresco default beans!should not be overridden!!
5. PDF/A transformation
Motivation. "We are required by law to expose all our documents in PDF/A format"!
5. PDF/A transformation <document-formats>
<document-format><name>Portable Document Format</name>
<mime-type>application/pdf</mime-type>
<file-extension>pdf</file-extension>
<export-filters>
<entry><family>Presentation</family>
<string>impress_pdf_Export</string></entry>
<entry><family>Spreadsheet</family><string>calc_pdf_Export</string></entry>
<entry><family>Text</family><string>writer_pdf_Export</string></entry>
</export-filters>
<export-options>
<entry><string>SelectPdfVersion</string><int>1</int></entry>
</export-options>
</document-format>
...
</document-formats>
config/alfresco/mimetype/openoffice-document-formats.xml
5. PDF/A transformation
Properties override 0 lines!
!Some additional development would be necessary to have both (PDF and PDFA) transformers available!
4. Importing original dates
Motivation. "We have large history before Alfresco, how can I preserve the records of date for every imported document?”!
1.
2.
3.
4.
5.
4. Importing original dates <model name="ks:custom-model" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d" />
</imports>
<namespaces>
<namespace uri="http://www.alfresco.com/model/custom-model/1.0" prefix="ks" />
</namespaces>
<aspects>
<aspect name="ks:importedDoc">
<properties>
<property name="ks:originalCreationDate">
<type>d:date</type>
</property>
<property name="ks:originalModificationDate">
<type>d:date</type>
</property>
</properties>
</aspect>
</aspects>
</model>
config/alfresco/extension/model/custom-model.xml
4. Importing original dates <beans>
<!-- Office 2007+ -->
<bean id="extracter.Poi”
class="org.alfresco.repo.content.metadata.PoiMetadataExtracter”
parent="baseMetadataExtracter">
<property name="inheritDefaultMapping">
<value>true</value>
</property>
<property name="mappingProperties">
<props>
<prop key="namespace.prefix.ks">
http://www.alfresco.com/model/custom-model/1.0</prop>
<prop key="Creation-Date">ks:originalCreationDate</prop>
<prop key="Last-Modified">ks:originalModificationDate</prop>
</props>
</property>
</bean>
</beans>
config/alfresco/extension/custom-model-context.xml
Content Model
4. Importing original dates
5 lines!!Other formats could be included (PDF, ODF…)!Some other XML config is required for Alfresco Share!
Extracter configuration
3. Custom EML node names
Motivation. "I don't understand Alfresco imported mails from IMAP, the names have no sense for me."!
3. Custom EML node names
content
autoVersionOnUpdateProps, autoVersion, initialVersion, versionLabel
title, author, modified, description
Create node!1
Create content!2
Create version!3
Update props!4
name, node-dbid, store-identifier, node-uuid, modified, locale, created, store-protocol, creator, modifier
Properties
Properties
Properties
Properties
public class ImapContentBehaviour implements
NodeServicePolicies.OnUpdatePropertiesPolicy {
public void onUpdateProperties(NodeRef nodeRef,
Map<QName, Serializable> before, Map<QName, Serializable> after) {
if (!before.get(ContentModel.PROP_TITLE).equals(
after.get(ContentModel.PROP_TITLE))) {
String intendedName =
nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE) + ".eml";
try {
fileFolderService.rename(nodeRef, intendedName);
} catch (Exception e) { // ELM node not renamed... }
}
}
}
1.
2.
3.
4.
5.
6.
3. Custom EML node names
es.keensoft.alfresco.behaviour.ImapContentBehaviour.java
3. Custom EML node names <beans>
<bean id="${project.artifactId}-ContentBehavior"
class="es.keensoft.alfresco.behaviour.ImapContentBehaviour"
init-method="init">
<property name="policyComponent" ref="policyComponent" />
<property name="nodeService" ref="NodeService" />
<property name="fileFolderService" ref="FileFolderService"/>
</bean>
</beans>
config/alfresco/module/context/service-context.xml
3. Custom EML node names
behavior 6 lines!!Custom RFC822 transformer for HTML could be included !
Alfresco Java API
2. Site custom properties
Motivation. "Every site on our company belongs to one entity and it’s identified by an internal ID, it’s required to set this entity on every Alfresco site creation."!
1.
2.
3.
4.
2. Site custom properties (share)
<@markup id="custom-properties" target="fields" action="after">
<div class="yui-gd">
<div class="yui-u first"><label for="${el}-idEntity">Entity:</label></div>
<div class="yui-u"><input id="${el}-idEntity" type="text" name="idEntity”/></div>
</div>
</@markup>
config/alfresco/web-extension/site-webscripts/es/keensoft/modules/ create-site.get.html.ftl
2. Site custom properties (share) <extension>
<modules>
<module>
<id>Custom Site Props</id>
<customizations>
<customization>
<targetPackageRoot>org.alfresco</targetPackageRoot>
<sourcePackageRoot>es.keensoft</sourcePackageRoot>
</customization>
</customizations>
</module>
</modules>
</extension>
web-extension/site-data/extensions/custom-site-prop-extensions.xml
2. Site custom properties (repo)
5.
6.
7.
8.
site = siteService.createSite(sitePreset, shortName, title, description, visibility,
sitetype);
if (json.has("idEntity")) {
site.node.properties["stcp:idEntity"] = json.get("idEntity");
site.node.save();
site.save();
}
model.site = site;
config/alfresco/extension/templates/webscripts/org/alfresco/repository/site/ sites.post.json.js
2 in a row!
2. Site custom properties
web-extension 8 lines!!Alfresco webscript repo extension not available!Easy to extend this !sample for site edition!
Alfresco JS API
FTL
1. Site templates with folders
Motivation. "Someone recently asked how to create Alfresco Share sites with a default folder structure. Currently, out-of-the-box, when you create an Alfresco Share site, the document library is empty. This person instead wanted to define a set of folders that would be created in the document library when a new Alfresco Share site is created."!http://ecmarchitect.com/archives/2014/04/04/3687
public class ShareDocumentLib implements NodeServicePolicies.OnCreateNodePolicy {
public void onCreateNode(ChildAssociationRef childAssocRef) {
String sitePreset =
nodeService.getProperty(childAssocRef.getChildRef(), PROP_SITE_PRESET);
String query = "+PATH:\"/app:company_home/app:dictionary/app:space_templates/*\" +
@cm\\:name:\"" + sitePreset + "\"";
ResultSet rs =
searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE,
SearchService.LANGUAGE_LUCENE, query);
NodeRef documentLibrary =
fileFolderService.copy(rs.getNodeRef(0), childAssocRef.getChildRef(),
"documentLibrary").getNodeRef();
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
props.put(ContentModel.PROP_DESCRIPTION, "Document Library");
props.put(PROP_SITE_COMPONENT_ID, "documentLibrary");
nodeService.addAspect(documentLibrary, ASPECT_SITE_CONTAINER, props);
}
}
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
1. Site templates with folders
com.ecmarchitect.share.behavior. ShareDocumentLibraryFromTemplate.java
1. Site templates with folders <beans>
<bean id="${project.artifactId}_siteBehavior”
class="com.ecmarchitect.share.behavior.ShareDocumentLib”
init-method="init">
<property name="nodeService” ref="NodeService”/>
<property name="policyComponent” ref="policyComponent”/>
<property name="fileFolderService” ref="FileFolderService”/>
<property name="searchService” ref="SearchService”/>
</bean>
</beans>
config/alfresco/module/share-site-space-templates-repo/context/service-context.xml
1. Site templates with folders
behavior 10 lines!
!Jeff Potts article and !GitHub sample available!
Alfresco Java API
What we have learned
As Alfresco developers
Badges earned
behavior
Content Model Alfresco JS API
Alfresco Java API
Alfresco source override web-extension WebScript
aikau
FTL
What should I learn?
XML!Java!
JS!FTL!
Source code lines (percentage)
Extend!Override!Overwrite!
!Alfresco source code to the rescue! .!
The less you write, the better you code . Alfresco is full of hooks! .!
!
Keep it SSO
[Open]
Resources
And some contact data
!http://github.com/keensoft/alfresco-summit-2014!
[Enhancements 1-9]!!!!http://ecmarchitect.com/archives/2014/04/04/3687!
[Enhancement 10]!
Resources
http://www.keensoft.es!!http://github.com/keensoft!!@AngelBorroy!!http://orderofthebee.org!!http://angelborroy.wordpress.com!
Contact