>**Warning**
>ADAL for Android has been **deprecated** as of June 30, 2023. The library **should not be used in any production scenarios**. While existing applications will continue to work, we offer no support or new features for the library.
>
>Developers who use ADAL for Android should switch to [MSAL for Android](https://github.com/AzureAD/microsoft-authentication-library-for-android). The team has put together a [migration guide](https://learn.microsoft.com/azure/active-directory/develop/migrate-android-adal-msal) to help transition to the new library.

| [Documentation](https://github.com/AzureAD/azure-activedirectory-library-for-android/wiki#documentation) | [Code Samples](https://github.com/azure-samples?utf8=✓&q=active-directory-android) | [Developer Guide](https://aka.ms/aaddev) | [Feedback](https://forms.office.com/r/Xx9tB8g8R4) |
| --- | --- | --- | --- |

# Microsoft Azure Active Directory Authentication Library (ADAL) for Android

ADAL for Android gives you the ability to add support for Work Accounts to your application. This SDK gives your application the full functionality of Microsoft Azure AD, including industry standard protocol support for OAuth2, Web API integration with user level consent, and two-factor authentication support. Best of all, it’s FOSS (Free and Open Source Software) so that you can participate in the development process as we build these libraries.

A Work Account is an identity you use to get work done from your organization or school. Anywhere you need to get access to your work life you'll use a Work Account. The Work Account can be tied to an Active Directory server running in your datacenter or live completely in the cloud like when you use Office 365. A Work Account will be how your users know that they are accessing their important documents and data backed my Microsoft security.

## ADAL for Android 3.0.0 Released!
>Please note: Production ADAL 2.0.x releases (first released March 2020) are neither API-compatible nor cache-compatible with the following versions:

    - 2.0-alpha   (released 2015-07-27)

    - 2.0.1-alpha (released 2015-09-25)

    - 2.0.2-alpha (released 2016-05-27)

    - 2.0.3-alpha (released 2016-06-11)

    - 2.0.4-alpha (released 2017-02-17)

## Build status

| Branch  | Status |
| ------------- | ------------- |
| dev (Travis)  | [![Build Status](https://travis-ci.org/AzureAD/azure-activedirectory-library-for-android.svg?branch=master)](https://travis-ci.org/AzureAD/azure-activedirectory-library-for-android) |
| dev (VSTS)  | [![Build status](https://identitydivision.visualstudio.com/_apis/public/build/definitions/a7934fdd-dcde-4492-a406-7fad6ac00e17/94/badge)](https://identitydivision.visualstudio.com/IDDP/_build/index?definitionId=94&_a=completed) |

Note: A corpnet account is required to view the VSTS build.

## Versions

Current version - 3.1.2

Minimum recommended version - 1.16.3-hf1

You can find version-to-version differences in the [change log](https://github.com/AzureAD/azure-activedirectory-library-for-android/blob/master/changelog.txt).

## Features

* Industry standard Oauth2 protocol support.
* Id Token exposure for full access to the token contents.
* Multi-resource refresh token allows for apps registered together to access different APIs without prompting the user.
* Cache with Encryption for easily accessing existing tokens and session state with assurance it wasn't tampered with.
* Support for the Microsoft Azure AD Authenticator plug-in for Android, which will be released soon!
* Dialog and Fragment support

## Samples and Documentation

[We provide a full suite of sample applications and documentation on GitHub](https://github.com/azure-samples?utf8=%E2%9C%93&q=active+directory&type=&language=) to help you get started with learning the Azure Identity system. This includes tutorials for native clients such as Windows, Windows Phone, iOS, OSX, Android, and Linux. We also provide full walkthroughs for auth flows, the Microsoft Graph API, other Microsoft APIs, and other Azure AD features.

Checkout the [ADAL for Android sample app for help getting started](https://github.com/Azure-Samples/active-directory-android).

Looking for [Xamarin](https://github.com/AzureADSamples/NativeClient-Xamarin-Android)?

## Community Help and Support

We leverage [Stack Overflow](https://stackoverflow.com/questions/tagged/adal) to work with the community on supporting Azure Active Directory and its SDKs, including this one! We highly recommend you ask your questions on Stack Overflow (we're all on there!) Also browse existing issues to see if someone has had your question before.

## Submit Feedback
We'd like your thoughts on this library. Please complete [this short survey.](https://forms.office.com/r/Xx9tB8g8R4)

## SSO and Conditional Access Support

This library allows your application to support our [Enterprise Mobility Suite](https://www.microsoft.com/en-us/cloud-platform/enterprise-mobility-security), including [Conditional Access](https://www.microsoft.com/en-us/cloud-platform/conditional-access), so businesses can use your application in their secure environment.

To configure your application to support these scenarios, please read this document: [How to enable cross-app SSO on Android using ADAL](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-sso-android)

## Security Reporting

If you find a security issue with our libraries or services please report it to [secure@microsoft.com](mailto:secure@microsoft.com) with as much detail as possible. Your submission may be eligible for a bounty through the [Microsoft Bounty](http://aka.ms/bugbounty) program. Please do not post security issues to GitHub Issues or any other public site. We will contact you shortly upon receiving the information. We encourage you to get notifications of when security incidents occur by visiting [this page](https://technet.microsoft.com/en-us/security/dd252948) and subscribing to Security Advisory Alerts.

## Contributing

All code is licensed under the MIT license and we triage actively on GitHub. We enthusiastically welcome contributions and feedback.

For more details [about contribution](https://github.com/AzureAD/azure-activedirectory-library-for-android/blob/master/contributing.md)

## Quick Start

To build with Gradle,

* Clone this repo in to a directory of your choice
* Setup emulator with SDK 23
* Go to the root folder where you cloned this repo
* To run the sample app, connect the test device and run the command: `./gradlew :userappwithbroker:installDebug`
* You should see app 'Fancy ADAL Test App' installed on the test device
* Select an authority, [optionally] enter a login hint and/or query parameters, and click `Acquire Token` to enter credentials with AAD

> Note: The `authority`, `clientId`, `redirectUri` and `resource` of the test app can be found in [`Constants.java`](https://github.com/AzureAD/azure-activedirectory-library-for-android/blob/dev/userappwithbroker/src/main/java/com/microsoft/aad/adal/example/userappwithbroker/Constants.java). These values can be updated as necessary to test different tenants and configurations.

To build with Maven, you can use the pom.xml at top level

* Clone this repo in to a directory of your choice
* Follow the steps at [Prerequisites section to setup your maven for android](https://github.com/AzureAD/azure-activedirectory-library-for-android/wiki/Maven)
* Setup emulator with SDK 19
* Go to the root folder where you cloned this repo
* Run the command: `mvn clean install`
* Change the directory to the Quick Start sample: `cd userappwithbroker/`
* Run the command: `mvn android:deploy android:run`
* You should see app launching
* Enter test user credentials to try!

Jar packages will be also submitted beside the aar package.

## Download

We've made it easy for you to have multiple options to use this library in your Android project:

* You can use the source code to import this library into Android Studio and link to your application.
* If using Android Studio, you can use *aar* package format and reference the binaries.

### Option 1: Source via Git

To get the source code of the SDK via git:

    git clone --recurse-submodules git@github.com:AzureAD/azure-activedirectory-library-for-android.git
    cd ./azure-activedirectory-library-for-android/src

### Option 2: Binaries via Gradle

You can get the binaries from Maven central repo. AAR package can be included as follows in your project in AndroidStudio:

```gradle
repositories {
    mavenCentral()
    maven {
        // Surface Duo SDK dependency.
        url 'https://pkgs.dev.azure.com/MicrosoftDeviceSDK/DuoSDK-Public/_packaging/Duo-SDK-Feed%40Local/maven/v1'
    }
}
dependencies {
    // your dependencies here...
    compile('com.microsoft.aad:adal:3.0.1') {
        // if your app includes android support
        // libraries, Gson or Surface Duo SDK
        // in its dependencies, exclude that
        // groupId from ADAL's compile task by
        // un-commenting the appropriate line below

        // exclude group: 'com.android.support'
        // exclude group: 'com.google.code.gson'
        // exclude group: 'com.microsoft.device.display'
    }
}
```

### Option 3: aar via Maven

If you are using the m2e plugin in Eclipse, you can specify the dependency in your pom.xml file:

```xml
<dependency>
    <groupId>com.microsoft.aad</groupId>
    <artifactId>adal</artifactId>
    <version>3.0.1</version>
    <type>aar</type>
</dependency>
```

### Option 4: jar package inside libs folder

You can get the jar file from maven the repo and drop into the *libs* folder in your project. You need to copy the required resources to your project as well since the jar packages don't include them.

## Prerequisites

* Maven 3.1.1+
* Git
* Android SDK
* AVD image running (API level 14) or higher.
* Android SDK with *ALL* packages installed
* You may use any IDE that supports Maven. Eclipse ADT will work fine after you complete prereq step.

## How To use this library

1. Follow the Prerequisites

2. Add a reference to your project and specify it as an Android library. If you are uncertain how to do this, [click here](http://developer.android.com/tools/projects/projects-eclipse.html) for more information.

3. Add the project dependency for debugging in to your project settings

4. Update your project's AndroidManifest.xml file to include:

```xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
    android:allowBackup="true"
    android:debuggable="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

    <activity
        android:name="com.microsoft.aad.adal.AuthenticationActivity"
        android:label="@string/title_login_hello_app" >
    </activity>
....
<application/>
```

5. Register your WEBAPI service app in Azure Active Directory (AAD). If you're not sure what a tenant is or how you would get one, read [What is a Microsoft Azure AD tenant](http://technet.microsoft.com/library/jj573650.aspx)? or [Sign up for Microsoft Azure as an organization](http://www.windowsazure.com/en-us/manage/services/identity/organizational-account/). These docs should get you started on your way to using Windows Azure AD.
  * NOTE: You need to write down the APP ID URI for the next steps
6. Register your client native app at AAD. Select webapis in the list and give permission to previously registered WebAPI. If you need help with this step, see: [Register the REST API Service Windows Azure Active Directory](https://github.com/AzureADSamples/WebAPI-Nodejs/wiki/Setup-Windows-Azure-AD)
  * NOTE: You will need to write down the clientId and redirectUri parameters for the next steps.
7. Create an instance of AuthenticationContext at your main Activity. The details of this call are beyond the scope of this README, but you can get a good start by looking at the [Android Native Client Sample](https://github.com/AzureADSamples/NativeClient-Android). Below is an example:

    ```java
    // Authority is in the form of https://login.windows.net/yourtenant.onmicrosoft.com
    mContext = new AuthenticationContext(MainActivity.this, authority, true); // This will use SharedPreferences as default cache
    ```

  * NOTE: mContext is a field in your activity

8. Copy this code block to handle the end of AuthenticationActivity after user enters credentials and receives authorization code:

    ```Java
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
         if (mContext != null) {
             mContext.onActivityResult(requestCode, resultCode, data);
         }
     }
    ```

9. To ask for a token, you define a callback

    * NOTE: In releases `1.13.2`, `1.13.3`, and `1.14.0` the `onError(Exception)` and `onSuccess(AuthenticationResult)` callbacks may not be invoked on the UI thread. This issue is tracked [here](https://github.com/AzureAD/azure-activedirectory-library-for-android/issues/1076).

    ```Java
    private AuthenticationCallback<AuthenticationResult> callback = new AuthenticationCallback<AuthenticationResult>() {

            @Override
            public void onError(Exception exc) {
                if (exc instanceof AuthenticationException) {
                    textViewStatus.setText("Cancelled");
                    Log.d(TAG, "Cancelled");
                } else {
                    textViewStatus.setText("Authentication error:" + exc.getMessage());
                    Log.d(TAG, "Authentication error:" + exc.getMessage());
                }
            }

            @Override
            public void onSuccess(AuthenticationResult result) {
                mResult = result;

                if (result == null || result.getAccessToken() == null
                        || result.getAccessToken().isEmpty()) {
                    textViewStatus.setText("Token is empty");
                    Log.d(TAG, "Token is empty");
                } else {
                    // request is successful
                    Log.d(TAG, "Status:" + result.getStatus() + " Expired:"
                            + result.getExpiresOn().toString());
                    textViewStatus.setText(PASSED);
                }
            }
        };
    ```

10. Finally, ask for a token using that callback:

    ```Java
     mContext.acquireToken(MainActivity.this, resource, clientId, redirect, user_loginhint, PromptBehavior.Auto, "",
                    callback);
    ```

    If you're implementing your authentication logic in a Fragment, you'll need to wrap it in an `IWindowComponent` before passing it as a parameter, like this:

```java
mContext.acquireToken(
    wrapFragment(MainFragment.this),
    resource,
    clientId,
    redirect,
    user_loginhint,
    PromptBehavior.Auto,
    "",
    callback);

private IWindowComponent wrapFragment(final Fragment fragment){
    return new IWindowComponent() {
        Fragment refFragment = fragment;
        @Override
        public void startActivityForResult(Intent intent, int requestCode) {
            refFragment.startActivityForResult(intent, requestCode);
        }
    };
}
```

Explanation of the parameters:

* Resource is required and is the resource you are trying to access.
* Clientid is required and comes from the AzureAD Portal.
* You can setup redirectUri as your packagename. It is not required to be provided for the acquireToken call.
* PromptBehavior helps to ask for credentials to skip cache and cookie.
* Callback will be called after authorization code is exchanged for a token.

Examples can be found at [Android Native Client Sample](https://github.com/AzureADSamples/NativeClient-Android).

The Callback receives an object of type AuthenticationResult which has accesstoken, date expired, and idtoken info.

**acquireTokenSilentSync**

In order to get token back without prompt, you can call **acquireTokenSilentSync** which handles caching and token refresh without UI prompt. It provides async version as well. **Note:** userId required in silent call is the one you get back from the interactive call) as parameter.

```java
mContext.acquireTokenSilentSync(String resource, String clientId, String userId);
```

or

```java
mContext.acquireTokenSilent(
    String resource,
    String clientId,
    String userId,
    final AuthenticationCallback<AuthenticationResult> callback);
```

11. Broker:

Microsoft Intune's Company portal App and Azure Authenticator App will provide the broker component.
In order to acquire token via broker, the following requirements have to be met (please check samples\userappwithbroker for authentication via broker):

* Starting version 1.1.14, developer has to explicitly specify set to use broker via:
    `AuthenticationSettings.INSTANCE.setUseBroker(true);`
* Developer needs to register special redirectUri for broker usage. RedirectUri is in the format of msauth://packagename/Base64UrlencodedSignature. You can get your redirecturi for your app using the script `GetBrokerRedirectURI.ps1` on Windows or `brokerRedirectPrint.sh` on Linux or Mac. You can also use API call mContext.getBrokerRedirectUri. Signature is related to your signing certificates.
* If target version is lower than 23, calling app has to have the following permissions declared in [the manifest](http://developer.android.com/reference/android/accounts/AccountManager.html):
  * `GET_ACCOUNTS`
  * `USE_CREDENTIALS`
  * `MANAGE_ACCOUNTS`
* If target version is 23 or higher, `USE_CREDENTIALS` and `MANAGE_ACCOUNTS` are deprecated. But `GET_ACCOUNTS` is under protection level "dangerous", calling app is responsible for requesting the run-time permission; see [Runtime permission request for API 23](http://developer.android.com/training/permissions/requesting.html).
* If you get an exception like "Broker related permissions are missing for GET_ACCOUNTS" with error code "DEVELOPER_BROKER_PERMISSIONS_MISSING" when acquiring token, it means you're using a very old version of ADAL(prior to V1.12.0) or broker app(Microsoft Authenticator or Intune Company Portal), please upgrade to the latest version of ADAL and broker app.
* There must be an account existed and registered via one of the two broker apps.

AuthenticationContext provides API method to get the broker user.

`String brokerAccount =  mContext.getBrokerUser();`

Broker user will be returned if account is valid.

Using this walkthrough, you should have what you need to successfully integrate with Azure Active Directory. For more examples of this working, visit the AzureADSamples/ repository on GitHub.

## Important Information

### Customization

Library project resources can be overwritten by your application resources. This happens when your app is building. For this reason, you can customize Authentication Activity layout the way you want. You need to make sure to keep the id of the controls that ADAL uses(Webview).

### Broker

Broker component will be delivered with Intune's Company portal app. Account will be created in Account Manager. Account type is "com.microsoft.workaccount". It only allows single SSO account. It will create SSO cookie for this user after completing device challenge for one of the apps.

### Authority Url and ADFS

ADFS is not recognized as production STS, so you need to turn of instance discovery and pass false at AuthenticationContext constructor.

Authority url needs STS instance and tenant name: https://login.windows.net/yourtenant.onmicrosoft.com

### Federated sign-in failure if additional certificate downloads are required

Federated sign-in may fail when attempting to authenticate using the Azure Active Directory Authentication Library (ADAL) for Android. See [Using ADAL to authenticate from Android devices fails if additional certificate downloads are required](https://support.microsoft.com/en-us/help/3203929/using-adal-to-authenticate-from-android-devices-fails-if-additional-certificate-downloads-are-required) for more information.

### Querying cache items

ADAL provides Default cache in SharedPrefrences with some simple cache query methods. You can get the current cache from AuthenticationContext with:

```java
ITokenCacheStore cache = mContext.getCache();
```

You can also provide your cache implementation, if you want to customize it.

```java
mContext = new AuthenticationContext(MainActivity.this, authority, true, yourCache);
```

### PromptBehavior

ADAL provides option to specify prompt behavior. PromptBehavior.Auto will pop up UI if refresh token is invalid and user credentials are required. PromptBehavior.Always will skip the cache usage and always show UI.

### Handle Doze and App Standby

Starting Android 6.0, Android introduces the new battery optimization, which will cause no network access when it's in doze and app standby mode. This wiki page contains details for doze mode and how to handle it with ADAL (https://github.com/AzureAD/azure-activedirectory-library-for-android/wiki/Handle-Doze-and-App-Standby).

### Silent token request from cache and refresh

This method does not use UI pop up and not require an activity. It will return token from cache if available. If token is expired, it will try to refresh it. If refresh token is expired or failed, it will return AuthenticationException.

```java
Future<AuthenticationResult> result = mContext.acquireTokenSilent(resource, clientid, userId, callback );
```

You can also make sync call with this method. You can set null to callback or use acquireTokenSilentSync.

### ProGuard

If you are using ProGuard, we suggest disabling shrinking and obfuscation of ADAL classes so that our development team may assist you should issues arise. Additionally, portions of our unit and automation test code rely heavily on reflection and may not execute predictably across different versions of ProGuard.

To disable obfuscation of ADAL classes:

```
-keep class com.microsoft.** {
  *;
}
```

### Diagnostics

The following are the primary sources of information for diagnosing issues:

* Exceptions
* Logs
* Network traces

Also, note that correlation IDs are central to the diagnostics in the library. You can set your correlation IDs on a per request basis if you want to correlate an ADAL request with other operations in your code. If you don't set a correlations id then ADAL will generate a random one and all log messages and network calls will be stamped with the correlation id. The self generated id changes on each request.

#### Exceptions

This is obviously the first diagnostic. We try to provide helpful error messages. If you find one that is not helpful please file an issue and let us know. Please also provide device information such as model and SDK#.

#### Logs

You can configure the library to generate log messages that you can use to help diagnose issues. You configure logging by making the following call to configure a callback that ADAL will use to hand off each log message as it is generated.

 ```java
 Logger.getInstance().setExternalLogger(new ILogger() {
     @Override
     public void Log(String tag, String message, String additionalMessage, LogLevel level, ADALError errorCode) {
      ...
      // You can write this to logfile depending on level or errorcode.
      writeToLogFile(getApplicationContext(), tag +":" + message + "-" + additionalMessage);
     }
 }
 ```
Messages can be written to a custom log file as seen below. Unfortunately, there is no standard way of getting logs from a device. There are some services that can help you with this. You can also invent your own, such as sending the file to a server.

```java
private syncronized void writeToLogFile(Context ctx, String msg) {
       File directory = ctx.getDir(ctx.getPackageName(), Context.MODE_PRIVATE);
       File logFile = new File(directory, "logfile");
       FileOutputStream outputStream = new FileOutputStream(logFile, true);
       OutputStreamWriter osw = new OutputStreamWriter(outputStream);
       osw.write(msg);
       osw.flush();
       osw.close();
}
```

##### Logging Levels

* Error(Exceptions)
* Warn(Warning)
* Info(Information purposes)
* Verbose(More details)

You set the log level like this:
`Logger.getInstance().setLogLevel(Logger.LogLevel.Verbose);`

 All log messages are sent to logcat in addition to any custom log callbacks.
 You can get log to a file form logcat as shown below:
 `adb logcat > "C:\logmsg\logfile.txt"`

 More examples about adb cmds: https://developer.android.com/tools/debugging/debugging-log.html#startingLogcat

#### Telemetry

ADAL provides a built-in callback mechanism to supply consuming applications with event data (telemetry) generated during requests. The event data is sanitized of Personally Identifiable Information (PII) and Organizationally Identifiable Information (OII) and is designed to give consumers of the library insight into the performance, reliability, and usage of ADAL.

For detailed guidance on the usage, configuration, and schema of ADAL telemetry, see [Wiki:Telemetry](https://github.com/AzureAD/azure-activedirectory-library-for-android/wiki/Telemetry)

#### Network Traces

You can use various tools to capture the HTTP traffic that ADAL generates.  This is most useful if you are familiar with the OAuth protocol or if you need to provide diagnostic information to Microsoft or other support channels.

Fiddler is the easiest HTTP tracing tool.  Use the following links to setup it up to correctly record ADAL network traffic.  In order to be useful it is necessary to configure fiddler, or any other tool such as Charles, to record unencrypted SSL traffic.  NOTE: Traces generated in this way may contain highly privileged information such as access tokens, usernames and passwords.  If you are using production accounts, do not share these traces with 3rd parties.  If you need to supply a trace to someone in order to get support, reproduce the issue with a temporary account with usernames and passwords that you don't mind sharing.

* [Setting Up Fiddler For Android](http://docs.telerik.com/fiddler/configure-fiddler/tasks/ConfigureForAndroid)
* [Configure Fiddler Rules For ADAL](https://github.com/AzureAD/azure-activedirectory-library-for-android/wiki/How-to-listen-to-httpUrlConnection-in-Android-app-from-Fiddler)

### Dialog mode

acquireToken method without activity supports dialog prompt.

### Encryption
>Important! Providing custom secret keys to ADAL is **deprecated**. Consumers of ADAL are advised to avoid setting their own keys. As no API is currently provided to transition off of custom secret key usage, this API remains available for use only in backwards compatibility scenarios.

ADAL encrypts the tokens and store in SharedPreferences by default. You can look at the StorageHelper class to see the details. ADAL uses AndroidKeyStore for 4.3(API18) and above for secure storage of private keys. If you want to use ADAL for lower SDK versions, you need to **provide secret key at AuthenticationSettings.INSTANCE.setSecretKey**

Following example is using the password based encryption key(which takes the specified password and salt). And then create the provider-independent secret key with the generated password based encryption key. ADAL requires the key to be 256 bits. You can use other key generation algorithm.

```java
    SecretKeyFactory keyFactory = SecretKeyFactory
        .getInstance("PBEWithSHA256And256BitAES-CBC-BC");
    SecretKey generatedSecretKey = keyFactory.generateSecret(new PBEKeySpec(your_password,
        byte-code-for-your-salt, 100, 256));
    SecretKey secretKey = new SecretKeySpec(generatedSecretKey.getEncoded(), "AES");
    AuthenticationSettings.INSTANCE.setSecretKey(secretKey.getEncoded());
```

### Oauth2 Bearer challenge

`AuthenticationParameters` class provides functionality to get the authorization_uri from Oauth2 bearer challange.

### Session cookies in Webview

Android webview does not clear session cookies after app is closed. You can handle this with sample code below:

```java
CookieSyncManager.createInstance(getApplicationContext());
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeSessionCookie();
CookieSyncManager.getInstance().sync();
```

More about cookies: http://developer.android.com/reference/android/webkit/CookieSyncManager.html

### Resource Overrides

The ADAL library includes English strings for the following two ProgressDialog messages.

Your application should overwrite them if localized strings are desired.

```xml
<string name="app_loading">Loading...</string>
<string name="broker_processing">Broker is processing</string>
<string name="http_auth_dialog_username">Username</string>
<string name="http_auth_dialog_password">Password</string>
<string name="http_auth_dialog_title">Sign In</string>
<string name="http_auth_dialog_login">Login</string>
<string name="http_auth_dialog_cancel">Cancel</string>
```

=======

### NTLM dialog

ADAL version 1.1.0 supports NTLM dialog that is processed through onReceivedHttpAuthRequest event from WebViewClient. Dialog layout and strings can be customized.

## License

Copyright (c) Microsoft Corporation. All rights reserved. This code is licensed under the MIT License.

## We Value and Adhere to the Microsoft Open Source Code of Conduct

This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.


[![Build status](https://builds.gbif.org/job/occurrence-master/badge/icon)](https://builds.gbif.org/job/occurrence-master/lastBuild/console)
[![Crowdin](https://badges.crowdin.net/gbif-registry/localized.svg)](https://crowdin.com/project/gbif-registry)

# GBIF Occurrence

The GBIF Occurrence project is a component of the architecture responsible for search and download of GBIF-mediated occurrence records. For data processing please see the [pipelines](https://github.com/gbif/pipelines) project.

This project handles occurrence web services, downloads, search and maps.

This project has many submodules and each of those has a README which you should read for more detail.

## Building

Jenkins builds this project without a profile, and the produced artifacts (JARs) are used together with the corresponding configuration found in the gbif-configuration project.

This project contains integration tests which use the GBIF `dev` environment and requires configuration of the `appkeys` providing the tokens to interact with the services and to be on a GBIF network.

To skip the integration tests (e.g. working without access to the GBIF dev network) please build using:

e.g. `mvn -Pdev -pl \!occurrence-integration-tests clean install`

## Contributing
* All changes must go to the **dev** branch for testing before merging to master.
* PR are preferred for complex functionality. **Please target the dev branch**.
* Simple changes can be committed without review.

## Testing

Run unit and integration tests:

```bash
mvn -Pdev clean verify
```

## Other documentation in this project

* [Occurrence persistence](occurrence-persistence/README.md)
* [Occurrence WS](occurrence-ws/README.md)
* [Occurrence CLI](occurrence-cli/README.md)
* [Occurrence download](occurrence-download/README.md)
* [Occurrence common](occurrence-common/README.md)
* [Occurrence registry sync](occurrence-registry-sync/README.md)
* [Occurrence Hive](occurrence-hive/README.md)
* [Occurrence search](occurrence-search/README.md)
* [Occurrence heatmaps](occurrence-heatmaps/README.md)
* [Occurrence processor](occurrence-processor/README.md)
* [Occurrence processor (Default values)](occurrence-processor/doc/DefaultValues.md)


[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/copper-engine/copper-engine/blob/master/LICENSE)
[![Build Status](https://img.shields.io/github/workflow/status/copper-engine/copper-engine/Build%20and%20upload)](https://github.com/copper-engine/copper-engine/actions?query=workflow%3A%22Build+and+upload%22)

copper-engine
=============

COPPER - the high performance Java workflow engine.

COPPER is an open-source, powerful, light-weight, and easily configurable **workflow engine**. The power of COPPER is that it uses **Java** as a description language for workflows. The project artifacts can be found on [Maven Central](https://search.maven.org/search?q=g:org.copper-engine%20AND%20a:copper-coreengine&core=gav). See [copper-engine.org](http://www.copper-engine.org) for more information.

How to build
------------

COPPER is built using [Gradle](http://www.gradle.org). However, you don't need to install Gradle, because COPPER is using the [Gradle wrapper](http://www.gradle.org/docs/current/userguide/gradle_wrapper.html).
Note: If you are behind an internet proxy, you have to configure the corresponding system properties in gradle. See [Accessing the web via a proxy](https://docs.gradle.org/current/userguide/build_environment.html#sec:accessing_the_web_via_a_proxy).

To build all COPPER projects, just execute the following in the projects root directory:

    ./gradlew assemble

If you want to build all and run all tests, just execute:

    ./gradlew build

To generate Eclipse project files, run:

    ./gradlew eclipse

once in the projects root directory and open the corresponding projects with the eclipse IDE. (You must perform this step every time the project dependencies change).

How to contribute
-----------------

1. Create an issue on GitHub.
2. Create a fork  on GitHub.
3. Configure your IDE (Eclipse, IntelliJ IDEA) as described [below](#how-to-configure-your-ide).
4. Run `./gradlew assemble` once if you haven't done so in step 3. This will generate some WSDL stubs needed for some tests.
5. Commit your changes incl. [WHATSNEW.txt](WHATSNEW.txt)
   * Ensure, that your sources are UTF-8 encoded!
   * Ensure, that your sources start with our [Apache License header](common/apache-license-file.txt). (The build will fail if they don't.)
6. Build all and run tests:
       ./gradlew clean build
7. Push your changes to your fork.
8. Create a pull request on GtHub.

**Have fun!**

How to configure your IDE
-------------------------

### Eclipse

Run `./gradlew eclipse` once. This will create Eclipse project files which you can import. This also creates proper code style settings. Before committing you should always reformat the code. You can configure Eclipse to do this automatically on each save.

Every time a dependency changes in `build.gradle` you must run `./gradlew eclipse` again. You don't need to restart Eclipse for this, simply press F5 on the projects.

### IntelliJ IDEA

Before you open the project in IntelliJ for the first time, run `./gradlew assemble` once. This also creates proper code style settings, which IntelliJ automatically picks up. After that open `build.gradle`  with "File->Open" and follow the instructions, accept the defaults.

Before committing you should always reformat the code. You can configure IntelliJ to do this automatically on each commit.

Performance Test
----------------

See [PERFORMANCE_TEST_HOWTO.MD](https://github.com/copper-engine/copper-engine/blob/master/projects/copper-performance-test/PERFORMANCE_TEST_HOWTO.MD)

License
-----------------
Copyright 2002-2018 Copper Engine Development Team

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


MyBatis CDI Extension
=====================

[![Java CI](https://github.com/mybatis/cdi/workflows/Java%20CI/badge.svg)](https://github.com/mybatis/cdi/actions?query=workflow%3A%22Java+CI%22)
[![Coverage Status](https://coveralls.io/repos/mybatis/cdi/badge.svg?branch=master&service=github)](https://coveralls.io/github/mybatis/cdi?branch=master)
[![Maven central](https://maven-badges.herokuapp.com/maven-central/org.mybatis/mybatis-cdi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.mybatis/mybatis-cdi)
[![Sonatype Nexus (Snapshots)](https://img.shields.io/nexus/s/https/oss.sonatype.org/org.mybatis/mybatis-cdi.svg)](https://oss.sonatype.org/content/repositories/snapshots/org/mybatis/mybatis-cdi/)
[![License](https://img.shields.io/:license-apache-brightgreen.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)

![mybatis-logo](https://mybatis.org/images/mybatis-logo.png)

MyBatis-CDI extension takes care of the lifecycle of MyBatis mappers and SqlSessions. MyBatis components are directly injected into your
CDI beans ready to be used, there is no need to create or destroy them. It also provides local and JTA transaction support based on the
@Transactional annotation.

Compatibility
-------------

| CDI API VERSION         | JDK 17 | JDK 11  | JDK 8  |
| ----------------------- | ------ | ------- | ------ |
| cdi-1.0 (not supported) | N      | N       | N      |
| cdi-1.1                 | Y      | Y       | Y      |
| cdi-1.2                 | Y      | Y       | Y      |
| cdi-2.0                 | Y      | Y       | Y      |
| cdi-3.0                 | Y      | Y       | N      |
| cdi-4.0                 | Y      | Y       | N      |
| cdi-4.1                 | Y      | N       | N      |

JavaEE is 1.1.4 and is now no longer our focus

JakartaEE is 2.0.0 and is the main focus

Jdk17+ requires jboss-classfilewriter to be at 1.2.5 or it will error, [classfilewriter](https://github.com/jbossas/jboss-classfilewriter/issues/24)

Building from [tag](https://github.com/mybatis/cdi/tree/mybatis-cdi-1.1.4) for javax namespace
----------------------------------------------------------------------------------------------

Maven does not allow multiple auto activated profiles (ie activateByDefault and Jdk).  This project supports 3 different CDI support levels currently
and was set to default to cdi-1.2.  Jdk 8 does not allow add opens and this is needed now for jdk 17.  We further are supporting jakarta EE packaging
in addition to java EE packaging.  This results is a tricky situation.  Therefore, we have opted to no longer use activateByDefault which means a
build without providing a profile will fail with missing classes.  Github actions is provisioned to always provide the specific cdi-api profile.
Any localized usage must now do the same as defined below.

The cdi profile can be cdi-1.1, cdi-1.2, or cdi-2.0 and required to run with any of the following.

- mvn clean install -P"cdi-1.1"
- mvn clean install -P"cdi-1.2"
- mvn clean install -P"cdi-2.0"

Building from master
--------------------

Normal maven build without any special profiles necessary.  This line is Jakarta.

Testing with Arquillian (for javaEE, has not been checked with jakarta)
-----------------------------------------------------------------------

In order to test with Arquillian, one class needs to be added to 'JavaArchive' in order for this to load properly.  Add 'SqlSessionManagerRegistry.class'.

See attachment on https://github.com/mybatis/cdi/issues/86 from 2021-12-30 ArquillianMybatisExample.zip [here](https://github.com/mybatis/cdi/files/7795050/ArquillianMybatisExample.zip).  This is to be run under jdk 8 to be error free but will run as-is under jdk 11 with an invocation error which still allows it to run.  Further updates are needed to get this code example current.

Essentials
----------

- [See the docs](https://mybatis.org/cdi/)
<!-- - [See the docs(简体中文)](https://mybatis.org/cdi/zh/index.html) -->

Contributed Examples
--------------------

- Ready to deploy sample web app (Jee7): [samples](https://github.com/mnesarco/mybatis-cdi-samples/)


# GBIF API

The GBIF API library provides:
 * The model objects used by the GBIF service interfaces and the internal messaging systems
 * Enumerations representing standardized vocabularies (country codes, databased enumerations etc)
 * The Java interface definitions for the public GBIF API (note: each implementation is responsible for mapping to the RESTful URL)
 * Utilities to simplify common operations when working with model objects (JSON serialization, filtered iterators etc)

## To build the project
```
mvn clean install
```

## Policies
 * All changes must go to the **dev** branch for testing before merging to master.
 * A pre-commit peer review on all commits, ideally referencing the review in the commit message. Simple changes can be committed without review.
 * All commits must reference a GitHub issue to which they relate
 * PR are preferred for complex functionality. **Please target the dev branch**.

 Dev and master versions must be different to avoid issues with many work-in-progress tasks. When master version is released increment _patch_ version, when released version is merged with development, increment minor version manually.

 **Example** of releasing **dev** branch:
  * Current dev and master versions
    ```
    1) dev version    - 1.7.0-SNAPSHOT
    2) master version - 1.6.0-SNAPSHOT
    ```
  * Merge changes into master
    ```
    1) dev version    - 1.7.0-SNAPSHOT
    2) master version - 1.7.0-SNAPSHOT
    ```
  * Release master and increment _patch_ version
    ```
    1) dev version    - 1.7.0-SNAPSHOT
    2) master version - 1.7.1-SNAPSHOT
    ```
  * Merge changes into dev
    ```
    1) dev version    - 1.7.1-SNAPSHOT
    2) master version - 1.7.1-SNAPSHOT
    ```
  * Bump dev _minor_ version
    ```
    1) dev version    - 1.8.0-SNAPSHOT
    2) master version - 1.7.1-SNAPSHOT
    ```
 **Example** of releasing a fix for **master** branch:
  * Current dev and master versions
    ```
    1) dev version    - 1.8.0-SNAPSHOT
    2) master version - 1.7.1-SNAPSHOT
    ```
  * Release master and increment _patch_ version
    ```
    1) dev version    - 1.8.0-SNAPSHOT
    2) master version - 1.7.2-SNAPSHOT
    ```
  * Merge changes into dev, without version bumping
    ```
    1) dev version    - 1.8.0-SNAPSHOT
    2) master version - 1.7.2-SNAPSHOT
    ```

## Change Log
[Change Log](CHANGELOG.md)

## Documentation

* [JavaDocs](https://gbif.github.io/gbif-api/apidocs/)
* [GBIF.org](https://www.gbif.org/developer/summary)


![logotype.svg](https://javers.org/img/logotype.svg)

[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.javers/javers-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.javers/javers-core)
[![Build Status](https://travis-ci.org/javers/javers.svg?branch=master)](https://travis-ci.org/javers/javers/)
[![Financial Contributors on Open Collective](https://opencollective.com/javers/all/badge.svg?label=financial+contributors)](https://opencollective.com/javers)

## What is JaVers

JaVers is the lightweight Java library for **auditing** changes in your data.

We all use Version Control Systems for source code,
so why not use a specialized framework to provide
an audit trail of your Java objects (entities, POJO, data objects)?

## Check out our site
You can find the latest information about JaVers project at [javers.org](http://javers.org).
Check out our [documentation](http://javers.org/documentation) pages.

## Build & test JaVers
Clone our github repository

```
git clone https://github.com/javers/javers.git
cd javers
```

Build JaVers and run unit tests

```
./gradlew build
```

Run the environment self-test, to check if JaVers is compatible with your JDK version

```
./gradlew javers-core:run
```

## Issues and Contributing
We'd love to get issues and contributions from you!

You can report a Bug or a Feature Request.
Questions should be asked at [stackoverflow.com](http://stackoverflow.com/questions/tagged/javers?sort=newest).
We'll answer them.
Before you create an issue please read our
[Guidelines for Bug Reporting](CONTRIBUTING.md#guidelines-for-bug-reporting).

JaVers is an open source project, so we are open to your contributions.
Before you start, please read our
[Contributing Guide](CONTRIBUTING.md#guidelines-for-contributors) and see how to get your changes merged.

### Code Contributors

This project exists thanks to all the people who contribute their work:

## Financial Contributing

Become a financial contributor and help us sustain the
JaVers project.
[[Contribute](https://opencollective.com/javers/contribute)]

#### Individual contributors

#### Organizations

Support Javers as an organization.
Your logo will show up here with a link to your website.

## License
JaVers is licensed under Apache License Version 2.0, see the LICENSE file.


# Jenkins Lockable Resources Plugin

[![Jenkins Plugin](https://img.shields.io/jenkins/plugin/v/lockable-resources.svg)](https://plugins.jenkins.io/lockable-resources)
[![GitHub release](https://img.shields.io/github/release/jenkinsci/lockable-resources-plugin.svg?label=release)](https://github.com/jenkinsci/lockable-resources-plugin/releases/latest)
[![Jenkins Plugin Installs](https://img.shields.io/jenkins/plugin/i/lockable-resources.svg?color=blue)](https://plugins.jenkins.io/lockable-resources)
[![Build Status](https://ci.jenkins.io/buildStatus/icon?job=Plugins%2Flockable-resources-plugin%2Fmaster)](https://ci.jenkins.io/job/Plugins/job/lockable-resources-plugin/job/master/)
[![GitHub license](https://img.shields.io/github/license/jenkinsci/lockable-resources-plugin.svg)](https://github.com/jenkinsci/lockable-resources-plugin/blob/master/LICENSE.txt)
[![Maintenance](https://img.shields.io/maintenance/yes/2023.svg)](https://github.com/jenkinsci/lockable-resources-plugin)
[![Crowdin](https://badges.crowdin.net/e/656dcffac5a09ad0fbdedcb430af1904/localized.svg)](https://jenkins.crowdin.com/lockable-resources-plugin)
[![Join the chat at https://gitter.im/jenkinsci/lockable-resources](https://badges.gitter.im/jenkinsci/lockable-resources.svg)](https://gitter.im/jenkinsci/lockable-resources?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

This plugin allows defining lockable resources (such as printers, phones,
computers, etc.) that can be used by builds. If a build requires a resource
which is already locked, it will wait for the resource to be free.

----
## Support

“Open source” does not mean “includes free support”

You can support the contributor and buy him a coffee.
[![coffee](https://www.buymeacoffee.com/assets/img/custom_images/black_img.png)](https://www.buymeacoffee.com/mpokornyetm)
Every second invested in an open-source project is a second you can't invest in your own family / friends / hobby.
That`s the reason, why supporting the contributors is so important.

Thx very much for supporting us.

----

## Usage

### Adding lockable resources

1. In *Manage Jenkins* > *Configure System* go to **Lockable Resources
   Manager**
2. Select *Add Lockable Resource*

Each lockable resource has the following properties:

- **Name** - A mandatory name (not containing spaces!) for this particular resource, i.e.
  `DK_Printer_ColorA3_2342`
- **Description** - Optional verbose description of this particular resource,
  i.e. `Printers in the Danish Office`
- **Labels** - Optional space-delimited list of Labels (A label can not containing spaces) used to
  identify a pool of resources. i.e. `DK_Printers_Office Country:DK device:printer`,
  `DK_Printer_Production`, `DK_Printer_Engineering`
- **Reserved by** - Optional reserved / locked cause. If non-empty,
  the resource will be unavailable for jobs. i.e. `All printers are currently not available due to maintenance.`
  This option is still possible, but we recommend to use the page `<jenkinsRootUrl>/lockable-resources/`

A resource is always the one thing that is locked (or free or reserved).
It exists once and has an unique name (if we take the hardware example, this may be `office_printer_14`).
Every resource can have multiple labels (the printer could be labeled `dot-matrix-printer`, `in-office-printer`, `a4-printer`, etc.).
All resources with the same label form a "pool", so if you try to lock an `a4-printer`, one of the resources with the label `a4-printer` will be locked when it is available.
If all resources with the label `a4-printer` are in use, your job waits until one is available.
This is similar to nodes and node labels.

### Using a resource in a freestyle job

When configuring the job, select **This build requires lockable resources**.
Please see the help item for each field for details.

### Using a resource in a pipeline job

When the `lock` step is used in a Pipeline, if the resource to be locked isn't
already defined in the Jenkins global configuration, an ephemeral resource is
used: These resources only exist as long as any running build is referencing
them.

Examples:

#### Acquire lock

Example for scripted pipeline:

```groovy
echo 'Starting'
lock('my-resource-name') {
  echo 'Do something here that requires unique access to the resource'
  // any other build will wait until the one locking the resource leaves this block
}
echo 'Finish'

```

Example for declarative pipeline:

```groovy
pipeline {
  agent any

  stages {
    stage("Build") {
      steps {
        lock(label: 'printer', quantity: 1, resource : null) {
          echo 'printer locked'
        }
      }
    }
  }
}
```

#### Take first position in queue

```groovy
lock(resource: 'staging-server', inversePrecedence: true) {
    node {
        servers.deploy 'staging'
    }
    input message: "Does ${jettyUrl}staging/ look good?"
}
```

> It is not allowed to mixed **inversePrecedence** and **priority**.

start time | job | resource | inversePrecedence
------ |--- |--- |---
00:01 | j1 | resource1 | false
00:02 | j2 | resource1 | false
00:03 | j3 | resource1 | true
00:04 | j4 | resource1 | false
00:05 | j5 | resource1 | true
00:06 | j6 | resource1 | false

Resulting lock order: j1 -> j5 -> j3 -> j2 -> j4 -> j6

#### lock (queue) priority

```groovy
lock(resource: 'staging-server', priority: 10) {
    node {
        servers.deploy 'staging'
    }
    input message: "Does ${jettyUrl}staging/ look good?"
}
```

  start time | job | resource  | priority
  ------     |---  |---        |---
  00:01      | j1  | resource1 | 0
  00:02      | j2  | resource1 | <default == 0>
  00:03      | j3  | resource1 | -1
  00:04      | j4  | resource1 | 10
  00:05      | j5  | resource1 | -2
  00:06      | j6  | resource1 | 100

  Resulting lock order: j1 -> j6 -> j4 -> j2 -> j3 -> j5

#### Resolve a variable configured with the resource name and properties

```groovy
lock(label: 'some_resource', variable: 'LOCKED_RESOURCE') {
  echo env.LOCKED_RESOURCE
  echo env.LOCKED_RESOURCE0_PROP_ABC
}
```

When multiple locks are acquired, each will be assigned to a numbered variable:

```groovy
lock(label: 'some_resource', variable: 'LOCKED_RESOURCE', quantity: 2) {
  // comma separated names of all acquired locks
  echo env.LOCKED_RESOURCE

  // first lock
  echo env.LOCKED_RESOURCE0
  echo env.LOCKED_RESOURCE0_PROP_ABC

  // second lock
  echo env.LOCKED_RESOURCE1
  echo env.LOCKED_RESOURCE1_PROP_ABC
}
```

#### Skip executing the block if there is a queue

```groovy
lock(resource: 'some_resource', skipIfLocked: true) {
  echo 'Do something now or never!'
}
```

Detailed documentation can be found as part of the
[Pipeline Steps](https://jenkins.io/doc/pipeline/steps/lockable-resources/)
documentation.

### Jenkins label parser allows sophisticated filtering

The plugin uses the Jenkins-internal label parser for filtering lockable resources. A full list of supported operators and syntax examples can be found in the [official documentation](https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#node-allocate-node).

```groovy
lock(label: 'labelA && labelB', variable : 'someVar') {
    echo 'labelA && labelB acquired by: ' + env.someVar;
}

lock(label: 'labelA || labelB', variable : 'someVar') {
    echo 'labelA || labelB acquired by: ' + env.someVar;
}

lock(label: 'labelA || labelB || labelC', variable : 'someVar', quantity : 100) {
    echo 'labelA || labelB || labelC acquired by: ' + env.someVar;
}
```

#### Multiple resource lock

```groovy
lock(label: 'label1', extra: [[resource: 'resource1']]) {
	echo 'Do something now or never!'
}
echo 'Finish'
```

```groovy
lock(
  variable: 'var',
  extra: [
    [resource: 'resource4'],
    [resource: 'resource2'],
    [label: 'label1', quantity: 2]
  ]
) {
  def lockedResources = env.var.split(',').sort()
  echo "Resources locked: ${lockedResources}"
}
echo 'Finish'
```

More examples are [here](src/doc/examples/readme.md).

----

## Node mirroring

Lockable resources plugin allow to mirror nodes (agents) into lockable resources. This eliminate effort by re-creating resources on every node change.

That means when you create new node, it will be also created new lockable-resource with the same name. When the node has been deleted, lockable-resource will be deleted too.

Following properties are mirrored:

- name.
- labels. Please note, that labels still contains node-name self.
- description.

To allow this behavior start jenkins with option `-Dorg.jenkins.plugins.lockableresources.ENABLE_NODE_MIRROR=true` or run this groovy code.

```groovy
System.setProperty("org.jenkins.plugins.lockableresources.ENABLE_NODE_MIRROR", "true");
```

> *Note:* When the node has been deleted, during the lockable-resource is locked / reserved / queued, then the lockable-resource will be NOT deleted.

----

## Improve performance

To be safe thread over all jobs and resources, need to be all operations synchronized.
This might lead to slow down your jobs. The jenkins self, has low CPU usage, but your jobs are very slow. Why?

The most time are spend to write the lockable-resources states into local file system. This is important to get the correct state after Jenkins reboots.

To eliminate this saving time has been added a property *DISABLE_SAVE*.

+ The best way is to use it with JCaC plugin. So you are sure, you have still correct
resources on Jenkins start.
+ When you set pipeline durability level to *PERFORMANCE_OPTIMIZED*, it makes also sense to set this property to true.

> *Note:* Keep in mind, that you will lost all your manual changes!

> *Note:* This option is experimental. It has been tested in many scenarios, but no body know.

To allow this behavior start jenkins with option `-Dorg.jenkins.plugins.lockableresources.DISABLE_SAVE=true` or run this groovy code.

```groovy
System.setProperty("org.jenkins.plugins.lockableresources.DISABLE_SAVE", "true");
```

## Detailed lock cause

Tle plugin step lock() will inform you in the build log detailed block cause. The size of cause depends on count of ordered resources and size of current queue. To eliminate big unreadable logs we limited the size. To see all cause change the properties as follow:

```groovy
System.setProperty("org.jenkins.plugins.lockableresources.PRINT_BLOCKED_RESOURCE", "-1");
System.setProperty("org.jenkins.plugins.lockableresources.PRINT_QUEUE_INFO", "-1");
```

*PRINT_BLOCKED_RESOURCE* means how many of ordered resources are printed. Per default 2.
*PRINT_QUEUE_INFO* how many queue items are printed. Per default 2.

 0 means disabled
 -1 means all / unlimited.

## Configuration as Code

This plugin can be configured via
[Configuration-as-Code](https://github.com/jenkinsci/configuration-as-code-plugin).

### Example configuration

```yml
unclassified:
  lockableResourcesManager:
    declaredResources:
      - name: "S7_1200_1"
        description: "S7 PLC model 1200"
        labels: "plc:S7 model:1200"
        reservedBy: "Reserved due maintenance window"
      - name: "S7_1200_2"
        labels: "plc:S7 model:1200"
      - name: "Resource-with-properties"
        properties:
          - name: "Property-A"
            value: "Value"
```

Properties *description*, *labels* and *reservedBy* are optional.

----

## lockable-resources overview

The page `<jenkinsRootUrl>/lockable-resources/` provides an overview over all lockable-resources.

### Resources

Provides an status overview over all resources and actions to change resource status.

Name | Permission | Description
-----|------------|------------
Reserve | RESERVE | Reserves an available resource for currently logged user indefinitely (until that person, or some explicit scripted action, decides to release the resource).
Unreserve | RESERVE | Un-reserves a resource that may be reserved by some person already. The user can unreserve only own resource. Administrator can unreserve any resource.
Unlock | UNLOCK | Unlocks a resource that may be or not be locked by some job (or reserved by some user) already.
Steal lock | STEAL | Reserves a resource that may be or not be locked by some job (or reserved by some user) already. Giving it away to currently logged user indefinitely (until that person, or some explicit scripted action, later decides to release the resource).
Reassign | STEAL | Reserves a resource that may be or not be reserved by some person already. Giving it away to currently logged user indefinitely (until that person, or some explicit scripted action, decides to release the resource).
Reset | UNLOCK | Reset a resource that may be reserved, locked or queued.
Note | RESERVE | Add or edit resource note.

### Labels

Provides an overview over all lockable-resources labels.

> *Note:* Please keep in mind, that lockable-resource-label is not the same as node-label!

### Queue

Provides an overview over currently queued requests.
A request is queued by the pipeline step `lock()`. When the requested resource(s) is currently in use (not free), then any new request for this resource will be added into the queue.

A resource may be requested by:

- name, such as in `lock('ABC') { ... }`
- label, such as in `lock(label : 'COFFEE_MACHINE')`

> *Note:* Please keep in mind that groovy expressions are currently supported only in free-style jobs. Free-style jobs do not update this queue and therefore can not be shown in this view.

> *Note:* An empty value in the column 'Requested at' means that this build has been started in an older plugin version - [1117.v157231b_03882](https://github.com/jenkinsci/lockable-resources-plugin/releases/tag/1117.v157231b_03882) and early. In this case we cannot recognize the timestamp.

----

## Upgrading from 1102.vde5663d777cf

Due an [issue](https://github.com/jenkinsci/lockable-resources-plugin/issues/434) **is not possible anymore to read resource-labels** from the config file org.jenkins.plugins.lockableresources.LockableResourcesManager.xml, **which is generated in the release** [1102.vde5663d777cf](https://github.com/jenkinsci/lockable-resources-plugin/releases/tag/1102.vde5663d777cf)

This issue does not **effect** instances configured by [Configuration-as-Code](https://github.com/jenkinsci/configuration-as-code-plugin) plugin.

A possible solution is to remove the `<string>` tags from your `org.jenkins.plugins.lockableresources.LockableResourcesManager.xml` config file manually, before you upgrade to new version (Keep in mind that a backup is still good idea).

Example:

change this one

```xml
<labels>
  <string>tests-integration-installation</string>
</labels>
```

to

```xml
<labels>
  tests-integration-installation
</labels>
```

----

## Changelog

- See [GitHub Releases](https://github.com/jenkinsci/lockable-resources-plugin/releases)
  for recent versions.
- See the [old changelog](CHANGELOG.old.md) for versions 2.5 and older.

----

## Report an Issue

Please report issues and enhancements through the [Jenkins issue tracker in GitHub](https://github.com/jenkinsci/lockable-resources-plugin/issues/new/choose)

----

## Contributing

Contributions are welcome, please
refer to the separate [CONTRIBUTING](CONTRIBUTING.md) document
for details on how to proceed!
Join [Gitter channel](https://gitter.im/jenkinsci/lockable-resources) to discuss your ideas with the community.

----

## License

All source code is licensed under the MIT license.
See [LICENSE](LICENSE.txt)


# GBIF ChecklistBank

ChecklistBank is the taxonomy store with its associated [webservices](http://www.gbif.org/developer/species) that allows GBIF to index any number of checklist datasets and match them to a global management taxonomy, the [GBIF backbone taxonomy](http://www.gbif.org/dataset/d7dddbf4-2cf0-4f39-9b2a-bb099caae36c).

**Warning!** We have evolved [ChecklistBank](https://www.checklistbank.org) together with the [Catalogue of Life](https://www.catalogueoflife.org) into a standalone service based on a [new open code base](https://github.com/CatalogueOfLife/checklistbank). This project is still in use by GBIF, but not very active any longer.

This is a multi module project containing all ChecklistBank modules, from api to persistence layer to the webservice client. Integration tests are part of the respective modules, in particular in the webservice client and the mybatis modules.

### Maven profile
To run all tests you need a maven profile with the following properties defined:

    <profile>
      <id>clb-local</id>
      <properties>
        <checklistbank.db.host>localhost</checklistbank.db.host>
        <checklistbank.db.name>clb</checklistbank.db.name>
        <checklistbank.db.username>postgres</checklistbank.db.username>
        <checklistbank.db.password>123456</checklistbank.db.password>
      </properties>
    </profile>

# ChecklistBank database schema

Checklistbank relies on postgres 9 and uses the HStore extension.  The simplest way of enabling this is to add it to the postgres template database, which is used whenever postgres creates a new one.  Thus if you run the following (or similar)
before creating the database, you are all set:

    psql -u postgres template1 -c 'create extension hstore;'

You can create a database schema from scratch or update one to the latest version using the maven liquiabse plugin like this:

    mvn -P clb-local liquibase:update

A [diagram of the database schema](docs/schema.pdf) is available for convenience.


# GoCD

[![Google Groups](https://img.shields.io/badge/Google_Groups-user_help-purple)](https://groups.google.com/g/go-cd)
[![GitHub Discussions](https://img.shields.io/badge/GitHub_discussions-user_&_dev_chat-green)](https://github.com/gocd/gocd/discussions)
[![GitHub License](https://img.shields.io/github/license/gocd/gocd?color=yellow)](LICENSE)
[![Server Docker Pulls](https://img.shields.io/docker/pulls/gocd/gocd-server?label=Server%20Docker%20pulls)](https://hub.docker.com/r/gocd/gocd-server/)

This is the main repository for [GoCD](https://gocd.org) - a continuous delivery server. GoCD helps you automate and streamline the build-test-release cycle for worry-free, continuous delivery of your product.

- To quickly build your first pipeline while learning key GoCD concepts, visit our [Test Drive GoCD](https://www.gocd.org/test-drive-gocd.html).
- To download GoCD, visit the [downloads page](https://www.gocd.org/download/).

## Security

Please see [the security policy](SECURITY.md) for details on GoCD's security status, and how to responsibly disclose issues.

## Development

GoCD is predominantly a Java & TypeScript project utilising [Spring Framework](https://spring.io/projects/spring-framework/), [SparkJava](https://sparkjava.com/) & [MithrilJS](https://mithril.js.org/) as key frameworks, built using [Gradle](https://gradle.org/) & [Webpack](https://webpack.js.org/) and running within [Eclipse Jetty](https://eclipse.dev/jetty/).

There are a small number of older parts of GoCD rendered server-side within [JRuby](https://www.jruby.org/) on [Rails](https://rubyonrails.org/) which utilise some legacy plain JavaScript with [JQuery](https://jquery.com/). GoCD itself is used to [build GoCD](https://build.gocd.org).

Here is the guide to [setup your development environment](https://developer.gocd.org/current/).

## Contributing

We'd love it if you contributed to GoCD. For information on contributing to this project, please see our [contributor's guide](https://gocd.org/contribute).
A lot of useful information like links to user documentation, design documentation, mailing lists etc. can be found in the [resources](https://gocd.org/community/resources.html) section.

## License

GoCD is an open source project, sponsored by [Thoughtworks, Inc.](https://www.thoughtworks.com) under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0).