# Alfresco CS Importer

## Introduction

The Alfresco CS Importer can import documents and folders processed in migration-center into a target Alfresco on-premises or PAAS repository.

The following versions of Alfresco are supported 7.1, 7.2, 7.3.1.&#x20;

## Known Issues and Limitations

The new Alfresco CS importer should not be installed with the old Alfresco importer or scanner. Having both installed can result in either of them not working.

* Empty file update made to an empty file original object does not create new minor version (#72565)
* Update cannot change object type (#72213)
* Not setting required attributes does not throw error on import (#72019)
* Import fails when extension changes in name in version tree when content doesn't exist in S3 with mapContentToStorage (#71932)
* Non descriptive error message when defaultFolderType is empty (#72582)

## Prerequisites

### WebScript component

The Alfresco CS Importer requires an additional WebScript component to be installed on the Alfresco Server. This WebScript is delivered as an **Alfresco Module Package** (.amp) which has to be installed in the Alfresco Repository Server.

The **AMP** file can be found inside the Jobserver folder under:\
`\lib\mc-alfresco-cs-importer\WebScripts`

#### On-premises install

To install the WebScript component on an on-premises Alfresco system, please see the official Alfresco documentation:\
[https://docs.alfresco.com/content-services/latest/install/zip/amp](https://docs.alfresco.com/content-services/latest/install/zip/amp/)

#### PAAS install

To install the WebScript component in an Alfresco PAAS, please send the AMP file to Hyland support and they will install it in your Alfresco instance.

### Uploading content to the server

If you are uploading content to the server during the import and **not** using the mapContentToStorage feature, the following configuration needs to be done on the Alfresco server:&#x20;

In **...\Tomcat\shared\classes\alfresco-global.properties** set:\
`contentPropertyRestrictions.whitelist=de.fme.mc.alfresco.dao.AlfrescoServiceImpl`

{% hint style="warning" %}
If this property is not set, you will receive an error as follows: \
`The node's content can't be updated via NodeService#setProperty directly`
{% endhint %}

### Mapping content to storage

If you are using the mapContentToStorage feature without uploading it during the import, the **ContentPropertyRestrictionInterceptor** property must be **disabled** on the server.&#x20;

<https://docs.alfresco.com/content-services/7.2/develop/reference/java-foundation-ref/#setting-content-for-node>

### Connecting to Server with Mutual TLS Authentication

If your Alfresco server is configured to use **Mutual TLS Authentication** (<https://docs.alfresco.com/content-services/7.4/config/mtls/>) the following steps need to be followed so that the importer can connect to it:

1. Import the CA certificate into the JDK that the Jobserver uses. \
   Ex.: \
   \&#xNAN;*keytool -import -trustcacerts -keystore "C:\Program Files\Eclipse Adoptium\jdk-17.0.14.7-hotspot\lib\security\cacerts" -storepass changeit -noprompt -alias mycert -file "C:\Users\example\\**rootCA.crt**"*
2. Stop the "Migration Center Job Server" service.
3. Add the following properties for the client certificate in \<job server home>/wrapper.conf:\
   \&#xNAN;*wrapper.java.additional.6=-Djavax.net.ssl.keyStore=C:\Users\example\\**client2.p12***\
   *wrapper.java.additional.7=-Djavax.net.ssl.keyStorePassword=migration123*
4. Start the the "Migration Center Job Server" service.

## Importer Configuration

To create a new Alfresco CS Importer, create a new importer and select *Alfresco CS* from the *Adapter Type* drop-down. Once the adapter type has been selected, the Parameters list will be populated with the parameters specific to the selected adapter type. Mandatory parameters are marked with an \*.

The properties window of an importer can be accessed by double-clicking an importer in the list or selecting the Properties button or entry from the toolbar or context menu.

### Importer parameters

The common adaptor parameters are described in [Common Parameters](https://docs.migration-center.com/common-parameters#common-adaptor-details).

The configuration parameters available for the Alfresco importer are described below:

* **username**\*\
  User name for connecting to the target repository.

  A user account with admin privileges must be used to support the full Alfresco functionality offered by migration-center.
* **password**\*\
  The user’s password.
* **serverURL\***\
  The URL to the Alfresco Server API. \
  i.e. **<http://my-alfresco-server/alfresco>**
* **importLocation**\
  The root path inside Alfresco where all documents/folder will be imported for this importer.

  The path must start below the "company\_home" node inside the spacesStore.\
  i.e. **/sites/demosite/documentLibrary** - the document library of a share site with internal name demosite

  This path will be concatenated in front of the parentfolder system rule value for each object.
* **autoCreateFolders**\
  When checked, the importer will automatically create any missing folders in the folderpath for any object (folder or documents).

  Leave unchecked if the target repository already has the needed folder structure and creating new ones is not desired.
* **defaultFolderType**\
  Specifies the default folder type when creating folders using the autoCreateFolders option described above.

  "cm:folder" for standard folder type

  "fme:folder" for your own folder type
* **batchSize**\
  The number of documents objects to be sent in the same batch. \
  Default: 100.
* **mapContentToStorage**\
  If checked, content is searched in the Alfresco Content Store and directly mapped without any upload. \
  See [mapContentToStorage](#map-content-to-storage).
* **loggingLevel**\*\
  See [Common Parameters](https://docs.migration-center.com/common-parameters#logging-level).

{% hint style="warning" %}
Parameters marked with an asterisk **(\*)** are **mandatory**.
{% endhint %}

## Migset System Rules

{% hint style="success" %}
The new Alfresco CS Importer uses the existing **...toAlfresco** migset types from the old Alfresco Importer.
{% endhint %}

### Documents

* **folderpath**\
  Each object in Alfresco must be created under a parent object (parent-child-association). This parent object must be a Alfresco folder or a subtype of the Alfresco folder object (cm:folder).

  For defining the parent object for an object which should be imported into Alfresco, use the system attribute folder.

  Currently, only one folder path is supported and the starting point for imports is the company\_home-node of the Spaces store. Only imports below this path are currently possible.

  The format of the value must be a valid child node path (without using prefixes for the namespace).\
  **Example:**\
  If the importLocation of the Importer Module (see section 5.2) is set to **/Sites/demosite** and the folderpath value is set to **/documentLibrary/Alfresco Demo**

  The object will be created under the documentLibrary of the demosite

  Full path is: **/Sites/demosite/documentlibrary/Alfresco Demo**
* **inheritPermissions**\
  Boolean flag indicating if permission inheritance should be applied for that object. (true / false)
* **mc\_content\_location**\
  If this rule is has a value, it will be used to fetch the content instead of the default content\_location.\
  If mapContentToStorage
* **permissions**\
  Multivalue attribute used to set object permissions. \
  See [Permissions](#permissions).
* **types / aspects**\
  Multivalue. Allows the setting of one mandatory type and zero, one or multiple aspects.\
  See [System Types And Aspects](#system-types-and-aspects) for the Alfresco system types and aspects that come with your installation of migration-center. \
  \
  **Important**: The first value in this attribute must be the content type.\
  \
  **Example values:**\
  **-** cm:content\
  \- cm:auditable\
  \- cm:titled\
  The object imported will be of type **cm:content** (alfresco standard document type) and will get the aspects **cm:auditable** and **cm:titled**.

### Folders

* **folderpath**\
  Same as [document system rules](#documents).
* **inheritPermissions**\
  Same as [document system rules](#documents).
* **permissions**\
  Same as [document system rules](#documents).
* **types / aspects**\
  Same as [document system rules](#documents).

#### Details on folder migration

Compared to migrating documents and having the folder structure auto-created by the importer, migrating folder objects allows you to set detailed metadata on the folders themselves (such as permissions or aspects).

This approach involves migrating the folder structure first and then migrating the documents in that structure with the **autoCreateFolders** parameter unchecked.&#x20;

In order to execute a folder-only migration the following steps should be performed to configure the migration process accordingly:

1. With the scanner you need to export folders as distinct migration-center objects. Only some scanners support this so please read the specific scanner userguide for details.
2. Creater a migset of type *\<SourceType>ToAlfresco(**folder**)* and add the scan run containin gthe folder objects.&#x20;
3. In the transformation rules use **cm:folder** for the base type and ensure to recreate the **folderpath** structure in a consistent way.

**Example:** \
To import the "MainFolder" folder object to the "/Folder/SubFolder/SubSubFolder" path your attributes should be set like this: \
**folderpath**: /Folder/SubFolder/SubSubFolder\
**cm:name**: MainFolder

{% hint style="warning" %}
The **folderpath** does **not** need to also contain the **cm:name** of the folder object.
{% endhint %}

## Permissions

In Alfresco each object (document or folder) can have several permissions.\
User and groups can be configured via Alfresco Explorer or Alfresco Share (Admin functions). Roles can be defined via permissions.xml (look at the Alfresco wiki to find more information).\
You can configure permissions for all object types (folder and documents).

**Permission value format:** \
Authority(Role, User or Group)###Permission###ACCESSSTATUS (ALLOWED or DENIED)

{% hint style="info" %}
\### is used as separator.\
ACCESSTATUS can be omitted, in which case the permission will default to ALLOWED.
{% endhint %}

**Examples:**\
ROLE\_ADMINISTRATOR###Read\
UserName###Contributor###ALLOWED\
GROUP\_GroupName###Consumer###DENIED\
GROUP\_EVERYONE###CONSUMER###ALLOWED

{% hint style="info" %}
When setting a permission for a group the name of the group must be preceded by "GROUP\_".
{% endhint %}

{% hint style="warning" %}
Note that user, group and permission names are all case sensitive. Giving a "READ" permission instead of "Read" will result in errors.&#x20;
{% endhint %}

## Versions

To import major/minor versions in Alfresco, you need to set the **cm:versionable** aspect with the **cm:versionLabel** attribute.&#x20;

If the version label ends with “**.0**”, a major version is created, otherwise a minor version is created. The actual version label numbers are determined automatically by Alfresco.

If you do not set the **cm:versionLabel** in the aspect association, the importer will create all versions as major.

If you do not assign the **cm:versionable** aspect in the system rule **types / aspects**, the importer assigns it automatically when importing the second version.

Version Comments can be assigned by setting the **versionComments** attribute.

{% hint style="warning" %}
Note that the first version of a version tree cannot have a comment, since it was not checked in, but created.
{% endhint %}

## Delta Migration (Updates)

Due to limitations with the Alfresco API importing updated versions works differently than with other importers.

When importing update objects for any **version in a version tree** the update will create a new minor version in Alfresco.&#x20;

Example:\
Importing an update for an object with version 3.0 will result in the Update object being imported as 3.1.

{% hint style="info" %}
Importing update objects for objects without any versions will not create a new minor version and behaves like other standard Updates.
{% endhint %}

## Map Content To Storage

This features allows the importer to skip the content upload and map the content that already exists in the **Alfresco Content Store**. So far the feature was tested with a **filesystem** store and an **Amazon S3** store.

To use this feature, make sure the **mapContentToStorage** parameter is checked in the importer.

When this feature is active, the values for the **content\_location** or **mc\_content\_location** attributes need to reflect the location of the content inside the **Alfresco Content Store** in the following format:

`<protocol>://<path>`

Example for regular Alfresco Store: \
`store://2024/4/17/10/41/71e92d20-8ac8-41b0-a92c-83b02820d1e5.bin`&#x20;

Example for S3 bucket: \
`s3v2://myFolder/test.txt`

{% hint style="warning" %}
For an S3 store make sure to match the protocol that Alfresco is using either **s3://** or **s3v2://**.

Also note that the S3 path does **not** include the actual bucket.
{% endhint %}

The importer will validate that the content exists and it will calculate the **content size**, **mimetype** and **encoding** based on it.\
If the content cannot be found or it is a folder, the object will fail to import with an error message.

## System Types and Aspects

Your migration-center installation will come with the following Alfresco System Types and Aspects configured as Object Types. \
Any custom object type which is derived from cm:content or cm:folder can also be used.

### Types

**cm:content** - Default Alfresco Document type

* cm:name\
  String. The document name

**cm:folder** - Default Alfresco Folder type

* cm:name\
  String. The folder name

### Aspects

**cm:auditable**&#x20;

* cm:accessed\
  Date. Date at which the object was last accessed
* cm:created\
  Date. Date at which the object was created
* cm:creator\
  User. Creator username
* cm:modified\
  Date. Date at which the object was last modified
* cm:modifier\
  User. Modifier username

**cm:author**

* cm:author\
  User. Author username

**cm:ownable**

* cm:owner\
  User. Owner username

**cm:titled**

* cm:description\
  String. Object description
* cm:title\
  String. Object title

**cm:versionable**

See [Versions](#versions).
