# Custom License Storage

While a default location is predefined for the local license file, the flexibility to modify its location exists within LicenseSpring's C++ and .NET SDK.

This versatility allows for storing the license file in various alternative locations, including databases, Windows registries, or remote servers.

{% hint style="info" %}
Note: This guide operates under the assumption that SQLite3 is properly installed on the reader's device, and a fundamental understanding of SQL is present.

If you require more information about SQLite, it's recommended to refer to their [**official documentation**](https://www.sqlite.org/docs.html) for comprehensive insights.
{% endhint %}

### Prerequisites

{% stepper %}
{% step %}

### Completed the Getting Started tutorial

You should have completed the [**Getting Started**](https://docs.licensespring.com/sdks/tutorials/getting-started) tutorial, specifically:

* Initialized `LicenseManager` (or `LicenseHandler`) with your configuration using the appropriate settings.
* Created a `LicenseID` using either `LicenseID::fromKey` or `LicenseID::fromUser` function, depending on the activation method you prefer.
* Implemented basic license management, including license activations, deactivations, and both online and local license checks.
  {% endstep %}
  {% endstepper %}

### Default License File Encryption

In the `LicenseStorage` interface, the encryption and decryption of the license file are executed by invoking basic functions within the C++ and .NET SDK.

Encryption takes place during the activation and initial storage of the license, utilizing the `activateLicense()` method on the `LicenseManager` object.

Decryption of the license file is done when either `reloadLicense()` or `getCurrentLicense()` are called, also on the `LicenseManager` object.

{% hint style="info" %}
Note: The methods `loadLicense()` and `saveLicense()` present in `LicenseFileStorage` are responsible for reading and writing the license file, without involving encryption or decryption. Encryption is exclusively carried out during license activation and retrieval processes.
{% endhint %}

### Adding License File to a Database

Once you've established the derived class and successfully implemented the `loadLicense()`, `saveLicense()`, and `clear()` methods, the next step involves customizing the default file location.

To accomplish this, when instantiating the `LicenseManager` object, you should provide a second parameter. This additional parameter allows you to specify a different storage location for the local license.

By default, the local license is stored in a file. To check this default location, see [**Local License File**](https://docs.licensespring.com/sdks/tutorials/best-practices/local-license-file).

{% tabs %}
{% tab title="C++" %}

```cpp
licenseManager->create( configuration, storage );
```

{% endtab %}

{% tab title="Java" %}

```java
licenseManager.initialize(configuration, repository);
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Reminder: Encryption operations are conducted independently of the `loadLicense()` and `saveLicense()` methods. These methods do not require encryption or decryption procedures.
{% endhint %}

### License File Terminology

#### LicenseFileStorageBase

`LicenseFileStorageBase` serves as the foundational class responsible for storing licenses in a file and implementing the `LicenseStorage` interface. It is important to note that this class does not incorporate any mechanisms for ensuring synchronized access to files, rendering it unsuitable for concurrent multi-threaded operations.

#### LicenseFileStorage

Derived from `LicenseFileStorageBase`, the `LicenseFileStorage` class inherits its characteristics and functionality, but with the added feature of thread-safe file operations. This class stands as the default choice for license storage, as it guarantees safe file handling even in multi-threaded scenarios.

#### LicenseFileStorageEx

A further specialization of the `LicenseFileStorageBase` class is `LicenseFileStorageEx`. This advanced license file storage variant is specifically designed for interprocess applications. It employs a synchronization mechanism using a mutex provided by the Boost library, ensuring both thread and process safety. This class is ideal for scenarios where concurrent access from multiple threads and processes is required while maintaining the integrity of file operations.
