Content is a fully integrated content management solution inside eXo Platform. Basically, in eXo Platform, the extension mechanism is used to add content features. To have more information about the extension mechanism, refer to the GateIn Reference Guide.
This integrated solution provides users with a comprehensive platform about integrating applications, managing and publishing content - all from a single, familiar console.
When starting a new project, you can see Content as a Java developer platform.
This document will give you guidelines related to building stable applications using Content from the inside. The document consists of the following main contents:
Applications describes portlet applications included in Content.
Configuration provides you the comprehensive knowledge about the configuration with a large range of configuration parameters declared in Content.
Developer References describes about extension, public APIs, Java APIs, FAQs and related others in Content.
All package actions in Content are started from the _delivery_ folder, so you should go to this folder first.
$ cd ecms/delivery
Package WCM standalone version - Tomcat bundle
$ cd wcm/assembly $ mvn clean install
Package WCM with workflow enabled - Tomcat bundle
$ cd wkf-wcm/assembly $ mvn clean install
Make WCM EAR packages to run with jBoss
$ cd wcm/assembly $ mvn clean install
Make WCM extension EAR
$ cd packaging/wcm/ear $ mvn clean install
Make WCM demo sites EAR
$ cd packaging/ecmdemo/ear $ mvn clean install
Make workflow EAR
$ cd packaging/workflow/ear $ mvn clean install
This chapter provides you a comprehensive view about portlet applications of Content, including:
These portlet applications are packaged as Web application archives (WARs).
Also, you can specify the package of each portlet and its available preferences that allow you to extend the configuration choices for standard preferences defined in portlet.xml.
The Content Detail portlet allows users to view the detail of a specific content.
This is an example of the Content Detail portlet used in Content:
Packaging: This portlet is packaged in the presentation.war file.
The portlet class name: org.exoplatform.wcm.webui.scv.UISingleContentViewerPortlet
Preference | Type | Value | Description |
---|---|---|---|
repository | String | repository | The repository where data are stored and maintained. |
workspace | String | collaboration | The workspace where content is stored. |
nodeIdentifier | String | N/A | The UUID or the path of content that you want to show. |
ShowTitle | Boolean | true | Show the content title on the top of the portlet. |
ShowDate | Boolean | false | Show the content date on the top of the portlet. |
ShowOptionBar | Boolean | false | Show a bar with some actions (Print, Back). |
ContextEnable | Boolean | false | Define if the portlet will use the parameter on URL as the path to content to display or not. |
ParameterName | String | content-id | Define which parameter will be used to get the content's path. |
ShowVote | Boolean | false | Show the result of voting for the displayed content. |
ShowComments | Boolean | false | Show the existing comments of this content (if any). |
sharedCache | Boolean | true | Define if the portlet will cache the displayed contents. |
<portlet-preferences>
<preference>
<name>repository</name>
<value>repository</value>
<read-only>false</read-only>
</preference>
<preference>
<name>workspace</name>
<value>collaboration</value>
<read-only>false</read-only>
</preference>
<preference>
<name>nodeIdentifier</name>
<value>/myfolder/mycontent</value>
<read-only>false</read-only>
</preference>
<preference>
<name>ShowTitle</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>ShowDate</name>
<value>false</value>
<read-only>false</read-only>
</preference>
<preference>
<name>ShowOptionBar</name>
<value>false</value>
<read-only>false</read-only>
</preference>
<preference>
<name>ShowPrintAction</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>isQuickCreate</name>
<value>false</value>
<read-only>true</read-only>
</preference>
<preference>
<name>ContextEnable</name>
<value>false</value>
<read-only>false</read-only>
</preference>
<preference>
<name>ParameterName</name>
<value>content-id</value>
<read-only>false</read-only>
</preference>
<preference>
<name>sharedCache</name>
<value>true</value>
<read-only>false</read-only>
</preference>
</portlet-preferences>
In Content 2.3.0, some preferences are no longer used, for example, the ShowPrintAction preference.
The Content List portlet shows a list of contents which already exist in the system.
This is an example of the Content List portlet used in Content:
Packaging: This porlet is packaged in the presentation.war file.
The portlet class name: org.exoplatform.wcm.webui.clv.UICLVPortlet
Preference | Type | Value | Description |
---|---|---|---|
mode | String | AutoViewerMode | The mode for displaying content of the portlet: all contents in a specific folder or all specific contents in the portlet. |
folderPath | String | The path to the folder whose contents are displayed by this portlet. | |
orderBy | String | publication:liveDate | The property by which all the contents in the portlet are sorted. |
orderType | String | DESC | The type of the content sort method: ascending or descending. |
header | String | The header of the portlet which is displayed at the top of the portlet. | |
automaticDetection | Boolean | true | This value indicates whether the header of the portlet is selected to be the title of the folder given in the folderPath parameter (true value) or the value given in the header parameter above. |
formViewTemplatePath | String | /exo:ecm/views/templates/content-list-viewer/list/UIContentListPresentationDefault.gtmpl | The path to the template used to display the contents in this portlet. |
paginatorTemplatePath | String | /exo:ecm/views/templates/content-list-viewer/paginators/UIPaginatorDefault.gtmpl | The path to the paginator used to display the contents in this portlet. |
itemsPerPage | Integer | 10 | The number of contents displayed in every "page" of the portlet. |
showThumbnailsView | Boolean | true | This value indicates whether the content image in this portlet is shown or not. |
showTitle | Boolean | true | This value indicates whether the content title in this portlet is shown or not. |
showHeader | Boolean | true | This value indicates whether the content header in this portlet is shown or not. |
showRefreshButton | Boolean | false | This value indicates whether the Refresh button is shown in this portlet or not. |
showDateCreated | Boolean | true | This value indicates whether the content created date in this portlet is shown or not. |
showReadmore | Boolean | true | This value indicates whether the Read more button is shown in every content of the portlet or not. After clicking this button, the user can read the whole text of the content. |
showSummary | Boolean | true | This value indicates whether the content summary in this portlet is shown or not. |
showLink | Boolean | true | If this value is true , the header of every content is also the link to view this content fully. If the value is false , the header is considered as a simple text. |
showRssLink | Boolean | true | Show the RSS link of this portlet. |
basePath | String | detail | Show the page in which the full content is displayed when the user clicks to the Read more button. |
contextualFolder | String | contextualDisable | Enable/disable the contextual mode of the portlet. If enabled, the portlet can take the folder path indicated in the URL to display contents. |
showScvWith | String | content-id | The parameter name which shows the folder path in URL when the Read more button is clicked. |
showClvBy | String | folder-id | The parameter name which shows the folder path in URL. |
sharedCache | Boolean | true | Define if the portlet will cache the displayed contents. |
<portlet-preferences>
<preference>
<name>mode</name>
<value>AutoViewerMode</value>
<read-only>false</read-only>
</preference>
<preference>
<name>folderPath</name>
<value/>
<read-only>false</read-only>
</preference>
<preference>
<name>orderBy</name>
<value>publication:liveDate</value>
<read-only>false</read-only>
</preference>
<preference>
<name>orderType</name>
<value>DESC</value>
<read-only>false</read-only>
</preference>
<preference>
<name>header</name>
<value/>
<read-only>false</read-only>
</preference>
<preference>
<name>automaticDetection</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>formViewTemplatePath</name>
<value>/exo:ecm/views/templates/content-list-viewer/list/UIContentListPresentationDefault.gtmpl</value>
<read-only>false</read-only>
</preference>
<preference>
<name>paginatorTemplatePath</name>
<value>/exo:ecm/views/templates/content-list-viewer/paginators/UIPaginatorDefault.gtmpl</value>
<read-only>false</read-only>
</preference>
<preference>
<name>itemsPerPage</name>
<value>10</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showThumbnailsView</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showTitle</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showHeader</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showRefreshButton</name>
<value>false</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showDateCreated</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showReadmore</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showSummary</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showLink</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showRssLink</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>basePath</name>
<value>detail</value>
<read-only>false</read-only>
</preference>
<preference>
<name>contextualFolder</name>
<value>contextualDisable</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showScvWith</name>
<value>content-id</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showClvBy</name>
<value>folder-id</value>
<read-only>false</read-only>
</preference>
<preference>
<name>sharedCache</name>
<value>true</value>
<read-only>false</read-only>
</preference>
</portlet-preferences>
The Search portlet allows users to do a search with any string. In Content, there are three types of search: quick search, advanced search and search with saved queries.
The users can find this porlet in the front page. This is an example of the Search portlet used in Content:
Packaging: This portlet is packaged in the searches.war file.
The portlet class name: org.exoplatform.wcm.webui.search.UIWCMSearchPortlet
Preference | Type | Value | Description |
---|---|---|---|
repository | string | repository | The place where data are stored and maintained. |
workspace | string | collaboration | The workspace where the content is stored. |
searchFormTemplatePath | string | /exo:ecm/views/templates/WCM Advance Search/search-form/UIDefaultSearchForm.gtmpl | The path to the search form template. |
searchResultTemplatePath | string | /exo:ecm/views/templates/WCM Advance Search/search-result/UIDefaultSearchResult.gtmpl | The path to the search result template. |
searchPaginatorTemplatePath | string | /exo:ecm/views/templates/WCM Advance Search/search-paginator/UIDefaultSearchPaginator.gtmpl | The path to the search paginator template. |
searchPageLayoutTemplatePath | string | /exo:ecm/views/templates/WCM Advance Search/search-page-layout/UISearchPageLayoutDefault.gtmpl | The path to the search page template. |
itemsPerPage | Integer | 5 | The number of items for each page. |
showQuickEditButton | boolean | true | Show or hide the quick edit icon. |
basePath | string | parameterizedviewer | The page which is used to display the search result. |
<portlet-preferences>
<preference>
<name>repository</name>
<value>repository</value>
<read-only>false</read-only>
</preference>
<preference>
<name>workspace</name>
<value>collaboration</value>
<read-only>false</read-only>
</preference>
<preference>
<name>searchFormTemplatePath</name>
<value>/exo:ecm/views/templates/WCM Advance Search/search-form/UIDefaultSearchForm.gtmpl</value>
<read-only>false</read-only>
</preference>
<preference>
<name>searchResultTemplatePath</name>
<value>/exo:ecm/views/templates/WCM Advance Search/search-result/UIDefaultSearchResult.gtmpl</value>
<read-only>false</read-only>
</preference>
<preference>
<name>searchPaginatorTemplatePath</name>
<value>/exo:ecm/views/templates/WCM Advance Search/search-paginator/UIDefaultSearchPaginator.gtmpl</value>
<read-only>false</read-only>
</preference>
<preference>
<name>searchPageLayoutTemplatePath</name>
<value>/exo:ecm/views/templates/WCM Advance Search/search-page-layout/UISearchPageLayoutDefault.gtmpl</value>
<read-only>false</read-only>
</preference>
<preference>
<name>itemsPerPage</name>
<value>5</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showQuickEditButton</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>basePath</name>
<value>parameterizedviewer</value>
<read-only>false</read-only>
</preference>
</portlet-preferences>
The Sites Explorer portlet is used to manage all documents in different drives. With this portlet, users can do many different actions depending on their roles, such as adding/deleting a category and a document, showing/hiding a node, managing publication, and more.
This is an example of the Sites Explorer portlet used in Content:
Packaging: The porlet is packaged in the ecmexplorer.war file.
The portlet class name: org.exoplatform.ecm.webui.component.explorer.UIJCRExplorerPortlet
Preference | Type | Value | Description |
---|---|---|---|
repository | string | repository | The repository name which is used in an instance of Sites Explorer. |
workspace | string | N/A | Not in use. The workspace name was included in the Drive. |
path | string | N/A | The path of the node. This preference will be used when the selected usecase is Parameterize. |
drive | string | N/A | Not in use. Replaced by the driveName preference. |
views | string | N/A | Not in use. The views will be displayed basing on the Drive which the user has the access permission. |
allowCreateFolders | string | N/A | Allow creating a folder by type. When you do not specify the value, the default value will be nt:unstructured, nt:folder. |
categoryMandatoryWhenFileUpload | boolean | false | Force a user to add a category when uploading or creating a document. |
uploadFileSizeLimitMB | float | 150 | The maximum size of a file that is uploaded to the system (MB). |
usecase | string | selection | The behavior to access Sites Explorer. By default, the "selection" option is configured. Besides "selection", there are four other ways to configure the Sites Explorer: Jailed, Personal, Social, Parameterize. |
driveName | string | private | The name of drive which the user wants to access. |
trashHomeNodePath | string | /Trash | The location to store the deleted nodes. |
trashRepository | string | repository | The name of the repository where stores the deleted nodes. |
trashWorkspace | string | collaboration | The name of the workspace where stores the deleted nodes. |
editInNewWindow | boolean | false | Allow editing documents with or without a window popup. |
showTopBar | boolean | true | Allow showing the Top bar or not. |
showActionBar | boolean | true | Allow showing the Action bar or not. |
showSideBar | boolean | true | Allow showing the Side bar or not. |
showFilterBar | boolean | true | Allow showing the Filter bar or not. |
<portlet-preferences>
<preference>
<name>repository</name>
<value>repository</value>
<read-only>false</read-only>
</preference>
<preference>
<name>workspace</name>
<value/>
<read-only>false</read-only>
</preference>
<preference>
<name>path</name>
<value/>
<read-only>false</read-only>
</preference>
<preference>
<name>drive</name>
<value/>
<read-only>false</read-only>
</preference>
<preference>
<name>views</name>
<value/>
<read-only>false</read-only>
</preference>
<preference>
<name>allowCreateFolders</name>
<value/>
<read-only>false</read-only>
</preference>
<preference>
<name>categoryMandatoryWhenFileUpload</name>
<value>false</value>
<read-only>false</read-only>
</preference>
<preference>
<name>uploadFileSizeLimitMB</name>
<value>150</value>
<read-only>false</read-only>
</preference>
<preference>
<name>usecase</name>
<value>selection</value>
<read-only>false</read-only>
</preference>
<preference>
<name>driveName</name>
<value>Private</value>
<read-only>false</read-only>
</preference>
<preference>
<name>trashHomeNodePath</name>
<value>/Trash</value>
<read-only>false</read-only>
</preference>
<preference>
<name>trashRepository</name>
<value>repository</value>
<read-only>false</read-only>
</preference>
<preference>
<name>trashWorkspace</name>
<value>collaboration</value>
<read-only>false</read-only>
</preference>
<preference>
<name>editInNewWindow</name>
<value>false</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showTopBar</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showActionBar</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showSideBar</name>
<value>true</value>
<read-only>false</read-only>
</preference>
<preference>
<name>showFilterBar</name>
<value>true</value>
<read-only>false</read-only>
</preference>
</portlet-preferences>
The Administration portlet is used to manage the main ECM functions, including categories and tags, content presentation, types of content and advanced configuration.
This is an example of the Administration portlet used in Content:
Packaging: This portlet is packaged in the ecmadmin.war file.
The portlet class name: org.exoplatform.ecm.webui.component.admin.UIECMAdminPortlet
Preference | Type | Value | Description |
---|---|---|---|
repository | string | Repository | The name of the current repository. |
<portlet-preferences>
<preference>
<name>repository</name>
<value>repository</value>
<read-only>false</read-only>
</preference>
</portlet-preferences>
The Fast Content Creator portlet consists of two modes: Standard Content Creator and Basic Content Creator. This portlet allows users to quickly create contents without accessing the Sites Explorer portlet.
This is an example of the Fast Content Creator portlet used in Content:
By default, this porlet is applied for the Contact Us portlet in Content.
Packaging: This portlet is packaged in the formgenerator.war file.
The portlet class name: org.exoplatform.wcm.webui.fastcontentcreator.UIFCCPortlet
Preference | Type | Value | Description |
---|---|---|---|
mode | string | basic | The default mode of the Fast Content Creator portlet. |
repository | string | repository | The name of the current repository. |
workspace | string | collaboration | The workspace where the content is stored. |
path | string | /Groups/platform/users/Documents | The destination path where the content is stored. |
type | string | exo:article | The node type of document which is shown on the dialog form. |
saveButton | string | Save | The custom button: Save. |
saveMessage | string | This node has been saved successfully | The custom message when the user clicks the Save button. |
isRedirect | boolean | false | Specify whether redirecting to another page or not. |
redirectPath | string | http://www.google.com.vn | The path to which the page will redirect. |
isActionNeeded | boolean | true | Specify whether an action is needed to save to the configuration or not. |
<portlet-preferences>
<preference>
<name>mode</name>
<value>basic</value>
<read-only>true</read-only>
</preference>
<preference>
<name>repository</name>
<value>repository</value>
<read-only>false</read-only>
</preference>
<preference>
<name>workspace</name>
<value>collaboration</value>
<read-only>false</read-only>
</preference>
<preference>
<name>path</name>
<value>/Groups/platform/users/Documents</value>
<read-only>false</read-only>
</preference>
<preference>
<name>type</name>
<value>exo:article</value>
<read-only>false</read-only>
</preference>
<preference>
<name>saveButton</name>
<value>Save</value>
<read-only>false</read-only>
</preference>
<preference>
<name>saveMessage</name>
<value>This node has been saved successfully</value>
<read-only>false</read-only>
</preference>
<preference>
<name>isRedirect</name>
<value>false</value>
<read-only>false</read-only>
</preference>
<preference>
<name>redirectPath</name>
<value>http://www.google.com.vn</value>
<read-only>false</read-only>
</preference>
<preference>
<name>isActionNeeded</name>
<value>true</value>
<read-only>true</read-only>
</preference>
</portlet-preferences>
The Form Builder portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
The Form Builder portlet allows users to create node types and document templates for node types.
This is an example of the Form Builder portlet used in Content:
Packaging: This porlet is packaged in the formgenerator.war file.
The portlet class name: org.exoplatform.wcm.webui.formgenerator.UIFormGeneratorPortlet
Preference | Type | Value | Description |
---|---|---|---|
repository | string | repository | The current repository name which is always "repository". |
<portlet-preferences>
<preference>
<name>repository</name>
<value>repository</value>
<read-only>false</read-only>
</preference>
</portlet-preferences>
The Authoring portlet allows users to manage contents in draft and ones which need to be approved or published.
This is an example of the Authoring portlet used in Content:
Packaging: This porlet is packaged in the authoring-apps.war file.
The portlet class name: org.exoplatform.wcm.webui.authoring.UIWCMDashboardPortlet
Preference | Type | Value | Description |
---|---|---|---|
repository | string | Repository | The name of the repository. |
workspace | string | Collaboration | The name of the workspace. |
drive | string | Collaboration | The name of the drive. |
<portlet-preferences>
<preference>
<name>repository</name>
<value>repository</value>
<read-only>true</read-only>
</preference>
<preference>
<name>workspace</name>
<value>collaboration</value>
<read-only>false</read-only>
</preference>
<preference>
<name>drive</name>
<value>collaboration</value>
<read-only>false</read-only>
</preference>
</portlet-preferences>
The Newsletter portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
The Newsletter portlet is used to help users quickly get the updated newsletter from a site.
This is an example of the Newsletter portlet used in Content:
Packaging: This portlet is packaged in the newsletter.war file.
The portlet class name: org.exoplatform.wcm.webui.newsletter.manager.UINewsletterManagerPortlet
The SEO portlet allows users to manage SEO data of web content and web pages, so they can maximize their website position on search engines.
This is an example of the SEO portlet used in Content:
Packaging: This porlet is packaged in the seo.war file.
The portlet class name: org.exoplatform.wcm.webui.seo.UISEOToolbarPortlet
This chapter will help you understand what CMIS is, how it is extended in WCM, and its features via the following topics:
eXo Platform provides CMIS support using the xCMIS project and the WCM Storage provider.
The CMIS standard aims at defining a common content management web services interface that can be applied in content repositories and bring about the interoperability across repositories. The formal specification of CMIS standard is approved by the Organization for the Advancement of Structured Information Standards (OASIS) technical committee, who drives the development, convergence and adoption of global information society. With CMIS, enterprises now can deploy systems independently, and create specialized applications running over a variety of content management systems.
To see the advantages of content interoperability and the significance of CMIS as a whole, it is necessary to learn about mutual targets which caused the appearance of specification first.
Content integration: With CMIS, integrating content among various repositories, even those created by different vendors in a single application, becomes faster, simpler and more effective. CMIS makes it possible for customers to integrate content management systems into their key business processes across business departments and vendor implementations.
Access unification: CMIS enables different applications and manufacturers to be connected to a CMIS-enabled content repository simply. With CMIS, a business application's developer can focus on the application's business logic, rather than issues related to the compatibility or content migration.
The xCMIS project, which is initially contributed to the Open Source community by eXo Platform, is an Open Source implementation of the Content Management Interoperability Services (CMIS) specification. xCMIS supports all the features stated in the CMIS core definition and both REST AtomPub and Web Services (SOAP/WSDL) protocol bindings.
To learn more about xCMIS, visit:
eXo CMIS is built on the top of xCMIS embedded in eXo Platform to expose the WCM drives as the CMIS repositories. The CMIS features are implemented as a set of components deployed on the eXo Container using XML files to describe the service configuration.
SOAP protocol binding is not implemented in eXo CMIS.
Figure: How eXo CMIS works
WCM drives exposure is implemented as a WCM storage provider to the xCMIS SPI. The storage provider uses mappings from the WCM's ManageDriveService to actual JCR nodes. AtomPub bindings makes WCM structure available via CMIS standard API.
This is related to Content Management Interoperability Services (CMIS) Version 1.0 OASIS Standard 1 May 2010
http://en.wikipedia.org/wiki/Content_Management_Interoperability_Services
The CMIS interface is designed to be layered on top of existing Content Management systems and their existing programmatic interfaces. It is intended to expose all of the CM systems capabilities through the CMIS interfaces exhaustively. The CMIS specification defines the followings:
A standard "domain model" for an ECM system - a set of core concepts included in all modern ECM systems, such as Object Types, properties, folders, documents, versions, and relationships; and a set of operations performed on those concepts, such as updating documents, or navigating via a folder hierarchy.
The way to bind the CMIS domain model to two different web service protocols, including the Simple Object Access Protocol (SOAP) used in many ECM systems, and the Atom used in many Web 2.0 applications.
The SOAP protocol is not implemented in eXo CMIS.
The CMIS specification provides a Web services interface which can:
Work over existing repositories, enabling customers to build and leverage applications against multiple repositories.
Decouple Web services and content from the content management repository, enabling customers to manage content independently.
Provide common Web services and Web 2.0 interfaces to dramatically simplify the application development.
Build the development platform and language agnostic.
Support the composite application development and mashups by the business or IT analysts.
xCMIS includes the client side frameworks for integrating content from different enterprise repositories, according to CMIS standard.
The project is to make joining Enterprise Content repositories simpler by offering CMIS abilities and exposing them to language-independent CMIS clients via the most convenient protocol.
xCMIS project:
Is embedded, packaged as the J2EE Web archive (WAR) and prepared "download and go" Tomcat bundle.
Has a live demo with the full-featured CMIS Expert client, which is accessible via xcmis.org site and with prepared "download and go" Tomcat bundle (the client is accessible as the remote gadget).
Is embedded in eXo Platform to create the special xCMIS jcr repository and access it with any CMIS client.
Tested with third-party CMIS clients, such as IBM CMIS Firefox Connector and CMIS Spaces Flex+AIR client. Either local repository (as described here), or can be used as a CMIS repository's endpoint URL for these, or other types of clients.
Benefits of xCMIS:
xCMIS is an open source, server side Java CMIS implementation, enabling to expose content in the existing content repositories according to the protocols defined in the CMIS specification.
xCMIS will give developers a way to make their content repositories "pluggable" on the server side based on the internal Storage Provider Interface and additional protocol on-demand bindings.
xCMIS will provide (several) CMIS client frameworks for repository-application and repository-repository interactions. The programming language and supported protocol can be selected by users. For example, the reasonable choice for using web applications, gadgets, and/or mashups is JavaScript, or GWT over REST AtomPub, while for inter-repository exchange, it may be Java over Web Services like WSDL/SOAP.
Both the server and client sides of xCMIS are easily integrated in eXo Platform 3.0 infrastructure. In particular, xCMIS exposes the eXo JCR content repository and provides a framework for building web applications and gadgets for the GateIn portal.
The xCMIS project is distributed under the LGPL license. You can download sources on Google code, or visit Community Wiki for more information.
eXo Web Content Management (WCM) system provides CMIS access to its content storage features:
WCM drives
Document files and folders
Symlinks
Categories
To expose WCM drives as CMIS repositories there is a special extension of CmisRegistry. Read the admin guide for the configuration of org.exoplatform.ecms.xcmis.sp.jcr.exo.DriveCmisRegistry component.
Work with CMIS is based on reference documents returned by services. Each CMIS service returns response containing links to other services describing the Document or operations on it. In most cases, a Document will be asked by its ID. Some services accepts a Document path.
Notes for use cases: To access the eXo CMIS services from the client side, use the Curl tool. The CMIS AtomPub binding which is based upon the Atom (RFC4287) and Atom Publishing Protocol (RFC5023) will be used.
SOAP binding is not implemented in eXo Platform 3.x.
CMIS uses special JCR namespaces cmis and xcmis internally.
To expose drives content following nodetypes supported:
nt:file nodetype for representation of cmis:documents
nt:folder for representation of cmis:folder
Since the CMIS specification does not allow having more root types except ones described above (cmis:documents and cmis:folder), those two (nt:file and nt:folder) are mapped to CMIS types.
There are two more nodetypes which are used: cmis:policy and cmis:relationship which represent CMIS types with corresponded (see Services description for details).
Additionally, nodetypes used in WCM are mapped as follow:
nt:unstructured + extensions as cmis:folder
exo:taxonomy + extensions as cmis:folder
In other words only nodetypes extending nt:file, nt:folder, nt:unstructured and exo:taxonomy will be exposed correctly via CMIS API.
WCM's nodetype exo:article is not supported by eXo CMIS due to uncompliant structure to nt:file.
The WCM drive is used to expose as an isolated repository via the CMIS service. Operations on the repository will reflect the drive immediately.
When working with CMIS repositories, it is important to understand that a repository reflects a WCM Drive, which is a sub-tree in JCR workspace. Two or more drives can be mapped to a same workspace or a sub-tree. As a result, changes in one repository can affect others. Refer to the WCM drives mappings to know actual location of a content you will access or change.
Login to the website as a user with the developer role.
Open Group | Sites Explorer, you can see the drives set of WCM, such as Sites Management, DMS Administration.
Get the list of these WCM drives via CMIS using Curl, asking getRepositories service:
curl -o getrepos.xml -u root:gtn http://localhost:8080/rest/private/cmisatom/
The requested file (getrepos.xml) contains the set of Repositories in the AtomPub format. The root element represents the set of workspaces representing WCM drives related to resources, for example, for DMS Administration, the response will contain data like:
<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">
<workspace>
<atom:title type="text">DMS Administration</atom:title>
<cmisra:repositoryInfo xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/">
<cmis:repositoryId>DMS Administration</cmis:repositoryId>
<cmis:repositoryName>DMS Administration</cmis:repositoryName>
</cmisra:repositoryInfo>
<collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/query">
<atom:title type="text">Query</atom:title>
<cmisra:collectionType>query</cmisra:collectionType>
</collection>
<collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/children/00exo0jcr0root0uuid0000000000000">
<atom:title type="text">Folder Children</atom:title>
<cmisra:collectionType>root</cmisra:collectionType>
</collection>
<collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/checkedout">
<atom:title type="text">Checkedout collection</atom:title>
<cmisra:collectionType>checkedout</cmisra:collectionType>
</collection>
<collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/unfiled">
<atom:title type="text">Unfiled collection</atom:title>
<cmisra:collectionType>unfiled</cmisra:collectionType>
</collection>
<collection href="http://localhost:8080/rest/private/cmisatom/DMS%20Administration/types">
<atom:title type="text">Types Children</atom:title>
<cmisra:collectionType>types</cmisra:collectionType>
</collection>
<cmisra:uritemplate>
<cmisra:template>http://localhost:8080/rest/private/cmisatom/DMS%20Administration/object/{id}?filter={filter}&includeAllowableActions={includeAllowableActions}&includePolicyIds={includePolicyIds}&includeRelationships={includeRelationships}&includeACL={includeACL}&renditionFilter={renditionFilter}
</cmisra:template>
<cmisra:type>objectbyid</cmisra:type>
<cmisra:mediatype>application/atom+xml;type=entry</cmisra:mediatype>
</cmisra:uritemplate>
<cmisra:uritemplate>
<cmisra:template>http://localhost:8080/rest/private/cmisatom/DMS%20Administration/objectbypath?path={path}&filter={filter}&includeAllowableActions={includeAllowableActions}&includePolicyIds={includePolicyIds}&includeRelationships={includeRelationships}&includeACL={includeACL}&renditionFilter={renditionFilter}
</cmisra:template>
<cmisra:type>objectbypath</cmisra:type>
<cmisra:mediatype>application/atom+xml;type=entry</cmisra:mediatype>
</cmisra:uritemplate>
<cmisra:uritemplate>
<cmisra:template>http://localhost:8080/rest/private/cmisatom/DMS%20Administration/query?q={q}&searchAllVersions={searchAllVersions}&maxItems={maxItems}&skipCount={skipCount}&includeAllowableActions={includeAllowableActions}=&includeRelationships={includeRelationships}
</cmisra:template>
<cmisra:type>query</cmisra:type>
<cmisra:mediatype>application/atom+xml;type=feed</cmisra:mediatype>
</cmisra:uritemplate>
<cmisra:uritemplate>
<cmisra:template>http://localhost:8080/rest/private/cmisatom/DMS%20Administration/typebyid/{id}
</cmisra:template>
<cmisra:type>typebyid</cmisra:type>
<cmisra:mediatype>application/atom+xml;type=entry</cmisra:mediatype>
</cmisra:uritemplate>
</workspace>
</service>
Here are the collection of services and predefined templates which can be used from the client side to request resources related to this repository. For example, to get the WCM node of the DMS Administration drive by path, the objectbypath template can be used:
http://localhost:8080/rest/private/cmisatom/DMS%20Administration/objectbypath?path={path}&filter={filter}&includeAllowableActions={includeAllowableActions}&includePolicyIds={includePolicyIds}&includeRelationships={includeRelationships}&includeACL={includeACL}&renditionFilter={renditionFilter}
where parameters include:
Required:
ID repositoryId: The identifier for the repository.
String path: The path to the object.
Optional:
String filter
Boolean includeAllowableActions
Enum includeRelationships
String renditionFilter
Boolean includePolicyIds
Boolean includeACL
Find full description of all specified services in the CMIS specification.
Symlinks are used to organize the virtual access to documents in WCM, which is implemented like links in Unix/Linux/Mac OS (refer to ln command for more details).
JCR exo:symlink nodetype is used for such nodetypes.
1. Login to the ACME website as a user with the developer role.
2. Open Group --> Sites Explorer --> Sites Management, go to the folder /acme/documents.
3. Upload any file (for example test.txt) to /acme/documents.
4. Add this file to the acme/News category. It will create a symlink to /acme/documents/test.txt in /acme/categories/acme/News.
5. Get content of folder /acme/categories/acme/News via CMIS:
curl -o news.xml -u root:gtn http://localhost:8080/rest/private/cmisatom/Managed%20Sites/objectbypath?path=/acme/categories/acme/News
The requested file (products.xml) contains the entry with information about the folder.
The list of properties for the object (such as node Id or type).
Allowable actions can be performed on the document; for example, requesting the children list.
ACL and policies information.
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">
<id>f59a3539c0a80003625790bdadf566c5</id>
<published>2010-09-09T18:11:57.707Z</published>
<updated>2010-09-09T18:11:57.707Z</updated>
<summary type="text"/>
<author>
<name>system</name>
</author>
<title type="text">News</title>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites" rel="service" type="application/atomsvc+xml"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f59a3539c0a80003625790bdadf566c5" rel="self"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f59a3539c0a80003625790bdadf566c5" rel="edit"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/typebyid/exo%3Ataxonomy" rel="describedby" type="application/atom+xml; type=entry"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/allowableactions/f59a3539c0a80003625790bdadf566c5" rel="http://docs.oasis-open.org/ns/cmis/link/200908/allowableactions" type="application/cmis+xml; type=allowableActions"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/relationships/f59a3539c0a80003625790bdadf566c5" rel="http://docs.oasis-open.org/ns/cmis/link/200908/relationships" type="application/atom+xml; type=feed"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/policies/f59a3539c0a80003625790bdadf566c5" rel="http://docs.oasis-open.org/ns/cmis/link/200908/policies" type="application/atom+xml; type=feed"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/objacl/f59a3539c0a80003625790bdadf566c5" rel="http://docs.oasis-open.org/ns/cmis/link/200908/acl" type="application/cmisacl+xml"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/children/f59a3539c0a80003625790bdadf566c5" rel="down" type="application/atom+xml; type=feed"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/descendants/f59a3539c0a80003625790bdadf566c5" rel="down" type="application/cmistree+xml"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/foldertree/f59a3539c0a80003625790bdadf566c5" rel="http://docs.oasis-open.org/ns/cmis/link/200908/foldertree" type="application/atom+xml; type=feed"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f59a3533c0a8000339af97059f243a25" rel="up" type="application/atom+xml; type=entry"/>
<content type="text">News</content>
<cmisra:object xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/">
<cmis:properties>
<cmis:propertyId displayName="cmis:allowedChildObjectTypeIds" localName="cmis:allowedChildObjectTypeIds" propertyDefinitionId="cmis:allowedChildObjectTypeIds" queryName="cmis:allowedChildObjectTypeIds"/>
<cmis:propertyString displayName="cmis:path" localName="cmis:path" propertyDefinitionId="cmis:path" queryName="cmis:path">
<cmis:value>/acme/categories/acme/News</cmis:value>
</cmis:propertyString>
<cmis:propertyId displayName="cmis:objectTypeId" localName="cmis:objectTypeId" propertyDefinitionId="cmis:objectTypeId" queryName="cmis:objectTypeId">
<cmis:value>exo:taxonomy</cmis:value>
</cmis:propertyId>
<cmis:propertyString displayName="cmis:lastModifiedBy" localName="cmis:lastModifiedBy" propertyDefinitionId="cmis:lastModifiedBy" queryName="cmis:lastModifiedBy"/>
<cmis:propertyString displayName="cmis:name" localName="cmis:name" propertyDefinitionId="cmis:name" queryName="cmis:name">
<cmis:value>News</cmis:value>
</cmis:propertyString>
<cmis:propertyString displayName="cmis:createdBy" localName="cmis:createdBy" propertyDefinitionId="cmis:createdBy" queryName="cmis:createdBy"/>
<cmis:propertyId displayName="cmis:objectId" localName="cmis:objectId" propertyDefinitionId="cmis:objectId" queryName="cmis:objectId">
<cmis:value>f59a3539c0a80003625790bdadf566c5</cmis:value>
</cmis:propertyId>
<cmis:propertyDateTime displayName="cmis:creationDate" localName="cmis:creationDate" propertyDefinitionId="cmis:creationDate" queryName="cmis:creationDate"/>
<cmis:propertyString displayName="cmis:changeToken" localName="cmis:changeToken" propertyDefinitionId="cmis:changeToken" queryName="cmis:changeToken"/>
<cmis:propertyId displayName="cmis:baseTypeId" localName="cmis:baseTypeId" propertyDefinitionId="cmis:baseTypeId" queryName="cmis:baseTypeId">
<cmis:value>cmis:folder</cmis:value>
</cmis:propertyId>
<cmis:propertyId displayName="cmis:parentId" localName="cmis:parentId" propertyDefinitionId="cmis:parentId" queryName="cmis:parentId">
<cmis:value>f59a3533c0a8000339af97059f243a25</cmis:value>
</cmis:propertyId>
<cmis:propertyDateTime displayName="cmis:lastModificationDate" localName="cmis:lastModificationDate" propertyDefinitionId="cmis:lastModificationDate" queryName="cmis:lastModificationDate"/>
</cmis:properties>
<cmis:acl/>
<cmis:exactACL>false</cmis:exactACL>
<cmis:policyIds/>
<cmis:rendition/>
</cmisra:object>
</entry>
To get the file which has been uploaded above, use the children service to get the list of child nodes of /acme/documents. Find this service URL in the response XML above:
curl -o childs.xml -u root:gtn http://localhost:8080/rest/private/cmisatom/Managed%20Sites/children/f59a3539c0a80003625790bdadf566c5
In the requested file (childs.xml), find the entry related to test.txt file uploaded via the Sites Explorer. Search for the "test.txt" name by title.
<entry xmlns:cmisra="http://docs.oasis-open.org/ns/cmis/restatom/200908/">
<id>f708e208c0a80003554babb97bd934ba</id>
<published>2010-09-09T18:06:31.987Z</published>
<updated>2010-09-09T18:06:31.987Z</updated>
<summary type="text"/>
<author>
<name>system</name>
</author>
<title type="text">test.txt</title>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites" rel="service" type="application/atomsvc+xml"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f708e208c0a80003554babb97bd934ba" rel="self"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f708e208c0a80003554babb97bd934ba" rel="edit"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/typebyid/cmis%3Adocument" rel="describedby" type="application/atom+xml; type=entry"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/allowableactions/f708e208c0a80003554babb97bd934ba" rel="http://docs.oasis-open.org/ns/cmis/link/200908/allowableactions" type="application/cmis+xml; type=allowableActions"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/relationships/f708e208c0a80003554babb97bd934ba" rel="http://docs.oasis-open.org/ns/cmis/link/200908/relationships" type="application/atom+xml; type=feed"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/policies/f708e208c0a80003554babb97bd934ba" rel="http://docs.oasis-open.org/ns/cmis/link/200908/policies" type="application/atom+xml; type=feed"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/objacl/f708e208c0a80003554babb97bd934ba" rel="http://docs.oasis-open.org/ns/cmis/link/200908/acl" type="application/cmisacl+xml"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/versions/f708a0f1c0a8000333e3681f99fab760" rel="version-history" type="application/atom+xml; type=feed"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/object/f708e208c0a80003554babb97bd934ba?returnVersion=latest" rel="current-version" type="application/atom+xml; type=entry"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/parents/f708e208c0a80003554babb97bd934ba" rel="up" type="application/atom+xml; type=feed"/>
<link href="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/file/f708e208c0a80003554babb97bd934ba" rel="edit-media"/>
<content src="http://localhost:8080/rest/private/cmisatom/Managed%20Sites/file/f708e208c0a80003554babb97bd934ba" type="text/plain"/>
<cmisra:object xmlns:cmis="http://docs.oasis-open.org/ns/cmis/core/200908/">
<cmis:properties>
<cmis:propertyBoolean displayName="cmis:isLatestMajorVersion" localName="cmis:isLatestMajorVersion" propertyDefinitionId="cmis:isLatestMajorVersion" queryName="cmis:isLatestMajorVersion">
<cmis:value>false</cmis:value>
</cmis:propertyBoolean>
<cmis:propertyInteger displayName="cmis:contentStreamLength" localName="cmis:contentStreamLength" propertyDefinitionId="cmis:contentStreamLength" queryName="cmis:contentStreamLength">
<cmis:value>38</cmis:value>
</cmis:propertyInteger>
<cmis:propertyId displayName="cmis:contentStreamId" localName="cmis:contentStreamId" propertyDefinitionId="cmis:contentStreamId" queryName="cmis:contentStreamId">
<cmis:value>f708a0c2c0a800033bedeb35caddeed1</cmis:value>
</cmis:propertyId>
<cmis:propertyId displayName="cmis:objectTypeId" localName="cmis:objectTypeId" propertyDefinitionId="cmis:objectTypeId" queryName="cmis:objectTypeId">
<cmis:value>cmis:document</cmis:value>
</cmis:propertyId>
<cmis:propertyString displayName="cmis:versionSeriesCheckedOutBy" localName="cmis:versionSeriesCheckedOutBy" propertyDefinitionId="cmis:versionSeriesCheckedOutBy" queryName="cmis:versionSeriesCheckedOutBy"/>
<cmis:propertyId displayName="cmis:versionSeriesCheckedOutId" localName="cmis:versionSeriesCheckedOutId" propertyDefinitionId="cmis:versionSeriesCheckedOutId" queryName="cmis:versionSeriesCheckedOutId"/>
<cmis:propertyString displayName="cmis:name" localName="cmis:name" propertyDefinitionId="cmis:name" queryName="cmis:name">
<cmis:value>test.txt</cmis:value>
</cmis:propertyString>
<cmis:propertyString displayName="cmis:contentStreamMimeType" localName="cmis:contentStreamMimeType" propertyDefinitionId="cmis:contentStreamMimeType" queryName="cmis:contentStreamMimeType">
<cmis:value>text/plain</cmis:value>
</cmis:propertyString>
<cmis:propertyId displayName="cmis:versionSeriesId" localName="cmis:versionSeriesId" propertyDefinitionId="cmis:versionSeriesId" queryName="cmis:versionSeriesId">
<cmis:value>f708a0f1c0a8000333e3681f99fab760</cmis:value>
</cmis:propertyId>
<cmis:propertyDateTime displayName="cmis:creationDate" localName="cmis:creationDate" propertyDefinitionId="cmis:creationDate" queryName="cmis:creationDate">
<cmis:value>2010-09-09T18:06:31.987Z</cmis:value>
</cmis:propertyDateTime>
<cmis:propertyString displayName="cmis:changeToken" localName="cmis:changeToken" propertyDefinitionId="cmis:changeToken" queryName="cmis:changeToken"/>
<cmis:propertyBoolean displayName="cmis:isLatestVersion" localName="cmis:isLatestVersion" propertyDefinitionId="cmis:isLatestVersion" queryName="cmis:isLatestVersion">
<cmis:value>true</cmis:value>
</cmis:propertyBoolean>
<cmis:propertyString displayName="cmis:versionLabel" localName="cmis:versionLabel" propertyDefinitionId="cmis:versionLabel" queryName="cmis:versionLabel">
<cmis:value>latest</cmis:value>
</cmis:propertyString>
<cmis:propertyBoolean displayName="cmis:isVersionSeriesCheckedOut" localName="cmis:isVersionSeriesCheckedOut" propertyDefinitionId="cmis:isVersionSeriesCheckedOut" queryName="cmis:isVersionSeriesCheckedOut">
<cmis:value>false</cmis:value>
</cmis:propertyBoolean>
<cmis:propertyString displayName="cmis:lastModifiedBy" localName="cmis:lastModifiedBy" propertyDefinitionId="cmis:lastModifiedBy" queryName="cmis:lastModifiedBy"/>
<cmis:propertyString displayName="cmis:createdBy" localName="cmis:createdBy" propertyDefinitionId="cmis:createdBy" queryName="cmis:createdBy"/>
<cmis:propertyString displayName="cmis:checkinComment" localName="cmis:checkinComment" propertyDefinitionId="cmis:checkinComment" queryName="cmis:checkinComment"/>
<cmis:propertyId displayName="cmis:objectId" localName="cmis:objectId" propertyDefinitionId="cmis:objectId" queryName="cmis:objectId">
<cmis:value>f708e208c0a80003554babb97bd934ba</cmis:value>
</cmis:propertyId>
<cmis:propertyBoolean displayName="cmis:isImmutable" localName="cmis:isImmutable" propertyDefinitionId="cmis:isImmutable" queryName="cmis:isImmutable">
<cmis:value>false</cmis:value>
</cmis:propertyBoolean>
<cmis:propertyBoolean displayName="cmis:isMajorVersion" localName="cmis:isMajorVersion" propertyDefinitionId="cmis:isMajorVersion" queryName="cmis:isMajorVersion">
<cmis:value>false</cmis:value>
</cmis:propertyBoolean>
<cmis:propertyId displayName="cmis:baseTypeId" localName="cmis:baseTypeId" propertyDefinitionId="cmis:baseTypeId" queryName="cmis:baseTypeId">
<cmis:value>cmis:document</cmis:value>
</cmis:propertyId>
<cmis:propertyString displayName="cmis:contentStreamFileName" localName="cmis:contentStreamFileName" propertyDefinitionId="cmis:contentStreamFileName" queryName="cmis:contentStreamFileName">
<cmis:value>test.txt</cmis:value>
</cmis:propertyString>
<cmis:propertyDateTime displayName="cmis:lastModificationDate" localName="cmis:lastModificationDate" propertyDefinitionId="cmis:lastModificationDate" queryName="cmis:lastModificationDate">
<cmis:value>2010-09-09T18:06:31.987Z</cmis:value>
</cmis:propertyDateTime>
</cmis:properties>
<cmis:acl/>
<cmis:exactACL>false</cmis:exactACL>
<cmis:policyIds/>
<cmis:rendition/>
</cmisra:object>
</entry>
Then, get the test.txt file content via CMIS by using the file service and id of the file test.txt from childs.xml:
curl -o test.txt -u root:gtn http://localhost:8080/rest/private/cmisatom/Managed%20Sites/file/f708e208c0a80003554babb97bd934ba
Get results in the test.txt file in the local folder. In this way, you will get file stored in the Sites Explorer to folder /acme/documents/test.txt via eXo CMIS by symlink path /acme/categories/acme/News/test.txt. As file's actual content referenced by id in CMIS, the path has no matter for content read or change.
Upload the modified local file using the command with id of the file stored in WCM (it is jcr:uuid of the file in JCR Workspace). Note that you should run this command from the folder where the local file is stored.
To update any file via CMIS, use the file service and the PUT request. Use the same file as in the previous use case (/acme/documents/test.txt, id:f708e208c0a80003554babb97bd934ba).
curl -T test.txt -X PUT -H "Content-Type:text/plain; charset=UTF-8" -u root:gtn http://localhost:8080/rest/private/cmisatom/Managed%20Sites/file/f708e208c0a80003554babb97bd934ba
Go to the Sites Explorer to see changes applied from the local file in /acme/documents/test.txt.
CMIS provides a type-based query service for discovering objects that match specified criteria by defining a read-only projection of the CMIS data model into a Relational View.
CMIS query languages are based on a subset of the SQL-92 grammar. CMIS-specific language extensions to SQL-92 are called out explicitly. The basic structure of a CMIS query is a SQL statement that MUST include the following clauses:
SELECT (virtual columns): This clause identifies the set of virtual columns that will be included in the query results for each row.
FROM (Virtual Table Names): This clause identifies which Virtual Table(s) the query will run against.
Additionally, a CMIS query MAY include the following clauses:
WHERE (conditions): This clause identifies the constraints that rows MUST satisfy to be considered a result for the query.
ORDER BY (sort specification): This clause identifies the order in which the result rows MUST be sorted in the result row set.
Each CMIS ObjectType definition has the following query attributes:
Name | Description |
---|---|
query name (String) | Used for query operations on object types. In our SQL statement examples, all objecttypes is a queryName. For example, the given queryName matches the specific type of document. For example, in query like "SELECT * FROM cmis:document" ,"cmis:document" is queryName preconfigured in Document object type definition. |
queryable (Boolean) | Indicate whether or not this object type is queryable. A non-queryable object type is not visible through the relational view that is used for query, and can not appear in the FROM clause of a query statement. |
fulltextIndexed (Boolean) | Indicate whether objects of this type are full-text indexed for querying via the CONTAINS() query predicate. |
includedInSupertypeQuery (Boolean) | Indicate whether this type and its subtypes appear in a query of this type's ancestor types. For example, if Invoice is a sub-type of Document, and its value is TRUE for a query on Document type, the matched instances of Invoice will be returned. If this attribute is FALSE, no instances (including matched ones) of Invoice will be returned. |
Property definition also contains queryName and queryable attributes with the same usage.
This section gives query examples for each specific case, including:
Query: Select all cmis:document.
SELECT * FROM cmis:document
Query result:
All documents from the Apollo program.
Query: Select all documents where apollo:propertyBooster is 'Saturn V' and apollo:propertyCommander is Frank F. Borman, II or James A. Lovell, Jr.
Initial data:
document1: apollo:propertyBooster - Saturn 1B, apollo:propertyCommander - Walter M. Schirra
document2: apollo:propertyBooster - Saturn V, apollo:propertyCommander - Frank F. Borman, II
document3: apollo:propertyBooster - Saturn V, apollo:propertyCommander - James A. Lovell, Jr.
SELECT * FROM cmis:document WHERE apollo:propertyBooster = 'Saturn V' AND (apollo:propertyCommander = 'Frank F. Borman, II' OR apollo:propertyCommander = 'James A. Lovell, Jr.')
Query result:
document2 and document3.
Query: Select all documents that contains the "here" word.
Initial data:
document1: content - "There must be test word"
document2: content - "Test word is not here"
SELECT * FROM cmis:document WHERE CONTAINS('here')
Query result:
document2.
Query: Select all documents that contains "There must" phrase and do not contain the "check-word" term.
Initial data:
document1: content - "There must be test word."
document2: content - "Test word is not here. Another check-word."
document3: content - "There must be check-word."
SELECT * FROM cmis:document WHERE CONTAINS("There must" - "check-word")
Query result:
document1.
Query: Select all documents where cmis:lastModificationDate is more than 2007-01-01.
Initial data:
document1: cmis:lastModificationDate - 2006-08-08
document2: cmis:lastModificationDate - 2009-08-08
SELECT * FROM cmis:document WHERE (cmis:lastModificationDate >= TIMESTAMP '2007-01-01T00:00:00.000Z')"
Query result:
document2.
Query: Select all documents where property apollo:someProperty equals to false.
Initial data:
document1: apollo:someProperty - true
document2: apollo:someProperty - false
SELECT * FROM cmis:document WHERE (apollo:someProperty = FALSE)
Query result:
document2.
Query: Select all documents where apollo:propertyCommander is in set {'Virgil I. Grissom', 'Frank F. Borman, II', 'James A. Lovell, Jr.'}.
Initial data:
document1: apollo:propertyCommander - Walter M. Schirra
document2: apollo:propertyCommander - Frank F. Borman, II
document3: apollo:propertyCommander - James A. Lovell, Jr.
document4: apollo:propertyCommander - Eugene A. Cernan
SELECT * FROM cmis:document WHERE apollo:propertyCommander IN ('Virgil I. Grissom', 'Frank F. Borman, II', 'James A. Lovell, Jr.')
Query result:
document2, document3.
Query: Select all documents where apollo:propertyCommander property is not in set {'Walter M. Schirra', 'James A. Lovell, Jr.'}.
Initial data:
document1: apollo:propertyCommander - Walter M. Schirra
document2: apollo:propertyCommander - Frank F. Borman, II
document3: apollo:propertyCommander - James A. Lovell, Jr.
document4: apollo:propertyCommander - Eugene A. Cerna
SELECT * FROM cmis:document WHERE apollo:PropertyCommander NOT IN ('Walter M. Schirra', 'James A. Lovell, Jr.')
Query result:
document2, document4.
Query: Select all documents where apollo:propertyCommander_ property is not in set {'James A. Lovell, Jr.'}.
Initial data:
document1: apollo:propertyCommander - Walter M. Schirra
document2: apollo:propertyCommander - Frank F. Borman, II
document3: apollo:propertyCommander - James A. Lovell, Jr.
document4: apollo:propertyCommander - Eugene A. Cerna
SELECT * FROM cmis:document WHERE NOT (apollo:propertyCommander NOT IN ('James A. Lovell, Jr.'))
Query result:
document3.
Query: Select all folders that are in folder1.
Initial data:
folder1: id - 123456789
document1: Title - node1
folder3:
folder4:
folder2:
document2: Title - node2
SELECT * FROM cmis:folder WHERE IN_FOLDER('123456789')
Query result:
folder3.
Query: Select all documents that are in folder1.
Initial data:
folder1: id - 123456789
document1: Title - node1
folder2:
document2: Title - node2
SELECT * FROM cmis:document WHERE IN_FOLDER('123456789')
Query result:
document1.
Initial data:
testRoot: id - 123456789
document1: Title - node1 typeID - cmis:article-sports
document2: Title - node2 typeID - cmis:article-animals
SELECT * FROM cmis:article WHERE IN_FOLDER('123456789')
Query result:
document1, document2.
Query: Select all documents that are in the tree of folder1.
Initial data:
folder1: id - 123456789
document1
folder2:
document2
SELECT * FROM cmis:document WHERE IN_TREE('123456789')
Query result:
document1, document2.
Query: Select all documents where apollo:propertyCommander begins with "James".
Initial data:
document1: apollo:propertyCommander - Walter M. Schirra
document2: apollo:propertyCommander - Frank F. James, II
document3: apollo:propertyCommander - James A. Lovell, Jr.
document4: apollo:propertyCommander - Eugene A. James
SELECT * FROM cmis:document AS doc WHERE apollo:PropertyCommander LIKE 'James%'
Query result:
document3.
Query: Select all documents where apollo:someProperty like 'ad%min%'.
Initial data:
document1: Title - node1, apollo:someProperty - ad%min master
document2: Title - node2, apollo:someProperty - admin operator
document3: Title - node2, apollo:someProperty - radmin
SELECT * FROM cmis:document AS doc WHERE apollo:someProperty LIKE 'ad%min%'
Query result:
document1.
Query: Select all documents that do not contain the "world" word.
Initial data:
document1: Title - node1, content - hello world
document2: Title - node2, content - hello
SELECT * FROM cmis:document WHERE NOT CONTAINS('world')
Query result:
document2.
Query: Select all documents that has apollo:propertyCommander property is NOT NULL.
Initial data:
document1: apollo:propertyCommander - Walter M. Schirra
document2: apollo:propertyCommander -
document3: apollo:propertyCommander - James A. Lovell, Jr.
document4: apollo:propertyCommander -
SELECT * FROM cmis:document WHERE apollo:propertyCommander is NOT NULL
Query result:
document1, document3.
Query: Select all documents in default order (by document name).
Initial data:
document1: Title - Apollo 7
document2: Title - Apollo 8
document3: Title - Apollo 13
document4: Title - Apollo 17
SELECT cmis:lastModifiedBy, cmis:objectId, cmis:lastModificationDate FROM cmis:document
Query result:
document3, document4, document1, document2.
Query: Order by apollo:propertyCommander property value (in ascending order).
Initial data:
document1: apollo:propertyCommander - Walter M. Schirra
document2: apollo:propertyCommander - Frank F. Borman, II
document3: apollo:propertyCommander - James A. Lovell, Jr.
document4: apollo:propertyCommander - Eugene A. Cerna
SELECT cmis:lastModifiedBy, cmis:objectId, cmis:lastModificationDate FROM cmis:document ORDER BY apollo:propertyCommander
Query result:
document4, document2, document3, document1.
Query: Order by apollo:propertyCommander property value (in descending order).
Initial data:
document1: apollo:propertyCommander - Walter M. Schirra
document2: apollo:propertyCommander - Frank F. James, II
document3: apollo:propertyCommander - James A. Lovell, Jr.
document4: apollo:propertyCommander - Eugene A. James
SELECT cmis:lastModifiedBy, cmis:objectId, cmis:lastModificationDate FROM cmis:document ORDER BY cmis:propertyCommander DESC
Query result:
document1, document3, document2, document4.
Query: Select all documents which contains word "moon" ordered by score.
Initial data:
document1: content - "Earth-orbital mission, the first manned launch"
document2: content - "from another celestial body - Earth's Moon"
document3: content - "NASA intended to land on the Moon, but a mid-mission technical"
document4: content - "It was the first night launch of a U.S. human"
SELECT cmis:lastModifiedBy, cmis:objectId, cmis:lastModificationDate FROM cmis:document WHERE CONTAINS('moon') ORDER BY SCORE()
Query result:
document2, document3.
Query: Select all documents which have apollo:propertyBooster peroperty that does not equal to 3.
Initial data:
document1: Title - node1, apollo:propertyBooster - 3
document2: Title - node2, apollo:propertyBooster - 15
SELECT * FROM cmis:document WHERE apollo:propertyBooster <> 3
Query result:
document2.
Query: Select all documents property apollo:someProperty that does not equals to "test word second".
Initial data:
document1: apollo:someProperty - "test word first"
document2: apollo:someProperty - "test word second"
SELECT * FROM cmis:document WHERE apollo:someProperty <> 'test word second'
Query result:
document1.
Query: Select all documents wihch have apollo:propertyBooster property which is more than 5.
Initial data:
document1: apollo:propertyBooster - 3
document2: apollo:propertyBooster - 15
SELECT * FROM cmis:document WHERE apollo:propertyBooster > 5
Query result:
document2.
The CMIS specification prescribes:
Domain model
Services
The CMIS Domain Model defines a repository as a container and an entry point to the objects that is quite simple and non-restrictive. The followings are some of the common entities of the domain model.
Repository is a container of objects with a set of "capabilities" which may be different depending on the implementation.
Object is the entity managed by a CMIS repository.
Object Type is a classification related to an object. It specifies a fixed and non-hierarchical set of properties ("schema") that all objects of that type have.
Document Object is an elementary information entity.
Folder Object is a collection of fileable objects.
Relationship Object is used to describe a dependent object semantically.
Policy Object represents an administrative policy applied to an object.
Access Object defines permissions.
Versioning is to support versioning for Document objects.
Query is type-based in a simplified SQL SELECT statement.
Change Log is a mechanism which enables applications to discover changes to the objects stored.
CMIS specifies a query language based on the SQL-92 standard, plus the extensions, in conjunction with the model mapping defined by the CMIS's relational view.
All objects are classified by an Object Type which declares that all objects of the given type have some sets of properties in common. Each property consists of a set of attributes, such as the TypeID, the property ID, its display name, its query name, and more. There are only four base types, including Document, Folder, Relationship, and Policy. Also, you can extend those basic types by modifying a set of their properties.
Document Object and Folder Object are self-explanatory. Document Object has properties to hold document metadata, such as the document author, modification date and custom properties. It can also contain a content stream whether it is required, and renditions, such as a thumbnail view of document. Folder is used to contain objects. Apart from the default hierarchical structure, CMIS can optionally store objects in multiple folders or in no folders at all (so-called multifiling and unfiling capabilities). Relationship Object denotes the connection between two objects (target and source). An object can have multiple relationships with other objects. Policy Object is a way to define administrative policies in managing objects. For example, you can use a CMIS policy to define which documents are subject to retention policies.
CMIS provides a set of services to access and manage the content or repository. These services include:
Name | Description |
---|---|
Repository Services | Discover information about the repository and the object types defined for the repository. |
Navigation Services | Traverse the folder hierarchy in a CMIS repository, and to locate documents which are checked out. |
Object Services | Execute ID-based CRUD functions (Create, Retrieve, Update, Delete) on objects in a repository. |
Multi-filing Services (optional) | Put an object in more than one folder (multi-filing), or outside the folder hierarchy (unfiling). |
Discovery Services | Search for queryable objects in a repository. |
Versioning Services | Check out, navigate to documents, or update a Document Version Series (checkOut, cancelCheckOut, getPropertiesOfLatestVersion, getAllVersions, deleteAllVersions). |
Relationship Services (optional) | Retrieve an object for its relationships. |
Policy Services (optional) | Apply, remove, or query for policies. |
ACL Services | Return and manage the Access Control List (ACL) of an object. ACL Services are not supported by all repositories. |
Some repositories might not implement certain optional capabilities, but they are still considered as CMIS-compliant. Each service has binding which defines the way messages will be serialized and wired. Binding is based on HTTP and uses the Atom Publishing Protocol.
JCRs are listed below for the informational purpose only. For example, if the customer application needs to use the same third-parties used by eXo CMIS but with another version. All files are delivered in eXo Platform 3.5 distribution.
eXo CMIS consists of JAR files below:
xCMIS project files (for xCMIS 1.2.x)
xcmis-renditions-X.X.X.jar
xcmis-restatom-X.X.X.jar
xcmis-search-model-X.X.X.jar
xcmis-search-parser-cmis-X.X.X.jar
xcmis-search-service-X.X.X.jar
xcmis-spi-X.X.X.jar
eXo WCM Storage Provider for xCMIS SPI (uses the same version as the WCM/ECMS system)
exo-ecms-ext-xcmis-sp-Y.Y.Y.jar
Third-party dependencies (for xCMIS 1.2.x)
abdera-client-0.4.0-incubating.jar
abdera-core-0.4.0-incubating.jar
abdera-i18n-0.4.0-incubating.jar
abdera-parser-0.4.0-incubating.jar
abdera-server-0.4.0-incubating.jar
antlr-runtime-3.1.3.jar
axiom-api-1.2.5.jar
axiom-impl-1.2.5.jar
jaxen-1.1.1.jar
lucene-regex-2.4.1.jar
This chapter describes configurations used in Content. It consists of the following main sections:
This section describes services which provide low-level functionality for UI components.
The ActionServiceContainer component is used to manage actions (adding, removing, or executing actions, and more) in the system. The configuration of this component is found in /core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/core-services-configuration.xml.
<component>
<key>org.exoplatform.services.cms.actions.ActionServiceContainer</key>
<type>org.exoplatform.services.cms.actions.impl.ActionServiceContainerImpl</type>
<init-params>
<value-param>
<name>workspace</name>
<value>system</value>
</value-param>
<value-param>
<name>repository</name>
<value>repository</value>
</value-param>
</init-params>
</component>
Details:
Value-param:
Name | Type | Value | Description |
---|---|---|---|
workspace | string |
system
| The workspace name. |
repository | string |
repository
| The repository name. |
The ApplicationTemplateManagerService component is used to manage dynamic Groovy templates for WCM-based products. The configuration of this component is found in /core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/core-services-configuration.xml.
<component>
<key>org.exoplatform.services.cms.views.ApplicationTemplateManagerService</key>
<type>org.exoplatform.services.cms.views.impl.ApplicationTemplateManagerServiceImpl</type>
<init-params>
<properties-param>
<name>storedLocations</name>
<property name="repository" value="system"/>
</properties-param>
</init-params>
</component>
Details:
Properties-param:
Name | Property name | Type | Value | Description |
---|---|---|---|---|
storedLocations | repository | string | system | The repository name. |
The FragmentCacheService component is used to cache the response fragments which are sent to end-users.
The configuration of this component is found in core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/wcm-configuration.xml.
<component>
<key>org.exoplatform.services.portletcache.FragmentCacheService</key>
<type>org.exoplatform.services.portletcache.FragmentCacheService</type>
<init-params>
<value-param>
<name>cleanup-cache</name>
<description>The cleanup cache period in seconds</description>
<value>300</value>
</value-param>
</init-params>
</component>
Details
Value-param:
Name | Type | Value | Description |
---|---|---|---|
cleanup-cache |
integer | 300 | The time period over which cache items are expired. |
The JodConverterServices component is used to convert documents into different office formats. The configuration of this component is found in /core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/core-services-configuration.xml.
<component>
<key>org.exoplatform.services.cms.jodconverter.JodConverterService</key>
<type>org.exoplatform.services.cms.jodconverter.impl.JodConverterServiceImpl</type>
<init-params>
<value-param>
<name>port</name>
<value>${jodconverter.portNumbers}</value>
</value-param>
<value-param>
<name>officeHome</name>
<value>${jodconverter.officeHome}</value>
</value-param>
<value-param>
<name>taskQueueTimeout</name>
<value>${jodconverter.taskQueueTimeout}</value>
</value-param>
<value-param>
<name>taskExecutionTimeout</name>
<value>${jodconverter.taskExecutionTimeout}</value>
</value-param>
<value-param>
<name>maxTasksPerProcess</name>
<value>${jodconverter.maxTasksPerProcess}</value>
</value-param>
<value-param>
<name>retryTimeout</name>
<value>${jodconverter.retryTimeout}</value>
</value-param>
</init-params>
</component>
Details:
Value-param:
Name | Type | Value | Description |
---|---|---|---|
port | Integer | ${jodconverter.portNumbers} | The number of ports to connect with the office server. |
officeHome | String
| ${jodconverter.officeHome} | The absolute path to the office home on the current local computer. |
taskQueueTimeout | Long
| ${jodconverter.taskExecutionTimeout} | The maximum living time of a task in the conversation queue. |
taskExecutionTimeout |
Long | ${jodconverter.taskExecutionTimeout} | The maximum time to process a task. |
maxTasksPerProcess |
Integer | ${jodconverter.maxTasksPerProcess} | The maximum number of tasks are processed. |
retryTimeout |
Long | ${jodconverter.retryTimeout} | The interval time to try to restart the office services in case they unexpectedly stop. |
The LiveLinkManagerService component is used to check broken links, update links when the links are edited and extract links to return a list of all links. The configuration of this component is found in /core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/wcm-configuration.xml.
<component>
<key>org.exoplatform.services.wcm.link.LiveLinkManagerService</key>
<type>org.exoplatform.services.wcm.link.LiveLinkManagerServiceImpl</type>
<init-params>
<properties-param>
<name>server.config</name>
<description>server.address</description>
<property name="scheme" value="http"/>
<property name="hostName" value="localhost"/>
<property name="port" value="8080"/>
</properties-param>
</init-params>
</component>
Details:
Properties-param | Property name | Type | Value | Description |
---|---|---|---|---|
server.config |
|
|
| All the property names are used together to configure the server. Here is an example about the server configuration: http//:localhost:8080. |
The LockService component is used to manage all locked nodes and allows unlocking the locked nodes in the system. It is also used to assign the Lock right to a user or a user group or a membership. The configuration of this component is found in /core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/core-services-configuration.xml.
<component>
<key>org.exoplatform.services.cms.lock.LockService</key>
<type>org.exoplatform.services.cms.lock.impl.LockServiceImpl</type>
</component>
The NewsletterInitializationService component is used to initiate some data for the newsletter portlet. The configuration of this component is found in packaging/ecmdemo/webapp/src/main/webapp/WEB-INF/conf/sample-portal/wcm/newsletter-configuration.xml.
The Newsletter portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
<component>
<type>org.exoplatform.services.wcm.newsletter.NewsletterInitializationService</type>
<init-params>
<values-param>
<name>portalNames</name>
<value>classic</value>
<value>acme</value>
</values-param>
<values-param>
<name>administrators</name>
<value>root</value>
<value>john</value>
</values-param>
<object-param>
<name>marketing</name>
<description>marketing</description>
<object type="org.exoplatform.services.wcm.newsletter.NewsletterCategoryConfig">
<field name="name">
<string>marketing</string>
</field>
<field name="title">
<string>Marketing</string>
</field>
<field name="description">
<string>You want to know where we are, where we go ?</string>
</field>
<field name="moderator">
<string>*:/platform/web-contributors</string>
</field>
</object>
</object-param>
<object-param>
<name>general</name>
<description>general</description>
<object type="org.exoplatform.services.wcm.newsletter.NewsletterCategoryConfig">
<field name="name">
<string>general</string>
</field>
<field name="title">
<string>General</string>
</field>
<field name="description">
<string>General information about us</string>
</field>
<field name="moderator">
<string>*:/platform/web-contributors</string>
</field>
</object>
</object-param>
<object-param>
<name>subscription2</name>
<description>subscription2</description>
<object type="org.exoplatform.services.wcm.newsletter.NewsletterSubscriptionConfig">
<field name="name">
<string>results</string>
</field>
<field name="title">
<string>Results</string>
</field>
<field name="description">
<string>Monthly newsletter about our results and forecasts</string>
</field>
<field name="categoryName">
<string>general</string>
</field>
<field name="redactor">
<string>*:/platform/web-contributors</string>
</field>
</object>
</object-param>
<object-param>
<name>subscription1</name>
<description>subscription1</description>
<object type="org.exoplatform.services.wcm.newsletter.NewsletterSubscriptionConfig">
<field name="name">
<string>checklist</string>
</field>
<field name="title">
<string>Check-List</string>
</field>
<field name="description">
<string>Weekly newsletter with general topics</string>
</field>
<field name="categoryName">
<string>general</string>
</field>
<field name="redactor">
<string>*:/platform/web-contributors</string>
</field>
</object>
</object-param>
<object-param>
<name>subscription3</name>
<description>subscription3</description>
<object type="org.exoplatform.services.wcm.newsletter.NewsletterSubscriptionConfig">
<field name="name">
<string>market</string>
</field>
<field name="title">
<string>The market</string>
</field>
<field name="description">
<string>What's on the market today ?</string>
</field>
<field name="categoryName">
<string>marketing</string>
</field>
<field name="redactor">
<string>*:/platform/web-contributors</string>
</field>
</object>
</object-param>
<object-param>
<name>user1@gmail.com</name>
<description>user1@gmail.com</description>
<object type="org.exoplatform.services.wcm.newsletter.config.NewsletterUserConfig">
<field name="mail">
<string>user1@gmail.com</string>
</field>
</object>
</object-param>
<object-param>
<name>user2@gmail.com</name>
<description>user2@gmail.com</description>
<object type="org.exoplatform.services.wcm.newsletter.config.NewsletterUserConfig">
<field name="mail">
<string>user2@gmail.com</string>
</field>
</object>
</object-param>
</init-params>
</component>
Details:
Value-param
Name | Type | Value | Description |
---|---|---|---|
portalNames | string | classic, acme | The portal names. |
administrators | string | root | The administrator who manages the newsletter portlet. |
Object-param:
object type: org.exoplatform.services.wcm.newsletter.NewsletterCategoryConfig
Field | Type | Description |
---|---|---|
name |
string
| The name of categories or subscriptions. |
title |
string | The title of categories or subscriptions. |
description |
string | The description of categories or subscriptions. |
moderator |
string
| The users or groups that can moderate the newsletter portlet. |
categoryName |
string
| The categories name. |
redactor |
string
| The users or groups that are newsletter redactor. |
string | The email that user uses to subscribe. |
The NewsletterManagerService component is used to send newsletters to subscribers. The configuration of this component is found in core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/ext-newsletter-configuration.xml.
The Newsletter Manager portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
<component>
<type>org.exoplatform.services.wcm.newsletter.NewsletterManagerService</type>
<init-params>
<value-param>
<name>repository</name>
<value>repository</value>
</value-param>
<value-param>
<name>workspace</name>
<value>collaboration</value>
</value-param>
</init-params>
</component>
Details:
Value-param:
Name | Type | Value | Description |
---|---|---|---|
repository |
string
|
repository
| The repository name. |
workspace |
string
|
collaboration
| The workspace name. |
The SiteSearchService component is used in the Search portlet that allows users to find all information matching with your given keyword.
It is configured in the core/core-configuration/src/main/webapp/WEB-INF/conf/configuration.xml file as follows:
<import>war:/conf/wcm-core/core-search-configuration.xml</import>
The component configuration maps the SiteSearchService component with its own implementation: SiteSearchServiceImpl.
<component>
<key>org.exoplatform.services.wcm.search.SiteSearchService</key>
<type>org.exoplatform.services.wcm.search.SiteSearchServiceImpl</type>
<component-plugins>
...
</component-plugins>
<init-params>
<value-param>
<name>isEnabledFuzzySearch</name>
<value>true</value>
</value-param>
<value-param>
<name>fuzzySearchIndex</name>
<value/>
</value-param>
</init-params>
</component>
Detail:
Value-param:
Name | Type | Value | Description |
---|---|---|---|
isEnabledFuzzySearch | boolean | true
| Allow administrators to enable/disable the fuzzy search mechanism. |
fuzzySearchIndex |
N/A | N/A | Allow the approximate level between the input keyword and the found key results. In case of the invalid configuration, the default value is set to 0.8. |
To have more information about the fuzzy search, please refer to Fuzzy Search.
The SEOService component is used to help users manage SEO data of a page or a content, so their websites can achieve higher rankings on search engines. The configuration of this component is found in /packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/wcm-extension/wcm/seo-configuration.xml.
<component>
<key>org.exoplatform.services.seo.SEOService</key>
<type>org.exoplatform.services.seo.impl.SEOServiceImpl</type>
<init-params>
<object-param>
<name>seo.config</name>
<object type="org.exoplatform.services.seo.SEOConfig">
<field name="robotsindex">
<collection type="java.util.ArrayList">
<value>
<string>INDEX</string>
</value>
<value>
<string>NOINDEX</string>
</value>
</collection>
</field>
<field name="robotsfollow">
<collection type="java.util.ArrayList">
<value>
<string>FOLLOW</string>
</value>
<value>
<string>NOFOLLOW</string>
</value>
</collection>
</field>
<field name="frequency">
<collection type="java.util.ArrayList">
<value>
<string>Always</string>
</value>
<value>
<string>Hourly</string>
</value>
<value>
<string>Daily</string>
</value>
<value>
<string>Weekly</string>
</value>
<value>
<string>Monthly</string>
</value>
<value>
<string>Yearly</string>
</value>
<value>
<string>Never</string>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component>
Details:
Object-param:
Object type: org.exoplatform.services.seo.SEOConfig
Field | Type | Value | Description |
---|---|---|---|
robotsindex |
ArrayList
|
| Allow search engines to index a particular page or not. |
robotsfollow |
ArrayList
|
| Allow search engines to follow links from a particular page to find other pages or not. |
frequency |
ArrayList
|
| Define how often a particular page is updated. |
The QueryService component is used to manage many queries, including adding, removing or executing a query. The configuration of this component is found in /core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/core-services-configuration.xml.
<component>
<key>org.exoplatform.services.cms.queries.QueryService</key>
<type>org.exoplatform.services.cms.queries.impl.QueryServiceImpl</type>
<init-params>
<value-param>
<name>workspace</name>
<value>system</value>
</value-param>
<value-param>
<name>relativePath</name>
<value>Private/Queries</value>
</value-param>
<value-param>
<name>group</name>
<value>*:/admin</value>
</value-param>
</init-params>
</component>
Details:
Value-param:
Name | Type | Value | Description |
---|---|---|---|
workspace |
string
|
system
| The workspace name. |
relativePath |
Private/Queries
|
Private/Queries
| The path to the query location. |
group |
string
| *:/admin | The group is allowed to access the query folder. |
The TaxonomyService component is used to sort documents to ease searches when browsing documents online. It provides a multi-dimensional set of paths to find a document. In many cases, you can get your content by using different category paths. Therefore, after creating a document somewhere in the repository, it is possible to categorize it by adding several taxonomy references. By browsing the taxonomy tree, it will be possible to find the referencing article and display them as if they were children of the taxonomy nodes. Taxonomies are stored in the JCR itself and the JCR Reference functionality is used to provide that advanced WCM feature. The tree of taxonomies can be managed simply, such as copying/cutting/pasting nodes, or adding and removing taxonomies from the tree. Once a taxonomy has been added, any user who has access to the "Manage Categories" icon from his/her view can then browse the taxonomy tree and refer one of its nodes to the created documents.
<component>
<key>org.exoplatform.services.cms.taxonomy.TaxonomyService</key>
<type>org.exoplatform.services.cms.taxonomy.impl.TaxonomyServiceImpl</type>
<init-params>
<object-param>
<name>defaultPermission.configuration</name>
<object type="org.exoplatform.services.cms.taxonomy.impl.TaxonomyTreeDefaultUserPermission">
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.taxonomy.impl.TaxonomyTreeDefaultUserPermission$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.taxonomy.impl.TaxonomyTreeDefaultUserPermission$Permission">
<field name="identity">
<string>*:/platform/users</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>false</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component>
Details:
Object type: org.exoplatform.services.cms.taxonomy.impl.TaxonomyTreeDefaultUserPermission
Field | Type | Value | Description |
---|---|---|---|
permissions | ArrayList
| {java.util.ArrayList} | The list of the default user permissions to access the taxonomy tree. |
Object type: org.exoplatform.services.cms.taxonomy.impl.TaxonomyTreeDefaultUserPermission$Permission
Field | Type | Description |
---|---|---|
identity | string | The name of user, group or membership. |
read |
boolean | The permission to read the taxonomy tree. |
addNode | boolean
| The permission to add a node to the taxonomy tree. |
setProperty | boolean | The permission to set properties for a node in the taxonomy tree. |
remove | boolean | The permission to remove a node from the taxonomy tree. |
The ThumbnailService component is used to resize all the images into different sizes. Besides the default sizes, it also allows users to customize the images into the desired sizes. The configuration of this component is found in /core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/core-services-configuration.xml.
<component>
<key>org.exoplatform.services.cms.thumbnail.ThumbnailService</key>
<type>org.exoplatform.services.cms.thumbnail.impl.ThumbnailServiceImpl</type>
<init-params>
<value-param>
<name>smallSize</name>
<value>32x32</value>
</value-param>
<value-param>
<name>mediumSize</name>
<value>64x64</value>
</value-param>
<value-param>
<name>largeSize</name>
<value>300x300</value>
</value-param>
<value-param>
<name>enable</name>
<value>false</value>
</value-param>
<value-param>
<name>mimetypes</name>
<value>image/jpeg;image/png;image/gif;image/bmp</value>
</value-param>
</init-params>
</component>
Details:
Value-param:
Name | Type | Value | Description |
---|---|---|---|
smallSize |
integer x integer
|
32x32
| The small thumbnail size. |
mediumSize |
integer x integer
|
64x64
| The medium thumbnail size. |
largeSize |
integer x integer
|
300x300
| The large thumbnail size. |
enable |
boolean
|
false
| Specify if the thumbnail is displayed or not. |
mimetypes |
Images formats
|
image/jpeg;image/png;image/gif;image/bmp
| The image formats are supported. |
The TimelineService component allows documents to be displayed by days, months and years. The configuration of this component is found in /core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/core-services-configuration.xml.
<component>
<key>org.exoplatform.services.cms.timeline.TimelineService</key>
<type>org.exoplatform.services.cms.timeline.impl.TimelineServiceImpl</type>
<init-params>
<value-param>
<name>itemPerTimeline</name>
<value>5</value>
</value-param>
</init-params>
</component>
Details:
Value-param
Name | Type | Value | Description |
---|---|---|---|
itemPerTimeline |
integer
|
5
| The number of documents are displayed. |
The WatchDocumentService component allows users to watch/unwatch a document. If they are watching the document, they will receive a notification mail when there are any changes on the document. The configuration of this component is found in /core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/core-services-configuration.xml.
<component>
<key>org.exoplatform.services.cms.watch.WatchDocumentService</key>
<type>org.exoplatform.services.cms.watch.impl.WatchDocumentServiceImpl</type>
<init-params>
<object-param>
<name>messageConfig</name>
<description>description</description>
<object type="org.exoplatform.services.cms.watch.impl.MessageConfig">
<field name="sender">
<string>support@exoplatform.com</string>
</field>
<field name="subject">
<string>Your watching document is changed</string>
</field>
<field name="content">
<string>The document that you are watching is changed.
Please go to ecm to see this change
</string>
</field>
</object>
</object-param>
</init-params>
</component>
Details:
object-param:
Object type: org.exoplatform.services.cms.watch.impl.MessageConfig
Field | Type | Value | Description |
---|---|---|---|
sender | string | support@exoplatform.com | The sender who sends the notification mail. |
subject | string | Your watching document is changed. | The subject of the notification mail. |
content | string | The document that you are watching is changed. Please go to ecm to see this change. | The content of the notification mail. |
The WCMService component allows setting expiration cache of portlets and checking given portals if they are shared portals or not. It also gets reference contents basing on item identifiers. The configuration of this component is found in /core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/core-services-configuration.xml.
<component>
<key>org.exoplatform.services.wcm.core.WCMService</key>
<type>org.exoplatform.services.wcm.core.impl.WCMServiceImpl</type>
<init-params>
<properties-param>
<name>server.config</name>
<description>server.config</description>
<property name="expirationCache" value="30"/>
</properties-param>
</init-params>
</component>
Details:
Properties-param | Property name | Type | Value | Description |
---|---|---|---|---|
server.config | expirationCache |
integer
|
30
| The period in which the cache is clear in second. By default, the cache is cleared every 30 seconds. |
This section describes the main component plugins used in Content. Each part supply an example configuration with the explanation about ini-params so you can know how to use these plugins.
This plugin is used to manage the publication lifecycle of web contents and DMS document on a portal page with more states and versions. The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/content-extended/authoring/configuration.xml.
Sample configuration:
<component-plugin>
<name>Authoring publication</name>
<set-method>addPublicationPlugin</set-method>
<type>org.exoplatform.services.wcm.extensions.publication.lifecycle.authoring.AuthoringPublicationPlugin
</type>
<description>This publication lifecycle publish a web content or DMS document to a portal page with more
states and version.
</description>
</component-plugin>
In which:
Name: Authoring publication
Set-method: addPublicationPlugin
Type: org.exoplatform.services.wcm.extensions.publication.lifecycle.authoring.AuthoringPublicationPlugin
This is an abstract class and the parent of ScriptActionPlugin and BPActionPlugin . You can create a link from this plugin to its children.
This plugin is used to define the business process action in Workflow.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.actions.ActionServiceContainer</target-component>
The configuration is applied mainly in packaging/workflow/webapp/src/main/webapp/WEB-INF/workflow-extension/workflow/workflow-system-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.actions.ActionServiceContainer</target-component>
<component-plugin>
<name>exo:businessProcessAction</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.plugin.actions.impl.BPActionPlugin</type>
<priority>112</priority>
<init-params>
<object-param>
<name>predefined.actions</name>
<description>description</description>
<object type="org.exoplatform.services.cms.actions.impl.ActionConfig">
<field name="repository">
<string>repository</string>
</field>
<field name="workspace">
<string>collaboration</string>
</field>
<field name="actions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.actions.impl.ActionConfig$Action">
<field name="type">
<string>exo:publishingProcess</string>
</field>
<field name="name">
<string>content publishing</string>
</field>
<field name="description">
<string>content publishing workflow</string>
</field>
<field name="srcWorkspace">
<string>collaboration</string>
</field>
<field name="srcPath">
<string>/Documents/Validation Requests</string>
</field>
<field name="isDeep">
<boolean>true</boolean>
</field>
<field name="lifecyclePhase">
<collection type="java.util.ArrayList">
<value>
<string>node_added</string>
</value>
</collection>
</field>
<field name="roles">
<string>*:/platform/users</string>
</field>
<field name="variables">
<string>
exo:supervisor=*:/organization/management/executive-board;exo:validator=*:/platform/administrators
</string>
</field>
<field name="mixins">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.actions.impl.ActionConfig$Mixin">
<field name="name">
<string>exo:publishLocation</string>
</field>
<field name="properties">
<string>
exo:publishWorkspace=collaboration;exo:publishPath=/Documents/Live;exo:validator=*:/platform/administrators
</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.actions.impl.ActionConfig$Mixin">
<field name="name">
<string>exo:pendingLocation</string>
</field>
<field name="properties">
<string>
exo:pendingWorkspace=collaboration;exo:pendingPath=/Documents/Pending
</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.actions.impl.ActionConfig$Mixin">
<field name="name">
<string>exo:backupLocation</string>
</field>
<field name="properties">
<string>exo:backupWorkspace=backup;exo:backupPath=/Expired
Documents
</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.actions.impl.ActionConfig$Mixin">
<field name="name">
<string>exo:trashLocation</string>
</field>
<field name="properties">
<string>
exo:trashWorkspace=collaboration;exo:trashPath=/Documents/Trash
</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.actions.impl.ActionConfig$Mixin">
<field name="name">
<string>mix:affectedNodeTypes</string>
</field>
<field name="properties">
<string>
exo:affectedNodeTypeNames=exo:article,exo:podcast,exo:sample,kfx:document,nt:file,rma:filePlan
</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: exo:businessProcessAction
Set-method: addPlugin
Type: org.exoplatform.services.plugin.actions.impl.BPActionPlugin
Object type: org.exoplatform.services.cms.actions.impl.ActionConfig
Field | Type | Value | Description |
---|---|---|---|
repository | string
| repository
| The repository name. |
workspace | string
| collaboration
| The workspace name. |
action | ArrayList
| {java.util.ArrayList} | The action name. |
This plugin is used to filter WCM node types.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.templates.TemplateService</target-component>
The configuration is applied mainly in /packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/dms-extension/dms/dms-templates-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.templates.TemplateService</target-component>
<component-plugin>
<name>FilterContentTypeForWCMSpecificFolder</name>
<set-method>addContentTypeFilterPlugin</set-method>
<type>org.exoplatform.services.cms.templates.ContentTypeFilterPlugin</type>
<description>this plugin is used to filter wcm nodetype</description>
<init-params>
<object-param>
<name>cssFolderFilter</name>
<description>only exo:cssFile can be created in exo:cssFolder</description>
<object type="org.exoplatform.services.cms.templates.ContentTypeFilterPlugin$FolderFilterConfig">
<field name="folderType">
<string>exo:cssFolder</string>
</field>
<field name="contentTypes">
<collection type="java.util.ArrayList">
<value>
<string>exo:cssFile</string>
</value>
</collection>
</field>
</object>
</object-param>
<object-param>
...
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: FilterContentTypeForWCMSpecificFolder
Set-method: addContentTypeFilterPlugin
Type: org.exoplatform.services.cms.templates.ContentTypeFilterPlugin
Object type: org.exoplatform.services.cms.templates.ContentTypeFilterPlugin$FolderFilterConfig
Field | Type | Value | Description |
---|---|---|---|
folderType | string | exo:cssFolder
| The folder type. |
contentTypes | ArrayList | {java.util.ArrayList} | The content type. |
This plugin is used to store the context configuration of a publication lifecycle. To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.wcm.extensions.publication.PublicationManager</target-component>
The configuration is applied mainly in packaging/ecmdemo/webapp/src/main/webapp/WEB-INF/conf/sample-portal/wcm/content-configuration.xml or packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/content-extended/authoring/configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.wcm.extensions.publication.PublicationManager</target-component>
<component-plugin>
<name>AddContext</name>
<set-method>addContext</set-method>
<type>org.exoplatform.services.wcm.extensions.publication.context.ContextPlugin</type>
<init-params>
<object-param>
<name>contexts</name>
<object type="org.exoplatform.services.wcm.extensions.publication.context.impl.ContextConfig">
<field name="contexts">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.wcm.extensions.publication.context.impl.ContextConfig$Context">
<field name="name">
<string>context2</string>
</field>
<field name="priority">
<string>100</string>
</field>
<field name="lifecycle">
<string>lifecycle2</string>
</field>
<field name="site">
<string>acme</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: AddContext
Set-method: addContext
Type: org.exoplatform.services.wcm.extensions.publication.context.ContextPlugin
Object type: org.exoplatform.services.wcm.extensions.publication.context.impl.ContextConfig
Field | Type | Value | Description |
---|---|---|---|
name |
string
|
context2
| The name of the context. |
priority |
string
|
100
| The context priority, the higher number indicates higher priority. Because a site may have several lifecycles, the lifecycle with higher priority will be executed sooner. |
lifecycle |
string
|
lifecycle2
| The name of the lifecycle. |
site |
string
|
acme
| The site that will apply the context configuration. |
This is an abstract class and the parent of TaxonomyPlugin . You can create a link from this plugin to its children.
This plugin is used in the SiteSearchService component to filter the search results before these results are presented on the search page.
The configuration is applied mainly in core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/core-search-configuration.xml.
Sample configuration:
<component-plugins>
<component-plugin>
<name>ExcludeMimeTypes</name>
<set-method>addExcludeIncludeDataTypePlugin</set-method>
<type>org.exoplatform.services.wcm.search.ExcludeIncludeDataTypePlugin</type>
<init-params>
<properties-param>
<name>search.exclude.datatypes</name>
<description>exclude some data type when search</description>
<property name="mimetypes" value="text/css,text/javascript,application/x-javascript,text/ecmascript"/>
</properties-param>
</init-params>
</component-plugin>
</component-plugins>
In which:
Name: ExcludeMimeTypes
Set-method: addExcludeIncludeDataTypePlugin
Type: org.exoplatform.services.wcm.search.ExcludeIncludeDataTypePlugin
The plugin has the following parameter:
Properties-param | Description |
---|---|
search.exclude.datatype | Exclude some data types when doing search. |
The search.exclude.datatype
property includes two attributes:
Attribute | Value | Description |
---|---|---|
name |
mimetypes
| The name of the property param. |
value |
text/css,text/javascript,application/x-javascript,text/ecmascript | The list of mimetypes which will be excluded from the search results. |
This plugin is used to refine URLs in Content.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.wcm.friendly.FriendlyService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/content-extended/friendly/configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.wcm.friendly.FriendlyService</target-component>
<component-plugin>
<name>FriendlyService.addConfiguration</name>
<set-method>addConfiguration</set-method>
<type>org.exoplatform.services.wcm.friendly.impl.FriendlyPlugin</type>
<description>Configures</description>
<priority>100</priority>
<init-params>
<value-param>
<name>enabled</name>
<value>true</value>
</value-param>
<object-param>
<name>friendlies.configuration</name>
<object type="org.exoplatform.services.wcm.friendly.impl.FriendlyConfig">
<field name="friendlies">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.wcm.friendly.impl.FriendlyConfig$Friendly">
<field name="friendlyUri">
<string>documents</string>
</field>
<field name="unfriendlyUri">
<string>/public/acme/detail?content-id=/repository/collaboration</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.wcm.friendly.impl.FriendlyConfig$Friendly">
<field name="friendlyUri">
<string>files</string>
</field>
<field name="unfriendlyUri">
<string>/rest-ecmdemo/jcr/repository/collaboration</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: FriendlyService.addConfiguration
Set-method: addConfiguration
Type: org.exoplatform.services.wcm.friendly.impl.FriendlyPlugin
Object type: org.exoplatform.services.wcm.friendly.impl.FriendlyConfig
Field | Type | Value | Description |
---|---|---|---|
friendlyUrl | string | documents | The object that will be applied the friendly URL. |
unfriendlyUrl | string | /public/acme/detail?content-id=/repository/collaboration | The path to the location that will be applied the friendly URL. |
This plugin is used to configure the file types and get thumbnail for images.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.thumbnail.ThumbnailService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/dms-extension/dms/dms-thumbnail-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.thumbnail.ThumbnailService</target-component>
<component-plugin>
<name>ImageThumbnailPlugin</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.cms.thumbnail.impl.ImageThumbnailPlugin</type>
<init-params>
<object-param>
<name>thumbnailType</name>
<description>Thumbnail types</description>
<object type="org.exoplatform.services.cms.thumbnail.impl.ThumbnailType">
<field name="mimeTypes">
<collection type="java.util.ArrayList">
<value>
<string>image/jpeg</string>
</value>
<value>
<string>image/png</string>
</value>
<value>
<string>image/gif</string>
</value>
<value>
<string>image/bmp</string>
</value>
<value>
<string>image/tiff</string>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: ImageThumbnailPlugin
Set-method: addPlugin
Type: org.exoplatform.services.cms.thumbnail.impl.ImageThumbnailPlugin
Object type: org.exoplatform.services.cms.thumbnail.impl.ThumbnailType
Field | Type | Value | Description |
---|---|---|---|
mimeTypes |
String
|
| The list of thumbnail image types. |
When a new portal is created, the configuration of IgnorePortalPlugin is used to avoid deploying data to the existing ones which are listed in the init-parameters.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.wcm.portal.artifacts.CreatePortalArtifactsService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/wcm-extension/wcm/deployment/template-deployment-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.wcm.portal.artifacts.CreatePortalArtifactsService</target-component>
<component-plugin>
<name>Add ignored portals</name>
<set-method>addIgnorePortalPlugin</set-method>
<type>org.exoplatform.services.wcm.portal.artifacts.IgnorePortalPlugin</type>
<description>ignored portals. the service will not deploy data to the ignored portals</description>
<init-params>
<values-param>
<name>ignored.portals</name>
<description>ignored portal list</description>
<value>classic</value>
<value>acme</value>
<value>WAIPortal</value>
</values-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: Add ignored portals
Set-method: addIgnorePortalPlugin
Type: org.exoplatform.services.wcm.portal.artifacts.IgnorePortalPlugin
Init-params
Name | Type | Value | Description |
---|---|---|---|
ignored.portals |
string
|
classic, acme, WAIPortal
| The list of ignored existing portals. |
When a portal is created, this plugin will deploy initial web-contents as the site artifact into the Site Artifact folder of that portal.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.wcm.portal.artifacts.CreatePortalArtifactsService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/wcm-extension/wcm/newsletter-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.wcm.portal.artifacts.CreatePortalArtifactsService</target-component>
<component-plugin>
<name>Initial webcontent artifact for each site</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.wcm.webcontent.InitialWebContentPlugin</type>
<description>This plugin deploy some initial webcontent as site artifact to site artifact folder of portal when
a portal is
created
</description>
<init-params>
<object-param>
<name>Portal logo data</name>
<description>Deployment Descriptor</description>
<object type="org.exoplatform.services.deployment.DeploymentDescriptor">
<field name="target">
<object type="org.exoplatform.services.deployment.DeploymentDescriptor$Target">
<field name="repository">
<string>repository</string>
</field>
<field name="workspace">
<string>collaboration</string>
</field>
<field name="nodePath">
<string>/sites content/live/{portalName}/web contents/site artifacts</string>
</field>
</object>
</field>
<field name="sourcePath">
<string>war:/conf/sample-portal/wcm/artifacts/site-resources/acme-templates/Logo.xml</string>
</field>
</object>
</object-param>
<object-param>
<name>Portal signin data</name>
<description>Deployment Descriptor</description>
<object type="org.exoplatform.services.deployment.DeploymentDescriptor">
<field name="target">
<object type="org.exoplatform.services.deployment.DeploymentDescriptor$Target">
<field name="repository">
<string>repository</string>
</field>
<field name="workspace">
<string>collaboration</string>
</field>
<field name="nodePath">
<string>/sites content/live/{portalName}/web contents/site artifacts</string>
</field>
</object>
</field>
<field name="sourcePath">
<string>war:/conf/sample-portal/wcm/artifacts/site-resources/acme-templates/Signin.xml</string>
</field>
</object>
</object-param>
<object-param>
...
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: AddLifecycle
Set-method: addPlugin
Type: org.exoplatform.services.wcm.webcontent.InitialWebContentPlugin
Object type: org.exoplatform.services.deployment.DeploymentDescriptor$Target
Name | Type | Value | Description |
---|---|---|---|
repository |
string
|
repository
| The repository into which the initial web contents will be deployed. |
workspace | string | collaboration | The workspace into which the initial web contents will be deployed. |
nodePath | string | /sites content/live//web contents/site artifacts | The target node where the initial web-contents will be deployed into. |
sourcePath | string | war:/conf/sample-portal/wcm/artifacts/site-resources/acme-templates/Logo.xml | The path to the source that this plugin will get data. |
This plugin is used to create predefined Symlinks into the system.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.deployment.WCMContentInitializerService</target-component>
The configuration is applied mainly in packaging/ecmdemo/webapp/src/main/webapp/WEB-INF/conf/sample-portal/wcm/deployment/acme-deployment-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.deployment.WCMContentInitializerService</target-component>
<component-plugin>
<name>Content Initializer Service</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.deployment.plugins.LinkDeploymentPlugin</type>
<description>Link Deployment Plugin</description>
<init-params>
<object-param>
<name>link01</name>
<description>Deployment Descriptor</description>
<object type="org.exoplatform.services.deployment.plugins.LinkDeploymentDescriptor">
<field name="sourcePath">
<string>repository:collaboration:/sites content/live/acme/web contents/News/News1</string>
</field>
<field name="targetPath">
<string>repository:collaboration:/sites content/live/acme/categories/acme</string>
</field>
</object>
</object-param>
<object-param>
<name>link02</name>
<description>Deployment Descriptor</description>
<object type="org.exoplatform.services.deployment.plugins.LinkDeploymentDescriptor">
<field name="sourcePath">
<string>repository:collaboration:/sites content/live/acme/web contents/News/News2</string>
</field>
<field name="targetPath">
<string>repository:collaboration:/sites content/live/acme/categories/acme</string>
</field>
</object>
</object-param>
<object-param>
<name>link03</name>
<description>Deployment Descriptor</description>
<object type="org.exoplatform.services.deployment.plugins.LinkDeploymentDescriptor">
<field name="sourcePath">
<string>repository:collaboration:/sites content/live/acme/web contents/News/News3</string>
</field>
<field name="targetPath">
<string>repository:collaboration:/sites content/live/acme/categories/acme</string>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: Content Initializer Service
Set-method: addPlugin
Type: org.exoplatform.services.wcm.webcontent.InitialWebContentPlugin
Object type: org.exoplatform.services.deployment.plugins.LinkDeploymentDescriptor
Field | Type | Value | Description |
---|---|---|---|
sourcePath |
string
|
repository:collaboration:/sites content/live/acme/web contents/News/News1
| The path to the source where this plugin will get data. |
targetPath |
string
|
repository:collaboration:/sites content/live/acme/categories/acme
| The path to the target where this plugin will deploy. |
This plugin is used to configure predefined groups or users for lock administration. To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.lock.LockService</target-component>
The configuration is applied mainly in core/core-configuration/src/main/webapp/WEB-INF/conf/wcm-core/core-services-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.lock.LockService</target-component>
<component-plugin>
<name>predefinedLockGroupsOrUsersPlugin</name>
<set-method>addLockGroupsOrUsersPlugin</set-method>
<type>org.exoplatform.services.cms.lock.impl.LockGroupsOrUsersPlugin</type>
<init-params>
<object-param>
<name>LockGroupsOrUsers.configuration</name>
<description>configuration predefined groups or users for lock administrator</description>
<object type="org.exoplatform.services.cms.lock.impl.LockGroupsOrUsersConfig">
<field name="settingLockList">
<collection type="java.util.ArrayList">
<value>
<string>*:/platform/administrators</string>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: predefinedLockGroupsOrUsersPlugin
Set-method: addLockGroupsOrUsersPlugin
Type: org.exoplatform.services.cms.lock.impl.LockGroupsOrUsersPlugin
Object type: org.exoplatform.services.cms.lock.impl.LockGroupsOrUsersConfig
Field | Type | Value | Description |
---|---|---|---|
settingLockList | ArrayList | {java.util.ArrayList} | The list of the groups or user to be locked. |
This plugin is used to create a predefined drive into a repository. A drive can be considered as a shortcut in the content repository, a quick access to some places for users. You can restrict the visibility of this drive to a group/user and apply a specific view depending on the content you have in this area.
A drive is the combination of:
Path: the root folder of the drive.
View: how we can see contents, such as by list, thumbnails, coverflow.
Role: the visibility to every users, a group or a single user.
Options: allow you to specify whether to see hidden nodes or not and to create folders in this drive or not.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.drives.ManageDriveService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/dms-extension/dms/dms-drives-configuration.xml.
The following structure is used for drives configuration.
<external-component-plugins>
<target-component>org.exoplatform.services.cms.drives.ManageDriveService</target-component>
<component-plugin>
<name>manage.drive.plugin</name>
<set-method>setManageDrivePlugin</set-method>
<type>org.exoplatform.services.cms.drives.impl.ManageDrivePlugin</type>
<description>Nothing</description>
<init-params>
<object-param>
There are initializing attributes of org.exoplatform.services.cms.drives.DriveData object
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
The file that contains the structure above will be configured in the configuration.xml file as the following:
<import>war:/conf/wcm-extension/dms/drives-configuration.xml</import>
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.drives.ManageDriveService</target-component>
<component-plugin>
<name>manage.drive.plugin</name>
<set-method>setManageDrivePlugin</set-method>
<type>org.exoplatform.services.cms.drives.impl.ManageDrivePlugin</type>
<description>Nothing</description>
<init-params>
<object-param>
<name>Managed Sites</name>
<description>Managed Sites</description>
<object type="org.exoplatform.services.cms.drives.DriveData">
<field name="name">
<string>Managed Sites</string>
</field>
<field name="repository">
<string>repository</string>
</field>
<field name="workspace">
<string>collaboration</string>
</field>
<field name="permissions">
<string>*:/platform/administrators</string>
</field>
<field name="homePath">
<string>/sites content/live</string>
</field>
<field name="icon">
<string/>
</field>
<field name="views">
<string>wcm-view</string>
</field>
<field name="viewPreferences">
<boolean>false</boolean>
</field>
<field name="viewNonDocument">
<boolean>true</boolean>
</field>
<field name="viewSideBar">
<boolean>true</boolean>
</field>
<field name="showHiddenNode">
<boolean>false</boolean>
</field>
<field name="allowCreateFolders">
<string>nt:folder,nt:unstructured</string>
</field>
<field name="allowNodeTypesOnTree">
<string>*</string>
</field>
</object>
</object-param>
<object-param>
<name>Public</name>
<description>Public drive</description>
<object type="org.exoplatform.services.cms.drives.DriveData">
<field name="name">
<string>Public</string>
</field>
<field name="repository">
<string>repository</string>
</field>
<field name="workspace">
<string>collaboration</string>
</field>
<field name="permissions">
<string>*:/platform/users</string>
</field>
<field name="homePath">
<string>/Users/${userId}/Public</string>
</field>
<field name="icon">
<string/>
</field>
<field name="views">
<string>simple-view, admin-view</string>
</field>
<field name="viewPreferences">
<boolean>false</boolean>
</field>
<field name="viewNonDocument">
<boolean>false</boolean>
</field>
<field name="viewSideBar">
<boolean>true</boolean>
</field>
<field name="showHiddenNode">
<boolean>false</boolean>
</field>
<field name="allowCreateFolders">
<string>nt:folder,nt:unstructured</string>
</field>
<field name="allowNodeTypesOnTree">
<string>*</string>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: manage.drive.plugin
Set-method: setManageDrivePlugin
Type: org.exoplatform.services.cms.drives.impl.ManageDrivePlugin
Object type: org.exoplatform.services.cms.drives.DriveData
Field | Type | Value | Description |
---|---|---|---|
name |
String
|
Public
| The name of drive which must be unique. |
repository |
String
|
repository
| Content Repository where to find the root path. |
workspace |
String
|
collaboration
| Workspace in the Content Repository. |
homePath |
String
|
/sites content/live
| Root path in the Content Repository.
userId
can be used to use the userId at runtime in the path. |
permissions |
String
| *:/platform/administrators | Visibility of the drive based on eXo rights. For example: *:/platform/users
|
icon |
String
| N/A | The Url to the icon. |
views |
String
|
wcm-view
| The list of views you want to use, separated by commas. For example: simple-view,admin-view
|
viewPreferences |
Boolean
|
false
| The User Preference icon will be visible if true. |
viewNonDocument |
Boolean
|
true
| Non-document types will be visible in the user view if true. |
viewSideBar |
Boolean
|
true
| Show/Hide the left bar (with navigation and filters). |
showHiddenNode |
Boolean
|
false
| Hidden nodes will be visible if true. |
allowCreateFolders |
String
|
nt:folder,nt:unstructured | List of node types that you can create as folders. For example: nt:folder,nt:unstructured . |
allowNodeTypesOnTree |
String
| * | Allow you to filter node types in the navigation tree. For example, the default value is "*" to show all content types. |
This plugin is used to create a predefined View into a repository. A View can include many object parameters. Parameters are used to create default Views, Templates and Actions of Manage View service. View enables administrators to customize View classification that can impact on users in exploring workspace. Each object-param has a type that is a class representing all properties of a View.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.views.ManageViewService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/dms-extension/dms/dms-views-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.views.ManageViewService</target-component>
<component-plugin>
<name>manage.view.plugin</name>
<set-method>setManageViewPlugin</set-method>
<type>org.exoplatform.services.cms.views.impl.ManageViewPlugin</type>
<description>this plugin manage user view</description>
<init-params>
<value-param>
<name>autoCreateInNewRepository</name>
<value>true</value>
</value-param>
<value-param>
<name>predefinedViewsLocation</name>
<value>war:/conf/dms-extension/dms/artifacts</value>
</value-param>
<value-param>
<name>repository</name>
<value>repository</value>
</value-param>
<object-param>
<name>System-View</name>
<description>View configuration for System workspace</description>
<object type="org.exoplatform.services.cms.views.ViewConfig">
<field name="name">
<string>system-view</string>
</field>
<field name="permissions">
<string>*:/platform/administrators</string>
</field>
<field name="template">
<string>/exo:ecm/views/templates/ecm-explorer/SystemView</string>
</field>
<field name="tabList">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.views.ViewConfig$Tab">
<field name="tabName">
<string>Info</string>
</field>
<field name="buttons">
<string>viewNodeType; viewPermissions; viewProperties; showJCRStructure</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
<object-param>
<name>System Template</name>
<description>Template for display documents in list style</description>
<object type="org.exoplatform.services.cms.views.TemplateConfig">
<field name="type">
<string>ecmExplorerTemplate</string>
</field>
<field name="name">
<string>SystemView</string>
</field>
<field name="warPath">
<string>/ecm-explorer/SystemView.gtmpl</string>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: manage.view.plugin
Set-method: setManageViewPlugin
Type: org.exoplatform.services.cms.views.impl.ManageViewPlugin
Init-param:
value-param | Type | Value | Description |
---|---|---|---|
autoCreateInNewRepository |
boolean |
true | Allow creating a predefined View in this repository if the value is "true". |
predefinedViewsLocation |
string | war:/conf/dms-extension/dms/artifacts | The location of the View node in the repository. |
repository | string | repository | The repository name. |
Object type: org.exoplatform.services.cms.views.ViewConfig
Field | Type | Value | Description |
---|---|---|---|
name | string |
system-view
| The name of view which must be unique inside WCM. |
permissions | string | *:/platform/administrators | Visibility of the view based on eXo rights. |
template | string | /exo:ecm/views/templates/ecm-explorer/SystemView
| Specify path to the template location. |
tabList | ArrayList
| {java.util.ArrayList} | Include a set of view names. |
Object type: org.exoplatform.services.cms.views.ViewConfig$Tab
Field | Type | Value | Description |
---|---|---|---|
tabName | string | Info
| The name of tab which must be unique. |
button | string | viewNodeType; viewPermissions; viewProperties; showJCRStructure
| Specify a set of view component names. |
Object type: org.exoplatform.services.cms.views.TemplateConfig
Field | Type | Vsalue | Description |
---|---|---|---|
type | string | ecmExplorerTemplate
| Specify if a name is truly a class representing all properties of a view. |
name | string | system-view
| Specify a set of view component names. |
warPath | string |
/ecm-explorer/SystemView.gtmpl
| Specify a template location to view. |
This plugin is to set the supported file types of PDF thumbnail. See also ImageThumbnailPlugin .
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.thumbnail.ThumbnailService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/dms-extension/dms/dms-thumbnail-configuration.xml.
Sample configuration:
<component-plugin>
<name>PDFThumbnailPlugin</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.cms.thumbnail.impl.PDFThumbnailPlugin</type>
<init-params>
<object-param>
<name>thumbnailType</name>
<description>Thumbnail types</description>
<object type="org.exoplatform.services.cms.thumbnail.impl.ThumbnailType">
<field name="mimeTypes">
<collection type="java.util.ArrayList">
<value>
<string>application/pdf</string>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
In which:
Name: PDFThumbnailPlugin
Set-method: addPlugin
Type: org.exoplatform.services.cms.thumbnail.impl.PDFThumbnailPlugin
Object type: org.exoplatform.services.cms.thumbnail.impl.ThumbnailType
Field | Type | Value | Description |
---|---|---|---|
mimeTypes | String | application/pdf | The MIME type of the pdf thumbnail. |
This plugin is used to import the view templates into Content List Viewer.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.views.ApplicationTemplateManagerService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/wcm-extension/dms/application-templates-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.views.ApplicationTemplateManagerService</target-component>
<component-plugin>
<name>clv.templates.plugin</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.cms.views.PortletTemplatePlugin</type>
<description>This plugin is used to import views templates for Content List Viewer</description>
<init-params>
<value-param>
<name>portletName</name>
<value>content-list-viewer</value>
</value-param>
<value-param>
<name>portlet.template.path</name>
<value>war:/conf/wcm-artifacts/application-templates/content-list-viewer</value>
</value-param>
<object-param>
<name>default.folder.list.viewer</name>
<description>Default folder list viewer groovy template</description>
<object type="org.exoplatform.services.cms.views.PortletTemplatePlugin$PortletTemplateConfig">
<field name="templateName">
<string>UIContentListPresentationDefault.gtmpl</string>
</field>
<field name="category">
<string>list</string>
</field>
</object>
</object-param>
<object-param>
....
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: clv.templates.plugin
Set-method: addPlugin
Type: org.exoplatform.services.cms.views.PortletTemplatePlugin
Init-param:
Value-param | Type | Value | Description |
---|---|---|---|
portletName | string | content-list-viewer | The name of the portlet. |
portlet.template.path | string | war:/conf/wcm-artifacts/application-templates/content-list-viewer | The path to the configuration of the portlet. |
Object type: org.exoplatform.services.cms.views.PortletTemplatePlugin$PortletTemplateConfig
Field | Type | Description |
---|---|---|
templateName | string | The name of the GROOVY template. |
category |
string
| The category name. |
This plugin is used to import the predefined processes into the system.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.workflow.WorkflowServiceContainer</target-component>
The configuration is applied mainly in packaging/workflow/webapp/src/main/webapp/WEB-INF/workflow-extension/workflow/bonita-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.workflow.WorkflowServiceContainer</target-component>
<component-plugin>
<name>deploy.predefined.processes</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.workflow.PredefinedProcessesPlugin</type>
<init-params>
<object-param>
<name>predefined.processes</name>
<description>load of default business processes</description>
<object type="org.exoplatform.services.workflow.ProcessesConfig">
<field name="processLocation">
<string>war:/conf/bp</string>
</field>
<field name="predefinedProcess">
<collection type="java.util.HashSet">
<value>
<string>/exo-ecms-ext-workflow-bp-bonita-content-2.3.8-SNAPSHOT.jar</string>
</value>
<value>
<string>/exo-ecms-ext-workflow-bp-bonita-payraise-2.3.8-SNAPSHOT.jar</string>
</value>
<value>
<string>/exo-ecms-ext-workflow-bp-bonita-holiday-2.3.8-SNAPSHOT.jar</string>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
name: deploy.predefined.processes
set-method: addPlugin
type: org.exoplatform.services.workflow.PredefinedProcessesPlugin
Object type: org.exoplatform.services.workflow.ProcessesConfig
Field | Type | Value | Description |
---|---|---|---|
processLocation | string | war:/conf/bp | The path to the process. |
predefinedProcess | HashSet | java.util.HashSet | The list of the processes. |
This is an abstract class and the parent of StageAndVersionPublicationPlugin and AuthoringPublicationPlugin . You can create a link from this plugin to its children.
This plugin is used to store predefined queries into the repositories of the system.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.queries.QueryService</target-component>
The configuration is applied mainly in /packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/dms-extension/dms/dms-queries-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.queries.QueryService</target-component>
<component-plugin>
<name>query.plugin</name>
<set-method>setQueryPlugin</set-method>
<type>org.exoplatform.services.cms.queries.impl.QueryPlugin</type>
<description>Nothing</description>
<init-params>
<value-param>
<name>autoCreateInNewRepository</name>
<value>true</value>
</value-param>
<value-param>
<name>repository</name>
<value>repository</value>
</value-param>
<object-param>
<name>CreatedDocuments</name>
<description>documents created by the current user</description>
<object type="org.exoplatform.services.cms.queries.impl.QueryData">
<field name="name">
<string>Created Documents</string>
</field>
<field name="language">
<string>xpath</string>
</field>
<field name="statement">
<string>//*[(@jcr:primaryType = 'exo:article' or @jcr:primaryType = 'nt:file') and
@exo:owner='${UserId}$'] order by @exo:dateCreated descending
</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<string>*:/platform/users</string>
</value>
</collection>
</field>
<field name="cachedResult">
<boolean>false</boolean>
</field>
</object>
</object-param>
<object-param>
<name>CreatedDocumentsDayBefore</name>
<description>documents created the day before</description>
<object type="org.exoplatform.services.cms.queries.impl.QueryData">
<field name="name">
<string>CreatedDocumentDayBefore</string>
</field>
<field name="language">
<string>xpath</string>
</field>
<field name="statement">
<string>//element(*,exo:article)[@exo:dateCreated < xs:dateTime('${Date}$')] order by
@exo:dateCreated descending
</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<string>*:/platform/users</string>
</value>
</collection>
</field>
<field name="cachedResult">
<boolean>true</boolean>
</field>
</object>
</object-param>
<object-param>
<name>AllArticles</name>
<description>All articles</description>
<object type="org.exoplatform.services.cms.queries.impl.QueryData">
<field name="name">
<string>All Articles</string>
</field>
<field name="language">
<string>xpath</string>
</field>
<field name="statement">
<string>//element(*,exo:article) order by @exo:dateCreated descending</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<string>*:/platform/users</string>
</value>
</collection>
</field>
<field name="cachedResult">
<boolean>true</boolean>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: predefinedTaxonomyPlugin
Set-method: setQueryPlugin
Type: org.exoplatform.services.cms.queries.impl.QueryPlugin
Init-param:
Value-param | Type | Value | Description |
---|---|---|---|
autoCreateInNewRepository | boolean | true | Store queries in a new repository if the value is "true". |
repository | string | repository | The repository to the target node. |
Object type: org.exoplatform.services.cms.queries.impl.QueryData
Field | Type | Description |
---|---|---|
name | string | The name of the query. |
language | string | The language of the query (Xpath, SQL). |
statement | string | The query statement. |
permissions | ArrayList | The permission which users must have to use this query. |
cachedResult | boolean | Specify if the query is cached or not. |
This is an abstract class and the parent of RemoveTaxonomyPlugin . You can create a link from this plugin to its children.
This plugin is used to invalidate taxonomy trees in categories folder of a portal when the portal is removed.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.wcm.portal.artifacts.RemovePortalArtifactsService</target-component>
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.wcm.portal.artifacts.RemovePortalArtifactsService</target-component>
<component-plugin>
<name>Remove taxonomy tree</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.wcm.category.RemoveTaxonomyPlugin</type>
<description>This plugin invalidate taxonomy tree to categories folder of portal when a portal is removed
</description>
</component-plugin>
</external-component-plugins>
In which:
Name: Remove taxonomy tree
Set-method: addPlugin
Type: org.exoplatform.services.wcm.category.RemoveTaxonomyPlugin
This plugin is used to import the predefined script actions into the system.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.actions.ActionServiceContainer</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/dms-extension/dms/dms-actions-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.actions.ActionServiceContainer</target-component>
<component-plugin>
<name>exo:scriptAction</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.cms.actions.impl.ScriptActionPlugin</type>
<init-params>
<object-param>
<name>predefined.actions</name>
<description>description</description>
<object type="org.exoplatform.services.cms.actions.impl.ActionConfig">
<field name="repository">
<string>repository</string>
</field>
<field name="workspace">
<string>collaboration</string>
</field>
<field name="actions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.actions.impl.ActionConfig$Action">
<field name="type">
<string>exo:sendMailAction</string>
</field>
<field name="name">
<string>sendMail</string>
</field>
<field name="description">
<string>send a notification mail</string>
</field>
<field name="srcWorkspace">
<string>collaboration</string>
</field>
<field name="srcPath">
<string>/Documents/Validation Requests</string>
</field>
<field name="isDeep">
<boolean>true</boolean>
</field>
<field name="lifecyclePhase">
<collection type="java.util.ArrayList">
<value>
<string>read</string>
</value>
</collection>
</field>
<field name="roles">
<string>*:/platform/administrators</string>
</field>
<field name="variables">
<string>exo:to=benjamin.mestrallet@exoplatform.com</string>
</field>
<field name="mixins">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.actions.impl.ActionConfig$Mixin">
<field name="name">
<string>mix:affectedNodeTypes</string>
</field>
<field name="properties">
<string>
exo:affectedNodeTypeNames=exo:article,exo:podcast,exo:sample,kfx:document,nt:file,rma:filePlan
</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.actions.impl.ActionConfig$Action">
<field name="type">
<string>exo:trashFolderAction</string>
</field>
<field name="name">
<string>trashFolder</string>
</field>
<field name="description">
<string>trigger actions for items in trash</string>
</field>
<field name="srcWorkspace">
<string>collaboration</string>
</field>
<field name="srcPath">
<string>/Trash</string>
</field>
<field name="isDeep">
<boolean>false</boolean>
</field>
<field name="lifecyclePhase">
<collection type="java.util.ArrayList">
<value>
<string>node_added</string>
</value>
<value>
<string>node_removed</string>
</value>
</collection>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
name: exo:scriptAction_
set-method : addPlugin
type: org.exoplatform.services.cms.actions.impl.ScriptActionPlugin
Object type: org.exoplatform.services.cms.actions.impl.ActionConfig
Name | Type | Default Value | Description |
---|---|---|---|
repository | string | repository | The name of the repository. |
workspace | string | collaboration | The name of the workspace. |
actions | ArrayList | {java.util.ArrayList} | The list of the actions. |
Object type: org.exoplatform.services.cms.actions.impl.ActionConfig$Action
Name | Type | Default Value | Description |
---|---|---|---|
type | string | exo:sendMailAction | The type of the action. |
name | string | sendMail | The name of the action. |
description | string | send a notification mail | The description of the action. |
srcWorkspace | string | collaboration | The source workspace of the action. |
isDeep | boolean | false | Specify the depth of node that the action script will affect. |
srcPath | string | trash | The path to the source. |
lifecyclePhase | ArrayList | {java.util.ArrayList} | Specify the lifecycle phase that the action will take place. |
This plugin is used to add groovy scripts into the system.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.scripts.ScriptService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/dms-extension/dms/dms-scripts-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.scripts.ScriptService</target-component>
<component-plugin>
<name>manage.script.plugin</name>
<set-method>addScriptPlugin</set-method>
<type>org.exoplatform.services.cms.scripts.impl.ScriptPlugin</type>
<description>Nothing</description>
<init-params>
<value-param>
<name>autoCreateInNewRepository</name>
<value>true</value>
</value-param>
<value-param>
<name>repository</name>
<value>repository</value>
</value-param>
<value-param>
<name>predefinedScriptsLocation</name>
<value>war:/conf/dms-extension/dms/artifacts</value>
</value-param>
<object-param>
<name>predefined.scripts</name>
<description>description</description>
<object type="org.exoplatform.services.cms.impl.ResourceConfig">
<field name="resources">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/action/RSSScript.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/action/SendMailScript.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/action/TrashFolderScript.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/action/EnableVersioningScript.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/action/AutoVersioningScript.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/action/AddMetadataScript.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/action/TransformBinaryChildrenToTextScript.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/action/GetMailScript.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/action/ProcessRecordsScript.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/action/PublishingRequestScript.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/action/AddTaxonomyActionScript.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/widget/FillSelectBoxWithCalendarCategories.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/widget/FillSelectBoxWithMetadatas.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/widget/FillSelectBoxWithWorkspaces.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/widget/FillSelectBoxWithNodeChildren.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/widget/FillSelectBoxWithLanguage.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/interceptor/PreNodeSaveInterceptor.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/interceptor/PostNodeSaveInterceptor.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>ecm-explorer/interceptor/PostFilePlanInterceptor.groovy</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.impl.ResourceConfig$Resource">
<field name="name">
<string>content-browser/GetDocuments.groovy</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: manage.script.plugin
Set-method: addScriptPlugin
Type: org.exoplatform.services.cms.scripts.impl.ScriptPlugin
Init-param:
Value-param | Type | Value | Description |
---|---|---|---|
autoCreateInNewRepository |
Boolean |
true | Enable/Disable the creation of the scripts in the newly created repository. |
repository | String
|
repository | The repository name. |
predefinedScriptsLocation | String
|
war:/conf/dms-extension/dms/artifacts | The location where the scripts are created. |
Object type: org.exoplatform.services.cms.impl.ResourceConfig
Field | Type | Value | Description |
---|---|---|---|
resource | ArrayList | {java.util.ArrayList} | The resource name. |
This plugin is used to control the state life cycle of a content.
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/content-extended/authoring/configuration.xml.
Sample configuration:
<component-plugin>
<name>States and versions based publication</name>
<set-method>addPublicationPlugin</set-method>
<type>org.exoplatform.services.wcm.publication.lifecycle.stageversion.StageAndVersionPublicationPlugin</type>
<description>This publication lifecycle publish a web content or DMS document to a portal page with more state
and version.
</description>
</component-plugin>
In which:
name: States and versions based publication
set method: addPublicationPlugin
type: org.exoplatform.services.wcm.publication.lifecycle.stageversion.StageAndVersionPublicationPlugin
This plugin is used to control the state life cycle of a content.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.wcm.extensions.publication.PublicationManager</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/content-extended/authoring/configuration.xml.
Sample configuration:
<component-plugin>
<name>AddLifecycle</name>
<set-method>addLifecycle</set-method>
<type>org.exoplatform.services.wcm.extensions.publication.lifecycle.StatesLifecyclePlugin</type>
<description>Configures</description>
<priority>1</priority>
<init-params>
<object-param>
<name>lifecycles</name>
<object type="org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig">
<field name="lifecycles">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig$Lifecycle">
<field name="name">
<string>lifecycle1</string>
</field>
<field name="publicationPlugin">
<string>Authoring publication</string>
</field>
<field name="states">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig$State">
<field name="state">
<string>draft</string>
</field>
<field name="membership">
<string>author:/platform/web-contributors</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig$State">
<field name="state">
<string>pending</string>
</field>
<field name="membership">
<string>author:/platform/web-contributors</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig$State">
<field name="state">
<string>approved</string>
</field>
<field name="membership">
<string>manager:/platform/web-contributors</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig$State">
<field name="state">
<string>staged</string>
</field>
<field name="membership">
<string>publisher:/platform/web-contributors</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig$State">
<field name="state">
<string>published</string>
</field>
<field name="membership">
<string>publisher:/platform/web-contributors</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
In which:
Name: AddLifecycle
Set-method: addLifecycle
Type: org.exoplatform.services.wcm.extensions.publication.lifecycle.StatesLifecyclePlugin
Object type:
org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig$Lifecycle
Field | Type | Value | Description |
---|---|---|---|
name |
string
|
lifecycle1
| The name of the lifecycle. |
publicationPlugin |
string
| Authoring publication
| The publication plugin name. |
states |
ArrayList
| {java.util.ArrayList} | The list of the publication states. |
Object type:
org.exoplatform.services.wcm.extensions.publication.lifecycle.impl.LifecyclesConfig$State
Field | Type | Description |
---|---|---|
state |
string
| The publication states: draft, pending, staged, approved or published. |
membership |
string
| The user or group. |
This plugin is used to configure the predefined permission for tag to inject in JCR.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.folksonomy.NewFolksonomyService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/dms-extension/dms/dms-folksonomy-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.folksonomy.NewFolksonomyService</target-component>
<component-plugin>
<name>predefinedTagPermissionPlugin</name>
<set-method>addTagPermissionPlugin</set-method>
<type>org.exoplatform.services.cms.folksonomy.impl.TagPermissionPlugin</type>
<init-params>
<object-param>
<name>TagPermission.configuration</name>
<description>configuration predefined permission for tag to inject in jcr</description>
<object type="org.exoplatform.services.cms.folksonomy.impl.TagPermissionConfig">
<field name="tagPermissionList">
<collection type="java.util.ArrayList">
<value>
<string>*:/platform/administrators</string>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: predefinedTagPermissionPlugin
Set-method: addTagPermissionPlugin
Type: org.exoplatform.services.cms.folksonomy.impl.TagPermissionPlugin
Object type: org.exoplatform.services.cms.folksonomy.impl.TagPermissionConfig
Name | Type | Value | Description |
---|---|---|---|
tagPermissionList | ArrayList | {java.util.ArrayList} | The users/groups that have the permission. |
This plugin is used to configure the predefined styles for tag to inject in JCR.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.folksonomy.NewFolksonomyService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/dms-extension/dms/dms-folksonomy-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.folksonomy.NewFolksonomyService</target-component>
<component-plugin>
<name>predefinedTagStylePlugin</name>
<set-method>addTagStylePlugin</set-method>
<type>org.exoplatform.services.cms.folksonomy.impl.TagStylePlugin</type>
<init-params>
<object-param>
<name>htmStyleForTag.configuration</name>
<description>configuration predefined html style for tag to inject in jcr</description>
<object type="org.exoplatform.services.cms.folksonomy.impl.TagStyleConfig">
<field name="autoCreatedInNewRepository">
<boolean>true</boolean>
</field>
<field name="repository">
<string>repository</string>
</field>
<field name="tagStyleList">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.folksonomy.impl.TagStyleConfig$HtmlTagStyle">
<field name="name">
<string>normal</string>
</field>
<field name="tagRate">
<string>0..2</string>
</field>
<field name="htmlStyle">
<string>font-size: 12px; font-weight: bold; color: #6b6b6b; font-family:
verdana; text-decoration:none;
</string>
</field>
<field name="description">
<string>Normal style for tag</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.folksonomy.impl.TagStyleConfig$HtmlTagStyle">
<field name="name">
<string>interesting</string>
</field>
<field name="tagRate">
<string>2..5</string>
</field>
<field name="htmlStyle">
<string>font-size: 13px; font-weight: bold; color: #5a66ce; font-family:
verdana; text-decoration:none;
</string>
</field>
<field name="description">
<string>Interesting style for tag</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.folksonomy.impl.TagStyleConfig$HtmlTagStyle">
<field name="name">
<string>attractive</string>
</field>
<field name="tagRate">
<string>5..7</string>
</field>
<field name="htmlStyle">
<string>font-size: 15px; font-weight: bold; color: blue; font-family: Arial;
text-decoration:none;
</string>
</field>
<field name="description">
<string>attractive style for tag</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.folksonomy.impl.TagStyleConfig$HtmlTagStyle">
<field name="name">
<string>hot</string>
</field>
<field name="tagRate">
<string>7..10</string>
</field>
<field name="htmlStyle">
<string>font-size: 18px; font-weight: bold; color: #ff9000; font-family: Arial;
text-decoration:none;
</string>
</field>
<field name="description">
<string>hot style for tag</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.folksonomy.impl.TagStyleConfig$HtmlTagStyle">
<field name="name">
<string>hottest</string>
</field>
<field name="tagRate">
<string>10..*</string>
</field>
<field name="htmlStyle">
<string>font-size: 20px; font-weight: bold; color: red; font-family:Arial;
text-decoration:none;
</string>
</field>
<field name="description">
<string>hottest style for tag</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
Name: predefinedTagStylePlugin
Set-method: addTagStylePlugin
Type: org.exoplatform.services.cms.folksonomy.impl.TagStylePlugin
Object type: org.exoplatform.services.cms.folksonomy.impl.TagStyleConfig
Name | Type | Value | Description |
---|---|---|---|
autoCreatedInNewRepository |
boolean
|
true
| Specify whether the tag style is added automatically in a new reposistory or not. |
repository |
string
|
repository
| Name of the repository where the tag style is added. |
tagStyleList |
ArrayList
| {java.util.ArrayList} | The list of tag styles. |
Object type: org.exoplatform.services.cms.folksonomy.impl.TagStyleConfig$HtmlTagStyle
Name | Type | Description |
---|---|---|
name |
string
| The name of the tag. |
tagRate |
string
| The number of times that a tag is used which will decide the respective tag style. |
htmlStyle |
string
| The HTML code that defines the style. |
This plugin is used to configure the predefined taxonomies to inject into JCR.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.taxonomy.TaxonomyService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/dms-extension/dms/dms-categories-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.cms.taxonomy.TaxonomyService</target-component>
<component-plugin>
<name>predefinedTaxonomyPlugin</name>
<set-method>addTaxonomyPlugin</set-method>
<type>org.exoplatform.services.cms.taxonomy.impl.TaxonomyPlugin</type>
<init-params>
<value-param>
<name>autoCreateInNewRepository</name>
<value>true</value>
</value-param>
<value-param>
<name>repository</name>
<value>repository</value>
</value-param>
<value-param>
<name>workspace</name>
<value>dms-system</value>
</value-param>
<value-param>
<name>treeName</name>
<value>System</value>
</value-param>
<object-param>
<name>permission.configuration</name>
<object type="org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig">
<field name="taxonomies">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig$Taxonomy">
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig$Permission">
<field name="identity">
<string>*:/platform/users</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>false</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
<object-param>
...
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: predefinedTaxonomyPlugin
Set-method: addTaxonomyPlugin
Type: org.exoplatform.services.cms.taxonomy.impl.TaxonomyPlugin
Init-param:
Value-param | Type | Value | Description |
---|---|---|---|
autoCreateInNewRepository | boolean |
true
| Enable/Disable the creation of the taxonomies in the newly created repository. |
repository | string |
repository
| The name of the repository where taxonomies are created. |
workspace | string |
dms-system
| The name of the workspace where taxonomies are created. |
treeName | string | system
| The name of the taxonomy tree created. |
Object type: org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig
Name | Type | Value | Description |
---|---|---|---|
taxonomies |
ArrayList
| {java.util.ArrayList} | The list of taxonomies to be configured with permission. |
Object type: org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig$Taxonomy
Name | Type | Value | Description |
---|---|---|---|
permissions |
ArrayList
| {java.util.ArrayList} | The list of permissions for users or groups to access the taxonomy. |
Object type: org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig$Permission
Name | Type | Value | Description |
---|---|---|---|
identity |
string
| *:/platform/users | The name of the user, group or membership. |
read |
boolean
|
true
| The permission to read the taxonomy tree. |
addNode | boolean
|
true
| The permission to add a node to the taxonomy tree. |
setProperty |
boolean
|
true
| The permission to set properties for a node in the taxonomy tree. |
remove | boolean
|
false | The permission to remove a node from the taxonomy tree. |
This plugin is used to create templates into the system. A template is a presentation to display the saved information.
The node type template is used to edit and display the node content. Each node type has one dialog1.gtmpl file (dialog template) for editing/creating a node and one view1.gtmpl file (view template) for viewing the node content. Using the dialog template, you can specify a dialog whose fields correspond to the properties of the node you want to edit their values. When this template is rendered, each specified field will appear with a data input box for you to edit. Note that you do not have to design a dialog in which all data of the node are listed to be edited. You can just list the subset of node data you want to edit. Like the dialog template, the view template renders information of the node. You just need to create the template and specify which data fields to be displayed. With this kind of template, node information is only displayed but cannot be edited. See details at ContentType.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.cms.templates.TemplateService</target-component>
The configuration is applied mainly in packaging/wcm/webapp/src/main/webapp/WEB-INF/conf/dms-extension/dms/dms-templates-configuration.xml.
Sample configuration:
This below example is configuration for the nt:file template, any other template will be put in the same level with this template starting from the line <object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$NodeType> as the another node type.
<external-component-plugins>
<target-component>org.exoplatform.services.cms.templates.TemplateService</target-component>
<component-plugin>
<name>addTemplates</name>
<set-method>addTemplates</set-method>
<type>org.exoplatform.services.cms.templates.impl.TemplatePlugin</type>
<init-params>
<value-param>
<name>autoCreateInNewRepository</name>
<value>true</value>
</value-param>
<value-param>
<name>storedLocation</name>
<value>war:/conf/dms-extension/dms/artifacts/templates</value>
</value-param>
<value-param>
<name>repository</name>
<value>repository</value>
</value-param>
<object-param>
<name>template.configuration</name>
<description>configuration for the localtion of templates to inject in jcr</description>
<object type="org.exoplatform.services.cms.templates.impl.TemplateConfig">
<field name="nodeTypes">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$NodeType">
<field name="nodetypeName">
<string>nt:file</string>
</field>
<field name="documentTemplate">
<boolean>true</boolean>
</field>
<field name="label">
<string>File</string>
</field>
<field name="referencedView">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$Template">
<field name="templateFile">
<string>/file/views/view1.gtmpl</string>
</field>
<field name="roles">
<string>*</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$Template">
<field name="templateFile">
<string>/file/views/admin_view.gtmpl</string>
</field>
<field name="roles">
<string>*:/platform/administrators</string>
</field>
</object>
</value>
</collection>
</field>
<field name="referencedDialog">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$Template">
<field name="templateFile">
<string>/file/dialogs/dialog1.gtmpl</string>
</field>
<field name="roles">
<string>*</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$Template">
<field name="templateFile">
<string>/file/dialogs/admin_dialog.gtmpl</string>
</field>
<field name="roles">
<string>*:/platform/administrators</string>
</field>
</object>
</value>
</collection>
</field>
<field name="referencedSkin">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$Template">
<field name="templateFile">
<string>/file/skins/Stylesheet-lt.css</string>
</field>
<field name="roles">
<string>*</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.cms.templates.impl.TemplateConfig$Template">
<field name="templateFile">
<string>/file/skins/Stylesheet-rt.css</string>
</field>
<field name="roles">
<string>*</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
name: addTemplates
set-method: addTemplates
type: org.exoplatform.services.cms.templates.impl.TemplatePlugin
Init-params:
Value-param | Type | Value | Description |
---|---|---|---|
autoCreateInNewRepository |
boolean
|
true
| Enable the application to import predefined templates at the start-up of template service automatically. |
storedLocation |
string
|
war:/conf/dms-extension/dms/artifacts/templates
| The location of stored templates. |
repository |
string
|
repository
| Location of stored templates. |
Object-type: org.exoplatform.services.cms.templates.impl.TemplateConfig that defines all available template files, using the "collection type" configuration.
type: It is the name of each object type. It means the type of template, the further configurations for this type are defined by some specified fields.
Field | Type | Value | Description |
---|---|---|---|
nodeTypes |
ArrayList
| {java.util.ArrayList} | The node type of the template. |
Object-type: org.exoplatform.services.cms.templates.impl.TemplateConfig$NodeType
Field | Type | Value | Description |
---|---|---|---|
nodetypeName |
string
| nt:file | The name of template that is saved as a node in system. |
documentTemplate |
boolean
| true
| Determine if the node type is a document type. |
label |
string
| file
| Visual display of the title for this node. |
referencedView |
ArrayList | {java.util.ArrayList} | Determine how to display a view. |
referencedDialog |
ArrayList | {java.util.ArrayList} | Determine how to display a dialog to input information. |
referencedSkin |
ArrayList | {java.util.ArrayList} | Determine the stylesheet for display. |
Object type: org.exoplatform.services.cms.templates.impl.TemplateConfig$Template
Field | Type | Description |
---|---|---|
templateFile |
string
| The location of the file store for the template's presentation. |
roles |
string
| Determine who can access this object (View/Dialog/CSS). |
When a site is created, most of end-users want to see something in the page instead of a blank page, so you need this plugin to deploy some "default" contents, such as Banner, Footer, Navigation, Breadcrumb.
There are two main cases to use:
The site is created only one time when the database is cleaned.
The site is created at runtime, when a user uses the core features of the GateIn portal.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.services.deployment.WCMContentInitializerService</target-component>
The configuration is applied mainly in packaging/ecmdemo/webapp/src/main/webapp/WEB-INF/conf/sample-portal/wcm/deployment/acme-deployment-configuration.xml.
Sample configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.deployment.WCMContentInitializerService</target-component>
<component-plugin>
<name>Content Initializer Service</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.deployment.plugins.XMLDeploymentPlugin</type>
<description>XML Deployment Plugin</description>
<init-params>
<object-param>
<name>ACME Logo data</name>
<description>Deployment Descriptor</description>
<object type="org.exoplatform.services.deployment.DeploymentDescriptor">
<field name="target">
<object type="org.exoplatform.services.deployment.DeploymentDescriptor$Target">
<field name="repository">
<string>repository</string>
</field>
<field name="workspace">
<string>collaboration</string>
</field>
<field name="nodePath">
<string>/sites content/live/acme/web contents/site artifacts</string>
</field>
</object>
</field>
<field name="sourcePath">
<string>war:/conf/sample-portal/wcm/artifacts/site-resources/acme/Logo.xml</string>
</field>
<field name="versionHistoryPath">
<string>war:/conf/sample-portal/wcm/artifacts/site-resources/acme/Logo_versionHistory.zip
</string>
</field>
<field name="cleanupPublication">
<boolean>true</boolean>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
name: Content Initializer Service
set-method: addPlugin
type: org.exoplatform.services.deployment.plugins.XMLDeploymentPlugin
Object type: org.exoplatform.services.deployment.DeploymentDescriptor
Name | Type | Value | Description |
---|---|---|---|
target | Object | org.exoplatform.services.deployment.DeploymentDescriptor$Target (*) | The target node which will contain the imported node. |
sourcePath | string | war:/conf/sample-portal/wcm/artifacts/site-resources/acme/Logo.xml< | The absolute path of the XML file. |
cleanupPublication | boolean | false |
Decide when the publication lifecycle is cleaned up in the target folder after importing the data. true: allow false:not allow |
versionHistoryPath | string | war:/conf/sample-portal/wcm/artifacts/site-resources/acme/Logo_versionHistory.zip< | The absolute path of the version history file. |
Object type: org.exoplatform.services.deployment.DeploymentDescriptor$Target
Field | Type | Value | Description |
---|---|---|---|
repository | string | repository | The repository name of the target node. |
workspace | string | collaboration | The collaboration name of the target node. |
nodePath | string | /sites content/live/acme/web contents/site artifacts | The path of the target node. |
To expose WCM drives to the CMIS repositories, you must make a special extension of CmisRegistry.
To make a typical component org.exoplatform.ecms.xcmis.sp.jcr.exo.DriveCmisRegistry, do as follows:
<component>
<type>org.exoplatform.ecms.xcmis.sp.jcr.exo.DriveCmisRegistry</type>
<init-params>
<!-- Disabled by default. Uncomment if you need query support in CMIS. -->
<!-- value-param>
<name>indexDir</name>
<value>${gatein.jcr.index.data.dir}/cmis-index${container.name.suffix}</value>
</value-param-->
<value-param>
<name>exo.cmis.renditions.persistent</name>
<value>true</value>
</value-param>
<values-param>
<name>renditionProviders</name>
<description>Redition providers classes.</description>
<!-- <value>org.xcmis.renditions.impl.PDFDocumentRenditionProvider</value> -->
<value>org.xcmis.renditions.impl.ImageRenditionProvider</value>
</values-param>
</init-params>
</component>
Where configuration parameters include:
indexDir: the directory where the lucene index will be placed. It is disabled by default.
exo.cmis.renditions.persistent: indicates if a rendition of the document (thumbnails) should be persisted in the JCR. The allowed value are true or false.
renditionProviders: a set of FQN of classes which can be used as Rendition Providers. Classes which implement the org.xcmis.spi.RenditionProvider interface used to preview the CMIS objects (thumbnails).
In most cases, it is not required to change anything in the xCIMIS configuration. In case of any change of the indexer storage location, do not comment the indexDir value parameter and point it to the actual location.
The following configuration is mandatory for JCR to work correctly:
<external-component-plugins>
<target-component>org.exoplatform.services.jcr.RepositoryService</target-component>
<component-plugin>
<name>add.namespaces</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.jcr.impl.AddNamespacesPlugin</type>
<init-params>
<properties-param>
<name>namespaces</name>
<property name="cmis" value="http://www.exoplatform.com/jcr/cmis/1.0"/>
<property name="xcmis" value="http://www.exoplatform.com/jcr/xcmis/1.0"/>
</properties-param>
</init-params>
</component-plugin>
<component-plugin>
<name>add.nodeType</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.jcr.impl.AddNodeTypePlugin</type>
<init-params>
<values-param>
<name>autoCreatedInNewRepository</name>
<description>Node types configuration file</description>
<value>jar:/conf/cmis-nodetypes-config.xml</value>
</values-param>
</init-params>
</component-plugin>
</external-component-plugins>
An authenticator is responsible for creating Identity Security Service Authenticator.
The eXo CMIS service is based on:
The authentication mechanism provided by the eXo organization service.
The JAAS configuration of eXo Platform. For example:
gatein-domain { org.exoplatform.web.security.PortalLoginModule required; org.exoplatform.services.security.jaas.SharedStateLoginModule required; org.exoplatform.services.security.j2ee.TomcatLoginModule required; };
The CMIS standard defines a query language based on a subset of the SQL-92 grammar (ISO/IEC 9075: 1992 -- Database Language SQL), with a few extensions to enhance its filtering capability for the CMIS data model, such as existential quantification for multi-valued property, full-text search, and folder membership.
CMIS search is disabled by default in eXo CMIS. Uncomment the indexDir parameter if you need the query support in CMIS. To discover the search capability, check the capabilityQuery property (see the table below).
The relational view of a CMIS repository consists of a collection of virtual tables that are defined on the top of the CMIS data model. A virtual table exists for every queryable object type (content type if you prefer) in the repository. Each row in these virtual tables corresponds to an instance of the corresponding object type (or one of its subtypes). A column exists for every property that the object type has.
Capability | Value |
---|---|
capabilityQuery | bothcombined (if indexDir is configured, otherwise none ) |
capabilityJoin | none |
capabilityPWCSearchable | false |
capabilityAllVersionsSearchable | false |
To be able to provide full-text search capabilities, xCMIS uses its own index. The following is the configuration parameter:
Parameter | Default | Description |
---|---|---|
indexDir | none | The location of the index directory. This parameter is mandatory for the default implementation. |
This parameter is passed through the XML configuration.
For example, to set up the index directory:
<component>
<type>org.exoplatform.ecms.xcmis.sp.DriveCmisRegistry</type>
<init-params>
<!-- Disabled by default. Uncomment if you need query support in CMIS. -->
<!-- value-param>
<name>indexDir</name>
<value>${gatein.jcr.index.data.dir}/cmis-index${container.name.suffix}</value>
</value-param-->
..............
</init-params>
</component>
Write-ahead logging
To be able to provide index consistency and recovery in case of unexpected crashes or damages, XCMIS uses write-ahead logging (WAL) technique. Write-ahead logging is a standard approach to transaction logging. Briefly, WAL's center concept is changes of data files (indexes) must be written only after those changes have been logged, that is, when the change log records have been flushed to permanent storage. If you follow this procedure, you do not need to flush data pages to disk on every transaction commit, because it is known in the event of a crash, and the index can be recovered by using the log: any changes that have not been applied to the data pages can be redone from the log records. (This is roll-forward recovery, also known as REDO.)
A major benefit of using WAL is a significantly reduced number of disk writes, because only the log file needs to be flushed to disk at the time of transaction commit, rather than every data file changed by the transaction.
Recover uncommitted transaction
When you start Indexer, it will check uncommitted transaction logs. If at least one log exists, recovering process will be started. Indexer will read all logs and extract added, updated and removed UUIDs into a set. Then, indexer walks through this set and checks objects against UUID. If the object exists, the indexer will put it into the added document list. In other cases, UUID will be added to the removed documents list. After that, depending on the list of added and removed documents, changes will be applied to the index.
Initial index population
When you run the indexer to check the number of documents in the index. If there are no documents in the index or the previous re-indexation was not successful, then re-indexation of all content will be started. The first step is cleaning old index data. Uncommitted transaction logs and old persistent data are removed. These data are useless, because re-indexation of all content will be started. Then indexer walks throw all objects and makes lucene document for each one. Then batches with less than 100 elements will be saved to the index. After re-indexation, all logs (WAL) will be removed, all data mentioned on these change logs are already indexed.
If the administrator gets an exception with the message "Can't remove reindex flag.", it means that the index restoring was finished but file-flag was not removed (see index directory, file named as "reindexProcessing"). You can manually remove this file-flag, and avoid a new reindex of repository on the JCR start.
This chapter supplies you with the basic knowledge about templates, UI extension, APIs in Content. Through it, you can build your own content. Also, with the step-by-step guides, you can create UI extension, deploy a workflow in Content and do many different actions.
This chapter consists of the main following contents:
Overview
The templates are applied to a node type or a metadata mixin type. There are two types of templates:
Dialogs: are in the HTML form that allows creating node instances.
Views: are in the HTML fragments which are used to display nodes.
From the ECM admin portlet, the Manage Template lists existing node types associated to Dialog and/or View templates. These templates can be attached to permissions (in the usual membership:group form), so that a specific one is displayed according to the rights of the user (very useful in a content validation workflow activity).
Document Type
The checkbox defines if the node type should be considered as the Document type or not. Sites Explorer considers such nodes as user content and applies the following behavior:
View template will be used to display the document type nodes.
Document types nodes can be created by the 'Add Document' action.
Non-document types are hidden (unless the 'Show non document types' option is checked).
Templates are written by using Groovy Templates that requires some experiences with JCR API and HTML notions.
Dialogs are Groovy templates that generate forms by mixing static HTML fragments and Groovy calls to the components responsible for building the UI at runtime. The result is a simple but powerful syntax.
These following parameters are common and can be used for all input fields.
Parameter | Type | Required | Example | Description |
---|---|---|---|---|
jcrPath |
string
|
![]() |
jcrPath=/node/exo:title
| The relative path inside the current node. |
mixintype |
string with the commas (,) character. |
![]() |
| The list of mixin types you want to initialize when creating the content. |
validate |
string with the comma (,) character |
![]() |
| The list of validators you want to apply to the input. Possible values are: name, email, number, empty, null, datetime, length OR validator classes. To know how to pass parameters to validators, refer here |
editable |
string
|
![]() |
editable=if-null
| The input will be editable only if the value of this parameter is if-null and the value of this input is null or blank. |
multiValues |
boolean
|
![]() |
multiValues=true
| Show a multi-valued component if true and must be used only with corresponding multi-valued properties. The default value of this parameter is false. |
visible |
boolean
|
![]() |
visible=true
| The input is visible if this value is true. |
options |
String separated by the commas (,) character. |
![]() | A list of parameters which are input while the content templates are initialized. |
"options=toolbar:CompleteWCM,height:'410px',noSanitization" |
"name" validator:
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=name", "editable=if-null"];
uicomponent.addTextField("title", webContentFieldTitle) ;
"email" validator:
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=email", "editable=if-null"];
uicomponent.addTextField("title", webContentFieldTitle) ;
"number" validator:
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=number", "editable=if-null"];
uicomponent.addTextField("title", webContentFieldTitle) ;
"empty" validator:
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=empty", "editable=if-null"];
uicomponent.addTextField("title", webContentFieldTitle) ;
"null" validator:
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=null", "editable=if-null"];
uicomponent.addTextField("title", webContentFieldTitle) ;
"datetime" validator:
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=datetime", "editable=if-null"];
uicomponent.addTextField("title", webContentFieldTitle) ;
"length" validator:
For a maximum length of 50 characters:
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=empty,length(50;int)", "editable=if-null"];
uicomponent.addTextField("title", webContentFieldTitle) ;
For a minimum length of 6 characters and maximum length of 50 characters:
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=empty,length(6;50;int)", "editable=if-null"];
uicomponent.addTextField("title", webContentFieldTitle) ;
See also
The mixintype can be used only in the root node field (commonly known as the name field).
See also: Common parameters
<%
String[] fieldTitle = ["jcrPath=/node/exo:title", "validate=empty"] ;
uicomponent.addTextField("title", fieldTitle) ;
%>
See also: Common parameters
String[] hiddenField5 = ["jcrPath=/node/jcr:content/dc:date", "visible=false"];
uicomponent.addCalendarField("hiddenInput5", hiddenField5);
Parameter | Type | Required | Description | Example |
---|---|---|---|---|
rows | Number | ![]() | The initial text area's number of rows. The value is 10 by default. | rows=20 |
cols | Number | ![]() | The initial text area's number of cols. The value is 30 by default . | cols=50 |
See also: Common parameters
<%
String[] fieldDescription = ["jcrPath=/node/exo:description", "validate=empty"] ;
uicomponent.addTextAreaField("description", fieldDescription) ;
%>
Parameter | Type | Required | Description | Example |
---|---|---|---|---|
options |
string with the semicolon (;) character |
![]() | Some options for CKEditor field: toolbar, width and height. |
options=CompleteWCM;width:'100%';height:'200px';
|
toolbar |
string
|
![]() | The predefined toolbar for CKEditor. The value can be: Default , Basic , CompleteWCM , BasicWCM , SuperBasicWCM . |
options=CompleteWCM
|
width |
string
|
![]() | The width of CKEditor. Its value can be the percent of pixel. |
options=width:'100%'
|
height |
string
|
![]() | The height of CKEditor. Its value can be the percent of pixel. |
options=height:'200px'
|
See also: Common parameters
<%
String[] fieldSummary = ["jcrPath=/node/exo:summary", "options=toolbar:CompleteWCM,width:'100%',height:'200px'", "validate=empty"] ;
uicomponent.addRichtextField("summary", fieldSummary) ;
%>
Parameter | Type | Required | Description | Example |
---|---|---|---|---|
options | string | ![]() | An option for the calendar field: Display time. | options=displaytime |
See also: Common parameters
<%
String[] fieldPublishedDate = ["jcrPath=/node/exo:publishedDate", "options=displaytime", "validate=datetime", "visible=true"] ;
uicomponent.addCalendarField("publishedDate", fieldPublishedDate) ;
%>
See also: Common parameters
When you create an upload form, you can store an image by two main ways:
If you want to store the image as a property, use the following code:
<%
String[] fieldMedia = ["jcrPath=/node/exo:image"] ;
uicomponent.addUploadField("media", fieldMedia) ;
%>
If you want to store the image as a node, use the following code:
<%
String[] hiddenField1 = ["jcrPath=/node/exo:image", "nodetype=nt:resource", "visible=false"] ;
String[] hiddenField2 = ["jcrPath=/node/exo:image/jcr:encoding", "visible=false", "UTF-8"] ;
String[] hiddenField3 = ["jcrPath=/node/exo:image/jcr:lastModified", "visible=false"] ;
uicomponent.addHiddenField("hiddenInput1", hiddenField1) ;
uicomponent.addHiddenField("hiddenInput2", hiddenField2) ;
uicomponent.addHiddenField("hiddenInput3", hiddenField3) ;
String[] fieldMedia = ["jcrPath=/node/exo:image"] ;
uicomponent.addUploadField("media", fieldMedia) ;
%>
But, this code is not complete. If you want to display the upload field, the image must be blank, otherwise you can display the image and an action enables you to remove it. You can do as follows:
<%
def image = "image";
// If you're trying to edit the document
if(uicomponent.isEditing()) {
def curNode = uicomponent.getNode();
// If the image existed
if (curNode.hasNode("exo:image")) {
def imageNode = curNode.getNode("exo:image") ;
// If the image existed and available
if (imageNode.getProperty("jcr:data").getStream().available() > 0 && (uicomponent.findComponentById(image) == null)) {
def imgSrc = uicomponent.getImage(curNode, "exo:image");
def actionLink = uicomponent.event("RemoveData", "/exo:image");
%>
<div>
<img src="$imgSrc" width="100px" height="80px"/>
<a href="$actionLink">
<img src="/eXoResources/skin/DefaultSkin/background/Blank.gif" alt="" class="ActionIcon Remove16x16Icon"/>
</a>
</div>
<%
} else {
String[] fieldImage = ["jcrPath=/node/exo:image/jcr:data"] ;
uicomponent.addUploadField(image, fieldImage) ;
}
} else {
String[] fieldImage = ["jcrPath=/node/exo:image/jcr:data"] ;
uicomponent.addUploadField(image, fieldImage) ;
}
} else if(uicomponent.dataRemoved()) {
String[] fieldImage = ["jcrPath=/node/exo:image/jcr:data"] ;
uicomponent.addUploadField(image, fieldImage) ;
} else {
String[] fieldImage = ["jcrPath=/node/exo:image/jcr:data"] ;
uicomponent.addUploadField(image, fieldImage) ;
}
%>
To have multiple upload fields, you just add the multiValues=true parameter to fieldProperty in dialog1.gtmpl:
# Multi upload
fieldProperty = ["jcrPath=/node/exo:value", "multiValues=true"];
uicomponent.addUploadField("/node/exo_value", fieldProperty);
In this case, you must be sure that the node type definition of the document you are currently editing should allow the document to have a child node named 'exo:value' whose node type is 'nt:unstructured'. All uploaded files of this upload component are stored in this 'exo:value' child node.
Parameter | Type | Required | Description | Example |
---|---|---|---|---|
options | string with the comma (,) characters | ![]() | Some radio values. | options=radio1,radio2,radio3 |
See also: Common parameters
<%
String[] fieldDeep = ["jcrPath=/node/exo:isDeep", "defaultValues=true", "options=radio1,radio2,radio3"];
uicomponent.addRadioBoxField("isDeep", fieldDeep);
%>
Parameter | Type | Required | Description | Example |
---|---|---|---|---|
options | string with the comma (,) characters | ![]() | Some option values. | options=option1,option2,option3 |
See also: Common parameters
<%
String[] fieldDeep = ["jcrPath=/node/exo:isDeep", "defaultValues=true", "options=checkbox1,checkbox2,checkbox3"];
uicomponent.addCheckBoxField("isDeep", fieldDeep);
%>
Parameter | Type | Required | Description | Example |
---|---|---|---|---|
options | string with the comma (,) characters | ![]() | Some checkbox values. | options=checkbox1,checkbox2,checkbox3 |
See also: Common parameters
<%
String[] fieldDeep = ["jcrPath=/node/exo:isDeep", "defaultValues=true", "options=checkbox1,checkbox2,checkbox3"];
uicomponent.addCheckBoxField("isDeep", fieldDeep);
%>
See also: Common parameters
<%
String[] fieldId = ["jcrPath=/node", "editable=false", "visible=if-not-null"] ;
uicomponent.addMixinField("id", fieldId) ;
%>
Parameter | Type | Required | Description | Example |
---|---|---|---|---|
selectorClass | string | ![]() | The component to display. | selectorClass=org.exoplatform.ecm.webui.tree.selectone.UIOneNodePathSelector |
selectorIcon | string | ![]() | The action icon. | selectorIcon=SelectPath24x24Icon |
Depending on the selectorClass
, some other parameters can be added.
For example, the component org.exoplatform.ecm.webui.tree.selectone.UIOneNodePathSelector
needs the following parameter:
Parameter | Type | Required | Description | Example |
---|---|---|---|---|
workspaceField | string | ![]() | The field which enables you to select a workspace. | workspaceField=targetWorkspace |
The component org.exoplatform.ecm.webui.selector.UIPermissionSelector
does not need any special parameters.
See also: Common parameters
<%
String[] fieldPath = ["jcrPath=/node/exo:targetPath", "selectorClass=org.exoplatform.ecm.webui.tree.selectone.UIOneNodePathSelector", "workspaceField=targetWorkspace", "selectorIcon=SelectPath24x24Icon"] ;
uicomponent.addActionField("targetPath", fieldPath) ;
%>
To add an interceptor to a dialog, you can use this method
uicomponent.addInterceptor(String scriptPath, String type)
Parameters | Type | Description |
---|---|---|
scriptPath | string | The relative path to the script file. |
type | string | The type of interceptor: prev or post . |
<%
uicomponent.addInterceptor("ecm-explorer/interceptor/PreNodeSaveInterceptor.groovy", "prev");
%>
To avoid refreshing the first tab for every action execution, add a new private function to the template with tabs. In the template, you must insert a new piece of code like the following:
private String getDisplayTab(String selectedTab) {
if ((uicomponent.getSelectedTab() == null && selectedTab.equals("mainWebcontent"))
|| selectedTab.equals(uicomponent.getSelectedTab())) {
return "display:block";
}
return "display:none";
}
private String getSelectedTab(String selectedTab) {
if (getDisplayTab(selectedTab).equals("display:block")) {
return "SelectedTab";
}
return "NormalTab";
}
Changing in every event of onClick must be done like the following:
<div class="UITab NormalTabStyle"> <div class="<%=getSelectedTab("mainWebcontent")%> "> <div class="LeftTab"> <div class="RightTab"> <div class="MiddleTab" onClick="<%=uicomponent.event("ChangeTab", "mainWebcontent")%>"><%=_ctx.appRes("WebContent.dialog.label.MainContent")%></div> </div> </div> </div> </div> <div class="UITab NormalTabStyle"> <div class="<%=getSelectedTab("illustrationWebcontent")%> "> <div class="LeftTab"> <div class="RightTab"> <div class="MiddleTab" onClick="<%=uicomponent.event("ChangeTab", "illustrationWebcontent")%>"><%=_ctx.appRes("WebContent.dialog.label.Illustration")%></div> </div> </div> </div> </div> <div class="UITab NormalTabStyle"> <div class="<%= getSelectedTab("contentCSSWebcontent")%> "> <div class="LeftTab"> <div class="RightTab"> <div class="MiddleTab" onClick="<%=uicomponent.event("ChangeTab", "contentCSSWebcontent")%>"><%=_ctx.appRes("WebContent.dialog.label.Advanced")%></div> </div> </div> </div> </div>
Finally, to display the selected tab, simply add it to the style of UITabContent class.
<div class="UITabContent" style="<%=getDisplayTab("mainWebcontent")%>">
In the content management sytem, its typical feature is enabling JavaScript in a content. This causes the XSS (Cross-site Scripting) attacks to the content displayed in the HTML format.
However, there is no solution to keep JavaScript and to prevent the XSS attacks at the same time, so Content allows you to decide whether JavaScript is allowed to run on a field of the content template or not by using the option
parameter.
To allow JavaScript to execute, add "options = noSanitization
" to the dialog template file. Normally, this file is named dialog1.gtmpl
.
For example: The following code shows how to enable JavaScript in the Main Content field of the Free Layout Wecontent content:
String [] htmlArguments = ["jcrPath = / node / default.html / JCR: content / JCR: data", "options = toolbar: CompleteWCM, height: '410px ', noSanitization" htmlContent];
By default, there is no "options = noSanitization
" parameter in the dialog template file and this helps you prevent the XSS attacks. When end-users input JavaScript into a content, the JavaScript is automatically deleted when the content is saved.
The following is a sample code of the View template of a content node:
Get a content node to display:
<%
def node = uicomponent.getNode() ;
def originalNode = uicomponent.getOriginalNode()
%>
Display the name of the content node:
<%=node.getName()%>
Display the exo:title property of the content node:
<%
if(node.hasProperty("exo:title")) {
%>
<%=node.getProperty("exo:title").getString()%>
<%
}
%>
Display the exo:date property of the content node in a desired format. For example: "MM DD YYYY" or "YYYY MM DD".
<%
import java.text.SimpleDateFormat ;
SimpleDateFormat dateFormat = new SimpleDateFormat() ;
%>
...
<%
if(node.hasProperty("exo:date")) {
dateFormat.applyPattern("MMMMM dd yyyy") ;
%>
<%=dateFormat.format(node.getProperty("exo:date").getDate().getTime())%>
<%
}
%>
Display the translation of the Sample.view.label.node-name message in different lanaguages.
<%=_ctx.appRes("Sample.view.label.node-name")%>
The Content List Template allows you to view the content list with various templates. eXo Platform supports the following content list templates:
Template | Description |
---|---|
BigHotNewsTemplateCLV.gtmpl | Display contents under one column with a content list. The illustration of each content is displayed above the content. |
ContentListViewerDefault.gtmpl | Its function is similar to BigHotNewsTemplateCLV.gtmpl. The illustration of each content is bigger. |
DocumentsTemplate.gtmpl | Display contents under a content list with a NodeType icon or the illustration on the left of the corresponding content. |
EventsTemplateCLV.gtmpl | Its function is similar to BigHotNewsTemplateCLV.gtmpl, but the illustration of each content is smaller. |
OneColumnCLVTemplate.gtmpl | Display contents under one column. The illustration of each content is displayed on its left. |
TwoColumnsCLVTemplate.gtmpl | Display contents under two columns. The illustration of each content is displayed on its left. |
UIContentListPresentationBigImage.gtmpl | Its function is similar to BigHotNewsTemplateCLV.gtmpl, but the illustration of each content is bigger than the image displayed with ContentListViewerDefault.gtmpl and the text font is different. |
UIContentListPresentationDefault.gtmpl | Its function is similar to BigHotNewsTemplateCLV.gtmpl, but the illustration of each content is smaller and the text font is different. |
UIContentListPresentationSmall.gtmpl | Display contents under one column with a content list. The images are displayed on the left of the corresponding content and smaller than the images of the other templates. |
By using WCM, all the stylesheets of each site can be managed online easily. You do not need to access the file system to modify and wait until the server has been restarted. For the structure, each site has its own CSS folder which can contain one or more CSS files. These CSS files have the data, and the priority. If they have the same CSS definition, the higher priority will be applied. You can also disable some of them to make sure the disabled style will no longer be applied into the site.
For example, a WCM demo package has two sites by default: ACME and Classic. The Classic site has a CSS folder which contains a CSS file called DefaultStylesheet. Most of the stylesheets of this site are defined within this stylesheet. Moreover, the ACME site has two CSS files called BlueStylesheet and GreenStylesheet. The blue one is enabled and the green one is disabled by default. All you need to test is to disable the blue one (by editing it and setting Available to 'false') and enable the green one. Now, back to the homepage and see the magic.
Remember the cache and refresh the browser first if you do not see any changes. Normally, this is the main reason why the new style is not applied.
Basically, if you want to add a rich text area to your dialogs, you can use the addRichtextField method. However, in case you want to add the rich text editor manually, you first need to use the addTextAreaField method and some additional Javascripts as shown below:
<%
String[] fieldDescription = ["jcrPath=/node/exo:description"] ;
uicomponent.addTextAreaField("description", fieldDescription)
%>
<script>
var instances = CKEDITOR.instances['description'];
if (instances) instances.destroy(true);
CKEDITOR.replace('description', {
toolbar : 'CompleteWCM',
uiColor : '#9AB8F3'
});
</script>
REST-style architectures consist of clients and servers. Clients initiate requests to servers; servers process requests and return appropriate responses. Requests and responses are built around the transfer of "representations" of "resources". A resource can be essentially any coherent and meaningful concept that may be addressed. A representation of a resource is typically a document that captures the current or intended state of a resource.
At any particular time, a client can either be in transition between application states or "at rest". A client in a REST state is able to interact with its users, but creates no load and consumes no per-client storage on the set of servers or on the network.
The client begins sending requests when it is ready to make the transition to a new state. While one or more requests are outstanding, the client is considered to be in transition. The representation of each application state contains links that may be used the next time, the client chooses to initiate a new state transition.
REST is initially described in the context of HTTP, but is not limited to that protocol. RESTful architectures can be based on other Application Layer protocols if they already provide a rich and uniform vocabulary for applications based on the transfer of meaningful representational state. RESTful applications maximize the use of the pre-existing, well-defined interface and other built-in capabilities provided by the chosen network protocol, and minimize the addition of new application-specific features on its top.
This section provides you the following topics:
Here is the convention you should follow:
Method | Definition |
---|---|
GET | Get a Resource. Its state should not be modified. |
POST | Create a Resource (or anything that does not fit elsewhere). |
PUT | Update a Resource. |
DELETE | Delete a Resource. |
The followings are formats which need to be supported for all your APIs:
The default format is JSON.
The response format can be specified by a parameter in the request: "format". You need to specify the format requested.
First, you need to register the REST service class to the configuration file in the package named conf.portal.
<configuration xmlns="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd http://www.exoplaform.org/xml/ns/kernel_1_1.xsd">
<component>
<type>org.exoplatform.services.ecm.publication.REST.presentation.document.publication.PublicationGetDocumentRESTService</type>
</component>
</configuration>
You can start creating GetEditedDocumentRESTService that implements from the ResourceContainer interface as follows:
@Path("/presentation/document/edit/")
public class GetEditedDocumentRESTService implements ResourceContainer {
@Path("/{repository}/")
@GET
public Response getLastEditedDoc(@PathParam("repository") String repository,
@QueryParam("showItems") String showItems) throws Exception {
........
}
}
Parameters | Definition |
---|---|
@Path("/presentation/document/edit/") | Specify the URI path which a resource or class method will serve requests for. |
@PathParam("repository") | Bind the value repository of a URI parameter or a path segment containing the template parameter to a resource method parameter, resource class field, or resource class bean property. |
@QueryParam("showItems") | Bind the value showItems of a HTTP query parameter to a resource method parameter, resource class field, or resource class bean property. |
In Content, it is possible to extend the Sites Explorer and the ECM Administration with the UI Extension Framework. Indeed, you can add your own action buttons to the Sites Explorer and/or add your own managers to the ECM Administration. This section shows you how to create a sample UI extension via adding your own tab to ECM Administration.
To add your own UIAction, do as follows:
1. Create a pom.xml file with the following content:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.exoplatform.ecms</groupId>
<artifactId>exo-ecms-examples-uiextension-framework</artifactId>
<version>2.2.0-SNAPSHOT</version>
</parent>
<artifactId>exo-ecms-examples-uiextension-framework-manage-wcm-cache</artifactId>
<name>eXo WCM Cache Examples</name>
<description>eXo WCM Cache Examples</description>
<dependencies>
<dependency>
<groupId>org.exoplatform.kernel</groupId>
<artifactId>exo.kernel.container</artifactId>
<version>2.3.8-GA-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.commons</groupId>
<artifactId>exo.platform.commons.webui.ext</artifactId>
<version>1.1.9-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.ecms</groupId>
<artifactId>exo-ecms-core-webui</artifactId>
<version>2.3.8-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.ecms</groupId>
<artifactId>exo-ecms-core-webui-administration</artifactId>
<version>2.3.8-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.jar</include>
<include>**/*.pom</include>
<include>**/*.conf</include>
<include>**/*.gtmpl</include>
<include>**/*.gif</include>
<include>**/*.jpg</include>
<include>**/*.png</include>
</includes>
</resource>
</resources>
</build>
</project>
2. Create the src/main/java directory and start launching mvn eclipse:eclipse. Then, you can launch your eclipse and import this new project.
3. Create a new class called org.exoplatform.wcm.component.cache.UIWCMCacheComponent that extends org.exoplatform.ecm.webui.component.admin.manager.UIAbstractManagerComponent.
With the Webui framework, you will be notified if any given action is triggered. You just need to call your own action listener ($ACTIONNAME) ActionListener. For example, to create your own action listener for CacheView, do as follows:
1. Call CacheViewActionListener.
2. Add a static inner class called CacheViewActionListener that extends org.exoplatform.ecm.webui.component.admin.listener.UIECMAdminControlPanelActionListener.
You will see the expected code below:
public class CacheViewComponent extends UIAbstractManagerComponent {
public static class CacheViewActionListener extends UIECMAdminControlPanelActionListener
<UIWCMCacheComponent>{
public void processEvent(Event
<UIWCMCacheComponent>event) throws Exception {
UIECMAdminPortlet portlet = event.getSource().getAncestorOfType(UIECMAdminPortlet.class);
UIECMAdminWorkingArea uiWorkingArea = portlet.getChild(UIECMAdminWorkingArea.class);
uiWorkingArea.setChild(UIWCMCachePanel.class) ;
event.getRequestContext().addUIComponentToUpdateByAjax(uiWorkingArea);
}
}
}
3. Create the src/main/java directory and launch mvn eclipse:eclipse. You can then launch your eclipse and import this new project.
4. Create a new configuration file called conf/portal/configuration.xml to register your action (see Register your UI Action) with the org.exoplatform.webui.ext.UIExtensionManager service.
To register your UI Action, do as follows:
1. Create the code:
<configuration xmlns="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd http://www.exoplaform.org/xml/ns/kernel_1_1.xsd">
<external-component-plugins>
<target-component>org.exoplatform.webui.ext.UIExtensionManager</target-component>
<component-plugin>
<name>Add.Actions</name>
<set-method>registerUIExtensionPlugin</set-method>
<type>org.exoplatform.webui.ext.UIExtensionPlugin</type>
<init-params>
<object-param>
<name>CacheView</name>
<object type="org.exoplatform.webui.ext.UIExtension">
<field name="type">
<string>org.exoplatform.ecm.dms.UIECMAdminControlPanel</string>
</field>
<field name="name">
<string>CacheView</string>
</field>
<field name="category">
<string>GlobalAdministration</string>
</field>
<field name="component">
<string>org.exoplatform.wcm.component.cache.UIWCMCacheComponent</string>
</field>
</object>
</object-param>
<object-param>
<name>UIWCMCacheManager</name>
<object type="org.exoplatform.webui.ext.UIExtension">
<field name="type">
<string>org.exoplatform.ecm.dms.UIECMAdminControlPanel</string>
</field>
<field name="name">
<string>UIWCMCacheManager</string>
</field>
<field name="category">
<string>GlobalAdministration</string>
</field>
<field name="component">
<string>org.exoplatform.wcm.manager.cache.UIWCMCacheManagerComponent</string>
</field>
<field name="extendedFilters">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.webui.ext.filter.impl.UserACLFilter">
<field name="permissions">
<collection item-type="java.lang.String" type="java.util.ArrayList">
<value>
<string>*:/platform/administrators</string>
</value>
</collection>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
</configuration>
With this configuration, only the users with the *:/platform/administrators membership have the right to access the CacheView item.
2. Launch mvn clean install.
All resources can be located in the src/main/resource package because the resources (*.xml, images, conf file) and the code are separated. This is very useful in a hierarchical structure.
Create ExamplePortlet_en.xml with the following content and add it to the src/main/resource package:
<bundle>
<!-- ################################################################################ # org.exoplatform.wcm.component.cache.UIWCMCacheForm
# ################################################################################ -->
<UIWCMCacheForm>
<action>
<Cancel>Cancel</Cancel>
<Save>Save</Save>
<Clear>Clear the cache</Clear>
</action>
<label>
<maxsize>Max size :</maxsize>
<livetime>Live time in sec :</livetime>
<isCacheEnable>Cache enabled(should always be on production enviroment)</isCacheEnable>
<hit>Hit count :</hit>
<currentSize>Current size</currentSize>
<miss>Miss count :</miss>
</label>
</UIWCMCacheForm>
<!-- ################################################################################ # org.exoplatform.wcm.manager.cache.UIWCMCacheManagerForm
# ################################################################################ -->
<UIWCMCacheManagerForm>
<action>
<Cancel>Cancel</Cancel>
<Save>Save</Save>
<Clear>Clear the cache</Clear>
</action>
<label>
<cacheModify>Cache to modify :</cacheModify>
<maxsize>Max size :</maxsize>
<livetime>Live time in sec :</livetime>
<isCacheEnable>Cache enabled(should always be on production enviroment)</isCacheEnable>
<hit>Hit count :</hit>
<currentSize>Current size</currentSize>
<miss>Miss count :</miss>
</label>
</UIWCMCacheManagerForm>
<UIECMAdminControlPanel>
<tab>
<label>
<GlobalAdministration>Global Administration</GlobalAdministration>
</label>
</tab>
<label>
<UIWCMCache>WCM Cache</UIWCMCache>
<UIWCMCachePanel>WCM Cache Administration</UIWCMCachePanel>
<UIWCMCacheManager>Managing Caches</UIWCMCacheManager>
<UIWCMCacheManagerPanel>WCM Cache Management</UIWCMCacheManagerPanel>
</label>
</UIECMAdminControlPanel>
</bundle>
You must add the following content to configuration.xml to register the resource bundle.
By being added this configuration, the resource bundle has been completely separated from the original system. This is clearly useful for you to get an independent plugin.
<external-component-plugins>
<!-- The full qualified name of the ResourceBundleService -->
<target-component>org.exoplatform.services.resources.ResourceBundleService</target-component>
<component-plugin>
<!-- The name of the plugin -->
<name>ResourceBundle Plugin</name>
<!-- The name of the method to call on the ResourceBundleService in order to register the ResourceBundles -->
<set-method>addResourceBundle</set-method>
<!-- The full qualified name of the BaseResourceBundlePlugin -->
<type>org.exoplatform.services.resources.impl.BaseResourceBundlePlugin</type>
<init-params>
<values-param>
<name>init.resources</name>
<description>Store the following resources into the db for the first launch</description>
<value>locale.portlet.cache.ExamplePortlet</value>
</values-param>
<values-param>
<name>portal.resource.names</name>
<description>The properties files of the portal , those file will be merged
into one ResoruceBundle properties
</description>
<value>locale.portlet.cache.ExamplePortlet</value>
</values-param>
</init-params>
</component-plugin>
</external-component-plugins>
Publication add-ons for Content.
This section covers the following topics:
This extended publication has new states and new profiles that are enabled in Content.
Profiles
Author: This profile can edit a content and mark this content as redacted.
Approver: This profile approves a pending content (marked by the Author).
Publisher: This profile publishes contents or marks them as "Ready for publication" in multi-server mode.
Archiver: An administrative profile which moves contents to an archive storage.
States
enrolled: It is a pure technical state, generally used for content creation.
draft (Author): Content is in editing phase.
pending (Author): The author validates the content.
approved (Approver): A content is approved by the manager.
inreview (Manager): This state can be used when a second approval state is needed (for i18 translation for example).
staged (Publisher): A content is ready for publication (multi-server mode).
published (Publisher or Automatic): A content is published and visible in the Live mode.
unpublished (Publisher or Automatic): A content is not visible in the Live mode.
obsolete: A content can still be published but it is not in an editing lifecycle anymore.
archived (Automatic): A content is archived and ready to be moved in the archive workspace if enabled.
In most cases, you do not want to publish a content directly, but at a defined date and you can also want the content to be unpublished automatically after that. New properties are added to the new publication plugin, that allows you to manage this:
publication:startPublishedDate_
publication:endPublishedDate_
The Content rendering engine does not know anything about publication dates, so another service needs to manage that. When the publisher sets start/end publication dates, he can "stage" the content. The content will go automatically to the "published" state when the start date arrives and to the "unpublished" state after end date. A cron job checks every hour (or less) all contents which need to be published (the start date in the past and the "staged" state) or unpublished (the end date in the past and the "published" state).
Thus, the publication dates are not mandatory and a content can go to:
Staged: in multi-server mode, the publisher can only put the content to the "staged" state and wait for auto-publication.
Published: in single-server mode, the publisher can directly publish a content (with or without publication dates).
<nodeType hasOrderableChildNodes="false" isMixin="true" name="publication:authoringPublication" primaryItemName="">
<supertypes>
<supertype>publication:stateAndVersionBasedPublication</supertype>
</supertypes>
<propertyDefinitions>
<propertyDefinition autoCreated="false" mandatory="true" multiple="false" name="publication:startPublishedDate" onParentVersion="IGNORE" protected="false" requiredType="Date">
<valueConstraints/>
</propertyDefinition>
<propertyDefinition autoCreated="false" mandatory="true" multiple="false" name="publication:endPublishedDate" onParentVersion="IGNORE" protected="false" requiredType="Date">
<valueConstraints/>
</propertyDefinition>
</propertyDefinitions>
</nodeType>
Note that some labels containing special or non-ASCII characters could not be well displayed in the publication UI. You can extend the width of the current UI State button by adding:
.UIPublicationPanel .StatusTable .ActiveStatus { width: 75px !important; }
Also, for the publication date inputs, UIPublicationPanel should not initialize the dates to any default value. The publishing and unpublish CRON jobs will do this:
A staged document with null publication start date is published instantly.
A document with null publication end date is published forever.
See the export section for more information about the CRON jobs.
The Publication Manager manages lifecycles and contexts in the Content platform. It allows to manages different lifecycles based on different publication plugin in the platform.
public interface PublicationManager {
public List<Lifecycle> getLifecycles();
public List<Context> getContexts();
public Context getContext(String name);
public Lifecycle getLifecycle(String name);
public List<Lifecycle> getLifecyclesFromUser(String remoteUser, String state);
}
In which:
getLifecycles: returns a list of lifecycles (see below), with lifecycle name, publication plugin involved and possible states.
getContexts: returns a list of context, with name, related Lifecycle and other properties (see below).
getContext: returns a context by its name.
getLifecycle: returns a lifecycle by its name.
getLifecycleFromUser: returns a list of lifecycles in which the user has rights (based on membership property).
A lifecycle is defined by a simple vertical workflow with steps (states) and profiles (membership). Each lifecycle is related to a Publication plugin (compliant with the JBPM or Bonita business processes).
For example: Two lifecycles with/without states
<external-component-plugins>
<target-component>org.exoplatform.services.wcm.publication.PublicationManager</target-component>
<component-plugin>
<name>AddLifecycle</name>
<set-method>addLifecycle</set-method>
<type>org.exoplatform.services.wcm.publication.lifecycles.StatesLifecyclePlugin</type>
<init-params>
<object-param>
<name>lifecyles</name>
<object type="org.exoplatform.services.wcm.publication.lifecycles.impl.LifecyclesConfig">
<field name="lifecycles">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.wcm.publication.lifecycles.impl.LifecyclesConfig$Lifecycle">
<field name="name">
<string>lifecycle1</string>
</field>
<field name="publicationPlugin">
<string>States and versions based publication</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.wcm.publication.lifecycles.impl.LifecyclesConfig$Lifecycle">
<field name="name">
<string>lifecycle2</string>
</field>
<field name="publicationPlugin">
<string>Authoring publication</string>
</field>
<field name="states">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.wcm.publication.lifecycles.impl.LifecyclesConfig$State">
<field name="state">
<string>draft</string>
</field>
<field name="memberships">
<collection type="java.util.ArrayList">
<value>
<string>author:/CA/communicationDG</string>
</value>
<value>
<string>author:/CA/alerteSanitaire</string>
</value>
<value>
<string>author:/CA/alerteInformatique</string>
</value>
<value>
<string>author:/CA/informations</string>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.wcm.publication.lifecycles.impl.LifecyclesConfig$State">
<field name="state">
<string>pending</string>
</field>
<field name="membership">
<string>author:/platform/web-contributors</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.wcm.publication.lifecycles.impl.LifecyclesConfig$State">
<field name="state">
<string>approved</string>
</field>
<field name="membership">
<string>manager:/platform/web-contributors</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.wcm.publication.lifecycles.impl.LifecyclesConfig$State">
<field name="state">
<string>staged</string>
</field>
<field name="membership">
<string>publisher:/platform/web-contributors</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.wcm.publication.lifecycles.impl.LifecyclesConfig$State">
<field name="state">
<string>published</string>
</field>
<field name="membership">
<string>automatic</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.wcm.publication.lifecycles.impl.LifecyclesConfig$Lifecycle">
<field name="name">
<string>lifecycle3</string>
</field>
<field name="publicationPlugin">
<string>Authoring publication</string>
</field>
<field name="states">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.wcm.publication.lifecycles.impl.LifecyclesConfig$State">
<field name="state">
<string>draft</string>
</field>
<field name="membership">
<string>author:/platform/web-contributors</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.wcm.publication.lifecycles.impl.LifecyclesConfig$State">
<field name="state">
<string>published</string>
</field>
<field name="memberships">
<collection type="java.util.ArrayList">
<value>
<string>publisher:/CA/communicationDG</string>
</value>
<value>
<string>publisher:/CA/alerteSanitaire</string>
</value>
<value>
<string>publisher:/CA/alerteInformatique</string>
</value>
<value>
<string>publisher:/CA/informations</string>
</value>
</collection>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In the last example, there are three lifecycles:
Lifecycle 1: Based on StatesAndVersionsPublicationPlugin .
This allows to be backward compliant with older Content releases. If all your site contents are using an existing plugin, you can create a lifecycle for it and it will work.
For new instances, you should use the new plugin with dynamic states capabilities.
Lifecycle 2: Based on AuthoringPublicationPlugin .
Visibility: Define only the "visible" steps. In this example, there is no step for "enrolled". Even if this step exists, it will not be displayed in the UI.
Automatic: Set a step as "automatic". In this mode, the step will be visible in the UI but it will be managed by the system (e.g. a cron job).
Lifecycle 3: Simulates the StatesAndVersionsPublicationPlugin plugin. Note that this simple lifecycle will work in a single server configuration.
When a state is changed, you can broadcast an event to add features. The event could look like this:
listenerService.broadcast(AuthoringPlugin.POST_UPDATE_STATE_EVENT, null, node);
Listener declaration could look like this:
<external-component-plugins>
<target-component>org.exoplatform.services.listener.ListenerService</target-component>
<component-plugin>
<name>PublicationService.event.postUpdateState</name>
<set-method>addListener</set-method>
<type>org.exoplatform.services.wcm.publication.listener.post.PostUpdateStateEventListener</type>
<description>this listener will be called every time a content changes its current state</description>
</component-plugin>
</external-component-plugins>
To perform some tasks when a content's state is updated, you need to create a listener that handles the task and configure it. Following is the general configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.listener.ListenerService</target-component>
<component-plugin>
<name>PublicationService.event.postUpdateState</name>
<set-method>addListener</set-method>
<type>my.package.MyListener</type>
<description>Your listener description</description>
</component-plugin>
</external-component-plugins>
With this configuration, your listener my.package.MyListener will be executed each time a content's state is changed.
For example, eXo provides a listener which automatically sends email notifications about the new state to all users of defined groups: org.exoplatform.wcm.authoring.listener.PostUpdateStateEventListener. So, the configuration will be:
<external-component-plugins>
<target-component>org.exoplatform.services.listener.ListenerService</target-component>
<component-plugin>
<name>PublicationService.event.postUpdateState</name>
<set-method>addListener</set-method>
<type>org.exoplatform.wcm.authoring.listener.PostUpdateStateEventListener</type>
<description>This listener will send a mail when there are changes in a content's state</description>
</component-plugin>
</external-component-plugins>
A context is defined by simple rules. In Content, you can select to enroll the content in a specific lifecycle (for example, publication plugin) based on context parameters. There are three parameters used to define contexts:
Remote User: The current user who can create/edit the content.
Current site name: The site from where the content is created (not the storage but the navigation).
Node: The node which you want to enroll.
From these parameters, you can easily connect and define contexts based on:
Membership: Does the current user have this membership?
Site: On this particular site, you want to enroll contents in a specific lifecycle.
Path: You can enroll contents in the lifecycles based on their path (from the Node).
Type of content: You can enroll contents in the lifecycles based on their nodetype (from the Node).
Because each site has a content storage (categories + physical storage), you can select the right lifecycle for the right storage/site. To avoid conflicts on contexts, you can set a priority (the less is the best).
For example, Different Contexts:
<external-component-plugins>
<target-component>org.exoplatform.services.wcm.publication.PublicationManager</target-component>
<component-plugin>
<name>AddContext</name>
<set-method>addContext</set-method>
<type>org.exoplatform.services.wcm.publication.context.ContextPlugin</type>
<init-params>
<object-param>
<name>contexts</name>
<object type="org.exoplatform.services.wcm.publication.context.impl.ContextConfig">
<field name="contexts">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.wcm.publication.context.impl.ContextConfig$Context">
<field name="name">
<string>contextdefault</string>
</field>
<field name="priority">
<string>200</string>
</field>
<field name="lifecycle">
<string>lifecycle1</string>
</field>
</object>
<object type="org.exoplatform.services.wcm.publication.context.impl.ContextConfig$Context">
<field name="name">
<string>context1</string>
</field>
<field name="priority">
<string>100</string>
</field>
<field name="lifecycle">
<string>lifecycle1</string>
</field>
<field name="membership">
<string>*:/platform/web-contributors</string>
</field>
<field name="site">
<string>acme</string>
</field>
<field name="path">
<string>repository:collaboration:/sites content/live/acme/categories</string>
</field>
</object>
<object type="org.exoplatform.services.wcm.publication.context.impl.ContextConfig$Context">
<field name="name">
<string>context2</string>
</field>
<field name="priority">
<string>100</string>
</field>
<field name="lifecycle">
<string>lifecycle1</string>
</field>
<field name="site">
<string>classic</string>
</field>
</object>
<object type="org.exoplatform.services.wcm.publication.context.impl.ContextConfig$Context">
<field name="name">
<string>context3</string>
</field>
<field name="priority">
<string>80</string>
</field>
<field name="lifecycle">
<string>lifecycle3</string>
</field>
<field name="membership">
<string>manager:/company/finances</string>
</field>
<field name="path">
<string>repository:collaboration:/documents/company/finances</string>
</field>
</object>
<object type="org.exoplatform.services.wcm.publication.context.impl.ContextConfig$Context">
<field name="name">
<string>context4</string>
</field>
<field name="priority">
<string>50</string>
</field>
<field name="lifecycle">
<string>lifecycle4</string>
</field>
<field name="memberships">
<collection type="java.util.ArrayList">
<value>
<string>manager:/CA/communicationDG</string>
</value>
<value>
<string>manager:/CA/alerteSanitaire</string>
</value>
<value>
<string>manager:/CA/alerteInformatique</string>
</value>
<value>
<string>manager:/CA/informations</string>
</value>
</collection>
</field>
<field name="path">
<string>repository:collaboration:/documents/company/finances</string>
</field>
<field name="nodetype">
<string>exo:article</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
The logic is very simple. When creating a content, it should be attached a lifecycle with the lifecyle priority:
context4 is the most important (priority=50): you will enroll the content in the lifecycle "lifecycle4" if:
The content creator has the manager:/company/finances membership.
The content is stored in repository:collaboration:/documents/company/finances or any subfolders.
The content is a 'exo:article
'.
If not, you will continue with context3.
The logic is very simple. When you create a content, go lifecycle by lifecycle starting with the better priority:
context4 is the most important (priority=50): you will enroll the content in the lifecycle "lifecycle4" if:
The content creator has the manager:/company/finances membership.
The content is stored in 'repository:collaboration:/documents/company/finances or any subfolders.
The content is a exo:article.
If not, you will continue with context3.
The contexts will be used only when the content is created and when you want to enroll it in a lifecycle for the first time. Once you have the corresponding lifecycle, you will set the lifecycle inside the content (see New Authoring Mixin) and the context service will not be called again for this content.
<nodeType hasOrderableChildNodes="false" isMixin="true" name="publication:authoring" primaryItemName="">
<propertyDefinitions>
<propertyDefinition autoCreated="false" mandatory="false" multiple="false" name="publication:lastUser" onParentVersion="IGNORE" protected="false" requiredType="String">
<valueConstraints/>
</propertyDefinition>
<propertyDefinition autoCreated="false" mandatory="false" multiple="false" name="publication:lifecycle" onParentVersion="IGNORE" protected="false" requiredType="String">
<valueConstraints/>
</propertyDefinition>
</propertyDefinitions>
</nodeType>
When adding the content in a lifecycle, set the publication:lifecycle_ property with the corresponding lifecycle.
A content can be in one lifecycle only.
Each time you change from one state to another, set the user who changed the state in publication:lastUser.
Querying based on publication status:
By adding this mixin to contents, you can access contents by simple queries based on the current user profile. For example:
All your draft contents:
query: select * from nt:base where publication:currentState
"draft" and publication:lastUser
="benjamin".
All the contents you have to approve.
call: PublicationManager.getLifecycles('benjamin','approved') => returns lifecycles where you can go to the 'approved' state.
query: select * from nt:base where publication:currentState="pending" and publication:lifecycle="lifecycle1" or publication:lifecycle="lifecycle3".
All the content that will be published tomorrow.
query: select * from nt:base where publication:currentState="staged" and publication:startPublishedDate="xxxx".
By default, your activities, such as writing a document, and uploading a file, are published on the activity stream. However, you can decide to publish these activities or not by creating a context named DocumentContext for a specific document. This context stores some auxiliary attributes of the document and helps document listeners make decision based on these attributes.
This context looks like:
public class DocumentContext {
private static ThreadLocal<DocumentContext> current = new ThreadLocal<DocumentContext>();
public static DocumentContext getCurrent() {
if (current.get() == null) {
setCurrent(new DocumentContext());
}
return current.get();
}
....
//Each time, attributes are able to set and got via:
/**
* @return the attributes
*/
public HashMap<String, Object> getAttributes() {
return attributes;
}
/**
* @param attributes the attributes to set
*/
public void setAttributes(HashMap<String, Object> attributes) {
this.attributes = attributes;
}
}
For example:
When you upload a document to a drive by using ManageDocumentService, but do not want to publish this activity on the activity stream, you can do as follows:
DocumentContext.getCurrent().getAttributes().put(DocumentContext.IS_SKIP_RAISE_ACT, true);
Then, this activity is skipped at:
Object isSkipRaiseAct = DocumentContext.getCurrent().getAttributes().get(DocumentContext.IS_SKIP_RAISE_ACT);
if (isSkipRaiseAct != null && Boolean.valueOf(isSkipRaiseAct.toString())) {
return;
}
The DocumentContext class is able to help developers manage various kinds of actions with a document based on its auxiliary attributes. You can be free to define new attributes for yourself.
The following examples of the CMIS usage may be useful for developers who need to access a repository. CMIS access code snippets are built using Apache HTTP Client for Java, or using Google gadgets (gadgets.io) for JavaScript examples. For the cURL examples, look at http://code.google.com/p/xcmis/wiki/xCMISusesWithCurl.
The CMIS service uses the default authentication in general case, but it can be overridden in case of embedding CMIS into an Application Service. In these examples, only the Basic HTTP authentication is covered.
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
HttpClient client = new HttpClient();
client.getState().setCredentials(
new AuthScope("localhost", 8080, "realm"),
new UsernamePasswordCredentials("root", "exo");
....
There are several methods to get the documents lists, such as getChildren(), getFolderTree() and getDescentants(), their usage will be described below. The difference between them is the usage of different URL segments to get data ("/children" for getChildren(), "/foldertree" for getFolderTree(), "/descendants" for getDescentants()), and a different kind of results (getChildren() returns a flat structure, while a getFolderTree() and getDescentants() have a tree of items in response).
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
String url = "http://localhost:8080/rest/private/cmisatom/";
url += repository;
url += "/children/";
url += obj_id;
HttpClient client = new HttpClient(new MultiThreadedHttpConnectionManager());
client.getHttpConnectionManager().
getParams().setConnectionTimeout(10000);
GetMethod get = new GetMethod(url);
try {
int result = client.executeMethod(get);
final String strResponse = get.getResponseBodyAsString();
} finally {
get.releaseConnection();
}
Creating an URL to make a request (consists of repository name, the method name, for example "/children/", and folderID to get children from):
var url = "http://localhost:8080/rest/private/cmisatom/";
url += repository;
url += "/children/";
url += obj_id;
Performing request:
var params = {};
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.FEED;
gadgets.io.makeRequest(url, handler, params);
Processing results (the code is located in the handler is specified while making a request, the same way it might be used for all examples in this chapter):
var handler = function(resp) {
var data = eval(resp.data.Entry);
for (var i = 0; i < data.length; i++) {
var doc = data[i];
alert(doc.Title);
alert(doc.Date);
...etc..
}
}
Reading the Document properties and content stream are two separate operations. Getting the content stream is possible after the properties set have been read and the content stream ID was extracted from it.
Get document properties.
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
String url = "http://localhost:8080/rest/private/cmisatom/";
url += repository;
url += "/object/";
url += obj_id;
HttpClient client = new HttpClient(new MultiThreadedHttpConnectionManager());
client.getHttpConnectionManager().
getParams().setConnectionTimeout(10000);
GetMethod get = new GetMethod(url);
try {
int result = client.executeMethod(get);
final String strResponse = get.getResponseBodyAsString();
// use response...
} finally {
get.releaseConnection();
}
Get document content-stream.
To get the Document's content stream, an URL must contain "/file" part, object ID, and optionally the content stream ID, which can be used, for example, to obtain renditions. If no stream ID is specified, the default stream will be returned.
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
String url = "http://localhost:8080/rest/private/cmisatom/";
url += repository;
url += "/file/";
url += obj_id;
//Optionally
url += "?";
url += "streamid=";
url += streamID;
HttpClient client = new HttpClient();
client.getHttpConnectionManager().
getParams().setConnectionTimeout(10000);
GetMethod get = new GetMethod(url);
try {
int result = client.executeMethod(get);
final InputStream stream = get.getResponseBodyAsStream();
try {
// use stream...
int dataByte = stream.read();
} finally {
stream.close();
}
} finally {
get.releaseConnection();
}
Get document properties.
Creating an URL to make a request (consists of repository name, method name, for example "/children/", and folder ID to get the children from):
var url = "http://localhost:8080/rest/private/cmisatom/";
url += repository;
url += "/object/";
url += obj_id;
Performing request:
var params = {};
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.FEED;
gadgets.io.makeRequest(url, handler, params);
You can also use the ContentType.DOM parameter to parse the feed in your application (Using DOMParser for example).
Get document content-stream.
Performing a content stream request in JavaScript will cause the browser dialog for a file download.
var url = "http://localhost:8080/rest/private/cmisatom/";
url += repository;
url += "/file/";
url += obj_id;
//Optionally
url += "?";
url += "streamid=";
url += streamID;
CMIS supports SQL queries for more handful content search. Query service can handle both GET and POST requests. URL for query consists of repository name and method name "/query". The GET request must contain query as a parameter named "q", in case of POST request query must be located in a request body.
For more detailed instructions how to construct queries, refer to the Query examples chapter.
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
String url = "http://localhost:8080/rest/private/cmisatom/";
url += repository;
url += "/query/";
HttpClient client = new HttpClient();
client.getHttpConnectionManager().
getParams().setConnectionTimeout(10000);
PostMethod post = new PostMethod(url);
String s = "<?xml version='1.0' encoding='utf-8'?>"
+ "<cmis:query xmlns='http://www.w3.org/2005/Atom' xmlns:cmis='http://docs.oasis-open.org/ns/cmis/core/200908/'>"
+ "<cmis:statement>SELECT * FROM cmis:document</cmis:statement>"
+ "<cmis:maxItems>10</cmis:maxItems>"
+ "<cmis:skipCount>0</cmis:skipCount>"
+ "<cmis:searchAllVersions>true</cmis:searchAllVersions>"
+ "<cmis:includeAllowableActions>true</cmis:includeAllowableActions>"
+ "</cmis:query>";
RequestEntity entity = new StringRequestEntity(s, "text/xml","utf-8");
try {
post.setRequestEntity(entity);
int result = client.executeMethod(post);
final String strResponse = post.getResponseBodyAsString();
// use response...
} finally {
post.releaseConnection();
}
var url = "http://localhost:8080/rest/private/cmisatom/";
url += repository;
url += "/query/";
var params = {};
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
params[gadgets.io.RequestParameters.POST_DATA] = gadgets.io.encodeValues(someQuery);
gadgets.io.makeRequest(url, handler, params);
The command of property update uses PUT method. The URL is the same as the one for reading properties, the difference is only in the HTTP method used. The body of the request must be an Atom document with specified properties (see spec. 2.2.4.12 for detailed constructing document).
Sending of content stream can be executed via PUT or POST requests. Content-type of the request must be an "multipart/form-data".
Update properties:
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
String url = "http://localhost:8080/rest/private/cmisatom/";
url += repository;
url += "/object/";
url += obj_id;
HttpClient client = new HttpClient();
client.getHttpConnectionManager().
getParams().setConnectionTimeout(10000);
String atomDoc = "<?xml version='1.0' encoding='utf-8'?>"
+ "<entry xmlns='http://www.w3.org/2005/Atom'"
+ " xmlns:cmis='http://docs.oasis-open.org/ns/cmis/core/200908/'"
+ " xmlns:cmisra='http://docs.oasis-open.org/ns/cmis/restatom/200908/'>"
+ "<cmisra:object><cmis:properties>"
+ "<cmis:propertyString queryName='cmis:name' localName='cmis:name' propertyDefinitionId='cmis:name'>"
+ "<cmis:value>newName</cmis:value>"
+ "</cmis:propertyString>"
+ "</cmis:properties></cmisra:object>"
+ "</entry>";
PutMethod put = new PutMethod(url);
RequestEntity entity = new StringRequestEntity(atomDoc, "text/xml", "utf-8");
put.setRequestEntity(entity);
try {
int result = client.executeMethod(put);
final String strResponse = put.getResponseBodyAsString();
} finally {
put.releaseConnection();
}
Set content stream:
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
String url = "http://localhost:8080/rest/private/cmisatom/";
url += repository;
url += "/file/";
url += obj_id;
HttpClient client = new HttpClient();
client.getHttpConnectionManager().
getParams().setConnectionTimeout(10000);
PostMethod post = new PostMethod(url);
RequestEntity entity = new InputStreamRequestEntity(inputStream, "text/xml; charset=ISO-8859-1");
post.setRequestEntity(entity);
try {
int result = client.executeMethod(post);
final String strResponse = post.getResponseBodyAsString();
} finally {
post.releaseConnection();
}
Update properties:
var url = "http://localhost:8080/rest/private/cmisatom/";
url += repository;
url += "/object/";
url += obj_id;
//constructing document
String atomDoc = "<?xml version='1.0' encoding='utf-8'?>";
atomDoc += "<entry xmlns='http://www.w3.org/2005/Atom'";
atomDoc += " xmlns:cmis='http://docs.oasis-open.org/ns/cmis/core/200908/'";
atomDoc += " xmlns:cmisra='http://docs.oasis-open.org/ns/cmis/restatom/200908/'>";
atomDoc += "<cmisra:object><cmis:properties>";
atomDoc += "<cmis:propertyString queryName='cmis:name' localName='cmis:name' propertyDefinitionId='cmis:name'>";
atomDoc += "<cmis:value>newName</cmis:value>";
atomDoc += "</cmis:propertyString>";
atomDoc += "</cmis:properties></cmisra:object></entry>";
var params = {};
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.PUT;
params[gadgets.io.RequestParameters.POST_DATA] = atomDoc;
gadgets.io.makeRequest(url, handler, params);
Set content stream:
var url = "http://localhost:8080/rest/private/cmisatom/";
url += repository;
url += "/file/";
url += obj_id;
var params = {};
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
params[gadgets.io.RequestParameters.CONTENT_TYPE] = "multipart/form-data";
params[gadgets.io.RequestParameters.POST_DATA] = contentStream;
gadgets.io.makeRequest(url, handler, params);
Service name | Service URL | Location | Description |
---|---|---|---|
ThumbnailRESTService | {portalname}/{restcontextname}/thumbnailImage/ |
Maven groupId: ArtifactId: | Return a responding data as a thumbnail image. |
{portalname}: The name of the portal.
{restcontextname}: The context name of rest webapplication which is deployed to the "{portalname}" portal.
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
getThumbnailImage | {portalname}/{restcontextname}/thumbnailImage/medium/{repoName}/{workspaceName}/{nodePath}/ |
repoName workspaceName nodePath |
String
| Return an image with the medium size (64x64). |
getLargeImage | {portalname}/{restcontextname}/thumbnailImage/large/{repoName}/{workspaceName}/{nodePath}/ |
repoName workspaceName nodePath |
String
| Return an image with the large size (300x300). |
getSmallImage | {portalname}/{restcontextname}/thumbnailImage/small/{repoName}/{workspaceName}/{nodePath}/ |
repoName workspaceName nodePath |
String
| Return an image with the small size (32x32). |
getCustomImage | {portalname}/{restcontextname}/thumbnailImage/custom/{size} }}/{repoName}/{workspaceName}/{nodePath}/ |
size repoName workspaceName nodePath |
String
| Return an image with the custom size. |
getOriginImage | {portalname}/{restcontextname}/thumbnailImage/origin/{repoName}/{workspaceName}/{nodePath}/ |
repoName workspaceName nodePath |
String
| Return an image with the original size. |
Service name | Service URL | Location | Description |
---|---|---|---|
RssConnector | {portalname}/{restcontextname}/feed/ |
Maven groupId: ArtifactId: | Generate an RSS feed. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
generate | {portalname}/{restcontextname}/feed/rss/ |
|
| Generate an RSS feed. |
Service name | Service URL | Location | Description |
---|---|---|---|
FCKCoreRESTConnector | {portalname}/{restcontextname}/fckconnector/jcr/ |
Maven groupId: ArtifactId: | Get a list of files and folders, and create a folder and upload files. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
getFoldersAndFiles | {portalname}/{restcontextname}/fckconnector/jcr/getFoldersAndFiles/{repositoryName}/{workspaceName}/{currentFolder}/{command}/{type}/ |
|
| Return the folders and the files in the current folder. |
createFolder | {portalname}/{restcontextname}/fckconnector/jcr/createFolder/{repositoryName}/{workspaceName}/{currentFolder}/{newFolderName}/{language}/ |
|
| Create a folder under the current folder. |
uploadFile | {portalname}/{restcontextname}/fckconnector/jcr/uploadFile/upload/ |
servletRequest
|
HttpServletRequest
| Uploads a file with the HttpServletRequest. |
processUpload | {portalname}/{restcontextname}/fckconnector/jcr/uploadFile/control/{repositoryName}/{workspaceName}/{currentFolder}/{action}/{language}/{fileName}/{uploadId}/ |
|
| Control the process of uploading a file, such as aborting, deleting or progressing the file. |
Service name | Service URL | Location | Description |
---|---|---|---|
ResourceBundleConnector | {portalname}/{restcontextname}/bundle/ |
Maven groupId: ArtifactId: | Get the bundle basing on the key and the locale. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
getBundle | {portalname}/{restcontextname}/bundle/getBundle/{key}/{locale}/ |
|
| Get the bundle basing on the key and the locale. |
Service name | Service URL | Location | Description |
---|---|---|---|
VoteConnector | {portalname}/{restcontextname}/contents/vote/ |
Maven groupId: ArtifactId: | Return and set a vote value of a given node in the sent parameter. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
postVote | {portalname}/{restcontextname}/contents/vote/postVote/{repositoryName}/{workspaceName}/{jcrPath}/{vote}/{lang}/ |
|
| Set a vote value for a given content. |
getVote | {portalname}/{restcontextname}/contents/vote/getVote/{repositoryName}/{workspaceName}/{jcrPath}/ |
|
| Return a vote value for a given content. |
Service name | Service URL | Location | Description |
---|---|---|---|
DriverConnector | {portalname}/{restcontextname}/wcmDriver/ |
Maven groupId: ArtifactId: | Return a drive list, a folder list and a document list in a specified location for a given user. Also, it processes the file uploading action. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
getDrivers | {portalname}/{restcontextname}/wcmDriver/getDrivers/ | lang |
string
| Return a list of drives for the current user. |
getFoldersAndFiles | {portalname}/{restcontextname}/wcmDriver/getFoldersAndFiles/ |
|
| Return all folders and files in a given location. |
uploadFile | {portalname}/{restcontextname}/wcmDriver/uploadFile/upload/ | uploadId | string | Uploads a file. |
processUpload | {portalname}/{restcontextname}/wcmDriver/uploadFile/control/ |
|
| Control the process of uploading a file, such as aborting, deleting or processing the file. |
Service name | Service URL | Location | Description |
---|---|---|---|
GadgetConnector | {portalname}/{restcontextname}/wcmGadget/ |
Maven groupId: ArtifactId: | Instantiate a new gadget connector. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
getFoldersAndFiles | {portalname}/{restcontextname}/wcmGadget/getFoldersAndFiles/{currentFolder}/{lang}/{host}/ |
|
| Get the folders and files. |
Service name | Service URL | Location | Description |
---|---|---|---|
PortalLinkConnector | {portalname}/{restcontextname}/portalLinks/ |
Maven groupId: ArtifactId: | Return a page URI for a given location. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
getPageURI | {portalname}/{restcontextname}/portalLinks/getFoldersAndFiles/ |
|
| Get the page URI. |
Service name | Service URL | Location | Description |
---|---|---|---|
GetEditedDocumentRESTService | {portalname}/{restcontextname}/presentation/document/edit/ |
Maven groupId: ArtifactId: | Return the latest edited documents. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
getLastEditedDoc | {portalname}/{restcontextname}/presentation/document/edit/{repository}/ | repository
| string | Return the latest edited documents. |
Service name | Service URL | Location | Description |
---|---|---|---|
PublicationGetDocumentRESTService | {portalname}/{restcontextname}/publication/presentation/ |
Maven groupId: ArtifactId: | Return a list of published documents. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
getPublishDocument | {portalname}/{restcontextname}/publication/presentation/{repository}/{workspace}/{state}/ |
|
| Return a list of published document by the default plugin. |
getPublishedListDocument | {portalname}/{restcontextname}/publication/presentation/{repository}/{workspace}/{publicationPluginName}/{state}/ |
|
| Return a list of published documents by a specific plugin. |
Service name | Service URL | Location | Description |
---|---|---|---|
FavoriteRESTService | {portalname}/{restcontextname}/favorite/ |
Maven groupId: ArtifactId: | Return a list of favourite documents of a given user. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
getFavoriteByUser | {portalname}/{restcontextname}/favorite/all/{repoName}/{workspaceName}/{userName} |
|
| Return a list of favourite documents of a given user. |
Service name | Service URL | Location | Description |
---|---|---|---|
RESTImagesRendererService | {portalname}/{restcontextname}/images/ |
Maven groupId: ArtifactId: | Get the image binary data of a given image node. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
serveImage | {portalname}/{restcontextname}/images/{repositoryName}/{workspaceName}/{nodeIdentifier}/ |
|
| Get the image binary data of a given image node. |
Service name | Service URL | Location | Description |
---|---|---|---|
LifecycleConnector | {portalname}/{restcontextname}/authoring/ |
Maven groupId: ArtifactId: | Return a list of contents in a given state range of the publication lifecycle. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
byState | {portalname}/{restcontextname}/authoring/bystate/ |
|
| Return a list of contents from the given state to the last state. |
toState | {portalname}/{restcontextname}/authoring/toState/ |
|
| Return a list of contents from the beginning state to the last state. |
byDate | {portalname}/{restcontextname}/authoring/byDate/ |
|
| Return a list of contents from the given beginning state and published before the given date. |
Service name | Service URL | Location | Description |
---|---|---|---|
CopyContentFile | {portalname}/{restcontextname}/copyfile/ |
Maven groupId: ArtifactId: | Copy a file. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
copyFile | {portalname}/{restcontextname}/copyfile/copy/ | param - the file information |
string
| Copy a file. |
Service name | Service URL | Location | Description |
---|---|---|---|
PDFViewerRESTService | {portalname}/{restcontextname}/pdfviewer//{repoName}/{workspaceName}/{pageNumber}/{rotation}/{scale}/{uuid}/ |
Maven groupId: ArtifactId: | Return the pdf content to display on the web page |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
getCoverImage | {portalname}/{restcontextname}/pdfviewer//{repoName}/{workspaceName}/{pageNumber}/{rotation}/{scale}/{uuid}/ |
|
| Return a thumbnail image for a pdf document. |
Service name | Service URL | Location | Description |
---|---|---|---|
ManageDocumentService | {portalname}/{restcontextname}/managedocument/ |
Maven groupId: ArtifactId: | The service which is used to perform some actions on a folder or a file, such as creating, deleting a folder/file, or uploading a file. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
getDrives | {portalname}/{restcontextname}/managedocument/getDrives/ |
| string
| Get all drives by type (General, Group or Personal drive). |
getFoldersAndFiles | {portalname}/{restcontextname}/managedocument/getFoldersAndFiles/ |
|
| Get all folders and files which the current user can view. |
createFolder | {portalname}/{restcontextname}/managedocument/createFolder/ |
|
| Create a new folder and return its information. |
deleteFolderOrFile | {portalname}/{restcontextname}/managedocument/deleteFolderOrFile/ |
|
| Delete a folder or a file. |
upload | {portalname}/{restcontextname}/managedocument//uploadFile/upload/ |
|
| Upload a file to the server. |
control | {portalname}/{restcontextname}/managedocument//uploadFile/control/ |
|
| Return the information about the upload status of a file (upload percentage, file name, and more). |
Service name | Service URL | Location | Description |
---|---|---|---|
DownloadConnector | {portalname}/{restcontextname}/contents/ |
Maven groupId: ArtifactId: | Enable downloading the content of nt:file. |
APIs usage:
Name | Service URL endpoint | Parameters | Values | Description |
---|---|---|---|---|
download | {portalname}/{restcontextname}/contents/download/{workspace}/{path:.*}/ |
|
| Return to browser a stream got from jcr:content/jcr:data for downloading the content of the node. |
Taxonomy service is used to work with taxonomies. In this service, there are many functions which enable you to add, find, or delete taxonomies from a node.
Method | Param | Return | Description |
---|---|---|---|
getTaxonomyTree(String repository, String taxonomyName, boolean system) throws ReposioryException; |
| node | Return the root node of the given taxonomy tree. |
getTaxonomyTree(String repository, String taxonomyName) throws RepositoryException; |
| node | Return the root node of the given taxonomy tree with the user session. |
getAllTaxonomyTrees(String repository, boolean system) throws RepositoryException; |
| List<Node>
| Return the list of all the root nodes of the taxonomy tree available. |
getAllTaxonomyTrees(String repository) throws RepositoryException; |
repository : The name of repository. |
List<Node> | Return the list of all the root nodes of the taxonomy tree available with the user session. |
hasTaxonomyTree(String repository, String taxonomyName) throws RepositoryException; |
| boolean | Check if a taxonomy tree with the given name has already been defined. |
addTaxonomyTree(Node taxonomyTree) throws RepositoryException, TaxonomyAlreadyExistsException; |
taxonomyTree : The taxonomy tree to define. | void | Define a node as a new taxonomy tree. |
updateTaxonomyTree(String taxonomyName, Node taxonomyTree) throws RepositoryException; |
| void | Re-define a node as a taxonomy tree. |
removeTaxonomyTree(String taxonomyName) throws RepositoryException |
taxonomyName : The name of the taxonomy to remove. | void | Remove the taxonomy tree definition. |
addTaxonomyNode(String repository, String workspace, String parentPath, String taxoNodeName, String creator) throws RepositoryException, TaxonomyNodeAlreadyExistsException; |
| void | Add a new taxonomy node at the given location. |
removeTaxonomyNode(String repository, String workspace, String absPath) throws RepositoryException; |
| void | Remove the taxonomy node located at the given absolute path. |
moveTaxonomyNode(String repository, String workspace, String srcPath, String destPath, String type) throws RepositoryException; |
| void | Copy or cut the taxonomy node from the source path to the destination path. The parameter type indicates if the node must be cut or copied. |
hasCategories(Node node, String taxonomyName) throws RepositoryException; |
| boolean | Return true if the given node has categories in the given taxonomy. |
hasCategories((Node node, String taxonomyName, boolean system) throws RepositoryException; |
|
boolean | Return true if the given node has categories in the given taxonomy. |
getCategories (Node node, String taxonomyName) throws RepositoryException; |
|
List<Node> | Return all the paths of the categories (relative to the root node of the given taxonomy) which have been associated to the given node for the given taxonomy. |
getCategories(Node node, String taxonomyName, boolean system) throws RepositoryException; |
| List<Node> | Return all the paths of the categories(relative to the root node of the given taxonomy) which have been associated to the given node for the given taxonomy. |
getAllCategories(Node node) throws RepositoryException; |
|
List<Node> | Return all the paths of the categories which have been associated to the given node. |
getAllCategories(Node node, boolean system) throws RepositoryException; |
|
List<Node> | Return all the paths of the categories which have been associated to the given node. |
removeCategory(Node node, String taxonomyName, String categoryPath) throws RepositoryException; |
| void | Remove a category to the given node. |
removeCategory(Node node, String taxonomyName, String categoryPath, boolean system) throws RepositoryException; |
| void | Remove a category to the given node. |
addCategories(Node node, String taxonomyName, String[] categoryPaths) throws RepositoryException; |
| void | Add several categories to the given node. |
addCategories(Node node, String taxonomyName, String[] categoryPaths, boolean system) throws RepositoryException; |
| void | Add several categories to the given node. |
addCategory(Node node, String taxonomyName, String categoryPath) throws RepositoryException; |
| void | Add a new category path to the given node. |
addCategory(Node node, String taxonomyName, String categoryPath, boolean system) throws RepositoryException; |
| void | Add a new category path to the given node. |
getTaxonomyTreeDefaultUserPermission(); | N/A | Map<String, String[]> | Get the default permission for the user in taxonomy tree. |
addTaxonomyPlugin(ComponentPlugin plugin); |
plugin : The plugin to add. | void | Add a new taxonomy plugin to the service. |
init(String repository) throws Exception; | repository : The name of repository. | void | Initialize all taxonomy plugins that have been already configured in .xml files. |
getCategoryNameLength(); | N/A | string | Get the limited length of the category name. |
Supply API to work with the linked node or the link included in a node.
Package org.exoplatform.services.cms.link.LinkManager
Method | Param | Return | Description |
---|---|---|---|
createLink(Node parent, String linkType, Node target)throws RepositoryException; |
| Node | Create a new link that is added to the parent node and return the link. |
createLink(Node parent, Node target)throws RepositoryException; |
| Node | Create a new node of type exo:symlink, then add it to the parent node and return the link node. |
createLink(Node parent, String linkType, Node target, String linkName) throws RepositoryException; |
| Node | Create a new link that is added to the parent node and return the link. |
updateLink(Node link, Node target)throws RepositoryException; |
| Node | Update the target node of the given link. |
getTarget(Node link, boolean system) throws ItemNotFoundException, RepositoryException; |
| Node | Get the target node of the given link. |
getTarget(Node link)throws ItemNotFoundException, RepositoryException; |
link : The node of type exo:symlink. | Node | Get the target node of the given link using the user. |
isTargetReachable(Node link) throws RepositoryException; | link : The node of type exo:symlink. | boolean | Check if the target node of the given link can be reached using the user session. |
isTargetReachable(Node link, boolean system)throws RepositoryException; |
| boolean | Check if the target node of the given link can be reached using the user session. |
isLink(Item item) throws RepositoryException; |
item : The item to test. | boolean | Indicate whether the given item is a link. @return <code>true</code>: if the node is a link, <code>false</code> otherwise. |
getTargetPrimaryNodeType(Node link)throws RepositoryException; | link : The node of type exo:symlink. | string | Return the primary node type of the target. |
getAllLinks(Node targetNode, String linkType, String repoName)throws Exception |
|
List<Node> - the list of link of the target node with given type. | Return all links of the given node. (Deprecated) |
getAllLinks(Node targetNode, String linkType, SessionProvider sessionProvider) throws Exception; |
| List<Node> - the list of link of the target node with given type. | Return all links of the given node. |
PublicationService is to manage the publication.
Method | Param | Return | Description |
---|---|---|---|
addLifecycle(ComponentPlugin plugin) | plugin | void | Add publication plugin to the publication service. |
removeLifecycle(ComponentPlugin plugin) | plugin
|
void
| Remove publication plugin from the publication service. |
addContext(ComponentPlugin plugin) | plugin
|
void
| Add publication plugin context to the publication service. |
removeContext(ComponentPlugin plugin) | plugin
|
void
| Remove publication plugin context from the publication service. |
getLifecycle(String name) | name - The name of the wanted lifecycle. | Lifecycle | Get a specific lifecycle with the given name. |
getLifecycles() |
N/A
| List<Lifecycle> | Get all the lifecycles which were added to service instances. |
getContext(String name) | name | Context | Get a specific context with the given names. |
getContexts() |
N/A | List<Context> | Get all the contexts which were added to service instances. |
getContents(String fromstate, String tostate, String date, String user, String lang , String workspace) throws Exception; |
| List<Node> | Get all the nodes. |
getLifecyclesFromUser(String remoteUser, String state); |
| List<Lifecycle> | Get all the Lifecycle of a specific user. |
This class is used to get contents inside the WCM product. You should not access contents directly from the JCR on the front side.
In general, this service stands between publication and cache.
Package org.exoplatform.services.wcm.publication.WCMComposer
Method | Param | Return | Description |
---|---|---|---|
getContent(String repository, String workspace, String nodeIdentifier, HashMap<String, String> filters, SessionProvider sessionProvider)throws Exception; |
| Node | Return contents at the specified path based on filters. |
getContents(String repository, String workspace, String path, HashMap<String, String> filters, SessionProvider sessionProvider)throws Exception; |
| List<Node> | Return contents at the specified path based on filters. |
updateContent(String repository, String workspace, String nodeIdentifier, HashMap<String, String> filters)throws Exception; |
| boolean | Update content. |
getAllowedStatesString mode)throws Exception; |
mode
| List<String> | Return allowed states for a specified mode. |
cleanTemplates()throws Exception; | N/A | void | Initialize the template hashmap. |
isCached()throws Exception; | N/A | boolean | Check isCache or not. |
updateTemplatesSQLFilter()throws Exception; | N/A | String | Update all document nodetypes and write a query cause. It returns a part of the query that allows to search all document nodes and taxonomy links. Return null if there is any exception. |
Package org.exoplatform.services.cms.folksonomy.NewFolksonomyService;
Method | Return | Prototype | Description |
---|---|---|---|
addPrivateTag(String[] tagsName, Node documentNode, String repository, String workspace, String userName) throws Exception ; |
| void | Add a private tag to a document. A folksonomy link will be created in a tag node. |
addGroupsTag(String[] tagsName, Node documentNode,String repository, String workspace, String[] roles) throws Exception ; |
| void | Add a group tag to a document. A folksonomy link will be created in a tag node. |
addPublicTag(String treePath, String[] tagsName, Node documentNode, String repository, String workspace) throws Exception ; |
| void | Add a public tag to a document. A folksonomy link will be created in a tag node. |
addSiteTag(String siteName, String[] tagsName, Node node, String repository, String workspace) throws Exception ; |
| void | Add a site tag to a document. A folksonomy link will be created in a tag node. |
getAllPrivateTags(String userName, String repository, String workspace) throws Exception ; |
| List<Node> | Get all private tags. |
getAllPublicTags(String treePath, String repository, String workspace) throws Exception ; |
| List<Node> | Get all public tags. |
getAllGroupTagsString[] roles, String repository, String workspace) throws Exception ; |
| List<Node> | Get all tags by groups. |
getAllGroupTags(String role, String repository, String workspace) throws Exception ; |
| List<Node> | Get all tags by a group. |
getAllSiteTags(String siteName, String repository, String workspace) throws Exception ; |
| List<Node> | Get all tags of Site. |
getAllDocumentsByTag(String tagPath, String repository, String workspace, SessionProvider sessionProvider) throws Exception ; |
| List<Node>
| Get all documents which are stored in a tag and return a list of documents in a tag. |
getTagStyle(String tagPath, String repository, String workspace) throws Exception ; |
| string | Get HTML_STYLE_PROP property in styleName node in the repository. |
addTagStyle(String styleName, String tagRange, String htmlStyle, String repository, String workspace) throws Exception ; |
| void | Update the properties TAG_RATE_PROP and HTML_STYLE_PROP, following the values tagRate, htmlStyle for a node in tagPath in repository. |
updateTagStyle(String styleName, String tagRange, String htmlStyle, String repository, String workspace) throws Exception ; |
| void | Update the properties TAG_RATE_PROP and HTML_STYLE_PROP, following the value tagRate, htmlStyle for a node in tagPath in repository. |
getAllTagStyle(String repository, String workspace) throws Exception ; |
| List<Node> | Get all tag style bases of a folksonomy tree. |
init(String repository) throws Exception ; |
repository : The repository name. | void | Initialize all TagStylePlugin with session in repository name. |
removeTagOfDocument(String tagPath, Node document, String repository, String workspace) throws Exception; |
| void | Remove a tag of a given document. |
removeTag(String tagPath, String repository, String workspace) throws Exception; |
| void | Remove a tag. |
modifyTagName(String tagPath, String newTagName, String repository, String workspace) throws Exception; |
| Node | Modify the tag name. |
getLinkedTagsOfDocument(Node documentNode, String repository, String workspace) throws Exception; |
| List<Node> | Get all tags linked to a given document. |
getLinkedTagsOfDocumentByScope(int scope, String value, Node documentNode, String repository, String workspace) throws Exception; |
| List<Node> | Get all tags linked to a given document by scope. |
removeTagsOfNodeRecursively(Node node, String repository, String workspace, String username, String groups) throws Exception; |
| void | Remove all tags linked to the child nodes of a given node. |
addTagPermission(String usersOrGroups); |
usersOrGroups | void | Add given users or groups to tagPermissionList. |
removeTagPermission(String usersOrGroups); |
usersOrGroups | void | Remove given users or groups from tagPermissionList. |
getTagPermissionList(); | N/A | List<String> | Return tagPermissionList. |
canEditTag(int scope, List<String> memberships); |
| boolean | Set the permission to edit a tag for a user. |
getAllTagNames(String repository, String workspace, int scope, String value) throws Exception; |
| List<String> | Get all tag names which start within a given scope. |
This class is used to manage dynamic groovy templates for WCM-based products.
Package org.exoplatform.services.cms.views.ApplicationTemplateManager;
Method | Param | Return | Description |
---|---|---|---|
addPlugin(PortletTemplatePlugin portletTemplatePlugin) throws Exception |
portletTemplatePlugin |
void | Add the plugin.. |
getAllManagedPortletName(String repository) throws Exception |
repository | List<String> | Retrieve all the portlet names that have dynamic groovy templates managed by service. |
getTemplatesByApplication(String repository, String portletName, SessionProvider provider)throws Exception; |
|
List<String> | Retrieve the templates node by application. |
getTemplatesByCategory(String repository, String portletName, String category, SessionProvider sessionProvider) throws Exception; |
| List<String> | Retrieve the templates node by category. |
getTemplateByName(String repository, String portletName, String category, String templateName, SessionProvider sessionProvider)throws Exception; |
| node | Retrieve the template by name. |
getTemplateByPath(String repository, String templatePath, SessionProvider sessionProvider)throws Exception ; |
| node | Get the template by path. |
addTemplate(node portletTemplateHome, PortletTemplateConfig config)throws Exception; |
|
void | Add the template. |
removeTemplate(String repository, String portletName, String catgory, String templateName, SessionProvider sessionProvider)throws Exception; |
|
void | Remove the template. |
NodeFinder is used to find a node with a given path. If the path to the node contains sub-paths to exo:symlink nodes, find the real link node.
Method | Param | Return | Description |
---|---|---|---|
getNode(Node ancestorNode, String relativePath) throws PathNotFoundException, RepositoryException; |
| node
| Return the node at relPath related to the ancestor node. |
getNode(Node ancestorNode, String relativePath, boolean giveTarget) throws PathNotFoundException, RepositoryException; |
|
node | Return the node at relPath related to the ancestor node. If the node is a link and giveTarget has been set to <code>true</code>, the target node will be returned. |
getItem(String repository, String workspace, String absPath) throws PathNotFoundException, RepositoryException; |
| item
| Return the item at the specified absolute path. |
getItemSys(String repository, String workspace, String absPath, boolean system) throws PathNotFoundException, RepositoryException; |
| item
| Return the item at the specified absolute path. |
getItem(String repository, String workspace, String : absPath, boolean giveTarget) throws PathNotFoundException, RepositoryException; |
| item | Return the item at the specified absolute path. If the item is a link and giveTarget has been set to <code>true</code>, the target node will be returned. |
getItemGiveTargetSys(String repository, String workspace, String absPath, boolean giveTarget, boolean system) throws PathNotFoundException, RepositoryException; |
| Item | Return the item at the specified absolute path. If the item is a link and giveTarget has been set to <code>true</code>, the target node will be returned. |
getItem(Session session, String absPath) throws PathNotFoundException, RepositoryException; |
| item
| Return the item at the specified absolute path. |
getItem(Session session, String absPath, boolean giveTarget) throws PathNotFoundException, RepositoryException; |
| item | Return the item at the specified absolute path. If the item is a link and giveTarget has been set to <code>true</code>, the target node will be returned. |
getItemTarget(Session session, String absPath, boolean giveTarget, boolean system) throws PathNotFoundException, RepositoryException; |
| item | Return the item at the specified absolute path. If the item is a link and giveTarget has been set to <code>true</code>, the target node will be returned. |
itemExists(Session session, String absPath) throws RepositoryException; |
| boolean |
Return <code>true</code> if an item exists at absPath; otherwise returns <code>false</code>. Also returns <code>false</code> if the specified absPath is malformed. |
JodConverter is used to convert documents into different office formats.
Package org.exoplatform.services.cms.jodconverter.JodConverterService
Method | Param | Return | Description |
---|---|---|---|
convert(InputStream input, String formatInput, OutputStream out, String formatOutput) throws Exception; |
| void | Convert InputStream in the formatInput format to OutputStream with the formatOutput format. Deprecate: This method is not supported by JODConverter 3.0 anymore, please use convert(File, File, String) instead. |
convert(File input, File output, String outputFormat) throws OfficeException; |
|
boolean
| Convert input File to output File with the outputFormat. |
TimelineService is used to get all documents by time frame (day, month, year).
Method | Param | Return | Description |
---|---|---|---|
getDocumentsOfToday(String nodePath,String repository,String workspace, SessionProvider sessionProvider, String userName, boolean byUser) throws Exception; |
|
List<Node>
| Get all documents of today. (Deprecated) |
getDocumentsOfToday(String nodePath,String workspace, SessionProvider sessionProvider, String userName, boolean byUser) throws Exception; |
| List<Node>
| Get all documents of today. |
getDocumentsOfToday(String nodePath,String workspace, SessionProvider sessionProvider, String userName, boolean byUser, boolean isLimit) throws Exception; |
|
List<Node>
| Get all documents of today. |
getDocumentsOfYesterday(String nodePath,String repository,String workspace, SessionProvider sessionProvider, String userName, boolean byUser) throws Exception; |
|
List<Node>
| Get all documents of yesterday. (Deprecated) |
getDocumentsOfYesterday(String nodePath,String workspace, SessionProvider sessionProvider, String userName, boolean byUser) throws Exception; |
|
List<Node>
| Get all documents of yesterday. |
getDocumentsOfYesterday(String nodePath,String workspace, SessionProvider sessionProvider, String userName, boolean byUser, boolean isLimit) throws Exception; |
|
List<Node>
| Get all documents of yesterday. |
getDocumentsOfEarlierThisWeek(String nodePath,String repository,String workspace, SessionProvider sessionProvider, String userName, boolean byUser) throws Exception; |
|
List<Node>
| Get all documents from earlier this week to yesterday. (Deprecated) |
getDocumentsOfEarlierThisWeek(String nodePath,String workspace, SessionProvider sessionProvider, String userName, boolean byUser) throws Exception; |
|
List<Node>
| Get all documents from earlier this week to yesterday. |
getDocumentsOfEarlierThisWeek(String nodePath,String workspace, SessionProvider sessionProvider, String userName, boolean byUser, boolean isLimit) throws Exception; |
|
List<Node>
| Get all documents from earlier this week to yesterday. |
getDocumentsOfEarlierThisMonth(String nodePath,String repository,String workspace, SessionProvider sessionProvider, String userName, boolean byUser) throws Exception; |
|
List<Node>
| Get all documents from earlier this month to earlier this week. (Deprecated) |
getDocumentsOfEarlierThisMonth(String nodePath,String workspace, SessionProvider sessionProvider, String userName, boolean byUser) throws Exception; |
| List<Node>
| Get all documents from earlier this month to earlier this week. |
getDocumentsOfEarlierThisMonth(String nodePath,String workspace, SessionProvider sessionProvider, String userName, boolean byUser, boolean isLimit) throws Exception; |
|
List<Node>
| Get all documents since earlier this month to earlier this week. |
getDocumentsOfEarlierThisYear(String nodePath,String repository,String workspace, SessionProvider sessionProvider, String userName, boolean byUser) throws Exception; |
|
List<Node>
| Get all documents from earlier this year to earlier this month. (Deprecated) |
getDocumentsOfEarlierThisYear(String nodePath,String workspace, SessionProvider sessionProvider, String userName, boolean byUser) throws Exception; |
|
List<Node>
| Get all documents from earlier this year to earlier this month. |
getDocumentsOfEarlierThisYear(String nodePath,String workspace, SessionProvider sessionProvider, String userName, boolean byUser, boolean isLimit) throws Exception; |
|
List<Node>
| Get all documents from earlier this year to earlier this month. |
getItemPerTimeline() |
N/A |
int | Get the number of documents per category displayed in the Timeline view. |
SiteSearchService is used in the Search portlet that allows users to find all information matching with your given keyword.
Method | Param | Return | Description |
---|---|---|---|
addExcludeIncludeDataTypePlugin(ExcludeIncludeDataTypePlugin plugin) | plugin : The plugin. | void | Filter mimetypes data in the search results. |
searchSiteContents(SessionProvider sessionProvider, QueryCriteria queryCriteria, int pageSize, boolean isSearchContent) throws Exception; |
|
AbstractPageList<ResultNode>
| Find all child nodes whose contents match with the given keyword. These nodes will be put in the list of search results. |
SEOService supplies APIs to manage SEO data of a page or a content. This service includes some major functions which enables you to add, store, get or remove the metadata of a page or a content.
Method | Param | Return | Description |
---|---|---|---|
storePageMetadata(PageMetadataModel metaModel, String portalName, boolean onContent) throws Exception |
| void
| Store the metadata of a page/content. |
getMetadata(ArrayList<String> params, String pageReference) throws Exception |
| PageMetadataModel | Return the metadata of a portal page or a content page. |
getPageMetadata (String pageReference) throws Exception | pageReference : The reference of the page. |
PageMetadataModel
| Return the metadata of a portal page. |
getContentMetadata(ArrayList<String> params) throws Exception |
params : The parameters list of a content page. | PageMetadataModel
| Return the metadata of a content page. |
removePageMetadata(PageMetadataModel metaModel, String portalName, boolean onContent) throws Exception |
| void
| Remove the metadata of a page. |
getContentNode(String contentPath) throws Exception | contentPath : The content path. | Node | Return the content node by the content path. |
getHash(String uri) throws Exception |
uri : The page reference of the UUID of a node. |
string
| Create a key from the page reference or the UUID of the node. |
getSitemap(String portalName) throws Exception |
portalName : The portal name. | string
| Return a sitemap's content of a specific portal. |
getRobots(String portalName) throws Exception |
portalName : The portal name. | string
| Return Robots' content of a specific portal. |
getRobotsIndexOptions() throws Exception | N/A | List<String> | Return a list of options (INDEX and NOINDEX) for robots to index. |
getRobotsFollowOptions() throws Exception | N/A | List<String> | Return a list of options (FOLLOW and NOFOLLOW) for robots to follow. |
getFrequencyOptions() throws Exception |
N/A | List<String> | Return a list of options for frequency. |
ManageViewService is used to work with views. This service has many functions which allow you to add, edit, delete, and get views.
Method | Param | Return | Description |
---|---|---|---|
addView(String name, String permissions, String template, List<?> tabs, String repository) throws Exception; |
| void
| Insert a new view to the system. (Deprecated) |
addView(String name, String permissions, String template, List<?> tabs) throws Exception; |
| void
| Insert a new view to the system. |
getViewByName(String viewName, String repository, SessionProvider provider) throws Exception; |
| node
| Specify a new view depending on the view name. (Deprecated) |
getViewByName(String viewName, SessionProvider provider) throws Exception; |
| node
| Specify a new view depending on the view name. |
getButtons() throws Exception; | N/A |
List<?> | Return all strings of buttons. |
removeView(String viewName, String repository) throws Exception; |
| void | Remove a view from the views list in the system. (Deprecated) |
removeView(String viewName) throws Exception; | viewName
| void | Remove a view from the views list in the system. |
getAllViews(String repository) throws Exception; | repository
| List<ViewConfig> | Return all views of the repository configured in the XML file. (Deprecated) |
getAllViews() throws Exception; | N/A
| List<ViewConfig> | Return all views of the repository configured in the XML file. |
hasView(String name, String repository) throws Exception; |
| boolean | Return true if the given repository has a view. (Deprecated) |
hasView(String name) throws Exception; | N/A
| boolean | Return true if the given repository has a view. |
getTemplateHome(String homeAlias, String repository, SessionProvider provider) throws Exception; |
| Node | Get a template node that has the path. (Deprecated) |
getTemplateHome(String homeAlias, SessionProvider provider) throws Exception; |
| Node | Get a template node that has the path. |
getAllTemplates(String homeAlias, String repository, SessionProvider provider) throws Exception; |
| List<Node> | Get all template nodes that have the path. (Deprecated) |
getAllTemplates(String homeAlias, SessionProvider provider) throws Exception; |
| List<Node> | Get all template nodes that have the path. |
getTemplate(String path, String repository, SessionProvider provider) throws Exception; |
| Node | Return a node that has the path of the repository. (Deprecated) |
getTemplate(String path, SessionProvider provider) throws Exception; |
| Node | Return a node that has the path of the repository. |
addTemplate(String name, String content, String homePath, String repository) throws Exception; |
| String | Insert a new template to a node by specifying its path. (Deprecated) |
addTemplate(String name, String content, String homePath) throws Exception; |
| String | Insert a new template to a node by a specified path. |
updateTemplate(String name, String content, String homePath, String repository) throws Exception; |
| String | Update a template for a node by specifying its path. (Deprecated) |
updateTemplate(String name, String content, String homePath) throws Exception; |
| String | Update a template for a node by specifying its path. |
removeTemplate(String templatePath, String repository) throws Exception; |
| void | Remove the template from the given node by specifying its path. (Deprecated) |
removeTemplate(String templatePath) throws Exception; | templatePath | void | Remove the template from the given node by specifying its path. |
addTab(Node view, String name, String buttons) throws Exception ; |
| void | Insert a new tab to the given view node. |
init(String repository) throws Exception ; | repository | void | Get all templates that are configured in the XML file of a specified repository. (Deprecated) |
init() throws Exception ; | N/A
| void | Get all templates that are configured in the XML file of a specified repository. |
In Content, there are some deprecated portlets, including Browse Content (BC), Parameterized Content Viewer (PCV), Parameterized Content List Viewer (PCLV), Category Navigation (CN), Newsletter Viewer, Newsletter Manager, Form Builder.
In which:
The BC, Newsletter Viewer, Newsletter Manager and Form Builder portlets are not used anymore.
The PCV portlet is still used, but its java class named UIPCVPortlet is replaced by UISingleContentViewerPortlet of the Single Content Viewer (SCV) portlet.
The PCLV portlet is still used, but its java class named UIPCLVPortlet is replaced by UICLVPortlet of the Content List Viewer (CLV) porlet.
The CN portlet is still used, but its java class named UICategoryNavigationPortlet is replaced by UICLVPortlet of the CLV porlet.
xCMIS project links:
CMIS-related links:
CMIS working group (list, mail, feeds, and more).
CMIS external tutorials, guides, videos, blogs, news.
CMIS clients, UI, web.
This section provides FAQs related to the product.
The addPlugin() function of WorkflowServiceContainer service is used to register a Business Process when a workflow is implemented. Thus, if you want to use a workflow, you are required to configure the workflow service to invoke the addPlugin() function by adding the external-component-plugins element to the configuration file.
You have to set values for the name and location of the workflow which you want to use. There are two ways to configure the location of the workflow.
You can use "war:(FOLDER_PATH)" to configure which .jar files contain your workflow processes inside the .war file.
<external-component-plugins>
<target-component>org.exoplatform.services.workflow.WorkflowServiceContainer</target-component>
<component-plugin>
<name>deploy.predefined.processes</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.workflow.PredefinedProcessesPlugin</type>
<init-params>
<object-param>
<name>predefined.processes</name>
<description>load of default business processes</description>
<object type="org.exoplatform.services.workflow.ProcessesConfig">
<field name="processLocation">
<string>war:/conf/bp</string>
</field>
<field name="predefinedProcess">
<collection type="java.util.HashSet">
<value>
<string>/exo-ecms-ext-workflow-bp-jbpm-content-2.1.1.jar</string>
</value>
<value>
<string>/exo-ecms-ext-workflow-bp-jbpm-payraise-2.1.1.jar</string>
</value>
<value>
<string>/exo-ecms-ext-workflow-bp-jbpm-holiday-2.1.1.jar</string>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
You can use classpath: to configure which .jar files contain your workflow processes inside the .jar file.
<external-component-plugins>
<target-component>org.exoplatform.services.workflow.WorkflowServiceContainer</target-component>
<component-plugin>
<name>deploy.predefined.processes</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.workflow.PredefinedProcessesPlugin</type>
<init-params>
<object-param>
<name>predefined.processes</name>
<description>load of default business processes</description>
<object type="org.exoplatform.services.workflow.ProcessesConfig">
<field name="processLocation">
<string>classpath:</string>
</field>
<field name="predefinedProcess">
<collection type="java.util.HashSet">
<value>
<string>/exo-ecms-ext-workflow-bp-jbpm-content-myworkflow.jar</string>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
The notification message is displayed when you deploy a workflow on Jboss. If you use classpath: to register, you must put your workflow in the .jar files inside the gatein.ear/lib folder (instead of the lib folder) to make it work.
You can refer to the following links to understand more about the eXo Collaboration Reference Guide:
This chapter provides you a comprehensive view about applications in eXo Collaboration, including:
These applications are packaged as Web application archives (WARs).
Also, you can specify the package of each portlet and gadget and its available preferences that allow you to extend the configuration choices for standard preferences.
This section provides all information, such as description, package, preferences, and portlet.xml about portlets included in eXo Collaboration.
The Calendar portlet shows the Calendar application of eXo Collaboration with a lot of features provided to users.
The Calendar application includes the following features:
Create multiple personal calendars, manage calendars easily with calendar groups.
Create events or tasks using the Quick Add dialog easily.
Create events or tasks in details.
Create all-day events.
View other attender's availability schedules.
Create recurring events.
Get reminders.
View calendars by various views: day, week, month and year.
View events day-by-day by navigating the mini-calendar quickly.
Share calendars with others.
Import/Export calendars.
Publish your calendars with RSS, CalDAV.
Search for events and/or tasks in calendars.
Print your agenda.
Package
The Calendar portlet is packaged in the calendar.war file.
To see the portlet in the project, follow this path: /eXoApplication/calendar/webapp/src/main/webapp/WEB-INF/portlet.xml.
The Chatbar portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
The Chatbar portlet shows the Chatbar application of eXo Collaboration that can be positioned in the portal or page layout as any other, but behaves as a floating box. The bar remains floating at its location even when the browser window is scrolled or resized. Its height is fixed, but can be expanded horizontally to any size available in its container. This allows the portlet to be placed in two layout cases:
Large width area (typically header or footer).
Narrow column.
The Chatbar application implements all functions of the Chat application, allowing you to send and receive messages anywhere after you are logged in successfully. The Chatbar is a typical toolbar with buttons to open menus. It gives access to main features of Chat:
Status change and presence indicator.
Contacts.
Rooms.
Minimized conversation window.
Package
The Chatbar portlet is packaged in the Chatbar.war file.
The Chatbar Portlet consists of some preferences as in the following sample code:
<portlet-preferences>
<preference>
<name>showMailLink</name>
<value>true</value> <!--true/false -->
<read-only>false</read-only>
</preference>
<preference>
<name>showCalendarLink</name>
<value>true</value> <!--true/false -->
<read-only>false</read-only>
</preference>
<preference>
<name>showContactLink</name>
<value>true</value> <!--true/false -->
<read-only>false</read-only>
</preference>
<preference>
<name>mailUrl</name>
<value>portal/private/intranet/mail</value> <!--String page name -->
<read-only>false</read-only>
</preference>
<preference>
<name>calendarUrl</name>
<value>portal/private/intranet/calendar</value> <!--String page name -->
<read-only>false</read-only>
</preference>
<preference>
<name>contactUrl</name>
<value>portal/private/intranet/contact</value> <!--String page name -->
<read-only>false</read-only>
</preference>
<preference>
<name>info</name>
<value>info</value> <!--this is only the key to get the resource bundle the full key : UIConfigForm.label.info -->
<read-only>true</read-only>
</preference>
</portlet-preferences>
In which:
Preference Name | Possible Values | Default Values | Description |
---|---|---|---|
showMailLink | true / false | true | The value as "true" or "false" means that users are allowed to see the application icon or not respectively. |
showCalendarLink | true / false | true | The value as "true" or "false" means that users are allowed to see the application icon or not respectively. |
showContactLink | true / false | true | The value as "true" or "false" means that users are allowed to see the application icon or not respectively. |
mailUrl | string | Portal/private/intranet/mail | The URL to the Mail application page in the portal without combining with the %domain name. The port% chatbar will resolve it from server. |
calendarUrl | string | Portal/private/intranet/calendar | The URL to the Calendar application page in the portal without combining with the %domain name. The port% chatbar will resolve it from server. |
contactUrl | string | Portal/private/intranet/contact | The URL to the Address Book application page in the portal without combining with the %domain name. The port% chatbar will resolve it from server. |
info | Info
| Info
| This is only the key to get the resource bundle of the full key: UIConfigForm.label.info. |
See the portlet in the project following this path: /eXoApplication/chatbar/webapp/src/main/webapp/WEB-INF/portlet.xml.
The Chat portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
The Chat Portlet shows the Chat application of eXo Collaboration that allows users to enter chat rooms and communicate with online others at real time.
Package
The Chat portlet is packaged in the Chat.war file.
See the portlet in the project following this path: /eXoApplication/chat/webapp/src/main/webapp/WEB-INF/portlet.xml
Contact Portlet shows the Contact application of eXo Collaboration that allows users to personalize their contact view from different view types, such as List view and VCards view.
Package
Contact Portlet is packaged in the Contact.war file.
See the portlet in the project following this path: /eXoApplication/contact/webapp/src/main/webapp/WEB-INF/portlet.xml.
The Mail portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
Mail Portlet shows the Mail application of eXo Collaboration that offers a lot of features to users such as sending, receiving or viewing their mails through Internet without actually downloading them to their computer. Users not only take advantages of eXo Mail by keeping and receiving all important messages, files and pictures forever but also by looking for and viewing their needed messages easily whenever they want. Additionally, the Mail application is smoothly integrated with other Collaboration modules, such as Address Book and Calendar.
Package
The Mail Portlet is packaged in the Mail.war file.
See the portlet in the project following this path: /eXoApplication/mail/webapp/src/main/webapp/WEB-INF/portlet.xml.
The RSSreader portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
eXo Collaboration uses the RSS Reader Portlet that facilitates users to quickly get a view of their favorite feeds around the web. They will get the latest news, the last updated posts from their favorite blogs, latest emails, and more.
Package
The RSSreader Portlet is packaged in the Rssreader.war file.
See the portlet in the project following this path: /eXoApplication/content/webapp/src/main/webapp/WEB-INF/portlet.xml.
eXo Collaboration consists of three gadgets: eventslist, taskslist and messageslist. They are packaged in the csResources.war file.
Eventslist lists the maximum number of upcoming events, that is configurable by users. For example, they can set the preference list to 5 or 10 events.
Preferences
See preferences of this gadget in the following sample code:
<UserPref datatype="string" display_name="__MSG_baseurl__" name="url" required="true" value="/calendar"/>
<UserPref datatype="string" display_name="__MSG_subscribeurl__" name="subscribeurl" required="true" value="/portal/rest/private/cs/calendar/upcoming"/>
<UserPref datatype="string" default_value="10" display_name="__MSG_limit__" name="limit"/>
<UserPref datatype="enum" default_value="AM/PM" display_name="__MSG_format__" name="timeformat"/>
Details:
Preferences | Description |
---|---|
url | Link to the Calendar portlet. |
Subscribeurl | Link to the upcoming events. |
limit | The maximum number of upcoming events. |
timeformat | The time format for upcoming events. |
For more details on the preferences of gadgets, see here.
It uses the upcomingEvent service in the following package: org.exoplatform.webservice.cs.calendar.CalendarWebservice.java.
Taskslist lists the maximum number of upcoming tasks that is configurable by users. For example, they can set the preference list to 5 or 10 tasks.
Preferences
See the preferences of this gadget in the following sample code:
<UserPref datatype="hidden" default_value="/calendar:/portal/rest/private/cs/calendar/upcoming:10:AM/PM:Default" name="setting"/>
Accordingly, setting collects all the configuration of upcoming tasks and add some more functions to help developers change the configuration of the default skin.
It uses upcomingEvent service in the following package: org.exoplatform.webservice.cs.calendar.CalendarWebservice.java.
It lists the maximum number of unread messages, that is configurable by users.
Preferences
See the prefereces of this gadget in the following sample code:
<UserPref datatype="hidden" display_name="__MSG_baseurl__" name="url" required="true" value="/mail"/>
<UserPref datatype="hidden" display_name="__MSG_subscribeurl__" name="subscribeurl" required="true" value="/portal/rest/private/cs/mail/unreadMail"/>
<UserPref datatype="hidden" default_value="5" display_name="__MSG_limit__" name="limit"/>
<UserPref datatype="hidden" default_value="" display_name="__MSG_account__" name="account"/>
<UserPref datatype="hidden" default_value="" display_name="__MSG_folder__" name="folder"/>
<UserPref datatype="hidden" default_value="" display_name="__MSG_tag__" name="tag"/>
Details:
Preferences | Description |
---|---|
Url | The URL of the Mail Application. |
Subscribeurl | The link to upcoming messages. |
Limit | The number of displayed unread messages that is set by users. |
Account | The mail account in the Mail application. |
Folder | The folder which consists of unread messages. |
Tag | The tags in all unread messages. |
It uses the unreadMail service in the following package: org.exoplatform.webservice.cs.mail.MailWebservice.java.
This chapter describes about configurations used in eXo Collaboration. It consists of the following main sections:
This table shows some main components that take init-param in the applications of eXo Collaboration:
Applications | Components | Description |
---|---|---|
Calendar | CalendarServiceImpl | It is a service that manages calendars in the Calendar application of eXo Collaboration. |
Chat |
|
It is a service that saves the chat history of users. It is a service that processes messages of chat users, basing on the XMPP Protocol. It is a component that controls the presence status of chat users. |
Contact | ContactServiceImpl | It is a service that supplies functions to manage contacts in the Address Book application of eXo Collaboration. |
Webservice | AddActionsPlugin | It is used to register a listener for the actions on the nodes. |
The configuration of the Calendar application is applied mainly in /eXoApplication/calendar/service/src/main/resources/conf/portal/configuration.xml.
Use the CalendarService to configure the Calendar. The following information will explain details of its configuration. When this configuration file is executed, the component named org.exoplatform.calendar.service.impl.CalendarServiceImpl will process actions of the Calendar application.
<component>
<key>org.exoplatform.calendar.service.CalendarService</key>
<type>org.exoplatform.calendar.service.impl.CalendarServiceImpl</type>
<init-params>
<properties-param>
<name>eventNumber.info</name>
<property name="eventNumber" value="100"/>
</properties-param>
</init-params>
</component>
Details:
Properties-Param | Property name | Description | Possible Value | Default Value |
---|---|---|---|---|
eventNumber | eventNumber | The number of events in a calendar. | interger | 100 |
The configuration of historyImpl is found in the /extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/chat/chat-service-configuration.xml. When this configuration file is executed, the component named org.exoplatform.services.xmpp.history.impl.jcr.HistoryImpl initializes all the configured parameters.
<component>
<type>org.exoplatform.services.xmpp.history.impl.jcr.HistoryImpl</type>
<init-params>
<value-param>
<name>workspace</name>
<value>collaboration</value>
</value-param>
<value-param>
<name>repository</name>
<value>repository</value>
</value-param>
<value-param>
<name>path</name>
<value>exo:applications/eXoChat/history</value>
</value-param>
</init-params>
</component>
Details:
Value-Param | Description | Possible Values | Default Value |
---|---|---|---|
workspace | The workspace name in JCR where history data is stored. | string | collaboration |
repository | The repository name in JCR where history data is stored. | string | repository |
path | The JCR path to the location where history data is stored. | string | exo:applications/eXoChat/history . |
The configuration of the XMPPMessenger component is found in /extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/chat/chat-service-configuration.xml. It helps eXo Collaboration connect the Openfire instance.
<component>
<type>org.exoplatform.services.xmpp.connection.impl.XMPPMessenger</type>
<init-params>
<properties-param>
<name>openfire-connection-conf</name>
<property name="host" value="127.0.0.1"/>
<property name="port" value="5222"/>
</properties-param>
<properties-param>
<name>send-file</name>
<property name="timeout" value="7200000"/>
</properties-param>
</init-params>
</component>
Details:
Properties-param | Property name | Description | Possible Values | Default Value |
---|---|---|---|---|
openfire-connection-conf |
|
IP address or hostname for the openfire server. Port to connect on the Openfire server. Should be the same that is set in the Openfire configuration "Client to Server". |
|
127.0.0.1 5222 |
send-file | timeout | The timeout before aborting attempt to establish a file transfer. | integer | 7200000 |
The configuration of the DefaultPresenceStatus component is found in /extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/chat/chat-service-configuration.xml.
<component>
<type>org.exoplatform.services.presence.DefaultPresenceStatus</type>
<init-params>
<properties-param>
<name>presence-status</name>
<property name="mode" value="Free to chat"/>
</properties-param>
</init-params>
</component>
Details:
Properties-param | Property name | Description | Possible Values | Default Value |
---|---|---|---|---|
presence-status | mode | Show the present status of users. | string | Free to chat |
The configuration of the ContactService component is found in eXoApplication/contact/service/src/main/resources/conf/portal/configuration.xml.
When the server starts, the configuration file which contains the declaration of ContactService component is executed. A ContactService component is then created with params and plugins in the configuration file.
<component>
<key>org.exoplatform.contact.service.ContactService</key>
<type>org.exoplatform.contact.service.impl.ContactServiceImpl</type>
<init-params>
<values-param>
<name>UserCanSeeAllGroupAddressBooks</name>
<description>User can see all GroupAddressBooks or only GroupAddressBooks that the user has at least one membership</description>
<value>false</value>
</values-param>
<values-param>
<name>NonPublicGroups</name>
<description>Groups that should not be displayed in broadcast list. Wildcards may be used in groups name</description>
</values-param>
</init-params>
</component>
Values-param | Description | Possible Values | Default Value |
---|---|---|---|
UserCanSeeAllGroupAddressBooks | User can see all GroupAddressBooks or only GroupAddressBooks that the user has at least one membership. | true/false | false |
NonPublicGroups | Groups that should not be displayed in the broadcast list. Wildcards may be used in groups name. | true/false | N/A |
The following table describes the main functions of external component plugins:
Applications | Components | Description |
---|---|---|
Calendar | NewUserListener | Create default personal calendars. |
NewGroupListener
| Create default group calendars. | |
NewMembershipListener | Share calendars to members of a specific group. | |
ReminderPeriodJob
| Execute sending reminder emails to users. | |
PopupReminderPeriodJob | Open a pop-up reminder on the browser of users. | |
AddActionsPlugin | Enable the systems to automatically update the updated date of events/tasks in a calendar when contents of these events/tasks are changed. | |
Chat | HistoryPeriodJob | Save the chat history of users. |
RequestFilterComponentPlugin | Delete the session of a user when the browser is suddenly closed or the session is changed. | |
AuthenticationLoginListener
| Start the session and log in the chat server. | |
AuthenticationLogoutListener | End the session and log out the chat server. | |
Contact | NewUserListener | Create personal contact data for users. |
NewMembershipListener | Create address book for a specific group. | |
UpdateUserProfileListener | Update the personal profile of a user when it is changed on the portal. | |
Content | RSSContentPlugin | The formatter used to analyze the data from a RSS resource. |
DescriptionPlugin | Represent the data from a RSS resource. | |
AuthenticationLogoutListener | Stop checking mails of a user when he logs out. | |
Social Intergration | CalendarDataInitialize | Create a calendar for a group in a specific space. |
ContactDataInitialize | Create an address book for a group in a specific space. | |
ContactSpaceActivityPublisher | Customize the activity status of a specific space when an event happens on an address book. | |
CalendarSpaceActivityPublisher | Customize the activity status of a specific space when an event happens on a calendar. | |
PortletPreferenceRequiredPlugin | Declare the application that will automatically create database. |
This section describes the configuration of external component plugin used to implement the Calendar application.
Each user can have a default personal calendar created. Use the NewUserListener to configure that. To use the plugin in the component configuration, you must use the target-component:
<target-component>org.exoplatform.services.organization.OrganizationService</target-component>
The configuration is applied mainly in extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/calendar/calendar-service-configuration.xml.
<component-plugin>
<name>calendar.new.user.event.listener</name>
<set-method>addListenerPlugin</set-method>
<type>org.exoplatform.calendar.service.impl.NewUserListener</type>
<description>description</description>
<init-params>
<value-param>
<name>defaultEventCategories</name>
<value>Meeting,Calls,Clients,Holiday,Anniversary</value>
</value-param>
<value-param>
<name>defaultCalendarCategory</name>
<value>My group</value><!-- Single value -->
</value-param>
<value-param>
<name>defaultCalendar</name>
<value>Default</value>
</value-param>
<!--Params for default calendar setting -->
<value-param>
<name>viewType</name>
<value>1</value>
</value-param>
<value-param>
<name>timeInterval</name>
<value>15</value><!-- in minutes -->
</value-param>
<value-param>
<name>weekStartOn</name>
<value>2</value>
</value-param>
<value-param>
<name>dateFormat</name>
<value>MM/dd/yyyy</value>
</value-param>
<value-param>
<name>timeFormat</name>
<value>HH:mm</value> <!-- HH:mm/hh:mm a -->
</value-param>
<value-param>
<name>localeId</name>
<value>BEL</value>
</value-param>
<value-param>
<name>timezoneId</name>
<value>Europe/Brussels</value>
</value-param>
<value-param>
<name>baseUrlForRss</name>
<value/>
</value-param>
<value-param>
<name>isShowWorkingTime</name>
<value>false</value><!-- boolean true/false -->
</value-param>
<value-param>
<name>workingTimeBegin</name>
<value>08:00</value><!-- -->
</value-param>
<value-param>
<name>workingTimeEnd</name>
<value>18:00</value><!-- -->
</value-param>
<values-param>
<name>ignoredUsers</name>
<description>Definition users to ignore create default calendar</description>
<!-- <value>demo</value> <value>marry</value> -->
</values-param>
</init-params>
</component-plugin>
Details:
Name: calendar.new.user.event.listener
- The unique key to avoid duplicate names. Users can change it.
Set-method: addListenerPlugin
- The function is executed at the target of the component to register NewUserListener.
Type: org.exoplatform.calendar.service.impl.NewUserListener
- The class is set up to execute the creation of database.
Description: It is a plugin used to create default personal calendars.
See the details about the init-params of the component in the following table:
Value-params | Possible value | Default value | Description |
---|---|---|---|
defaultEventCategories |
String (Comma separated list of category names)
|
Meeting,Calls,Clients,Holiday,Anniversary
| Default event categories for users. |
defaultCalendarCategory |
String
|
Default
| Name of the calendar group. |
viewType |
0-6 (see below)
|
1
| Default view after user logs in and goes to the Calendar portlet. |
timeInterval |
integer in minutes
|
15
| The time unit interval when you drag and move the event (in Day and Week views only). |
weekStartOn |
1-7 (see below)
|
2
| Day to use as the beginning of the week. It only affects the Week view. |
dateFormat |
valid Java Date format
|
MM/dd/yyyy
| The display format for dates. |
timeFormat |
valid Java Date format
|
HH:mm
| The display format for time. |
localeId |
valid locale ID
|
BEL
| Id of the geographic locale. |
timezoneIds |
valid TimeZone id
|
Europe
| User time zone. |
baseUrlForRss |
none
|
none
| The URL to publish the RSS content. |
isShowWorkingTime |
true/false
|
false
| Indicate if the working time should be highlighted in the Day view. |
workingTimeBegin |
time in timeFormat
|
08:00
| The start time in working time. |
workingTimeEnd |
time in timeFormat
|
18:00
| The end time in working time. |
ignoredUsers |
user id, use multiple by each line
|
demo/marry
| Definition users to ignore creating the default calendar. |
The viewType parameter is encoded by a number as follow:
0 : Day view
1 : Week view
2 : Month view
3 : Year view
4 : List view
5 : Schedule view
6 : Working days view
The weekStartOn parameter is encoded as follow:
1 : Sunday
2 : Monday
3 : Tuesday
4 : Wednesday
5 : Thursday
6 : Friday
7 : Saturday
To use the plugin in the component configuration, you must use the target-component:
<target-component>org.exoplatform.services.organization.OrganizationService</target-component>
The configuration is applied mainly in extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/calendar/calendar-service-configuration.xml.
<component-plugin>
<name>calendar.new.group.event.listener</name>
<set-method>addListenerPlugin</set-method>
<type>org.exoplatform.calendar.service.impl.NewGroupListener</type>
<description>description</description>
<init-params>
<value-param>
<name>defaultEditPermission</name>
<value>*.*</value><!-- Multi value membership, use coma (,) to split values -->
</value-param>
<value-param>
<name>defaultViewPermission</name>
<value>*.*</value>
</value-param>
<value-param>
<name>defaultLocale</name>
<value>BEL</value>
</value-param>
<value-param>
<name>defaultTimeZone</name>
<value>Europe/Brussels</value>
</value-param>
<values-param>
<name>ignoredGroups</name>
<description>Definition group to ignore create default calendar</description>
<!-- <value>/platform/guests</value> -->
<value>/spaces/*</value> <!-- single value, use more <value> tags to add more group -->
</values-param>
</init-params>
</component-plugin>
Details:
Name: calendar.new.group.event.listener
- The unique key to avoid duplicate names. Users can change it.
Set-method: addListenerPlugin
- The function is executed at the target of the component to register NewGroupListener.
Type: org.exoplatform.calendar.service.impl.NewGroupListener
- The class which is set up to execute the creation of database.
Description - It is the plugin used to create default group calendars.
See the details about the init-params of the component in the following table:
Value-params | Possible values | Default values | Description |
---|---|---|---|
defaultEditPermission |
User id (Multi value membership, use coma (,) to split values) |
. means that all members in that group can modify and add, remove a calendar, events/tasks of the calendar
| The default permission assigned to membership in a specific group to edit calendars and events/tasks of the calendar. |
defaultViewPermission |
User id (Multi value membership, use coma (,) to split values) |
. means that all members in that group can view this calendar and all the events/tasks of this calendar.
| The default permission assigned to membership in a specific group to view a calendar and events /tasks of the calendar. |
defaultLocale |
Valid locade id | BEL (see more locale ids http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html )
| The default locale of the calendar. |
defaultTimeZone |
Valid timezone id | Europe/Brussels (see more for timeZone ids http://www.unicode.org/cldr/data/docs/design/formatting/zone_log.html#windows_ids)
| The default time zone of the calendar. |
ignoredGroups |
Group id (use line to define multiple value) | /platform/guests
| Definition group to ignore create the default calendar. |
To use the plugin in the component configuration, you must use the target-component:
<target-component>org.exoplatform.services.organization.OrganizationService</target-component>
The configuration is applied mainly in extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/calendar/calendar-service-configuration.xml.
<component-plugin>
<name>calendar.new.membership.event.listener</name>
<set-method>addListenerPlugin</set-method>
<type>org.exoplatform.calendar.service.impl.NewMembershipListener</type>
<description>description</description>
</component-plugin>
Details:
Name: calendar.new.membership.event.listener
- The unique key to avoid duplicate names. Users can change it.
Set-method: addListenerPlugin
- The function which is executed at the target of the component.
Type: org.exoplatform.calendar.service.impl.NewMembershipListener
- The class which is set up to execute the creation of database.
Description: It is a plugin used to execute sending reminder emails to users.
The Calendar application of eXo Collaboration can send event reminders by using the email reminder plugin configuration. You will probably need to adjust this configuration to meet your own needs. The feature is based on a periodic poll of the stored reminders.
You must use the following target component to use the plugin in this configuration:
<target-component>org.exoplatform.services.scheduler.JobSchedulerService</target-component>
The configuration is applied in extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/cs-configuration.xml.
<component-plugin>
<name>RecordsJob</name>
<set-method>addPeriodJob</set-method>
<type>org.exoplatform.calendar.service.ReminderPeriodJob</type>
<description>add e-mail reminder job to the JobSchedulerService</description>
<init-params>
<properties-param>
<name>job.info</name>
<description>save the monitor data periodically</description>
<property name="jobName" value="ReminderJob"/>
<property name="groupName" value="CollaborationSuite"/>
<property name="job" value="org.exoplatform.calendar.service.ReminderJob"/>
<property name="repeatCount" value="0"/>
<property name="period" value="180000"/>
<property name="startTime" value="+0"/>
<property name="endTime" value=""/>
</properties-param>
</init-params>
</component-plugin>
Details:
Name: RecordsJob
- The name of a schedule job.
Set-method: addPeriodJob
- The plugin which registers the method.
Type: org.exoplatform.calendar.service.ReminderPeriodJob
- A class that executes to transfer data into database of Job Scheduler.
Description: Add email reminder job to the JobSchedulerService.
See details about the init-params of the component in the following table:
Properties-param | Description | Property names | Description | Possible values | Default values |
---|---|---|---|---|---|
job.info | Save the monitor data periodically. | jobName | The name of job | String | ReminderJob
|
groupName | The name of group job. | String | CollaborationSuite | ||
job | The name of actual job class. | Class path | org.exoplatform.calendar.service.ReminderJob | ||
repeatCount | How many times to run this job. | Long | 0, ( use '0' which means 'run forever) | ||
period | The time interval (millisecond) between job executions. | Long | 180000 | ||
startTime | The time when the job starts running. | Integer | +0 | ||
endTime | The time when the job ends running. | Integer | none |
You must use the following target component to use the plugin in this configuration:
<target-component>org.exoplatform.services.scheduler.JobSchedulerService</target-component>
The configuration is applied in extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/cs-configuration.xml.
<component-plugin>
<name>PopupRecordsJob</name>
<set-method>addPeriodJob</set-method>
<type>org.exoplatform.calendar.service.PopupReminderPeriodJob</type>
<description>add popup reminder job to the JobSchedulerService</description>
<init-params>
<properties-param>
<name>job.info</name>
<description>save the monitor data periodically</description>
<property name="jobName" value="PopupReminderJob"/>
<property name="groupName" value="CollaborationSuite"/>
<property name="job" value="org.exoplatform.calendar.service.PopupReminderJob"/>
<property name="repeatCount" value="0"/>
<property name="period" value="6000"/>
<property name="startTime" value="+0"/>
<property name="endTime" value=""/>
</properties-param>
<properties-param>
<name>popupreminder.info</name>
<description>save the monitor data periodically</description>
<property name="portalName" value="portal"/>
</properties-param>
</init-params>
</component-plugin>
Details:
Name: PopupRecordsJob
- The name of the job.
Set-method: addPeriodJob
- The plugin registering method.
Type: org.exoplatform.calendar.service.PopupReminderPeriodJob
- The class which executes to transfer the data into database of Job Scheduler.
Description: Add popup reminder job to the JobSchedulerService.
See details about the init-params of the component in the following table:
Properties-param: job.info. This param saves the monitor data periodically and includes the following sub-params:
Properties-param | Description | Property names | Description | Possible values | Default values |
---|---|---|---|---|---|
job.info | Save the monitor data periodically. |
jobName
| The name of job. |
String
|
PopupReminderJob
|
groupName
| The name of group job. |
String
|
CollaborationSuite
| ||
job
| The name of actual job class. |
Class path
|
org.exoplatform.calendar.service.PopupReminderJob
| ||
repeatCount
| How many times to run this job. |
Long
|
0, ( use '0' which means 'run forever)
| ||
period
| The time interval (millisecond) between job executions. |
Long
|
6000
| ||
startTime
| The time when the job starts running. |
Long
|
+0
| ||
endTime
| The time when the job ends running. |
Integer
|
None
| ||
popupreminder.info | Save the monitor data periodically. |
portalName
| The name of the portal. |
String
|
portal
|
The configuration of the AddActionsPlugin is found in WEB-INF/cs-extension/cs/webservice/webservice-configuration.xml.
It is used to register the listener named org.exoplatform.webservice.cs.LastUpdateAction
and it is executed, basing on eventTypes.
<component>
<type>org.exoplatform.services.jcr.impl.ext.action.SessionActionCatalog</type>
<component-plugins>
<component-plugin>
<name>Last Update Action</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.jcr.impl.ext.action.AddActionsPlugin</type>
<description>add actions plugin</description>
<init-params>
<object-param>
<name>actions</name>
<object type="org.exoplatform.services.jcr.impl.ext.action.AddActionsPlugin$ActionsConfig">
<field name="actions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.impl.ext.action.ActionConfiguration">
<field name="eventTypes">
<string>addNode,changeProperty</string>
</field>
<field name="nodeTypes">
<string>exo:calendarEvent</string>
</field>
<field name="actionClassName">
<string>org.exoplatform.webservice.cs.LastUpdateAction</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</component-plugins>
</component>
object-param: Actions
- The name of the object.
object type: org.exoplatform.services.jcr.impl.ext.action.AddActionsPlugin$ActionsConfig
- A class used to register the following field names in the table below:
Field name | String | Description |
---|---|---|
eventTypes | addNode,changeProperty | The type of the event. |
nodeTypes | exo:calendarEvent
| The type of the node. |
actionClassName | org.exoplatform.webservice.cs.LastUpdateAction | The registration class to execute the actions that the plugin requires. |
The Chat Configuration is applied in /extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/chat/chat-service-configuration.xml.
The Chat portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
<external-component-plugins>
<target-component>org.exoplatform.services.scheduler.JobSchedulerService</target-component>
<component-plugin>
<name>ChatRecordsJob</name>
<set-method>addPeriodJob</set-method>
<type>org.exoplatform.services.xmpp.connection.impl.HistoryPeriodJob</type>
<description>add chat messages from Openfire Server to History</description>
<init-params>
<properties-param>
<name>job.info</name>
<description>save the monitor data periodically</description>
<property name="jobName" value="messageToHistoricalMessageJob"/>
<property name="groupName" value="CollaborationSuite"/>
<property name="job" value="org.exoplatform.services.xmpp.connection.impl.HistoryJob"/>
<property name="repeatCount" value="0"/>
<property name="period" value="3000"/>
<property name="startTime" value="+0"/>
<property name="endTime" value=""/>
</properties-param>
<properties-param>
<name>history.info</name>
<description>save the monitor data periodically</description>
<property name="logBatchSize" value="50"/>
</properties-param>
</init-params>
</component-plugin>
</external-component-plugins>
Details:
Name: ChatRecordsJob
- The name of the job.
Set-method: addPeriodJob
- The plugin which registers the method.
Type: org.exoplatform.services.xmpp.connection.impl.HistoryPeriodJob
- A class which executes to transfer the data into the database of Job Scheduler.
Description: It is used to save chat messages from Openfire Server to History.
See details about the init-params of the component in the following table:
Properties-param | Description | Property names | Description | Possible values | Default values |
---|---|---|---|---|---|
job.info | Save the monitor data periodically. | jobName | The name of job. | String | messageToHistoricalMessageJob
|
groupName | The name of group name. | String | CollaborationSuite | ||
job | The name of actual job class. | Class path | org.exoplatform.services.xmpp.connection.impl.HistoryJob | ||
repeatCount | How many times to run this job. | integer | 0 ( use '0' which means 'run forever) | ||
period | The time interval (millisecond) between job executions. | Long | 3000 | ||
startTime | The time the job starts running. | Long | +0 | ||
endTime | The time the job ends running. | Long | none | ||
history.info | Save the monitor data periodically. | logBatchSize | The maximum number of messages in the cache are saved once the job runs. | Integer | 50 |
<external-component-plugins>
<target-component>org.exoplatform.services.rest.impl.RequestHandlerImpl</target-component>
<component-plugin>
<name>ws.rs.request.filter</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.rest.impl.RequestFilterComponentPlugin</type>
<init-params>
<value-param>
<name>RESTXMPPServiceFilter</name>
<value>org.exoplatform.services.xmpp.rest.filter.RESTXMPPServiceFilter</value>
</value-param>
</init-params>
</component-plugin>
</external-component-plugins>
Details:
Name: ws.rs.request.filter
- The name of the filter.
Set-method: addPlugin
- The plugin which registers the method.
Type: org.exoplatform.services.rest.impl.RequestFilterComponentPlugin
- The class which executes the requests of the plugin.
Description: It is used to delete the session of a user when he suddenly closes the browser or changes the session.
See details about the init-params of the component in the following table:
Value-param | Description | Possible value | Default value |
---|---|---|---|
RESTXMPPServiceFilter | The name of the filter. | Class path | org.exoplatform.services.xmpp.rest.filter.RESTXMPPServiceFilter
|
Two functions, including login and logout of XMPPRestService, are responsible for creating a new XMPPSessionImpl and destroying an existing XMPPSessionImpl. They can be called by listeners: AuthenticationLoginListener, AuthenticationLogoutListener or from client(browser) through the REST protocol (jabberLogin, jabberLogout in UIMainChatWindow.js). You must use the same target component for two external component plugins:
<target-component>org.exoplatform.services.listener.ListenerService</target-component>
<component-plugin>
<name>exo.core.security.ConversationRegistry.register</name>
<set-method>addListener</set-method>
<type>org.exoplatform.services.xmpp.connection.impl.AuthenticationLoginListener</type>
<description>description</description>
</component-plugin>
Details:
Name: exo.core.security.ConversationRegistry.register
- The name of plugin.
Set-method: addListener
- The plugin which registers the method.
Type: org.exoplatform.services.xmpp.connection.impl.AuthenticationLoginListener
- The class to execute the requests of the plugin.
Description: It is used to start the session and log in the chat server.
<component-plugin>
<name>exo.core.security.ConversationRegistry.unregister</name>
<set-method>addListener</set-method>
<type>org.exoplatform.services.xmpp.connection.impl.AuthenticationLogoutListener</type>
<description>description</description>
</component-plugin>
Details:
Name: exo.core.security.ConversationRegistry.register
- The name of plugin.
Set-method: addListener
- The plugin which registers the method.
Type: org.exoplatform.services.xmpp.connection.impl.AuthenticationLogoutListener
- A class to execute the requests of the plugin.
Description: It is used to end the session and log in the chat server.
The Contact Application is configured by three external component plugins: NewUserListener
, NewMembershipListener
and UpdateUserProfileListener
. They use the same target component:
<target-component>org.exoplatform.services.organization.OrganizationService</target-component>
The Contact configuration is found in extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/contact/contact-service-configuration.xml.
<component-plugin>
<name>contact.new.user.event.listener</name>
<set-method>addListenerPlugin</set-method>
<type>org.exoplatform.contact.service.impl.NewUserListener</type>
<description>description</description>
</component-plugin>
Details:
Name: contact.new.user.event.listener
- The name of listener.
Set-method: addListenerPlugin
- The plugin which registers the method.
Type: org.exoplatform.contact.service.impl.NewUserListener
- A class that executes all requirements of the plugin.
Description: It is used to initialize personal contact data for users.
<component-plugin>
<name>contact.new.membership.event.listener</name>
<set-method>addListenerPlugin</set-method>
<type>org.exoplatform.contact.service.impl.NewMembershipListener</type>
<description>description</description>
</component-plugin>
Details:
Name: contact.new.membership.event.listener
- The name of the listener.
Set-method: addListenerPlugin
- The plugin which registers the method. Keep this value.
Type: org.exoplatform.contact.service.impl.NewMembershipListener
- The class which executes all requirements of the plugin.
Description: It is used to initialize an address book for a specific group.
<component-plugin>
<name>contact.new.userprofile.event.listener</name>
<set-method>addListenerPlugin</set-method>
<type>org.exoplatform.contact.service.impl.UpdateUserProfileListener</type>
<description>description</description>
</component-plugin>
Details:
Name: contact.new.userprofile.event.listener
- The name of the listener.
Set-method: addListenerPlugin
- The plugin which registers the method. Keep this value.
Type: org.exoplatform.contact.service.impl.UpdateUserProfileListener
- The class which executes all the requirements of the plugin.
Description: It is used to update the personal profile of a user when he changes it on the portal.
The Content application, such as RSS reader of eXo Collaboration, is configured by two external component plugins: RSSContentPlugin and DescriptionPlugin. Both the external components plugins use the same target component:
<target-component>org.exoplatform.content.service.ContentDAO</target-component>
This content configuration is applied in extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/content/content-service-configuration.xml.
<component-plugin>
<name>rssreader.listener</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.content.service.RSSContentPlugin</type>
<description>rss reader plugin</description>
</component-plugin>
Details:
Name: rssreader.listener
- The name of the listener.
Set-method: addPlugin
- The plugin which registers the method. Keep this value.
Type: org.exoplatform.content.service.RSSContentPlugin
- A class which extends ContentPlugin and implements the loadContentMeta method to get content items.
Description: It is a formater used to analyze the data from a RSS resource.
<component-plugin>
<name>description.listener</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.content.service.DescriptionPlugin</type>
<description>Description plugin</description>
</component-plugin>
Details:
Name: description.listener
- The name of the listener.
Set-method: addPlugin
- The plugin registering method. Keep this value.
Type: org.exoplatform.content.service.DescriptionPlugin
- A class which executes all requirements of the plugin.
Description: It is a plugin to represent data from a RSS source.
The Mail portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
In the Mail application of eXo Collaboration, when a user checks messages for one account, the remote mailbox fetch is performed as a background job. Before eXo Collaboration 1.2, the job was continued until all messages had been retrieved or when the user stopped the check through the UI. Hence, even when a user was not logged in, the background job was continued. This can be the resource intensive for the server if many users have large mailboxes. Since eXo Collaboration 1.2, one capability is added to halt the background job when the user session terminates (logout or timeout). It makes eXo Collaboration more friendly with server resources. If you want to activate this feature, you need to add a bunch of the xml congifuration in /extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/mail/mail-service-configuration.xml:
<external-component-plugins>
<target-component>org.exoplatform.services.listener.ListenerService</target-component>
<component-plugin>
<name>exo.core.security.ConversationRegistry.unregister</name>
<set-method>addListener</set-method>
<type>org.exoplatform.mail.service.AuthenticationLogoutListener</type>
<description>description</description>
</component-plugin>
</external-component-plugins>
Details:
Name: exo.core.security.ConversationRegistry.unregister
- The name of listener.
Set-method: addListener
The plugin which registers the method. Keep this value.
Type: org.exoplatform.mail.service.AuthenticationLogoutListener
- A class which executes all requirements of the plugin.
Description: It is a plugin used to stop checking mails of a user when he logs out.
Since eXo Collaboration 2.2.0, MailSettingConfigPlugin is used to define the behavior, for example, showing/hiding fields and checking/unchecking checkboxes, of email account settings in the mail-server-configuration.xml file. It allows administrators to preconfigure all settings and to specify if end-users have the modification right on each specific setting or not.
<external-component-plugins>
<target-component>org.exoplatform.mail.service.MailService</target-component>
<component-plugin>
<name>cs.mail.service.settings</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.mail.service.MailSettingConfigPlugin</type>
<description>description</description>
<init-params>
<object-param>
<name>leaveOnServer</name>
<description>options to keep a copy of the message on the mail server after eXo Mail has downloaded the message</description>
<object type="org.exoplatform.mail.service.MailSettingConfig">
<field name="name"><string>leaveOnServer</string></field>
<field name="userAllowed"><boolean>true</boolean></field>
<field name="defaultValue"><string>true</string></field>
</object>
</object-param>
<object-param>
<name>incomingServer</name>
<description>default incoming server to check for new mails.</description>
<object type="org.exoplatform.mail.service.MailSettingConfig">
<field name="name"><string>incomingServer</string></field>
<field name="userAllowed"><boolean>true</boolean></field>
<field name="defaultValue"><string>imap.gmail.com</string></field>
</object>
</object-param>
<object-param>
<name>incomingPort</name>
<description>default port incoming server to check for new mails.</description>
<object type="org.exoplatform.mail.service.MailSettingConfig">
<field name="name"><string>incomingPort</string></field>
<field name="userAllowed"><boolean>true</boolean></field>
<field name="defaultValue"><string>993</string></field>
</object>
</object-param>
<object-param>
<name>outgoingServer</name>
<description>description</description>
<object type="org.exoplatform.mail.service.MailSettingConfig">
<field name="name"><string>outgoingServer</string></field>
<field name="userAllowed"><boolean>true</boolean></field>
<field name="defaultValue"><string>smtp.gmail.com</string></field>
</object>
</object-param>
<object-param>
<name>outgoingPort</name>
<description>description</description>
<object type="org.exoplatform.mail.service.MailSettingConfig">
<field name="name"><string>outgoingPort</string></field>
<field name="userAllowed"><boolean>true</boolean></field>
<field name="defaultValue"><string>465</string></field>
</object>
</object-param>
<object-param>
<name>acceptIncomingSecureAuthentication</name>
<description>description</description>
<object type="org.exoplatform.mail.service.MailSettingConfig">
<field name="name"><string>acceptIncomingSecureAuthentication</string></field>
<field name="userAllowed"><boolean>true</boolean></field>
<field name="defaultValue"><string>true</string></field>
</object>
</object-param>
<object-param>
<name>incomingSecureAuthentication</name>
<description>description</description>
<object type="org.exoplatform.mail.service.MailSettingConfig">
<field name="name"><string>incomingSecureAuthentication</string></field>
<field name="userAllowed"><boolean>true</boolean></field>
<field name="defaultValue"><string>starttls</string></field>
</object>
</object-param>
<object-param>
<name>incomingAuthenticationMechanism</name>
<description>description</description>
<object type="org.exoplatform.mail.service.MailSettingConfig">
<field name="name"><string>incomingAuthenticationMechanism</string></field>
<field name="userAllowed"><boolean>true</boolean></field>
<field name="defaultValue"><string>plain</string></field>
</object>
</object-param>
<object-param>
<name>acceptOutgoingSecureAuthentication</name>
<description>description</description>
<object type="org.exoplatform.mail.service.MailSettingConfig">
<field name="name"><string>acceptOutgoingSecureAuthentication</string></field>
<field name="userAllowed"><boolean>true</boolean></field>
<field name="defaultValue"><string>true</string></field>
</object>
</object-param>
<object-param>
<name>outgoingSecureAuthentication</name>
<description>description</description>
<object type="org.exoplatform.mail.service.MailSettingConfig">
<field name="name"><string>outgoingSecureAuthentication</string></field>
<field name="userAllowed"><boolean>true</boolean></field>
<field name="defaultValue"><string>starttls</string></field>
</object>
</object-param>
<object-param>
<name>outgoingAuthenticationMechanism</name>
<description>description</description>
<object type="org.exoplatform.mail.service.MailSettingConfig">
<field name="name"><string>outgoingAuthenticationMechanism</string></field>
<field name="userAllowed"><boolean>true</boolean></field>
<field name="defaultValue"><string>plain</string></field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
Details:
Name: cs.mail.service.settings
- The name of the mail settings.
Set-method: addPlugin
- The plugin which registers the method.
Type: org.exoplatform.mail.service.MailSettingConfigPlugin
- The plugin's class name.
object type: org.exoplatform.mail.service.MailSettingConfig
- A class of object that contains a specific setting.
Description: Describes what the setting is or what the setting does.
Object-param | Desciption |
---|---|
leaveOnServer | Options to keep the message on the mail server after it has been downloaded to the Mail application of eXo Collaboration. |
incomingServer | The default incoming server used to check new mails. |
incomingPort | The default port of the incoming server used to check new mails. |
outgoingServer | The default port of the outgoing server used to send new mails. |
outgoingPort | The default outgoing port to send new mails. |
acceptIncomingSecureAuthentication | Accept the secure authentication of the incoming server. |
incomingSecureAuthentication | The type of incoming secure authentication. |
incomingAuthenticationMechanism | The type of incoming authentication mechanism. |
acceptOutgoingSecureAuthentication | Accepts the secure authentication of the outgoing server. |
outgoingSecureAuthentication | The type of outgoing secure authentication. |
outgoingAuthenticationMechanism | The type of incoming authentication mechanism. |
The object parameters have the same field names, but the values of the parameters are different.
Field names | Description | Possible values |
---|---|---|
name | The field name in the account settings form. | String |
userAllowed | Allow users to edit the field in the account settings form or not. | Boolean |
defaultValue | The default value of the field in the account settings form. | String |
The Social Integration Configuration is applied in /extension/webapp/src/main/webapp/WEB-INF/cs-extension/cs/social-integration/social-integration-configuration.xml.
<external-component-plugins>
<target-component>org.exoplatform.social.core.space.spi.SpaceService</target-component>
<component-plugin>
<name>CalendarDataInitialize</name>
<set-method>addSpaceListener</set-method>
<type>org.exoplatform.cs.ext.impl.CalendarDataInitialize</type>
<init-params>
<value-param>
<name>portletName</name>
<value>CalendarPortlet</value>
</value-param>
</init-params>
</component-plugin>
</external-component-plugins>
Details:
Name: CalendarDataInitialize
- The name of plugin.
Set-method: addSpaceListener
- The plugin which registers the method.
Type: org.exoplatform.cs.ext.impl.CalendarDataInitialize
- A class that executes all requirements of the plugin.
Description: It is used to initialize a calendar for a group in a specific space.
See the details about the init-params of the component in the following table:
value-param | Description | Possible value | Default value |
---|---|---|---|
portletName | The name of the portlet | String | CalendarPortlet
|
<external-component-plugins>
<target-component>org.exoplatform.social.core.space.spi.SpaceService</target-component>
<component-plugin>
<name>ContactDataInitialize</name>
<set-method>addSpaceListener</set-method>
<type>org.exoplatform.cs.ext.impl.ContactDataInitialize</type>
<init-params>
<value-param>
<name>portletName</name>
<value>ContactPortlet</value>
</value-param>
</init-params>
</component-plugin>
</external-component-plugins>
Details:
Name: ContactDataInitialize
- The name of the plugin.
Set-method: addSpaceListener
- The plugin which registers the method.
Type: org.exoplatform.cs.ext.impl.ContactDataInitialize
- A class that executes all the requires of the plugin.
Description: It is a plugin used to initialize an address book for a group in a specific space.
See the details about the init-params of the component in the following table:
value-param | Possible value | Default value | Description |
---|---|---|---|
portletName | String | ContactPortlet
| The name of the portlet. |
<external-component-plugins>
<target-component>org.exoplatform.contact.service.ContactService</target-component>
<component-plugin>
<name>ContactEventListener</name>
<set-method>addListenerPlugin</set-method>
<type>org.exoplatform.cs.ext.impl.ContactSpaceActivityPublisher</type>
</component-plugin>
</external-component-plugins>
Details:
Name: ContactEventListener
- The name of the plugin.
Set-method: addListenerPlugin
- The plugin which registers the method.
Type: org.exoplatform.cs.ext.impl.ContactSpaceActivityPublisher
- A class that executes all requirements of the plugin.
Description: It is a plugin used to customize the activity status of a specific space when an event happens on an address book.
<external-component-plugins>
<target-component>org.exoplatform.calendar.service.CalendarService</target-component>
<component-plugin>
<name>CalendarEventListener</name>
<set-method>addEventListenerPlugin</set-method>
<type>org.exoplatform.cs.ext.impl.CalendarSpaceActivityPublisher</type>
</component-plugin>
</external-component-plugins>
Details:
Name: CalendarEventListener
- The name of the plugin.
Set-method: addEventListenerPlugin
- The plugin which registers the method.
Type: org.exoplatform.cs.ext.impl.CalendarSpaceActivityPublisher
- A class that executes all the requires of the plugin.
Description: It is a plugin used to customize the activity status of a specific space when an event happens on a calendar.
<external-component-plugins>
<target-component>org.exoplatform.social.core.space.spi.SpaceService</target-component>
<component-plugin>
<name>portlets.prefs.required</name>
<set-method>setPortletsPrefsRequired</set-method>
<type>org.exoplatform.social.core.application.PortletPreferenceRequiredPlugin</type>
<init-params>
<values-param>
<name>portletsPrefsRequired</name>
<value>CalendarPortlet</value>
<value>ContactPortlet</value>
</values-param>
</init-params>
</component-plugin>
</external-component-plugins>
Details:
Name: ortlets.prefs.required
- The name of the plugin.
Set-method: setPortletsPrefsRequired
- The plugin which registers the method.
Type: org.exoplatform.social.core.application.PortletPreferenceRequiredPlugin
- A class that executes all the requires of the plugin.
Description: It is a plugin used to declare the application that will automatically create database.
See the details about the init-params of the component in the following table:
value-param | Possible value | Default value | Description |
---|---|---|---|
portletsPrefsRequired | String | ContactPortlet / ContactPortlet
| The name of plugin added to SpaceService. |
Data injectors are used to create data for performance test. This part will describe which data injectors are implemented in eXo Collaboration and how to use them.
In eXo Collaboration, data injectors are implemented as plug-ins attached to the org.exoplatform.services.bench.DataInjectorService service and handled via RESTful requests. This service is normally registered to the portal container as a general component.
To use this service, add the following dependency to the Classpath of the server:
<dependency>
<groupId>org.exoplatform.commons</groupId>
<artifactId>exo.platform.commons.component</artifactId>
</dependency>
To activate the DataInjectorService component, you need to register it to a portal container by the following configuration:
<component>
<type>org.exoplatform.services.bench.DataInjectorService</type>
</component>
When you want to inject data for a specific product, you must implement a class which extends "org.exoplatform.services.bench.DataInjector" and register it to the DataInjectorService component as a plug-in.
In eXo Collaboration, there are three plug-ins attached to the DataInjectorService component:
ContactDataInjector
CalendarDataInjector
MailDataInjector
The ContactDataInjector plug-in is used to manage data injection of the Address Book application.
To use this plug-in, do as follows:
1. Add the following configuration to the configuration.xml file to register the plug-in to the DataInjectorService component:
<external-component-plugins>
<target-component>org.exoplatform.services.bench.DataInjectorService</target-component>
<component-plugin>
<name>ContactDataInjector</name>
<set-method>addInjector</set-method>
<type>org.exoplatform.contact.service.bench.ContactDataInjector</type>
<description>inject data for Contact</description>
<init-params>
<value-param>
<name>mA</name> <!-- maximum number of address books -->
<value>5</value>
</value-param>
<value-param>
<name>mC</name> <!-- maximum number of contacts per a address books -->
<value>10</value>
</value-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: ContactDataInjector
Set-method: addInjector
Type: org.exoplatform.contact.service.bench.ContactDataInjector
Parameters | Possible Values | Default Values | Description |
---|---|---|---|
mA | number | 5 | The maximum number of address books of the Address Book application in each injection. |
mC | number | 5 | The maximum number of contacts of an address book in each injection. |
2. Execute the injector by the RESTful request as follows:
http://{domain}/{rest}/bench/inject/ContactDataInjector?mA=5&mC=10
In which:
{domain}: The domain name of the server.
{rest}: The name of eXo REST service.
The CalendarDataInjector plug-in is used to manage data injection in the Calendar application.
To use this plug-in, do as follows:
1. Add the following configuration to the configuration.xml file to register the plug-in to the DataInjectorService component:
<external-component-plugins>
<target-component>org.exoplatform.services.bench.DataInjectorService</target-component>
<component-plugin>
<name>CalendarDataInjector</name>
<set-method>addInjector</set-method>
<type>org.exoplatform.calendar.bench.CalendarDataInjector</type>
<description>inject data for Calendar</description>
<init-params>
<value-param>
<name>mCt</name> <!-- maximum number of categories -->
<value>5</value>
</value-param>
<value-param>
<name>mEcat</name> <!-- maximum number of event categories -->
<value>10</value>
</value-param>
<value-param>
<name>mCal</name> <!-- maximum number of calendars -->
<value>10</value>
</value-param>
<value-param>
<name>mEv</name> <!-- maximum number of events -->
<value>5</value>
</value-param>
<value-param>
<name>mTa</name> <!-- maximum number of tasks -->
<value>5</value>
</value-param>
<value-param>
<name>typeOfInject</name> <!-- type of inject -->
<value>all</value> <!-- string all/public/private -->
</value-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which:
Name: CalendarDataInjector
Set-method: addInjector
Type: org.exoplatform.calendar.bench.CalendarDataInjector
Parameters | Possible Values | Default Values | Description |
---|---|---|---|
mCt | number | 5 | The maximum number of categories in each injection. |
mEcat | number | 10 | The maximum number of event categories in each injection. |
mCal | number | 10 | The maximum number of calendars in each injection. |
mEv | number | 5 | The maximum number of events in one calendar in each injection. |
mTa | number | 5 | The maximum number of tasks in one calendar in each injection. |
typeOfInject | String | all | The type of injection, including "public", "private" and "all". If the type is set as "public", only public calendars are created. If the type is set as "private", only personal calendars are create. If the type is set as "all", both the public and private ones are created. |
2. Execute the injector by the RESTful request as follows.
http://{domain}/{rest}/bench/inject/CalendarDataInjector?mCt=5&mEcat=10&mCal=10&mEv=20&mTa=20&typeOfInject=private
The MailDataInjector is used to manage data injection in the Mail application.
Because of the quite complicated architecture of the Mail application in eXo Collaboration, the injector uses a simple mail server (a mock server) to simulate the way a mail server works. This will create real mail data without mocking effort from the injector and create a reliable testing environment.
To use the injector, do as follows:
1. Add the Greenmail library to the classpath of the web server (in tomcat, copy it to the lib folder). The library is Greenmail 1.3.1b but including some bug fixes which are not updated in the counterpart version of Icegreen. (To have the library, contact eXo Support team).
2. Initialize this component as a service of GateIn, then it will be invoked by MailDataInjector.
<component>
<type>org.exoplatform.mail.service.bench.SimpleMailServerInitializer</type>
</component>
3. Register MailDataInjector to DataInjectorService by the following configuration:
<external-component-plugins>
<target-component>org.exoplatform.services.bench.DataInjectorService</target-component>
<component-plugin>
<name>MailDataInjector</name>
<set-method>addInjector</set-method>
<type>org.exoplatform.mail.service.bench.MailDataInjector</type>
<description>inject data for Contact</description>
</component-plugin>
</external-component-plugins>
In which:
Name: MailDataInjector
Set-method: addInjector
Type: org.exoplatform.mail.service.bench.MailDataInjector
To insert mail data into the Mail application, the request link is as follows:
http://{domain}/{rest}/bench/inject/MailDataInjector/?users=mary,root&accounts=2,account&inPro=IMAP&check=true&msgs=100&attSize=100
Params | Values | Description |
---|---|---|
users | String | The list of users separated by commas. |
accounts | String | The number of accounts injected by the data injector. This value consists of two parts separated by commas: the first is the number of accounts of an user, the second is the prefix of the account Id. |
inPro | String | The incoming protocol. The possible values are: POP3 and IMAP. |
check | Boolean | Specify if checking mails after the data are created on the mail server or not. If the value is true, the injector will execute checking new message tasks sequentially. This task can take some time if the data are large. |
msgs | Number | The number of messages will be available in each account. |
attSize | Number | The size of an attachment. If it does not exist or is equal to 0, no file is attached to the mail message. |
To reject mail data from the Mail application, the request link is as follows:
http://{domain}/{rest}/bench/reject/MailDataInjector/?users=root&accounts=2,account
This link will request for removing 2 accounts of "root" of which Id starts with "account".
By default, such settings have been declared in "csdemo.war/WEB-INF/conf/csdemo/cs/bench-configuration.xml". Therefore, to save time, you should import the bench-configuration.xml file to "csdemo.war/WEB-INF/conf/configuration.xml", and then modify it as your purpose rather than create a new one.
The Chat service of eXo Collaboration is a Jabber engine powered by Openfire. eXo Platform will delegate the actual Jabber protocol communication to Openfire.
You have the full latitude to configure Openfire. There are two possible ways to do it:
The admin console: http://localhost:9090/.
The openfire.xml file in $openfire_home/conf/.
The Openfire server has a single configuration file called openfire.xml and located under the exo-openfire/conf directory. Configuration is based on properties expressed in an XML syntax. For example, to set the property prop.name.is.blah=value, you would write this xml snippet:
<prop>
<name>
<is>
<blah>value</blah>
</is>
</name>
</prop>
Openfire has an extensive list of configuration properties. You can read a list of all properties on this page: http://www.igniterealtime.org/community/docs/DOC-1061.
The eXo Collaboration bundle comes with a pre-configured Openfire server. It is bundled with some eXo plugins and configurations that allow connectivity with eXo Platform. The key properties for integration are:
provider.auth.className: An implementation of the AuthProvider interface for authentication of users on the Chat server.
provider.users.className: An implementation of the UserProvider interface to which Openfire will delegate users management.
provider.groups.className: An implementation of the GroupProvider interface to which Openfire will delegate groups management.
eXo Platform provides implementations for these 3 interfaces with ExoAuthProvider, ExoUserProvider, ExoGroupProvider. These implementations are based on the eXo REST framework and let you configure the endpoints within the openfire.xml file with additional properties:
Property | Default value | Description |
---|---|---|
eXo.env.serverBaseURL |
http://localhost:8080/##
| The base URL of the server. |
eXo.env.restContextName | rest | The context name of REST Web application. |
provider.authorizedUser.name | root
| The username to authenticate to access the HTTP REST service. |
provider.authorizedUser.password | gtn | The password matching with provider.authorizeduser.name. |
exoAuthProvider.authenticationURL |
/organization/authenticate/ | The URL to authenticate users. |
exoAuthProvider.authenticationMethod | POST | The HTTP method used for the authentication method. |
exoUserProvider.findUsersURL | /organization/xml/user/find-all/ | The URL to find all users. |
exoUserProvider.findUsersMethod | GET | The HTTP method used to find all users in the system. |
exoUserProvider.getUsersURL | /organization/xml/user/view-range/ | The URL to retrieve a range of users. |
exoUserProvider.getUsersMethod | GET | The HTTP method used for user/view-range. |
exoUserProvider.usersCountURL | /organization/xml/user/count | The URL to count the number of users. |
exoUserProvider.usersCountMethod | GET | The HTTP method used to count the number of users. |
exoUserProvider.userInfoURL | /organization/xml/user/info/ | The URL to get the information of users. |
exoUserProvider.userInfoMethod | GET | The HTTP method used to get the information of users. |
exoGroupProvider.groupInfoURL | /organization/xml/group/info/ | The URL to get the information of a group of users. |
exoGroupProvider.groupInfoMethod | GET | The HTTP method used to get the information of a group of users. |
exoGroupProvider.getGroupsAllURL | /organization/xml/group/view-all/ | The URL to view a list of all user groups. |
exoGroupProvider.getGroupsAllMethod | GET | The HTTP method used to view a list of all user groups. |
exoGroupProvider.getGroupsRangeURL | /organization/xml/group/view-from-to/ | The URL to list groups in a specific range. |
exoGroupProvider.getGroupsRangeMethod | GET | The HTTP method used to list groups in a specific range. |
exoGroupProvider.getGroupsForUserURL | /organization/xml/group/groups-for-user/ | The URL to list groups to which a user belongs. |
exoGroupProvider.getGroupsForUserMethod | GET | The HTTP method used to list groups to which a user belongs. |
exoGroupProvider.groupsCountURL | /organization/xml/group/count | The URL to count the number of groups. |
exoGroupProvider.groupsCountMethod | GET | The HTTP method used to count the number of groups. |
As you can see, the default settings will only work if eXo Platform is deployed on the same host as Openfire, on the port 8080.
restContextName is used to specify the Openfire server that is dedicated for the portal. If the eXo.env.restContextName system property exists, it will override this value.
The eXo.env.restContextName system property can be set by specifying the -D option to the Java command when running Openfire.
For example:
If the Openfire server is dedicated for the portal named "portal", the command will have the following format: java -DeXo.env.restContextName=rest -jar ../lib/startup.jar.
If the Openfire server is dedicated for the portal named "csdemo", the command will have following format: java -DeXo.env.restContextName=rest-csdemo -jar ../lib/startup.jar.
By default, the Openfire server is dedicated to the portal named "portal".
Openfire makes use of several ports for communication.
Interface | Port | Type | Description |
---|---|---|---|
All addresses | 5222 | Client to Server | The standard port for clients is to connect to the server. Connection may or may not be encrypted. You can update the security settings for this port. |
All addresses | 9090 & 9091 | Admin Console | The ports used for the unsecured and secured Openfire Admin Console accesses respectively. |
All addresses | 7777 | File Transfer Proxy | The port used for the proxy service that allows files to be transferred between two entities on the XMPP network. |
All addresses | 3478 & 3479 | STUN Service | The port used for the service that ensures connectivity between entities behind a NAT. |
You can view the table above in http://hostname:9090/index.jsp after you have logged into the Openfire's web console and also customize those ports by yourself.
To enable the propagation of identity across the Chat webapp, you are required to enable the SSO valve on the Tomcat-based Application server.
For the Jboss server, edit jboss/server/default/deploy/jboss-web.deployer/server.xml.
For the Tomcat server, edit tomcat/conf/server.xml.
The valve should already be there, you just need to uncomment it if it is not already done.
<Valve className="org.apache.catalina.authenticator.SingleSignOn"/>
In case of the cluster deployment, you may want to use ClusteredSingleSignOn
instead.
<Valve className="org.jboss.web.tomcat.service.sso.ClusteredSingleSignOn"/>
eXo Collaboration is a JCR-based product, so data of eXo Collaboration are managed by the eXo-JCR service with each specific structure. The chapter aims at outlining the JCR structure of each application in eXo Collaboration through diagrams and then describing properties of main node types.
Each diagram shows nodes and their primary node types. Every node/child node must have only one primary node type represented in the round bracket () under the node/childnode, but may also have many mixin node types. Because mixin nodes cannot define the node structure like the primary nodes, they are not shown in the diagrams and their properties hereafter are not described.
This chapter describes the structure of the main applications in eXo Collaboration via the following topics:
To learn more about the eXo Collaboration JCR Structure, you should have the certain knowledge of JCR.
The Calendar data are saved in eXo-JCR under the CalendarApplication data directory. The Calendar JCR Structure is divided into two main branches: one for public (exo:application) and the other for users (Users).
The whole JCR structure of Calendar can be visualized in the diagram below:
The Calendars node of the nt:unstructured type contains the child nodes of the exo:calendar type. When a calendar is created by users or the default ones in the system, it is stored under the calendars node: CalendarApplication/calendars/%calendar_id%. Its node type is exo:calendar that has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The Id of the calendar. |
exo:name | String | false | The name of the calendar. |
exo:description | String | false | The brief description of the calendar. |
exo:viewPermissions | String | true | The list of users/groups having the view permissions. |
exo:editPermissions | String | true | The list of users/groups having the edit permissions. |
exo:groups | String | true | The list of user groups to which the calendar belongs. |
exo:categoryId | String | false | The Id of the category containing the calendar. |
exo:calendarColor | String | false | The color name of the calendar that is defined in the org.exoplatform.web ui.form.ext.UIFormColorPicker class (such as Sky blue, Powder blue). |
exo:calendarOwner | String | false | The name of the user creating the calendar. |
exo:locale | String | false | Location where the calendar is set in format of the uppercase ISO 3166 3-letter country code. |
exo:timeZone | String | false | The Id of the time zone that is set by the user in compliance with the Java class: java.util.TimeZone. |
exo:publicUrl | String | false | The public ICAL link of the calendar. |
exo:privateUrl | String | false | The private ICAL link of the calendar. |
When a user shares his own calendar with other users, the Id of the calendar node is referred to the node under the sharedCalendar node: CalendarApplication/sharedCalendars/%user_id% following the JCR reference mechanism.
In case of users' private calendar, two mixin node types exo:remoteCalendar and exo:calendarShared can be added to the exo:calendar node type.
The exo:remoteCalendar mixin node type has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:remoteUrl | String | false | The URL of the remote calendar. |
exo:remoteType | String | false | The type of the remote calendar, including ICalendar (.ics) and CalDav. |
exo:username | String | false | The username used to access the remote calendar. |
exo:password | String | false | The password used to access the remote calendar. |
exo:syncPeriod | String | false | The period the remote calendar is synchronized. auto, 5 minutes, 10 minutes, 15 minutes, 1 hour, 1 day, 1 year |
exo:lastUpdated | Date | false | The last update of the remote calendar. |
exo:beforeDate | String | false | The period before the current date in which the calendar is checked out, including the values: None (the unlimited time), 1 week, 2 weeks, 1month, 2 months, 3 months, 6 months and 1 year. |
exo:afterDate | String | false | The period after the current date in which the calendar is checked out, including the values: Forever (the unlimited time), 1 week, 2 weeks, 1month, 2 months, 3 months, 6 months and 1 year. |
The exo:calendarShared mixin node type has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:sharedId | Reference | true | The user Ids who are shared the calendars. |
An event can have many attachments which are stored under the attachment node of the exo:eventAttachmenttype: CalendarApplication/calendars/%calendar_id%/%event_id%/attachment/%attachment_id%. The exo:eventAttachment node type has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:fileName | String | false | The name of the attached file. |
The eventCategories node contains all event categories. When an event category is created, it is stored in a node of the exo:eventCategory type, under the eventCategories node defined at the path: CalendarApplication/eventCategories/%eventcategory_id%.
This node type has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The Id of the category to which an event belongs. |
exo:name | String | false | The name of the category to which an event belongs. |
exo:description | String | false | The brief description of the category to which an event belongs. |
Each event category node contains the calendar event node of the exo:calendarEvent type. This node of the exo:calendarEvent type is stored at the path: CalendarApplication/eventCategories/%eventcategory_id%/%event_id%.
This node type has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The Id of the event. |
exo:eventType | String | false | Type of the event, including Event and Task. |
exo:summary | String | false | The summary of the event. |
exo:location | String | false | The location where the event will take place. |
exo:taskDelegator | String | false | The name of the user being delegated the task. |
exo:description | String | false | The brief description of the event. |
exo:eventCategoryId | String | false | The Id of the category containing the event. |
exo:eventCategoryName | String | false | The name of the category containing the event. |
exo:calendarId | String | false | The Id of the calendar containing the event. |
exo:fromDateTime | Date | false | The start time of the event. |
exo:toDateTime | Date | false | The end time of the event. |
exo:priority | String | false | The preference order of the event, including 4 values: none, low, normal, high. |
exo:isPrivate | Boolean | false | Define if the event is private or not. |
exo:eventState | String | false | The state of the event which depends on each event type. |
exo:invitation | String | true | The list of email addresses of users being invited to the event. This property is for the Event type only. |
exo:participant | String | true | The list of users being invited to the event. This property is for the Event type only. |
exo:participantStatus | true | String | The status of the participant, including name and status value. |
exo:message | String | false | The content of the invitation email. |
exo:repeat | String | false | Repetition type of the event, including: "norepeat", "daily", "weekly", "monthly", "yearly", "weekend", "workingdays". |
exo:sendOption | String | false | The option to notify users before sending the invitation via email: never (not sending all time), always (sending without asking) and ask (asking before sending). |
The categories node of the nt:unstructured type contains the child nodes of the exo:calendarCategory type. These child nodes containing the Id of the calendars in the categories are stored under the categories node: CalendarApplication/categories/%calendarcategories_id%.
The exo:calendarCategory node type has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The Id of the category to which a calendar belongs. |
exo:name | String | false | The name of the category to which a calendar belongs. |
exo:description | String | false | The brief description of the category to which a calendar belongs. |
exo:calendarIds | String | true | A list of calendar Ids belonging to the category. |
The eXoCalendarFeed of the nt:unstructured type contains iCalendars, webDavCalendars as child nodes and others of the exo:rssData type.
The exo:rssData node type has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:baseUrl | String | false | The original link to the RSS source. |
exo:title | String | false | The title of the feed. |
exo:content | Binary | false | The content of the feed. |
The iCalendars node of the nt:unstructured type contains the child nodes of exo:iCalData type.
The exo:iCalData node type has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:data | Binary | false | The exported content of the calendar in the ics.format. |
The webDavCalendars node of the nt:unstructured type contains the child nodes of the exo:caldavCalendarEvent type.
The exo:caldavCalendarEvent node type has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:caldavHref | String | false | The URL of the remote calendar event. |
exo:caldavEtag | String | false | The tag of the remote calendar event. |
The Y%yyyy% of the nt:unstructured type has the name beginning with the Y character followed by the year name having 4 numbers. It contains all the child nodes of M%mm%.
The M%mm% of the nt:unstructured type has the name beginning with the M character followed by the month name having 2 numbers. It contains all the child nodes of D%dd%.
The D%dd% of the nt:unstructured type has the name beginning with the D character followed by the date having 2 numbers. This node has two child nodes: reminder and events.
The reminder node of the nt:unstructured type contains the child nodes named basing on the Id of the event. This child node also has the nt:unstructured type. Each node is used to classify reminders of the same event. Each reminder is stored under a node of the exo:reminder type: CalendarApplication/Y%yyyy%/M%mm%/D%dd%/reminders/%event_id%/%reminder_id%.
The exo:reminder node type has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The Id of the reminder. |
exo:eventId | String | false | The event Id of the reminder. |
exo:creator | String | false | Define who creates the reminder. |
exo:alarmBefore | Long | false | The amount of time that the reminder message is sent before the event starts. |
exo:email | String | false | The list of emails to which the reminder message is sent. |
exo:timeInterval | Long | false | Interval for resending the reminder message in minutes. |
exo:reminderType | String | false | The types of reminders, including email and pop-up. |
exo:fromDateTime | Date | false | The start time to send the reminder. |
exo:remindDateTime | Date | false | The time to send the reminder. |
exo:isRepeat | Boolean | false | Check if the reminder is repeated or not. |
exo:isOver | Boolean | false | Check if the reminder is expired or not. |
exo:summary | String | false | The summary of the reminder. |
exo:description | String | false | The brief description of the reminder. |
The events node of the nt:unstructured type contains the child node of the exo:calendarPublicEvent type defined at the path: CalendarApplication/Y%yyyy%/M%mm%/D%dd%/events/%event_id%.
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The Id of the public event. |
exo:eventType | String | false | Event type, including Task and Event. |
exo:calendarId | String | false | The calendar Id of the public event. |
exo:rootEventId | String | false | The Id of each corresponding node: exo:calendarEvent. |
exo:fromDateTime | Date | false | The start time of the public event. |
exo:toDateTime | Date | false | The snd time of the public event. |
exo:participant | String | true | The list of users being invited to the public event. |
exo:eventState | String | false | The state of the public event, including: busy, available, outside. |
The events node can add the exo:repeatCalendarEvent mixin node that has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:repeatCount | Long | false | The number of times that the event is repeated. |
exo:repeatUntil | Date | false | The given time until when the event is repeated. |
exo:repeatInterval | Long | false | The interval when the event is repeated. It can be day, week, month or year corresponding to the repetition type chosen of day, week, month or year. |
exo:repeatByDay | String | true | The given days in a week on which the event is repeated. |
exo:repeatByMonthDay | Long | true | The given day/date in a month on which the event is repeated. |
exo:recurrenceId | String | false | The Id of each event in the event series. |
exo:excludeId | String | true | The Id of the events that are removed from the event series. |
exo:isException | Boolean | false | Show whether the event is the exception in the event series or not. This case occurs when the event is removed from the repeated event series. |
exo:originalReference | Reference | false | The UUID of the event that is repeated first. |
exo:repeatFinishDate | Date | false | The end date on which the event is repeated. |
The calendarSetting node of the exo:calendarSetting type is stored in CalendarApplication/calendarsetting. The exo:calendarSetting node type has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:viewType | String | false | View type of the calendar. For more details, refer to the org.exoplatform.calendar.service. CalendarSetting class. |
exo:timeInterval | Long | false | The interval for each action displayed each UI, for example, dragging and dropping one event in the Calendar application. |
exo:weekStartOn | String | false | Define the start date of one week, complying with the org.exoplatform.cal endar.service.CalendarSetting class. |
exo:dateFormat | String | false | Define the date format, including dd/MM/yyyy, dd-MM-yyyy, MM/dd/yyyy, and MM-dd-yyyy. |
exo:timeFormat | String | false | Define the time format, including "hh:mm a" and "HH:mm". |
exo:location | String | false | Location where the calendar is set in format of the uppercase ISO 3166 3-letter country code. |
exo:timeZone | String | false | The Id of the time zone, which is set by the user in compliance with the Java class: java.util.TimeZone. |
exo:showWorkingTime | false | Boolean | Check if the working period is displayed or not. |
exo:workingTimeBegin | String | false | Time to start working. This property only takes effect when exo:showWorkingTime is set to true. |
exo:workingTimeEnd | String | false | Time to end working. This property only takes effect when exo:showWorkingTime is set to true. |
exo:defaultPrivateCalendars | String | true | The list of the hidden private calendars. |
exo:defaultPublicCalendars | String | true | The list of the hidden public calendars. |
exo:defaultSharedCalendars | String | true | The list of the hidden shared calendars. |
exo:sharedCalendarsColors | String | true | Define the color of the shared calendar, which is in the format of calendar id:color name. |
exo:sendOption | String | false | The option to notify users before sending an invitation via email: never (not sending all time), always (sending message without asking) and ask (asking before sending). |
The Chat portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
The node type lr:conversation has the following properties:
Property name | Required type | Description |
---|---|---|
lr:conversationstartDate | Date | Start date of the conversation. |
lr:conversationlastActiveDate | Date | Last date when the conversation is updated. |
The node type lr:historicalmessage has the following properties:
Property name | Required type | Description |
---|---|---|
lr:messagefrom | String | Jabber Id of the user (or chat room) sending (or containing) the message respectively. |
lr:messageto | String | Jabber Id of the user (or chat room) to whom (to which) the message is sent. |
lr:messagetype | String | List of message types. For more details, refer to the org.jivesoftware. smack.packet.Message.Type class. |
lr:messagebody | String | Main content of the message. |
lr:messagedateSend | Date | Date when the message was sent. |
lr:messagereceive | Boolean | Check if the message has been received or not. |
The node type lr:participantchat has the following properties:
Property name | Required type | Description |
---|---|---|
lr:participantchatjid | String | Jabber Id of the user. |
lr:participantchatusername | String | Username of the portal. |
The node type lr:interlocutor contains information regarding to the conversation between two users or of the chat room. It has the following properties:
Property name | Required type | Description |
---|---|---|
lr:conversationId | String | Id of the conversation which is the JCR node name of lr:conversation. |
lr:interlocutorjid | String | Jabber Id of the chat room or user. |
lr:interlocutorname | String | Username or name of the chat room. |
lr:interlocutorisRoom | Boolean | Define if the conversation is performed between two users or is of chat room. |
The node type lr:defaultpresencestatus has the following properties:
Property name | Required type | Description |
---|---|---|
lr:conversationlastActiveDate | Date | Date when the conversation is last updated. |
The node type lr:presencestatus contains information regarding to the current status of user. It has the following properties:
Property name | Required type | Description |
---|---|---|
lr:userid | String | Id of the user. |
lr:status | String | Current status of the user included in the org.jivesoftware.smack.pack et.Presence.Type class. |
The Address Book portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
The Address Book portlet is a JCR-based application. The Address Book data are stored in the eXo-JCR under the ContactApplication data directory. The whole JCR structure of Address Book can be visualized in the diagram below:
The Contacts node of the nt:unstructured type has the child nodes of the exo:contact. When a contact is created and added to an address book, it is stored in a node defined at the path: ContactAppication/Contacts/%contact_id%. When a contact is tagged, it is saved in the tags node with the exo:tags property. In case, a contact is shared to other users, it is referred to the SharedContact node of the exo:sharedId type. The exo:contact node type has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | Node name of the exo:contact property. |
exo:fullName | String | false | The full name of the contact. |
exo:firstName | String | false | The first name of the contact. |
exo:lastName | String | false | The last name of the contact. |
exo:nickName | String | false | The nickname of the contact. |
exo:gender | String | false | The gender of the contact. |
exo:birthday | Date | false | The birthday of the contact. |
exo:jobTitle | String | false | The job title of the contact. |
exo:emailAddress | String | true | The email address of the contact. |
exo:exoId | String | false | The Id of the user in the Chat application of eXo Collaboration. |
exo:googleId | String | false | The Google Id of the user. |
exo:msnId | String | false | The MSN Id of the user. |
exo:aolId | String | false | The AOL Id of the user. |
exo:yahooId | String | false | The Yahoo Id of the user. |
exo:icrId | String | false | The ICR Id of the user. |
exo:skypeId | String | false | The Skype Id of the user. |
exo:icqId | String | false | The ICQ Id of the user. |
exo:homeAddress | String | false | The home address of the contact. |
exo:homeCity | String | false | The home city of the contact. |
exo:homeState_province | String | false | The home state/province of the contact. |
exo:homePostalCode | String | false | The home postal code of the contact. |
exo:homeCountry | String | false | The home country of the contact. |
exo:homePhone1 | String | false | The primary home phone number of the contact. |
exo:homePhone2 | String | false | The secondary home phone number of the contact. |
exo:homeFax | String | false | The home fax of the contact. |
exo:personalSite | String | false | The personal site of the contact. |
exo:workAddress | String | false | The address where the contact works. |
exo:workCity | String | false | The city where the contact works. |
exo:workState_province | String | false | The state/province where the contact works. |
exo:workPostalCode | String | false | The postal code of the location where the contact works. |
exo:workCountry | String | false | The country where the contact works. |
exo:workPhone1 | String | false | The primary phone number at the contact's working location. |
exo:workPhone2 | String | false | The secondary phone number at the contact's working location. |
exo:workFax | String | false | The fax number at the contact's working location. |
exo:mobilePhone | String | false | The mobile phone number of the contact. |
exo:webPage | String | false | The website of the contact. |
exo:note | String | false | The note about the contact. |
exo:categories | String | true | The list of categories created by the user. |
exo:editPermissionUsers | String | true | The list of users obtaining the edit permission. |
exo:viewPermissionUsers | String | true | The list of users obtaining the view permission. |
exo:editPermissionGroups | String | true | The list of groups obtaining the edit permission. |
exo:viewPermissionGroups | String | true | The list of groups obtaining the view permission. |
exo:tags | String | true | The list of tag Ids which the contact has marked. |
exo:lastUpdated | Date | false | The time when the contact is last updated. |
exo:isOwner | Boolean | false | Show if this contact is the contact of the user in the system or not. |
exo:ownerId | String | false | If the contact is a user in the system, the owner Id will be the username of this user. |
This node type may add the exo:contactShared mixin that has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:sharedUserId | String | false | The name of the user sharing the contact. |
exo:sharedId | Reference | true | The list of the references to shared users/groups.s |
The ContactGroup node of the nt:unstructured type contains all the child nodes of the exo:contactGroup type. These child nodes store address books and are stored in ContactApplication/ContactGroup/%addressbook_id. This node is also referred to the exo:contact node type with the exo:categories property. When an address book is shared, it is referred to the SharedAddressBook node with the exo:sharedId property.
The information of each address book is contained in a node of the exo:contactGroup type that has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The Id of the address book. |
exo:name | String | false | The name of the address book. |
exo:description | String | false | The brief description of the address book. |
exo:editPermissionUsers | String | true | The list of users having the permission to edit the address book. |
exo:viewPermissionUsers | String | true | The list of users having the permission to view the address book. |
exo:editPermissionGroups | String | true | The list of groups having the permission to edit the address book. |
exo:viewPermissionGroups | String | true | The list of groups having the permission to view the address book. |
Tags are used to categorize the contacts in groups, so users can easily find the contacts. The tags node of the nt:unstructured type contains the child nodes of the exo:contactTag type. When a new tag is created, it is stored in a node defined at the path: ApplicationData/ContactApplications/tags/%tags_id%. The information of each tag is contained in a node of the exo:contactTag type that has the following properties:
Property name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The Id of the tag. |
exo:name | String | false | The name of the tag. |
exo:description | String | false | The brief description of the tag. |
exo:color | String | false | The color of the tag. |
The Mail portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
The node type exo:account has the following properties:
Property name | Required type | Description |
---|---|---|
exo:id | String | Id of the account. |
exo:label | String | Name of the account. |
exo:userDisplayName | String | Screen name of the user. |
exo:emailAddress | String | Email address of the account. |
exo:emailReplyAddress | String | Email address of the account receiving replies. |
exo:signature | String | Signature of the account. |
exo:description | String | Brief description of the account. |
exo:checkMailAuto | Boolean | Define if the mail is automatically checked after a given period or not. |
exo:emptyTrash | Boolean | Define if the trash needs to be cleaned up when exiting from the Mail application or not. |
exo:serverProperties | String | Information of the POP/IMAP server configuration. |
exo:smtpServerProperties | String | Information of the SMTP server configuration. |
exo:lastCheckedTime | Date | Time when the account was last checked. |
exo:checkAll | Boolean | Define if all folders of the mail are checked or not. |
exo:checkFromDate | Date | Get mails as from the given date only if the value of exo:serverProperties is set for configuring the IMAP server. |
exo:isSavePassword | Boolean | Define if the password is saved or not. |
exo:secureAuthsIncoming | String | Type of the incoming connection for security. Its values include starttls, ssl/tls. |
exo:secureAuthsOutgoing | String | Type of the outgoing connection for security. Its values include starttls, ssl/tls. |
exo:authMechsIncoming | String | Authentication mechanism of the incoming connections. Its values consist of ntlm, plain, login, digest-md5, kerberos/gssapi, cram-md5. |
exo:authMechsOutgoing | String | Authentication mechanism of the outgoing connections. Its values consist of ntlm, plain, login, digest-md5, kerberos/gssapi, cram-md5. |
exo:permissions | String | Permissions of delegators. |
The node type exo:folder has the following properties:
Property name | Required type | Description |
---|---|---|
exo:id | String | Id of the folder. |
exo:name | String | Name of the folder. |
exo:label | String | Absolute path referring to the folder on the Mail server. |
exo:unreadMessages | Long | Number of unread messages in the folder. |
exo:totalMessages | Long | Total number of messages in the folder. |
exo:personal | Boolean | Define if the folder is created by one user or the Mail system. |
exo:folderType | Long | Type of folder, which is defined in the javax.mail.Folder class. |
exo:lastStartCheckingTime | Date | Start time of the last check in the folder. |
exo:lastCheckedTime | Date | End time of the last check in the folder. |
The node type exo:message has the following properties:
Property name | Required type | Description |
---|---|---|
exo:id | String | Id of the message. |
exo:uid | String | Id of the message on the IMAP server. |
exo:inReplyToHeader | String | Id of the first message in the matching thread. |
exo:path | String | Absolute path of the exo:message type. |
exo:account | String | Id of the account. |
exo:from | String | Value given in the From field in the email message, containing information of the sender, such as full name and email. |
exo:to | String | Value given in the To field in the email message, containing information of the receiver, such as full name and email. |
exo:cc | String | Value given in the CC field in the email message, containing information of the receivers, such as full name and email. |
exo:replyto | String | Value given in the Reply-To field in the email message, such as emails. |
exo:isUnread | Boolean | Define if the email has been read or not. |
exo:subject | String | Subject of the email message that can be read from the Subject field. |
exo:body | String | Main content of the email message. |
exo:sendDate | Date | Date when the email message was sent. |
exo:receivedDate | Date | Date when the email message was received. |
exo:size | Long | Capacity of the email message in bytes. |
exo:contentType | String | Content type of the email message, for example: text/plain and text/html. |
exo:folders | String | List of folder Ids containing the email message. |
exo:tags | String | List of tag Ids marked in the email message. |
exo:star | Boolean | Define if the email message is starred or not. |
exo:hasAttach | Boolean | Define if any files are attached with the email message or not. |
exo:priority | Long | Preference order of the message with 3 default values: 1 = High, 3 = Normal, 5 = Low. |
exo:lastUpdateTime | Date | Time when the message was last updated. |
The node type exo:mailAttachment has the following property:
Property name | Required type | Description |
---|---|---|
exo:fileName | String | Name of the file attached in the mail. |
The node type exo:mailtag has the following properties:
Property name | Required type | Description |
---|---|---|
exo:id | String | Tag id of the mail. |
exo:name | String | Name of the tag. |
exo:description | String | Brief description of the mail tag. |
exo:color | String | Color of the tag which is defined in the org.exoplatform.webui.form.ext.UIFormColorPicker class. |
The node type exo:filter has the following properties:
Property name | Required type | Description |
---|---|---|
exo:id | String | Filter id which is a unique and randomized value. |
exo:name | String | Name of the filter which is defined by the user. |
exo:from exo:to exo:subject exo:body | String |
Filter email messages by each field respectively: * From * To * Subject * Body |
exo:fromCondition exo:toCondition exo:subjectCondition exo:bodyCondition | Long |
Filter emails by the condition types set in each property respectively: * exo:from * exo:to * exo:subject * exo:body All these properties have two values: * 0 = returned messages contains the value set in the corresponding property. * 1 = do not contain the value set in the corresponding property. |
exo:applyTag | String | Apply the tag for the filtered email messages. |
exo:applyFolder | String | Apply the folder for the filtered email messages. |
exo:keepInbox | Boolean | Define if the email message is still kept in the Inbox folder or not. |
exo:applyForAll | Boolean | If the value is set to "true" into the exo:applyForAll property, the filter will be executed for all email messages. |
The node type exo:mailSetting has the following properties:
Property name | Required type | Description |
---|---|---|
exo:numberMsgPerPage | Long | Number of messages displayed in one page. |
exo:formatAsOriginal | Boolean | Define if the email message got from the mail server is kept in the original format or not. |
exo:replyWithAttach | Boolean | Make the original message as the attachment before replying or not. |
exo:forwardWithAttach | Boolean | Make the original message as the attachment before forwarding or not. |
exo:prefixMsgWith | String | Prefix for the message. |
exo:periodCheckAuto | Long | Time interval to check the email messages automatically. |
exo:defaultAccount | String | Id of the user account that is displayed by default when the user logged in the Mail application. |
exo:useWysiwyg | String | Define the Wysiwyg editor is used or not. |
exo:saveMsgInSent | Boolean | Define the sent email message is saved to the Sent folder or not. |
exo:layout | Long | Type of layout which is displayed to the user. |
exo:returnReceipt | Long | Action type of the user when receiving the "return receipt" to confirm the arrival of one email message, including: 0 = ask, 1 = never, 3 = always. |
The node type exo:content has the following properties:
Property name | Required type | Description |
---|---|---|
id | String | Id of the content. |
ownerType | String | Type of the owner. Its default value is user. |
ownerId | String | User Id of owner. |
dataType | String | Type of data. |
data | String | XML string of the content navigation. |
createdDate | Date | Created date of the content. |
modifiedDate | Date | Modified date of the content. |
This chapter supplies you with the basic knowledge about overridden components and REST APIs implemented in eXo Collaboration via the following topics:
There are some overridable components in eXo Collaboration so that you can control how these components work by implementing or extending default implementations and then reconfigure these new components in the configuration.xml file.
ContentDAO is an overridable component used in the Content application (or called RSS reader) of eXo Collaboration.
You can find the configuration file at WEB-INF/cs-extension/cs/content/content-service-configuration.xml with the declaration as below:
<component>
<key>org.exoplatform.content.service.ContentDAO</key>
<type>org.exoplatform.content.service.impl.ContentDAOImpl</type>
</component>
The example below is an example of plugin configuration:
<external-component-plugins>
<target-component>org.exoplatform.content.service.ContentDAO</target-component>
<component-plugin>
<name>rssreader.listener</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.content.service.RSSContentPlugin</type>
<description>rss reader plugin</description>
</component-plugin>
<component-plugin>
<name>description.listener</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.content.service.DescriptionPlugin</type>
<description>Description plugin</description>
</component-plugin>
</external-component-plugins>
ContactLifeCycle is an interface to extend the capabilities of eXo Platform. The ContactLifeCycle lets you be notified during the lifecycle of an address book's contact when a contact is added or modified.
An example of ContactLifeCycle has been implemented to integrate the Address Book application in the eXo Social's Spaces. See the following configuration at: ext/social-integration/src/main/resources/conf/portal/configuration.xml.
See the following example:
<external-component-plugins>
<target-component>org.exoplatform.contact.service.ContactService</target-component>
<component-plugin>
<name>ContactEventListener</name>
<set-method>addListenerPlugin</set-method>
<type>org.exoplatform.cs.ext.impl.ContactSpaceActivityPublisher</type>
</component-plugin>
</external-component-plugins>
Details: ContactSpaceActivityPublisher
implements ContactLifeCycle
. This implementation publishes activities in the space activity stream to notify of new and updated contacts in the space address book.
Transport is an overridable component used in the Chat application of eXo Collaboration.
This overridable component is used to help users add the protocol to the Chat application, such as: ICQ, YAHOO, MSN, XMPP, AIM, GTALk.
The Chat application of eXo Collaboration only uses the XMPP protocol that is implemented in the XMPPTransport object.
EventLifeCycle is an extension point used in the Calendar application of eXo Collaboration. You can find the configuration file of this component at: ext/social-integration/src/main/resources/conf/portal/configuration.xml.
See the following example:
<external-component-plugins>
<target-component>org.exoplatform.calendar.service.CalendarService</target-component>
<component-plugin>
<name>CalendarEventListener</name>
<set-method>addEventListenerPlugin</set-method>
<type>org.exoplatform.cs.ext.impl.CalendarSpaceActivityPublisher</type>
</component-plugin>
</external-component-plugins>
Details: CalendarSpaceActivityPublisher
implements EventLifeCycle
. It writes activities in the space activity stream when events or tasks are added/modified.
eXo Collaboration implements and provides many public REST APIS to help built-in applications, such as Calendar, Chat and Mail to communicate and transfer data with the server. By using these public REST APIs, extended or 3rd party applications can make use of this to develop cool web applications faster without much implementation.
The Calendar application of eXo Collaboration uses CalendarWebservice to provide all APIs for working with calendars, such as creating personal/group calendars, sharing calendars, managing events/tasks.
The REST API of Calendar portlet is exposed by org.exoplatform.services.cs.calendar.CalendarWebservice class.
Service name | Service URL | Location | Description |
---|---|---|---|
CalendarWebservice | $portalname/$restcontextname/cs/calendar |
- Maven groupId: org.exoplatform.cs - ArtifactId: exo.cs.web.webservice | Call extended services of the Calendar application. |
Details:
$portalname: The name of the portal
$restcontextname: The context name of rest webapplication which is deployed to the "$portalname" portal.
APIs usage:
Use the following APIs to build all functions of the Calendar application:
Name | Service URL endpoint | Parameters | Expected Values | Description |
---|---|---|---|---|
checkpermission | /cs/calendar/checkPermission/{username}/{calendarId}/type} |
username calendarId type |
user id calendar id INVALID_TYPE = -1 / PRIVATE_TYPE = 0 / SHARED_TYPE = 1 / PUBLIC_TYPE = 2 | Check the permission of a user to a calendar, aiming at defining if the user has the edit permission to the calendar or not. |
event | /cs/calendar/event/{username}/{eventFeedName} |
username eventFeedName |
user id string | Return a feed RSS that lists links to access a specific event. |
feed | /cs/calendar/feed/{username}/{feedname}/{filename} |
username feedname filename |
username string string | Show the content of a feed that is a list of events in the "filename" file. |
publicProcess | /cs/calendar/subscribe/{username}/{calendarId}/{type} |
username calendarId type |
user id calendar id INVALID_TYPE = -1 / PRIVATE_TYPE = 0 / SHARED_TYPE = 1 / PUBLIC_TYPE = 2 | Process the public calendar when having a remote access request. |
privateProcess | cs/calendar/private/{username}/{calendarId}/{type} |
username calendarID type |
user id calendar id INVALID_TYPE = -1 / PRIVATE_TYPE = 0 / SHARED_TYPE = 1 / PUBLIC_TYPE = 2 | Process the public calendar when having a remote access request. User must enter username and password to access. |
getEvents | /cs/calendar/events/personal/{type}/{calids}/{from}/{to}/{limit} |
type calids from to limit |
Event/Task Personal calendar id long long integer | Get personal events/tasks of a particular calendar by time range and limit the number of returned events/tasks by the 'limit ' parameter. |
upcomingEvent | /cs/calendar/getissues/{currentdatetime}/{type}/{limit} |
currentdatatime type limit |
valid time format INVALID_TYPE = -1 / PRIVATE_TYPE = 0 / SHARED_TYPE = 1 / PUBLIC_TYPE = 2 integer | The list of upcoming events in a specific calendar. |
updateStatus | /cs/calendar/updatestatus/{taskid}?statusid={status_id} |
taskid status_id |
task id integer with following values: 1 - Need Action 2 - In Progress 3 - Completed 4 - Canceled | Update the status of a task. |
getCalendars | /cs/calendar/getcalendars | no param | Get a list of calendars. |
The Mail application of eXo Collaboration uses MailWebservice to provide all APIs for working with mail, such as sending/checking/storing mail to JCR.
REST API of the Mail portlet is exposed by org.exoplatform.services.cs.mail.MailWebservice class.
The Mail portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
Service name | Service URL | Location | Description |
---|---|---|---|
MailWebservice | $portalname/$restcontextname/private/cs/mail |
- Maven groupId: org.exoplatform.cs - artifactId: exo.cs.web.webservice | This service is used to call extended services of the Mail application. |
APIs Usage:
Use the following APIs to build all functions of the Mail application:
Name | Service URL endpoint | Parameters | Expected Values | Description |
---|---|---|---|---|
checkMail | /checkmail/{username}/{accountId}/{folderId/}/ |
username accountID folderId |
user id account id folder id | Check mails when having a request. |
synchFolders | /synchfolders/{username}/{accountId}/ |
username accountID |
user id account id | Synchronize the mail folders in the clients and those in the mail server. |
stopCheckMail | /stopcheckmail/{username}/{accountId}/ |
username accountId |
user id account id | Stop checking the mail. |
getCheckMailJobInfo | /checkmailjobinfo/{username}/{accountId}/ |
username accountId |
user id account id | The method to get information of the mail-checking job. |
searchemail | /searchemail/{keywords} | keywords | string | Search information from emails. |
The Chat application uses some APIs to help users create a room, join a room, invite other users to room, or send files, and more.
The Chat application of eXo Collaboration uses two services: RESTXMPPService and FileExchangeService to do these tasks.
The Chat portlet and its services are deprecated. It remains fully supported for eXo customers, however it will not receive any enhancement and will be removed from the product scope in the future.
REST API RESTXMPPService of the Chat portlet is exposed by org.exoplatform.services.xmpp.rest.RESTXMPPService class.
Service name | Service URL | Location | Description |
---|---|---|---|
RESTXMPPService | $portalname/$restcontextname/xmpp |
* Maven groupid: org.exoplatform.cs * exo.cs.eXoApplication.chat.service | Implement all actions sent to the Chat server; |
APIs Usage:
Use the following APIs to build all functions of the Chat application:
Name | Service URL endpoint | Parameters | Expected Values | Description |
---|---|---|---|---|
loadJsResourceBundle | /loadJsResourceBundle/{locale}/ | locale | locale id | Read the language files in the Chat server. |
createRoom | /muc/createroom/{username}/ |
username room nickname |
user id room name display name | Create a chat room or a group chat. |
configRoom | /muc/configroom/{username}/ |
username room |
user id room name | Establish the configuration of a chat room. |
getRoomConfigForm | /muc/getroomconfig/{username}/ |
username room |
user id room name | Get the configuration of a chat room created. |
getRoomInfo | /muc/getroominfo/{username}/ |
username room |
user id string | Get the inforamtion of a chat room created. |
getJoinedRooms | /muc/joinedrooms/{username}/ | username | user id | List chat rooms that a user has been joined. |
getRooms | /muc/rooms/{username}/ | username | user id | Get a list of group chat or chat rooms created. |
declineToRoom | /muc/decline/{username}/{inviter}/ |
username inviter room reason |
user id user id room name string | Refuse the invitation to join the chat room. |
destroyRoom | /muc/destroy/{username} |
username room reason altroom |
user id room name string room id | Delete a chat room created. |
inviteToRoom | /muc/invite/{username}/{invitee}/ |
username invitee room reason |
user id user id room name string | Invite other users to join a chat room. |
joinRoom | /muc/join/{username}/ |
username room nickname password |
user id room name display name room password | Join a chat room. |
leftRoom | /muc/leaveroom/{username}/ |
username room |
user id room name | Leave a chat room. |
changeNickname | /muc/changenickname/{username}/{nickname}/ |
username nickname |
user id display name | Change the nickname of users. |
changeAvailabilityStatusInRoom | /muc/changestatus/{username}/{mode}/ |
username mood room status |
user id presence type room name presence type | Change the status of a user in the chat room. |
changeSubject | muc/changesubject/{username}/ |
username room subject |
user id room name string | Change the subject of a chat room. |
manageRoleRoom | /muc/managerole/{username}/ |
username room nickname role command |
user id room name display name Participant / moderator grant/revoke | Change the role of each user in a chat room. |
manageAffilationRoom | /muc/manageaffiliation/{username}/ |
username room nickname affiliation command |
user id room name display name String affiliation grant / revoke | Change the ownership of a chat room. |
kickUserFromRoom | /muc/kick/{username}/ |
username nickname room reason |
user id display name room name string | Remove a user from the chat room. |
banUserFromRoom | /muc/ban/{username}/ |
username room name reason |
user id room name user id string | Ban a user in the chat room. |
addBoddyToRoster | /roster/add/{username}/{adduser} |
username adduser nickname group |
user id use id display name group id | Add a user into the contact list. |
updateBoddy | /roster/update/{username}/{upduser}/ |
username upduser nickname group |
user id user id display name group id | Update new users into the contact list. |
createGroup | /roster/group/{username}/{group}/ |
username group |
user id group id | Create a chat room. |
askForSubscription | /askforsubscription/{username}/{askuser}/ |
username askuser nickname |
user id user id display name | Change the presence type of a user into Subscription. |
cleanBuddylist | /rosterclean/{username}/ | username | user id | Remove a user from the contact list. |
getAllHistory | /history/getmessages/{usernameto}/{isGroupChat}/ |
usernameto isGroupChat usernamefrom |
user id true / false user id | Get all the chat history of two users. |
getHistoryBetweenDate | /history/getmessages/{usernameto}/{isGroupChat}/{from}/{to}/ |
usernameto isgroupchat from to usernamefrom |
user id true / false valid date format valid date format user id | Get the chat history of two users in a specific period. |
getHistoryFromDateToNow | /history/getmessages/{usernameto}/{isGroupChat}/{from}/ |
username isGroupChat from usernamefrom |
user id true / false valid date format valid date format user id | Get the chat history of two users from a specific date to the current time. |
getAllHistoryFile | /history/file/getmessages/{usernameto}/{isGroupChat}/{clientTimezoneOffset}/ |
uernameto isGroupChat clientTimezoneOffset usernamefrom |
user id true / false Long user id | Download all the chat history file of two users. |
getHistoryFromDateToNowFile | /history/file/getmessages/{usernameto}/{isGroupChat}/{from}/{clientTimezoneOffset}/ |
usernameto isGroupChat from clientTimezoneOffset usernamefrom |
user id true / false valid date format Long user id | Download the chat history file of two users from a specific date to the current time |
getHistoryBetweenDateFile | /history/file/getmessages/{usernameto}/{isGroupChat}/{from}/{to}/{clientTimezoneOffset}/ |
usernameto isGroupChat from to clientTimezoneOffset usernamefrom |
user id true / false valid date format valid date format Long user id | Download the chat history file of two users in the specific date. |
getUserInfo | /getuserinfo/{username}/{needinfo}/ |
username needinfo |
user id string | Get the information of a user. |
login2 | /login2/{forcache}/ | forcache | Allow a user to log in the chat server. | |
logout | /logout/{username}/{presencestatus}/ |
username presencestatus |
user id presencestatus | Allow a user to log out the chat server. |
messageReceive | /history/messagereceive/{username}/{messageid}/ |
username messageid |
user id message id | Receive a message from other users. |
removeBuddy | /roster/del/{username}/{removeboddy}/ |
username removeboddy |
user id user id | Delete a contact from the contact list. |
removeTransport | /removetransport/{username}/{transport}/ |
username transport |
user id transport servive (e.g: Yahoo, XMPP) | Reset the presence type at the service that is being used. |
searchUsers | /searchuser/{username}/ |
username search byUsername byName byEmail searchService |
user id string true / false true /false true / false string | Search users in the chat server. |
sendMessage | /sendmessage/{username}/ |
username messageBean |
usesr id object | Send an message to other users. |
sendMUCMessage | /muc/sendmessage/{username}/ |
username messageBean |
user id object | Send a message to multile users or a group. |
setUserStatus | /sendstatus/{username}/{status}/ |
username status |
user id available/ unavailabe / do not disturb / away / extend away | Change the status of a user. |
subscribeUser | /subscribeuser/{username}/{subsuser}/ |
username subsuser |
user id user id | Change presence type into Subcribed type. |
unsubscribeUser | /unsubscribeuser/{username}/{unsubsuser}/ |
username unsubsuser |
user id user id | Change presence type into the Unsubscribed type. |
acceptFile | /fileexchange/accept/{username}/{uuid}/ |
username uuid |
user id string | Accept getting a file sent from another user. |
rejectFile | /fileexchange/reject/{username}/{uuid}/ |
username uuid |
user id string | Refuse getting a file sent from another user. |
getPreviousStatus | /getprevstatus/{username}/ | username | user id | Get the tatus of a user in the last log-in. |
REST API FileExchangeService for uploading files is defined in org.exoplatform.services.xmpp.rest.FileExchangeService class.
Service name | Service URL | Location | Description |
---|---|---|---|
FileExchangeService | $portalname/$restcontextname/fileexchange |
- Maven groupid: org.exoplatform.cs - InterfactId: exo.cs.eXoApplication.chat.service | Upload a file to the server and inform the user that the file can be downloaded to the local computer. |
APIs usage: Use the following APIs to upload and send files to other users:
Name | Service URL endpoint | Parameters | Expected Values | Description |
---|---|---|---|---|
upload | $portalname/$restcontextname/fileexchange |
description username requestor isroom |
string user id user id true / false | Upload a file to the server. |
There are 2 prerequisites you may need to learn before thoroughly going into Knowledge as follows:
This chapter provides you with a comprehensive view about applications in Knowledge, including:
These applications are packaged as Web application archives (WARs).
Also, you can specify the package of each portlet and gadget and its available preferences that allow you to extend the configuration choices for standard preferences.
The Forum portlet is the application for users to post and read messages on different topics.
Package
This portlet is packaged in the forum.war file.
See the portlet.xml file in the project following this path: forum/WEB-INF/portlet.xml.
Preference name | Possible value | Default value | Description |
---|---|---|---|
useAjax | true , false | true | Define if links in the Forum will be plain hrefs or javascript ajax (better for SEO) or not. |
showForumActionBar | true , false | true | This is the UIForumActionBar. If the value is set to "true", the UIForumActionBar will be shown. If false, the UIForumActionBar will be hidden. |
forumNewPost | day number | 1 | Specify if a post is new. If the post is created within the set period, it is new in the Forum. |
enableIPLogging | true , false | true | Enable the IP logging function in the Forum. IP addresses of all posts will be collected. |
enableIPFiltering | true , false | true | Enable the IP filter function in Forum, enabling IP addresses to be blocked in the Forum. |
invisibleCategories | id categories | empty | Hide some categories. If the value is set empty, all categories of the Forum will be shown. |
invisibleForums | id forums | empty | Hide some Forums. All Forums will be shown if the value is set empty. |
uploadFileSizeLimitMB | integer | 20 | Limit the size of uploaded files in MB in the Forum. |
isShowForumJump | true , false | true | Specify if the Forum jump panel is shown or not. |
isShowIconsLegend | true , false | true | Specify if the icon legends panel is shown or not. |
isShowModerators | true , false | true | Specify if the moderators panel is shown or not. |
isShowPoll | true , false | true | Specify if the poll panel is shown or not. |
isShowQuickReply | true , false | true | Specify if the quick reply panel is shown or not. |
isShowRules | true , false | true | Specify if the forum rules panel is shown or not. |
isShowStatistics | true , false | true | Specify if the statistics panel is shown or not. |
Name | Description |
---|---|
ForumLinkEvent | Set the render for UIForumLinkPortlet and set values for UIForumLinks. |
ReLoadPortletEvent | Reload UIForumPortlet. |
OpenLink | Update values for UIForumLinks. |
ForumPollEvent | Set the render for UIForumPollPortlet. |
ForumModerateEvent | Set the render for UIForumModeratorPortlet. |
ForumRuleEvent | Set the render for UIForumRulePortlet. |
QuickReplyEvent | Set the render for UIForumQuickReplyPortlet. |
This event is fired through UIForumLinkPortlet.
To receive ForumLinkEvent, you must use the ForumParameter class with two properties:
Name | Type | Possible value | Description |
---|---|---|---|
isRenderForumLink | boolean | true/false | If the value is set to true or false, the Forum link is rendered or not respectively. |
path | string | The absolute path of the class node (including types: category, forum, topic) defined by JCR. | Set data for the UIForumLinkPortlet. |
For example:
PortletRequestContext pcontext = (PortletRequestContext) WebuiRequestContext.getCurrentInstance();
ActionResponse actionRes = (ActionResponse) pcontext.getResponse();
ForumParameter param = new ForumParameter();
String path = forum.getPath();
if ( ...condition to render the UIForumLinkPortlet... ) {
param.setRenderForumLink(true);
param.setPath(path);
} else {
param.setRenderForumLink(false);
}
actionRes.setEvent(new QName("ForumLinkEvent"), param) ;
This event is fired through UIForumPortlet.
To receive ReLoadPortletEvent, you must use the ForumParameter class with two properties:
Name | Type | Possible value | Description |
---|---|---|---|
topicId | string | Id of topic. | Return the id of topic for UIForumPortlet |
isRenderPoll | boolean | true/false | If the value is set to true or false, the UITopicPoll component is rendered or not respectively. |
For example:
....
ActionResponse actionRes = pcontext.getResponse() ;
ForumParameter param = new ForumParameter() ;
param.setRenderPoll(true);
param.setTopicId(topic.get());
actionRes.setEvent(new QName("ReLoadPortletEvent"), param) ;
....
This event is fired through UIForumPortlet.
To receive OpenLink, you must use the ForumParameter class with one property:
Name | Type | Possible value | Description |
---|---|---|---|
path | string | The absolute path of the node defined by JCR. | Set data for the UIForumPortlet. |
For example:
....
ActionResponse actionRes = pcontext.getResponse() ;
ForumParameter param = new ForumParameter() ;
param.setPath(path);
actionRes.setEvent(new QName("OpenLink"), param) ;
....
This event is fired through UIForumPollPortlet.
To receive ForumPollEvent, you must use the ForumParameter class with four properties:
Name | Type | Possible value | Description |
---|---|---|---|
isRenderPoll | boolean | True/false | If the value is set to true or false, the UIForumPollPortlet portlet is rendered or not respectively. |
categoryId | string | Id of category | Return the Id of category for UIForumPollPortlet. |
forumId | string | Id of forum | Return the Id of forum for UIForumPollPortlet. |
topicId | string | Id of topic | Return the Id of topic for UIForumPollPortlet. |
For example:
....
ActionResponse actionRes = pcontext.getResponse() ;
ForumParameter param = new ForumParameter() ;
param.setCategoryId(categoryId) ;
param.setForumId(forumId);
param.setTopicId(topicId);
param.setRenderPoll(topic.getIsPoll());
actionRes.setEvent(new QName("ForumPollEvent"), param);
....
This event is fired through UIForumModeratePortlet.
To receive ForumModerateEvent, you must use the ForumParameter class with two properties:
Name | Type | Possible value | Description |
---|---|---|---|
isRenderModerator | boolean | True/false | If the value is set to true or false, the UIForumModeratePortlet portlet is rendered or not respectively. |
moderator | list of strings | List of user name | Set data for UIForumModeratePortlet. |
For example:
....
List<String> moderators = Arays.asList(forum.getModerators());
ActionResponse actionRes = pcontext.getResponse() ;
ForumParameter param = new ForumParameter() ;
param.setModerators(moderators);
param.setRenderModerator(true);
actionRes.setEvent(new QName("ForumPollEvent"), param);
....
This event is fired through UIForumRulePortlet.
To receive ForumRuleEvent, you must use the ForumParameter class with two properties:
Name | Type | Possible value | Description |
---|---|---|---|
isRenderRule | boolean | True/false | If the value is set to true or false, the UIForumRulePortlet portlet is rendered or not respectively. |
infoRules | list of strings | The list of states: can create topic, can add post and topic has lock. | Set permissions for users in UIForumRulePortlet. |
For example:
....
ActionResponse actionRes = pcontext.getResponse() ;
ForumParameter param = new ForumParameter() ;
List<String> list = param.getInfoRules();
if(forum.getIsClosed() || forum.getIsLock()) {
list.set(0, "true");
} else {
list.set(0, "false");
}
list.set(1, String.valueOf(canCreateTopic));
list.set(2, String.valueOf(isCanPost));
param.setInfoRules(list);
param.setRenderRule(true);
actionRes.setEvent(new QName("ForumRuleEvent"), param) ;
....
This event is fired through UIQuickReplyPortlet.
To receive QuickReplyEvent, you must use the ForumParameter class with five properties:
Name | Type | Possible value | Description |
---|---|---|---|
isRenderQuickReply | boolean | True/false | If the value is set to true or false, the UIQuickReplyPortlet portlet is rendered or not respectively. |
isModerator | boolean | True/false | Specify if the user is moderator of forum containing the topic with quick reply or not. |
categoryId | string | Id of category | Return the Id of category for UIQuickReplyPortlet. |
forumId | string | Id of forum | Return the Id of forum for UIQuickReplyPortlet. |
topicId | string | Id of topic | Return the Id of topic for UIQuickReplyPortlet. |
For example:
....
ActionResponse actionRes = pcontext.getResponse() ;
ForumParameter param = new ForumParameter() ;
param.setRenderQuickReply(isCanPost);
param.setModerator(isMod);
param.setCategoryId(categoryId) ;
param.setForumId(forumId);
param.setTopicId(topicId);
actionRes.setEvent(new QName("QuickReplyEvent"), param) ;;
....
The Answers portlet is the application to create answers, reply and manage questions.
Package
This portlet is packaged in the faq.war file.
See the portlet.xml file in the project following this path: /webapps/faq/WEB-INF/portlet.xml.
The Answers portlet consists of preferences as follows:
Preference name | Possible value | Default value | Description |
---|---|---|---|
enableViewAvatar | true , false | true | Enable users to view the avatar of owner posting the question. |
enableAutomaticRSS | true , false | true | Enable users to get RSS automatically. |
enableVotes AndComments | true , false | true | Enable users to give votes and comments for the question. |
enableAnonymous SubmitQuestion | true , false | true | Enable anonymous users to submit questions. |
display | approved , both | both | Enable administrators to view unapproved questions in the questions list in UIQuestions. |
SendMailAdd NewQuestion | string | empty | Display the content of sent email when a new question is added. |
SendMailEdit ResponseQuestion | string | empty | Display the email content when a response is edited. |
emailMoveQuestion | string | empty | Display the email content when a question is moved. |
orderBy | alphabet , created | alphabet | Arrange questions in the alphabet or created date order. |
orderType | asc , desc | asc | Display questions in the ascending or descending order. |
isDiscussForum | true , false | false | Enable the DiscussQuestions function. |
idNameCategoryForum | CategoryName, ForumName
| empty | Select categories and forums for the DiscussionQuestions function. |
uploadFileSizeLimitMB | integer | 20
| Set the maximum size of uploaded files in MB. |
The FAQ portlet is the application to show questions and answers.
Package
This portlet is packaged in the faq.war file.
See the portlet.xml file in the project following this path: /webapps/faq/WEB-INF/portlet.xml.
The FAQ portlet includes some portlet preferences that you can configure to alter the behavior.
At runtime, you can use the EDIT mode portlet to set the preferences:
Alternatively, you can configure the portlet in the portet-preferences.xml file.
Preference name | Possible value | Default value | Description |
---|---|---|---|
useAjax | true , false | false | Specify if the AJAX load or HREF load is used. |
The Poll portlet is the application for users to vote any ideas, or activities.
Package
This portlet is packaged in the poll.war file.
See the portlet.xml file in the project following this path: poll/WEB-INF/portlet.xml.
<portlet-preferences>
<preference>
<name>pollIdShow</name>
<value/> <!-- PollId -->
<read-only>false</read-only>
</preference>
</portlet-preferences>
eXo Platform provides a gadget which enables users to see a poll. The Poll Gadget is developed on the combination of Gadget by GateIn and Polls Service. The Poll Gadget allows users to apply functions of Polls, such as viewing and voting Polls.
Gadget name | War name | Description |
---|---|---|
pollslist | poll.war | The list of Polls. |
Preference name | Description |
---|---|
pollId | The Id of Polls which is displayed in the Polls gadget. |
portal/rest/private/ks/poll/viewpoll/pollId
portal/rest/private/ks/poll/votepoll/pollId/indexVote
This chapter describes configurations used in Knowledge. It consists of the following main sections:
Key | Data type | Description |
---|---|---|
org.exoplatform.ks.common. jcr.KSDataLocation | org.exoplatform.ks.common. jcr.KSDataLocation | Hold the JCR storage location for eXo Knowledge data. |
org.exoplatform.services. scheduler.JobSchedulerService | org.exoplatform.services.scheduler. impl.JobSchedulerServiceImpl | Define a job to execute a given number of times during a given period. It is used to monitor jobs automatically and continously, to schedule event-driven jobs and reports, and to control performance. |
Init-params of org.exoplatform.ks.common.jcr.KSDataLocation:
Name | Possible value | Default value |
---|---|---|
repository | string | repository |
workspace | string | knowledge |
Key | Data type | Description |
---|---|---|
org.exoplatform.ks.bbcode. api.BBCodeService | org.exoplatform.ks.bbcode. core.BBCodeServiceImpl | Manage CRUD operations on BBCodes. |
org.exoplatform.forum. service.DataStorage | org.exoplatform.forum.service. impl.JCRDataStorage | Store data of Forum via the JCR system. |
org.exoplatform.forum. service.ForumService | org.exoplatform.forum.service. impl.ForumServiceImpl | Include all public APIs to interact with the UI component and database. |
org.exoplatform.forum.service. ForumStatisticsService | org.exoplatform.forum.service. impl.ForumStatisticsServiceImpl | Include all public APIs to interact with the database of Statistics system. |
Key | Data type | Description |
---|---|---|
org.exoplatform.faq. service.FAQService | org.exoplatform.faq.service. impl.FAQServiceImpl | Include all public APIs to interact with the UI component and database. |
org.exoplatform.faq. service.DataStorage | org.exoplatform.faq.service. impl.JCRDataStorage | Store data of FAQ via the JCR system. |
Key | Data type | Description |
---|---|---|
org.exoplatform.poll. service.DataStorage | org.exoplatform.poll.service. impl.JCRDataStorage | Include all public APIs to interact with the UI component and database. |
org.exoplatform.poll. service.PollService | org.exoplatform.poll.service. impl.PollServiceImpl | Store data of Polls via the JCR system. |
The Init data plug-in is used to define the default data in the .xml file. It includes nodes (node of jcr). When the org.exoplatform.services.jcr.config.RepositoryServiceConfiguration component is initialized, the org.exoplatform.services.jcr.impl.config.RepositoryServiceConfigurationPlugin component will be get and the function addConfig is called. Then, the /ks-extension/jcr/repository-configuration.xml file is loaded and the component org.exoplatform.ks.common.jcr.KSDataLocation will be initialized. Next, the setLocation function is called, setting up the workspace and repository for KS. After that, the addPlugin function will be run, generating the DataLocation (some parent nodes) for eXo Knowledge.
The following is the list of applications in eXo Knowledge and the corresponding components used to initialize the default data.
Application | Component | Description |
---|---|---|
Forum | KSDataLocation, ForumServiceImpl | Initialize default data of the Forum portlet. |
Answers | KSDataLocation, AnswerServiceImpl | Initialize default data of the Answers portlet. |
Polls | KSDataLocation, PollServiceImpl | Initialize default data of the Polls portlet. |
In this section, you will understand how to initialize data via the sample configurations below.
When the server starts, the jcr-configuration.xml file is initialized. The component-plugin named addConfig will be referred to org.exoplatform.services.jcr.impl.config.RepositoryServiceConfigurationPlugin to load the war:/ks-extension/jcr/repository-configuration.xml_ file.
<component-plugin>
<!-- The name of the plugin -->
<name>Sample RepositoryServiceConfiguration Plugin</name>
<!-- The name of the method to call on the RepositoryServiceConfiguration
in order to add the RepositoryServiceConfigurations -->
<set-method>addConfig</set-method>
<!-- The full qualified name of the RepositoryServiceConfigurationPlugin -->
<type>org.exoplatform.services.jcr.impl.config.RepositoryServiceConfigurationPlugin</type>
<init-params>
<value-param>
<name>conf-path</name>
<description>JCR configuration file</description>
<value>war:/ks-extension/jcr/repository-configuration.xml</value>
</value-param>
</init-params>
</component-plugin>
In which:
Name | Set-method | Type | Description |
---|---|---|---|
RepositoryService ConfigurationPlugin | addConfig | org.exoplatform.services. jcr.impl.config.Repository ServiceConfigurationPlugin | Read the configuration of JCR data to initialize data. |
Init-params
Name | Possible value | Default value | Description |
---|---|---|---|
conf-path | string | war:/ks-extension/jcr/ repository- configuration.xml | The path to the repository-configuration.xml file. |
In details:
Once the war:/ks-extension/jcr/repository-configuration.xml file has been initialized, the server will load the storage-configuration.xml file, and the setLocation function in the org.exoplatform.ks.common.conf.DataLocationPlugin component will run.
<external-component-plugins>
<target-component>org.exoplatform.ks.common.jcr.KSDataLocation</target-component>
<component-plugin>
<name>ks.data.location</name>
<set-method>setLocation</set-method>
<type>org.exoplatform.ks.common.conf.DataLocationPlugin</type>
<init-params>
<value-param>
<name>repository</name>
<description>JCR repository for KS data</description>
<value>repository</value>
</value-param>
<value-param>
<name>workspace</name>
<description>workspace for KS data</description>
<value>knowledge</value>
</value-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which,
Value-param | Possible value | Default value | Description |
---|---|---|---|
repository | string | repository | The JCR repository for KS data. |
workspace | string | knowledge | The workspace for KS data. |
Once the workspace name and repository name are registered, the server will load org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator and the addPaths function in org.exoplatform.services.jcr.ext.hierarchy.impl.AddPathPlugin is called. Then, the data location will be built.
<component-plugin>
<name>addPaths</name>
<set-method>addPlugin</set-method>
<type>org.exoplatform.services.jcr.ext.hierarchy.impl.AddPathPlugin</type>
<init-params>
<object-param>
<name>ks.storage</name>
<description>ks data storage tree</description>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig">
<field name="repository">
<string>repository</string>
</field>
<field name="workspaces">
<collection type="java.util.ArrayList">
<value>
<string>knowledge</string>
</value>
</collection>
</field>
<field name="jcrPaths">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>eXoApplications</string>
</field>
<field name="path">
<string>/exo:applications</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>ksUserAvatar</string>
</field>
<field name="path">
<string>/exo:applications/ksUserAvatar</string>
</field>
<field name="nodeType">
<string>nt:unstructured</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>ForumService</string>
</field>
<field name="path">
<string>/exo:applications/ForumService</string>
</field>
<field name="nodeType">
<string>exo:forumHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>ForumSystem</string>
</field>
<field name="path">
<string>/exo:applications/ForumService/ForumSystem</string>
</field>
<field name="nodeType">
<string>exo:forumSystem</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>UserProfileHome</string>
</field>
<field name="path">
<string>/exo:applications/ForumService/ForumSystem/UserProfileHome</string>
</field>
<field name="nodeType">
<string>exo:userProfileHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>StatisticHome</string>
</field>
<field name="path">
<string>/exo:applications/ForumService/ForumSystem/StatisticHome</string>
</field>
<field name="nodeType">
<string>exo:statisticHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>forumStatistic</string>
</field>
<field name="path">
<string>/exo:applications/ForumService/ForumSystem/StatisticHome/forumStatistic</string>
</field>
<field name="nodeType">
<string>exo:forumStatistic</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>AdministrationHome</string>
</field>
<field name="path">
<string>/exo:applications/ForumService/ForumSystem/AdministrationHome</string>
</field>
<field name="nodeType">
<string>exo:administrationHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>BanIPHome</string>
</field>
<field name="path">
<string>/exo:applications/ForumService/ForumSystem/BanIPHome</string>
</field>
<field name="nodeType">
<string>exo:banIPHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>forumBanIP</string>
</field>
<field name="path">
<string>/exo:applications/ForumService/ForumSystem/BanIPHome/forumBanIP</string>
</field>
<field name="nodeType">
<string>exo:banIP</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>ForumData</string>
</field>
<field name="path">
<string>/exo:applications/ForumService/ForumData</string>
</field>
<field name="nodeType">
<string>exo:forumData</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>TopicTypeHome</string>
</field>
<field name="path">
<string>/exo:applications/ForumService/ForumData/TopicTypeHome</string>
</field>
<field name="nodeType">
<string>exo:topicTypeHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>CategoryHome</string>
</field>
<field name="path">
<string>/exo:applications/ForumService/ForumData/CategoryHome</string>
</field>
<field name="nodeType">
<string>exo:categoryHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>TagHome</string>
</field>
<field name="path">
<string>/exo:applications/ForumService/ForumData/TagHome</string>
</field>
<field name="nodeType">
<string>exo:tagHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>forumBBCode</string>
</field>
<field name="path">
<string>/exo:applications/ForumService/ForumData/forumBBCode</string>
</field>
<field name="nodeType">
<string>exo:forumBBCodeHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>faqApp</string>
</field>
<field name="path">
<string>/exo:applications/faqApp</string>
</field>
<field name="nodeType">
<string>exo:faqHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>settingHome</string>
</field>
<field name="path">
<string>/exo:applications/faqApp/settingHome</string>
</field>
<field name="nodeType">
<string>exo:faqSettingHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>userSettingHome</string>
</field>
<field name="path">
<string>/exo:applications/faqApp/settingHome/userSettingHome</string>
</field>
<field name="nodeType">
<string>exo:faqUserSettingHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>categories</string>
</field>
<field name="path">
<string>/exo:applications/faqApp/categories</string>
</field>
<field name="nodeType">
<string>exo:faqCategory</string>
</field>
<field name="mixinTypes">
<collection type="java.util.ArrayList">
<value>
<string>mix:faqSubCategory</string>
</value>
</collection>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>templateHome</string>
</field>
<field name="path">
<string>/exo:applications/faqApp/templateHome</string>
</field>
<field name="nodeType">
<string>exo:templateHome</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>eXoPolls</string>
</field>
<field name="path">
<string>/exo:applications/eXoPolls</string>
</field>
<field name="nodeType">
<string>nt:unstructured</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$JcrPath">
<field name="alias">
<string>groupsPath</string>
</field>
<field name="path">
<string>/Groups</string>
</field>
<field name="permissions">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>*:/platform/administrators</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>true</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>true</string>
</field>
</object>
</value>
<value>
<object type="org.exoplatform.services.jcr.ext.hierarchy.impl.HierarchyConfig$Permission">
<field name="identity">
<string>any</string>
</field>
<field name="read">
<string>true</string>
</field>
<field name="addNode">
<string>false</string>
</field>
<field name="setProperty">
<string>true</string>
</field>
<field name="remove">
<string>false</string>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
The roles plug-in component defines roles in Forum of eXo Platform 3. This convenient application defines access to a set of functions within the application. Currently, it only defines the person who has the administrator role. Administrators can get access to administration functions. At runtime, the application gets data from the roles plug-in to decide whether the logged user has the administrative role or not.
The plug-in is configured in the roles-configuration.xml file.
When the user signs in, his or her username, group and membership will be compared with the user roles defined in the .xml file that is provided by the roles plug-in component.
In particular, at runtime of ForumService, the roles plug-in component is called. The role plug-in is configured in the roles-configuration.xml file. The plug-in component named add.role.rules.plugin will be referred to org.exoplatform.ks.common.conf.RoleRulesPlugin to create users for Forum corresponding to users who exist in the organization database. In addition, the list of users who have administration roles are also defined.
<component-plugin>
<name>add.role.rules.plugin</name>
<set-method>addRolePlugin</set-method>
<type>org.exoplatform.ks.common.conf.RoleRulesPlugin</type>
<description>add role rules</description>
<init-params>
<value-param>
<name>role</name>
<description>name of the role</description>
<value>ADMIN</value>
</value-param>
<values-param>
<name>rules</name>
<description>rules of the role</description>
<value>root</value>
<!--value>admin</value -->
<!--value>member:/demo</value-->
<!--value>/forums/admin</value-->
<!--value>*:/forum/admin</value-->
<!--value>/platform/administrators</value-->
<!--value>manager:/platform/users</value-->
<!--value>*:/somegroup/somesubgroup</value-->
<!--value>manager:/somegroup/someothergroup</value-->
</values-param>
</init-params>
</component-plugin>
In which:
Name | Set-method | Type | Description |
---|---|---|---|
add.role.rules.plugin | addRolePlugin | org.exoplatform.ks. common.conf. RoleRulesPlugin | Add role rules. |
Init-params:
Name | Possible value | Default value | Description |
---|---|---|---|
role | string | ADMIN | The name of role. |
rules | string | root | The rules of role. |
When the role-configuration.xml file is executed, the administration role (with ADMIN
value) will be checked and assigned to a matrix of users/groups/memberships defined inside the "value" tags as below:
<value>...</value>
For example:
...
<value>root</value>
<value>john</value>
<value>/platform/administrators</value>
<value>member:/VIP</value>
<value>validator:/VIP</value>
...
In the example above, the default administrators of Forum include root, john, users in /platform/administrators group and users who have member/validator memberships in the VIP group.
When being root, the users who belong to the /platform/administrators group or who have member/validator memberships in the VIP group and sign in the Forum, they will be identified as the default administrator of Forum.
To add or remove the default administrator of the Forum, simply edit the roles-configuration.xml file, add or remove the relevant "value" tags.
...
<values-param>
...
<value>...</value>
...
</values-param>
...
The default administrators of the Forum can only change their roles by editing in the roles-configuration.xml file.
At runtime, modifications in the roles-configuration.xml file will be read and database will be updated. Normal users of the Forum and default administration will be created correspondingly.
Forum and FAQ applications are to show some information about posters. The way to retrieve that information is pluggable through the ContactProvider component.
For public internet websites, users can provide personal information, such as personal email address and location. To enable, simply override the ContactProvider component in your configuration.
Configure the profile-configuration.xml file as shown below:
<component>
<key>org.exoplatform.ks.common.user.ContactProvider</key>
<type>org.exoplatform.ks.common.user.DefaultContactProvider</type>
<!--<type>org.exoplatform.ks.ext.common.SocialContactProvider</type> -->
</component>
When eXo Knowledge is integrated in eXo Platform and if you want to use ProfileProvider from eXo Social, you need to change "type" org.exoplatform.ks.common.user.DefaultContactProvider into org.exoplatform.ks.ext.common.SocialContactProvider.
You can get the ContactProvider as follows:
public CommonContact getPersonalContact(String userId) throws Exception {
try {
if(userId.indexOf(Utils.DELETED) > 0) return new CommonContact();
ContactProvider provider = (ContactProvider) PortalContainer.getComponent(ContactProvider.class) ;
return provider.getCommonContact(userId);
} catch (Exception e) {
return new CommonContact();
}
}
In eXo Knowledge, when using ContactProvider, you can use one of two following classes:
When you start the Tomcat, the DefaultContactProvider class will be initialized and the OrganizationService component is set within the DefaultContactProvider component.
The DefaultContactProvider class allows you to get user information via the OrganizationService component.
public CommonContact getCommonContact(String userId) {
CommonContact contact = new CommonContact();
try {
User user = orgService.getUserHandler().findUserByName(userId);
UserProfile profile = orgService.getUserProfileHandler().findUserProfileByName(userId);
contact.setEmailAddress(user.getEmail());
contact.setFirstName(user.getFirstName());
contact.setLastName(user.getLastName());
if(profile.getUserInfoMap() != null) {
contact.setAvatarUrl(profile.getAttribute("user.other-info.avatar.url"));
contact.setBirthday(profile.getAttribute("user.bdate"));
contact.setCity(profile.getAttribute("user.home-info.postal.city"));
contact.setCountry(profile.getAttribute("user.home-info.postal.country"));
contact.setGender(profile.getAttribute("user.gender"));
contact.setJob(profile.getAttribute("user.jobtitle"));
contact.setMobile(profile.getAttribute("user.home-info.telecom.mobile.number"));
contact.setPhone(profile.getAttribute("user.business-info.telecom.telephone.number"));
contact.setWebSite(profile.getAttribute("user.home-info.online.uri"));
}
} catch (Exception e) {
log.error("Could not retrieve forum user profile for " + userId + ": " ,e);
}
return contact;
}
The information which is get by the user includes:
Name | Type | Description |
---|---|---|
String
| Email of user. | |
firstName |
String
| First name of user. |
lastName |
String
| Last name of user. |
The information which is get via UserProfile includes:
Attribute | Type | Description |
---|---|---|
user.other-info.avatar.url | String | The path containing the user's avatar. |
user.bdate | String | The user's birthday. |
user.home-info.postal.city | String | The home city of user. |
user.home-info.postal.country | String | The home country of user. |
user.gender | String | The user's gender. |
user.jobtitle | String | The user's job. |
user.home-info.telecom. mobile.number | String | The home phone number of user. |
user.business-info.telecom. telephone.number | String | The mobile number of user. |
user.home-info.online.uri | String | The individual websites of user. |
The SocailContactProvider class gets users' profiles by userId via the IdentityManager class.
public CommonContact getCommonContact(String userId) {
CommonContact contact = new CommonContact();
try {
IdentityManager identityM = (IdentityManager) PortalContainer.getInstance().getComponentInstanceOfType(IdentityManager.class);
Identity userIdentity = identityM.getIdentity(OrganizationIdentityProvider.NAME, userId, true);
Profile profile = userIdentity.getProfile();
if (profile.contains(Profile.EMAIL)) {
contact.setEmailAddress(profile.getProperty(Profile.EMAIL).toString());
}
if (profile.contains(Profile.FIRST_NAME)) {
contact.setFirstName(profile.getProperty(Profile.FIRST_NAME).toString());
}
if (profile.contains(Profile.LAST_NAME)) {
contact.setLastName(profile.getProperty(Profile.LAST_NAME).toString());
}
contact.setAvatarUrl(profile.getAvatarImageSource());
if (profile.contains(Profile.GENDER)) {
contact.setGender(profile.getProperty(Profile.GENDER).toString());
}
if (profile.contains(Profile.CONTACT_PHONES)) {
contact.setPhone(profile.getProperty(Profile.CONTACT_PHONES).toString());
}
if (profile.contains(Profile.URL)) {
contact.setWebSite(profile.getProperty(Profile.URL).toString());
}
} catch (Exception e) {
if (LOG.isErrorEnabled()) LOG.error(String.format("can not load contact from eXo Social Profile with user [%s]", userId), e);
}
return contact;
}
The BBCode plug-in component defines default BBCode data in the .xml file, including BBCode tags, for example, I, B, U, SIZE, COLOR.
When the BBCode Service runs, it will get values returned from the BBCode plug-in component to initialize default BBCode data.
Configuration of default BBCode data
The default BBCode data is configured in the bbcodes-configuration.xml file.
In particular, at runtime of BBCode Service, the BBCode plug-in component is called. Then, the bbcodes-configuration.xml file will be executed, and the component-plugin named registerBBCodePlugin will be referred to org.exoplatform.ks.bbcode.spi.BBCodePlugin to execute some objects that will generate default data.
<component-plugin>
<name>forum.default.bbcodes</name>
<set-method>registerBBCodePlugin</set-method>
<type>org.exoplatform.ks.bbcode.spi.BBCodePlugin</type>
<description>default supported BBCodes</description>
<init-params>
<object-param>
<name>I</name>
<description>set text in italic</description>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>I</string>
</field>
<field name="replacement">
<string><i>{param}</i></string>
</field>
<field name="description">
<string>Set text in italic</string>
</field>
<field name="example">
<string>[I]This text is italic[/I]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>B</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>B</string>
</field>
<field name="replacement">
<string><strong>{param}</strong></string>
</field>
<field name="description">
<string>Set text in bold</string>
</field>
<field name="example">
<string>[B]This text is bold[/B]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>U</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>U</string>
</field>
<field name="replacement">
<string><u>{param}</u></string>
</field>
<field name="description">
<string>Set text in underline</string>
</field>
<field name="example">
<string>[U]This text is underline[/U]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>COLOR</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>COLOR</string>
</field>
<field name="replacement">
<string><font color="{option}">{param}</font></string>
</field>
<field name="description">
<string>The [color=option] tag allows you to change the color of your text.</string>
</field>
<field name="example">
<string>[COLOR=blue]This text is blue[/COLOR]</string>
</field>
<field name="isOption">
<string>true</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>SIZE</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>SIZE</string>
</field>
<field name="replacement">
<string><font size="{option}">{param}</font></string>
</field>
<field name="description">
<string>The [size=option] tag allows you to change the size of your text.</string>
</field>
<field name="example">
<string>[size=+2]this text is two sizes larger than normal[/size]</string>
</field>
<field name="isOption">
<string>true</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>FONT</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>FONT</string>
</field>
<field name="replacement">
<string><font face="{option}">{param}</font></string>
</field>
<field name="description">
<string>The [font=option] tag allows you to change the font of your text.</string>
</field>
<field name="example">
<string>[font=courier]this text is in the courier font[/font]</string>
</field>
<field name="isOption">
<string>true</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>HIGHLIGHT</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>HIGHLIGHT</string>
</field>
<field name="replacement">
<string><span style="font-weight: bold; color: blue;">{param}</span></string>
</field>
<field name="description">
<string>The [highlight] tag allows you to make highlight of your text.</string>
</field>
<field name="example">
<string>[highlight]this text is highlighted[/highlight]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>LEFT</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>LEFT</string>
</field>
<field name="replacement">
<string><div align="left">{param}</div></string>
</field>
<field name="description">
<string>The [left] tag allows aligntment text to left. </string>
</field>
<field name="example">
<string>[LEFT]This text is left-aligned[/LEFT]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>RIGHT</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>RIGHT</string>
</field>
<field name="replacement">
<string><div align="right">{param}</div></string>
</field>
<field name="description">
<string>The [right] tag allows aligntment text to right.</string>
</field>
<field name="example">
<string>[RIGHT]example[/RIGHT]</string>
</field>
<field name="isOption">
<string>[RIGHT]this text is right-aligned[/RIGHT]</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>CENTER</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>CENTER</string>
</field>
<field name="replacement">
<string><div align="center">{param}</div></string>
</field>
<field name="description">
<string>The [center] allows aligntment text to center.</string>
</field>
<field name="example">
<string>[CENTER]this text is center-aligned[/CENTER]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>JUSTIFY</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>JUSTIFY</string>
</field>
<field name="replacement">
<string><div align="justify">{param}</div></string>
</field>
<field name="description">
<string>The [justify] tag allows aligntment text to justify.</string>
</field>
<field name="example">
<string>[JUSTIFY]this text is justify-aligned[/JUSTIFY]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>EMAIL</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>EMAIL</string>
</field>
<field name="replacement">
<string><a href="mailto:{param}">{param}</a></string>
</field>
<field name="description">
<string>The [email] tag allows you to link to an email address.</string>
</field>
<field name="example">
<string>[email]demo@example.com[/email]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>EMAIL-OPT</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>EMAIL</string>
</field>
<field name="replacement">
<string><a href="mailto:{option}">{param}</a></string>
</field>
<field name="description">
<string>The [email=option] tag allows link to an email address and use an optional parameter to 'name' of this link.</string>
</field>
<field name="example">
<string>[email=demo@example.com]Click Here to Email me[/email] </string>
</field>
<field name="isOption">
<string>true</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>URL</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>URL</string>
</field>
<field name="replacement">
<string><a target='_blank' href="{param}">{param}</a></string>
</field>
<field name="description">
<string>The [url] tag allows link to other websites and files.</string>
</field>
<field name="example">
<string>[URL]http://www.exoplatform.com[/URL]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>URL-OPT</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>URL</string>
</field>
<field name="replacement">
<string><a target='_blank' href="{option}">{param}</a></string>
</field>
<field name="description">
<string>The [url=option] tag allows link to other websites and files and usean optional parameter to 'name' of thislink.</string>
</field>
<field name="example">
<string>[URL=http://www.exoplatform.com]Click goto exoplatform website.[/URL]</string>
</field>
<field name="isOption">
<string>true</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>GOTO</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>GOTO</string>
</field>
<field name="replacement">
<string><a href="{option}">{param}</a></string>
</field>
<field name="description">
<string>Allows goto directly to link instead of open a new window or a new tab. </string>
</field>
<field name="example">
<string>[goto=http://www.exoplatform.com]Goto this link.[/goto]></string>
</field>
<field name="isOption">
<string>true</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>LIST</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>LIST</string>
</field>
<field name="replacement">
<string>You can not define this bbcode tag. It is defined by the developer.</string>
</field>
<field name="description">
<string>The [list] tag allows create simple, each bullet is denoted by the [*] tag.</string>
</field>
<field name="example">
<string>[list][*]list item 1[*]list item 2[/list]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>LIST-OPT</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>LIST</string>
</field>
<field name="replacement">
<string>You can not define this bbcode tag. It is defined by the developer.</string>
</field>
<field name="description">
<string>The [list=option] tag allows create bulleted lists specifying an option. Within the value portion, each bullet is denoted by the [*] tag.</string>
</field>
<field name="example">
<string>[list=1][*]list item 1[*]list item 2[/list]</string>
</field>
<field name="isOption">
<string>true</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>IMG</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>IMG</string>
</field>
<field name="replacement">
<string><img border="0" alt="" src="{param}" class="inlineimg"/></string>
</field>
<field name="description">
<string>The [img] tag allows you to shows the image indicated by {url}</string>
</field>
<field name="example">
<string>[url=http://www.google.com.vn] [img]http://groups.google.com.vn/groups/img/3nb/groups_medium_vi.gif[/img] [/url]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>QUOTE</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>QUOTE</string>
</field>
<field name="replacement">
<string><div style="background:#ededf7; border:1px solid #d8d8d8; padding:6px 6px 6px 15px; margin:2px 0px;">{param}</div></string>
</field>
<field name="description">
<string>The [quote] tag allows attribute content of post.</string>
</field>
<field name="example">
<string>[quote]Lorem ipsum dolor sit amet[/quote]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>QUOTE-OPT</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>QUOTE</string>
</field>
<field name="replacement">
<string><div style="background:#ededf7; border:1px solid #d8d8d8; padding:6px 6px 6px 15px; margin:2px 0px;"><div>Originally Posted by <strong>{option}</strong></div><div>{param}</div></div></string>
</field>
<field name="description">
<string>The [quote=option] tag allows attibute content and user name of poster.</string>
</field>
<field name="example">
<string>[quote=John Doe]Lorem ipsum dolor sit amet[/quote]</string>
</field>
<field name="isOption">
<string>true</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>CODE</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>CODE</string>
</field>
<field name="replacement">
<string><div style="background:#ededed; border:1px inset #7b7b7b; margin:5px; overflow:auto;"><pre style="margin: 0px; padding: 0px; overflow: auto; text-align: left;" dir="ltr"><div>{param}</div></pre></div></string>
</field>
<field name="description">
<string>The [code] tag allows you to view source code html.</string>
</field>
<field name="example">
<string>[code]<div>some text or code html</div>[/code]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>CSS</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>CSS</string>
</field>
<field name="replacement">
<string><span class="{option}">{param}</span></string>
</field>
<field name="description">
<string>The [css=option] tag allows you to add div tag and set class Name for this it.</string>
</field>
<field name="example">
<string>[css=highlight]Text is highlight[/css]</string>
</field>
<field name="isOption">
<string>true</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
<object-param>
<name>SLIDESHARE</name>
<description/>
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>SLIDESHARE</string>
</field>
<field name="replacement">
<string>
<div style="width:425px; height:355px;" align="center">
<object style="margin:0px" width="425" height="355">
<param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc={option}&rel=0"/>
<param name="allowFullScreen" value="true"/>
<param name="allowScriptAccess" value="always"/>
<embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc={option}&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355">
</embed>
</object>
<strong>{param}</strong></div>
</string>
</field>
<field name="description">
<string>The [SLIDESHARE=option] tag allows you to run slide in slidesharecdn.com site.</string>
</field>
<field name="example">
<string>[SLIDESHARE=slideId]My slide[/SLIDESHARE]</string>
</field>
<field name="isOption">
<string>true</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
In which,
Name | Set method | Type | Description |
---|---|---|---|
forum.default.bbcodes | registerBBCodePlugin | org.exoplatform.ks.bbcode. spi.BBCodePlugin | Define formats for data displayed on UI. |
The BBCode array is defined by the org.exoplatform.ks.bbcode.spi.BBCodeData object as below:
<object type="org.exoplatform.ks.bbcode.spi.BBCodeData">
<field name="tagName">
<string>I</string>
</field>
<field name="replacement">
<string><i>{param}</i></string>
</field>
<field name="description">
<string>Set text in italic</string>
</field>
<field name="example">
<string>[I]This text is italic[/I]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
</object>
The BBCode includes basic data which are defined in the field tag with a specific name as below:
<field name="tagName">
<string>I</string>
</field>
<field name="replacement">
<string><i>{param}</i></string>
</field>
<field name="description">
<string>Set text in italic</string>
</field>
<field name="example">
<string>[I]This text is italic[/I]</string>
</field>
<field name="isOption">
<string>false</string>
</field>
<field name="isActive">
<string>true</string>
</field>
In which:
Field name | Value | Description |
---|---|---|
tagName | string | The text for the BBCode, which is put between two square brackets ([ ]). For example, for the bold tag, if you type [b], the BBCode tag will be b without any square brackets ([ ]). |
replacement | string | The HTML code that replaces the BBCode entered by the user. Make sure that you include '{param}' (without quotes) to insert the text between opening and closing BBCode tags, and '{option}' for the parameter within the BBCode tag. You can only use option if 'Use Option' is selected. |
description | string | The piece of text to describe the BBCode tag, including HTML tags if you want. |
example | string | The sample piece of BBCode to use as an example for the particular BBCode. For example, to demonstrate the usage of [b] tag, enter [b]text[/b]. |
isOption | true , false | Select the [tag=option] [/tag] style tag, rather than just a [tag][/tag] style tag. This function will be created if you select this option. |
isActive | true , false | Activate the BBCode tag. |
The Initialization plug-in component defines the default Forum data in the .xml file, including categories, forums, topics and posts.
When the Forum Service runs, it will get values which are returned from the Initialization plug-in component to initialize default data of the Forum.
This section covers the following topics:
The default forum data is configured in the war:webapp/WEB-INF/conf/ksdemo/ks/services-configuration.xml file.
In particular, when the ForumService starts, the Initialization plug-in component is called. Next, the services-configuration.xml file is executed. The component-plugin named addInitialDefaultDataPlugin will refer to org.exoplatform.forum.service.conf.InitializeForumPlugin to execute some objects to create default data for the Forum application.
<component-plugin>
<name>default.data</name>
<set-method>addInitialDefaultDataPlugin</set-method>
<type>org.exoplatform.forum.service.conf.InitializeForumPlugin</type>
<description>description</description>
<init-params>
<object-param>
<name>livedemo.default.configuration</name>
<description>initial data for live demo</description>
<object type="org.exoplatform.forum.service.conf.ForumInitialData">
<field name="categories">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.forum.service.conf.CategoryData">
<field name="owner">
<string>root</string>
</field>
<field name="name">
<string>Knowledge Suite</string>
</field>
<field name="description">
<string>All about eXo KS</string>
</field>
<field name="forums">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.forum.service.conf.ForumData">
<field name="owner"><string>root</string></field>
<field name="name"><string>Live demo</string></field>
<field name="description"><string>Questions about this demo</string></field>
<field name="topics">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.forum.service.conf.TopicData">
<field name="name"><string>Demo data policy</string></field>
<field name="icon"><string>Shield</string></field>
<field name="owner"><string>root</string></field>
<field name="content"><string>
Welcome to eXo Knowledge Suite live demo!
We hope you enjoy discovering eXo Forum and FAQ applications features.
You don't need to be logged in to see the applications in action.
But the power of KS lies in the rich set of admin/moderation features.
We didn't want you to miss them so, when you [b][url="/portal/public/classic/register"]
create a demo account[/url][/b], you will be granted full permissions.
Anybody can become an administrator or a moderator and play in the sandbox!
As a consequence, the data for this forum (including the accounts) is not meant to stay.
[b][center]WE MAY RESET FORUMS AND FAQS ANYTIME[/center][/b]
Enjoy and don't forget to send feedback at [email]ks@exoplatform.com[/email]</string></field>
</object>
</value>
</collection>
</field>
</object>
</value>
</collection>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
In which,
Name | Set-method | Type | Description |
---|---|---|---|
default.data | addInitialDataPlugin | org.exoplatform.forum. service.conf. InitializeForumPlugin | The initial default data of Forum. |
Init-param
Name | Possible value | Default value | Description |
---|---|---|---|
livedemo.default. configuration | object | org.exoplatform.forum. service.conf. ForumInitialData | The initial data for live demo. |
Category array
After the org.exoplatform.forum.service.conf.InitializeForumPlugin object has been executed, the org.exoplatform.forum.service.conf.ForumInitialData object will be called. It returns a category array. The value of category array is defined by the org.exoplatform.forum.service.conf.CategoryData object as below:
<object-param>
<name>livedemo.default.configuration</name>
<description>initial data for live demo</description>
<object type="org.exoplatform.forum.service.conf.ForumInitialData">
<field name="categories">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.forum.service.conf.CategoryData">
<field name="owner">
<string>root</string>
</field>
<field name="name">
<string>Knowledge Suite</string>
</field>
<field name="description">
<string>All about eXo KS</string>
</field>
...
</object>
</value>
</collection>
</field>
</object>
</object-param>
Category includes some basic data which are defined in the field tag with a specific name as below:
<field name="owner">
<string>root</string>
</field>
<field name="name">
<string>Knowledge Suite</string>
</field>
<field name="description">
<string>All about eXo KS</string>
</field>
In which:
Field | Possible value | Default value | Description |
---|---|---|---|
owner | user id | root | The creator of Category. |
name | string | Knowledge Suite | The title of Category. |
description | string | All about eXo KS | The brief description of Category. |
Modify values of Category
Values of the default Category can be changed by editing text values in the string tag of each field by the other one. In the sample code above, the org.exoplatform.forum.service.conf.CategoryData object is called. It means that only one default Category is defined. If you want to define more default Categories, repeat calling the org.exoplatform.forum.service.conf.CategoryData object and define values for the new Category with the sample code as below:
<value>
<object type="org.exoplatform.forum.service.conf.CategoryData">
<field name=" ">
...
</field>
</object>
</value>
Category may contain one or more Forums. The value of the Forum is defined in the forums field. It returns a forum array. The value of forum array is defined by the org.exoplatform.forum.service.conf.ForumData object as below:
<field name="forums">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.forum.service.conf.ForumData">
<field name="owner"><string>root</string></field>
<field name="name"><string>Live demo</string></field>
<field name="description"><string>Questions about this demo</string></field>
...
</object>
</value>
</collection>
</field>
Basic Forum data
Forum includes some basic data which are defined in the field tag with the specific name as above.
In which:
Field | Possible value | Default value | Description |
---|---|---|---|
owner | user id | root | The creator of default Forum. |
name | string | Live demo | The name or title of default Forum. |
description | string | Questions about this demo | The brief description of default Forum. |
The default Forum values can be changed by editing text values in the string tag of each field by the other one.
In the sample code above, the org.exoplatform.forum.service.conf.ForumData object is called only one time. It means that only one default Forum is defined inside the default Category named Knowledge Suite. If you want to define more default Forums, repeat calling the org.exoplatform.forum.service.conf.ForumData object and define values for the new Forum with the sample code as below:
<value>
<object type="org.exoplatform.forum.service.conf.ForumData">
<field name=" ">
...
</field>
</object>
</value>
Forum may contain one or more topics. The value of topic is defined in the topics field. It returns a topic array. The value of topic array is defined by the org.exoplatform.forum.service.conf.TopicData object as below:
<field name="topics">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.forum.service.conf.TopicData">
<field name="name"><string>Demo data policy</string></field>
<field name="icon"><string>Tux</string></field>
<field name="owner"><string>root</string></field>
<field name="content"><string>Welcome to eXo Forum live demo. ... at anytime.</string></field>
...
</object>
</value>
</collection>
</field>
A topic includes some basic data which are defined in the field tag with a specific name as above.
In which:
Field | Possible value | Default value | Description |
---|---|---|---|
name | string | Demo data policy | The name or title of default topic. |
icon | string
| Tux | The default icon of default topic. |
owner | user id | root | The creator of default topic. |
content | string | Welcome to eXo Forum live demo...at anytime. | The main content of default topic. |
The values of default topic can be changed by editing text values in the string tag of each field.
With the sample code above, the org.exoplatform.forum.service.conf.TopicData object is called only one time. It means that only one default topic is defined inside the default Forum named Live demo. If you want to define more default topics, repeat calling the org.exoplatform.forum.service.conf.TopicData object and define values for the new topic with the sample code as below:
<value>
<object type="org.exoplatform.forum.service.conf.TopicData">
<field name=" ">
...
</field>
</object>
</value>
Topic may contain one or more posts. The value of the post is defined in the posts field. It returns a post array. The value of the post array is defined by the org.exoplatform.forum.service.conf.PostData object as below:
<field name="posts">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.forum.service.conf.PostData">
<field name="name"><string>Reply: Demo data policy</string></field>
<field name="icon"><string>IconsView</string></field>
<field name="owner"><string>root</string></field>
<field name="content"><string>Enjoy and don't forget to send feedback at ks@exoplatform.com</string></field>
...
</object>
</value>
</collection>
</field>
A post includes some basic data which are defined in the field tag with a specific name as above.
In which:
Field | Possible value | Default value | Description |
---|---|---|---|
name | string | Reply: Demo data policy | The name or title of default post. |
icon | string | IconsView | The default icon of default post. |
ownwer | user id | root | The creator of default post. |
content | string | Enjoy and don't forget to send feedback at ks@exoplatform.com | The main content of default post. |
The default post values can be changed by editing text values in the string tag of each field.
With the sample code above, the org.exoplatform.forum.service.conf.PostData object is called only one time. It means that only one default post is defined inside the default topic named Demo data policy. If you want to define more default posts, repeat calling the org.exoplatform.forum.service.conf.PostData object and define values for the new post with the sample code as below:
<value>
<object type="org.exoplatform.forum.service.conf.PostData">
<field name=" ">
...
</field>
</object>
</value>
By default, the default Forum data can only be changed by modifying the services-configuration.xml file.
At runtime, the new changes in the services-configuration.xml file will be executed and updated. The default Forum data will be created correspondingly.
The Initial Data plugin is configured in the services-configuration.xml file. In details, at runtime of Forum Service, the Initialization plugin component is called, the services-configuration.xml file will be executed. The component-plugin named addInitialDataPlugin will refer to org.exoplatform.forum.service.conf.ForumInitialDataPlugin to import some objects to create data for the Forum service. The default data in the .zip or .xml file is initialized as follows:
<component-plugin>
<name>technical.forum</name>
<set-method>addInitialDataPlugin</set-method>
<type>org.exoplatform.forum.service.conf.ForumInitialDataPlugin</type>
<description>Initialize</description>
<init-params>
<values-param>
<name>locations</name>
<description>location where Forum export format file is stored</description>
<value>war:/data/forum/data-full-forum.zip</value>
<!-- value>war:/data/forum/forumCategory.xml</value -->
</values-param>
</init-params>
</component-plugin>
In which:
Name | Set-Method | Type | Description |
---|---|---|---|
technical.forum | addInitialDataPlugin | org.exoplatform.forum.service.conf.ForumInitialDataPlugin | Initialize the data plugin. |
Init-params
Name | Possible values | Default value | Description |
---|---|---|---|
locations | String | war:/data/forum/data-full-forum.zip | The location where the Forum export format file is stored. |
The Auto-prune component is to prune inactive topics which have not been viewed, edited or received for a given period. The "prune" operation does not denote to the physical removal of topics, but sets them to invisible. The function helps you not clutter busy forums from outdated information.
When the Job Scheduler runs, it will get values returned from the Auto-prune plug-in component to identify topics which have to be inactivated in the Forum application. These topics will be invisible to users.
The properties of Auto-prune plug-in are configured in the war:webapp/WEB-INF/ks-extension/ks/forum/prune-configuration.xml file.
In particular, at runtime of Job Scheduler, the Auto-prune plugin component is called. Then, the prune-configuration.xml file will be executed. The component-plugin named ForumDeactiveJob will refer to org.exoplatform.forum.service.conf.DeactivePeriodJob to inactivate topics in Forum which meets predefined inactivation properties.
<component-plugin>
<name>ForumDeactiveJob</name>
<set-method>addPeriodJob</set-method>
<type>org.exoplatform.forum.service.conf.DeactivePeriodJob</type>
<description>add a Deactive job to the JobSchedulerService</description>
<init-params>
<properties-param>
<name>job.info</name>
<description>save the monitor data periodically</description>
<property name="jobName" value="DeactiveJob"/>
<property name="groupName" value="KnowlegedSuite"/>
<property name="job" value="org.exoplatform.forum.service.conf.DeactiveJob"/>
<property name="repeatCount" value="0"/>
<property name="period" value="7200000"/> <!-- 2 hours-->
<property name="startTime" value="+0"/>
<property name="endTime" value=""/>
</properties-param>
<properties-param>
<name>deactive.info</name>
<description/>
<property name="inactiveDays" value="15"/>
<property name="forumName" value="Live demo"/>
</properties-param>
</init-params>
</component-plugin>
In which,
Name | Set-method | Type | Description |
---|---|---|---|
ForumDeactiveJob | addPeriodJob | org.exoplatform.forum. service.conf. DeactivePeriodJob | Add a DeactiveJob to the JobSchedulerService. |
The properties for the Auto-prune plug-in are defined in the property tag with the format as below:
...
<property name="jobName" value="DeactiveJob"/>
<property name="groupName" value="KnowlegedSuite"/>
<property name="job" value="org.exoplatform.forum.service.conf.DeactiveJob"/>
<property name="repeatCount" value="0"/>
<property name="period" value="7200000"/> <!-- 2 hours-->
<property name="startTime" value="+0"/>
<property name="endTime" value=""/>
...
<property name="inactiveDays" value="15"/>
<property name="forumName" value="Live demo"/>
...
In details:
Property name | Possible value | Default value | Description |
---|---|---|---|
jobname | String | DeactiveJob | The name of job which will be executed. |
groupname | String | KnowlegedSuite | The name of application which will be executed. |
job | Class path | org.exoplatform.forum. service.conf.DeactiveJob | The reference function of the job which will be executed. |
repeatCount | Long | 0 | The repeating time for the job, meaning that how many times the job will be executed. The 0 value means that DecactiveJob is called at runtime only without repeating. If the value is set to 2 or 3, DecactiveJob will be called two or three times correspondingly. |
period | Long | 72000000 | The interval between job executions. |
starttime | Integer | +0 | The start time when the function executes. The starttime is 0, meaning that the time to start executing DecactiveJob is the runtime. |
endtime | Integer | null | The end time when the function stops executing. The endtime is blank, meaning that there is no limitation for the end time for DecactiveJob. |
With start and end time, you can give a specific date in the format: yyyy-mm-dd HH:mm:ss.sss to define the start and end time for DecactiveJob. Besides, inactive information is also defined:
Property name | Possible value | Default value | Description |
---|---|---|---|
inactiveDays | Integer | 15 | The number of days the topic has not been activated. The inactivateDays is set to 1, meaning that all the topics, which have one inactivated day, will be set as inactivated status. They will be invisible. |
forumname | String | Live Demo | The name of Forum which will be checked for Auto-prune. In case the value of forumname is blank, all forums will be checked for the Auto-prune. If the forumname is Live demo, only the Forum named 'Live demo' is checked for the Auto-prune. |
By default, the default properties can only be changed by editing its value in the prune-configuration.xml file.
At runtime, the new changes in the prune-configuration.xml file are executed and updated. After that, the Auto-prune plug-in will be executed, depending on its properties.
The Auto-count Active Users component is to calculate the number of active users automatically. A user is considered as the active user only when he/she adds a topic/post in the Forum and his/her last post date matches the predefined interval time.
For example, if one user does not have any new posts after 15 days, he/she is not considered as an active user.
When the Job Scheduler runs, it will get values returned from the Auto-count Active Users plug-in component to identify the number of active users. This value is updated to Active Members information when the user views Forum statistics.
The properties of Auto-count Active Users plug-in is configured in the war:webapp/WEB-INF/ks-extension/ks/forum/statistics-configuration.xml file.
In details, at runtime of Job Scheduler, the Auto-count Active Users plug-in component is called. Then, the statistics-configuration.xml file is executed. The component-plugin named RecountActiveUserJob will refer to org.exoplatform.forum.service.conf.RecountActiveUserPeriodJob to calculate the number of active users.
<component-plugin>
<name>RecountActiveUserJob</name>
<set-method>addPeriodJob</set-method>
<type>org.exoplatform.forum.service.conf.RecountActiveUserPeriodJob</type>
<description>add a RecountActiveUser job to the JobSchedulerService</description>
<init-params>
<properties-param>
<name>job.info</name>
<description>save the monitor data periodically</description>
<property name="jobName" value="RecountActiveUserJob"/>
<property name="groupName" value="KnowlegedSuite"/>
<property name="job" value="org.exoplatform.forum.service.conf.RecountActiveUserJob"/>
<property name="repeatCount" value="0"/>
<property name="period" value="7200000"/> <!-- 2 hours-->
<property name="startTime" value="+0"/>
<property name="endTime" value=""/>
</properties-param>
<properties-param>
<name>RecountActiveUser.info</name>
<description/>
<property name="lastPost" value="15"/> <!-- users are active if have last posts in 15 day -->
</properties-param>
</init-params>
</component-plugin>
In which,
Name | Method | Type | Description |
---|---|---|---|
RecountActiveUserJob | addPeriodJob | org.exoplatform.forum. service.conf. RecountActiveUserPeriodJob | Add a RecountActiveUser job to the JobSchedulerService. |
The properties for Auto-count Active Members plug-in are defined in the property tag as below:
...
<property name="jobName" value="RecountActiveUserJob"/>
<property name="groupName" value="KnowlegedSuite"/>
<property name="job" value="org.exoplatform.forum.service.conf.RecountActiveUserJob"/>
<property name="repeatCount" value="0"/>
<property name="period" value="7200000"/>
<property name="startTime" value="+0"/>
<property name="endTime" value=""/>
...
<property name="lastPost" value="15"/>
...
In which:
Property name | Possible value | Default value | Description |
---|---|---|---|
jobname | String | RecountActiveUserJob | The name of job which will be executed. |
groupname |
String | KnowlegedSuite | The name of application which will be executed. |
job | Class path | org.exoplatform.forum. service.conf. RecountActiveUserJob | The reference function of job which will be executed. |
repeatCount | Long | 0 | The number of times the job is repeated. If repeatCount is set to 0, RecountActiveUserJob is called at runtime only without repeating. If the number is set to 2 or 3, RecountActiveUserJob will be called two or three times. |
period | Long | 7200000 (millisecond) (equal to two hours) | The interval time to execute the job. |
starttime | Integer | 0 | The start time when the function executes. The starttime is 0, meaning that the time to start executing RecountActiveUserJob is the runtime. |
endtime | Integer | null | The end time when the function stops executing. The endtime is blank, meaning that there is no limitation for the end time for RecountActiveUserJob. |
With start and end time, you can give a specific date in the format: yyyy-mm-dd HH:mm:ss.sss to define the start and end time for RecountActiveUserJob. The information of active time is also defined:
Property name | Possible value | Default value | Description |
---|---|---|---|
lastPost | Integer | 15 | The number of days that the user has added the last post. lastPost is 15, meaning that all users, who have any new posts within 15 days as from their last post date, are active members. |
By default, the default properties can only be changed by editing its values in the statistics-configuration.xml file.
At runtime, the new changes in the statistics-configuration.xml file will be executed and updated. The Auto-count Active Users plug-in will be executed, depending on its properties.
UpdateDataJob is used when there are abnormal changes in Forum data (such as migration). By default, UpdateDataJob is disabled at the server start up. When UpdateDataJob is running, it will calculate the statistic data in Forum to make sure that the statistic data are correct.
The properties of Forum's UpdateDataJob is configured in /WEB-INF/ks-extension/ks/forum/statistics-configuration.xml which is located in ks-extension webapp.
<component-plugin>
<name>UpdateDataJob</name>
<set-method>addPeriodJob</set-method>
<type>org.exoplatform.services.scheduler.PeriodJob</type>
<description>update topic count and post count to forum service</description>
<init-params>
<properties-param>
<name>job.info</name>
<description>save the monitor data periodically</description>
<property name="jobName" value="UpdateDataJob"/>
<property name="groupName" value="KnowledgeSuite-forum"/>
<property name="job" value="org.exoplatform.forum.service.conf.UpdateDataJob"/>
<property name="repeatCount" value="1"/>
<property name="period" value="30000"/>
<property name="startTime" value="+0"/>
<property name="endTime" value=""/>
</properties-param>
</init-params>
</component-plugin>
In which:
Name | Method | Type | Description |
---|---|---|---|
UpdateDataJob | addPeriodJob | org.exoplatform.services.scheduler.PeriodJob | Add a UpdateDataJob to the JobSchedulerService. |
The properties for Auto-count Active Members plug-in are defined in the property tag as below:
<property name="jobName" value="UpdateDataJob"/>
<property name="groupName" value="KnowledgeSuite-forum"/>
<property name="job" value="org.exoplatform.forum.service.conf.UpdateDataJob"/>
<property name="repeatCount" value="1"/>
<property name="period" value="30000"/>
<property name="startTime" value="+0"/>
<property name="endTime" value=""/>
Property name | Possible value | Default value | Description |
---|---|---|---|
jobname | String | UpdateDataJob | The name of job which will be executed. |
groupname |
String | KnowledgeSuite-forum | The name of application which will be executed. |
job | Class path | org.exoplatform.forum.service.conf.UpdateDataJob | The reference function of job which will be executed. |
repeatCount | Long | 1 | The number of times the job is repeated. If repeatCount is set to 1, RecountActiveUserJob is called at runtime only without repeating. If the number is set to 2 or 3, RecountActiveUserJob will be called two or three times. |
period | Long | 30000 (millisecond) (equal to two hours) | The interval time to execute the job. |
starttime | Integer | 0 | The start time when the function executes. The starttime is 0, meaning that the time to start executing RecountActiveUserJob is the runtime. |
endtime | Integer | null | The end time when the function stops executing. The endtime is blank, meaning that there is no limitation for the end time for UpdateDataJob. |
With start and end time, you can give a specific date in the format: yyyy-mm-dd HH:mm:ss.sss to define the start and end time for UpdateDataJob.
The default Forum settings are a set of settings for a new account. It contains declarations of time zone, short date format, long date format, time format, maximum topics per page, maximum posts per page and flag for showing forum jump or not. The settings are simple, and users can change such settings to UI-based functions later.
This configuration is declared in the file named ks-configuration.xml. Its path is "[tomcat source]/webapps/ks-extension/WEB-INF/ks-extension/ks/ks-configuration.xml" if you are running the tomcat and "[project source]/extension/webapp/src/main/webapp/WEB-INF/ks-extension/ks/ks-configuration.xml" if you are in the development phrase.
...
<external-component-plugins>
<target-component>org.exoplatform.services.organization.OrganizationService</target-component>
<component-plugin>
...
<init-params>
<properties-param>
<name>user.profile.setting</name>
<description>set default user profile</description>
<property name="timeZone" value="GMT"/>
<property name="shortDateFormat" value="MM/dd/yyyy"/>
<property name="longDateFormat" value="DDD,MMM dd,yyyy"/>
<property name="timeFormat" value="hh:mm a"/>
<property name="maxTopic" value="10"/>
<property name="maxPost" value="10"/>
<property name="isShowForumJump" value="true"/>
</properties-param>
</init-params>
</component-plugin>
</external-component-plugins>
...
In which:
Parameter | Possible value | Default value | Description |
---|---|---|---|
timeZone | Time zone id | GMT | The time zone set by user. For example: GMT, GMT-05:00, GMT+07:00, GMT+08:30 ... Visit the website: http://java.sun.com/j2se/1.4.2/docs/api/java/util/TimeZone.html for more details. |
shortDateFormat | Valid Java Date format | MM/dd/yyyy | The format to display short information of date. Visit the website: http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html to ensure the exact format.) |
longDateFormat | Valid Java Date format | DDD,MMM dd,yyyy | The format to display a date with more information. Visit the website http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html to ensure the exact format. |
timeFormat | valid Java Date format | hh:mm a | The format to view time (for example, hour, minute,). Visit the website: http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html to ensure the exact format. |
maxTopic | Integer | 10 | The maximum number of topics per page. |
maxPost | Integer | 10 | The maximum number of posts per page. |
isShowForumJump | true / false | true | Show the forum jump or not. |
The Initialization plug-in component is to define the default answers data in the .xml or .zip file. It includes categories of question that should be exported from the Answers application.
When the Answers Service starts, it will get values returned from the Initialization plug-in component to initialize the default Answers data.
Default Answers data
The default Answers data is configured in the services-configuration.xml file.
In details, at runtime of Answers Service, the Initialization plug-in component is called, the services-configuration.xml file will be executed. The component-plugin named addInitialDataPlugin will refer to org.exoplatform.faq.service.InitializeDataPlugin to execute some objects to create default data.
The default data in the .zip file is initialized as follows:
<component-plugin>
<name>technical-faq</name>
<set-method>addInitialDataPlugin</set-method>
<type>org.exoplatform.faq.service.InitialDataPlugin</type>
<description>Initialize</description>
<init-params>
<value-param>
<name>location</name>
<description>location where Answers export format file is stored</description>
<value>war:/data/Technical-FAQ.zip</value>
</value-param>
</init-params>
</component-plugin>
In which,
Name | Set-Method | Type | Description |
---|---|---|---|
technical-faq | addInitialDataPlugin | org.exoplatform.faq.service. InitialDataPlugin | Initialize the data plugin. |
Init-param
Name | Possible value | Default value | Description |
---|---|---|---|
location | string | war:/data/ Technical-FAQ.zip | The location where the Answers export format file is stored. |
If the default data is in the XML format:
<value>war:/data/Technical-FAQ.xml</value>
By default, the default Answers data can only import if the importing categories do not exist in database.
To initialize default data in multiple files, it is required to declare them in multiple plugins.
<component-plugin>
....
</component-plugin>
Answers is configured mainly in the file:
Portlet preferences: /webapps/faq/WEB-INF/portlet.xml
For general information of eXo Knowledge configuration, refer to eXo Knowledge Configuration section.
The Mail templates use a specific syntax, enabling you to create a customized email message in the Edit mode via three templates: New question, Edit/answer, and Move question.
Parameters which are used in templates consist of:
Parameter | Description |
---|---|
&categoryName | Load the name of Category. |
&questionContent | Load the question's content. |
&questionResponse | Load the question's answer. |
&questionLink | Load the link to question in the Answers portlet. |
The Initialization plugin component defines the default Poll data in the .xml file, including polls. When the Poll Service runs, it will get values returned from the Initialization plugin component to initialize default Poll data.
Configuration of default Poll data
The default Poll data are configured in the war:webapp/WEB-INF/conf/ksdemo/ks/services-configuration.xml file.
In particular, when the Poll service starts, the Initialization plug-in component is called. Next, the services-configuration.xml file is executed. The component-plugin named addInitialDefaultDataPlugin will refer to org.exoplatform.poll.service.InitialDeafaultDataPlugin to execute some objects to create default data for the Poll application.
<component-plugin>
<name>default.data</name>
<set-method>addInitialDefaultDataPlugin</set-method>
<type>org.exoplatform.poll.service.InitialDefaultDataPlugin</type>
<description>Initialize</description>
<init-params>
<object-param>
<name>livedemo.default.configuration</name>
<description>initial data for live demo</description>
<object type="org.exoplatform.poll.service.PollInitialData">
<field name="pollDatas">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.poll.service.PollData">
<field name="parentPath">
<string>ksdemo/Polls</string>
</field>
<field name="owner">
<string>root</string>
</field>
<field name="question">
<string>What color do you like ?</string>
</field>
<field name="timeOut">
<string>0</string>
</field>
<field name="isMultiCheck">
<string>false</string>
</field>
<field name="isAgainVote">
<string>false</string>
</field>
<field name="isClosed">
<string>false</string>
</field>
<field name="options">
<collection type="java.util.ArrayList">
<value><string>Green</string></value>
<value><string>Blue</string></value>
<value><string>Red</string></value>
<value><string>Yellow</string></value>
<value><string>Orange</string></value>
<value><string>Purple</string></value>
</collection>
</field>
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
In which,
Name | Set-method | Type | Description |
---|---|---|---|
default.data | addInitialDefaultDataPlugin | org.exoplatform.poll.service.InitialDefaultDataPlugin | The initial default data of Poll. |
Init-param
Name | Possible value | Default value | Description |
---|---|---|---|
livedemo.default.configuration | object | org.exoplatform.poll.service.PollInitialData | The initial data for live demo. |
Poll array
After the org.exoplatform.poll.service.InitialDefaultDataPlugin object has been executed, the org.exoplatform.poll.service.PollInitialData object will be called. It returns a polls array. The value of poll array is defined by the org.exoplatform.poll.service.PollData object as below:
<name>livedemo.default.configuration</name>
<description>initial data for live demo</description>
<object type="org.exoplatform.poll.service.PollInitialData">
<field name="pollDatas">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.poll.service.PollData">
....
</object>
</value>
</collection>
</field>
</object>
A Poll includes some basic data which are defined in the field tag with a specific name as below:
....
<field name="parentPath">
<string>ksdemo/Polls</string>
</field>
<field name="owner">
<string>root</string>
</field>
<field name="question">
<string>What color do you like ?</string>
</field>
<field name="timeOut">
<string>0</string>
</field>
<field name="isMultiCheck">
<string>false</string>
</field>
<field name="isAgainVote">
<string>false</string>
</field>
<field name="isClosed">
<string>false</string>
</field>
<field name="options">
<collection type="java.util.ArrayList">
<value><string>Green</string></value>
<value><string>Blue</string></value>
<value><string>Red</string></value>
<value><string>Yellow</string></value>
<value><string>Orange</string></value>
<value><string>Purple</string></value>
</collection>
</field>
....
In which:
Field | Possible value | Default value | Description |
---|---|---|---|
parentPath | string | ksdemo/Polls | Parent path of Poll data. |
owner | user id | root | The creator of Poll. |
question | string | What color do you like? | The question for Poll. |
timeout | number | 0 | The time before poll is closed. If value is set to 0, the poll will never be closed. |
isMultiCheck | boolean | false | If the value is true, user can vote for multi-options. If the value is false, only one option can be voted. |
isAgainVote | boolean | false | If the value is true, user can vote again. |
isClose | boolean | false | If the value is true, the poll will be closed. |
options | java.util.ArrayList | List of string | list of options for Poll. |
Modify values of Poll
Values of the default Poll can be changed by editing text values in the tag of each field by the other one.
Data injector is used to create data for the performance benchmark. This part will describe which data injectors are implemented in eXo Knowledge and how to use them.
In eXo Knowledge, data injectors are implemented as plugins attached to the org.exoplatform.services.bench.DataInjectorService service. This service is normally registered to the portal container as a general component and handled via RESTful requests.
To use this service, add the following dependency to the Classpath of the server:
<dependency>
<groupId>org.exoplatform.commons</groupId>
<artifactId>exo.platform.commons.component</artifactId>
<version>1.1.9-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
When you want to inject data for a specified product, you will have to implement a class which extends org.exoplatform.services.bench.DataInjector and register it to DataInjectorService as a plugin.
In which, methods need to be installed are:
public abstract class DataInjector extends BaseComponentPlugin {
/**
* get log object.
* @return
*/
public abstract Log getLog();
/**
* This function should be implemented to execute tasks that require to response data to client.
* <br>
* @param params query parameters of a HTTP GET request.
* @return object that can be serialized to JSON object.
* @throws Exception
*/
public abstract Object execute(HashMap<String , String> params) throws Exception;
/**
* This function should be implemented to inject data into the product.
* @param params parameters for injecting. They can be query parameters of a HTTP GET request.
* @throws Exception
*/
public abstract void inject(HashMap<String , String> params) throws Exception;
/**
* This function should be implemented to clear data that is injected before by {@link #inject()}.
* @param params parameters for rejecting. They can be query parameters of a HTTP GET request.
* @throws Exception
*/
public abstract void reject(HashMap<String , String> params) throws Exception;
To activate DataInjectorService, you must register this component to a portal container by the following configuration:
<component>
<type>org.exoplatform.services.bench.DataInjectorService</type>
</component>
In eXo Knowledge, there are three plugins attached to the DataInjectorService component:
ForumDataInjector
WikiDataInjector
AnswerDataInjector
The Forum Data injector is configured to register to DataInjectorService by the following code:
<external-component-plug-ins>
<target-component>org.exoplatform.services.bench.DataInjectorService</target-component>
<component-plug-in>
<name>ForumDataInjector</name>
<set-method>addInjector</set-method>
<type>org.exoplatform.forum.bench.ForumDataInjector</type>
<description>inject data for Forum</description>
</component-plug-in>
</external-component-plug-ins>
To inject data, the request link is in the following format:
http://[rest-path]/bench/inject/ForumDataInjector/?type=data&q=10,20,30,40,50&pre=cat,for,top,post,att&attSize=1
The query parameters description:
Param | Value | Description |
---|---|---|
q | Number | The quantity of each item in forum. For example, if the value is 10,20,30,40,50 then the injector will create 10 categories, each category will have 20 forums, each forum contains 30 topics, each topic has 40 posts which contains 50 attachments in each posts. |
pre | String | The prefixes of category, forum, topic, post and attachment. If "cat,for,top,pos,att" is inputed, the injector will create a set of data inlcude: categories with "cat" prefix, forums with "for" prefix and so on. |
attSize | Number | The size of each attachment which is created in a post. |
Every created topic can only be read/modified by user 'root' to grant permission to other members.
The Data injector for Wiki is configured as follow:
<external-component-plug-ins>
<target-component>org.exoplatform.services.bench.DataInjectorService</target-component>
<component-plug-in>
<name>WikiDataInjector</name>
<set-method>addInjector</set-method>
<type>org.exoplatform.wiki.bench.WikiDataInjector</type>
<description>inject data for Wiki</description>
</component-plug-in>
</external-component-plug-ins>
To inject data, the request link is in the following format:
http://[rest path]/bench/inject/WikiDataInjector/?type=data&q=1,2,3&pre=abc,def,mnp&wo=classic&wt=portal&maxAtt=10&mP=100
In which, parameters mean:
Param | Value | Description |
---|---|---|
type | [data | perm] | Type of injector. It can be data or perm which injects data or permission respectively. |
q | Number | The number of pages in each depth, separated by commas. For example, if value is 1,2,3 then the injector will create 1 new child of WikiHome, 2 children per each page created in depth 1 and 3 children for each page created in depth 2. |
pre | String | Prefix for page id in each depth, separated by commas. For example, if value is abc,def,ghk then pages in depth 1 have title starting with "abc", title of pages in depth 2 start with "def" and in depth 3 is "ghk". |
wo | String | Wiki owner. |
wt | String | Wiki type. The value can be: 'portal', 'user', 'group'. |
maxAtt | Number | The size of attachment in created pages. the value is evaluated in KByte. If the value is 0 or not set, no attachment is created. |
mP | Number | The maximum pages in each injection. The number of created pages must not exceed this value. |
To grant permission, the request link is in the following format:
http://localhost:8080/rest-ksdemo/private/bench/inject/WikiDataInjector/?type=perm&q=1,2,3&pre=abc,def,ghk&wo=classic&wt=portal&perm=11&users=root,mary&groups=*:/platform/user&rcs=true
For instance, in the link above, the injector will set the Read and Edit permission for pages of portal/classic which meet the constraint (q=1,2,3 and pre=abc,def,ghk).
You can use these parameters to set up permissions for pages:
Param | Value | Description |
---|---|---|
q | Number | The number of pages in each depth separated by commas. For example, if value is 1,2,3 then the injector will create 1 new child of WikiHome, 2 children per each page created in depth 1 and 3 children for each page created in depth 2. |
pre | String | The prefix for page id in each depth separated by commas. For example, if the value is "abc,def,ghk" then pages in depth 1 will have title starting with "abc", title of pages in depth 2 will start with "def" and in depth 3 is "ghk" |
wo | String | The wiki owner separated by commas. |
wt | String | The wiki type separated by commas. This value can be: portal, user or group. |
users | String, | The list of granted permissions users separated by commas. |
groups | String | The list of granted permissions groups separated by commas. |
memship | String | The list of granted permissions memberships separated by commas. |
perm | [number][number] | The declared permissions. The value must be a string with 2 numbers. The first number is to define Read permission of identity while the other one is for Edit permission. If the number is "zero", the privilege is denied and vise versa. For example, 11 means that both Read and Edit pages permmission are granted. |
rcs | Boolean | Recursive or not. If the value is true, all pages that meet the constraint will be set permission, or deepest pages (smallest descendants) will be affected. |
The following configuration is used for the Answer Data injector:
<external-component-plug-ins>
<target-component>org.exoplatform.services.bench.DataInjectorService</target-component>
<component-plug-in>
<name>AnswerDataInjector</name>
<set-method>addInjector</set-method>
<type>org.exoplatform.faq.bench.AnswerDataInjector</type>
<description>inject data for Answer</description>
</component-plug-in>
</external-component-plug-ins>
To inject data, the request link is in the following format:
http://[rest path]/bench/inject/AnswerDataInjector/?type=data&q=2,3,4,5,6&pre=cate,ques,answ,comm&att=2&attCp=100&&txtCp=100
In which:
Param | Value | Description |
---|---|---|
type | [data | perm] | Type of injector. It can be data or perm means injecting data or permission respectively. |
q | number,number,etc | The number of items in each depth. For example, if the value is 2,3,4,5,6 then the injector will create 2 new categories with the depth level is '3', add 4 questions in each category, 5 answer and 6 comment in each question. Warning: Do not set the depth level to more than 5, because the number of items are calculated by number*depth. |
pre | string, string, etc | The prefix for items id in each depth. For example, if the value is "cate, ques, answ, comm", then the category has the first name/id called "cate", the question has the fist name/id called "ques", the answer has the fist id called "answ" and the comment has the first id called "comm". |
att | number | The number of attachments in one question. If the value is '0' or not set, no attachment is created. |
attCp | number | The capacity of one attachment. The value is evaluated in KByte and must be larger than KByte. |
txtcp | number | The capacity text of one item (question/answer/comment). The value is evaluated in KByte. If the value is 0 or not set, texts are created randomly. |
All number of item injectors are calculated by:
Categories: cats = numberCat * depth!
Questions : ques = cats * numberQue
Answers : anss = quest * numberAns
Comments : coms = quest * numberComs
All = cats + ques + anss + coms
For example:
q=2,3,4,5,6: All = 2 * 3! + (2 * 3) * 4) * 5 + ((2 * 3!) * 4) * 6 = 588 (items)
If you change the depth from '3' to '5', the number of items will be 11760.
To grant permission, the request link is in the following format:
http://[rest path]/bench/inject/AnswerDataInjector/?type=perm&q=2,3,4,5,6&pre=cate,ques,answ,comm&att=2&attCp=100&&txtCp=100&view=root,demo,*:/platform/user&edit=root,*:/platform/manager
In which:
Param | Value | Description | |
---|---|---|---|
view | string, string, etc | The list of granted permissions users/groups/memberships, if the value is "any" or not set, everyone can view all category create by prefix. | |
edit | string, string, etc | The list of granted permissions users/groups/memberships, if the value is "any" or not set, only user with highest permission (Administrator) can edit all category create by prefix. |
In the other way, such settings have been declared in "ksdemo.war/WEB-INF/conf/ksdemo/ks/bench-configuration.xml", therefore, to save time and effort, you can import it to "ksdemo.war/WEB-INF/conf/configuration.xml" and then modify it rather than create new one.
You can use RESTful service to request to inject or reject data. The format of request link is:
http://{domain}/{rest}/bench/{inject|reject}/{plug-inName}?[params]
For example, after registering the WikiDataInjector plug-in as above, you can request injection as follows: http://localhost:8080/rest-ksdemo/bench/inject/WikiDataInjector?mP=10&mA=100&mD=1&rand=false&wo=classic&wt=portal with 10 childrens of each page created, 100 kb each attachment, 1 depth level for wiki portal classic.
To reject such created data, request this link: http://localhost:8080/rest-ksdemo/bench/reject/WikiDataInjector.
Knowledge is a JCR-based product which uses JCR to store data. The root node of Knowledge is exo:application which includes these child nodes: exo:forumHome, exo:faqHome.
In this chapter, you will have opportunity to further understand about the JCR structure of Knowledge that consists of the following main sections:
Forum is a JCR-based application. The Forum data are saved in eXo-JCR under the Forum Service data directory. The whole JCR structure of Forum can be visualized in the diagram below:
The Forum System node is created from the node type exo:forumSystem. That is defined as a child node of Forum Service and can store nodes with these following node types: exo:banIP, exo:forumUserProfile, exo:statistic, exo:administration under the Forum System. The Forum System node is stored in /exo:applications/ForumService/ForumSystem
.
The User Profile and User Profile Home node are used to store information of each user. User Profile is automatically created by a listener when a user registers to the organization service. Private message and forum subscription can be added to User Profile as a child node. These node types exo:forumUserProfile, exo:userProfileHome, exo:privateMessage and exo:forumSubscription are defined as child nodes of exo:forumUserProfile. The User Profile node is stored under ForumSystem node: /exo:applications/ForumService/ForumSystem/exo:userProfileHome/exo:forumUserProfile
.
The node type exo:forumUserProfile has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:userId | String | false | The user id. |
exo:fullName | String | false | The user's full name. |
exo:firstName | String | false | The user's first name. |
exo:lastName | String | false | The user's last name. |
exo:email | String | false | The user's email address. |
exo:userTitle | String | false | The user's title: Administrator, Moderator or User. |
exo:screenName | String | false | The displayed name of user in Forum. |
exo:userRole | Long | false | The user's role. The value can be: "O": Administrator, "1": Moderator, "2": User, "3": guest. |
exo:signature | String | false | The signature displayed at the end of each user's post. |
exo:totalPost | Long | false | The total posts submitted by the user. |
exo:totalTopic | Long | false | The total topics started by the user. |
exo:jobWattingForModerator | Long | false | The number of jobs that are waiting to be moderated. |
exo:moderateForums | String | true | The list of forum ids that user is the moderator. |
exo:moderateCategory | String | true | The list of category ids that user is the moderator. |
exo:readTopic | String | true | The list of topics that user has read. |
exo:readForum | String | true | The list of forums that user has read. |
exo:lastReadPostOfTopic | String | true | The list of the last read posts id in a topic that user has read. |
exo:lastReadPostOfForum | String | true | The list of the last read posts id in a forum that user has read. |
exo:isAutoWatchMyTopics | Boolean | false | Enable/disable the auto-watch the topics created by user. Topics created by a user will be watched automatically if the value is set to "true". |
exo:isAutoWatchTopicIPost | Boolean | false | Enable/disable the auto-watch posts submitted by user. Topics posted by an user will be watched automatically if the value is set to "true". |
exo:bookmark | String | true | The list of topics/posts bookmarked by user. |
exo:lastLoginDate | Date | false | The date of the last login. |
exo:joinedDate | Date | false | The date when user joined forum. |
exo:lastPostDate | Date | false | The date of the last post. |
exo:isDisplaySignature | Boolean | false | User's signature will be displayed at the end of their post if the value is set to "true". |
exo:isDisplayAvatar | Boolean | false | User's avatar is displayed if the value is set to "true". |
exo:newMessage | Long | false | The number of new messages. |
exo:timeZone | Double | false | The time zone configured by user. |
exo:timeFormat | String | false | The time format configured by user: 12h or 24h format. |
exo:shortDateformat | String | false | The format of short date configured by user. Example: 'dd/MM/yyyy'. |
exo:longDateformat | String | false | The format of long date configured by user. Example: 'dd mmm, yyyy'. |
exo:maxPost | Long | false | The number of the maximum posts displayed per page. |
exo:maxTopic | Long | false | The number of the maximum topics displayed per page |
exo:isShowForumJump | Boolean | false | Display/hide the forum jump drop-down list. This jump list will be shown if the value is set to "true". |
exo:collapCategories | String | true | The list of categories collapsed by user. |
exo:isBanned | Boolean | false | The user's condition. User is currently banned if the value is set to "true". |
exo:banUntil | Long | false | The time when the ban period expires. |
exo:banReason | String | false | The description for the reason that user was banned. |
exo:banCounter | String | false | The number of bans that user has committed. |
exo:banReasonSummary | String | true | The list of ban reason summaries when a user is banned for more than one time. |
exo:createdDateBan | Date | false | The date when the ban period starts. |
The child node type exo:privateMessage has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:from | String | false | The user id of the sender. |
exo:sendTo | String | false | The user id of the receiver. |
exo:name | String | false | The private message subject. |
exo:message | String | false | The message contents. |
exo:type | String | false | The private message type: sent messages or received messages. |
exo:receivedDate | Date | false | The date when the private message was received. |
exo:isUnread | Boolean | false | The status of private message: read/unread. |
The child node type exo:forumSubscription has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:categoryIds | String | true | The ids of the subscribed categories. |
exo:forumIds | String | true | The ids of the subscribed forums. |
exo:topicIds | String | true | The ids of the subscribed topics. |
Statistic and Statistic Home are used to store statistic information of forum, such as number of posts, topics, users, active users. The node type is exo:forumStatistic, exo:statisticHome.
The Statistic node is stored under the Forum System node: /exo:applications/ForumService/ForumSystem/exo:statisticHome/exo:forumStatistic
and its node type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:postCount | Long | false | The total number of submitted posts in Forum. |
exo:topicCount | Long | false | The number of total created topics in Forum. |
exo:membersCount | Long | false | The number of the registered users. |
exo:newMembers | String | false | The id of the latest registered user. |
exo:mostUsersOnline | String | false | The highest number of the online users. |
exo:activeUsers | Long | false | The number of active users. |
The Ban IP and Ban IP Home node are used to store data about banned IP addresses. The node type exo:banIPHome contains the child node exo:IPHome.
The Ban IP node is stored under the Forum System node: /exo:applications/ForumService/ForumSystem/exo:banIPHome/exo:banIP
and its node type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:ips | String | true | The list of ip addresses of the banned users. |
Administration and Administration Home are used to store data for setting the layout, notification email format and censor jobs. The node type of the Administration Home node is exo:administrationHome and the its child node type is exo:administration. The Administration node is stored under the ForumSystem node /exo:applications/ForumService/ForumSystem/exo:administrationHome/exo:administration
and its node type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:forumSortBy | String | false | Sort forum by criteria: post count, topic count, lock status. |
exo:forumSortByType | String | false | Sort forum by ascending/descending type. |
exo:topicSortBy | String | false | Sort topic by criteria. |
exo:topicSortByType | String | false | Sort topic by ascending type or descending type. |
exo:censoredKeyword | String | false | The list of censored words. |
exo:headerSubject | String | false | The subject header. |
exo:enableHeaderSubject | Boolean | false | Enable/disable the subject header. The subject header is displayed if the value is set to "true". |
exo:notifyEmailContent | String | false | Define if the notification email will be sent when there is a new added topic/post. |
exo:notifyEmailMoved | String | false | Define if the notification email will be sent when there are any moved topic/post. |
The Forum Data node is created from the node type exo:forumData. The data nodes like category, forum, topic, post, tag, BBcode and topic type will be stored under the Forum Data node:/exo:applications/ForumService/ForumData
.
The Category node is used to store all categories of forum, this node is a child node of the Forum Data node and only Category node type can be added to the Category Home. The node type of the Category Home node is exo:categoryHome is stored in /exo:applications/ForumService/ForumData/CategoryHome
. The Category node has the node type exo:forumCategory which is a child node of the CategoryHome node. This node type is defined to allow adding child nodes as exo:forum and exo:forumRSS.
The node type exo:forumCategory has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The category id. |
exo:owner | String | false | The category creator. |
exo:path | String | false | The node path of the category. |
exo:createdDate | Date | false | The date when the category was created. |
exo:modifiedBy | String | false | The id of the user who made the last modification on the category. |
exo:name | String | false | The category name. |
exo:modifiedDate | Date | false | The date when the modifications on category were made. |
exo:description | String | false | The category description. |
exo:moderators | String | true | The list of moderators of the category. |
exo:tempModerators | String | true | The temporary moderator of the category. |
exo:createTopicRole | String | true | The topic role. |
exo:poster | String | true | The list of ids of the users and groups who can post in the category. |
exo:viewer | String | true | The list of ids of the users and groups who can only view posts in the category. |
exo:categoryOrder | Long | false | The order number of category in the category list. |
exo:userPrivate | String | true | The list of user ids whose access are restricted from the category. |
exo:forumCount | Long | false | The total number of forums in the category. |
The Forum node is defined as a child node of category and allowed adding child nodes as Topic and RSS type. The node type of Forum is exo:forum. The Forum node is stored in /exo:applications/ForumService/ForumData/CategoryHome/%Category-id%/%Forum-id%
and its node type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The forum id. |
exo:owner | String | false | The forum creator. |
exo:path | String | false | The node path of the forum. |
exo:name | String | false | The forum title. |
exo:forumOrder | Integer | false | The order number in the list of forums. Forum with smaller number will get higher order. |
exo:createdDate | Date | false | The date and time when the forum was created. |
exo:modifiedBy | String | false | The id of user who modified the category. |
exo:modifiedDate | Date | false | The time of modification, including date, time and time zone. |
exo:lastTopicPath | String | false | The id of the last topic in the forum. |
exo:description | String | false | The description of forum. |
exo:postCount | Long | false | The total number of submitted posts in the forum. |
exo:topicCount | Long | false | The total number of created topics in the forum. |
exo:isAutoAddEmailNotify | Boolean | false | Enable/disable the notification email to moderators. |
exo:notifyWhenAddTopic | String | true | Email addresses to notify when there is a new topic in the forum. |
exo:notifyWhenAddPost | String | true | Email addresses to notify when there is a new post in the forum. |
exo:isModerateTopic | Boolean | false | All new topic will be moderated if the value is set to "true". |
exo:isModeratePost | Boolean | false | All new posts will be moderated if the value is set to "true". |
exo:isClosed | Boolean | false | The forum status: closed/open. Forum is closed if the value is set to "true". |
exo:isLock | Boolean | false | The forum status: locked/unlocked. Forum is locked if the value is set to "true". |
exo:createTopicRole | String | true | The list of ids of the users or groups who can create topic in the forum. |
exo:poster | String | true | The list of ids of the users or groups who can submit post in the forum. |
exo:viewer | String | true | The list ids of the users or groups who can view posts in the forum. |
exo:moderators | String | true | The list of user ids who are the moderators of forum. |
exo:tempModerators | String | true | The list of user ids who are the temporary moderators. |
exo:banIPs | String | true | The list of banned IP addresses. |
The child node pruneSetting has the following perperties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | False | The forum id. |
exo:inActiveDay | Long | False | The number of days/weeks/months that the topics in forum have not been active. |
exo:periodTime | Long | False | The number of days/weeks/months that the prune job will be executed to check for the old topics and deactivate them. |
exo:isActive | Boolean | False | The current status of the prune job. If the value is set to "True", the prune job will be run. |
exo:lastRunDate | Date | False | The date that prune job runs for the last time. |
The Topic node is defined as a child node of the Forum node and allowed adding child nodes as Topic, Poll and RSS type. The node type of the Topic and Poll node is exo:topic, exo:poll.
The Topic node is stored in /exo:applications/ForumService/ForumData/CategoryHome/%Category-id%/%Forum-id%/%Topic-id%
and its node type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The topic id. |
exo:owner | String | false | The user id of the topic creator. |
exo:path | String | false | The node path of the topic. |
exo:name | String | false | The subject of the topic |
exo:createdDate | Date | false | The time when the topic was created. |
exo:modifiedBy | String | false | The id of the user who made the latest modification in the topic. |
exo:modifiedDate | Date | false | The date when the modifications were made. |
exo:lastPostBy | String | false | The user id of the last poster in topic. |
exo:lastPostDate | Date | false | The date when the last post was submitted. |
exo:description | String | false | The topic description. |
exo:topicType | String | false | The id of the topic type. |
exo:postCount | Long | false | The number of posts in the topic. |
exo:viewCount | Long | false | The number of topic views. |
exo:numberAttachments | Long | false | The number of attachments in the topic. |
exo:icon | String | false | The name of the topic icon. |
exo:link | String | false | The link to the topic. Example: http://localhost:8080/ksdemo/public/classic/forum/topic/%Topic-id%. |
exo:isModeratePost | Boolean | false | All posts in the topic will have to wait for moderation if the value is set to "true". |
exo:isNotifyWhenAddPost | Boolean | false | When there is a new post in a topic, a notification message will be sent to the topic owner if this value is set to "true". |
exo:isClosed | Boolean | false | The state of the topic: closed/open. If the value is set to "true", the topic is closed. |
exo:isLock | Boolean | false | The lock status of the topic: lock/unlocked. If the value is set to "true", the topic is locked. |
exo:isApproved | Boolean | false | The topic is approved to be published if the value is set to "true". |
exo:isSticky | Boolean | false | If the value is set to "true", the topic is currently sticky. |
exo:isWaiting | boolean | false | The topic status. The topic is waiting for moderation if the value is set to "true". |
exo:isActive | boolean | false | The topic activity status: active/inactive. The topic is active (topic gets new posts in a period of time) if the status is set to "true". |
exo:isActiveByForum | Boolean | false | The topic status based on the forum state. Example: When the topic is active and the forum that contains it is closed, this topic will be considered as inactive. |
exo:canView | String | true | List of user ids who can view the topic contents. |
exo:canPost | String | true | List of user ids who can post in the topic. |
exo:isPoll | Boolean | false | The topic contains poll if the value is set to "true". |
exo:userVoteRating | String | true | The list of user id who voted. |
exo:tagId | String | true | The list of the topic tag id. |
exo:voteRating | Double | false | The average vote score of the topic. |
The child node type exo:poll has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The poll id. |
exo:owner | String | false | The user id of poll creator. |
exo:createdDate | Date | false | The date and time when the poll was created. |
exo:modifiedBy | String | false | The user id who modified the poll. |
exo:modifiedDate | Date | false | The time when the poll is modified. |
exo:lastVote | Date | false | The date of the last vote. |
exo:question | String | false | The contents of the question for poll. |
exo:timeOut | Long | false | The time when the polled is closed. |
exo:option | String | true | The list of options for poll. |
exo:vote | String | true | The list of votes by users. |
exo:userVote | String | true | The list of user ids who voted. |
exo:isMultiCheck | Boolean | false | User can choose more than one option if the value is set to "true". |
exo:isAgainVote | Boolean | false | Users can change their vote if the value is set to "true". |
exo:isClosed | Boolean | false | The poll status. Poll is closed if the value is set to "true". |
The Post node is defined as child node of Topic and allowed adding only the Attachment child node type. The Post node type is exo:post, and the child node type is exo:forumAttachment.
The Post node is stored in /exo:applications/ForumService/ForumData/CategoryHome/%Category-id%/%Forum-id%/%Topic-id%/%Post-id%
and its node type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The post id. |
exo:owner | String | false | The user id of the poster. |
exo:path | String | false | The node path of the post. |
exo:createdDate | Date | false | The date time when post is submitted, including date, time, time zone. |
exo:modifiedBy | String | false | The id of the user who modified the post. |
exo:editReason | String | false | The reason for editing the post. |
exo:modifiedDate | Date | false | The date when the post was modified. |
exo:name | String | false | The post title. |
exo:message | String | false | The message of the post. |
exo:remoteAddr | String | false | The remote IP address of the post. |
exo:icon | String | false | The name of the icon for the post. |
exo:userPrivate | String | true | The list of user ids that are restricted from the post. |
exo:link | String | false | The link to open the topic. |
exo:isApproved | Boolean | false | The state of the post: approved/unapproved. The post is approved if the value is set to "true". |
exo:numberAttach | Long | false | The number of attachments in the post. |
exo:isActiveByTopic | Boolean | false | The post is activity status based on the topic state. If the topic is close, all post in it will be considered as inactive. |
exo:isHidden | Boolean | false | The post status: shown/hidden. The post is hidden if the value is set to "true". |
exo:isFirstPost | Boolean | false | The post is the first one in a topic if the value is set to "true". |
The Tag node is used to store data about tag name, topics with tag added, number of users using this tag, number of tags in use. The node type of the Tag node is exo:forumTag and its child node type is "exo:tagHome". The Tag node is stored in /exo:applications/ForumService/ForumData/TagHome/%tag-id%
and its node type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The id of tag. |
exo:name | String | false | The tag name. |
exo:useCount | Long | false | The number of times that the tag was used. |
exo:userTag | String | true | The number of users using the tag. |
The BBCode node is used to define what BBCode will be used in the forum. The node type of the BBCode node is exo:forumBBCode. The BBCode node is stored in /exo:applications/ForumService/ForumData/forumBBCode/%BBCode_tag%
and its node type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:description | String | false | The description about the tag purpose. Example: 'The [url] tag allows creating links to other websites and files'. |
exo:example | String | false | The example about using the tag. Example: [URL]http://www.exoplatform.com[/URL]'. |
exo:isActive | Boolean | false | The BBCode tag is active/deactive. The BBCode tag is active if the value is set to "true". |
exo:isOption | Boolean | false | If the value is set to "true", user can create a tag with atributes and values. |
exo:replacement | String | false | The HTML code that will be replaced by the tag. Example: [url] tag replaces '<a target='_blank' href="{param}">{param}</a>'. |
exo:tagName | String | false | The BBCode tag name. |
The Topic type home contains a child node with the node type exo:topicType. The Topic node is stored in /exo:applications/ForumService/ForumData/TopicTypeHome/%Topic-id%
and its node type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The id of the topic type. |
exo:name | String | false | The name of the topic type. |
exo:icon | String | false | The icon of the topic type. |
FAQ is a JCR-based application. The FAQ data are stored in the eXo-JCR under the faqApp data directory. The whole FAQ JCR structure can be visualized in the following diagram:
The system will automatically create the Category Home node under the FAQ application node at the first time the user launches application. All users-created categories are the sub-categories of Category Home. The home of the Category node is automatically created in /exo:applications/faqApp/categories
.
In fact, Sub-category is also a category. FAQ has defined a mixin node type called mix:faqSubCategory to allow adding a node having the same type with category to an existing category. When a category is created, this mixin node type will be mixed to that category.
The node type exo:faqCategory has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The sub-category id. |
exo:name | String | false | The name of the sub-category. |
exo:userPrivate | String | true | The list of user ids that are restricted from the category. |
exo:description | String | false | The description of the sub-category. |
exo:isModerateQuestions | Boolean | false | The question post moderation status. All questions posted in the sub-category will have wait for moderation if the value is set to "true". |
exo:isModerateAnswers | Boolean | false | The answer post moderation status. All answers posted in the sub-category will have to wait for moderation if the value is set to "true". |
exo:isView | Boolean | false | The category is shown/hidden. The category will be shown if the value is set to "true". |
exo:viewAuthorInfor | Boolean | false | The category enables user to view the information of questions poster if the value is set to "true'. |
exo:moderators | String | true | The list of user ids who are the category moderator. |
exo:createdDate | Date | false | The time when the sub-category is created. |
exo:index | Long | false | The index number of the category. |
Each category has a RSS child node that stores a RSS feed representing all questions in this category as the binary data type. The RSS node is stored in /exo:applications/faqApp/categories/ks.rss
and its node type is exo:faqRSS.
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:content | Binary | false | The content of the RSS. |
The Question Home node is created from the exo:faqQuestionHome node type that is defined as a child node of category. This node cantains all question nodes that created in side a category. Only the Question node type exo:faqQuestion can be added to the question Home. The Question Home node is created as a child node of Categories /exo:applications/faqApp/categories/questions
.
Question node is created from exo:faqQuestion node type under the Question Home node. The Answers, Comments and Attachments node are defined as child nodes of the Question node. The Question node is created under the Question Home: /exo:applications/faqApp/categories/questions/%Question-id%
.
The exo:faqQuestion node type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The question id. |
exo:language | String | false | The language of the question. |
exo:name | String | false | The question details. |
exo:title | String | false | The question title. |
exo:author | String | false | The the user id of the question poster. |
exo:email | String | false | The email of the question author |
exo:isActivated | Boolean | false | The question status: activated/inactivated. The question is activated if the value is set to "true". |
exo:isApproved | Boolean | false | The state of the question: approved/unapproved. The question is approved to be published if the value is set to "true". |
exo:categoryId | String | false | The id of the category containing the question. |
exo:createdDate | Date | false | The date and time when the question was submitted. |
exo:relatives | String | true | The list of the related questions ids. |
exo:usersVote | String | true | The list of user ids who voted. |
exo:markVote | Double | false | The average vote scores of the question. |
exo:topicIdDiscuss | String | false | The topic id in the forum where the question is discussed. |
exo:nameAttachs | String | true | The file name of attachments in the question. |
exo:lastActivity | String | false | The user id and time when the last activity of the question was made. |
exo:numberOfPublicAnswers | Long | false | The number of all posted answers that has been published. |
exo:link | String | false | The link to open the question. |
exo:responses | String | true | The responses of the question. |
exo:dateResponse | Date | true | The date when the question received the answer. |
exo:responseBy | String | true | The user id of the answer poster. |
A question can support multilanguages, all other languages are stored as a child node of the question and can be add to the question via a mixin node type called mix:faqi18n. After the mixin node type mix:faqi18n is added to the question, the node type exo:questionLanguageHome can be added to the question node and this node type will contain all languages node with the node type exo:faqLanguage. All display properties of the question are defined in the node type exo:faqLanguage.
The node type exo:faqLanguage has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:language | String | false | The language of the question. |
exo:name | String | false | The name of the language. |
exo:title | String | false | The title of the question in the selected language. |
exo:questionId | String | false | The id of the question. |
exo:categoryId | String | false | The id of the category. |
The Answer, Comment and Attachment node is defined as the child nodes of the Question node. Attachment node is defined as a nt:file node type and stored right under the Question node. Answers and comments node are stored under the Answer home and the Comment home node.
The Answer node is stored in /exo:applications/faqApp/categories/questions/%Question-id%/faqAnswerHome/%Answer-id%
and its node type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The id of the answer. |
exo:answerPath | String | false | The path to the answer. |
exo:questionId | String | false | The id of the question. |
exo:categoryId | String | false | The id of the category containing the question. |
exo:responses | String | false | The content of the answer. |
exo:dateResponse | Date | false | The date when the response was posted. |
exo:responseBy | String | false | The id of the user who responded the answer. |
exo:responseLanguage | String | false | The language of the answer response. |
exo:approveResponses | Boolean | false | The response is pending for approval if the value is set to "false". |
exo:activateResponses | Boolean | false | The state of the answer: activated/deactivated . |
exo:usersVoteAnswer | String | true | The list of user ids who voted for the answer. |
exo:MarkVotes | Long | false | The average vote scores of the answer. |
exo:postId | String | false | The post id. |
exo:fullName | String | false | The answer author's full name. |
The Comment node is stored in /exo:applications/faqApp/categories/questions/%Question-id%/faqCommentHome/%Comment-id%
and its node type has the following propeties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The comment id. |
exo:comments | String | false | The comment contents. |
exo:dateComment | Date | false | The date when the comment is posted. |
exo:commentBy | String | false | The user id of the comment poster. |
exo:postId | String | false | The id of the post. |
exo:fullName | String | false | The full name of the comment poster. |
exo:categoryId | String | false | The id of the category in which the comment is posted. |
exo:questionId | String | false | The id of the question in which the comment is posted. |
exo:commentLanguage | String | false | The language of the comment. |
The Attachment node is stored in /exo:applications/faqApp/categories/questions/%Question-id%/faqAttachment
and its node type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:fileName | String | false | The name of the attachment file. |
This FAQ Setting node stores the user settings data, such as how answer is ordered (in alphabetical order or by created date), the order type (descending or ascending) or the user's selection to sort questions by popularity. Each user has a dedicated settings data to select the display preferences in FAQ . The default setting will be used if the users has never changed and saved their setting.
The User Setting node of an individual user is stored in /exo:applications/faqApp/settingHome/userSettingHome/%user-id%
and has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:ordeBy | string | false | Define how questions are ordered, by "alphabet/index" or "created date". |
exo:ordeType | string | false | The value "asc" = ascending and "des" = descending. |
exo:sortQuestionByVote | Boolean | false | All questions will be sorted by the popularity (based on the number of votes) if the value is set to "true". |
The Poll data are saved in eXo-JCR under the eXoPolls data directory. The whole JCR structure of Poll can be visualized in the diagram below:
The Poll node is used to store the default data in a poll. The node type of the Poll node is exo:poll. The Poll node is stored under eXoPolls node /exo:applications/eXoPolls/%PortalName%/Polls/Poll-id%
and its node type (exo:polls) has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
exo:id | String | false | The poll id. |
exo:owner | String | false | The user id of the poll creator. |
exo:createdDate | Date | false | The date and time when the poll is created. |
exo:modifiedBy | String | false | The id of the user who made the last modification on the poll. |
exo:modifiedDate | Date | false | The date and time when the latest modification on poll was made. |
exo:lastVote | Date | false | The date and time when the last vote was made. |
exo:question | String | false | The question content of poll. |
exo:timeOut | Long | false | The time when the poll will be closed. |
exo:option | String | true | The list of options for poll. Each option is separated by a comma. |
exo:vote | String | true | The list of votes by users. |
exo:userVote | String | true | The list of user ids who voted. |
exo:isMultiCheck | Boolean | false | Enable/disable the multi check. User can vote for more than one option if the value is set to "true". |
exo:isAgainVote | Boolean | false | Enable/disable the option to vote again. User can change their vote if the value is set to "true". |
exo:isClosed | Boolean | false | The poll status: open/closed. The poll is closed if the value is set to "true". |
The Wiki portlet is a JCR-based application. The Wiki data are stored in the eXo JCR storage. The Wiki application of eXo Knowledge supports several wikis, each wiki is organized as a tree of pages and hosted in different locations, depending on the type of wiki:
Portal wikis: /exo:applications/eXoWiki/wikis/$PORTAL/WikiHome
Group wikis: /Groups/$GROUP/ApplicationData/eXoWiki/WikiHome
User wikis: /Users/$USERNAME/ApplicationData/eXoWiki/WikiHome
WikiHome a conventional name of the root page of a Wiki. The type of WikiHome is "exo:wikihome". Each page may have a number of sub-pages and attachments.
Other Wiki metadata are organized below /exo:applications/eXoWiki/wikimetadata.
The whole Wiki JCR structure can be visualized in the following diagram:
Depending on the Wiki type (portal, group or user); its pages, attachments and default syntax are stored under a node with either of node types: "wiki:portalwiki", "wiki:groupwiki" or "wiki:userwiki", respectively. Such a node has four child nodes: WikiHome, Preferences, LinkRegistry and Trash. These node types have the super type "wiki:wiki" that has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
ref | Reference | false | The reference to one of three following nodes: portalwikis, groupwikis or userwikis. |
owner | String | false | The name of the wiki. |
wikiPermissions | String | true | The property consists of the permission information of the wiki. The permission string has the format: VIEWPAGE,EDITPAGE,ADMINPAGE,ADMINSPACE:USER:john; VIEWPAGE:GROUP:/platform/users; VIEWPAGE,EDITPAGE,ADMINPAGE,ADMINSPACE:MEMBERSHIP:manager:/platform/administrators. |
isDefaultPermissionsInited | Boolean | true | Check whether the default permission is applied to all the wiki tree or not. Its default value is "false". |
The WikiHome node stores the root page of a Wiki. It has the node type "exo:wikihome" that has the super type "wiki:page" inherited from "nt:folder". The super type has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
owner | String | false | The creator of the page. |
author | String | false | The last person who modifies the page. |
createdDate | Date | false | The date when the page is created. |
updatedDate | Date | false | The last date when the page is updated. |
syntax | String | false | The Wiki syntax is used to write the page. |
title | String | false | The title of the page. |
comment | String | false | The comment explains what is modified in the page. |
url | String | false | The URL to the page. |
isOverridePermission | Boolean | false | Check whether the default permission is overridden on the page or not. Its default value is "false". |
exo:relation | Reference | true | The property consists of the UUIDs of the related pages. |
The nodes that have the type "wiki:page", have a child node named "content" and other child nodes including attachments with the type "wiki:attachment" inherited from "nt:file". The node type "wiki:attachment" has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
title | String | false | The name of the attachment. |
fileType | String | false | The type of the attachment. |
creator | String | false | The creator of the attachment. |
Three mixin node types: "wiki:removed", "wiki:renamed" and "wiki:watched" may be added to the node type "wiki:page".
The mixin node type "wiki:removed" has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
removedBy | String | false | The person who deleted the page. |
removedDate | Date | false | The date when the page is deleted. |
parentPath | String | false | The path to the parent page of the deleted page. |
The mixin node type "wiki:renamed" has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
oldPageIds | String | true | The old Ids of the renamed page. |
The mixin node type "wiki:watched" has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
watcher | String | false | The Id of the person who is watching the page. |
The "Preferences" node stores the default syntax and page templates of the Wiki. It has the node type "wiki:preferences" and two child nodes "PreferencesSyntax" and "TemplateContainer".
The "PreferencesSyntax" node has the node type "wiki:preferencessyntax" that has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
defaultSyntax | String | false | The default Wiki syntax of each wiki. |
allowMutipleSyntaxes | Boolean | false | Specify whether multiple syntaxes are enabled or not. |
The "TemplateContainer" node stores the page templates. Its child node has the node type "wiki:template" inherited from the node type "wiki:page".
The node type "wiki:template" has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
description | String | false | The description of the template. |
The "LinkRegistry" node stores the entries to keep track of renaming or moving pages. Each link entry has the node type "wiki:linkentry" that has the following properties:
Properties name | Required type | Multiple | Description |
---|---|---|---|
alias | String | false | The Id of a page that is moved or renamed. Its format is "wikitype@wikiowner@pagename". |
newlink | Path | false | A new path to the wiki page that has been moved or renamed. |
Wiki metadata are stored in the node wikimetadata that has the node type "wiki:store". These metadata consist of information about help contents, draft contents and the way to find the wikis in the system. The nodes portalwikis, groupwikis and userwikis allow finding the wikis under the type: portal, group and user, basing on the JCR reference features. These nodes have the node types "wiki:portalwikis", "wiki:groupwikis" and "wiki:userwikis" relatively.
Help pages
Help-related information about Wiki syntaxes are stored under the "helppages" node which has the node type "wiki:page". For syntax help, there are two help pages (summary and detailed) for each syntax. The summary page suggests the simple syntax, while the detailed page provides the full syntax-related information. The detailed page is arranged as the child page of the summary page, and both of which have the same node type "wiki:page".
Draft pages
The unsaved content of a new page is stored under the "draftNewPages" node that has the node type "wiki:page".
This chapter provides you with the basic knowledge of overridden components, internal APIs implemented in Knowledge. Also, you will know how to set up a default template for the FAQ portlet, and how to create a sample action extension in Wiki.
In this chapter, there are the following main topics:
There are some extension points in eXo Knowledge, so that you can control how these components work by implementing or extending default implementations, then reconfigure these new components in the configuration.xml file.
ForumEventLifeCycle
enables you to listen to the lifecycle of a forum. By implementing ForumEventLifeCycle, you can be notified of new posts and replies, categories and topics. This installation will be injected when the data flow is called to save data.
You can find the configuration file of this component at: ext/social-integration/src/main/resources/conf/portal/configuration.xml.
For example, to add a Forum to a space of the Social application and keep new activities of Forum (such as new posts and topics) updated to the activities of space, do as follows:
<external-component-plugins>
<target-component>org.exoplatform.forum.service.ForumService</target-component>
<component-plugin>
<name>ForumEventListener</name>
<set-method>addListenerPlugin</set-method>
<type>org.exoplatform.ks.ext.impl.ForumSpaceActivityPublisher</type>
</component-plugin>
</external-component-plugins>
To use ForumEventLifeCycle class, do the following steps:
1. Create a new class that extends ForumEventListener.
For example: class ABCActivityPublisher
public class ABCActivityPublisher extends ForumEventListener {
..............
}
2. Override fuctions in this created class. In each function, you can write anythings to meet your needs.
public class ABCActivityPublisher extends ForumEventListener {
public void saveCategory(Category category){
....
}
public void saveForum(Forum forum){
....
}
public void addTopic(Topic topic, String categoryId, String forumId)){
....
}
public void updateTopic(Topic topic, String categoryId, String forumId){
....
}
public void addPost(Post post, String categoryId, String forumId, String topicId){
....
}
public void updatePost(Post post, String categoryId, String forumId, String topicId){
....
}
}
The function saveCategory is called when a category is added and/or edited.
The function saveForum is called when a forum is added and/or edited.
The function addTopic is called when a topic is added.
The function updateTopic is called when a topic is updated.
The function addPost is called when a post is added.
The function updatePost is called when a post is updated.
3. Add a new configuration to the configuration.xml file with the type that is the class created in the Step 1.
<external-component-plugins>
<target-component>org.exoplatform.forum.service.ForumService</target-component>
<component-plugin>
<name>ForumEventListener</name>
<set-method>addListenerPlugin</set-method>
<type>{package}.{class name}</type>
<!-- example
<type>org.exoplatform.ks.ext.impl.ABCActivityPublisher</type>
-->
</component-plugin>
</external-component-plugins>
AnswerEventLifeCycle
installs event updates for the Answers data that is injected while saving answers, saving questions or posting comments.
You can find the configuration file of this component at:_ext/social-integration/src/main/resources/conf/portal/configuration.xml_.
For example, to add Answers to a space of the Social application and keep new activities of Answers updated to the activities of space, do as follows:
<external-component-plugins>
<target-component>org.exoplatform.faq.service.FAQService</target-component>
<component-plugin>
<name>AnswerEventListener</name>
<set-method>addListenerPlugin</set-method>
<type>org.exoplatform.ks.ext.impl.AnswersSpaceActivityPublisher</type>
</component-plugin>
</external-component-plugins>
In which, AnswersSpaceActivityPublisher
is the class to implement ForumEventLifeCycle
.
To use the AnswerEventLifeCycle class, do the following steps:
1. Create a new class that extends AnswerEventListener.
For example: ABCActivityPublisher
public class ABCActivityPublisher extends AnswerEventListener {
....
}
2. Override fuctions in this created class. In each function, you can write anything to meet your needs.
public class ABCActivityPublisher extends AnswerEventListener {
public void saveQuestion(Question question, boolean isNew){
....
}
public void saveAnswer(String questionId, Answer answer, boolean isNew){
....
}
public void saveAnswer(String questionId, Answer[] answers, boolean isNew){
....
}
public void saveComment(String questionId, Comment comment, boolean isNew){
....
}
}
The function saveQuestion is called when a question is added and/or edited.
The function saveAnswer is called when an answer is added and/or edited.
The function saveAnswer is called when answers are added and/or edited.
The function saveComment is called when a comment is added and/or edited.
3. Add a new configuration to the configuration.xml file with the type that is the class created in the Step 1.
<external-component-plugins>
<target-component>org.exoplatform.faq.service.FAQService</target-component>
<component-plugin>
<name>AnswerEventListener</name>
<set-method>addListenerPlugin</set-method>
<type>{package}.{class name}</type>
<!-- example
<type>org.exoplatform.ks.ext.impl.ABCActivityPublisher</type>
-->
</component-plugin>
</external-component-plugins>
BBCodeRenderer
is used in the core of eXo Knowledge to render BBCodes. In which, the data input is text, containing BBCode tags. The data output will be BBCode tags which have been encrypted into HTML tags.
You can find the configuration file of this component at: extension/webapp/src/main/webapp/WEB-INF/ks-extension/ks/forum/bbcodes-configuration.xml.
For example, to register BBCodeRenderer, do as follows:
<external-component-plugins>
<target-component>org.exoplatform.ks.rendering.MarkupRenderingService</target-component>
<component-plugin>
<name>BBCodeRenderer</name>
<set-method>registerRenderer</set-method>
<type>org.exoplatform.ks.rendering.spi.RendererPlugin</type>
<description>BBCode renderer</description>
<init-params>
<object-param>
<name>renderer</name>
<description>Extended BBCodeRenderer</description>
<object type="org.exoplatform.ks.bbcode.core.BBCodeRenderer">
<field name="bbCodeProvider">
<object type="org.exoplatform.ks.bbcode.core.ExtendedBBCodeProvider"/>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which, ExtendedBBCodeProvider
is the class to implement BBCodeProvider
.
Applications of eXo Knowledge, such as Forum, Answers and Polls, use REST services to communicate with the server. This section describes REST Services of internal APIs.
The Forum application of eXo Knowledge uses the ForumWebservice to provide all APIs to work with Forum, such as filtering IPs, viewing RSS, and more.
Service name | Service URL | Description | Location |
---|---|---|---|
ForumWebservice | $portalName/ $restcontextname/ ks/forum/ | Call extended services of the Forum application. |
* Maven groupId: org.exoplatform.ks * ArtifactId: exo.ks.web.webservice |
APIs Usage
Use the following APIs to build all the functions of the Forum application:
Name | Description | Service URL endpoint | Parameters | Expected values |
---|---|---|---|---|
getMessage | Get all new posts with the number based on the maxcount value. | $portalName/ $restcontextname/ ks/forum/getmessage/ | String maxcount | integer |
filterIps | Ban IPs with no access to Forum. | $portalName/ $restcontextname/ ks/forum/filter/ | String str | String in the IP format. |
filterIpBanForum | Ban IPs with no access to a specific Forum. | $portalName/ $restcontextname/ ks/forum/ filterIpBanforum/ |
String forumId String str | string in the IP format, string in the Forum format |
filterTagNameForum | Do the quick search for tags that returns the list of tags. | $portalName/ $restcontextname/ ks/forum/ filterTagNameForum/ |
String str String userAndTopicId |
Tag name id of user and topic |
viewrss | Process the request by users when they want to view RSS. | $portalName/ $restcontextname/ ks/forum/rss/ | String resourceid |
category id forum id topic id |
userrss | Process the request by users when they want to view their own collected RSS. | $portalName /$restcontextname/ ks/forum/rss/user/ | String resourceid | username id |
The Answers application of eXo Knowledge uses the FAQWebservice to view RSS.
Service name | Service URL | Description | Location |
---|---|---|---|
FAQWebservice | $portalName/ $restcontextname/ ks/faq | Call the extended services of the Answers application. |
* Maven groupId: org.exoplatform.ks * ArtifactId: exo.ks.eXoApplication. faq.service |
APIs Usage
Use the following APIs to build all the functions of Answers application:
Name | Description | Service URL endpoint | Parameters | Expected values |
---|---|---|---|---|
viewrss | View RSS | $portalName/ $restcontextname/ ks/faq/rss/ | String resourceid | category id, question id |
The Polls application of eXo Knowledge uses the PollWebservice to create and interact with the Polls gadget.
Service name | Service URL | Description | Location |
---|---|---|---|
PollWebservice | $portalName/ $restcontextname/ private/ks/poll | Call extended services of the Polls application. |
* Maven groupId: org.exoplatform.ks * ArtifactId: exo.ks.eXoApplication. poll.service |
APIs Usage
Use the following APIs to build all functions of the Answers application:
Name | Description | Service URL endpoint | Parameters | Expected values |
---|---|---|---|---|
viewPoll | Return data of the Polls system | $portalName/ $restcontextname/ private/ks/poll/ viewpoll/ | String pollId | id of poll |
votePoll | Update data for the Polls with the returned id | $portalName/ $restcontextname/ private/ks/poll /votepoll/ |
String pollId String indexVote |
id of poll integer |
Configuration plug-in is used to automatically set up a default template for the FAQ portlet. When the FAQ service starts, it will get values which are returned from the TemplatePlugin component to initialize the template for the FAQ portlet.
The template configuration plug-in is configured in the templates-configuration.xml file.
In details:
At runtime of the FAQ Service, FAQService component is called, then templates-configuration.xml file is executed. The component-plugin named addTemplatePlugin will be referred to org.exoplatform.faq.service.TemplatePlugin- to execute some objects and create default data for the Forum application.
<external-component-plugins>
<target-component>org.exoplatform.faq.service.FAQService</target-component>
<component-plugin>
<name>faq.default.template</name>
<set-method>addTemplatePlugin</set-method>
<type>org.exoplatform.faq.service.TemplatePlugin</type>
<init-params>
<value-param>
<name>viewerTemplate</name>
<value>war:/ks-extension/ks/faq/templates/FAQViewerPortlet.gtmpl</value>
</value-param>
</init-params>
</component-plugin>
</external-component-plugins>
The properties of template configuration plug-in are defined in the init-params tag as follows:
<init-params>
<value-param>
<name>viewerTemplate</name>
<value>war:/ks-extension/ks/faq/templates/FAQViewerPortlet.gtmpl</value>
</value-param>
</init-params>
Name | Description | Value |
---|---|---|
viewerTemplate | Path of file template. | war:/ks-extension/ks/faq/templates/ FAQViewerPortlet.gtmpl |
You can change the template FAQ viewer in one of the following two ways:
1. Create a file named FAQViewerPortlet.gtmpl . The content of the file is the template of the FAQ viewer.
2. Copy this file and paste into ks-extension/WEB-INF/ks-extension/ks/faq/templates/ that is in the webapps folder of the server (tomcat, jboss).
When the server runs, FAQViewerPortlet.gtmpl will initialize the template of the FAQ viewer.
1. Run the server and open the FAQ Portlet.
2. Go to edit mode and open the Edit Template tab.
3. Edit the content of text-area-input and click Save.
UIViewer is the child of the component UIFAQPortlet. It shows the main content of FAQ portlet.
List of APIs:
Function name | Param | Return | Description |
---|---|---|---|
getCategoryInfo | Empty | CategoryInfo object | Get the object CategoryInfo |
arrangeList |
(List< String > list) : List of path | A new list is arranged | Arrange a list of path. |
render | (String) : The content of answers or comments | A new string is converted by function render | Render the content of answers or comments. |
...
private String id;
private String path;
private String name;
private List<String> pathName;
private List<QuestionInfo> questionInfos = new ArrayList<QuestionInfo>();
private List<SubCategoryInfo> subCateInfos = new ArrayList<SubCategoryInfo>();
...
Param | Type | Description |
---|---|---|
id |
String
| The jcr node name of the category node. |
path |
String
| The jcr node path of the category node. |
name |
String
| The name of the category. |
pathName |
List<String>
| The path to the category includes a list of category names. |
questionInfos |
List<QuestionInfo>
| The list of QuestionInfo object. |
subCateInfos |
List<SubCategoryInfo>
| The list of SubCategoryInfo object. |
The QuestionInfo class:
...
private String id;
private String question;
private String detail;
private List<String> answers = new ArrayList<String>();
...
Param | Type | Description |
---|---|---|
id | String | The jcr node name of the question node. |
question | String
| The content of the question. |
details | String | Details of the question. |
answers | List<String> | The list of answers for the question. |
The SubCategoryInfo class:
The params of this class are the same as those of the CategoryInfo class. See here for more information.
This section describes how to create a sample action extension in Wiki.
The toolbar in Wiki is built basing on the UI Extension Framework, so you can add your own actions packaged in external jars to it.
After reading this section, you can add your own actions to the Wiki toolbar. In the following example, you are going to add a new action on the Wiki toolbar to view the Wiki markup of a page.
Create a Maven project which has the following directory structure:
Navigating in the project's folder, you will see the following structure:
pom.xml: the project's POM file.
src/main/java/.../ViewSourceActionComponent.java: a simple action supporting user to view the wiki markup of a page.
src/main/resources/conf/portal/configuration.xml: the configuration file to register your actions with the org.exoplatform.webui.ext.UIExtensionManager service.
Here is the content of the pom.xml file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.acme</groupId>
<artifactId>example</artifactId>
<version>1.0-SNAPSHOT</version>
<name>eXo Wiki action - Example</name>
<description>eXo Wiki action - Example</description>
<dependencies>
<dependency>
<groupId>org.exoplatform.portal</groupId>
<artifactId>exo.portal.webui.core</artifactId>
<version>3.2.0-PLF-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.commons</groupId>
<artifactId>exo.platform.commons.webui.ext</artifactId>
<version>1.1.3-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.ks</groupId>
<artifactId>exo.ks.eXoApplication.wiki.service</artifactId>
<version>2.2.4-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.ks</groupId>
<artifactId>exo.ks.eXoApplication.wiki.webapp</artifactId>
<version>2.2.4-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Edit the ViewSourceActionComponent class as below:
package com.acme;
import java.util.Arrays;
import java.util.List;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.ext.filter.UIExtensionFilter;
import org.exoplatform.webui.ext.filter.UIExtensionFilters;
import org.exoplatform.wiki.commons.Utils;
import org.exoplatform.wiki.mow.core.api.wiki.PageImpl;
import org.exoplatform.wiki.webui.UIWikiContentDisplay;
import org.exoplatform.wiki.webui.UIWikiPageContentArea;
import org.exoplatform.wiki.webui.UIWikiPortlet;
import org.exoplatform.wiki.webui.control.action.core.AbstractEventActionComponent;
import org.exoplatform.wiki.webui.control.filter.IsViewModeFilter;
import org.exoplatform.wiki.webui.control.listener.MoreContainerActionListener;
@ComponentConfig (
template = "app:/templates/wiki/webui/control/action/AbstractActionComponent.gtmpl",
events = {
@EventConfig(listeners = ViewSourceActionComponent.ViewSourceActionListener.class)
}
)
public class ViewSourceActionComponent extends AbstractEventActionComponent {
public static final String ACTION = "ViewSource";
private static final List<UIExtensionFilter> FILTERS = Arrays.asList(new UIExtensionFilter[] { new IsViewModeFilter() });
@UIExtensionFilters
public List<UIExtensionFilter> getFilters() {
return FILTERS;
}
@Override
public String getActionName() {
return ACTION;
}
@Override
public boolean isAnchor() {
return false;
}
public static class ViewSourceActionListener extends MoreContainerActionListener<ViewSourceActionComponent> {
@Override
protected void processEvent(Event<ViewSourceActionComponent> event) throws Exception {
UIWikiPortlet wikiPortlet = event.getSource().getAncestorOfType(UIWikiPortlet.class);
UIWikiContentDisplay contentDisplay = wikiPortlet.findFirstComponentOfType(UIWikiPageContentArea.class)
.getChildById(UIWikiPageContentArea.VIEW_DISPLAY);
PageImpl wikipage = (PageImpl) Utils.getCurrentWikiPage();
contentDisplay.setHtmlOutput(wikipage.getContent().getText());
event.getRequestContext().addUIComponentToUpdateByAjax(contentDisplay);
}
}
}
Edit the configuration.xml file as below:
<configuration xmlns="http://www.exoplatform.org/xml/ns/kernel_1_2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplatform.org/xml/ns/kernel_1_2.xsd http://www.exoplatform.org/xml/ns/kernel_1_2.xsd">
<external-component-plugins>
<target-component>org.exoplatform.webui.ext.UIExtensionManager</target-component>
<component-plugin>
<name>add.action</name>
<set-method>registerUIExtensionPlugin</set-method>
<type>org.exoplatform.webui.ext.UIExtensionPlugin</type>
<init-params>
<object-param>
<name>ViewSource</name>
<object type="org.exoplatform.webui.ext.UIExtension">
<field name="type"><string>org.exoplatform.wiki.webui.control.MoreExtensionContainer</string></field>
<field name="rank"><int>1000</int></field>
<field name="name"><string>ViewSource</string></field>
<field name="component"><string>com.acme.ViewSourceActionComponent</string></field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
</configuration>
Besides the MoreExtensionContainer type, action extension may be one of these following types:
Type | Description |
---|---|
org.exoplatform.wiki.webui.control.UIPageToolBar | Actions will be placed on the Wiki page toolbar at the view mode. |
org.exoplatform.wiki.webui.control.AddExtensionContainer | Actions will be placed on the Add Page drop-down list on the Wiki page toolbar at the view mode. |
org.exoplatform.wiki.webui.control.MoreExtensionContainer | Actions will be placed on the More drop-down list on the Wiki page toolbar at the view mode. |
org.exoplatform.wiki.webui.control.UISubmitToolBar | Actions will be placed on the Wiki page toolbar at the edit mode. |
org.exoplatform.wiki.webui.control.UIEditorTabs | Actions will be placed the on Wiki editor tabs. |
org.exoplatform.wiki.webui.control.BrowseExtensionContainer | Actions will be placed on the Browse drop-down list at the view mode. |
org.exoplatform.wiki.webui.popup.UIWikiSettingContainer | Actions will be placed on the Wiki setting tabs. |
Follow these steps to deploy your new action extension:
1. Build the project by using the mvn clean install command.
2. Copy the target/example-1.0-SNAPSHOT.jar file into the TOMCATHOME/webapps/wiki.war/WEB-INF/lib/ directory.
3. Run the tomcat and go to Wiki application, you should see the result as below:
This chapter provides you a comprehensive view about applications in Social, including:
These applications are packaged as Web application archives (WARs).
All the portlets are in the social-portlet.war file.
Portlet name | Description |
---|---|
Members Portlet | Enable users to search for Space members or list Space members in the alphabetical order. |
My Spaces Portlet | Display the spaces that user is member or manager. |
Space Activity Stream Portlet | Share Spaces activities. |
Invitations Portlet | List all people that invite users. |
Requests Portlet | List all invitations requested by users. |
Invitation Spaces Portlet | Display the spaces that user is invited. |
Pending Spaces Portlet | Display the Space requests to join page. |
Public Spaces Portlet | Display the Public Spaces page. |
User Activity Stream Portlet | Update and share the user's activities and/or status. |
People Portlet | Display the People page. |
Connections Portlet | Display the Connections page. |
User Profile Portlet | Display the User profile page. |
All Social gadgets are in opensocial.war.
Description: Manage activities of users: update status, like/unlike activities, comment activities, delete activities and delete comments.
Used REST services: ActivitiesRestServices.
Description: Fetch, parse and display RSS from a specific URL.
Description of user preferences: There are 2 preference fields: URL input box (default value is http://blog.exoplatform.org/feed/) and Number of RSS per page selector (default value is 10).
Used REST services: N/A.
Description: Get and display information of the current viewer and his connections.
Description of user preferences: The number of connections displayed per page. It is set to '5' by default.
Used REST services: N/A.
This chapter describes about configurations used in Social. It consists of the following main sections:
The service is used for spaces management, including creating spaces, and installing applications.
Sample configuration:
<component>
<key>org.exoplatform.social.core.space.spi.SpaceService</key>
<type>org.exoplatform.social.core.space.impl.SpaceServiceImpl</type>
<!--Deprecated, Use external-component-plugins instead
<init-params>
<values-param>
<name>space.homeNodeApp</name>
<value>SpaceActivityStreamPortlet</value>
</values-param>
<values-param>
<name>space.apps</name>
<value>DashboardPortlet:true</value>
<value>SpaceSettingPortlet:false</value>
<value>MembersPortlet:true</value>
</values-param>
</init-params>
-->
</component>
Init-params:
Name | Type | Value | Description |
---|---|---|---|
space.homeNodeApp | String | SpaceActivityStreamPortlet | The home application for a space. |
space.apps | String list | DashboardPortlet:true , SpaceSettingPortlet:false , MembersPortlet:true | The applications that are used for initializing the application when the space is created. |
Deprecated: Use external-component-plugins instead: org.exoplatform.social.core.space.SpaceApplicationConfigPlugin.
This component is used to process the callable request out of the HTTP request.
Sample configuration:
<component>
<key>org.exoplatform.social.common.lifecycle.LifeCycleCompletionService</key>
<type>org.exoplatform.social.common.lifecycle.LifeCycleCompletionService</type>
<init-params>
<value-param>
<name>thread-number</name>
<value>10</value>
</value-param>
<value-param>
<name>async-execution</name>
<value>false</value>
</value-param>
</init-params>
</component>
Init-params:
Name | Type | Value | Description |
---|---|---|---|
thread-number | integer | 10 | The maximum number of threads parallel executed. |
async-execution | boolean | false
| Specify the running mode of service is synchronous or asynchronous. |
Name | Type | Value | Description |
---|---|---|---|
providers | String | org.exoplatform.social.core.identity.provider.SpaceIdentityProvider | The identity providers. |
The service is to handle all events related to creating and managing all the application spaces.
This plugin is used to set the portal container name used for REST service.
Sample configuration:
<component>
<key>org.exoplatform.social.opensocial.auth.RestPortalContainerNameConfig</key>
<type>org.exoplatform.social.opensocial.auth.RestPortalContainerNameConfig</type>
<init-params>
<value-param>
<name>rest-container-name</name>
<value>portal</value>
</value-param>
</init-params>
</component>
Init-params:
Name | Type | Value | Description |
---|---|---|---|
rest-container-name | any valid container name | portal | The name of the container. |
This service is used to provide the utility to get the URLs of the activities, profiles, spaces, avatars and more.
Sample configuration:
<component>
<key>org.exoplatform.social.core.service.LinkProvider</key>
<type>org.exoplatform.social.core.service.LinkProvider</type>
<init-params>
<value-param>
<name>predefinedOwner</name>
<description>this for generate profile link</description>
<value>classic</value>
</value-param>
</init-params>
</component>
Init-params:
Name | Type | Value | Description |
---|---|---|---|
predefinedOwner |
String
| classic
| The default portal owner name. |
This plugin is used to register the external resource bundle for the internationalized activity type.
Sample configuration:
<component-plugin>
<name>exosocial:spaces</name> <!-- activity type -->
<set-method>addActivityResourceBundlePlugin</set-method>
<type>org.exoplatform.social.core.processor.ActivityResourceBundlePlugin</type>
<init-params>
<object-param>
<name>locale.social.Core</name> <!-- resource bundle key file -->
<description>activity key type resource bundle mapping for exosocial:spaces</description>
<object type="org.exoplatform.social.core.processor.ActivityResourceBundlePlugin">
<field name="activityKeyTypeMapping">
<map type="java.util.HashMap">
<entry>
<key><string>space_created</string></key>
<value><string>SpaceActivityPublisher.space_created</string></value>
</entry>
<entry>
<key><string>manager_role_granted</string></key>
<value><string>SpaceActivityPublisher.manager_role_granted</string></value>
</entry>
<entry>
<key><string>user_joined</string></key>
<value><string>SpaceActivityPublisher.user_joined</string></value>
</entry>
<entry>
<key><string>member_left</string></key>
<value><string>SpaceActivityPublisher.member_left</string></value>
</entry>
</map>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
In which:
Name: exosocial:spaces
Set-method: addActivityResourceBundlePlugin
Type: org.exoplatform.social.core.processor.ActivityResourceBundlePlugin
Init-params:
Object-param | Description |
---|---|
locale.social.Core | The resource bundle key file. |
The plugin provides the identity for a space.
Sample configuration:
<component-plugins>
<component-plugin>
<name>SpaceIdentityProvider plugin</name>
<set-method>registerIdentityProviders</set-method>
<type>org.exoplatform.social.core.identity.IdentityProviderPlugin</type>
<init-params>
<values-param>
<name>providers</name>
<description>Identity Providers</description>
<value>org.exoplatform.social.core.identity.provider.SpaceIdentityProvider</value>
</values-param>
</init-params>
</component-plugin>
</component-plugins>
In which:
Name: SpaceIdentityProvider plugin
Set-method: registerIdentityProviders
Type: org.exoplatform.social.core.identity.IdentityProviderPlugin
Init-params:
Name | Possible value | Default value | Description |
---|---|---|---|
providers | Every other identity providers | org.exoplatform.social.core.identity.provider.SpaceIdentityProvider | Identity Provider instances for managing identities. |
This plugin allows creating a link to a user profile when the user is mentioned in the activity content.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.social.core.manager.ActivityManager</target-component>
Sample Configuration:
<component-plugin>
<name>MentionsProcessor</name>
<set-method>addProcessorPlugin</set-method>
<type>org.exoplatform.social.core.processor.MentionsProcessor</type>
<init-params>
<value-param>
<name>priority</name>
<description>priority of this processor (lower are executed first)</description>
<value>2</value>
</value-param>
</init-params>
</component-plugin>
In which:
Name: MentionsProcessor
Set-method: addProcessorPlugin
Type: org.exoplatform.social.core.processor.MentionsProcessor
Init-params:
Name | Possible value | Default value | Description |
---|---|---|---|
priority |
integer | 2 | The priority of this processor. The lower priority level is executed first. |
The plugin renders valid HTML tags appearing in the Activity body (content).
Sample configuration:
<component>
<key>org.exoplatform.social.core.manager.ActivityManager</key>
<type>org.exoplatform.social.core.manager.ActivityManagerImpl</type>
<component-plugins>
<component-plugin>
<name>OSHtmlSanitizer</name>
<set-method>addProcessorPlugin</set-method>
<type>org.exoplatform.social.core.processor.OSHtmlSanitizerProcessor</type>
</component-plugin>
</component-plugins>
</component>
In which:
Name: OSHtmlSanitizer
Set-method: addProcessorPluginn
Type: org.exoplatform.social.core.processor.OSHtmlSanitizerProcessor
This plugin is used to configure the list of portlet names which will have portlet preference of space context.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.social.core.space.spi.SpaceService</target-component>
Sample configuration:
<component-plugin>
<name>portlets.prefs.required</name>
<set-method>setPortletsPrefsRequired</set-method>
<type>org.exoplatform.social.core.application.PortletPreferenceRequiredPlugin</type>
<init-params>
<values-param>
<name>portletsPrefsRequired</name>
<value>SpaceActivityStreamPortlet</value>
<value>SpaceSettingPortlet</value>
<value>MembersPortlet</value>
</values-param>
</init-params>
</component-plugin>
In which:
Name: portlets.prefs.required
Set-method: setPortletsPrefsRequired
Type: org.exoplatform.social.core.application.PortletPreferenceRequiredPlugin
Init-params:
Name | Possible value | Default value | Description |
---|---|---|---|
portletsPrefsRequired | Portlet names | SpaceActivityStreamPortlet; SpaceSettingPortlet; MembersPortlet | The list of portlets which need to be saved and get the space context name. |
This plugin is used to configure the default applications when creating a new space.
Sample configuration:
<component-plugin>
<name>Space Application Configuration</name>
<set-method>setSpaceApplicationConfigPlugin</set-method>
<type>org.exoplatform.social.core.space.SpaceApplicationConfigPlugin</type>
<init-params>
<object-param>
<name>spaceHomeApplication</name>
<description>Space Home Application</description>
<object type="org.exoplatform.social.core.space.SpaceApplicationConfigPlugin$SpaceApplication">
<field name="portletApp"><string>social-portlet</string></field>
<field name="portletName"><string>SpaceActivityStreamPortlet</string></field>
<field name="appTitle"><string>Home</string></field>
<!--<field name="icon"><string>SpaceHomeIcon</string></field>-->
</object>
</object-param>
<object-param>
<name>spaceApplicationListConfig</name>
<description>space application list configuration</description>
<object type="org.exoplatform.social.core.space.SpaceApplicationConfigPlugin">
<field name="spaceApplicationList">
<collection type="java.util.ArrayList">
<value>
<object type="org.exoplatform.social.core.space.SpaceApplicationConfigPlugin$SpaceApplication">
<field name="portletApp"><string>dashboard</string></field>
<field name="portletName"><string>DashboardPortlet</string></field>
<field name="appTitle"><string>Dashboard</string></field>
<field name="removable"><boolean>true</boolean></field>
<field name="order"><int>1</int></field>
<field name="uri"><string>dashboard</string></field>
<!--<field name="icon"><string>SpaceDashboardIcon</string></field>-->
</object>
</value>
<value>
<object type="org.exoplatform.social.core.space.SpaceApplicationConfigPlugin$SpaceApplication">
<field name="portletApp"><string>social-portlet</string></field>
<field name="portletName"><string>SpaceSettingPortlet</string></field>
<field name="appTitle"><string>Space Settings</string></field>
<field name="removable"><boolean>false</boolean></field>
<field name="order"><int>2</int></field>
<field name="uri"><string>settings</string></field>
<!--<field name="icon"><string>SpaceSettingsIcon</string></field>-->
</object>
</value>
<value>
<object type="org.exoplatform.social.core.space.SpaceApplicationConfigPlugin$SpaceApplication">
<field name="portletApp"><string>social-portlet</string></field>
<field name="portletName"><string>MembersPortlet</string></field>
<field name="appTitle"><string>Members</string></field>
<field name="removable"><boolean>true</boolean></field>
<field name="order"><int>3</int></field>
<field name="uri"><string>members</string></field>
<!--<field name="icon"><string>SpaceMembersIcon</string></field>-->
</object>
</value>
</collection>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
In which:
Name: Space Application Configuration
Set-method: setSpaceApplicationConfigPlugin
Type: org.exoplatform.social.core.space.SpaceApplicationConfigPlugin
Init-params:
Object-param | Description |
---|---|
spaceHomeApplication | Set the Application portlet to be the home page of a space. |
spaceApplicationListConfig | The list of the applications that are installed by default to a new space. |
Field name | Possible value | Description |
---|---|---|
portletAp | string | The .war name file which has the portlet. |
portletName | string | The name of portlet which is registered in the system. |
appTitle | string | The display name of the application. |
removable | boolean | Specify if the application is removed from the space or not. |
order | integer | The order of the application in the space navigation. |
uri | string | The URI of the application in the page node. |
icon | string | The icon of the application. |
This plugin is used to manage ChromatticSession in the Social project.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.commons.chromattic.ChromatticManager</target-component>
Sample configuration:
<component-plugin>
<name>chromattic</name>
<set-method>addLifeCycle</set-method>
<type>org.exoplatform.social.common.lifecycle.SocialChromatticLifeCycle</type>
<init-params>
<value-param>
<name>domain-name</name>
<value>soc</value>
</value-param>
<value-param>
<name>workspace-name</name>
<value>social</value>
</value-param>
<value-param profiles="all,default,minimal">
<name>workspace-name</name>
<value>social</value>
</value-param>
<values-param>
<name>entities</name>
<value>org.exoplatform.social.core.chromattic.entity.ProviderRootEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.ProviderEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.IdentityEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.ProfileEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.RelationshipEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.RelationshipListEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.ActivityEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.ActivityListEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.ActivityDayEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.ActivityMonthEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.ActivityYearEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.ActivityParameters</value>
<value>org.exoplatform.social.core.chromattic.entity.SpaceRootEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.SpaceEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.SpaceListEntity</value>
<value>org.exoplatform.social.core.chromattic.entity.SpaceRef</value>
</values-param>
<properties-param>
<name>options</name>
<property name="org.chromattic.api.Option.root_node.path" value="/production"/>
<property name="org.chromattic.api.Option.root_node.create" value="true"/>
</properties-param>
</init-params>
</component-plugin>
In which:
Name: chromattic
Set-method: addLifeCycle
Type: org.exoplatform.social.common.lifecycle.SocialChromatticLifeCycle
Init-params:
Value-param | Possible value | Description |
---|---|---|
domain-name | String
| The life cycle domain name. |
workspace-name | String
| The repository workspace name that is associated with this life cycle. |
entities | List<String> | The list of chromatic entities that will be registered against the chromatic builder. |
Properties-param: option
Property name | Possible value | Default value | Description |
---|---|---|---|
org.chromattic.api.Option.rootnode.path |
String |
/production
| The path of the root node. |
org.chromattic.api.Option.rootnode.create |
Boolean |
true
| Specify whether or not the root node is created by the ROOT_NODE_PATH option when it does not exist. |
This plugin uses the value in the template parameter of the activity and replaces the title and body of the activity with the template parameter of this activity.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.social.core.manager.ActivityManager</target-component>
Sample configuration:
<component-plugin>
<name>TemplateParamsProcessor</name>
<set-method>addProcessorPlugin</set-method>
<type>org.exoplatform.social.core.processor.TemplateParamsProcessor</type>
<init-params>
<value-param>
<name>priority</name>
<value>1</value>
</value-param>
</init-params>
</component-plugin>
In which:
Name: TemplateParamsProcessor
Set-method: addProcessorPlugin
Type: org.exoplatform.social.core.processor.TemplateParamsProcessor
Init-params:
Name | Possible value | Default value | Description |
---|---|---|---|
priority |
integer | 1 | The priority of this processor. The lower priority level is executed first. |
This plugin converts all the URLs in the activity into the hyperlinks.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.social.common.xmlprocessor.XMLProcessor</target-component>
Sample configuration:
<component-plugin>
<name>URLConverterFilterPlugin</name>
<set-method>addFilterPlugin</set-method>
<type>org.exoplatform.social.common.xmlprocessor.filters.URLConverterFilterPlugin</type>
<init-params>
<value-param>
<name>urlMaxLength</name>
<description>the max length of URL</description>
<value>-1</value>
</value-param>
</init-params>
</component-plugin>
In which:
Name: URLConverterFilterPlugin
Set-method: addFilterPlugin
Type: org.exoplatform.social.common.xmlprocessor.filters.URLConverterFilterPlugin
Init-params:
Value-param | Possible value | Default value | Description |
---|---|---|---|
urlMaxLength | integer
| -1 | The maximum length of the URL. If the URL is exceeding the maximum length, the URL will be shorten. If the value is -1, it means the URL is not be shortened. |
This plugin is used to set the portal container name used for REST service.
To use the plugin in the component configuration, you must use the following target-component:
<target-component>org.exoplatform.social.opensocial.auth.RestPortalContainerNameConfig</target-component>
Sample configuration:
<component-plugin>
<name>set portal container name used for REST service</name>
<set-method>setRestContainerName</set-method>
<type>org.exoplatform.social.opensocial.auth.RestPortalContainerNameConfig</type>
<init-params>
<value-param>
<name>rest-container-name</name>
<value>socialdemo</value>
</value-param>
</init-params>
</component-plugin>
In which:
Set-method: setRestContainerName
Type: org.exoplatform.social.opensocial.auth.RestPortalContainerNameConfig
Init-params:
Value-param | Possible value | Default value | Description |
---|---|---|---|
rest-container-name |
String
|
socialdemo | The portal container name. |
This chapter supplies you with the basic knowledge about the following topics:
With this knowledge, you can extend more functions for Social, or customize them as you want.
The activity plugin feature was introduced to allow using the activity composer extension and the custom UI component for displaying activity by its type.
You should have an idea about the UI Extension Framework. If you have already worked with the UI Extension Framework, it is really easy to create an activity plugin. If not, you have chance to work with it now. You should have a look at UI Extension Framework.
The Project Code is available here.
When an activity is displayed, UIActivityFactory will look for its registered custom actvity display by activity's type. If not found, UIDefaultActivity will be called for displaying that activity.
For example, in Social, there is an activity of type "exosocial:spaces" created by SpaceActivityPublisher, but now, you want to display it without own UI component instead of the default one. To do that, follow these steps.
1. Create a sample project:
mvn archetype:generate [INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'archetype'. [INFO] artifact org.apache.maven.plugins:maven-archetype-plugin: checking for updates from central [INFO] snapshot org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-6-SNAPSHOT: checking for updates from central [INFO] snapshot org.apache.maven.archetype:maven-archetype:2.0-alpha-6-SNAPSHOT: checking for updates from central [INFO] ------------------------------------------------------------------------ [INFO] Building Maven Default Project [INFO] task-segment: [archetype:generate] (aggregator-style) [INFO] ------------------------------------------------------------------------ [INFO] Preparing archetype:generate [INFO] No goals needed for project - skipping [INFO] snapshot org.apache.maven.archetype:archetype-common:2.0-alpha-6-SNAPSHOT: checking for updates from central [INFO] snapshot org.apache.maven.archetype:archetype-common:2.0-alpha-6-SNAPSHOT: checking for updates from apache.snapshots [INFO] [archetype:generate {execution: default-cli}] [INFO] Generating project in Interactive mode [INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0) Choose archetype: 1: remote -> docbkx-quickstart-archetype (null) 2: remote -> gquery-archetype (null) 3: remote -> gquery-plugin-archetype (null) //.... 285: remote -> wicket-scala-archetype (Basic setup for a project that combines Scala and Wicket, depending on the Wicket-Scala project. Includes an example Specs test.) 286: remote -> circumflex-archetype (null) Choose a number: 76: 76 Choose version: 1: 1.0 2: 1.0-alpha-1 3: 1.0-alpha-2 4: 1.0-alpha-3 5: 1.0-alpha-4 6: 1.1 Choose a number: : 1 Define value for property 'groupId': : org.exoplatform.social.samples Define value for property 'artifactId': : exo.social.samples.activity-plugin Define value for property 'version': 1.0-SNAPSHOT: 1.0.0-SNAPSHOT Define value for property 'package': org.exoplatform.social.samples: org.exoplatform.social.samples.activityPlugin Confirm properties configuration: groupId: org.exoplatform.social.samples artifactId: exo.social.samples.activity-plugin version: 1.0.0-SNAPSHOT package: org.exoplatform.social.samples.activityPlugin Y: y
2. Edit the pom.xml file as below.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.exoplatform.social</groupId>
<artifactId>social-project</artifactId>
<version>1.1.0-GA</version>
</parent>
<groupId>org.exoplatform.social.samples</groupId>
<artifactId>exo.social.samples.activity-plugin</artifactId>
<packaging>jar</packaging>
<version>1.1.0-GA</version>
<name>exo.social.samples.activity-plugin</name>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<outputDirectory>target/classes</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.gtmpl</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
<dependencies>
<dependency>
<groupId>org.exoplatform.portal</groupId>
<artifactId>exo.portal.webui.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.portal</groupId>
<artifactId>exo.portal.webui.portal</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.social</groupId>
<artifactId>exo.social.component.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.social</groupId>
<artifactId>exo.social.component.webui</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.social</groupId>
<artifactId>exo.social.component.service</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
To use the custom UI component for displaying its activity, you need a class that must be a subclass of BaseUIActivity.
3. Call UISpaceSimpleActivity
package org.exoplatform.social.samples.activityplugin;
import org.exoplatform.social.webui.activity.BaseUIActivity;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
@ComponentConfig(
lifecycle = UIFormLifecycle.class,
template = "classpath:groovy/social/plugin/space/UISpaceSimpleActivity.gtmpl"
)
public class UISpaceSimpleActivity extends BaseUIActivity {
}
The UISpaceSimpleActivity.gtmpl template should be created under main/resources/groovy/social/plugin/space:
<div>This is a space activity UI component displayed for type "exosocial:spaces"</div>
An activity builder as explained later is also needed.
package org.exoplatform.social.samples.activityplugin;
import org.exoplatform.social.core.activity.model.Activity;
import org.exoplatform.social.webui.activity.BaseUIActivity;
import org.exoplatform.social.webui.activity.BaseUIActivityBuilder;
public class SimpleSpaceUIActivityBuilder extends BaseUIActivityBuilder {
@Override
protected void extendUIActivity(BaseUIActivity uiActivity, Activity activity) {
// TODO Auto-generated method stub
}
}
4. Create the configuration.xml file under conf/portal:
<configuration xmlns="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd http://www.exoplaform.org/xml/ns/kernel_1_1.xsd">
<external-component-plugins>
<target-component>org.exoplatform.webui.ext.UIExtensionManager</target-component>
<component-plugin>
<name>add.action</name>
<set-method>registerUIExtensionPlugin</set-method>
<type>org.exoplatform.webui.ext.UIExtensionPlugin</type>
<init-params>
<object-param>
<name>Simple Space Activity</name>
<object type="org.exoplatform.social.webui.activity.UIActivityExtension">
<field name="type">
<string>org.exoplatform.social.webui.activity.BaseUIActivity</string>
</field>
<field name="name">
<string>exosocial:spaces</string>
</field>
<field name="component">
<string>org.exoplatform.social.samples.activityplugin.UISpaceSimpleActivity</string>
</field>
<field name="activityBuiderClass">
<string>org.exoplatform.social.samples.activityplugin.SimpleSpaceUIActivityBuilder</string>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
</configuration>
Note that exosocial:spaces must have its value matching with the activity's type that you want to display with your UI component.
Assume that you have already built the Social project with version 1.1. If you do not know how to, have a look at building from sources with Social 1.1.0-CR01. Next, build a sample project and copy the jar file to /tomcat/lib. Then, run Social, create a space and access it, you can see the space's activity of type "exosocial:spaces" is displayed by default in Social:
The custom UI component for displaying activity of type "exosocial:spaces" is like below:
5. Make the custom UI activity display have the look, feel and function like the default one.
When displaying an activity, you should make sure that the look and feel of the custom UI component is consistent and match with other activities and have the full functions of Like, Comments. To create another UI component to display, call UISpaceLookAndFeelActivity:
package org.exoplatform.social.samples.activityplugin;
import org.exoplatform.social.webui.activity.BaseUIActivity;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
@ComponentConfig(
lifecycle = UIFormLifecycle.class,
template = "classpath:groovy/social/plugin/space/UISpaceLookAndFeelActivity.gtmpl",
events = {
@EventConfig(listeners = BaseUIActivity.ToggleDisplayLikesActionListener.class),
@EventConfig(listeners = BaseUIActivity.ToggleDisplayCommentFormActionListener.class),
@EventConfig(listeners = BaseUIActivity.LikeActivityActionListener.class),
@EventConfig(listeners = BaseUIActivity.SetCommentListStatusActionListener.class),
@EventConfig(listeners = BaseUIActivity.PostCommentActionListener.class),
@EventConfig(listeners = BaseUIActivity.DeleteActivityActionListener.class, confirm = "UIActivity.msg.Are_You_Sure_To_Delete_This_Activity"),
@EventConfig(listeners = BaseUIActivity.DeleteCommentActionListener.class, confirm = "UIActivity.msg.Are_You_Sure_To_Delete_This_Comment")
}
)
public class UISpaceLookAndFeelActivity extends BaseUIActivity {
}
6. Create the UISpaceLookAndFeelActivity template. The easiest way is to copy the content of UIDefaultActivity.gtmpl to this template file:
<%
import org.exoplatform.portal.webui.util.Util;
import org.exoplatform.webui.form.UIFormTextAreaInput;
def pcontext = Util.getPortalRequestContext();
def jsManager = pcontext.getJavascriptManager();
def labelActivityHasBeenDeleted = _ctx.appRes("UIActivity.label.Activity_Has_Been_Deleted");
def activity = uicomponent.getActivity();
def activityDeletable = uicomponent.isActivityDeletable();
%>
<% if (activity) { //process if not null
jsManager.importJavascript("eXo.social.Util", "/social-resources/javascript");
jsManager.importJavascript("eXo.social.PortalHttpRequest", "/social-resources/javascript");
jsManager.importJavascript("eXo.social.webui.UIForm", "/social-resources/javascript");
jsManager.importJavascript("eXo.social.webui.UIActivity", "/social-resources/javascript");
def labelComment = _ctx.appRes("UIActivity.label.Comment");
def labelLike = _ctx.appRes("UIActivity.label.Like");
def labelUnlike = _ctx.appRes("UIActivity.label.Unlike");
def labelSource = _ctx.appRes("UIActivity.label.Source");
def inputWriteAComment = _ctx.appRes("UIActivity.input.Write_A_Comment");
def labelShowAllComments = _ctx.appRes("UIActivity.label.Show_All_Comments");
def labelHideAllComments = _ctx.appRes("UIActivity.label.Hide_All_Comments");
def labelOnePersonLikeThis = _ctx.appRes("UIActivity.label.One_Person_Like_This");
def labelPeopleLikeThis = _ctx.appRes("UIActivity.label.People_Like_This");
def labelYouLikeThis = _ctx.appRes("UIActivity.label.You_Like_This");
def labelYouAndOnePersonLikeThis = _ctx.appRes("UIActivity.label.You_And_One_Person_Like_This");
def labelYouAndPeopleLikeThis = _ctx.appRes("UIActivity.label.You_And_People_Like_This");
def likeActivityAction = uicomponent.event("LikeActivity", "true");
def unlikeActivityAction = uicomponent.event("LikeActivity", "false");
def commentList = uicomponent.getComments();
def allComments = uicomponent.getAllComments();
if (allComments) {
labelShowAllComments = labelShowAllComments.replace("{0}", allComments.size() + "");
labelHideAllComments = labelHideAllComments.replace("{0}", allComments.size() + "");
}
def displayedIdentityLikes = uicomponent.getDisplayedIdentityLikes();
def identityLikesNum = 0;
def labelLikes = null;
def toggleDisplayLikesAction = uicomponent.event("ToggleDisplayLikes");
def startTag = "<a onclick={{{"}}}$toggleDisplayLikesAction{{{"}}} id={{{"}}}ToggleDisplayListPeopleLikes${activity.id}{{{"}}} href={{{"}}}#ToggleDisplayListPeopleLikes{{{"}}}>";
def endTag = "</a>";
if (displayedIdentityLikes != null) {
identityLikesNum = displayedIdentityLikes.length;
}
def commentListStatus = uicomponent.getCommentListStatus();
def commentFormDisplayed = uicomponent.isCommentFormDisplayed();
def likesDisplayed = uicomponent.isLikesDisplayed();
//params for init UIActivity javascript object
def params = """
{activityId: '${activity.id}',
inputWriteAComment: '$inputWriteAComment',
commentMinCharactersAllowed: ${uicomponent.getCommentMinCharactersAllowed()},
commentMaxCharactersAllowed: ${uicomponent.getCommentMaxCharactersAllowed()},
commentFormDisplayed: $commentFormDisplayed,
commentFormFocused: ${uicomponent.isCommentFormFocused()}
}
"""
jsManager.addOnLoadJavascript("initUIActivity${activity.id}");
//make sures commentFormFocused is set to false to prevent any refresh to focus, only focus after post a comment
uicomponent.setCommentFormFocused(false);
def activityUserName, activityUserProfileUri, activityImageSource, activityContentBody, activityPostedTime;
def commentFormBlockClass = "", listPeopleLikeBlockClass = "", listPeopleBGClass = "";
if (!commentFormDisplayed) {
commentFormBlockClass = "DisplayNone";
}
if (!likesDisplayed) {
listPeopleLikeBlockClass = "DisplayNone";
}
if (uicomponent.isLiked()) {
if (identityLikesNum > 1) {
labelLikes = labelYouAndPeopleLikeThis.replace("{start}", startTag).replace("{end}", endTag).replace("{0}", identityLikesNum + "");
} else if (identityLikesNum == 1) {
labelLikes = labelYouAndOnePersonLikeThis.replace("{start}", startTag).replace("{end}", endTag);
} else {
labelLikes = labelYouLikeThis;
}
} else {
if (identityLikesNum > 1) {
labelLikes = labelPeopleLikeThis.replace("{start}", startTag).replace("{end}", endTag).replace("{0}", identityLikesNum + "");
} else if (identityLikesNum == 1) {
labelLikes = labelOnePersonLikeThis.replace("{start}", startTag).replace("{end}", endTag);
}
}
if (!labelLikes) {
//hides diplayPeopleBG
listPeopleBGClass = "DisplayNone";
}
activityContentTitle = activity.title;
activityPostedTime = uicomponent.getPostedTimeString(activity.postedTime);
activityUserName = uicomponent.getUserFullName(activity.userId);
activityUserProfileUri = uicomponent.getUserProfileUri(activity.userId);
activityImageSource = uicomponent.getUserAvatarImageSource(activity.userId);
if (!activityImageSource) {
activityImageSource = "/social-resources/skin/ShareImages/SpaceImages/SpaceLogoDefault_61x61.gif";
}
%>
<div class="UIActivity">
<script type="text/javascript">
function initUIActivity${activity.id}() {
new eXo.social.webui.UIActivity($params);
}
</script>
<% uiform.begin() %>
<div class="NormalBox clearfix">
<a class="Avatar" title="$activityUserName" href="$activityUserProfileUri">
<img title="$activityUserName" src="$activityImageSource" alt="$activityUserName" height="54px" width="56px">
</a>
<div class="ContentBox" id="ContextBox${activity.id}">
<div class="TitleContent clearfix">
<div class="Text">
<a title="$activityUserName" href="$activityUserProfileUri">$activityUserName</a>
</div>
<% if (activityDeletable) {%>
<div onclick="<%= uicomponent.event("DeleteActivity", uicomponent.getId(), ""); %>" class="CloseContentBoxNormal" id="DeleteActivityButton${activity.id}"><span></span></div>
<%}%>
</div>
<div class="Content">
$activityContentTitle (from custom UI component)<br>
</div>
<div class="LinkCM">
<span class="DateTime">$activityPostedTime *</span>
<% def toggleDisplayCommentAction = uicomponent.event('ToggleDisplayCommentForm', null, false);
def commentLink = "";
%>
<a class="LinkCM $commentLink" onclick="$toggleDisplayCommentAction" id="CommentLink${activity.id}" href="#comment">
$labelComment
</a> |
<% if (uicomponent.isLiked()) { %>
<a onclick="$unlikeActivityAction" class="LinkCM" id="UnLikeLink${activity.id}" href="#unlike">
$labelUnlike
</a>
<% } else { %>
<a onclick="$likeActivityAction" class="LinkCM" id="LikeLink${activity.id}" href="#like">
$labelLike
</a>
<% }%>
</div>
</div>
<div class="ListPeopleLikeBG $listPeopleBGClass">
<div class="ListPeopleLike">
<div class="ListPeopleContent">
<% if (!labelLikes) labelLikes = ""; %>
<div class="Title">$labelLikes</div>
<div class="$listPeopleLikeBlockClass">
<%
//def personLikeFullName, personLikeProfileUri, personLikeAvatarImageSource;
displayedIdentityLikes.each({
personLikeFullName = uicomponent.getUserFullName(it);
personLikeProfileUri = uicomponent.getUserProfileUri(it);
personLikeAvatarImageSource = uicomponent.getUserAvatarImageSource(it);
if (!personLikeAvatarImageSource) {
personLikeAvatarImageSource = "/social-resources/skin/ShareImages/activity/AvatarPeople.gif";
}
%>
<a class="AvatarPeopleBG" title="$personLikeFullName" href="$personLikeProfileUri">
<img width="47px" height="47px" src="$personLikeAvatarImageSource" alt="$personLikeFullName" title="$personLikeFullName" />
</a>
<% })%>
</div>
<div class="ClearLeft">
<span></span>
</div>
</div>
</div>
</div>
<div class="CommentListInfo">
<% if (uicomponent.commentListToggleable()) {
def showAllCommentsAction = uicomponent.event("SetCommentListStatus", "all");
def hideAllCommentsAction = uicomponent.event("SetCommentListStatus", "none");
%>
<div class="CommentBlock">
<div class="CommentContent">
<div class="CommentBorder">
<% if (commentListStatus.getStatus().equals("latest") || commentListStatus.getStatus().equals("none")) { %>
<a onclick="$showAllCommentsAction" href="#show-all-comments">
$labelShowAllComments
</a>
<% } else if (commentListStatus.getStatus().equals("all")) { %>
<a onclick="$hideAllCommentsAction" href="#hide-all-comments">
$labelHideAllComments
</a>
<% } %>
</div>
</div>
</div>
<% } %>
</div>
<% if (allComments.size() > 0) { %>
<div class="DownIconCM"><span></span></div>
<% }%>
<%
def commenterFullName, commenterProfileUri, commenterImageSource, commentMessage, commentPostedTime;
def first = true, commentContentClass;
commentList.each({
if (first & !uicomponent.commentListToggleable()) {
commentContentClass = "CommentContent";
first = false;
} else {
commentContentClass = "";
}
commenterFullName = uicomponent.getUserFullName(it.userId);
commenterProfileUri = uicomponent.getUserProfileUri(it.userId);
commenterImageSource = uicomponent.getUserAvatarImageSource(it.userId);
if (!commenterImageSource) {
commenterImageSource = "/social-resources/skin/ShareImages/activity/AvatarPeople.gif";
}
commentMessage = it.title;
commentPostedTime = uicomponent.getPostedTimeString(it.postedTime);
%>
<div id="CommentBlock${activity.id}" class="CommentBox clearfix">
<a class="AvatarCM" title="$commenterFullName" href="$commenterProfileUri">
<img src="$commenterImageSource" alt="$commenterFullName" height="36px" width="38px">
</a>
<div class="ContentBox">
<div class="Content">
<a href="$commenterProfileUri"><span class="Commenter">$commenterFullName<span></a><br />
$commentMessage
<br/>
</div>
<div class="LinkCM">
<span class="DateTime">$commentPostedTime</span>
</div>
</div>
<%
if (uicomponent.isCommentDeletable(it.userId)) {
%>
<div onclick="<%= uicomponent.event("DeleteComment", uicomponent.id, it.id); %>" class="CloseCMContentHilight"><span></span></div>
<% } %>
</div>
<% }) %>
<div class="CommentBox $commentFormBlockClass clearfix" id="CommentFormBlock${activity.id}">
<% uicomponent.renderChild(UIFormTextAreaInput.class); %>
<input type="button" onclick="<%= uicomponent.event("PostComment") %>" value="$labelComment" class="CommentButton DisplayNone" id="CommentButton${activity.id}" />
</div>
</div>
<% uiform.end() %>
</div>
<% } else { %> <!-- activity deleted -->
<div class="UIActivity Deleted">$labelActivityHasBeenDeleted</div>
<% }%>
And you should make needed modifications for this template:
<div class="Content">
$activityContentTitle (from custom UI component)<br>
</div>
7. Reconfigure the configuration.xml file:
<configuration xmlns="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_1.xsd http://www.exoplaform.org/xml/ns/kernel_1_1.xsd">
<external-component-plugins>
<target-component>org.exoplatform.webui.ext.UIExtensionManager</target-component>
<component-plugin>
<name>add.action</name>
<set-method>registerUIExtensionPlugin</set-method>
<type>org.exoplatform.webui.ext.UIExtensionPlugin</type>
<init-params>
<object-param>
<name>Look And Feel Space Activity</name>
<object type="org.exoplatform.social.webui.activity.UIActivityExtension">
<field name="type">
<string>org.exoplatform.social.webui.activity.BaseUIActivity</string>
</field>
<field name="name">
<string>exosocial:spaces</string>
</field>
<field name="component">
<string>org.exoplatform.social.samples.activityplugin.UISpaceLookAndFeelActivity</string>
</field>
<field name="activityBuiderClass">
<string>org.exoplatform.social.samples.activityplugin.SimpleSpaceUIActivityBuilder</string>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
</configuration>
8. Rebuild the sample project, copy the .jar file to tomcat/lib. Run the server again and see the result:
Currently, you have to copy and paste in the template file. By this way, you have full control of the UI but it is not a good way when there are changes in UIDefaultActivity. This will be improved soon so that no copy/paste is needed.
ActivityBuilder is one class which is used to get values of ExoSocialActivity to set to UIActivity for displaying. Social provides the BaseUIActivityBuilder class for developers to extend and customize their own activity builder easily and properly.
For example, to write your own UILinkActivityBuilder, you just need to extend BaseUIActivityBuilder and then customize attributes and behaviors of the activity builder as below.
public class UILinkActivityBuilder extends BaseUIActivityBuilder {
private static final Log LOG = ExoLogger.getLogger(UILinkActivityBuilder.class);
@Override
protected void extendUIActivity(BaseUIActivity uiActivity, ExoSocialActivity activity) {
UILinkActivity uiLinkActivity = (UILinkActivity) uiActivity;
Map<String, String> templateParams = activity.getTemplateParams();
uiLinkActivity.setLinkSource(templateParams.get(UILinkActivityComposer.LINK_PARAM));
uiLinkActivity.setLinkTitle(templateParams.get(UILinkActivityComposer.TITLE_PARAM));
uiLinkActivity.setLinkImage(templateParams.get(UILinkActivityComposer.IMAGE_PARAM));
uiLinkActivity.setLinkDescription(templateParams.get(UILinkActivityComposer.DESCRIPTION_PARAM));
uiLinkActivity.setLinkComment(templateParams.get(UILinkActivityComposer.COMMENT_PARAM));
}
}
To learn more about ActivityBuilder, refer to the BaseUIActivity class.
The UIActivityComposer is an extended class of UIContainer that is used to display inputs for users to create their own activities. To write your own activity composer, it is recommended that you use the UIActivityComposer available in Social.
For example, to create an input component for inserting video links into your activity, do the following steps:
1. Write UIVideoActivityComposer which extends UIActivityComposer. The UIActivityComposer allows you to input extended activities (for example, adding videos, links or documents) on the UI composer.
package org.exoplatform.social.plugin.videolink;
import org.exoplatform.social.plugin.videolink.util.VideoEmbedTool;
@ComponentConfig(
template = "classpath:groovy/social/plugin/videolink/UIVideoActivityComposer.gtmpl",
events = {
@EventConfig(listeners = UIVideoActivityComposer.SearchVideo.class),
@EventConfig(listeners = UIVideoActivityComposer.SelectVideoFromResultList.class),
@EventConfig(listeners = UIVideoActivityComposer.AttachActionListener.class),
@EventConfig(listeners = UIVideoActivityComposer.ChangeLinkContentActionListener.class),
@EventConfig(listeners = UIActivityComposer.CloseActionListener.class),
@EventConfig(listeners = UIActivityComposer.SubmitContentActionListener.class),
@EventConfig(listeners = UIActivityComposer.ActivateActionListener.class)
}
)
public class UIVideoActivityComposer extends UIActivityComposer {
public static final String LINK_PARAM = "link";
public static final String IMAGE_PARAM = "image";
public static final String TITLE_PARAM = "title";
public static final String HTML_PARAM = "htmlembed";
public static final String COMMENT_PARAM = "comment";
private static final String HTTP = "http://";
private static final String HTTPS = "https://";
private JSONObject videoJson;
private boolean linkInfoDisplayed_ = false;
private Map<String, String> templateParams;
/**
* The constructor.
*/
public UIVideoActivityComposer() {
setReadyForPostingActivity(false);
addChild(new UIFormStringInput("InputLink", "InputLink", null));
}
/**
* Set the link info to be displayed.
*
* @param displayed
*/
public void setLinkInfoDisplayed(boolean displayed) {
linkInfoDisplayed_ = displayed;
}
/**
* Set the template params.
*
* @param templateParams
*/
public void setTemplateParams(Map<String, String> templateParams) {
this.templateParams = templateParams;
}
/**
* Get the template params.
*/
public Map<String, String> getTemplateParams() {
return templateParams;
}
/**
* Clear the video json.
*/
public void clearVideoJson() {
videoJson = null;
}
/**
* Get the video json.
*/
public JSONObject getVideoJson() {
return videoJson;
}
/**
* Set the link.
* @param url
* @throws Exception
*/
private void setLink(String url) throws Exception {
if (!(url.contains(HTTP) || url.contains(HTTPS))) {
url = HTTP + url;
}
videoJson = VideoEmbedTool.getoembedData(url);
templateParams = new HashMap<String, String>();
templateParams.put(LINK_PARAM, url);
templateParams.put(TITLE_PARAM, videoJson.getString(VideoEmbedTool.OEMBED_TITLE));
templateParams.put(HTML_PARAM, videoJson.getString(VideoEmbedTool.OEMBED_HTML));
setLinkInfoDisplayed(true);
}
static public class AttachActionListener extends EventListener<UIVideoActivityComposer> {
@Override
public void execute(Event<UIVideoActivityComposer> event) throws Exception {
WebuiRequestContext requestContext = event.getRequestContext();
UIVideoActivityComposer uiComposerLinkExtension = event.getSource();
String url = requestContext.getRequestParameter(OBJECTID);
try {
uiComposerLinkExtension.setLink(url.trim());
} catch (Exception e) {
uiComposerLinkExtension.setReadyForPostingActivity(false);
return;
}
requestContext.addUIComponentToUpdateByAjax(uiComposerLinkExtension);
event.getSource().setReadyForPostingActivity(true);
}
}
static public class ChangeLinkContentActionListener extends EventListener<UIVideoActivityComposer> {
@Override
public void execute(Event<UIVideoActivityComposer> event) throws Exception {
WebuiRequestContext requestContext = event.getRequestContext();
UIVideoActivityComposer uiComposerLinkExtension = event.getSource();
Map<String, String> tempParams = new HashMap<String, String>();
uiComposerLinkExtension.setTemplateParams(tempParams);
requestContext.addUIComponentToUpdateByAjax(uiComposerLinkExtension);
UIComponent uiParent = uiComposerLinkExtension.getParent();
if (uiParent != null) {
uiParent.broadcast(event, event.getExecutionPhase());
}
}
}
public static class SelectVideoFromResultList extends EventListener<UIVideoActivityComposer>{
@Override
public void execute(Event<UIVideoActivityComposer> event) throws Exception {
WebuiRequestContext requestContext = event.getRequestContext();
UIVideoActivityComposer uiComposerLinkExtension = event.getSource();
}
}
public static class SearchVideo extends EventListener<UIVideoActivityComposer>{
@Override
public void execute(Event<UIVideoActivityComposer> event) throws Exception {
WebuiRequestContext requestContext = event.getRequestContext();
UIVideoActivityComposer uiComposerLinkExtension = event.getSource();
}
}
@Override
public void onPostActivity(PostContext postContext, UIComponent source,
WebuiRequestContext requestContext, String postedMessage) throws Exception {
templateParams.put(COMMENT_PARAM, postedMessage);
setTemplateParams(templateParams);
if (templateParams.size() == 0) {
uiApplication.addMessage(new ApplicationMessage("UIComposer.msg.error.Empty_Message",
null,
ApplicationMessage.WARNING));
return;
}
String title = "Shared a video: <a href={{{"}}}${" + LINK_PARAM + "}{{{"}}}>${" + TITLE_PARAM + "} </a>";
ExoSocialActivity activity = new ExoSocialActivityImpl(userIdentity.getId(),
UIVideoActivity.ACTIVITY_TYPE,
title,
null);
activity.setTemplateParams(templateParams);
if (postContext == UIComposer.PostContext.SPACE) {
UIActivitiesContainer activitiesContainer = uiDisplaySpaceActivities.getActivitiesLoader().getActivitiesContainer();
activitiesContainer.addActivity(activity);
requestContext.addUIComponentToUpdateByAjax(activitiesContainer);
requestContext.addUIComponentToUpdateByAjax(uiComposer);
} else if (postContext == PostContext.USER) {
UIUserActivitiesDisplay uiUserActivitiesDisplay = (UIUserActivitiesDisplay) getActivityDisplay();
String ownerName = uiUserActivitiesDisplay.getOwnerName();
Identity ownerIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME,
ownerName, false);
activityManager.saveActivity(ownerIdentity, activity);
if (uiUserActivitiesDisplay.getSelectedDisplayMode() == UIUserActivitiesDisplay.DisplayMode.MY_STATUS) {
UIActivitiesContainer activitiesContainer = uiUserActivitiesDisplay.getActivitiesLoader().getActivitiesContainer();
if (activitiesContainer.getChildren().size() == 1) {
uiUserActivitiesDisplay.setSelectedDisplayMode(UIUserActivitiesDisplay.DisplayMode.MY_STATUS);
} else {
activitiesContainer.addActivity(activity);
requestContext.addUIComponentToUpdateByAjax(activitiesContainer);
requestContext.addUIComponentToUpdateByAjax(uiComposer);
}
} else{
uiUserActivitiesDisplay.setSelectedDisplayMode(UIUserActivitiesDisplay.DisplayMode.MY_STATUS);
}
}
}
}
2. Use the BaseUIActivity class to write and customize the UIActivity display as below:
package org.exoplatform.social.plugin.videolink;
import org.exoplatform.social.webui.activity.BaseUIActivity;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
import org.exoplatform.webui.config.annotation.EventConfig;
@ComponentConfig(lifecycle = UIFormLifecycle.class, template = "classpath:groovy/social/plugin/videolink/UIVideoActivity.gtmpl", events = {
@EventConfig(listeners = BaseUIActivity.ToggleDisplayLikesActionListener.class),
@EventConfig(listeners = BaseUIActivity.ToggleDisplayCommentFormActionListener.class),
@EventConfig(listeners = BaseUIActivity.LikeActivityActionListener.class),
@EventConfig(listeners = BaseUIActivity.SetCommentListStatusActionListener.class),
@EventConfig(listeners = BaseUIActivity.PostCommentActionListener.class),
@EventConfig(listeners = BaseUIActivity.DeleteActivityActionListener.class, confirm = "UIActivity.msg.Are_You_Sure_To_Delete_This_Activity"),
@EventConfig(listeners = BaseUIActivity.DeleteCommentActionListener.class, confirm = "UIActivity.msg.Are_You_Sure_To_Delete_This_Comment")
}
)
public class UIVideoActivity extends BaseUIActivity {
public static final String ACTIVITY_TYPE = "VIDEO_ACTIVITY";
private String linkSource = "";
private String linkTitle = "";
private String linkHTML = "";
private String linkComment = "";
/**
* Get the link comment.
*/
public String getLinkComment() {
return linkComment;
}
/**
* Set the link comment.
*
* @param linkComment
*/
public void setLinkComment(String linkComment) {
this.linkComment = linkComment;
}
/**
* Get the link html.
*/
public String getLinkHTML() {
return linkHTML;
}
/**
* Set the link html.
*
* @param linkHTML
*/
public void setLinkHTML(String linkHTML) {
this.linkHTML = linkHTML;
}
/**
* Get the link source.
*/
public String getLinkSource() {
return linkSource;
}
/**
* Set the link source.
*
* @param linkSource
*/
public void setLinkSource(String linkSource) {
this.linkSource = linkSource;
}
/**
* Get the link title.
*/
public String getLinkTitle() {
return linkTitle;
}
/**
* Set the link title.
*
* @param linkTitle
*/
public void setLinkTitle(String linkTitle) {
this.linkTitle = linkTitle;
}
}
3. Use the UIVideoActivityBuilder class to get values of ExoSocialActivity that are set to UIVideoActivity for displaying.
package org.exoplatform.social.plugin.videolink;
import java.util.Map;
import org.exoplatform.social.core.activity.model.ExoSocialActivity;
public class UIVideoActivityBuilder extends BaseUIActivityBuilder {
private static final Log LOG = ExoLogger.getLogger(UIVideoActivityBuilder.class);
@Override
protected void extendUIActivity(BaseUIActivity uiActivity, ExoSocialActivity activity) {
UIVideoActivity uiVideoActivity = (UIVideoActivity) uiActivity;
Map<String, String> templateParams = activity.getTemplateParams();
uiVideoActivity.setLinkSource(templateParams.get(UIVideoActivityComposer.LINK_PARAM));
uiVideoActivity.setLinkTitle(templateParams.get(UIVideoActivityComposer.TITLE_PARAM));
uiVideoActivity.setLinkImage(templateParams.get(UIVideoActivityComposer.IMAGE_PARAM));
uiVideoActivity.setLinkHTML(templateParams.get(UIVideoActivityComposer.HTML_PARAM));
uiVideoActivity.setLinkComment(templateParams.get(UIVideoActivityComposer.COMMENT_PARAM));
}
}
You can check out the source code to get more details.
There are 2 components in Social that can be overridden: Space Application Handler & Space Service.
Space Application Handler
<component>
<key>org.exoplatform.social.core.space.spi.SpaceApplicationHandler</key>
<type>org.exoplatform.social.core.space.impl.DefaultSpaceApplicationHandler</type>
</component>
Space Service
<component>
<key>org.exoplatform.social.core.space.spi.SpaceService</key>
<type>org.exoplatform.social.core.space.impl.SpaceServiceImpl</type>
<init-params>
<!-- Configure the applications to install in a space -->
<values-param>
<name>space.homeNodeApp</name>
<value>SpaceActivityStreamPortlet</value>
</values-param>
<!-- Configure removable application or not <value>Application:removable</value> -->
<values-param>
<name>space.apps</name>
<value>DashboardPortlet:true</value>
<value>SpaceSettingPortlet:false</value>
<value>MembersPortlet:true</value>
</values-param>
</init-params>
</component>
Method | Param | Return | Description |
---|---|---|---|
saveActivity(Identity owner, ExoSocialActivity activity) throws ActivityStorageException |
owner - the owner of activity stream, activity - the activity which needs to be saved | ExoSocialActivity | Save an activity to the stream of an owner. Note that the Activity.userId will be set to the owner's identity if it has not been already set. |
getActivity(String activityId) throws ActivityStorageException |
activityId - the id of activity | ExoSocialActivity | Get an activity by its id. |
deleteActivity(String activityId) throws ActivityStorageException |
activityId - the id of activity | void | Delete an activity by its id. |
deleteActivity(ExoSocialActivity activity) throws ActivityStorageException |
activity | void | Delete a stored activity (id != null). (Since 1.1.1). |
deleteComment(String activityId, String commentId) throws ActivityStorageException |
activityId - the id of activity, commentId - the id of comment | void | Delete a comment by its id. |
getActivities(Identity identity) throws ActivityStorageException |
identity | List<ExoSocialActivity> | Get the latest activities by an identity with the default limit of 20 latest activities. |
getActivities(Identity identity, long start, long limit) throws ActivityStorageException |
identity , start , limit | List<ExoSocialActivity> | Get the latest activities by an identity, specifying start that is an offset index and limit. |
getActivitiesOfConnections(Identity ownerIdentity) throws ActivityStorageException | ownerIdentity | List<ExoSocialActivity> | Get activities of connections from an identity. The activities are returned as a list that is sorted descending by activity posted time. (Since 1.1.1). |
getActivitiesOfConnections(Identity ownerIdentity, int offset, int limit) throws ActivityStorageException; | ownerIdentity, offset, limit | List<ExoSocialActivity> | Get the activities of connections from an identity by specifying offset and limit. The activities are returned as a list that is sorted starting from the most recent activity.(Since 1.2.0-GA). |
getActivitiesOfUserSpaces(Identity ownerIdentity) | ownerIdentity | List<ExoSocialActivity> | Get the activities from all spaces of a user. By default, the activity list is composed of all spaces' activities. Each activity list of the space contains maximum 20 activities and are sorted by time. (Since 1.1.1). |
getActivityFeed(Identity identity) throws ActivityStorageException | identity | List<ExoSocialActivity> | Get the activity feed of an identity. This feed is the combination of all the activities of his own activities, his connections' activities and spaces' activities which are returned as a list that is sorted starting from the most recent activity.(Since 1.1.2). |
saveActivity(ExoSocialActivity activity) throws ActivityStorageException | activity - the activity to save | ExoSocialActivity | Save an activity into the stream for the activity's userId. The userId must be set and this field is used to indicate the owner stream. |
saveComment(ExoSocialActivity activity, ExoSocialActivity comment) throws ActivityStorageException | activity, comment | void | Save a new comment or updates an existing comment that is an instance of activity with mandatory fields: userId, title. |
saveLike(ExoSocialActivity activity, Identity identity) throws ActivityStorageException | activity, identity | void | Save an identity who likes an activity. |
removeLike(ExoSocialActivity activity, Identity identity) throws ActivityStorageException | activity , identity - a user who dislikes an activity | void | Remove an identity who likes an activity, if this activity is liked, it will be removed. |
getComments(ExoSocialActivity activity) throws ActivityStorageException | activity | List<ExoSocialActivity> | Get the comment list of an activity. |
recordActivity(Identity owner, String type, String title) throws ActivityStorageException | owner, type, title | ExoSocialActivity | Record an activity. (Since 1.2.0-GA). |
recordActivity(Identity owner, ExoSocialActivity activity) throws Exception | owner, activity | ExoSocialActivity | Save an activity. You should use ActivityManager#saveActivity(org.exoplatform.social.core.identity.model.Identity, org.exoplatform.social.core.activity.model.ExoSocialActivity) instead. It will be removed in Social 1.3.x. |
recordActivity(Identity owner, String type, String title, String body) throws ActivityStorageException | owner - the owner of the target stream for this activity, type - the type of an activity which will be used to render a custom UI, title - the title, body - the body | ExoSocialActivity | Record an activity. |
addProcessor(ActivityProcessor processor) | processor | void | Add a new processor. |
addProcessorPlugin(BaseActivityProcessorPlugin plugin) | plugin | void | Add a new processor plugin. |
getActivitiesCount(Identity owner) throws ActivityStorageException | owner | int | Get the number of activities from a stream owner. |
processActivitiy(ExoSocialActivity activity) | activity | void | Pass an activity through the chain of processors. |
Method | Param | Return | Description |
---|---|---|---|
registerIdentityProviders(IdentityProviderPlugin plugin) | plugin
| void | Register one or more IdentityProvider through an IdentityProviderPlugin. |
getIdentity(String id) | id can be a social GlobalId or a raw identity such as in Identity.getId() | Identity - null if nothing is found, or the Identity object | Get the identity by ID and loads his profile. |
getIdentity(String id, boolean loadProfile) | id can be a social GlobalId or a raw identity such as in Identity.getId(), loadProfile - the value is true if the profile is loaded and false if not loaded | null if nothing is found, or the Identity object | Get the identity by loading id of the profile optionally. |
deleteIdentity(Identity identity) |
identiy
| void | Delete an identity. |
addIdentityProvider(IdentityProvider<?> idProvider) | idProvider - the id of provider | void | Add the identity provider. |
getOrCreateIdentity(String providerId, String remoteId) | providerId - the id of provider, remoteId - the remote id | Identity | Get the identity by remoteId. If the provider can not find any identity by remoteId, the return value is null. If no identity found by identity provider and that identity is still stored on JCR, the stored identity will be deleted and the return value is null. |
getOrCreateIdentity(String providerId, String remoteId, boolean loadProfile) | providerId - referring to the name of the Identity provider, remoteId - the identifier that identify the identity in the specific identity provider, loadProfile - true when the profile is loaded | null if nothing is found, or the Identity object improves the performance by specifying what needs to be loaded | This function returns an Identity object that is specific to a special type. For example, if the type is Linked'In, the identifier will be the URL of profile or if it is a CS contact manager, it will be the UID of the contact. A new identity is created if it does not exist. |
getIdentitiesByProfileFilter(String providerId, ProfileFilter profileFilter) throws Exception | providerId - the id of provider, profileFilter - the filter of provider | Identity | Get the identities by a profile filter. |
getIdentitiesByProfileFilter(String providerId, ProfileFilter profileFilter, long offset, long limit) throws Exception | providerId, profileFilter, offset, limit | List<Identity> | Get the identities by a profile filter. |
getIdentitiesByProfileFilter(ProfileFilter profileFilter) throws Exception | profileFilter - the profile filter | List<Identity> | Get the identities by a profile filter. |
getIdentitiesByProfileFilter(ProfileFilter profileFilter, long offset, long limit) throws Exception | providerId, profileFilter, offset, limit | List<Identity> | Get the identities by a profile filter. |
getIdentitiesFilterByAlphaBet(String providerId, ProfileFilter profileFilter) throws Exception | providerId - the id of provider, profileFilter - the profile filter | List<Identity> | Get the identities filter by alphabet. |
getIdentitiesFilterByAlphaBet(String providerId, ProfileFilter profileFilter, long offset,long limit) throws Exception | providerId, profileFilter, offset, limit
| List<Identity> | Get the identities filter by alphabet with offset and limit. |
getIdentitiesFilterByAlphaBet(ProfileFilter profileFilter) throws Exception | profileFilter - the profile filter | List<Identity> | Get the identities filter by alphabet. |
getIdentity(String providerId, String remoteId, boolean loadProfile) | providerId , remoteId , loadProfile | Identity | Get the identity. |
getIdentitiesCount(String providerId) | providerId | long | Get the number of identities. |
identityExisted(String providerId, String remoteId) | providerId , remoteId | boolean | Check if the identity is already existed or not. |
saveIdentity(Identity identity) | identity - the identity | void | Save the identity. |
saveProfile(Profile profile) | profile | void | Save a profile. |
addOrModifyProfileProperties(Profile profile) throws Exception | profile
| void | Add or modify properties of profile. Profile parameter is a lightweight that contains only the property that you want to add or modify. NOTE: The method will not delete the properties of an old profile when the param profile does not have those keys. |
updateAvatar(Profile p) | profile | void | Update the avatar. |
updateBasicInfo(Profile p) throws Exception | profile | void | Update the basic information. |
updateContactSection(Profile p) throws Exception | profile | void | Update the contact section of the profile. |
updateExperienceSection(Profile p)throws Exception | profile | void | Update the experience section of the profile. |
updateHeaderSection(Profile p) throws Exception | profile | void | Update the header section of the profile. |
getIdentities(String providerId) throws Exception | providerId - the id of provider | List<Identity> | Get the identities by the provider id. |
getIdentities(String providerId, boolean loadProfile) | providerId - the id of provider, loadProfile - the loaded profile. | List<Identity> | Get the identities by the provider id. If loadProvider is true, loading the profile will be performed. |
getConnections(Identity ownerIdentity) throws Exception | ownerIdentity | List<Identity> | Get connections of an identity. (Since 1.1.1). |
getIdentityStorage() | N/A | IdentityStorage | Get the identity storage. |
getStorage() | N/A | IdentityStorage | Get the storage. Deprecated: should use method getIdentityStorage(). |
registerProfileListener(ProfileListener listener) | listener | void | Register the profile listener. |
unregisterProfileListener(ProfileListener listener) | listener
| void | Unregister the profile listener. |
addProfileListener(ProfileListenerPlugin plugin) | plugin | void | Register a profile listener component plug-in. |
Method | Param | Return | Description |
---|---|---|---|
getRelationshipById(String id) throws Exception | id
| Relationship | Get the relationship by id. You should use get(String) instead. It will be removed at 1.2.x. |
invite(Identity sender, Identity receiver) throws RelationshipStorageException | sender receiver | Relationship | Create a connection invitation between two identities. |
saveRelationship(Relationship relationship) throws RelationshipStorageException | relationship - a relationship | void | Save a relationship. |
confirm(Relationship relationship) throws RelationshipStorageException | relationship - a pending relationship | void | Mark a relationship as confirmed. |
deny(Relationship relationship) throws RelationshipStorageException | relationship - a pending relationship | void | Deny a relationship. |
remove(Relationship relationship) throws RelationshipStorageException | relationship - a pending relationship | void | Remove a relationship. |
ignore(Relationship relationship) throws RelationshipStorageException | relationship - a pending relationship | void | Mark a relationship as ignored |
getPendingRelationships(Identity sender) throws Exception | sender - an identity | List<Relationship> | Get all the pending relationship of sender. |
getPendingRelationships(Identity sender, List<Identity> identities) throws Exception | sender - an identity, identities - a list of identity | List<Relationship> | Get pending relationships of sender that match with identities. |
getRequireValidationRelationships(Identity receiver) throws Exception | receiver - an identity | List<Relationship> | Get list of required validation relationship of receiver. |
getRequireValidationRelationships(Identity receiver, List<Identity> identities) | receiver - an identity, identities - a list of identity | List<Relationship> | Get list of required validation relationship of receiver that match with identities. |
getConfirmedRelationships(Identity identity) | identity - an identity | List<Relationship> | Get list of confirmed relationship of identity. |
getConfirmedRelationships(Identity identity, List<Identity> identities) | identity - an identity, identities - a list of identity | List<Relationship> | Get list of confirmed relationship of identity that match with identities. |
getAllRelationships(Identity identity) | identity - an identity | List<Relationship> | Return all the relationship of a given identity with other identity. |
getAllRelationships(Identity identity, List<Identity> identities) | identity - an identity, identities - a list of identity | List<Relationship> | Return all the relationship of a given identity with other identity in identities. |
getAllRelationships(Identity identity) | identity - an identity | List<Relationship> | Return all the relationship of a given identity with other identity. |
getAllRelationships(Identity identity, Relationship.Type type, List<Identity> identities) | identity - an identity, type - a Relationship.Type, identities - a list of identity <Relationship> | Return all the relationship of a given identity with other identity in identities in type. | |
getRelationship(Identity identity1, Identity identity2) | identity1 and identity2 - identities | Relationship | Get the relationship of two identities. |
Method | Param | Return | Description |
---|---|---|---|
getSpaceByDisplayName(String spaceDisplayName) |
spaceDisplayName
| Space | Get a space whose display name matches the string input. (Since 1.2.0-GA). |
getSpaceByPrettyName(String spaceName) | spaceName
| Space | Get a space whose pretty name matches the string input. (Since 1.2.0-GA). |
getSpaceByGroupId(String groupId) |
groupId
| Space | Get a space that has group Id matching the string input. |
getSpaceById(String spaceId) |
spaceId | Space | Get a space by its Id. |
getSpaceByUrl(String spaceUrl) |
spaceUrl | Space | Get a space whose URL matches the string input. |
getAllSpaces() |
N/A
| ListAccess<Space> | Get a list of spaces with the type of a space list access. (Since 1.3.0-GA). |
getAllSpacesWithListAccess() |
N/A
| ListAccess<Space> | Get a list of spaces with the type of a space list access. (Since 1.2.0-GA). |
getAllSpacesByFilter(SpaceFilter spaceFilter) |
spaceFilter
| ListAccess<Space> | Get a list of spaces with the type of a space list access. These spaces matches the space filter. (Since 1.2.0-GA). |
getMemberSpaces(String userId) |
userId
| ListAccess<Space> | Get a list of spaces with the type of list access that contains all the spaces in which a user has the "member" role. (Since 1.2.0-GA). |
getMemberSpacesByFilter(String userId, SpaceFilter spaceFilter) |
userId , spaceFilter
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains the spaces which a user has the "member" role and match the provided space filter. (Since 1.2.0-GA). |
getAccessibleSpaces(String userId) |
userId
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user has the access permission.(Since 1.3.0-GA). |
getAccessibleSpacesWithListAccess(String userId) |
userId
| ListAccess<Space> | Get a list of spaces with a space list access. The list contains all the spaces that a user has the access permission. (Since 1.2.0-GA). |
getAccessibleSpacesByFilter(String userId, SpaceFilter spaceFilter) |
userId , spaceFilter
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user has the access permission and match the provided space filter. (Since 1.2.0-GA). |
getSettingableSpaces(String userId) |
userId
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user has the setting permission. (Since 1.2.0-GA). |
getSettingabledSpacesByFilter(String userId, SpaceFilter spaceFilter) |
userId, spaceFilter
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user has the setting permission and match the provided space filter. (Since 1.2.0-GA). |
getInvitedSpaces(String userId) |
userId
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user is invited to join. (Since 1.3.0-GA). |
getInvitedSpacesWithListAccess(String userId) | userId
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user is invited to join. (Since 1.2.0-GA). |
getInvitedSpacesByFilter(String userId, SpaceFilter spaceFilter) |
userId , spaceFilter
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user is invited to join and match the provided space filter. (Since 1.2.0-GA). |
getPublicSpaces(String userId) |
userId
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user can request to join. (Since 1.3.0-GA). |
getPublicSpacesWithListAccess(String userId) |
userId
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user can request to join. (Since 1.2.0-GA). |
getPublicSpacesByFilter(String userId, SpaceFilter spaceFilter) |
userId , spaceFilter
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user can request to join and match the provided space filter. (Since 1.2.0-GA). |
getPendingSpaces(String userId) |
userId
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user sent join-request to a space. (Since 1.3.0-GA). |
getPendingSpacesWithListAccess(String userId) |
userId
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user sent a request for joining a space. (Since 1.2.0-GA). |
getPendingSpacesByFilter(String userId, SpaceFilter spaceFilter) |
userId , spaceFilter
| ListAccess<Space> | Get a list of spaces with the type of a space list access. The list contains all the spaces that a user sent join-request to a space and match the provided space filter. (Since 1.2.0-GA). |
createSpace(Space space, String creatorUserId) |
space, creatorUserId
| Space | Create a new space: create a group, its group navigation with pages for installing space applications. |
updateSpace(Space existingSpace) |
existingSpace
| Space | Update information of a space. (Since 1.2.0-GA). |
deleteSpace(Space space) |
space
| void | Delete a space. When deleting a space, all of its page navigation bars and its group will be deleted. |
addPendingUser(Space space, String userId) |
space, userId
| void | Add a user to the pending list to request to join a space. (Since 1.2.0-GA). |
removePendingUser(Space space, String userId) |
space, userId
| void | Remove a user from the pending list to request to join a space. (Since 1.2.0-GA). |
isPendingUser(Space space, String userId) |
space, userId
| void | Check if a user is in the pending list to request to join a space or not. (Since 1.2.0-GA). |
addInvitedUser(Space space, String userId) |
space, userId
| void | Add a user, who is invited to a space, to the invited list. (Since 1.2.0-GA). |
removeInvitedUser(Space space, String userId) |
space, userId
| void | Remove a user, who is invited to a space, from the invited list. (Since 1.2.0-GA). |
isInvitedUser(Space space, String userId) |
space, userId
| void | Check if a user invited to join a space is in the invited list or not. (Since 1.2.0-GA). |
addMember(Space space, String userId) |
space, userId
| void | Add a user to a space. The user will get the "member" role in that space. |
removeMember(Space space, String userId) |
space, userId
| void | Remove a member from a space. |
isMember(Space space, String userId) |
space, userId
| boolean | Check whether a user is a space's member or not. |
setManager(Space space, String userId, boolean isManager) |
space, userId, isManager
| void | Add a user to have the "manager" role in a space. If isManager is set to "true", a user will get the "manager" role. If false, that user will get the "member" role. (Since 1.2.0-GA). |
isManager(Space space, String userId) |
space, userId
| void | Check if a user has the "manager" role in a space or not. (Since 1.2.0-GA). |
isOnlyManager(Space space, String userId) |
space, userId
| boolean | Check if a user is the only one who has the "manager" role in a space. True if the user Id is the only one who has "manager" role in a space. Otherwise, return false. (Since 1.2.0-GA). |
hasAccessPermission(Space space, String userId) |
space, userId
| boolean | Check if a user can access a space or not. If the user is root or the space's member, return true. |
hasSettingPermission(Space space, String userId) |
space, userId
| boolean | Check if a user can have the setting permission to a space or not. If the user is root or the space's member, return true. (Since 1.2.0-GA). |
registerSpaceListenerPlugin(SpaceListenerPlugin spaceListenerPlugin) |
spaceListenerPlugin
| void | Register a space listener plugin to listen to space lifecyle events: creating, removing space, activating, deactiving, adding, removing application, promoting, joining, leaving, and revoking. (Since 1.2.0-GA). |
unregisterSpaceListenerPlugin(SpaceListenerPlugin spaceListenerPlugin) |
spaceListenerPlugin
| void | Unregister an existing space listener plugin. (Since 1.2.0-GA). |
setSpaceApplicationConfigPlugin(SpaceApplicationConfigPlugin spaceApplicationConfigPlugin) |
spaceApplicationConfigPlugin
| void | Set a space application configuration plugin to configure the home and space applications. By configuring this, the space service will know how to create a new page node with title, URL, and portlet to use. (Since 1.2.0-GA). |
getSpaceApplicationConfigPlugin() |
N/A
| SpaceApplicationConfigPlugin | Get the configuration of applications to be initialized when creating a new space. (Since 1.2.0-GA). |
getAllSpaces() throws SpaceException |
N/A
| List<Space> | Get all spaces in Social. You should use method getAllSpaceWithListAccess instead of getAllSpaces. It will be removed in Social 1.3.x. |
getSpaceByName(String spaceName) throws SpaceException |
spaceName
| Space | Get a space by its name. You should use SpaceService#getSpaceByPrettyName instead. It will be removed version 1.3.x. |
getSpacesByFirstCharacterOfName(String firstCharacterOfName) throws SpaceException |
firstCharacterOfName
| List<Space> | Get all spaces whose name starting with the input character. |
getSpacesBySearchCondition(String condition) throws Exception |
condition | List<Space> | Get all spaces which has the name or the description that matches the input condition. |
getSpaces(String userId) throws SpaceException |
userId | List<Space> | Get spaces of a user in which that user is a member. You should use getMemberSpaces(String) instead. It will be removed in Social 1.3.x |
getAccessibleSpaces(String userId) throws SpaceException |
userId
| List<Space> | Get spaces of a user which that user has the access permission. You should use getAccessibleSpacesWithListAccess(String) instead. It will be removed in Social 1.3.x. |
getEditableSpaces(String userId) throws SpaceException |
userId
| List<Space> | Get spaces of a user which that user has the edit permission. You should use getSettingableSpaces(String) instead. It will be removed in Social 1.3.x. |
getInvitedSpaces(String userId) throws SpaceException |
userId
| List<Space> | Get invited spaces of a user and that user can accept or deny the request. You should use getInvitedSpacesWithListAccess(String) instead. It will be removed in Social 1.3.x. |
getPublicSpaces(String userId) throws SpaceException |
userId - Id of user
| List<Space> | Get invited spaces of a user that can be accepted or denied by the user. You should use getPublicSpacesWithListAccess(String) instead. It will be removed in Social 1.3.x. |
getPendingSpaces(String userId) throws SpaceException |
userId
| List<Space> | Get pending spaces of a user and spaces which the user can revoke that request. You should use getPendingSpacesWithListAccess(String) instead. It will be removed in Social 1.3.x. |
createSpace(Space space, String creator, String invitedGroupId) throws SpaceException |
space, creator, invitedGroupId
| Space | Create a new space and invite all users from invitedGroupId to join this newly created space. |
saveSpace(Space space, boolean isNew) throws SpaceException |
space , isNew
| void | Save a new space or update a space. You should use updateSpace(org.exoplatform.social.core.space.model.Space) instead. It will be removed in Social 1.3.x. |
deleteSpace(String spaceId) throws SpaceException |
spaceId
| void | Delete a space by its id. You should use deleteSpace(org.exoplatform.social.core.space.model.Space) instead. It will be removed in Social 1.3.x. |
initApp(Space space) throws SpaceException |
space
| void | It is just for compatibility. Deprecated: it will be removed in Social 1.3.x. |
initApps(Space space) throws SpaceException |
space
| void | It is just for compatibility. Deprecated: it will be removed in Social 1.3.x. |
deInitApps(Space space) throws SpaceException |
space
| void | It is just for compatibility. Deprecated: it will be removed in Social 1.3.x. |
addMember(String spaceId, String userId) throws SpaceException |
spaceId, userId
| void | Add a user to a space, the user will get the "member" role in a space. You should use addMember(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
removeMember(String spaceId, String userId) throws SpaceException |
spaceId, userId
| void | Remove a member from a space. You should use removeMember(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
getMembers(Space space) throws SpaceException |
space
| List<String> | Get a list of the space members from a space. You should use Space#getMembers() instead. It will be removed in Social 1.3.x. |
getMembers(String spaceId) throws SpaceException |
spaceId
| List<String> | Get a list of the space members from a space. You should use Space#getMembers() instead. It will be removed in Social 1.3.x. |
setLeader(Space space, String userId, boolean isLeader) throws SpaceException |
space, userId, isLeader
| void | Set a member of a space as a manager. You should use setManager(org.exoplatform.social.core.space.model.Space, String, boolean) instead. It will be removed in Social 1.3.x. |
setLeader(String spaceId, String userId, boolean isLeader) throws SpaceException |
spaceId, userId, isLeader
| void | Set a member of a space as a manager. You should use setManager(org.exoplatform.social.core.space.model.Space, String, boolean) instead. It will be removed in Social 1.3.x. |
isLeader(Space space, String userId) throws SpaceException |
space, userId
| boolean | Check whether a user is a space's leader or not. You should use isManager(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
isLeader(String spaceId, String userId) throws SpaceException |
spaceId, userId
| boolean | Check whether a user is a space's leader or not. You should use isManager(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
isOnlyLeader(Space space, String userId) throws SpaceException |
space, userId
| boolean | Check whether a user is the only leader of a space or not. You should use isOnlyManager(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
isOnlyLeader(String spaceId, String userId) throws SpaceException |
spaceId, userId
| boolean | Check whether a user is the only leader of a space or not. You should use isOnlyManager(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
isMember(String spaceId, String userId) throws SpaceException |
spaceId, userId,
| boolean | Check whether a user is a space's member or not. You should use isMember(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
hasAccessPermission(String spaceId, String userId) throws SpaceException |
spaceId, userId
| boolean | Check if a user can access a space or not. You should use hasAccessPermission(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
hasEditPermission(Space space, String userId) throws SpaceException |
space, userId
| Boolean | Check if a user can have the edit permission of a space or not. You should use hasSettingPermission(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
hasEditPermission(String spaceId, String userId) throws SpaceException |
spaceId, userId
| Boolean | Check if a user can have the edit permission of a space or not. You should use hasSettingPermission(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
isInvited(Space space, String userId) throws SpaceException |
space, userId
| Boolean | Check if a user is in the invited list of a space or not. You should use isInvitedUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
isInvited(String spaceId, String userId) throws SpaceException |
spaceId, userId
| Boolean | Check if a user is in the invited list of a space or not. You should use isInvitedUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
isPending(Space space, String userId) throws SpaceException |
space, userId
| Boolean | Check if a user is in the pending list of a space or not.You should use isPendingUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
isPending(String spaceId, String userId) throws SpaceException |
spaceId, userId
| Boolean | Check if a user is in the pending list of a space or not. You should use isPendingUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
installApplication(String spaceId, String appId) throws SpaceException |
spaceId, appId
| void | Install an application to a space. |
installApplication(Space space, String appId) throws SpaceException |
space, appId
| void | Install an application to a space. |
activateApplication(Space space, String appId) throws SpaceException |
space, appId
| void | Activate an installed application in a space. |
activateApplication(String spaceId, String appId) throws SpaceException |
spaceId, appId
| void | Activate an installed application in a space. |
deactivateApplication(Space space, String appId) throws SpaceException |
space, appId
| void | Deactivate an installed application in a space. |
deactivateApplication(String spaceId, String appId) throws SpaceException |
spaceId, appId
| void | Deactivate an installed application in a space. |
removeApplication(Space space, String appId, String appName) throws SpaceException |
space, appId, appName
| void | Remove an installed application from a space. |
removeApplication(String spaceId, String appId, String appName) throws SpaceException |
space, appId, appName
| void | Remove an installed application from a space. |
requestJoin(Space space, String userId) throws SpaceException |
space, userId
| void | Request users to join a space. The invited users are then added to the pending list of the space. You should use addPendingUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
requestJoin(String spaceId, String userId) throws SpaceException |
spaceId, userId
| void | Request users to join a space. The invited users are then added to the pending list of the space.. You should use addPendingUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
revokeRequestJoin(Space space, String userId) throws SpaceException |
space, userId
| void | Revoke a join request after users request to join a group and is in the pending status. You should use removePendingUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
revokeRequestJoin(String spaceId, String userId) throws SpaceException |
spaceId, userId
| void | Revoke a request to join a space. You should use removePendingUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
inviteMember(Space space, String userId) throws SpaceException |
space, userId
| void | Invite a userId to become a member of a space. You should use addInvitedUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
inviteMember(String spaceId, String userId) throws SpaceException |
spaceId, userId
| void | Invite a userId to a be member of a space. You should use addInvitedUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
revokeInvitation(Space space, String userId) throws SpaceException |
space, userId
| void | Revoke an invitation. Remove a user from the invited member list of the space. You should use removeInvitedUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
revokeInvitation(String spaceId, String userId) throws SpaceException |
spaceId, userId
| void | Revoke an invitation. Remove a user from the invited member list of the space. You should use removeInvitedUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
acceptInvitation(Space space, String userId) throws SpaceException |
space, userId
| void | Accept an invitation and move a user from the invited list to the member list. You should use addMember(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
acceptInvitation(String spaceId, String userId) throws SpaceException |
spaceId, userId
| void | Accept an invitation and move a user from the invited list to the member list. You should use addMember(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
denyInvitation(Space space, String userId) throws SpaceException |
space, userId
| void | Deny an invitation and remove a user from the invited list. You should use removeInvitedUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
denyInvitation(String spaceId, String userId) throws SpaceException |
spaceId, userId
| void | Deny an invitation and remove a user from the invited list. You should use removeInvitedUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
validateRequest(Space space, String userId) throws SpaceException |
space, userId
| void | Validate a request and move a user from the pending list to the member list. You should use addMember(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
validateRequest(String spaceId, String userId) throws SpaceException |
spaceId, userId
| void | Validate a request and move a user from the pending list to the member list. You should use addMember(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
declineRequest(Space space, String userId) throws SpaceException |
space, userId
| void | Decline a request and remove a user from the pending list. You should use removePendingUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
declineRequest(String spaceId, String userId) throws SpaceException |
spaceId, userId
| void | Decline a request and remove a user from the pending list. You should use removePendingUser(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
registerSpaceLifeCycleListener(SpaceLifeCycleListener listener |
listener
| void | Register a space lifecycle listener. Deprecated: it will be removed in Social 1.3.x. |
unregisterSpaceLifeCycleListener(SpaceLifeCycleListener listener) |
listener
| void | Unregister a space lifecycle listener. Deprecated: it will be removed in Social 1.3.x. |
setPortletsPrefsRequired(PortletPreferenceRequiredPlugin portletPrefsRequiredPlugin) |
portletPrefsRequiredPlugin
| void | Set the portlet preferences got from the plug-in configuration. You should use SpaceApplicationConfigPlugin(org.exoplatform.social.core.space.model.Space, String) instead. It will be removed in Social 1.3.x. |
getPortletsPrefsRequired() |
N/A
| String | Get the portlet preferences required to use in creating the portlet application. Deprecated: it will be removed in Social 1.3.x. |
Method | Param | Return | Description |
---|---|---|---|
addActivityResourceBundlePlugin(ActivityResourceBundlePlugin activityResourceBundlePlugin) |
activityResourceBundlePlugin
| void | Register an activity resource bundle plugin. |
removeActivityResourceBundlePlugin(ActivityResourceBundlePlugin activityResourceBundlePlugin) |
activityResourceBundlePlugin
| void | Unregister an existing registered resource bundle plugin. |
process(ExoSocialActivity i18nActivity, Locale selectedLocale) |
i18nActivity, selectedLocale
| ExoSocialActivity | Process the internationalized activity which means that activity.getTitleId() != null . |
setResourceBundleService(ResourceBundleService resourceBundleService) |
resourceBundleService
| void | Set the external resource bundle service. |
Method | Param | Return | Description |
---|---|---|---|
getSpaceUri(final String prettyName) |
prettyName | String | Return the URI link to the space profile. (Since 1.2.0-GA). |
getProfileUri(final String username) |
username | String | Return the URI link to the user profile. |
getProfileUri(final String username, final String portalOwner) |
username, portalOwner | String | Return the URI link to the user profile in a portalOwner. |
getProfileLink(final String username) |
username | String | Return the <a> tag with a link to the profile of userName. |
getProfileLink(final String username, final String portalOwner) |
username, portalOwner
| String | Return the <a> tag with a link to the profile of userName on a portalName. |
getAbsoluteProfileUrl(final String userName, final String portalName, final String portalOwner, final String host) |
userName, portalName, portalOwner, host | String | Get the absolute profile URI of the userName. |
getUserActivityUri(final String remoteId) |
remoteId | String | Get an activity link of a user. The remoteId parameter should be the Id name. For example: root. |
getUserConnectionsUri(final String remoteId) | remoteId
| String | Get a connection link of a user. The remoteId parameter should be the Id name. For example: root. |
getUserConnectionsYoursUri(final String remoteId) |
remoteId
| String | Get a connection link of a user. The remoteId parameter should be the Id name. For example: root. |
getUserProfileUri(final String remoteId) |
remoteId
| String | Get a profile link of a user. The remoteId parameter should be the Id name.For example: root. |
getActivityUri(final String providerId, final String remoteId) |
providerId, remoteId | String | Get an activity link of a space or a user. The remoteId parameter should be the Id name. For example: organization:root or space:abc_def. |
getActivityUriForSpace(final String remoteId, final String groupId) |
remoteId, groupId | String | Get an activity link of the space. (Since 1.2.8). |
buildAvatarImageUri(final AvatarAttachment avatarAttachment) |
avatarAttachment | String | Build an avatar image URI from avatarAttachment. |
buildAvatarImageUri(final Space space) |
space | String | Get the URI link of the avatar. (Since 1.2.0-GA). |
buildAvatarImageUri(final String identityName) |
identityName | String | Get the URI link of the avatar from the identity name. (Since 1.2.0-GA). |
buildAvatarImageUri(final PortalContainer container, final AvatarAttachment avatarAttachment) |
container, avatarAttachment | String | Build an avatar image URI from avatarAttachment. (Sine 1.2.0-GA). |
getAvatarImageSource(final PortalContainer portalContainer, final Profile profile) |
portalContainer, profile | String | Get an avatar image URI of a profile in a portalContainer. Deprecated: You should use Profile#getAvatarUrl() instead. It will be removed in eXo Social 1.3.x. |
getAvatarImageSource(final Profile profile) |
profile | String | Get an avatar image URI of the profile. Deprecated: You should use Profile#getAvatarUrl() instead. It will be removed in eXo Social 1.3.x. |
escapeJCRSpecialCharacters(String string) |
string | String | Escape the JCR special characters. |
Social provides users with a way to share their activity information (also known as Activity Stream) and collaborate in spaces (also known as group work). With the API, you can customize the way to display activities or publish new ones. To manipulate activities, you need to use the AtivityManager service.
There are two types of activities: activities for a user and activities for a space. The following examples will show you how to publish an activity for each type.
The following examples will show you how to publish an activity for each type.
package org.exoplatform.publish.user;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.social.core.manager.ActivityManager;
import org.exoplatform.social.core.manager.IdentityManager;
import org.exoplatform.social.core.identity.model.Identity;
import org.exoplatform.social.core.activity.model.ExoSocialActivity;
import org.exoplatform.social.core.activity.model.ExoSocialActivityImpl;
import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider;
public class PublishActivityForUser {
// Exo Log.
private final Log LOG = ExoLogger.getLogger(PublishActivityForUser.class);
// Portal container.
private PortalContainer container;
// identityManager manages identities.
private IdentityManager identityManager;
// activityManager manages activities.
private ActivityManager activityManager;
private final static String DEFAULT_USER_NAME = "zun";
private final static String DEFAULT_ACTIVITY_TITLE = "Hello World!";
/**
* Constructor.
*/
public PublishActivityForUser() {
// Gets the current container.
container = PortalContainer.getInstance();
// Gets identityManager to handle an identity operation.
identityManager = (IdentityManager) container.getComponentInstance(IdentityManager.class);
// Gets activityManager to handle an activity operation.
activityManager = (ActivityManager) container.getComponentInstanceOfType(ActivityManager.class);
}
public void createActivityForUser() {
try {
// Gets an existing identity or creates a new one.
Identity userIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, DEFAULT_USER_NAME, false);
// Creates a new activity for this user.
ExoSocialActivity activity = new ExoSocialActivityImpl();
activity.setUserId(userIdentity.getId());
activity.setTitle(DEFAULT_ACTIVITY_TITLE);
// Saves an activity into JCR by using ActivityManager.
activityManager.saveActivity(activity);
} catch (Exception e) {
LOG.error("can not save activity.", e);
}
}
}
package org.exoplatform.publish.space;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.social.core.manager.ActivityManager;
import org.exoplatform.social.core.manager.IdentityManager;
import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider;
import org.exoplatform.social.core.identity.model.Identity;
import org.exoplatform.social.core.activity.model.ExoSocialActivity;
import org.exoplatform.social.core.activity.model.ExoSocialActivityImpl;
import org.exoplatform.social.core.space.model.Space;
import org.exoplatform.social.core.space.SpaceException;
import org.exoplatform.social.core.space.spi.SpaceService;
import org.exoplatform.social.core.identity.provider.SpaceIdentityProvider;
public class PublishActivityForSpace {
// Exo Log.
private final Log LOG = ExoLogger.getLogger(PublishActivityForSpace.class);
// Portal container.
private PortalContainer container;
// identityManager manages identities.
private IdentityManager identityManager;
// activityManager manages activities.
private ActivityManager activityManager;
// spaceService manages spaces.
private SpaceService spaceService;
private final static String DEFAULT_NAME_SPACE = "mySpace";
private final static String DEFAULT_USER_NAME = "zun";
private final static String DEFAULT_ACTIVITY_TITLE = "An activity for space";
/**
* Constructor method.
*/
public PublishActivityForSpace() {
// Gets the current container.
container = PortalContainer.getInstance();
// Gets identityManager to manage identities.
identityManager = (IdentityManager) container.getComponentInstance(IdentityManager.class);
// Gets activityManager to manage activities.
activityManager = (ActivityManager) container.getComponentInstanceOfType(ActivityManager.class);
// Gets spaceService to handle the operation of a space.
spaceService = (SpaceService) container.getComponentInstanceOfType(SpaceService.class);
}
public void createActivityForSpace() {
try {
// make sure that a space with the name "mySpace" is created.
Space space = spaceService.getSpaceByDisplayName(DEFAULT_NAME_SPACE);
if (space != null) {
// Gets spaceIdentity if it already exists. If not, a new one is created.
Identity spaceIdentity = identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME, DEFAULT_NAME_SPACE, false);
// Gets an identity if it already exists. If not, a new one is created.
Identity userIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, DEFAULT_USER_NAME, false);
// Creates a new activity for this space.
ExoSocialActivity activity = new ExoSocialActivityImpl();
activity.setUserId(userIdentity.getId());
activity.setTitle(DEFAULT_ACTIVITY_TITLE);
activityManager.saveActivity(spaceIdentity, activity);
}
} catch (SpaceException e) {
LOG.error("Can not save activity.", e);
} catch (Exception e) {
LOG.error("Can not save activity.", e);
}
}
}
An activity processor is used to modify the content of activities before they are returned from an activity manager. For example, to create an activity processor to replace all the texts representing the smile face ":-)" in the activity title by the smiley icons, do as follows:
Firstly, create the SmileyProcessor class by extending the BaseActivityProcessorPlugin.
package org.exoplatform.social.core.activitystream;
import org.exoplatform.social.core.BaseActivityProcessorPlugin;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.social.core.activity.model.ExoSocialActivity;
public class SmileyProcessor extends BaseActivityProcessorPlugin {
private String smiley;
public SmileyProcessor(InitParams params) {
super(params);
this.smiley = "<img src={{{"}}}http://www.tombraider4u.com/pictures/smiley.gif{{{"}}}/>";
}
@Override
public void processActivity(ExoSocialActivity activity) {
String title = activity.getTitle();
activity.setTitle(title.replaceAll(":-)", this.smiley));
}
}
Then, register this processor by editing the configuration.xml file:
<external-component-plugins>
<target-component>org.exoplatform.social.core.manager.ActivityManager</target-component>
<component-plugin>
<name>SmileyProcessor</name>
<set-method>addProcessorPlugin</set-method>
<type>org.exoplatform.social.core.activitystream.SmileyProcessor</type>
<description/>
<init-params>
<values-param>
<name>priority</name>
<value>1</value>
</values-param>
</init-params>
</component-plugin>
</external-component-plugins>
The "init-params" contains all the key-value data which a processor will use to initialize. In the above configuration, the priority value indicates the order in which this processor is executed. If the value is 1, this processor will be used before all the remaining processors with the lower priority.
It is really easy to publish an RSS feed to a space's activity stream. Social provides FeedmashJobPlugin to publish the RSS feeds. As you can see in the project "exo.social.extras.feedmash", there are the JiraFeedConsumer and HudsonFeedConsumer samples to post Social project's feeds (jira and hudson) to a pre-defined space named exosocial in a specific portal container named socialdemo as in the configuration file:
<external-component-plugins>
<target-component>org.exoplatform.services.scheduler.JobSchedulerService</target-component>
<component-plugin>
<name>RepubSocialJiraActivityJob</name>
<set-method>addPeriodJob</set-method>
<type>org.exoplatform.social.extras.feedmash.FeedmashJobPlugin</type>
<description/>
<init-params>
<properties-param>
<name>mash.info</name>
<property name="feedURL" value="http://jira.exoplatform.org/plugins/servlet/streams?key=SOC"/>
<property name="categoryMatch" value="resolved|created"/>
<property name="targetActivityStream" value="space:exosocial"/>
<property name="portalContainer" value="socialdemo"/>
</properties-param>
<properties-param>
<name>job.info</name>
<description>save the monitor data periodically</description>
<property name="jobName" value="JIRAFeedConsumer"/>
<property name="groupName" value="Feedmash"/>
<property name="job" value="org.exoplatform.social.feedmash.JiraFeedConsumer"/>
<property name="repeatCount" value="0"/>
<property name="period" value="60000"/>
<property name="startTime" value="+45"/>
<property name="endTime" value=""/>
</properties-param>
</init-params>
</component-plugin>
<component-plugin>
<name>WatchSocialBuildStatus</name>
<set-method>addPeriodJob</set-method>
<type>org.exoplatform.social.extras.feedmash.FeedmashJobPlugin</type>
<description/>
<init-params>
<properties-param>
<name>mash.info</name>
<property name="feedURL" value="http://builder.exoplatform.org/hudson/view/social/job/social-trunk-ci/rssAll"/>
<property name="targetActivityStream" value="space:exosocial"/>
<property name="portalContainer" value="socialdemo"/>
</properties-param>
<properties-param>
<name>job.info</name>
<description>save the monitor data periodically</description>
<property name="jobName" value="HudsonFeedConsumer"/>
<property name="groupName" value="Feedmash"/>
<property name="job" value="org.exoplatform.social.feedmash.HudsonFeedConsumer"/>
<property name="repeatCount" value="0"/>
<property name="period" value="60000"/>
<property name="startTime" value="+100"/>
<property name="endTime" value=""/>
</properties-param>
</init-params>
</component-plugin>
</external-component-plugins>
Run Social with the URL: http://localhost:8080/socialdemo, then log in and create a space named "exosocial". After creating the "exosocial" space, all the feeds of the Social project on Jira and Hudson will be automatically published to the exosocial space.
See the following code snippet to know more details about how to publish an activity and add comments to an activity:
package org.exoplatform.social.introduction.activitystreamandexosocialactivity;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.social.core.activity.model.ActivityStream;
import org.exoplatform.social.core.activity.model.ExoSocialActivity;
import org.exoplatform.social.core.activity.model.ExoSocialActivityImpl;
import org.exoplatform.social.core.manager.ActivityManager;
import org.exoplatform.social.core.manager.IdentityManager;
import org.exoplatform.social.core.identity.model.Identity;
import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider;
public class IntroduceActivityStreamAndExoSocialActivity {
// Exo Log.
private final Log LOG = ExoLogger.getLogger(IntroduceActivityStreamAndExoSocialActivity.class);
// Demo identity.
private Identity demoIdentity;
// John identity.
private Identity johnIdentity;
// identityManager manages identities.
private IdentityManager identityManager;
// activityManager manages activities.
private ActivityManager activityManager;
// Portal container.
private PortalContainer container;
private final static String DEMO_NAME = "demo";
private final static String JOHN_NAME = "john";
private final static String DEFAULT_ACTIVITY_TITLE = "blabla";
private final static String DEFAULT_COMMENT_TITLE = "comment blah blah";
/**
* Constructor.
*/
public IntroduceActivityStreamAndExoSocialActivity() {
// Gets the current container.
container = PortalContainer.getInstance();
// Gets IdentityManager to handle an identity operation.
identityManager = (IdentityManager) container.getComponentInstanceOfType(IdentityManager.class);
// Gets ActivityManager to handle activity operation.
ActivityManager activityManager = (ActivityManager) container.getComponentInstanceOfType(ActivityManager.class);
// Gets or create demo's identity
demoIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, DEMO_NAME, false);
// Gets or creates the identity "john".
johnIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, JOHN_NAME, false);
}
/**
* Posts activity to activity stream
*/
public void introduceActivityStreamAndExoSocialActivity {
// Sets a string that specifies the primary text of an activity. This field is REQUIRED by ActivityManager. The title field may only have the following HTML tags: <b> <i>, <a>, <span>.
activity.setTitle(DEFAULT_ACTIVITY_TITLE);
// Sets this activity for demo.
activity.setUserId(demoIdentity.getId());
// Saves the activity.
activityManager.saveActivity(johnIdentity, activity);
// Gets activity stream.
ActivityStream activityStream = activity.getActivityStream();
// Type of the activity stream. It can be organization or space.
LOG.info("activity stream type: " + activityStream.getType());
LOG.info("activity stream id: " + activityStream.getId());
LOG.info("activity stream pretty id: " + activityStream.getPrettyId());
LOG.info("activity stream perma link: " + activityStream.getPermaLink());
LOG.info("activity stream id: " + activity.getStreamId());
LOG.info("activity stream owner: " + activity.getStreamOwner());
// Comment in Social
ExoSocialActivity demoActivity = new ExoSocialActivityImpl();;
activity.setTitle(DEFAULT_ACTIVITY_TITLE);
activityManager.saveActivity(demoIdentity, demoActivity);
ExoSocialActivity comment = new ExoSocialActivityImpl();;
comment.setTitle(DEFAULT_COMMENT_TITLE);
//Sets comment of demo
comment.setUserId(demoIdentity.getId());
//Saves a comment.
activityManager.saveComment(activity, comment);
}
}
Social supports the OpenSocial standard. So you can integrate OpenSocial gadgets in your dashboard and use the RPC or REST service to view or publish the social data. With the support for the OpenSocial standard, Social provides a framework for developers to build gadgets that can display and mash up activity information for contacts, social networks, applications and services.
Gadgets are web-based software components based on HTML, CSS, JavaScript; defined by using an XML declaration syntax. They allow developers to easily write social applications that work on the social networks supporting OpenSocial APIs without modification. See the following links for detailed information:
To know how to create an OpenSocial gadget, see here.
Gadgets will work out of the box on Dashboard. In eXo, gadgets are wrapped by GadgetWrapperPortlet so they can work as any other portlet applications. At present, Social supports OpenSocial Specification v1.1.
Social leverages Apache Shindig - an OpenSocial reference implementation to provide and extend OpenSocial APIs which is compatible with the common OpenSocial APIs which is supported by other big social networks like Ning, Hi5, Orkut and more.
To get more details about Supported APIs, refer to OpenSocial Specification.
Suppose that you are running the local host at port 8080 (http://localhost:8080/), the path of the API will be:
REST API:
http://localhost:8080/social/social/rest
RPC API:
http://localhost:8080/social/social/rpc
To learn what you can do with the APIs, have a look at the specification. If you are developing in Java, you can use the opensocial-java-client.
If you are using OpenSocial, you need to configure the OAuth authentication. With the case of eXo Platform, you need to edit the file: gatein/conf/portal/portal/configuration.xml and add the following configuration:
<component>
<key>org.exoplatform.social.opensocial.oauth.ServiceProviderStore</key>
<type>org.exoplatform.social.opensocial.oauth.ServiceProviderStore</type>
<init-params>
<properties-param>
<name>grails-book-flow</name>
<description>consumer key and secret for sample oauth provider. </description>
<property name="consumerKey" value="YOUR_KEY_HERE"/>
<property name="sharedSecret" value="YOUR_SECRET_KEY_HERE"/>
</properties-param>
</init-params>
</component>
consumerKey and sharedSecret are keys that need to be shared with the application which is doing the request.
This functionality is not available in the standard OpenSocial APIs.
Instead of publishing your activities to the group @self as usual, you will publish them to the group "space:spaceId" or "space:spacePrettyName".
After using the OpenSocial Java library and Groovy, your code will look like this:
def client = getOpenSocialClient()
//create your new activity
Activity activity = new Activity()
activity.body = "xx purchased the book xxx"
activity.title = "BookFlow Purchased"
//prepare the request that will create the activity
Request request = ActivitiesService.createActivity(activity);
//specify that the creation of this new activity is for the space bookflow
request.groupId = "space:bookflow";
client.send(request);
In the example above, the groupId is set to "space:bookflow" and bookflow is the name of the space.
Social provides a way to manage profile information, and connections between users. With the APIs provided, you can easily add, manage and customize information and relationships of users.
The identity allows identifying a unique social object. The Social objects can be person, group, application, or whatever related to social interactions, such as connecting, publishing an activity stream or holding a user profile.
Social provides IdentityProvider as an identiy mechanism for the third parties to extend Social's identity system without any limitation. Here is an example:
class SampleIdentityProvider extends OrganizationIdentityProvider{
public SampleIdentityProvider(OrganizationService organizationService) {
super(organizationService);
}
@Override
public void populateProfile(Profile profile, User user) {
profile.setProperty(Profile.FIRST_NAME, "this is first name");
profile.setProperty(Profile.LAST_NAME, "this is last name");
profile.setProperty(Profile.USERNAME, "this is user name");
profile.setUrl("/path/to/profile/");
}
}
In this example, the SampleIdentityProvider class extends OrganizationIdentityProvider which is the IdentityProvider used to connect to the portal user's base. In this class, the populateProfile method is overridden and some dummy data are added to the profile fields.
IdentityManager is the service used to manipulate the identity operations, such as creating, getting, deleting or finding a profile. You can get the IdentityManager via the ExoContainer. The following code will show how to get an IdentityManager instance and create a basic identity instance:
import org.exoplatform.container.ExoContainer;
import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.social.core.identity.IdentityManager;
import org.exoplatform.social.core.identity.impl.organization.OrganizationIdentityProvider;
import org.exoplatform.social.core.identity.model.Identity;
//......
String containerName = "portal";
String username = "zun";
//get container to get other registered components
ExoContainer container = ExoContainerContext.getContainerByName(containerName);
//get IdentityManager to handle identity operation
IdentityManager identityManager = (IdentityManager) container.getComponentInstanceOfType(IdentityManager.class);
//get ActivityManager to handle activity operation
ActivityManager activityManager = (ActivityManager) container.getComponentInstanceOfType(ActivityManager.class);
//create new user with name Zun
Identity userIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, username);
APIs provide notification interfaces which you can implement to create your own handlers for notification when having the profile modifications by extending the ProfileListenerPlugin class, or relationship changes by extending RelationshipListenerPlugin.
1. Create the ProfileLoggerListener class to log all profile modifications of the systems. The abstract class named ProfileListenerPlugin provides the interface to implement this method.
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.social.core.identity.lifecycle.ProfileListenerPlugin;
import org.exoplatform.social.core.identity.spi.ProfileLifeCycleEvent;
public class ProfileLoggerListener extends ProfileListenerPlugin{
private static final Log logger = ExoLogger.getExoLogger(ProfileLoggerListener.class);
@Override
public void avatarUpdated(ProfileLifeCycleEvent event) {
logger.info("@" + event.getUsername() + " profile has updated his basic profile info.");
}
@Override
public void basicInfoUpdated(ProfileLifeCycleEvent event) {
logger.info("@" + event.getUsername() + " profile has updated his basic profile info.");
}
@Override
public void contactSectionUpdated(ProfileLifeCycleEvent event) {
logger.info("@" + event.getUsername() + " profile has updated his contact info.");
}
@Override
public void experienceSectionUpdated(ProfileLifeCycleEvent event) {
logger.info("@" + event.getUsername() + " profile has an updated experience section.");
}
@Override
public void headerSectionUpdated(ProfileLifeCycleEvent event) {
logger.info("@" + event.getUsername() + " has updated his header info.");
}
}
2. Add some configurations to this class to the configuration.xml:
<external-component-plugins>
<target-component>org.exoplatform.social.core.identity.IdentityManager</target-component>
<component-plugin>
<name>ProfileLoggerListener</name>
<set-method>addProfileListener</set-method>
<type>path.to.ProfileLoggerListener</type>
</component-plugin>
</external-component-plugins>
Similarly, you can apply the above steps to implement RelationshipListenerPlugin for relationship notifications.
Relationship is the bridge between two identities in Social. There are many types of relationships defined in the Relationship class. With these types, a user can invite another user, confirm invitations or remove relationship.
The following code will show you how to invite a user to connect with another:
import org.exoplatform.container.ExoContainer;
import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.social.core.identity.IdentityManager;
import org.exoplatform.social.core.identity.impl.organization.OrganizationIdentityProvider;
import org.exoplatform.social.core.identity.model.Identity;
import org.exoplatform.social.core.relationship.Relationship;
import org.exoplatform.social.core.relationship.RelationshipManager;
public void inviteUser() throws Exception {
String containerName = "portal";
ExoContainer container = ExoContainerContext.getContainerByName(containerName);
IdentityManager identityManager = (IdentityManager) container.getComponentInstanceOfType(IdentityManager.class);
Identity invitedIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, "Hoat");
String invitedUserId = invitedIdentity.getId();
String currUserId = "Zun";
Identity currentIdentity = identityManager.getOrCreateIdentity(OrganizationIdentityProvider.NAME, currUserId);
RelationshipManager relationshipManager = (RelationshipManager) container.getComponentInstanceOfType(RelationshipManager.class);
Relationship relationship = relationshipManager.invite( currentIdentity, invitedIdentity);
}
The following example will show you how to implement one of these interfaces and how to configure this plugin. The following step is similar to the Profile notifications implementation.
1. Create the RelationshipLoggerListener class:
import org.exoplatform.social.core.relationship.Relationship;
import org.exoplatform.social.core.relationship.lifecycle.RelationshipListenerPlugin;
import org.exoplatform.social.relationship.spi.RelationshipEvent;
public class RelationshipLoggerListener extends RelationshipListenerPlugin{
private static final Log logger = ExoLogger.getExoLogger(RelationshipLoggerListener.class);
@Override
public void confirmed(RelationshipEvent event) {
String[] names = getUserNamesFromEvent(event);
logger.info(names[0] +" confirmed the invitation of "+ names[1]);
}
@Override
public void ignored(RelationshipEvent event) {
String[] names = getUserNamesFromEvent(event);
logger.info(names[0] +" ignored the invitation of "+ names[1]);
}
@Override
public void removed(RelationshipEvent event) {
String[] names = getUserNamesFromEvent(event);
logger.info(names[0] +" removed the relationship with "+ names[1]);
}
private String[] getUserNamesFromEvent(RelationshipEvent event){
Relationship relationship = event.getPayload();
Identity id1 = relationship.getIdentity1();
Identity id2 = relationship.getIdentity2();
String user1 = "@" + id1.getRemoteId();
String user2 = "@" + id2.getRemoteId();
return new String[]{user1, user2 };
}
}
2. Add some configurations for this class in the configuration.xml file:
<external-component-plugins>
<target-component>org.exoplatform.social.core.relationship.RelationshipManager</target-component>
<component-plugin>
<name>RelationshipLoggerListener</name>
<set-method>addListenerPlugin</set-method>
<type>classpath.of.your.RelationshipLoggerListener</type>
</component-plugin>
</external-component-plugins>
Social provides a way to create groups and to share data and applications by spaces. A space has its own activity stream in which applications or members can publish information. In each space, members use applications together with shared data.
To manipulate the spaces, you will use the SpaceService. To get an instance of this class, you need to get the current PortalContainer instance.
The following example will show how to create a space:
package org.exoplatform.social.sample;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.social.application.impl.DefaultSpaceApplicationHandler;
import org.exoplatform.social.space.Space;
import org.exoplatform.social.space.SpaceException;
import org.exoplatform.social.space.SpaceService;
public class SpaceCreationSample {
public void createSpace() throws SpaceException {
String spaceName = "mySpace";
String creator = "jeremi";
PortalContainer container = PortalContainer.getInstance();
SpaceService spaceService = (SpaceService) container.getComponentInstanceOfType(SpaceService.class);
// verify if there is no space already created
Space space = spaceService.getSpaceByDisplayName(spaceName);
if (space == null) {
space = new Space();
space.setDisplayName(spaceName);
space.setRegistration(Space.OPEN);
space.setDescription("space description");
//DefaultSpaceApplicationHander is the default implementation of SpaceApplicationHandler. You can create your own by extending SpaceApplicationHandler. The default type is "classic" (DefaultSpaceApplicationHandler.NAME = clasic)
space.setType(DefaultSpaceApplicationHandler.NAME);
//create the space
space = spaceService.createSpace(space, creator);
//initialize the applications
spaceService.initApps(space);
}
}
}
The management of space's applications includes 2 specific actions:
You can add portlet or gadget applications to spaces. Once added, all members of the space can use that application. The following code shows you how to add an application to a space:
public void addApplicationToSpace() throws SpaceException {
//Your portlet name
String appId = "SocialBannerPortlet";
String spaceId = "zunSpace";
//get container to get other registered components
PortalContainer container = PortalContainer.getInstance();
//get space service for installing operations
SpaceService spaceService = (SpaceService) container.getComponentInstanceOfType(SpaceService.class);
//install application for the space
spaceService.installApplication(spaceId, appId);
//you must activate installed application to be able to use it
spaceService.activateApplication(spaceId, appId);
}
appId is the portlet or gadget name as defined in portlet.xml or gadget.xml in the web-app. You can find it in social-portlet.war and social.war.
You can remove portlet or gadget applications from a space and the members of this space will not see them anymore. The following code shows you how to remove an application from a space:
public void removeApplicationFromSpace() throws SpaceException {
//Your portlet name
String appId = "SocialBannerPortlet";
String appName = "SocialBannerPortlet1"
String spaceId = "zunSpace";
//get container to get other registered components
PortalContainer container = PortalContainer.getInstance();
//get space service for installing operations
SpaceService spaceService = (SpaceService) container.getComponentInstanceOfType(SpaceService.class);
//install application for the space
spaceService.removeApplication(spaceId, appId, appName);
}
SpaceService allows you to manage the spaces' members. Here is the way to add a new member to a space:
String spacePrettyName = "mySpace";
PortalContainer container = PortalContainer.getInstance();
SpaceService spaceService = (SpaceService) container.getComponentInstanceOfType(SpaceService.class);
Space space = service.getSpaceByPrettyName(spacePrettyName);
if (space != null) {
spaceService.addMember(space, "mary");
}
To receive notifications of what are happening in spaces, you need to extend SpaceListenerPlugin and register it. Every method takes a SpaceLifeCycleEvent object as a parameter that contains the information about the event and its context.
The available events are:
spaceCreated: This event is called right after a space is created successfully with its applications.
spaceRemoved: This event is called right after the space is removed. It means all the applications of the space are removed, its group and group navigation are removed.
applicationAdded: This event is called right after an application is added (installed) to the space.
applicationActivated: This event is called right after an application is activated in the space.
applicationDeactivated: This event is called right after an application is deactivated.
applicationRemoved: This event is called right after an application is removed from the space.
joined: This event is called right after a user joins the space.
left: This event is called right after a space member leaves its space.
grantedLead: This event is called right after a user is granted the space's manager role.
revokedLead: This event is called right after the space's manager is revoked his role to be a space member.
import org.exoplatform.social.space.lifecycle.SpaceListenerPlugin;
public class MySpaceListenerPlugin extends SpaceListenerPlugin {
...
}
As an example, see SpaceActivityPublisher that publishes an activity based on an event that happened in a space.
To register your listener, configure it as a plugin to the SpaceService like this:
<external-component-plugins>
<target-component>org.exoplatform.social.core.space.spi.SpaceService</target-component>
<component-plugin>
<name>SpaceActivityPublisher</name>
<set-method>addSpaceListener</set-method>
<type>org.mycompany.MySpaceListenerPlugin</type>
</component-plugin>
</external-component-plugins>
The Social widget enables developers to add capabilities of Social to external applications. Since the widget is hosted on your Social server, it can display personalized information. An activity stream of the most recent user actions will display to the group's members.
There are two options of the Social widget that provide different levels of integration and information.
The basic version of this widget is an iFrame. The more advanced version is a button you can insert in a page; this will display a small pop-up with information about the space.
To insert the basic version, you need to have an iFrame to insert on your site.
<iframe scrolling="no" height="180" frameborder="no" width="220" src="http://URL_OF_YOUR_EXO_INSTALLATION.COM/rest/private/spaces/portal/space_info? spaceName=NAME_OF_YOUR_SPACE&description=DESCRIPTION_OF_THE_SPACE"></iframe>
To install this version in your application, replace all the uppercase text below:
URL_OF_YOUR_EXO_INSTALLATION.COM: This is the URL of your Social installation. If you are testing on your local computer, the URL may be localhost:8080.
NAME_OF_YOUR_SPACE: This is the title of your space in Social. In the URL, it is necessary to avoid special characters. For the space name, you can only use alphanumeric characters and "_", ".", "-" or ".".
DESCRIPTION_OF_THE_SPACE: This will be displayed in the list of spaces.
To install an advanced version of the widget, you need to insert a code snippet in your page. This includes some HTMLs plus some JavaScript. The necessary CSS will be added dynamically.
Next, insert the following code at the position you want the button to be displayed:
<div class="exoSpacesContainer"><a href="javascript:void(0);" id="exoSpacesLink" class="exoSpacesLink" target="_blank">Space</a></div> <script src="/socialWidgetResources/javascript/space.js"></script> <script>spaces.createPopup("exoSpacesLink", "MyAppName - my social object", "my cool description");</script>
The important function here is:
spaces.createPopup(link, spaceName, description)
In which:
link is the ID or the HTMLElement where the pop-up will be placed. If you copy and paste the code snippet provided above, you do not need to change this value.
spaceName is the name of space. It is also used to identify the space. You should use the following format: "MyAppName - my social object".
description is a brief introduction about your space.
serverURL (Default: "http://127.0.0.1:8080"): The address of your eXo installation. To change it, use spaces.setServerURL(...).
spaceServicePath (Default: "/rest/private/spaces/"): The path to the spaces service. It is rare you have to change it; but if needed, use spaces.setSpaceServicePath(...).
portalName (Default: "socialdemo"): The name of portal you are using. To change it, use spaces.setPortalName(...).
If you want to change any part of this configuration, the best way is to change before creating the pop-up. For example:
<div class="exoSpacesContainer"><a href="#" id="exoSpacesLink" class="exoSpacesLink" target="_blank">Space</a></div> <script src="/socialWidgetResources/javascript/space.js"></script> <script> spaces.setServerURL("http://192.168.2.100:8080"); spaces.createPopup("exoSpacesLink", "My cool new space", "my cool description"); </script>
You can see an example of integration at: http://localhost:8080/socialWidgetResources/test.html
In this section, you will learn how to implement a preprocessor for activities rendering.
To understand this section, the knowledge of Java and eXo Kernel (component model and its XML configuration) is prerequisite.
A simple activity is made of simple text. An extension point has been created at the level of activities rendering for two cases:
support more HTML tags.
support @mentions.
But you may want to support a special syntax, for example:
#hashtags to feel like Twitter.
smileys to look like Skype.
Markdown to experience Buzz.
You can have more sophisticated cases to process, such as parsing the link that include in the activity's content. Because a process actually has the full access to the Activity, you can very well process based on the owner, app, and media item.
Social lets you pre-process an activity before it is returned by the ActivityManager. To do this, you simply need to implement the interface ActivityProcessor:
/**
* An activity processor is responsible to pre-process an activity before it is returned by the {@link ActivityManager}
*/
public interface ActivityProcessor {
/**
* Process an activity
* @param activity the activity. It can be modified
*/
void processActivity(Activity activity);
/**
* Priority of this processor.
* All activity processors will be executed in ascending priority order
* @return
*/
int getPriority();
}
For example, the following shows you how to implement a SmileyProcessor that will replace text smileys by icons:
public class SmileyProcessor implements ActivityProcessor {
String smiley = "<img src='/images/smiley.gif'/>";
public void processActivity(Activity activity) {
String title = activity.getTitle();
activity.setTitle(title.replaceAll(":-\)", smiley));
}
public int getPriority() {
return 100;
}
}
Now, you have a nice procesor, so need to hook it to the system. At runtime, the processors can be attached to ActivityManager via the addProcessor(ActivityProcessor) method.
But there is also a component plugin hooked for it: public void addProcessorPlugin(BaseActivityProcessorPlugin plugin).
So, to make your processor easy to hook, you simply need to let him extend the BaseActivityProcessorPlugin.
public class SmileyProcessor extends BaseActivityProcessorPlugin {
String smiley = "<img src='/images/smiley.gif'/>";
public SmileyProcessor(InitParams params) {
super(params);
}
public void processActivity(Activity activity) {
String title = activity.getTitle();
activity.setTitle(title.replaceAll(":-\)", smiley));
}
}
It will have the additional benefit to make the priority field configurable, so you do not need to implement getPriorty().
Then your processor can be configured as a component plugin like this:
<external-component-plugins>
<target-component>org.exoplatform.social.core.activitystream.ActivityManager</target-component>
<component-plugin>
<name>SmileyProcessor</name>
<set-method>addProcessorPlugin</set-method>
<type>org.example.SmileyProcessor</type>
<init-params>
<value-param>
<name>priority</name>
<description>priority of this processor (lower are executed first)</description>
<value>2</value>
</value-param>
</init-params>
</component-plugin>
</external-component-plugins>
Restart, then place the smiley images on the server and you should see something like that:
This section shows you the way to change the content of input texts by using and extending the XMLProcessor component and its plugins.
This service processes the input texts in the system by pushing it through a filter (plugin) chain and returns a result as the diagram below:
Each filter is responsible for enriching the content of the input texts. For example, highlight usernames existing in a user's connection or remove the forbidden HTML tags.
The XMLProcessor component is configured in the config/src/main/java/conf/social/common-configuration.xml file:
<component>
<key>org.exoplatform.social.common.xmlprocessor.XMLProcessor</key>
<type>org.exoplatform.social.common.xmlprocessor.XMLProcessorImpl</type>
</component>
To manage the chain of the filters in XMLProcessor, you can use the addFilterPlugin() and removeFilterPlugin() methods. XMLProcessor is initialized by IOC (Invesion of Control) via the configuration files defined in the /demo/war/src/main/webapp/WEB-INF/conf/socialdemo/social/component-plugins-configuration.xml path.
<external-component-plugins>
<target-component>org.exoplatform.social.common.xmlprocessor.XMLProcessor</target-component>
<component-plugin>
<name>URLConverterFilterPlugin</name>
<set-method>addFilterPlugin</set-method>
<type>org.exoplatform.social.common.xmlprocessor.filters.URLConverterFilterPlugin</type>
<init-params>
<value-param>
<name>urlMaxLength</name>
<description>the max length of URL</description>
<value>-1</value>
</value-param>
</init-params>
</component-plugin>
</external-component-plugins>
In Social, there are the following built-in XMLProcessor plugins (also known as filters) that filter the input texts of users.
Filters | Description |
---|---|
DOMContentEscapeFilter | Process the DOM tree input and escape all text nodes. |
DOMLineBreakerFilter | Process the DOM tree input and add <br /> to all text nodes which contain \n. |
DOMXMLTagFilter | Process the DOM tree input and convert all tag nodes which do not exist in the allowed tags list into text Node. |
LineBreakerFilter | Process the String input and replace \n to <br />. |
XMLBalancer | Process the String input and add missing close tags to input. |
XMLTagFilter | Process the String input and convert all tags which do not exist in the allowed tags list into the escapsed String. |
The following is the general Class diagram of XMLProcesscor in Social:
All of these filters implements the Filter interface as follows:
package org.exoplatform.social.common.xmlprocessor;
public interface Filter {
/**
* Filters the input data.
*
* @param input the input data
* @return an Object with the result after filtered
*/
public Object doFilter(Object input);
}
These filters will process the input texts in the doFilter(Object input) method and return the result to XMLProcessor. They are declared in the configuration files found in the /demo/war/src/main/webapp/WEB-INF/conf/socialdemo/social/component-plugins-configuration.xml path.
<external-component-plugins>
<target-component>org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy</target-component>
<component-plugin>
<name>setAllowedTagPlugin</name>
<set-method>setAllowedTagPlugin</set-method>
<type>org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTagPlugin</type>
<init-params>
<object-param>
<name>b tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>b</string></field>
</object>
</object-param>
<object-param>
<name>i tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>i</string></field>
</object>
</object-param>
<object-param>
<name>a tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>a</string></field>
<field name="tagAttributes">
<collection item-type="java.lang.String" type="java.util.HashSet">
<value><string>href</string></value>
</collection>
</field>
</object>
</object-param>
<object-param>
<name>span tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>span</string></field>
</object>
</object-param>
<object-param>
<name>em tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>em</string></field>
</object>
</object-param>
<object-param>
<name>strong tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>strong</string></field>
</object>
</object-param>
<object-param>
<name>p tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>p</string></field>
</object>
</object-param>
<object-param>
<name>ol tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>ol</string></field>
</object>
</object-param>
<object-param>
<name>ul tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>ul</string></field>
</object>
</object-param>
<object-param>
<name>li tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>li</string></field>
</object>
</object-param>
<object-param>
<name>br tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>br</string></field>
</object>
</object-param>
<object-param>
<name>img tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>img</string></field>
<field name="tagAttributes">
<collection item-type="java.lang.String" type="java.util.HashSet">
<value><string>src</string></value>
</collection>
</field>
</object>
</object-param>
<object-param>
<name>blockquote tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>blockquote</string></field>
</object>
</object-param>
<object-param>
<name>q tag</name>
<object type="org.exoplatform.social.common.xmlprocessor.model.XMLTagFilterPolicy$AllowedTag">
<field name="tagName"><string>q</string></field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
You can write your own filter by implementing the Filter interface and add it to XMLProcessor as the sample code in the XMLProccessor Component section.
This section will show you how to internationalize activities in Social.
In the previous versions, Social had hard-coded messages for activities, such as creating spaces, granting the "manager" role to a member, sending connection request to another user, updating a user's profile/avatar, and more. And now, to internationalize these types of messages, you can use resource bundles and I18NActivityProcessor.
For example, to internationalize an activity of the exosocial:spaces type that is for space creation message, do as follows:
1. Set titleId for the ExoSocialActivity model.
ActivityType = exosocial:spaces, titleId = space_created, resource bundle key file: locale.social.Core, and associated message bundle key:SpaceActivityPublisher.space_created
The titleId is used to map with a corresponding message bundle key via the configuration.
Sample code for saving internationalized activities
public void saveActivity() {
ActivityManager activityManager = (ActivityManager) PortalContainer.getInstance().getComponentInstanceOfType(ActivityManager.class);
ExoSocialActivity activity = new ExoSocialActivityImpl();
activity.setType("exosocial:spaces"); // the associated activity type
activity.setTitleId("space_created"); // to indicate this is i18n activity type
// this is the fallback activity title when it's not i18n-ized.
// This must be required.
activity.setTitle("Test was created by @john");
//template params are used to for compound messages
// with message bundle key:
// SpaceActivityPublisher.space_created={0} was created by {1}.
Map<String, String> templateParams = new LinkedHashMap<String, String>();
templateParams.put("space_name", "Test");
templateParams.put("user", "@john");
//must indicate this param if you want a template value is processed by activity processors
templateParams.put(BaseActivityProcessorPlugin.TEMPLATE_PARAM_TO_PROCESS, "user");
activity.setTemplateParams(templateParams);
//gets the target stream to post
IdentityManager identityManager = (IdentityManager) PortalContainer.getInstance().getComponentInstanceOfType(IdentityManager.class);
Identity spaceIdentity = identityManager.getOrCreateIdentity(SpaceIdentityProvider.NAME, "test", false);
activity.setUserId(spaceIdentity.getId()); // the actor is the space identity
//posts this activity to space's activity stream
activityManager.saveActivityNoReturn(spaceIdentity, activity);
}
The sample code above is enough for creating an internationalized activity that will be displayed on the space activity stream portlet after all the configurations below are done. The returned result will be displayed in English like this: "Test was created by <a href="link-to-john-profile">John</a>".
2. Register the ActivityResourceBundlePlugin plugin to the I18NActivityProcessor component in the configuration file as the example below:
<external-component-plugins> <target-component>org.exoplatform.social.core.processor.I18NActivityProcessor</target-component> <component-plugin> <name>exosocial:spaces</name> <!-- activity type --> <set-method>addActivityResourceBundlePlugin</set-method> <type>org.exoplatform.social.core.processor.ActivityResourceBundlePlugin</type> <init-params> <object-param> <name>locale.social.Core</name> <!-- resource bundle key file --> <description>activity key type resource bundle mapping for exosocial:spaces</description> <object type="org.exoplatform.social.core.processor.ActivityResourceBundlePlugin"> <field name="activityKeyTypeMapping"> <map type="java.util.HashMap"> <entry> <key><string>space_created</string></key> <value><string>SpaceActivityPublisher.space_created</string></value> </entry> </map> </field> </object> </object-param> </init-params> </component-plugin> </external-component-plugins>
If the resource bundle message is compound, you must provide templateParams. The argument number will be counted as it appears on the map. For example:
templateParams = {"key1": "value1", "key2": "value2"} => arguments = ["value1", "value2"]
To reserve this order, LinkedHashMap must be used to create templateParams instead of HashMap.
3. Register an external resource bundle for that activity type to get an associated resource bundle as follow:
<external-component-plugins>
<target-component>org.exoplatform.services.resources.ResourceBundleService</target-component>
<component-plugin>
<name>Social Core Component Resource Bundle</name>
<set-method>addResourceBundle</set-method>
<type>org.exoplatform.services.resources.impl.BaseResourceBundlePlugin</type>
<init-params>
<values-param>
<name>classpath.resources</name>
<description>The resources that start with the following package name should be loaded from file system</description>
<value>locale.social.Core</value>
</values-param>
<values-param>
<name>portal.resource.names</name>
<description>The resources that start with the following package name should be loaded from file system</description>
<value>locale.social.Core</value>
</values-param>
</init-params>
</component-plugin>
</external-component-plugins>
If you do not have registered UI activity plugins, your activity messages will be internationalized and displayed by the default UI activity.
If you have registered ui activity plugins, you just need to display activity.getTitle() as it is already internationalized by BaseUIActivity.
In other cases, base on a provided locale as the code below:
I18NActivityProcessor i18NActivityProcessor = (I18NActivityProcessor) PortalContainer.getInstance().getComponentInstanceOfType(I18NActivityProcessor.class);
ExoSocialActivity processedActivity = i18NActivityProcessor.process(unprocessedActivity, chosenLocale);
Name | Service URL | Location | Description |
---|---|---|---|
ActivitiesRestService | {restContextName}/{portalName}/social/activities |
Maven groupId: org.exoplatform.social ArtifactId: exo.social.component.service | Provide REST services for activity applications: like/unlike; comment; delete activity. |
API:
Name | Service URL Endpoint | Parameters | Expected Values | Description |
---|---|---|---|---|
destroyActivity | {restContextName}/{portalName}/social/activities/destroy/{activityId}.{format} |
portalName activityId format |
String String String: json or xml | Destroy activity and get the JSON/XML format. |
showLikes | {restContextName}/{portalName}/social/activities/{activityId}/likes/show.{format} |
portalName activityId format |
String String String: json or xml | Show the list of likes by activityId and return the JSON/XML format. |
updateLike | {restContextName}/{portalName}/social/activities/{activityId}/likes/update.{format} |
portalName activityId format |
String String String: json or xml | Update the list of likes by the JSON/XML format. |
destroyLike | {restContextName}/{portalName}/social/activities/{activityId}/likes/destroy/{identity}.{format} |
portalName activityId identityId format |
String String String String: json or xml | Destroy like by identityId and get the JSON/XML format return format. |
showComments | {restContextName}/{portalName}/social/activities/{activityId}/likes/show.{format} |
portalName activityId format |
String String String: json or xml | Show the comment list by the JSON/XML format. |
updateComment | {restContextName}/{portalName}/social/activities/{activityId}/likes/update.{format} |
portalName activityId format |
String String String: json or xml | Update the comment by the JSON/XML format. |
destroyComment | {restContextName}/{portalName}/social/activities/{activityId}/comments/destroy/{commentId}.{format} |
portalName activityId commentId format |
String String String String: json or xml | Destroy comments and return the JSON/XML format. |
Example:
http://localhost:8080/rest-socialdemo/socialdemo/social/activities/s08d397dg6/likes/destroy/abc.json
Name | Service URL | Location | Description |
---|---|---|---|
AppsRestService | {restContextName}/social/apps/ |
Maven groupId: org.exoplatform.social ArtifactId: exo.social.component.service | Provide REST services for the application registry gadget: shows application list. |
API:
Name | Service URL Endpoint | Parameters | Expected Values | Description |
---|---|---|---|---|
showApps | {restContextName}/social/apps/show.{format} | format | String: json or xml | Show applications by the JSON/XML format. |
Example:
Name | Serive URL | Location | Description |
---|---|---|---|
IdentityRestService | restContextName}/{portalName}/social/identity/{username}/id |
Maven groupId: org.exoplatform.social ArtifactId: exo.social.component.service | Get identityId by the username. |
API:
Name | Service URL Endpoint | Parameters | Expected Values | Description |
---|---|---|---|---|
UserId getId | {restContextName}/{portalName}/social/identity/{username}/id/show.json |
username portalName |
String String | Get the identity by username and return by the JSON format. |
Example:
http://localhost:8080/rest-socialdemo/socialdemo/social/identity/john/id/show.json
Name | Service URL | Location | Description |
---|---|---|---|
LinkshareRestService | {restContextName}/social/linkshare |
Maven groupId: org.exoplatform.social ArtifactId: exo.social.component.service | Get information from a provided link. |
API:
Name | Service URL Endpoint | Parameters | Expected Values | Description |
---|---|---|---|---|
getLink | {restContextName}/social/linkshare/show.{format} | format | String: json or xml | Get the link content by posting a linkShare request. |
Example:
http://localhost:8080/rest-socialdemo/social/linkshare/show.json
Name | Service URL | Location | Description |
---|---|---|---|
PeopleRestService | {restContextName}/social/people |
Maven groupId: org.exoplatform.social ArtifactId: exo.social.component.service | Provide REST services for manipulating jobs related to people. |
API:
Name | Service URL Endpoint | Parameters | Expected Values | Description |
---|---|---|---|---|
suggestUsernames | {restContextName}/social/people/suggest.{format} |
nameToSearch currentUser typeOfRelation spaceURL format |
String String String String String: json or xml | Get and return a list of usernames which match the input string for suggest. |
Example: http://localhost:8080/rest-socialdemo/social/people/suggest.json
Name | Service URL | Location | Description |
---|---|---|---|
SpacesRestService | {restContextName}/{portalName}/social/spaces |
Maven groupId: org.exoplatform.social ArtifactId: exo.social.component.service | Provide REST services for space gadget to display users' spaces and pending spaces. |
API:
Name | Service URL Endpoint | Parameters | Expected Values | Description |
---|---|---|---|---|
showMySpaceList | {restContextName}/social/spaces/mySpaces/show.{format} |
portalName format |
String String: json or xml | Show mySpaceList by the JSON/XML format. |
showPendingSpaceList | {restContextName}/social/spaces/pendingSpaces/show.{format} |
portalName format |
String String: json or xml | Show pendingSpaceList by the JSON/XML format. |
suggestSpacenames | {restContextName}/social/spaces/spaceNames/suggest.{format} |
portalName conditionToSearch typeOfRelation currentUser format |
String String String String String: json or xml | Get and return space's names that match the input string for suggest. |
Example:
http://localhost:8080/rest-socialdemo/social/spaces/mySpaces/show.xml
Name | Service URL | Location | Description |
---|---|---|---|
WidgetRestService | {restContextName}/spaces/{containerName} |
Maven groupId: org.exoplatform.social ArtifactId: exo.social.extras.widget.rest | Provide REST services for creating spaces or getting spaces'information. |
API:
Name | Service URL Endpoint | Parameters | Expected Values | Description |
---|---|---|---|---|
spaceInfo | {restContextName}/spaces/{containerName}/space_info |
containerName portalName spacePrettyName description |
String String (default value: classic) String String | Return the HTML page for displaying the information of the space. Two query parameters needed: spaceName and description. |
Example:
http://localhost:8080/rest-socialdemo/spaces/socialdemo/space_info?name=Social&description=Social
Objectives:
The third parties want to integrate and extend the Social capability and features and Social REST Services APIs are dedicated for them to complete that. By using these REST APIs, the third parties can write any applications (desktop apps, mobile apps, web apps) to integrate with Social services and business.
Conventions:
The entry point for Social Rest service must be: /{rest_context_name}/private/api/social/{version}/{portalContainerName}/{social_resources}/. An example of activities resources: /rest/private/api/social/v1-alpha3/portal/activity/.
There are 3 types of parameters on each URL:
{server_params}: this is the unchanged parameter for a specified server.
:id: this param is for a specified data object, for example, activity Id and identity Id.
format: this is the supported data format. It can be JSON, XML, RSS, or ATOM.
Notes:
Currently, only the basic authentication is supported. Please see more details at http://en.wikipedia.org/wiki/Basic_access_authentication.
The JSON support is mandatory. The other format SHOULD be supported too (XML, RSS, ATOM). The supported formats will be specified by the detailed documentation for the REST resources.
The rest_context_name and portal_container_name parameters are used as follows:
In Social standalone:
rest_context_name: rest-socialdemo;
portal_container_name: socialdemo;
In eXo Platform:
rest_context_name: rest;
portal_container_name: portal;
Description: Gets an activity object from a specified activity Id.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity/{activityId}.{format}
Requires Authentication: true
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
activityId: the specified activity Id
format: the expected returned format
Optional (query paramters):
poster_identity: When this parameter is set to true, t or 1, the returned activity will provide more information for the user who posted this activity.
number_of_comments: Specifies the number of comments to be displayed along with this activity. By default, numberofcomments=0. If numberofcomments is a positive number, this number is considered as a limit number that must be equal or less than 100. If the actual number of comments is less than the provided positive number, the number of actual comments must be returned. If the total number of comments is more than 100, it is recommended to use activity/:id/comments.format instead.
activity_stream: When this parameter is set to true, t or 1, the returned activity will provide more information for the activity stream that this activity belongs to.
number_of_likes: Specifies the number of latest detailed likes to be returned along with this activity. By default, number_of_likes=0. If number_of_likes is a positive number, this number is considered as a limit number that must be equal or less than 100. If the total number of likes is less than the provided positive number, the number of actual likes must be returned. If the total number of likes is more than 100, it is recommended to use activity/:activityId/likes.format instead.
Request:
GET: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/portal/activity/1a2b3c4d5e6f7g8h9i.json
Response:
{ "id": "1a2b3c4d5e6f7g8h9j", "title": "Hello World!!!", "appId": "", "type": "exosocial:core", "postedTime": 123456789, //timestamp "createdAt": "Fri Jun 17 06:42:26 +0000 2011", //The Date follows ISO 8601 "priority": 0.5, //between 0.0 and 1.0, higher value => higher priority. "templateParams": {}, "titleId": "", "identityId": "123456789abcdefghi", //the identity id of the user who created this activity "liked": true, //is liked (favorites) by this authenticated identity "likedByIdentities": ["identityId1", "identityId2"], "posterIdentity": {}, //optional "comments": [{}, {}, {}], //optional "totalNumberOfComments": 1234, "activityStream": { "type": "user", // or "space" "prettyId": "root", // or space_abcde "faviconURL": "http://demo3.exoplatform.org/favicons/exo-default.jpg", "title": "Activity Stream of Root Root", "permaLink": "http://cloud-workspaces.com/profile/root" } //optional }
Description: Creates an activity to an identity's activity stream. If no identityid is specified, the activity will be created to the authenticated identity's activity stream.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity.{format}
Requires Authentication: true
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
format: the expected returned format
Optional (query paramters):
identity_id: the optional identity stream to post this new activity to
Request:
POST: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/portal/activity.json BODY: {"title": "Hello World!!!"}
Response:
{ "id": "1a2b3c4d5e6f7g8h9j", "title": "Hello World!!!", "appId": "", "type": "exosocial:core", "postedTime": 123456789, //timestamp "createdAt": "Fri Jun 17 06:42:26 +0000 2011", "priority": 0.5, //between 0.0 and 1.0, higher value => higher priority. "templateParams": {}, "titleId": "", "identityId": "123456789abcdefghi" //the identity id of the user who created this activity }
Description: Deletes an existing activity by its Id using the DELETE method. The deleted activity information will be returned in the JSON format.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity/{activityId}.{format}
Requires Authentication: true
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
activityId: the specified activity id
format: the expected returned format
Optional (query paramters): No
Request:
DELETE: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/portal/activity/1a2b3c4d5e6f7g8h9i.json
Response:
{ "id": "1a2b3c4d5e6f7g8h9j", "title": "Hello World!!!", "appId": "", "type": "exosocial:core", "postedTime": 123456789, //timestamp "createdAt": "Fri Jun 17 06:42:26 +0000 2011", //The Date follows ISO 8601 "priority": 0.5, //between 0.0 and 1.0, higher value => higher priority. "templateParams": {}, "titleId": "", "identityId": "123456789abcdefghi", //the identity id of the user who created this activity "liked": true, //is liked (favorites) by this authenticated identity "likedByIdentities": ["identityId1", "identityId2"], "posterIdentity": {}, //optional "comments": [{}, {}, {}], //optional "totalNumberOfComments": 1234, //if comments is required, the total number of comments "activityStream": { "type": "user", // or "space" "prettyId": "root", // or space_abcde "faviconURL": "http://demo3.exoplatform.org/favicons/exo-default.jpg", "title": "Activity Stream of Root Root", "permaLink": "http://cloud-workspaces.com/profile/root" } //optional }
Description: Deletes an existing activity by its Id using the POST method. The deleted activity information will be returned in the JSON format. It is recommended to use the DELETE method, except the case that clients cannot make request via this method.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity/destroy/{activityId}.{format}
Requires Authentication: true
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
activityId: the specified activity id
format: the expected returned format
Optional (query paramters): No
Request:
POST: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/portal/activity/destroy/1a2b3c4d5e6f7g8h9i.json
Response:
{ "id": "1a2b3c4d5e6f7g8h9j", "title": "Hello World!!!", "appId": "", "type": "exosocial:core", "postedTime": 123456789, //timestamp "createdAt": "Fri Jun 17 06:42:26 +0000 2011", //The Date follows ISO 8601 "priority": 0.5, //between 0.0 and 1.0, higher value => higher priority. "templateParams": {}, "titleId": "", "identityId": "123456789abcdefghi", //the identity id of the user who created this activity "liked": true, //is liked (favorites) by this authenticated identity "likedByIdentities": ["identityId1", "identityId2"], "posterIdentity": {}, //optional "comments": [{}, {}, {}], //optional "totalNumberOfComments": 1234, //if comments is required, the total number of comments "activityStream": { "type": "user", // or "space" "prettyId": "root", // or space_abcde "faviconURL": "http://demo3.exoplatform.org/favicons/exo-default.jpg", "title": "Activity Stream of Root Root", "permaLink": "http://cloud-workspaces.com/profile/root" } //optional }
Description: Gets the comments on an activity.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity/{activityId}/comments.{format}
Requires Authentication: true
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
activityId: the specified activity id
format: the expected returned format
Optional (query paramters): No
Request:
GET: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/portal/activity/1a2b3c4d5e/comments.json
Response:
{ total: 10, comments: [ { "id": "123456" "identityId": "12345abcde", "text": "Comment there!", "postedTime": 123456789, "createdAt": "Fri Jun 17 06:42:26 +0000 2011" }, { "id" : "234567" "identityId": "12345abcde", "text": "Comment there 2!", "postedTime": 123456789, "createdAt": "Fri Jun 17 06:42:26 +0000 2011" } ] }
Description: Posts a new comment on an existing activity. The poster of this comment is an authenticated identity.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity/{activityId}/comment.{format}
Requires Authentication: true
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
activityId: the specified activity id
format: the expected returned format
Optional (query paramters): No
Request:
POST: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/portal/activity/1a2b3c4d5e/comment.json BODY: {"text": "My comment here!!!"}
Response:
{ "id": "123456" "identityId": "12345abcde", "text": "My comment here!!!", "postedTime": 123456789, "createdAt": "Fri Jun 17 06:42:26 +0000 2011" }
Description: Deletes an existing comment by its Id.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity/{activityId}/comment/{commentId}.{format}
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
activityId: the specified activity id
format: the expected returned format
commentId:
Optional (query paramters): No
Request:
DELETE: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/portal/activity/1a2b3c4d5e/comment/123456.json
Response:
{ "id": "123456" "identityId": "12345abcde", "text": "My comment here!!!", "postedTime": 123456789, "createdAt": "Fri Jun 17 06:42:26 +0000 2011" }
Description: Deletes an existing comment by its Id using the POST method. The deleted activity information will be returned in the JSON format. It is recommended to use the POST method, except the case that clients cannot make request via this method.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity/{activityId}/comment/destroy/{commentId}.{format}
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
activityId: the specified activity id
format: the expected returned format
commentId: the specified comment id
Optional (query paramters): No
Request:
POST: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/portal/activity/1a2b3c4d5e/comment/destroy/123456.json
Response:
{ "id": "123456" "identityId": "12345abcde", "text": "My comment here!!!", "postedTime": 123456789, "createdAt": "Fri Jun 17 06:42:26 +0000 2011" }
Description: Gets all the identities who like an existing activity.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity/{activityId}/likes.{format}
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
activityId: the specified activity id
format: the expected returned format
Optional (query paramters): No
Request:
GET: http://localhost:8080/rest-socialdemo/private/api/social/v1-alpha3/socialdemo/activity/1a2b3c4d5e/likes.json
Response:
{ totalNumberOfLikes: 2, likesByIdentities: [ { "id":1234567, "providerId":"organization", "remoteId":"demo", "profile": { "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } }, { "id":23456, "providerId":"organization", "remoteId":"root", "profile": { "fullName":"Root GTN", "avatarUrl":"http://localhost:8080/profile/u/root/avatar.jpg?u=12345" } }, ] }
Description: Allows an authenticated identity to do the "like" action on an existing activity.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity/{activityId}/like.{format}
Requires Authentication: true
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
activityId: the specified activity id
format: the expected returned format
Optional (query paramters): No
Request:
POST: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/portal/activity/1a2b3c4d5e/like.json
Response:
{ "liked": true }
Description: Allows an identity to remove his "like" action on an activity.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity/{activityId}/like.{format}
Requires Authentication: true
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
activityId: the specified activity id
format: the expected returned format
Optional (query paramters): No
Request:
DELETE: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/portal/activity/1a2b3c4d5e/like.json
Response:
{ "liked": false }
Description: Allows an identity to remove his "like" action on an activity. It is recommended to use the DELETE method, except the case that clients cannot make request via this method.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity/{activityId}/like/destroy.{format}
Requires Authentication: true
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
activityId: the specified activity id
format: the expected returned format
Optional (query paramters): No
Request:
POST: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/portal/activity/1a2b3c4d5e/like/destroy.json
Response:
{ "liked": false }
Description: Gets activities of a defined identity which can be a user identity, a space identity, or any type of identities. There is one special identityId called "me" which stands for the authenticated user who makes this request.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity_stream/{identityId}.{format}
Parameters:
Required (path parameters):
portalContainerName: the portal container name
identityId: The identity id. There is one special identityId: "me" standing for the authenticated user who make this request.
format: The response format type, for example: json, xml...
Optional (query paramters):
limit: The number of activities retrieved with the default value of 100. This input value must be less than or equal to its default value (100). The number of the returned results is actually less than or equal to the limit value. If no specified, 100 will be the default value.
since_id: Returns the activities having the created timestamps greater than the specified since_id 's created timestamp.
max_id: Returns the activities having the created timestamps less than the specified max_id's created timestamp. Note that since_id and max_id must not be defined in one request, if they are, the since_id query param is chosen.
number_of_comments: Specifies the number of latest comments to be displayed along with each activity. By default, number_of_comments=0. If number_of_comments is a positive number, this number is considered as a limit number that must be equal or less than 100. If the total number of comments is less than the provided positive number, the number of actual comments must be returned. If the total number of comments is more than 100, it is recommended to use activity/:activityId/comments.format instead.
number_of_likes: Specifies the number of latest detailed likes to be returned along with this activity. By default, number_of_likes=0. If number_of_likes is a positive number, this number is considered as a limit number that must be equal or less than 100. If the total number of likes is less than the provided positive number, the number of actual likes must be returned. If the total number of likes is more than 100, it is recommended to use activity/:activityId/likes.format instead.
Request:
GET: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/socialdemo/activity_stream/f92cd6f0c0a80137102696ac26430766.json?limit=30&since_id=12345&number_of_likes=5
Response:
{ "activities":[ { "id":"1a2b3c4d5e6f7g8h9j", "title":"Hello World!!!", "appId":"", "type":"DEFAULT_ACTIVITY", "postedTime":123456789, "createdAt":"Fri Jun 17 06:42:26 +0000 2011", "priority":0.5, "templateParams":{ }, "titleId": "", "body": "", "identityId":"123456789abcdefghi", "liked":true, "likedByIdentities":[ { "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } } ], "totalNumberOfLikes":20, "posterIdentity":{ "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } }, "comments":[ { } ], "totalNumberOfComments":1234, "activityStream":{ "type":"user", "prettyId":"root", "fullName": "Root Root", "faviconUrl":"http://demo3.exoplatform.org/favicons/exo-default.jpg", "title":"Activity Stream of Root Root", "permaLink":"http://localhost:8080/profile/root" } }, { "id":"1a210983123f7g8h9j", "title":"Hello World 1!!!", "appId":"", "type":"DEFAULT_ACTIVITY", "postedTime":123456789, "createdAt":"Fri Jun 19 06:42:26 +0000 2011", "priority":0.5, "templateParams":{ }, "titleId":"", "body": "", "identityId":"123456789abcdefghi", "liked":true, "likedByIdentities":[ { "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } } ], "totalNumberOfLikes":20, "posterIdentity":{ "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } }, "comments":[ { } ], "totalNumberOfComments":1234, "activityStream":{ "type":"user", "prettyId":"root", "fullName": "Root Root", "faviconUrl":"http://demo3.exoplatform.org/favicons/exo-default.jpg", "title":"Activity Stream of Root Root", "permaLink":"http://localhost:8080/profile/root" } } ] }
Description: Gets the activity stream feed of the authenticated user identity who makes this request.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity_stream/feed.{format}
Parameters:
Required (path parameters):
portalContainerName: The portal container name
format: The response format type, for example: json, xml...
Optional (query paramters):
limit: Specifies the number of activities to retrieve. Must be less than or equal to 100. The value you pass as limit is a maximum number of activities to be returned. The actual number of activities you receive maybe less than limit. If no specified, 100 will be the default value.
since_id: Returns the activities having the created timestamps greater than the specified sinceId's created timestamp
max_id: Returns the activities having the created timestamp less than the specified maxId's created timestamp. Note that sinceId and maxId must not be defined in one request, if they are, the sinceId query param is chosen.
number_of_comments: Specifies the latest number of comments to be displayed along with each activity. By default, numberOfComments=0. If numberOfComments is a positive number, this number is considered as a limit number that must be equal or less than 100. If the actual number of comments is less than the provided positive number, the number of actual comments must be returned. If the total number of comments is more than 100, it's recommended to use: "activity/:activityId/comments.format" instead
number_of_likes: Specifies the latest number of detailed likes to be returned along with this activity. By default, numberOfLikes=0. If numberOfLikes is a positive number, this number is considered as a limit number that must be equal or less than 100. If the actual number of likes is less than the provided positive number, the number of actual likes must be returned. If the total number of likes is more than 100, it's recommended to use: "activity/:activityId/likes.format" instead.
Request:
GET: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/socialdemo/activity_stream/feed.json?limit=30&since_id=12345&number_of_comments=5&number_of_likes=5
Response:
{ "activities":[ { "id":"1a2b3c4d5e6f7g8h9j", "title":"Hello World!!!", "appId":"", "type":"DEFAULT_ACTIVITY", "postedTime":123456789, "createdAt":"Fri Jun 17 06:42:26 +0000 2011", "priority":0.5, "templateParams":{ }, "titleId":"", "body": "", "identityId":"123456789abcdefghi", "liked":true, "likedByIdentities":[ { "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } } ], "totalNumberOfLikes":20, "posterIdentity":{ "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } }, "comments":[ { } ], "totalNumberOfComments":1234, "activityStream":{ "type":"user", "prettyId":"root", "fullName": "Root Root", "faviconUrl":"http://demo3.exoplatform.org/favicons/exo-default.jpg", "title":"Activity Stream of Root Root", "permaLink":"http://localhost:8080/profile/root" } }, { "id":"1a210983123f7g8h9j", "title":"Hello World 1!!!", "appId":"", "type":"DEFAULT_ACTIVITY", "postedTime":123456789, "createdAt":"Fri Jun 19 06:42:26 +0000 2011", "priority":0.5, "templateParams":{ }, "titleId":"", "body": "", "identityId":"123456789abcdefghi", "liked":true, "likedByIdentities":[ { "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } } ], "totalNumberOfLikes":20, "posterIdentity":{ "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } }, "comments":[ { } ], "totalNumberOfComments":1234, "activityStream":{ "type":"user", "prettyId":"root", "fullName": "Root Root", "faviconUrl":"http://demo3.exoplatform.org/favicons/exo-default.jpg", "title":"Activity Stream of Root Root", "permaLink":"http://localhost:8080/profile/root" } } ] }
Description: Gets activities of spaces in which the authenticated user identity is space member that makes this request.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity_stream/spaces.{format}
Parameters:
Required (path parameters):
portalContainerName: The portal container name
format: The response format type, for example: json, xml...
Optional (query paramters):
limit: Specifies the number of activities to retrieve. Must be less than or equal to 100. The value you pass as limit is a maximum number of activities to be returned. The actual number of activities you receive maybe less than limit. If no specified, 100 will be the default value.
since_id: Returns the activities having the created timestamps greater than the specified sinceId's created timestamp
max_id: Returns the activities having the created timestamp less than the specified maxId's created timestamp. Note that sinceId and maxId must not be defined in one request, if they are, the sinceId query param is chosen.
number_of_comments: Specifies the latest number of comments to be displayed along with each activity. By default, numberOfComments=0. If numberOfComments is a positive number, this number is considered as a limit number that must be equal or less than 100. If the actual number of comments is less than the provided positive number, the number of actual comments must be returned. If the total number of comments is more than 100, it's recommended to use: "activity/:activityId/comments.format" instead
number_of_likes: Specifies the latest number of detailed likes to be returned along with this activity. By default, numberOfLikes=0. If numberOfLikes is a positive number, this number is considered as a limit number that must be equal or less than 100. If the actual number of likes is less than the provided positive number, the number of actual likes must be returned. If the total number of likes is more than 100, it's recommended to use: "activity/:activityId/likes.format" instead.
Request:
GET: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/socialdemo/activity_stream/spaces.json?limit=30&since_id=12345&number_of_comments=5&number_of_likes=5
Response:
{ "activities":[ { "id":"1a2b3c4d5e6f7g8h9j", "title":"Hello World!!!", "appId":"", "type":"DEFAULT_ACTIVITY", "postedTime":123456789, "createdAt":"Fri Jun 17 06:42:26 +0000 2011", "priority":0.5, "templateParams":{ }, "titleId":"", "body": "", "identityId":"123456789abcdefghi", "liked":true, "likedByIdentities":[ { "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } } ], "totalNumberOfLikes":20, "posterIdentity":{ "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } }, "comments":[ { } ], "totalNumberOfComments":1234, "activityStream":{ "type":"user", "prettyId":"root", "fullName": "Root Root", "faviconUrl":"http://demo3.exoplatform.org/favicons/exo-default.jpg", "title":"Activity Stream of Root Root", "permaLink":"http://localhost:8080/profile/root" } }, { "id":"1a210983123f7g8h9j", "title":"Hello World 1!!!", "appId":"", "type":"DEFAULT_ACTIVITY", "postedTime":123456789, "createdAt":"Fri Jun 19 06:42:26 +0000 2011", "priority":0.5, "templateParams":{ }, "titleId":"", "body": "", "identityId":"123456789abcdefghi", "liked":true, "likedByIdentities":[ { "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } } ], "totalNumberOfLikes":20, "posterIdentity":{ "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } }, "comments":[ { } ], "totalNumberOfComments":1234, "activityStream":{ "type":"user", "prettyId":"root", "fullName": "Root Root", "faviconUrl":"http://demo3.exoplatform.org/favicons/exo-default.jpg", "title":"Activity Stream of Root Root", "permaLink":"http://localhost:8080/profile/root" } } ] }
Description: Gets activities of connections of a specified identity.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/activity_stream/connections.{format}
Parameters:
Required (path parameters):
portalContainerName: The portal container name
format: The response format type, for example: json, xml...
Optional (query paramters):
limit: Specifies the number of activities to retrieve. Must be less than or equal to 100. The value you pass as limit is a maximum number of activities to be returned. The actual number of activities you receive maybe less than limit. If no specified, 100 will be the default value.
since_id: Returns the activities having the created timestamps greater than the specified sinceId's created timestamp
max_id: Returns the activities having the created timestamp less than the specified maxId's created timestamp. Note that sinceId and maxId must not be defined in one request, if they are, the sinceId query param is chosen.
number_of_comments: Specifies the latest number of comments to be displayed along with each activity. By default, numberOfComments=0. If numberOfComments is a positive number, this number is considered as a limit number that must be equal or less than 100. If the actual number of comments is less than the provided positive number, the number of actual comments must be returned. If the total number of comments is more than 100, it's recommended to use: "activity/:activityId/comments.format" instead
number_of_likes: Specifies the latest number of detailed likes to be returned along with this activity. By default, numberOfLikes=0. If numberOfLikes is a positive number, this number is considered as a limit number that must be equal or less than 100. If the actual number of likes is less than the provided positive number, the number of actual likes must be returned. If the total number of likes is more than 100, it's recommended to use: "activity/:activityId/likes.format" instead.
Request:
GET: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/socialdemo/activity_stream/connections.json?limit=30&since_id=12345&number_of_comments=5&number_of_likes=5
Response:
{ { "activities":[ { "id":"1a2b3c4d5e6f7g8h9j", "title":"Hello World!!!", "appId":"", "type":"DEFAULT_ACTIVITY", "postedTime":123456789, "createdAt":"Fri Jun 17 06:42:26 +0000 2011", "priority":0.5, "templateParams":{ }, "titleId":"", "body": "", "identityId":"123456789abcdefghi", "liked":true, "likedByIdentities":[ { "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } } ], "totalNumberOfLikes":20, "posterIdentity":{ "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } }, "comments":[ { } ], "totalNumberOfComments":1234, "activityStream":{ "type":"user", "prettyId":"root", "fullName": "Root Root", "faviconUrl":"http://demo3.exoplatform.org/favicons/exo-default.jpg", "title":"Activity Stream of Root Root", "permaLink":"http://localhost:8080/profile/root" } }, { "id":"1a210983123f7g8h9j", "title":"Hello World 1!!!", "appId":"", "type":"DEFAULT_ACTIVITY", "postedTime":123456789, "createdAt":"Fri Jun 19 06:42:26 +0000 2011", "priority":0.5, "templateParams":{ }, "titleId":"", "body": "", "identityId":"123456789abcdefghi", "liked":true, "likedByIdentities":[ { "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } } ], "totalNumberOfLikes":20, "posterIdentity":{ "id":"123456313efghi", "providerId":"organization", "remoteId":"demo", "profile":{ "fullName":"Demo GTN", "avatarUrl":"http://localhost:8080/profile/u/demo/avatar.jpg?u=12345" } }, "comments":[ { } ], "totalNumberOfComments":1234, "activityStream":{ "type":"user", "prettyId":"root", "fullName": "Root Root", "faviconUrl":"http://demo3.exoplatform.org/favicons/exo-default.jpg", "title":"Activity Stream of Root Root", "permaLink":"http://localhost:8080/profile/root" } } ] }
Description: Gets the identity and its associated profile by the activity Id.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/identity/{identityId}.{format}
Requires Authentication: true
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
identityId: the specified identityId
format: the expected returned format
Optional (query paramters): No
Request:
GET: http://cloud-workspaces.com/rest/private/api/social/v1-alpha3/portal/identity/123456789.json
Response:
{ "id" : "123456789", "providerId": "organization", "remoteId": "demo", "profile": { "fullName": "Demo Gtn", "avatarUrl": "http://cloud-workspaces.com/profile/avatar/demo.jpg" } }
Description: Gets the identity and its associated profile by specifying its providerId and remoteId. Every identity has its providerId and remoteId. There could be as many identities as possible. Currently, there are 2 built-in types of identities (user identities and space identities) in eXo Social.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/v1-alpha3/{portalContainerName}/identity/{providerId}/{remoteId}.{format}
Requires Authentication: true
Parameters:
Required (path parameters):
portalContainerName: the associated portal container name
providerId: the providerId of Identity
remoteId: the remoteId of Identity
format: the expected returned format
Optional (query paramters): No
Request:
GET: http://localhost:8080/rest-socialdemo/private/api/social/v1-alpha3/socialdemo/identity/organization/demo.json
user identities: providerId = organization; remoteId = portal user name.
space identities: providerId = space; remoteId = space's pretty name.
Response:
{ "id" : "123456789", "providerId": "organization", "remoteId": "demo", "profile": { "fullName": "Demo Gtn", "avatarUrl": "http://localhost:8080/socialdemo/demo/profile/avatar/demo.jpg" } }
Description: Gets the latest eXo Social REST API version. This version number should be used as the latest and stable version that is considered to include all new features and updates of eXo Social REST services.
URL:
http://{domain_name}/{rest_context_name}/private/api/social/versionlatest.{format}
Parameters:
Required (path parameters):
format: the expected returned format
Optional (query paramters): No
Request:
GET: http://cloud-workspaces.com/rest/api/social/version/latest.json or GET: http://cloud-workspaces.com/rest/api/social/version/latest.xml
Response:
{"version": "v1-alpha3"}
or
<version>v1-alpha3</version>
Description: Gets eXo Social REST service versions that are supported. This is for backward compatibility. If a client application is using an older eXo Social REST APIs version, all APIs of the version still can work. The array MUST have the latest to oldest order. For example, [v2, v1, v1-beta3], but not [v1, v2, v1-beta3].
URL:
http://{domain_name}/{rest_context_name}/private/api/social/versionsupported.{format}
Parameters:
Required (path parameters):
format: the expected returned format
Optional (query paramters): No
Request:
GET: http://cloud-workspaces.com/rest/api/social/version/supported.json or GET: http://cloud-workspaces.com/rest/api/social/version/supported.xml
Response:
{"versions": ["v1-alpha3"]}
or
<versions>
<version>v1-alpha3</version>
</versions>
All references for Opensocial Javascript APIs can be viewed here.
Like any other eXo's products, Social fully complies the JCR standard to store data (identity, profile, activity, space and relationship). The Social JCR structure is organized to conform to the data storage for the individual purpose of Social. With this structure, it is easy for you to manage and access the data properly.
See the Social JCR structure in the chart below:
The root node of Social workspace is /production/ which consists of two child nodes named soc:providers, and soc:spaces.
The soc:providers node is used to store the provider entities. In Social, there are two built-in provider entities, including organization, and space. Its type is soc:providers that has the soc:<provider_name> child node of the soc:providerdefinition type.
The <provider_name> parameter in the soc:<provider_name> node depends on the identity providers. Social has two identity providers, including OrgarnizationIdentityProvider, and SpaceIdentityProvider that contain organization identities (users) and space identities respectively.
The soc:<provider_name> node of the soc:providerdefinition type has the soc:<identityRemoteId> child nodes that have the soc:identitydefinition type.
The soc:identitydefinition node type has the following properties:
Property Name | Required Type | Mutiple | Description |
---|---|---|---|
soc:providerId | String | false | The provider Id is considered as a namespace for the remote Id. |
soc:remoteId | String | false | The local Id from a provider Id. |
soc:isDeleted | Boolean | false | Show that if the provider Id is deleted or not via the provider. |
The soc:identitydefinition node type has the following child nodes:
Child Nodes | Default Primary Type | Description |
---|---|---|
soc:profile | soc:profiledefinition | Store the detailed information of an identity. |
soc:activities | soc:activitylist | Store all activities in the activity stream of an identity. |
soc:sender | soc:relationship | Store all the relationships which contain an identity inviting other identities to connect with himself. |
soc:receiver | soc:relationship | Store all the relationships which contain an identity invited to connect by other identities. |
soc:relationship | soc:relationship | Store all the relationships of an identity that is in connection with other identities. |
soc:ignored | soc:relationship | Store all the relationships which contain an identity ignored by other identities. |
soc:ignore | soc:relationship | Store all the relationships which contain an identity ignoring other identities. |
soc:spacemember | soc:spaceslist | Store all spaces of which an identity is a member. |
soc:spacependingmember | soc:spaceslist | Store all spaces which an identity is pending for validation to join. |
soc:spaceinvitedmember | soc:spaceslist | Store all spaces which an identity is invited to join. |
soc:spacemanagermember | soc:spaceslist | Store all spaces of which an identity is a manager. |
The soc:relationshipdefinition node type has the following properties:
Property Name | Required Type | Mutiple | Description |
---|---|---|---|
soc:status | String | false | The status of the relationship, including three values: PENDING, CONFIRMED, and IGNORED. |
soc:from | Reference | false | The receiver identity. It refers to the soc:identity node type. |
soc:to | Reference | false | The sender identity. It refers to the soc:identity node type. |
soc:reciprocal | Reference | false | Denotes if the relationship is one way or two ways. It refers to the soc:relationshipdefinition node type. |
soc:createdTime | Long | false | The time when the relationship is created. |
The soc:profiledefinition node type has the following properties:
Property Name | Required Type | Mutiple | Description |
---|---|---|---|
soc:externalUrl | String | false | |
soc:externalAvatarUrl | String | false | |
soc:parentId | String | false | The parent id is the identity id. It is used for queries. |
The soc:profiledefinition node type has the following child nodes:
Child Nodes | Default Primary Type | Description |
---|---|---|
soc:avatar | nt:file | The users's avatar. |
childName | soc:profilexp | All the experiences stored in the profile. |
Some residual properties can be set and will be used by Social:
Property Name | Required Type | Multiple | Description |
---|---|---|---|
void-Url | undefined | true | The URL to access the profile of an identity. |
void-email | undefined | true | The email of an identity in the profile. |
void-firstName | undefined | true | The first name of an identity in his profile. |
void-fullName | undefined | true | The full name of an identity in his profile. |
void-lastName | undefined | true | The last name of an identity in his profile. |
void-username | undefined | true | The username of an identity in his profile. |
The soc:profilexp node type has the following properties:
Property Name | Required Type | Mutiple | Description |
---|---|---|---|
soc:skills | String | false | The work skills of an identity. |
soc:position | String | false | The job position of an identity at an organization. |
soc:startDate | String | false | The date when an identity starts working at an organization. |
soc:endDate | String | false | The date when an identity stops working at an organization. |
soc:description | String | false | The description of an identity's position at an organization. |
soc:company | String | false | The company where an identity works. |
The soc:activitylist node type has the following properties:
Property Name | Required Type | Mutiple | Description |
---|---|---|---|
soc:number | Integer | false | The number of activities in the activities list. The default value is set to 0. |
The soc:activitylist node type has the following child nodes:
Child Nodes | Default Primary Type | Description |
---|---|---|
childName | soc:activityyear | All the years containing activities in the list. |
The soc:activityyear node type has the following properties:
Property Name | Required Type | Mutiple | Description |
---|---|---|---|
soc:number | Integer | false | The number of activities in the year. The default value is set to 0. |
The soc:activityyear node type has the following child nodes:
Child Nodes | Default Primary Type | Description |
---|---|---|
childName | soc:activitymonth | All the months containing activities in the year. |
The soc:activitymonth node type has the following properties:
Property Name | Required Type | Mutiple | Description |
---|---|---|---|
soc:number | Integer | false | The number of activities in the month. The default value is set to 0. |
The soc:activitymonth node type has the following child nodes:
Child Nodes | Default Primary Type | Description |
---|---|---|
childName | soc:activityday | All the days containing activities in the month. |
The soc:activityday node type has the following properties:
Property Name | Required Type | Mutiple | Description |
---|---|---|---|
soc:number | Integer | false | The number of activities in the day. The default value is set to 0. |
The soc:activityday node type has the following child nodes:
Child Nodes | Default Primary Type | Description |
---|---|---|
childName | soc:activity | All the activities in the day. |
The soc:activity node type has the following properties:
Property Name | Required Type | Mutiple | Description |
---|---|---|---|
soc:identity | Reference | false | The identity whose activity stream contains an activity. |
soc:posterIdentity | Reference | false | The identity of the user who creates an activity. |
soc:title | String | false | The string which specifies the primary text of an activity. |
soc:titleId | String | false | The title Id of an activity. |
soc:appId | String | false | The application Id which creates an activity. |
soc:body | String | false | The string which specifies the body template message Id in the gadget specification. The body is an optional extended version of an activity. |
soc:bodyId | String | false | The body Id of an activity. |
soc:type | String | false | The application Id which creates an activity. |
soc:externalId | String | false | An optional string Id which is generated by the posting application. |
soc:url | String | false | The URL to access an activity. |
soc:priority | Float | false | A float number between '0' and '1' which represents the relative priority level of an activity in relation to other activities from the same source. |
soc:likes | String | true | The list of identity Ids who like the activity. |
soc:isComment | Boolean | false | Specify if an activity is a comment or not. The default value is false, meaning that it is a normal activity. |
soc:postedTime | Long | false | The number which specifies the time at which an activity took place in milliseconds since the epoch. |
The soc:activity node type has the following child nodes:
Child Nodes | Default Primary Type | Description |
---|---|---|
childName | soc:activity | All comments of the identity. The child is the posted time stamp. |
soc:params | soc:activityparam | The activity parameters. |
The soc:activityparam node type has the following property:
Property Name | Required Type | Multiple | Description |
---|---|---|---|
* | String | false | A map of key-values. |
The soc:spaceslist node type has the following child nodes:
Child Nodes | Default Primary Type | Description |
---|---|---|
soc:refs | soc:spaceref | List of soc:spaceref as child node. |
The soc:spacedefinition node type has the following properties:
Property Name | Required Type | Mutiple | Description |
---|---|---|---|
soc:app | String | false | The list of applications with portlet Id, application name, and its state (installed, activated, deactivated). |
soc:name | String | false | The space name. |
soc:displayName | String | false | The display name of a space. |
soc:registration | String | false | The space registration status: open, validation, and close. |
soc:description | String | false | The description of a space. |
soc:avatarLastUpdated | Long | false | The last time when the avatar is updated. |
soc:type | String | false | The type of space which is used to run in the Classic or WebOS mode. |
soc:visibility | String | false | The space visibility: public, private, and hidden. |
soc:priority | String | false | The space priority level that is used to sort spaces in the spaces list. It contains three values: 1, 2 and 3. The smaller value has the higher priority level. |
soc:groupId | String | false | The group associated with the corresponding space. |
soc:url | String | false | The link to access a space. |
soc:membersId | String | true | The list of users which are members of a space. |
soc:pendingMembersId | String | true | The list of users who are pending for validation to join a space. |
soc:invitedMembersId | String | true | The list of users who are invited to join a space. |
soc:managerMembersId | String | true | The list of users who are managers of a space. |
In Social, you may have two space types (classic and webos spaces).
For the classic space, you can pre-configure the template. You can configure the layout to select where to display the applications (for example, the application's menu on the left, the selected application is displayed on the right, and more).
Here is an example of the configuration file that displays the menu on the left. The application will be inserted in the container with the ID Application:
<page>
<owner-type/>
<owner-id/>
<name/>
<container id="SpacePage" template="system:/groovy/portal/webui/container/UITableColumnContainer.gtmpl">
<container id="Menu" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
<portlet-application>
<portlet>
<application-ref>space</application-ref>
<portlet-ref>SpaceMenuPortlet</portlet-ref>
</portlet>
<access-permissions>*:/platform/users</access-permissions>
<show-info-bar>false</show-info-bar>
</portlet-application>
</container>
<container id="Application" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
</container>
</container>
</page>
In this example, the outer container contains two inner containers: one container has id as Menu for your Menu and another has id as Application containing your applications.
If you want to put the menu on the right and the application on the left, you can swap the declared position of these two containers:
<page>
<owner-type/>
<owner-id/>
<name/>
<container id="SpacePage" template="system:/groovy/portal/webui/container/UITableColumnContainer.gtmpl">
<container id="Application" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
<container id="Menu" template="system:/groovy/portal/webui/container/UIContainer.gtmpl">
<portlet-application>
<portlet>
<application-ref>space</application-ref>
<portlet-ref>SpaceMenuPortlet</portlet-ref>
</portlet>
<access-permissions>*:/platform/users</access-permissions>
<show-info-bar>false</show-info-bar>
</portlet-application>
</container>
</container>
</container>
</page>
In Social standalone, this configuration file is at:
$EXO_TOMCAT/webapps/socialdemo/WEB-INF/conf/portal/template/pages/space/page.xml
In eXo Platform, this configuration file is at:
$EXO_TOMCAT/webapps/{portal-name}/WEB-INF/conf/portal/template/pages/space/page.xml
This section is about configuring the oAuth 2 legs scenario in OpenSocial. (Reference: OpenSocial.org)
For more information, visit 2-legged OAuth for the OpenSocial REST API.
To generate the key:
$ openssl req -newkey rsa:1024 -days 365 -nodes -x509 -keyout testkey.pem \ -out testkey.pem -subj '/CN=mytestkey' $ openssl pkcs8 -in testkey.pem -out oauthkey.pem -topk8 -nocrypt -outform PEM