eXo Platform 3.5

## Chapter 37. HTTPBackupAgent and backup client

### Warning

For this service, you should configure the org.exoplatform.services.jcr.impl.config.JDBCConfigurationPersister in order to save the changes of the repository configuration. See the eXo JCR Configuration article at chapter '2 Portal and Standalone configuration' .

GateIn uses context /portal/rest, therefore you need to use http://host:port/portal/rest/ instread of http://host:port/rest/

GateIn uses form authentication, so first you need to login (url to form authentication is http://host:port/portal/login) and then perform requests.

The service org.exoplatform.services.jcr.ext.backup.server.HTTPBackupAgent is REST-based front-end to service org.exoplatform.services.jcr.ext.backup.BackupManager. HTTPBackupAgent is representation BackupManager to creation backup, restore, getting status of current or completed backup/restore, etc.

The backup client is http client for HTTPBackupAgent.

## HTTPBackupAgent

The HTTPBackupAgent is based on REST (see details about the REST Framework).

HTTPBackupAgent is using POST and GET methods for request.

The HTTPBackupAgent allows :

- Start backup

- Stop backup

- Restore from backup

- Delete the workspace

- Get information about backup service (BackupManager)

- Get information about current backup / restores / completed backups

### HTTPBackupAgent methods

#### Starting Backup Service

/rest/jcr-backup/start/{repo}/{ws}

Start backup on specific workspace

URL: `http://host:port/rest/jcr-backup/start/{repo}/{ws}`

Formats: json.

Method: POST

Parameters:

- {repo} - the repository name;

- {ws} - the workspace name;

- BackupConfigBean - the JSON to BackupConfigBean.

The BackupConfigBean:

    header :
    "Content-Type" = "application/json; charset=UTF-8"

    body:
    <JSON to BackupConfigBean>

The JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.BackupConfigBean :

    {"incrementalRepetitionNumber":<Integer>,"incrementalBackupJobConfig":<JSON to BackupJobConfig>,
    "backupType":<Integer>,"fullBackupJobConfig":<JSON to BackupJobConfig>,
    "incrementalJobPeriod":<Long>,"backupDir":"<String>"}

Where :

    backupType                  - the type of backup:
                                      0 - full backup only;
                                      1 - full and incremental backup.
    backupDir                   - the path to backup folder;
    incrementalJobPeriod        - the incremental job period;
    incrementalRepetitionNumber - the incremental repetition number;
    fullBackupJobConfig         - the configuration to full backup, JSON to BackupJobConfig;
    incrementalJobPeriod        - the configuration to incremental backup, JSON to BackupJobConfig.

The JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.response.BackupJobConfig :

    {"parameters":[<JSON to Pair>, ..., <JSON to pair> ],"backupJob":"<String>"}

Where:

    backupJob  - the FQN (fully qualified name) to BackupJob class;
    parameters - the list of JSON of Pair.

The JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.response.Pair :

    {"name":"<String>","value":"<String>"}

Where:

    name  - the name of parameter;
    value - the value of parameter.

Returns:

- Return when being successful

      status code = 200

- Return when being failure

      status code = 404            - the not found repositry '{repo}' or workspace '{ws}'
      status code = 500            - the other unknown errors
      failure message in response  - the description of failure

#### Stopping Backup Service

/rest/jcr-backup/stop/{id}

Stop backup with identifier {id}.

URL: `http://host:port/rest/jcr-backup/stop/{id}`

Formats: plain text

Method: GET

Parameters:

- {id} - the identifier of backup

Returns:

- Return when being successful

      status code = 200

- Return when being failure

      status code = 404            - the no active backup with identifier {id}
      status code = 500            - the other unknown errors
      failure message in response  - the description of failure

#### Backup Info Service

/rest/jcr-backup/info

Information about the backup service.

URL: `http://host:port/rest/jcr-backup/info`

Formats: json

Method: GET

Parameters: no

Returns:

- Return when being successful

  Return the JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.response.BackupServiceInfoBean :

      {"backupLogDir":"<String>","defaultIncrementalJobPeriod":<Long>,"fullBackupType":"<String>","incrementalBackupType":"<String>"}

  Where:

      fullBackupType              - the FQN (fully qualified name) of BackupJob class for full backup type;
      incrementalBackupType       - the FQN (fully qualified name) of BackupJob class for incremental backup type;
      backupLogDir                - path to backup folder;
      defaultIncrementalJobPeriod - the default incremental job period.

- Return when being failure

      status code = 500            - the unknown error
      failure message in response  - the description of failure

#### Dropping Workspace Service

/rest/jcr-backup/drop-workspace/{repo}/{ws}/{force-session-close}

Delete the workspace from repository /{repo}/{ws}. With this service, you can delete any workspaces regardless of whether the workspace is a backup or has been copied to a backup.

URL: `http://host:port/rest/jcr-backup/drop-workspace/{repo}/{ws}/{force-session-close}`

Formats: plain text

Method: GET

Parameters:

- {repo} - the repository name;

- {ws} - the workspace name;

- {force-session-close} - the boolean value : true - the open sessions on workspace will be closed; false - will not close open sessions.

Returns:

- Return when being successful.

      status code = 200

- Return when being failure

      status code = 500            - the other unknown errors;
                                   - not found repositry '{repo}' or workspace '{ws}'
      failure message in response  - the description of failure

#### Backup Info

/rest/jcr-backup/info/backup

Information about the current and completed backups

URL: `http://host:port/rest/jcr-backup/info/backup`

Formats: json

Method: GET

Parameters: no

Returns:

- Return when being successful

  The JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.response.ShortInfoList :

      {"backups":[<JSON to ShortInfo>,<JSON to ShortInfo>,...,<JSON to ShortInfo>]}

  The JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.response.ShortInfo :

      {"startedTime":"<String>","backupId":"<String>","type":<Integer>,"state":<Integer>,"backupType":<Integer>,
      "workspaceName":"<String>","finishedTime":"<String>","repositoryName":"<String>"}

  Where:

      type           - the type of ShortInfo :
                         0 - the ShorInfo to completed backup;
                        -1 - the ShorInfo to current (active) backup.
                         1 - the ShorInfo to current restore.
      backupType     - the type of backup:
                         0 - full backup only;
                         1 - full and incremental backup.
      backupId       - the identifier of backup;
      workspaceName  - the name of workspace;
      repositoryName - the name of repository.
      startedTime    - the date of started backup. The date in format RFC 1123 (for examle "Thu, 16 Apr 2009 14:56:49 EEST").

      The ShorInfo to current (active) backup :
        finishedTime - no applicable, always an empty string ("");
        state        - the state of full backup :
                         0 - starting;
                         1 - waiting;
                         2 - working;
                         4 - finished.

      The ShorInfo to completed backup :
        finishedTime - the date of finished backup. The date in format RFC 1123;
        state        - no applicable, always zero (0).

      The ShorInfo to current restore :
        finishedTime - the date of finished backup. The date in format RFC 1123;
        state        - the state of restore :
                         1 - started;
                         2 - successful;
                         3 - failure;
                         4 - initialized.

- Return when being failure

      status code = 500            - the unknown error
      failure message in response  - the description of failure

#### Current Backups Information

/rest/jcr-backup/info/backup/current Information about the current backups

URL: `http://host:port/rest/jcr-backup/info/backup/current`

Formats: json

Method: GET

Parameters: no

Returns:

- Return when being successful

  The JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.response.ShortInfoList (see item /rest/jcr-backup/info/backup)

- Return when being failure

      status code = 500            - the unknown error
      failure message in response  - the description of failure

#### Completed Backups Information

/rest/jcr-backup/info/backup/completed Information about the completed backups.

URL: `http://host:port/rest/jcr-backup/info/backup/completed`

Formats: json

Method: GET

Parameters: no

Returns:

- Return when being successful

  The JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.response.ShortInfoList (see item /rest/jcr-backup/info/backup)

- Return when being failure

      status code = 500            - the unknown error
      failure message in response  - the description of failure

#### Workspace-specific Backup Information

/rest/jcr-backup/info/backup/{repo}/{ws} Information about the current and completed backups for specific workspace.

URL: `http://host:port/rest/jcr-backup/info/backup/{repo}/{ws}`

Formats: json

Method: GET

Parameters:

- {repo} - the repository name

- {ws} - the workspace name

Returns:

- Return when being successful

  The JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.response.ShortInfoList (see item /rest/jcr-backup/info/backup)

- Return when being failure

      status code = 500            - the unknown error
      failure message in response  - the description of failure

#### Single Backup Information

/rest/jcr-backup/info/backup/{id} Detailed information about a current or completed backup with identifier '{id}'.

URL: `http://host:port/rest/jcr-backup/info/backup/{id}`

Formats: json

Method: GET

Parameters:

- {id} - the identifier of backup

Returns:

- Return when being successful

  The JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.response.DetailedInfo :

      {"backupConfig":<JSON to BackupConfigBean>,"startedTime":"<String>","backupId":"<String>","type":<Integer>,
      "state":<Integer>,"backupType":<Integer>,"workspaceName":"<String>","finishedTime":"<String>",
      "repositoryName":"<String>"}

  Where:

      type           - the type of DetailedInfo :
                         0 - the DetailedInfo to completed backup;
                        -1 - the DetailedInfo to current (active) backup;
                         1 - the DetailedInfo to restore.
      backupType     - the type of backup:
                         0 - full backup only;
                         1 - full and incremental backup.
      backupId       - the identifier of backup;
      workspaceName  - the name of workspace;
      repositoryName - the name of repository;
      backupConfig   - the JSON to BackupConfigBean.

      The DetailedInfo to current (active) backup :
        startedTime  - the date of started backup. The date in format RFC 1123 (for examle "Thu, 16 Apr 2009 14:56:49 EEST");
        finishedTime - no applicable, always an empty string ("");
        state        - the state of full backup :
                         0 - starting;
                         1 - waiting;
                         2 - working;
                         4 - finished.
      The DetailedInfo to completed backup :
        startedTime  - the date of started backup. The date in format RFC 1123 (for examle "Thu, 16 Apr 2009 14:56:49 EEST");
        finishedTime - the date of finished backup. The date in format RFC 1123;
        state        - no applicable, always zero (0).

      The DetailedInfo to restore :
        startedTime  - the date of started restore. The date in format RFC 1123 (for examle "Thu, 16 Apr 2009 14:56:49 EEST");
        finishedTime - the date of finished restore;
        state        - the state of restore :
                         1 - started;
                         2 - successful;
                         3 - failure;
                         4 - initialized.

  The JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.BackupConfigBean (see item /rest/jcr-backup/start/{repo}/{ws}).

- Return when being failure

      status code = 404            - not found the backup with {id}
      status code = 500            - the unknown error
      failure message in response  - the description of failure

#### Restores on a Workspace Information

/rest/jcr-backup/info/restore/{repo}/{ws} The information about the last restore on a specific workspace /{repo}/{ws}.

URL: `http://host:port/rest/jcr-backup/info/restore/{repo}/{ws}`

Formats: json

Method: GET

Parameters:

- {repo} - the repository name

- {ws} - the workspace name

Returns:

- Return when being successful

  The JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.response.DetailedInfo (see item /rest/jcr-backup/info/backup/{id})

- Return when being failure

      status code = 404            - the not found the restore for workspace /{repo}/{ws}
      status code = 500            - the unknown error
      failure message in response  - the description of failure

#### Restores Information

/rest/jcr-backup/info/restores

The information about the last restores.

URL: `http://host:port/rest/jcr-backup/info/restores`

Formats: json

Method: GET

Parameters: no

Returns:

- Return when being successful

  The JSON bean of org.exoplatform.services.jcr.ext.backup.server.bean.response.ShortInfoList (see item /rest/jcr-backup/info/backup)

- Return when being failure

      status code = 500            - the unknown error
      failure message in response  - the description of failure

#### Restoring Service

/rest/jcr-backup/restore/{repo}/{id}

Restore the workspace from specific backup.

URL: `http://host:port/rest/jcr-backup/restore/{repo}/{id}`

Formats: json.

Method: POST

Parameters:

- {repo} - the repository name;

- {id} - the identifier to backup; * WorkspaceEntry - the JSON to WorkspaceEntry.

The RestoreBean:

    header :
    "Content-Type" = "application/json; charset=UTF-8"

    body:
    <JSON to WorkspaceEntry>

The example of JSON bean to org.exoplatform.services.jcr.config.WorkspaceEntry :

    { "accessManager" : null,
      "autoInitPermissions" : null,
      "autoInitializedRootNt" : null,
      "cache" : { "parameters" : [ { "name" : "max-size",
                "value" : "10k"
              },
              { "name" : "live-time",
                "value" : "1h"
              }
            ],
          "type" : "org.exoplatform.services.jcr.impl.dataflow.persistent.LinkedWorkspaceStorageCacheImpl"
        },
      "container" : { "parameters" : [ { "name" : "source-name",
                "value" : "jdbcjcr"
              },
              { "name" : "dialect",
                "value" : "hsqldb"
              },
              { "name" : "multi-db",
                "value" : "false"
              },
              { "name" : "update-storage",
                "value" : "false"
              },
              { "name" : "max-buffer-size",
                "value" : "200k"
              },
              { "name" : "swap-directory",
                "value" : "../temp/swap/production"
              }
            ],
          "type" : "org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer",
          "valueStorages" : [ { "filters" : [ { "ancestorPath" : null,
                      "minValueSize" : 0,
                      "propertyName" : null,
                      "propertyType" : "Binary"
                    } ],
                "id" : "system",
                "parameters" : [ { "name" : "path",
                      "value" : "../temp/values/production"
                    } ],
                "type" : "org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage"
              } ]
        },
      "initializer" : { "parameters" : [ { "name" : "root-nodetype",
                "value" : "nt:unstructured"
              } ],
          "type" : "org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer"
        },
      "lockManager" : { "persister" : { "parameters" : [ { "name" : "path",
                    "value" : "../temp/lock/system"
                  } ],
              "type" : "org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister"
            },
          "timeout" : 15728640
        },
      "name" : "production",
      "queryHandler" : { "analyzer" : {  },
          "autoRepair" : true,
          "bufferSize" : 10,
          "cacheSize" : 1000,
          "documentOrder" : true,
          "errorLogSize" : 50,
          "excerptProviderClass" : "org.exoplatform.services.jcr.impl.core.query.lucene.DefaultHTMLExcerpt",
          "excludedNodeIdentifers" : null,
          "extractorBackLogSize" : 100,
          "extractorPoolSize" : 0,
          "extractorTimeout" : 100,
          "indexDir" : "../temp/jcrlucenedb/production",
          "indexingConfigurationClass" : "org.exoplatform.services.jcr.impl.core.query.lucene.IndexingConfigurationImpl",
          "indexingConfigurationPath" : null,
          "maxFieldLength" : 10000,
          "maxMergeDocs" : 2147483647,
          "mergeFactor" : 10,
          "minMergeDocs" : 100,
          "parameters" : [ { "name" : "index-dir",
                "value" : "../temp/jcrlucenedb/production"
              } ],
          "queryClass" : "org.exoplatform.services.jcr.impl.core.query.QueryImpl",
          "queryHandler" : null,
          "resultFetchSize" : 2147483647,
          "rootNodeIdentifer" : "00exo0jcr0root0uuid0000000000000",
          "spellCheckerClass" : null,
          "supportHighlighting" : false,
          "synonymProviderClass" : null,
          "synonymProviderConfigPath" : null,
          "type" : "org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex",
          "useCompoundFile" : false,
          "volatileIdleTime" : 3
        },
      "uniqueName" : "repository_production"
    }

Returns:

- Return when being successful

      status code = 200

  Return the JSON bean org.exoplatform.services.jcr.ext.backup.server.bean.response.ShortInfo of just started restore. For JSON description see item /rest/jcr-backup/info/backup

- Return when being failure

      status code = 403            - the already was restore to workspace /{repo}/{ws}
      status code = 404            - the not found repositry '{repo}' or unsupported encoding to workspaceConfig
      status code = 500            - the other unknown errors
      failure message in response  - the description of failure

#### Default Workspace Information

/rest/jcr-backup/info/default-ws-config Will be returned the JSON bean to WorkspaceEntry for default workspace.

URL: `http://host:port/rest/jcr-backup/info/default-ws-config`

Formats: json

Method: GET

Parameters: no

Returns:

- Return when being successful

  The JSON bean to org.exoplatform.services.jcr.config.WorkspaceEntry :

      { "accessManager" : null,
        "autoInitPermissions" : null,
        "autoInitializedRootNt" : null,
        "cache" : { "parameters" : [ { "name" : "max-size",
                  "value" : "10k"
                },
                { "name" : "live-time",
                  "value" : "1h"
                }
              ],
            "type" : "org.exoplatform.services.jcr.impl.dataflow.persistent.LinkedWorkspaceStorageCacheImpl"
          },
        "container" : { "parameters" : [ { "name" : "source-name",
                  "value" : "jdbcjcr"
                },
                { "name" : "dialect",
                  "value" : "hsqldb"
                },
                { "name" : "multi-db",
                  "value" : "false"
                },
                { "name" : "update-storage",
                  "value" : "false"
                },
                { "name" : "max-buffer-size",
                  "value" : "200k"
                },
                { "name" : "swap-directory",
                  "value" : "../temp/swap/production"
                }
              ],
            "type" : "org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer",
            "valueStorages" : [ { "filters" : [ { "ancestorPath" : null,
                        "minValueSize" : 0,
                        "propertyName" : null,
                        "propertyType" : "Binary"
                      } ],
                  "id" : "system",
                  "parameters" : [ { "name" : "path",
                        "value" : "../temp/values/production"
                      } ],
                  "type" : "org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage"
                } ]
          },
        "initializer" : { "parameters" : [ { "name" : "root-nodetype",
                  "value" : "nt:unstructured"
                } ],
            "type" : "org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer"
          },
        "lockManager" : { "persister" : { "parameters" : [ { "name" : "path",
                      "value" : "../temp/lock/system"
                    } ],
                "type" : "org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister"
              },
            "timeout" : 15728640
          },
        "name" : "production",
        "queryHandler" : { "analyzer" : {  },
            "autoRepair" : true,
            "bufferSize" : 10,
            "cacheSize" : 1000,
            "documentOrder" : true,
            "errorLogSize" : 50,
            "excerptProviderClass" : "org.exoplatform.services.jcr.impl.core.query.lucene.DefaultHTMLExcerpt",
            "excludedNodeIdentifers" : null,
            "extractorBackLogSize" : 100,
            "extractorPoolSize" : 0,
            "extractorTimeout" : 100,
            "indexDir" : "../temp/jcrlucenedb/production",
            "indexingConfigurationClass" : "org.exoplatform.services.jcr.impl.core.query.lucene.IndexingConfigurationImpl",
            "indexingConfigurationPath" : null,
            "maxFieldLength" : 10000,
            "maxMergeDocs" : 2147483647,
            "mergeFactor" : 10,
            "minMergeDocs" : 100,
            "parameters" : [ { "name" : "index-dir",
                  "value" : "../temp/jcrlucenedb/production"
                } ],
            "queryClass" : "org.exoplatform.services.jcr.impl.core.query.QueryImpl",
            "queryHandler" : null,
            "resultFetchSize" : 2147483647,
            "rootNodeIdentifer" : "00exo0jcr0root0uuid0000000000000",
            "spellCheckerClass" : null,
            "supportHighlighting" : false,
            "synonymProviderClass" : null,
            "synonymProviderConfigPath" : null,
            "type" : "org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex",
            "useCompoundFile" : false,
            "volatileIdleTime" : 3
          },
        "uniqueName" : "repository_production"
      }

- Return when being failure

      status code = 500            - the unknown error
      failure message in response  - the description of failure

### HTTPBackupAgent Configuration

Add the components org.exoplatform.services.jcr.ext.backup.server.HTTPBackupAgent and org.exoplatform.services.jcr.ext.backup.BackupManager to services configuration :

    <component>

      <type>org.exoplatform.services.jcr.ext.backup.server.HTTPBackupAgent</type>

    </component>

    <component>

      <type>org.exoplatform.services.jcr.ext.repository.RestRepositoryService</type>

    </component>

    <component>

      <key>org.exoplatform.services.jcr.ext.backup.BackupManager</key>

      <type>org.exoplatform.services.jcr.ext.backup.impl.BackupManagerImpl</type>

      <init-params>

        <properties-param>

          <name>backup-properties</name>

          <property name="backup-dir" value="../temp/backup" />

        </properties-param>

      </init-params>

    </component>

In case, if you will restore backup in same workspace (so you will drop previous workspace), you need configure RepositoryServiceConfiguration in order to save the changes of the repository configuration. For example

    <component>

      <key>org.exoplatform.services.jcr.config.RepositoryServiceConfiguration</key>

      <type>org.exoplatform.services.jcr.impl.config.RepositoryServiceConfigurationImpl</type>

      <init-params>

        <value-param>

          <name>conf-path</name>

          <description>JCR repositories configuration file</description>

          <value>jar:/conf/portal/exo-jcr-config.xml</value>

        </value-param>

        <properties-param>

          <name>working-conf</name>

          <description>working-conf</description>

          <property name="source-name" value="jdbcjcr" />

          <property name="dialect" value="hsqldb" />

          <property name="persister-class-name" value="org.exoplatform.services.jcr.impl.config.JDBCConfigurationPersister" />

        </properties-param>

      </init-params>

    </component>

See the eXo JCR Configuration article at chapter '2 Portal and Standalone configuration' for details.

## Backup Client

For GateIn should use context "/portal/rest". GateIn uses form authentication, so first you need to login (url to form authentication is http://host:port/portal/login) and then perform requests.

Backup client is support form authentication. For example call command "info" with form authentication to GateIn :

./jcrbackup.sh http://127.0.0.1:8080/portal/rest form POST "/portal/login?initialURI=/portal/private&username=root&password=gtn" info

Backup client is console application.

The backup client is http client for HTTPBackupAgent.

Command signature:

    Help info:
     <url_basic_authentication>|<url form authentication>  <cmd>
     <url_basic_authentication>  :   http(s)//login:password@host:port/<context>

     <url form authentication>   :   http(s)//host:port/<context> "<form auth parm>"
         <form auth parm>        :   form <method> <form path>
         <method>                :   POST or GET
         <form path>             :   /path/path?<paramName1>=<paramValue1>&<paramName2>=<paramValue2>...
         Example to <url form authentication> : http://127.0.0.1:8080/portal/rest form POST "/portal/login?initialURI=/portal/private&username=root&password=gtn"

     <cmd>  :   start <repo[/ws]> <backup_dir> [<incr>]
                stop <backup_id>
                status <backup_id>
                restores <repo[/ws]>
                restore [remove-exists] {{<backup_id>|<backup_set_path>} | {<repo[/ws]> {<backup_id>|<backup_set_path>} [<pathToConfigFile>]}}
                list [completed]
                info
                drop [force-close-session] <repo[/ws]>
                help

     start          - start backup of repository or workspace
     stop           - stop backup
     status         - information about the current or completed backup by 'backup_id'
     restores       - information about the last restore on specific repository or workspace
     restore        - restore the repository or workspace from specific backup
     list           - information about the current backups (in progress)
     list completed - information about the completed (ready to restore) backups
     info           - information about the service backup
     drop           - delete the repository or workspace
     help           - print help information about backup console

     <repo[/ws]>         - /<reponsitory-name>[/<workspace-name>]  the repository or workspace
     <backup_dir>        - path to folder for backup on remote server
     <backup_id>         - the identifier for backup
     <backup_set_dir>    - path to folder with backup set on remote server
     <incr>              - incemental job period
     <pathToConfigFile>  - path (local) to  repository or workspace configuration
     remove-exists       - remove fully (db, value storage, index) exists repository/workspace
     force-close-session - close opened sessions on repository or workspace.

     All valid combination of parameters for command restore:
      1. restore remove-exists <repo/ws> <backup_id>       <pathToConfigFile>
      2. restore remove-exists <repo>    <backup_id>       <pathToConfigFile>
      3. restore remove-exists <repo/ws> <backup_set_path> <pathToConfigFile>
      4. restore remove-exists <repo>    <backup_set_path> <pathToConfigFile>
      5. restore remove-exists <backup_id>
      6. restore remove-exists <backup_set_path>
      7. restore <repo/ws> <backup_id>       <pathToConfigFile>
      8. restore <repo>    <backup_id>       <pathToConfigFile>
      9. restore <repo/ws> <backup_set_path> <pathToConfigFile>
     10. restore <repo>    <backup_set_path> <pathToConfigFile>
     11. restore <backup_id>
     12. restore <backup_set_path>

## Backup Client Usage

### Building application

- Go to folder of "backup client" ${JCR-SRC-HOME}/applications/exo.jcr.applications.backupconsole . - build the application :

      mvn clean install -P deploy

- Go to ${JCR-SRC-HOME}/applications/exo.jcr.applications.backupconsole/target/backupconsole-binary and use it.

### Note

${JCR-SRC-HOME} the path where eXo JCR sources located

### Running application

- Run jar

      java -jar exo.jcr.applications.backupconsole-binary.jar <command>

  or use jcrbackup.cmd (or .sh);

### Getting information about backup service

    jcrbackup http://root:exo@127.0.0.1:8080 info

Return :

    The backup service information :
      full backup type               : org.exoplatform.services.jcr.ext.backup.impl.fs.FullBackupJob
      incremetal backup type         : org.exoplatform.services.jcr.ext.backup.impl.fs.IncrementalBackupJob
      backup log folder              : /home/rainf0x/java/exo-working/JCR-839/new_JCR/exo-tomcat/bin/../temp/backup
      default incremental job period : 3600

### Starting full backup

Start full backup only on workspace "backup", the parameter <bakcup_dir> (../temp/backup) should be exists:

    jcrbackup http://root:exo@127.0.0.1:8080 start /repository/backup ../temp/backup

Return :

    Successful :
      status code = 200

### Starting full and incremental backup on a single workspace

Start full and incremental backup on workspace "production":

    jcrbackup http://root:exo@127.0.0.1:8080 start /repository/production ../temp/backup 10000

Return :

    Successful :
     tatus code = 200

### Getting information about the current backups (in progress)

    jcrbackup http://root:exo@127.0.0.1:8080 list

Return :

    The current backups information :
      1) Backup with id b46370107f000101014b03ea5fbe8d54 :
        repository name           : repository
        workspace name            : production
        backup type               : full + incremetal
        full backup state         : finished
        incremental backup state  : working
        started time              : Fri, 17 Apr 2009 17:03:16 EEST
      2) Backup with id b462e4427f00010101cf243b4c6015bb :
        repository name           : repository
        workspace name            : backup
        backup type               : full only
        full backup state         : finished
        started time              : Fri, 17 Apr 2009 17:02:41 EEST

### Getting information about the current backup by 'backup_id'

    jcrbackup http://root:exo@127.0.0.1:8080 status b46370107f000101014b03ea5fbe8d54

return:

    The current backup information :
        backup id                : b46370107f000101014b03ea5fbe8d54
        backup folder            : /home/rainf0x/java/exo-working/JCR-839/new_JCR/exo-tomcat/bin/../temp/backup
        repository name          : repository
        workspace name           : production
        backup type              : full + incremetal
        full backup state        : finished
        incremental backup state : working
        started time             : Fri, 17 Apr 2009 17:03:16 EEST

### Stopping backup by "backup_id"

    jcrbackup http://root:exo@127.0.0.1:8080 stop 6c302adc7f00010100df88d29535c6ee

Return:

    Successful :
      status code = 200

### Getting information about the completed (ready to restore) backups

    jcrbackup http://root:exo@127.0.0.1:8080 list completed

Return:

    The completed (ready to restore) backups information :
      1) Backup with id adf6fadc7f00010100053b2cba43513c :
        repository name           : repository
        workspace name            : backup
        backup type               : full only
        started time              : Thu, 16 Apr 2009 11:07:05 EEST

      2) Backup with id b46370107f000101014b03ea5fbe8d54 :
        repository name           : repository
        workspace name            : production
        backup type               : full + incremetal
        started time              : Fri, 17 Apr 2009 17:03:16 EEST

      3) Backup with id aec419cc7f000101004aca277b2b4e9f :
        repository name           : repository
        workspace name            : backup8
        backup type               : full only
        started time              : Thu, 16 Apr 2009 14:51:08 EEST

### Restoring to workspace

Restore to workspace "backup3", for restore need the <backup_id> of completed backup and path to file with workspace configuration:

    jcrbackup http://root:exo@127.0.0.1:8080 restore /repository/backup3 6c302adc7f00010100df88d29535c6ee /home/rainf0x/java/exo-working/JCR-839/exo-jcr-config_backup3.xml

Return:

    Successful :
      status code = 200

### Getting information about the current restore

Get information about the current restore for workspace /repository/backup3:

    jcrbackup http://root:exo@127.0.0.1:8080 restores

Return:

    The current restores information :
    1) Restore with id 6c302adc7f00010100df88d29535c6ee:
        full backup date        : 2009-04-03T16:34:37.394+03:00
        backup log file         : /home/rainf0x/java/exo-working/JCR-839/exo-tomcat/bin/../temp/backup/backup-6c302adc7f00010100df88d29535c6ee.xml
        repository name         : repository
        workspace name          : backup3
        backup type             : full only
        path to backup folder   : /home/rainf0x/java/exo-working/JCR-839/exo-tomcat/bin/../temp/backup
        restore state           : successful

### Restoring workspace and remove exists workspace

Restore to workspace "backup" and remove fully (will be removed content from db, value storage, index) exists workspace, for restore need the <backup_id> of completed backup and path to file with workspace configuration:

    jcrbackup http://root:exo@127.0.0.1:8080 restore remove-exists /repository/backup 6c302adc7f00010100df88d29535c6ee /home/rainf0x/java/exo-working/JCR-839/exo-jcr-config_backup.xml

Return:

    Successful :
      status code = 200

### Restoring workspace from backup set

Restore to workspace "backup", for restore need the <backup_set_path> (<backup_set_path> is path to backup set folder on server side) of completed backup and path to file with workspace configuration:

    jcrbackup http://root:exo@127.0.0.1:8080 restore /repository/backup /tmp/123/repository_backup-20101220_114156 /home/rainf0x/java/exo-working/JCR-839/exo-jcr-config_backup.xml

Return:

    Successful :
      status code = 200

### Restoring workspace from backup set and remove exists workspace

Restore to workspace "backup" and remove fully (will be removed content from db, value storage, index) exists workspace, for restore need the <backup_set_path> (<backup_set_path> is path to backup set folder on server side) of completed backup and path to file with workspace configuration:

    jcrbackup http://root:exo@127.0.0.1:8080 restore remove-exists /repository/backup /repository/backup /tmp/123/repository_backup-20101220_114156 /home/rainf0x/java/exo-working/JCR-839/exo-jcr-config_backup.xml

Return:

    Successful :
      status code = 200

### Restoring workspace with original configuation

Restore to workspace "backup" with original configuration of workspace (the original configuration was stored in backup set), for restore need the <backup_id> of completed backup:

    jcrbackup http://root:exo@127.0.0.1:8080 restore  6c302adc7f00010100df88d29535c6ee

Return:

    Successful :
      status code = 200

### Restoring workspace with original configuation and remove exists workspace

Restore to workspace "backup" with original configuration of workspace (the original configuration was stored in backup set) and remove fully (will be removed content from db, value storage, index) exists workspace, for restore need the <backup_id> of completed backup:

    jcrbackup http://root:exo@127.0.0.1:8080 restore remove-exists 6c302adc7f00010100df88d29535c6ee

Return:

    Successful :
      status code = 200

### Restoring workspace from backup set with original configuation

Restore to workspace "backup" with original configuration of workspace (the original configuration was stored in backup set), for restore need the <backup_set_path> (<backup_set_path> is path to backup set folder on server side) of completed backup:

    jcrbackup http://root:exo@127.0.0.1:8080 restore /tmp/123/repository_backup-20101220_114156

Return:

    Successful :
      status code = 200

### Restoring workspace from backup set with original configuation and remove exists workspace

Restore to workspace "backup" and remove fully (will be removed content from db, value storage, index) exists workspace with original configuration of workspace (the original configuration was stored in backup set), for restore need the <backup_set_path> (<backup_set_path> is path to backup set folder on server side) of completed backup:

    jcrbackup http://root:exo@127.0.0.1:8080 restore remove-exists /tmp/123/repository_backup-20101220_114156

Return:

    Successful :
      status code = 200

### Restoring repository

Restore to repository "repository" , for restore need the <backup_id> of completed backup and path to file with repository configuration:

    jcrbackup http://root:exo@127.0.0.1:8080 restore remove-exists /repository 6c302adc7f00010100df88d29535c6ee /home/rainf0x/java/exo-working/JCR-839/exo-jcr-config.xml

Return:

    Successful :
      status code = 200

### Restoring repository and remove exists repository

Restore to repositoy "repository" and remove fully (will be removed content from db, value storage, index) exists repository, for restore need the <backup_id> of completed backup and path to file with repository configuration:

    jcrbackup http://root:exo@127.0.0.1:8080 restore remove-exists /repository 6c302adc7f00010100df88d29535c6ee /home/rainf0x/java/exo-working/JCR-839/exo-jcr-config.xml

Return:

    Successful :
      status code = 200

### Restoring repository from backup set

Restore to repository "repository", for restore need the <backup_set_path> (<backup_set_path> is path to backup set folder on server side) of completed backup and path to file with repository configuration:

    jcrbackup http://root:exo@127.0.0.1:8080 restore /repository /tmp/123/repository_repository_backup_1292833493681 /home/rainf0x/java/exo-working/JCR-839/exo-jcr-config.xml

Return:

    Successful :
      status code = 200

### Restoring repository from backup set and remove exists repository

Restore to repository "repository" and remove fully (will be removed content from db, value storage, index) exists repository, for restore need the <backup_set_path> (<backup_set_path> is path to backup set folder on server side) of completed backup and path to file with repository configuration:

    jcrbackup http://root:exo@127.0.0.1:8080 restore remove-exists /repository /repository/backup /tmp/123/repository_repository_backup_1292833493681 /home/rainf0x/java/exo-working/JCR-839/exo-jcr-config.xml

Return:

    Successful :
      status code = 200

### Restoring repository with original configuation

Restore to repository "repository" with original configuration of repository (the original configuration was stored in backup set), for restore need the <backup_id> of completed backup:

    jcrbackup http://root:exo@127.0.0.1:8080 restore  6c302adc7f00010100df88d29535c6ee

Return:

    Successful :
      status code = 200

### Restoring repository with original configuation and remove exists repository

Restore to repository "repository" with original configuration of repository (the original configuration was stored in backup set) and remove fully (will be removed content from db, value storage, index) exists repository, for restore need the <backup_id> of completed backup:

    jcrbackup http://root:exo@127.0.0.1:8080 restore remove-exists 6c302adc7f00010100df88d29535c6ee

Return:

    Successful :
      status code = 200

### Restoring repository from backup set with original configuation

Restore to repository "repository" with original configuration of repository (the original configuration was stored in backup set), for restore need the <backup_set_path> (<backup_set_path> is path to backup set folder on server side) of completed backup:

    jcrbackup http://root:exo@127.0.0.1:8080 restore /tmp/123/repository_repository_backup_1292833493681

Return:

    Successful :
      status code = 200

### Restoring repository from backup set with original configuation and remove exists repository

Restore to repository "repository" and remove fully (will be removed content from db, value storage, index) exists repository with original configuration of repository (the original configuration was stored in backup set), for restore need the <backup_set_path> (<backup_set_path> is path to backup set folder on server side) of completed backup:

    jcrbackup http://root:exo@127.0.0.1:8080 restore remove-exists /tmp/123/repository_repository_backup_1292833493681

Return:

    Successful :
      status code = 200

## Full example about creating backup and restoring it for workspace 'backup'

### Creating backup

    jcrbackup http://root:exo@127.0.0.1:8080 start /repository/backup ../temp/backup 10000

Return :

    Successful :
      status code = 200

### Getting information about current backups

    jcrbackup http://root:exo@127.0.0.1:8080 list

Return :

    The current backups information :
      1) Backup with id b469ba957f0001010178febaedf20eb7 :
        repository name           : repository
        workspace name            : backup
        backup type               : full + incremetal
        full backup state         : finished
        incremental backup state  : working
        started time              : Fri, 17 Apr 2009 17:10:09 EEST

### Stopping backup by id

Stop backup with id b469ba957f0001010178febaedf20eb7 :

    jcrbackup http://root:exo@127.0.0.1:8080 stop b469ba957f0001010178febaedf20eb7

Return :

    Successful :
      status code = 200

### Deleting the workspace "backup" and close opened sessions on this workspace

    jcrbackup http://root:exo@127.0.0.1:8080 drop force-close-session /repository/backup

Return :

    Successful :
      status code = 200

### Restoring the workspace "backup"

- Delete/clean the database for workspace "backup" : When we use "single-db", then we will run the SQL queries for clean database :

      delete from JCR_SREF where NODE_ID in (select ID from JCR_SITEM where CONTAINER_NAME = 'backup')
      delete from JCR_SVALUE where PROPERTY_ID in (select ID from JCR_SITEM where CONTAINER_NAME = 'backup')
      delete from JCR_SITEM where CONTAINER_NAME='backup'

- Delete the value storage for workspace "backup"; - delete the index data for workspace "backup"; - restore :

      jcrbackup http://root:exo@127.0.0.1:8080 restore /repository/backup b469ba957f0001010178febaedf20eb7 /home/rainf0x/java/exo-working/JCR-839/exo-jcr-config_backup.xml

  Return :

      Successful :
        status code = 200

  The /home/rainf0x/java/exo-working/JCR-839/exo-jcr-config_backup.xml content the configuration for restored workspace "backup":

    <repository-service default-repository="repository">

      <repositories>

        <repository name="repository" system-workspace="production" default-workspace="production">

          <security-domain>exo-domain</security-domain>

          <access-control>optional</access-control>

          <authentication-policy>org.exoplatform.services.jcr.impl.core.access.JAASAuthenticator</authentication-policy>

          <workspaces>

            <workspace name="backup">

              <container class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">

                <properties>

                  <property name="source-name" value="jdbcjcr" />

                  <property name="dialect" value="pgsql" />

                  <property name="multi-db" value="false" />

                  <property name="update-storage" value="false" />

                  <property name="max-buffer-size" value="200k" />

                  <property name="swap-directory" value="../temp/swap/backup" />

                </properties>

                <value-storages>

                  <value-storage id="draft" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">

                    <properties>

                      <property name="path" value="../temp/values/backup" />

                    </properties>

                    <filters>

                      <filter property-type="Binary"/>

                    </filters>

                  </value-storage>

                </value-storages>

              </container>

              <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">

                <properties>

                  <property name="root-nodetype" value="nt:unstructured" />

                </properties>

              </initializer>

              <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.LinkedWorkspaceStorageCacheImpl">

                <properties>

                  <property name="max-size" value="10k" />

                  <property name="live-time" value="1h" />

                </properties>

              </cache>

              <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">

                <properties>

                  <property name="index-dir" value="../temp/jcrlucenedb/backup" />

                </properties>

              </query-handler>

            </workspace>

          </workspaces>

        </repository>

      </repositories>

    </repository-service>

### Getting information about restore for workspace /repository/backup

    jcrbackup http://root:exo@127.0.0.1:8080 restores /repository/backup

Return:

    The current restores information :
      Restore with id b469ba957f0001010178febaedf20eb7:
        backup folder           : /home/rainf0x/java/exo-working/JCR-839/new_JCR/exo-tomcat/bin/../temp/backup
        repository name         : repository
        workspace name          : backup
        backup type             : full + incremetal
        restore state           : successful
        started time            : Fri, 17 Apr 2009 16:38:00 EEST
        finished time           : Fri, 17 Apr 2009 16:38:00 EEST

## Full example about creating backup and restoring it for repository 'repository'

### Note

If delete default repository that should be restored repository with name as default repository.

This usecase needs RestRepositoryService enabled. (Deleting the repository needs it)

    <component>

       <type>org.exoplatform.services.jcr.ext.repository.RestRepositoryService</type>

    </component>

### Creating backup

    jcrbackup http://root:exo@127.0.0.1:8080 start /repository ../temp/backup 10000

Return :

    Successful :
      status code = 200

### Getting information about current backups

    jcrbackup http://root:exo@127.0.0.1:8080 list

Return :

    The current backups information :
      1) Repository backup with id 9a4d40fb7f0000012ec8f0a4ec70b3da :
        repository name            : repository
        backup type                : full + incremetal
        full backups state         : finished
        incremental backups state  : working
        started time               : Mon, 11 Oct 2010 10:59:35 EEST

### Stopping backup by id

Stop backup with id 9a4d40fb7f0000012ec8f0a4ec70b3da :

    jcrbackup http://root:exo@127.0.0.1:8080 stop 9a4d40fb7f0000012ec8f0a4ec70b3da

Return :

    Successful :
      status code = 200

### Deleting the repository "repository" and close all opened sessions

    jcrbackup http://root:exo@127.0.0.1:8080 drop force-close-session /repository

Return :

    Successful :
      status code = 200

### Restoring the repository "repository"

- Delete/clean the database for workspace "repository": When we use "single-db", then we will run the SQL queries for clean database :

             drop table JCR_SREF;
             drop table JCR_SVALUE;
             drop table JCR_SITEM;

- Delete the value storage for repository "repository";

- Delete the index data for repository "repository";

- Restore:

      jcrbackup http://root:exo@127.0.0.1:8080 restore /repository 9a6dba327f000001325dfb228a181b07 /home/rainf0x/exo-jcr-config_backup.xml

  Return :

      Successful :
        status code = 200

  The /home/rainf0x/exo-jcr-config_backup.xml content the configuration for restored repository "repository":

    <repository-service default-repository="repository">

       <repositories>

          <repository name="repository" system-workspace="production" default-workspace="production">

             <security-domain>exo-domain</security-domain>

             <access-control>optional</access-control>

             <authentication-policy>org.exoplatform.services.jcr.impl.core.access.JAASAuthenticator</authentication-policy>

             <workspaces>

                <workspace name="production">

                   <!-- for system storage -->

                   <container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">

                      <properties>

                         <property name="source-name" value="jdbcjcr" />

                         <property name="multi-db" value="false" />

                         <property name="update-storage" value="false" />

                         <property name="max-buffer-size" value="200k" />

                         <property name="swap-directory" value="../temp/swap/production" />

                      </properties>

                      <value-storages>

                         <value-storage id="system" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">

                            <properties>

                               <property name="path" value="../temp/values/production" />

                            </properties>

                            <filters>

                               <filter property-type="Binary" />

                            </filters>

                         </value-storage>

                      </value-storages>

                   </container>

                   <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">

                      <properties>

                         <property name="root-nodetype" value="nt:unstructured" />

                      </properties>

                   </initializer>

                   <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.LinkedWorkspaceStorageCacheImpl">

                      <properties>

                         <property name="max-size" value="10k" />

                         <property name="live-time" value="1h" />

                      </properties>

                   </cache>

                   <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">

                      <properties>

                         <property name="index-dir" value="../temp/jcrlucenedb/production" />

                      </properties>

                   </query-handler>

                   <lock-manager>

                      <time-out>15m</time-out>

                      <persister class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister">

                         <properties>

                            <property name="path" value="../temp/lock/system" />

                         </properties>

                      </persister>

                   </lock-manager>

                </workspace>

                <workspace name="backup">

                   <container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">

                      <properties>

                         <property name="source-name" value="jdbcjcr" />

                         <property name="multi-db" value="false" />

                         <property name="update-storage" value="false" />

                         <property name="max-buffer-size" value="200k" />

                         <property name="swap-directory" value="../temp/swap/backup" />

                      </properties>

                      <value-storages>

                         <value-storage id="draft" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">

                            <properties>

                               <property name="path" value="../temp/values/backup" />

                            </properties>

                            <filters>

                               <filter property-type="Binary" />

                            </filters>

                         </value-storage>

                      </value-storages>

                   </container>

                   <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">

                      <properties>

                         <property name="root-nodetype" value="nt:unstructured" />

                      </properties>

                   </initializer>

                   <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.LinkedWorkspaceStorageCacheImpl">

                      <properties>

                         <property name="max-size" value="10k" />

                         <property name="live-time" value="1h" />

                      </properties>

                   </cache>

                   <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">

                      <properties>

                         <property name="index-dir" value="../temp/jcrlucenedb/backup" />

                      </properties>

                   </query-handler>

                </workspace>

                <workspace name="digital-assets">

                   <container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">

                      <properties>

                         <property name="source-name" value="jdbcjcr" />

                         <property name="multi-db" value="false" />

                         <property name="update-storage" value="false" />

                         <property name="max-buffer-size" value="200k" />

                         <property name="swap-directory" value="../temp/swap/digital-assets" />

                      </properties>

                      <value-storages>

                         <value-storage id="digital-assets" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">

                            <properties>

                               <property name="path" value="../temp/values/digital-assets" />

                            </properties>

                            <filters>

                               <filter property-type="Binary" />

                            </filters>

                         </value-storage>

                      </value-storages>

                   </container>

                   <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">

                      <properties>

                         <property name="root-nodetype" value="nt:folder" />

                      </properties>

                   </initializer>

                   <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.LinkedWorkspaceStorageCacheImpl">

                      <properties>

                         <property name="max-size" value="5k" />

                         <property name="live-time" value="15m" />

                      </properties>

                   </cache>

                   <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">

                      <properties>

                         <property name="index-dir" value="../temp/jcrlucenedb/digital-assets" />

                      </properties>

                   </query-handler>

                </workspace>

             </workspaces>

          </repository>

       </repositories>

    </repository-service>

### Getting information about restore for repository 'repository'

    jcrbackup http://root:exo@127.0.0.1:8080 restores /repository

Return:

      Repository restore with id 9a6dba327f000001325dfb228a181b07:
        backup folder           : /home/rainf0x/java/exo-working/JCR-1459/exo-tomcat/bin/../temp/backup/repository_repository_backup_1286786103858
        repository name         : repository
        backup type             : full + incremetal
        restore state           : successful
        started time            : Mon, 11 Oct 2010 11:51:15 EEST
        finished time           : Mon, 11 Oct 2010 11:51:17 EEST

Copyright © 2009-2012. All rights reserved. eXo Platform SAS