[![Latest Version](https://jitpack.io/v/100mslive/android-sdk.svg)](https://docs.100ms.live/android/v2/release-notes/Release-Notes)
[![Documentation](https://img.shields.io/badge/Read-Documentation-blue)](https://docs.100ms.live/android/v2/foundation/Basics)
[![Discord](https://img.shields.io/discord/843749923060711464?label=Join%20on%20Discord)](https://100ms.live/discord)
[![Download App](https://img.shields.io/badge/Download%20via-Firebase-green)](https://appdistribution.firebase.dev/i/d8f1648365a33c3e)
[![Activity](https://img.shields.io/github/commit-activity/m/100mslive/100ms-android.svg)](https://github.com/100mslive/100ms-android/pulls)
[![Email](https://img.shields.io/badge/Contact-Know%20More-blue)](https://dashboard.100ms.live/register)

# 🎉 Sample App using 100ms Android SDK 🚀

Here you will find everything you need to build experiences with video using 100ms Android SDK. Dive into our SDKs, quick starts, add real-time video, voice, and screen sharing to your web and mobile applications.

Sample App of 100ms can be downloaded from Play store : https://play.google.com/store/apps/details?id=live.hms.app2

Meeting links can be generated using [dashboard](https://dashboard.100ms.live/)

## 📦 Prebuilt (Room Kit)

Room Kit is library built to take even building the UI off your hands. It uses 100ms SDK to and a dynamic layout decided by Prebuilt in the dashboard to have fully functional video up and running in your app in minutes.
To add the library to your own app, take a look at the [Prebuilt Quickstart](https://www.100ms.live/docs/android/v2/quickstart/prebuilt-android) in the docs.

#### 🛠 Developing against Prebuilt Room Kit
We don't intend this to be a very common as Room Kit is updated very frequently with new features but the benefit of open source is that if you don't like how something works you can change it yourself! If you wanted to change anything in the Prebuilt library here's how.
1. Clone this repo.
2. Find the line in `app/build.gradle` that says `implementation "live.100ms:room-kit:$HMS_ROOM_KIT_VERSION"` and change it to
   ``implementation project(":room-kit")``
3. Run the app.

Now you'll be loading the room kit library locally with your own changes rather than from the maven library that 100ms publishes to.

To use this in your own code, you can put the library in your local computer and import it in your app.
To put the room kit library in your computer as a library locally:
1. Open a terminal and cd into the root of this project. Opening the terminal from Android Studio works as well.
2. Run the following command to build and put the library in your local storage. `./gradlew clean publishToMavenLocal`
3. Verify the library was built correctly by seeing if it is in `ls ~/.m2/repository/live/100ms/room-kit`
4. In your app find where the `mavenCentral()` repository is referenced and add `mavenLocal()` before it. Eg:
```
   allprojects {
         repositories {
         mavenLocal()
         mavenCentral()
     }
  }
```

5. Add the import for `room kit` as you would do for any library `implementation "live.100ms:room-kit:$HMS_ROOM_KIT_VERSION"`

That's it. Once you sync, the library should be available to your app.
This is the recommended method since adding the module to your own app directly would make it difficult to sync with our changes.

## ☝ Pre-requisites

- Android Studio
- Support for Java 11

## 📱 Supported Devices

The Android SDK supports Android API level 21 and higher. It is built for armeabi-v7a, arm64-v8a, x86, and x86_64 architectures.

## 📑 100ms SDK Documentation

Refer the [Getting Started - Android](https://docs.100ms.live/android/v2/foundation/Basics) guide to get detailed SDK information


# ManagementPortal

[![Latest release](https://img.shields.io/github/v/release/RADAR-base/ManagementPortal)](https://github.com/RADAR-base/ManagementPortal/releases/latest)
[![Build Status](https://github.com/RADAR-base/ManagementPortal/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/RADAR-base/ManagementPortal/actions/workflows/main.yml?query=branch%3Amaster)

Management Portal is an application which is used to manage clinical studies for [RADAR-base](https://www.radar-base.org/) platform.

## Table of contents

- [Quickstart](#quickstart)
  * [Using Docker-Compose](#using-docker-compose)
  * [Build from source](#build-from-source)
- [Configuration](#configuration)
  * [Environment Variables](#environment-variables)
  * [OAuth Clients](#oauth-clients)
  * [UI Customization](#ui-customization)
- [Development](#development)
  * [Managing dependencies](#managing-dependencies)
  * [Using angular-cli](#using-angular-cli)
- [Building for production](#building-for-production)
- [Testing](#testing)
  * [Client tests](#client-tests)
  * [Other tests](#other-tests)
- [Using Docker to simplify development (optional)](#using-docker-to-simplify-development-optional)
- [Documentation](#documentation)
- [Client libraries](#client-libraries)

## Dependencies

The following are the prerequisites to run ManagementPortal from source on your machine:

- Java 17
- Node.js (v16 or later is recommended)
- Yarn (3.1.0 or later is recommended)

## Quickstart

Management Portal can be easily run either by running from source or by using the provided `docker-compose` file.  For documentation on how to run ManagementPortal in production, please see [RADAR-Kubernetes][].

### Using Docker-Compose

The quickest way to get Management Portal up and running in production mode is by using the included
docker-compose files.
1. Make sure [Docker][] and [Docker-Compose][] are installed on your system.
2. Generate a key pair for signing JWT tokens as follows:
   ```shell
   keytool -genkeypair -alias radarbase-managementportal-ec -keyalg EC -validity 3650 -keysize 256 -sigalg SHA256withECDSA -storetype PKCS12 -keystore src/main/docker/etc/config/keystore.p12 -storepass radarbase -keypass radarbase
   ```
3. Now, we can start the stack with `docker-compose -f src/main/docker/management-portal.yml up -d`.

This will start a Postgres database and ManagementPortal. The default password for the `admin`
account is `admin`. An angular live development server to access the managementportal can be started using the `yarn start` command (see [Development](#development)).

### Build from source

You must install and configure the following dependencies on your machine to run from source.
1. [Node.js][]: We use Node to run a development web server and build the project.
   Depending on your system, you can install Node either from source or as a pre-packaged bundle.
2. [Yarn][]: We use Yarn to manage Node dependencies.
   Depending on your system, you can install Yarn either from source or as a pre-packaged bundle.
3. Generate a key pair for signing JWT tokens as follows:
   ```shell
   keytool -genkeypair -alias radarbase-managementportal-ec -keyalg EC -validity 3650 -keysize 256 -sigalg SHA256withECDSA -storetype PKCS12 -keystore src/main/resources/config/keystore.p12 -storepass radarbase -keypass radarbase
   ```
   **Make sure the key password and store password are the same!** This is a requirement for Spring Security.

4. **Profile configurations :** ManagementPortal can be run with either `development` or `production` profile. The table below lists the
main differences between the profiles. Configure the application using the property file at `src/main/resources/config/application-<profile>.yml`.Read more about configurations [here](#configuration)

5. Run ManagementPortal by running `./gradlew bootRun -Pprod` or `./gradlew bootRun -Pdev`. Development mode will start an in
memory database and ManagementPortal. An angular live development server to access the managementportal can be started using the `yarn start` command (see [Development](#development)).
6. You can log in to the application using `admin:admin`. Please don't forgot to change the password of `admin`, if you are using the application on production environment.

|                                  | Development     | Production                        |
|----------------------------------|-----------------|-----------------------------------|
| Database type                    | In-memory       | Postgres                          |
| Demo data loaded                 | Yes             | No                                |

The docker image can be pulled by running `docker pull radarbase/management-portal:latest`.

## Configuration

Management Portal comes with a set of default values for its configuration. You can either modify
the `application.yml` and `application-prod.yml` (or `application-dev.yml` when running the
development profile) before building the application, or override the defaults using environment
variables.

### Environment Variables

The table below lists the variables that are most likely in need of change when deploying Management
Portal. You can find the complete configuration
in the [application.yml](src/main/resources/config/application.yml) and
[application-prod.yml](src/main/resources/config/application-prod.yml) files. See
[Spring external configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html)
for other options on overriding the default configuration.

| Variable                                                    | Default value                                       | Description                                                                                |
|-------------------------------------------------------------|-----------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `SPRING_DATASOURCE_URL`                                     | `jdbc:postgresql://localhost:5432/managementportal` | URL for the database to be used                                                                                |
| `SPRING_DATASOURCE_USERNAME`                                | `<username>`                                        | Username to access the database                                                                                |
| `SPRING_DATASOURCE_PASSWORD`                                | `<password>`                                        | Password to access the database                                                                                |
| `SPRING_APPLICATION_JSON`                                   | None                                                | Generic environment variable for overriding all types of application settings                                                                                |
| `MANAGEMENTPORTAL_MAIL_FROM`                                | None, you need to override this                     | Email address that will be set  in the From email header.                                                                                |
| `MANAGEMENTPORTAL_FRONTEND_CLIENT_SECRET`                   | None, you need to override this                     | OAuth client secret for the frontend                                                                                |
| `MANAGEMENTPORTAL_FRONTEND_ACCESS_TOKEN_VALIDITY_SECONDS`   | `14400`                                             | Frontend access token validity period in seconds                                                                                |
| `MANAGEMENTPORTAL_FRONTEND_REFRESH_TOKEN_VALIDITY_SECONDS`  | `259200`                                            | Frontend refresh token validity period in seconds                                                                                |
| `MANAGEMENTPORTAL_OAUTH_CLIENTS_FILE`                       | `/mp-includes/config/oauth_client_details.csv`      | Location of the OAuth clients file                                                                                |
| `MANAGEMENTPORTAL_OAUTH_KEY_STORE_PASSWORD`                 | `radarbase`                                         | Password for the JWT keystore                                                                                |
| `MANAGEMENTPORTAL_OAUTH_SIGNING_KEY_ALIAS`                  | `radarbase-managementportal-ec`                     | Alias in the keystore of the keypair to use for signing                                                                                |
| `MANAGEMENTPORTAL_OAUTH_ENABLE_PUBLIC_KEY_VERIFIERS`        | `false`                                             | Whether to use additional verifiers using public-keys and deprecated verifier implementation. If you set this to `true`, also set `RADAR_IS_CONFIG_LOCATION` and provide yaml file with public keys. Read more at radar-auth documentation. |
| `MANAGEMENTPORTAL_CATALOGUE_SERVER_ENABLE_AUTO_IMPORT`      | `false`                                             | Whether to enable or disable auto import of sources from the catalogue server                                                                                |
| `MANAGEMENTPORTAL_CATALOGUE_SERVER_SERVER_URL`              | None                                                | URL to the catalogue server                                                                                |
| `MANAGEMENTPORTAL_COMMON_BASE_URL`                          | None                                                | Resolvable baseUrl of the hosted platform                                                                                |
| `MANAGEMENTPORTAL_COMMON_MANAGEMENT_PORTAL_BASE_URL`        | None                                                | Resolvable baseUrl of this managementportal  instance                                                                                |
| `MANAGEMENTPORTAL_COMMON_PRIVACY_POLICY_URL`                | None                                                | Resolvable URL to the common privacy policy url                                                                                |
| `MANAGEMENTPORTAL_COMMON_ADMIN_PASSWORD`                    | None                                                | Admin password                                                                                |
| `MANAGEMENTPORTAL_COMMON_ACTIVATION_KEY_TIMEOUT_IN_SECONDS` | 86400                                               | Account activation/reset timeout in seconds                                                                                |
| `RADAR_IS_CONFIG_LOCATION`                                  | `radar-is.yml` from class path                      | Location of additional public-key configuration file.                                                                                |
| `JHIPSTER_SLEEP`                                            | `10`                                                | Time in seconds that the application should wait at bootup. Used to allow the database to become ready                                                                                |
| `JAVA_OPTS`                                                 | `-Xmx512m`                                          | Options to pass on the JVM                                                                                |

Lists cannot directly be encoded by environment variables in this version of Spring. So for example the OAuth checking key aliases need to be encoded using the `SPRING_APPLICATION_JSON` variable. For setting two aliases, set it to `{"managementportal":{"oauth":{"checkingKeyAliases":["one","two"]}}}`, for example. If this list is not set, the signing key will also be used as the checking key.

### OAuth Clients

ManagementPortal uses `OAuth2` workflow to provide authentication and authorization. To add new OAuth clients, you can add at runtime through the UI, or you can add them to the OAuth clients file
referenced by the `MANAGEMENTPORTAL_OAUTH_CLIENTS_FILE` configuration option.
- If your client is supposed to work with the `Pair app` feature, you need to set a key called `dynamic_registration` to `true` like this `{"dynamic_registration": true}` in its `additional_information` map. See the aRMT and pRMT
clients for an example.
- If your client is `dynamic_registration` enabled, the QR code generated by `Pair app` feature will contain a short-living URL. By doing a `GET` request on that URL the `refresh-token` and related meta-data can be fetched.
- If you want to prevent an OAuth client from being altered through the UI, you can add a key `{"protected": true}` in the `additional_information` map.

If the app is paired via the Pair App dialog, the QR code that will be scanned contains a short-lived URL, e.g. `https://radar-base-url.org/api/meta-token/bMUkowOmTOci`

Your app should access the URL, where it will receive an OAuth2
refresh token as well as the platform's base URL and a URL to the privacy policy. No authorization
is required to access this URL. **Important:** For security reasons, the information at this URL can
only be accessed once. Once it has been accessed it can not be retrieved again.

The app can use that refresh token to get new access and refresh tokens by doing the following HTTP
request to the base URL, using HTTP basic authentication with your OAuth client ID as username, and
an empty password.
```
POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=<refresh_token>
```
This will respond with at least the access token and refresh token:
```json
{
   "access_token": "...",
   "refresh_token": "...",
   "expires_in": 14400
}
```
Both tokens are valid for a limited time only. When the access token runs out, you will need to
perform another request like the one above, but you need to use the new `refresh_token`, since
refresh tokens are valid only once.

### Authorization Code flow
The code grant flow for OAuth2 clients can be the following:
1. Register an oauth-client with grant_type `authorization_code` and add a valid `redirect_uri` to that client. (`e.g. https://my.example.com/oauth_redirect` in this example)
2. Ask user authorization for your app:
     ```
     GET /oauth/authorize?client_id=MyId&response_type=code&redirect_uri=https://my.example.com/oauth_redirect
     ```
   where you replace `MyId` with your OAuth client id. This needs to be done from a interactive
   web view, either a browser or a web window. If the user approves, this will redirect to
   `https://my.example.com/oauth_redirect?code=abcdef`. In Android, with [https://appauth.io]
   (AppAuth library), the URL could be `com.example.my://oauth_redirect` for the `com.example.my`
   app.
   You can add an optional parameter for `state`. If you add the state parameter, it will be returned with the `code`.
3. Request a token for your app by doing a POST, again with HTTP basic authentication with as
   username your OAuth client id, and leaving the password empty:
    ```
    POST /oauth/token
    Content-Type: application/x-www-form-urlencoded

    grant_type=authorization_code&code=abcdef&redirect_uri=https://my.example.com/oauth_redirect
    ```
   This will respond with the access token and refresh token:
    ```json
    {
       "access_token": "...",
       "refresh_token": "..."
    }
    ```
   Now the app can use the refresh token flow as shown above.

### Client credentials flow
The code grant flow for OAuth2 clients can also be the following:
1. Register an oauth-client with grant_type `client_credentials`
2. Request a token for your app by doing a POST with HTTP basic authentication with as
   username your OAuth client id and password your OAuth client secret:
    ```
    POST /oauth/token
    Content-Type: application/x-www-form-urlencoded

    grant_type=client_credentials
    ```
   This will respond with the access token:
    ```json
    {
        "access_token": "...",
        "token_type": "bearer",

        "...": "..."
    }
    ```
   Now the app can use the access token flow.

### UI Customization

You can customize ManagementPortal web app by replacing images located in `src/main/webapp/content/images` with your logos:
- `navbar-logo.png` is a 70x45 (WxH in pixels) image shown at the top of every page;
- `home-page-logo.png` is shown on the home page only; 350x350 px image recommended.

Once you build the project, you will find these images in `build/www/assets/images`.

## Development

Before you can build this project, you must install and configure the following dependencies on your machine:

1. [Node.js][]: We use Node to run a development web server and build the project.
   Depending on your system, you can install Node either from source or as a pre-packaged bundle.
2. [Yarn][]: We use Yarn to manage Node dependencies.
   Depending on your system, you can install Yarn either from source or as a pre-packaged bundle.
3. Local SMTP server: currently a simple docker-compose is provided with a local SMTP server. Create `smtp.env` from `smtp.env.template` and modify `application.yml` accordingly.

After installing Node, you should be able to run the following command to install development tools.
You will only need to run this command when dependencies change in [package.json](package.json).

    yarn install

We use yarn scripts and [Webpack][] as our build system.

Run the following commands in two separate terminals to create a blissful development experience where your browser
auto-refreshes when files change on your hard drive.

    ./gradlew
    yarn start

Then open <http://localhost:8081/> to start the interface and sign in with admin/admin.

### Managing dependencies

[Yarn][] is also used to manage CSS and JavaScript dependencies used in this application. You can upgrade dependencies by
specifying a newer version in [package.json](package.json). You can also run `yarn update` and `yarn install` to manage dependencies.
Add the `help` flag on any command to see how you can use it. For example, `yarn help update`.

The `yarn run` command will list all the scripts available to run for this project.

### Using angular-cli

You can also use [Angular CLI][] to generate some custom client code.

For example, the following command:

    ng generate component my-component

will generate few files:

    create src/main/webapp/app/my-component/my-component.component.html
    create src/main/webapp/app/my-component/my-component.component.ts
    update src/main/webapp/app/app.module.ts

## On Production
### Building for production

To optimize the ManagementPortal application for production, run:

    ./gradlew -Pprod clean bootWar
### Hosting in production
The latest Meta-QR code implementation requires REST resources on `api/meta-token/*` should definitely be rate-limited by upstream servers.

This will concatenate and minify the client CSS and JavaScript files. It will also modify `index.html` so it references these new files.
To ensure everything worked, run:

    java -jar build/libs/*.war

Then navigate to [http://localhost:8080](http://localhost:8080) in your browser.

## Testing

To launch your application's tests, run:

    ./gradlew test

### Client tests

Unit tests are run by [Karma][] and written with [Jasmine][]. They're located in `src/test/javascript/` and can be run with:

    yarn test

UI end-to-end tests are powered by [Cypress][], which is built on top of WebDriverJS. They're located in [src/test/javascript/e2e](src/test/javascript/e2e)
and can be run by starting Spring Boot in one terminal (`./gradlew bootRun`) and running the tests (`yarn run e2e`) in a second one.
### Other tests

Performance tests are run by [Gatling][] and written in Scala. They're located in `src/test/gatling` and can be run with:

    ./gradlew gatlingRunAll

or

    ./gradlew gatlingRun<SIMULATION_CLASS_NAME> # E.g., gatlingRunProjectGatlingTest

For more information, refer to the [Running tests page][].

## Using Docker to simplify development (optional)

You can use Docker to improve your JHipster development experience. A number of docker-compose configuration are available in the [src/main/docker](src/main/docker) folder to launch required third party services.
For example, to start a postgreSQL database in a docker container, run:

    docker-compose -f src/main/docker/postgresql.yml up -d

To stop it and remove the container, run:

    docker-compose -f src/main/docker/postgresql.yml down

You can also fully dockerize your application and all the services that it depends on.
To achieve this, first build a docker image of your app by running:

    ./gradlew bootWar -Pprod buildDocker

Then run:

    docker-compose -f src/main/docker/app.yml up -d

For more information refer to [Using Docker and Docker-Compose][], this page also contains information on the docker-compose sub-generator (`yo jhipster:docker-compose`), which is able to generate docker configurations for one or several JHipster applications.
## Documentation

Please find the links for some of the documentation per category/component
* [management-portal-javadoc](https://radar-base.github.io/ManagementPortal/management-portal-javadoc/)
* [radar-auth-javadoc](https://radar-base.github.io/ManagementPortal/radar-auth-javadoc/)
* [managementportal-client-javadoc](https://radar-base.github.io/ManagementPortal/managementportal-client-javadoc/)
* [Swagger 2.0 apidoc](https://radar-base.github.io/ManagementPortal/apidoc/swagger.json)

The pages site is published from the `gh-pages` branch, which has its own history. If you want to
contribute to the documentation, it is probably more convenient to clone a separate copy of this
repository for working on the `gh-pages` branch:
```bash
git clone --branch gh-pages https://github.com/RADAR-base/ManagementPortal.git ManagementPortal-docs
```
## Client libraries

This project provides a Gradle task to generate an [OpenAPI] specification from which client libraries can be automatically generated:
```bash
./gradlew generateOpenApiSpec
```
ManagementPortal needs to be running and be accessible at `http://localhost:8080` for this task to work.

The resulting file can be imported into the [Swagger editor][], or used with [Swagger codegen][] to generate client libraries.

[JHipster Homepage and latest documentation]: https://www.jhipster.tech

[RADAR-Kubernetes]: https://github.com/RADAR-base/RADAR-Kubernetes
[Using Docker and Docker-Compose]: https://www.jhipster.tech/docker-compose/
[Running tests page]: https://www.jhipster.tech/running-tests/
[Setting up Continuous Integration]: https://www.jhipster.tech/setting-up-ci/

[Gatling]: https://gatling.io/
[Node.js]: https://nodejs.org/
[Yarn]: https://yarnpkg.org/
[Webpack]: https://webpack.github.io/
[Angular CLI]: https://cli.angular.io/
[BrowserSync]: http://www.browsersync.io/
[Karma]: https://karma-runner.github.io/
[Jasmine]: https://jasmine.github.io
[Cypress]: https://www.cypress.io
[Protractor]: https://angular.github.io/protractor/
[Leaflet]: http://leafletjs.com/
[DefinitelyTyped]: http://definitelytyped.org/
[Docker]: https://docs.docker.com/
[Docker-Compose]: https://docs.docker.com/compose/
[OpenAPI]: https://www.openapis.org/
[Swagger editor]: https://editor.swagger.io/
[Swagger codegen]: https://swagger.io/swagger-codegen/
[OAuth2 spec]: https://tools.ietf.org/html/rfc6749#section-9


# Cottontail DB

![Cottontail CI](https://github.com/ppanopticon/cottontaildb/workflows/Cottontail%20CI/badge.svg?branch=master)
[![Maven Central](https://img.shields.io/maven-central/v/org.vitrivr/cottontaildb.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22org.vitrivr%22%20AND%20a:%22cottontaildb%22)

Cottontail DB is a column store aimed at multimedia retrieval. It allows for classical boolean as well as vector-space retrieval, i.e., nearest-neighbours lookup, as used in similarity search. If you're interested in using or contributing to
Cottontail DB, please have a look at the [Wiki](https://github.com/vitrivr/cottontaildb/wiki/).

## Setup
Cottontail DB requires Java 11 or newer (Open JDK or Oracle JDK should both work). Please clone this repository using:

``git clone https://github.com/vitrivr/cottontaildb.git``

The entire project is a Gradle project and comes with a Gradle Wrapper so things should work pretty much out of the box.

### Building and starting Cottontail DB

A distribution of Cottontail DB can be built from the sources using the Gradle tasks `distTar` or `distZip`. This distribution includes the actual DBMS as well as the CLI. Distributions are
stored relatively to the project root in `build/distributions` as either TAR or ZIP file.

All the details as to how Cottontail DB can be setup and started can be found in the [Wiki](https://github.com/vitrivr/cottontaildb/wiki/Setup).

### Using Cottontail DB Docker Image

Cottontail DB is available as Docker Image from [DockerHub](https://hub.docker.com/r/vitrivr/cottontaildb). Please have a look at the repository instructions and/or the [Wiki](https://github.com/vitrivr/cottontaildb/wiki/Setup) for more information.

### Connecting to Cottontail DB

Communication with Cottontail DB is facilitated by [gRPC](https://grpc.io/). By default, the gRPC endpoint runs on **port 1865**. To connect to Cottontail DB, you must first generate the model classes and stubs using the gRPC library of your
preference based on the programming environment you use. You can find the latest gRPC definitions [here](https://github.com/vitrivr/cottontaildb-proto).

For Kotlin and Java, there is also a Maven dependency, which includes pre-built stubs and models as well as a client API:

```xml
<dependency>
  <groupId>org.vitrivr</groupId>
  <artifactId>cottontaildb-client</artifactId>
  <version>0.16.0</version>
</dependency>
```

More information as to how to connect to and use Cottontail DB can be found in the [Wiki](https://github.com/vitrivr/cottontaildb/wiki/Connecting-to-Cottontail-DB) and the [example repository](https://github.com/vitrivr/cottontaildb-examples).

### CLI / 🥕-LI
Cottontail DB comes with a CLI application called 🥕-LI. The CLI is bundled with the distribution but can also be built separately using the `cottontaildb-cli:distTar` or `cottontaildb-cli:distZip` gradle task.

### Compatibility with vitrivr

Please refer to the [compatibility matrix](https://github.com/vitrivr/cottontaildb/wiki/Compatibility-Matrix) to check for compatibility with other *vitrivr* components.

## Citation
We kindly ask you to refer to the following paper in publications mentioning or employing Cottontail DB:

Ralph Gasser, Luca Rossetto, Silvan Heller, Heiko Schuldt. _Cottontail DB: An Open Source Database System for Multimedia Retrieval and Analysis._ In Proceedings of 28th ACM International Conference on Multimedia (ACM MM 2020), Seattle, USA, 2020

**Link:** https://doi.org/10.1145/3394171.3414538

**Bibtex:**

```
@inproceedings{10.1145/3394171.3414538,
    author = {Gasser, Ralph and Rossetto, Luca and Heller, Silvan and Schuldt, Heiko},
    title = {Cottontail DB: An Open Source Database System for Multimedia Retrieval and Analysis},
    year = {2020},
    isbn = {9781450379885},
    publisher = {Association for Computing Machinery},
    address = {New York, NY, USA},
    doi = {10.1145/3394171.3414538},
    booktitle = {Proceedings of the 28th ACM International Conference on Multimedia},
    pages = {4465–4468},
    numpages = {4},
    keywords = {open source, multimedia retrieval, database, multimedia indexing, data management system},
    location = {Seattle, WA, USA},
    series = {MM '20}
}
```

## Credits
Cottontail DB is based on the ideas presented in the following papers:

- Ivan Giangreco and Heiko Schuldt (2016): ADAMpro: Database Support for Big Multimedia Retrieval. Datenbank-Spektrum.
http://link.springer.com/article/10.1007/s13222-015-0209-y
- Ivan Giangreco (2018): Database support for large-scale multimedia retrieval. PhD Thesis. https://edoc.unibas.ch/64751/


[![Build](https://github.com/navikt/mock-oauth2-server/workflows/Build%20master/badge.svg)](https://github.com/navikt/mock-oauth2-server/actions) [![Maven Central](https://img.shields.io/maven-central/v/no.nav.security/mock-oauth2-server?color=green&logo=Apache%20Maven)](https://search.maven.org/artifact/no.nav.security/mock-oauth2-server)

# mock-oauth2-server
A scriptable/customizable web server for testing HTTP clients using OAuth2/OpenID Connect or applications with a dependency to a running OAuth2 server (i.e. APIs requiring signed JWTs from a known issuer).  The server also provides the necessary endpoints for token validation (endpoint for JWKS) and ID Provider metadata discovery ("well-known" endpoints providing  server metadata)

**mock-oauth2-server** is written in Kotlin using the great [OkHttp MockWebServer](https://github.com/square/okhttp/tree/master/mockwebserver) as the underlying server library and can be used in unit/integration tests in both **Java** and **Kotlin** or in any language as a standalone server in e.g. docker-compose.

Even though the server aims to be compliant with regards to the supported OAuth2/OpenID Connect specifications, you should never use it for anything else than tests. That being said, when developing OAuth2 clients you should always verify that the expected requests are being made in your tests.

## Motivation

The motivation behind this library is to provide a setup such that application developers don't feel the need to disable security in their apps when running tests! If you have any issues with regards to OAuth2 and tokens et. al. and consider to disable "security" when running tests please submit an issue or a PR so that we can all help developers and security to live in harmony once again (if ever..)!

## Features

* **Multi-issuer/Multi-tenancy support**: the server can represent as many different Identity Providers/Token Issuers as you need (with different token issuer names) WITHOUT any setup!
* **Implements OAuth2/OpenID Connect grants/flows**
  * OpenID Connect Authorization Code Flow
  * OAuth2 Client Credentials Grant
  * OAuth2 JWT Bearer Grant (On-Behalf-Of flow)
  * OAuth2 Token Exchange Grant
  * OAuth2 Refresh Token Grant
  * OAuth2 Resource Owner Password Credentials (Password Grant)
    * *usage should be avoided if possible as this grant is considered insecure and [removed in its entirety](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-13#section-3.4) from OAuth 2.1*
* **Issued JWT tokens are verifiable** through standard mechanisms with OpenID Connect Discovery / OAuth2 Authorization Server Metadata
* **Unit/Integration test support**
  * Start and stop server for each test
  * Sane defaults with minimal setup if you don't need token customization
  * Enqueue expected tokens if you need to customize token claims
  * Enqueue expected responses
  * Verify expected requests made to the server
  * Customizable through exposure of underlying  [OkHttp MockWebServer](https://github.com/square/okhttp/tree/master/mockwebserver)
* **Standalone support** - i.e. run as application in IDE, run inside your app, or as a Docker image (provided)
* **OAuth2 Client Debugger** - e.g. support for triggering OIDC Auth Code Flow and receiving callback in debugger app, view token response from server (intended for standalone support)

## API Documentation

[mock-oauth2-server](https://navikt.github.io/mock-oauth2-server/)

## 📦 Install

**Gradle Kotlin DSL**

Latest version [![Maven Central](https://img.shields.io/maven-central/v/no.nav.security/mock-oauth2-server?color=green&logo=Apache%20Maven)](https://search.maven.org/artifact/no.nav.security/mock-oauth2-server)

```kotlin
testImplementation("no.nav.security:mock-oauth2-server:$mockOAuth2ServerVersion")
```

**Maven**

Latest version [![Maven Central](https://img.shields.io/maven-central/v/no.nav.security/mock-oauth2-server?color=green&logo=Apache%20Maven)](https://search.maven.org/artifact/no.nav.security/mock-oauth2-server)

```xml
<dependency>
  <groupId>no.nav.security</groupId>
  <artifactId>mock-oauth2-server</artifactId>
  <version>${mock-oauth2-server.version}</version>
  <scope>test</scope>
</dependency>
```

**Docker**

Latest version [![GitHub release (latest SemVer including pre-releases)](https://img.shields.io/github/v/release/navikt/mock-oauth2-server?color=green&include_prereleases&label=GitHub%20Package%20Registry&logo=Docker)](https://github.com/navikt/mock-oauth2-server/packages/)

```
docker pull ghcr.io/navikt/mock-oauth2-server:$MOCK_OAUTH2_SERVER_VERSION
```

## ⌨ Usage

### Well-Known Configuration

The **mock-oauth2-server** will supply different configurations depending on the url used against the server, more specifically the first **path** (or context root) element in your request url will specify the `issuerId`.

A request to `http://localhost:8080/default/.well-known/openid-configuration` will yield an `issuerId` of `default` with the following configuration:

```json
{
   "issuer":"http://localhost:8080/default",
   "authorization_endpoint":"http://localhost:8080/default/authorize",
   "end_session_endpoint" : "http://localhost:8080/default/endsession",
   "revocation_endpoint" : "http://localhost:8080/default/revoke",
   "token_endpoint":"http://localhost:8080/default/token",
   "userinfo_endpoint":"http://localhost:8080/default/userinfo",
   "jwks_uri":"http://localhost:8080/default/jwks",
   "introspection_endpoint":"http://localhost:8080/default/introspect",
   "response_types_supported":[
      "query",
      "fragment",
      "form_post"
   ],
   "subject_types_supported":[
      "public"
   ],
   "id_token_signing_alg_values_supported":[
     "ES256",
     "ES384",
     "RS256",
     "RS384",
     "RS512",
     "PS256",
     "PS384",
     "PS512"
   ],
  "code_challenge_methods_supported":[
      "plain",
      "S256"
  ]
}
```

The actual issuer value in a JWT will be `iss: "http://localhost:8080/default"`

To use another issuer with id `anotherissuer` simply make a request to `http://localhost:8080/anotherissuer/.well-known/openid-configuration` and the configuration will change accordingly.

### Unit tests

##### Setup test

* Start the server at a random port
* Get url for server metadata/configuration
* Setup your app to use the OAuth2 server metadata and conduct your tests
* Shutdown the server

```kotlin
val server = MockOAuth2Server()
server.start()
// Can be anything you choose - should uniquely identify your issuer if you have several
val issuerId = "default"
// Discovery url to authorization server metadata
val wellKnownUrl = server.wellKnownUrl(issuerId).toString()
// ......
// Setup your app with metadata from wellKnownUrl and do your testing here
// ......
server.shutdown()
```

##### Testing an app requiring user login with OpenID Connect Authorization Code Flow

* Setup test like above
* Make your test HTTP client follow redirects
* Your callback (redirect_uri) endpoint should receive the callback request as required and be able to retrieve a token from the token endpoint.

If you need to get a login for a specific user you can use the `OAuth2TokenCallback` interface to provide your own or set values in the `DefaultOAuth2TokenCallback`

```kotlin
@Test
fun loginWithIdTokenForSubjectFoo() {
    server.enqueueCallback(
        DefaultOAuth2TokenCallback(
            issuerId = issuerId,
            subject = "foo"
        )
    )
  // Invoke your app here and assert user foo is logged in
}
```

 If you need specific claims in the resulting `id_token` - e.g. `acr` or a custom claim you can also use the `OAuth2TokenCallback`:

~~~kotlin
@Test
fun loginWithIdTokenForAcrClaimEqualsLevel4() {
    server.enqueueCallback(
        DefaultOAuth2TokenCallback(
            issuerId = issuerId,
            claims = mapOf("acr" to "Level4")
        )
    )
  // Invoke your app here and assert acr=Level4 is present in id_token
}
~~~

##### Testing an API requiring access_token (e.g. a signed JWT)

```kotlin
val token: SignedJWT = oAuth2Server.issueToken(issuerId, "someclientid", DefaultOAuth2TokenCallback())
//use your favourite HTTP client to invoke your API and attach the serialized token
val request = // ....
request.addHeader("Authorization", "Bearer ${token.serialize()}")
```
If you for some reason need to manipulate the system time/clock you can configure the OAuth2TokenProvider to use a specific time, resulting in the `iat` claim being set to that time:

```kotlin
@Test
fun testWithSpecificTime() {
    val server = MockOAuth2Server(
        config = OAuth2Config(
            tokenProvider = OAuth2TokenProvider(systemTime = Instant.parse("2020-01-21T00:00:00Z")
        )
    )
    val token = server.issueToken(issuerId = "issuer1")
    // do whatever token testing you need to do here and assert the token has iat=2020-01-21T00:00:00Z
}
```

##### More examples

Have a look at some examples in both Java and Kotlin in the src/test directory:
* [Kotlin with the ktor framework](src/test/kotlin/examples/kotlin/ktor)
* [Java with Spring Boot and Spring Security](src/test/java/examples/java/springboot/)

### API

##### Server URLs

You can retrieve URLs from the server with the correct port and issuerId etc. by invoking one of the ` fun *Url(issuerId: String): HttpUrl` functions/methods:

```kotlin
val server = MockOAuth2Server()
server.start()
val wellKnownUrl = server.wellKnownUrl("yourissuer")
// will result in the following url:
// http://localhost:<a random port>/yourissuer/.well-known/openid-configuration
```

### Standalone server

The standalone server will default to port `8080` and can be started by invoking `main()` in  `StandaloneMockOAuth2Server.kt` (in kotlin) or `StandaloneMockOAuth2ServerKt` (in Java)

On Windows, it's easier to run the server in docker while specifying the host as localhost, e.g. `docker run -p 8080:8080 -h localhost $IMAGE_NAME`

> **Note**
> If you want to check if the server is up and running you can visit `/isalive` and see if you get a 200 in return.

#### Configuration

The standalone server supports the following configuration by `ENV` variables:

| Variable                | Description                                                                                |
|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `SERVER_HOSTNAME`       | Lets the standalone server bind to a specific hostname, by default it binds to `0.0.0.0`                                                                                |
| `SERVER_PORT` or `PORT` | The port that the standalone server will listen to, defaults to `8080`. The `PORT` environment variable may be used to [run the Docker image on Heroku](https://devcenter.heroku.com/articles/container-registry-and-runtime#pushing-an-existing-image) as per the documentation [here](https://devcenter.heroku.com/articles/setting-the-http-port-for-java-applications).                                                                                |
| `JSON_CONFIG_PATH`      | The absolute path to a json file containing configuration about the OAuth2 part of the server (`OAuth2Config`). More details on the format below.                                                                                |
| `JSON_CONFIG`           | The actual JSON content of `OAuth2Config`, this ENV var takes precedence over the `JSON_CONFIG_PATH` var. More details on the format below.                                                                                |
| `LOG_LEVEL`             | How verbose the root logging output is, defaults to `INFO`                                                                                |
| `LOGBACK_CONFIG`        | You can override the default logging config in [logback-standalone.xml](src/main/resources/logback-standalone.xml) with a path to your own logback xml file.                                                                                |

##### JSON_CONFIG

The JSON_CONFIG lets you configure the contents of the [`OAuth2Config`](src/main/kotlin/no/nav/security/mock/oauth2/OAuth2Config.kt) class using JSON.

Example:
```json
{
    "interactiveLogin": true,
    "httpServer": "NettyWrapper",
    "tokenCallbacks": [
        {
            "issuerId": "issuer1",
            "tokenExpiry": 120,
            "requestMappings": [
                {
                    "requestParam": "scope",
                    "match": "scope1",
                    "claims": {
                        "sub": "subByScope",
                        "aud": [
                            "audByScope"
                        ]
                    }
                }
            ]
        },
        {
            "issuerId": "issuer2",
            "requestMappings": [
                {
                    "requestParam": "someparam",
                    "match": "somevalue",
                    "claims": {
                        "sub": "subBySomeParam",
                        "aud": [
                            "audBySomeParam"
                        ]
                    }
                }
            ]
        }
    ]
}
```

A token provider can support different `signing` algorithms. Configure your token provider and
add this to your config with preferred `JWS algorithm`:

```json
{
  "tokenProvider" : {
    "keyProvider" : {
      "algorithm" : "ES256"
    }
  }
}
```

A token provider can also support a static "systemTime", i.e. the time for when the token is issued (`iat` claim) if you have tests that require a specific time.
The following configuration will set the system time to `2020-01-21T00:00:00Z`:

```json
{
  "tokenProvider" : {
    "systemTime" : "2020-01-21T00:00:00Z"
  }
}
```

| Property             | Description                                                                                |
|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `interactiveLogin`   | `true` or `false`, enables login screen when redirecting to server `/authorize` endpoint                                                                                |
| `loginPagePath`      | An optional string refering to a html file that is served as login page. This page needs to contain a form that posts a `username` and optionally a `claims` field. See `src/test/resource/login.example.html` as an example.                                                     |
| `staticAssetsPath`   | The path to a directory containing static resources/assets. Lets you serve your own static resources from the server. Resources are served under the `/static` URL path. E.g. http://localhost:8080/static/myimage.svg or by reference `/static/myimage.svg` from the login page. |                                                     |
| `rotateRefreshToken` | `true` or `false`, setting to true will generate a new unique refresh token when using the `refresh_token` grant.                                                                                |
| `httpServer`         | A string identifying the httpserver to use. Must match one of the following enum values: `MockWebServerWrapper` or `NettyWrapper`                                                                                |
| `tokenCallbacks`     | A list of [`RequestMappingTokenCallback`](src/main/kotlin/no/nav/security/mock/oauth2/token/OAuth2TokenCallback.kt) that lets you specify which token claims to return when a token request matches the specified condition.                                                      |

*From the first JSON example above:*

A token request to `http://localhost:8080/issuer1/token` with parameter `scope` equal to `scope1` will match the first `tokenCallback`:

```json
{
    "issuerId": "issuer1",
    "tokenExpiry": 120,
    "requestMappings": [
        {
            "requestParam": "scope",
            "match": "scope1",
            "claims": {
                "sub": "subByScope",
                "aud": [
                    "audByScope"
                ]
            }
        }
    ]
}
```

and return a token response containing a token with the following claims:

```json
{
  "sub": "subByScope",
  "aud": "audByScope",
  "nbf": 1616416942,
  "iss": "http://localhost:54905/issuer1",
  "exp": 1616417062,
  "iat": 1616416942,
  "jti": "28697333-6f25-4b1f-b2c2-409ce010933a"
}
```

Use variable `clientId` to set `sub` claim for Client Credentials Grant dynamically.

A token request with client credentials where `clientId = myClientId` and `tokenCallback`:
```json
{
    "issuerId": "issuer1",
    "tokenExpiry": 120,
    "requestMappings": [
        {
            "requestParam": "scope",
            "match": "scope1",
            "claims": {
                "sub": "${clientId}",
                "aud": [
                    "audByScope"
                ]
            }
        }
    ]
}
```
will return a token response containing a token with the following claims:

```json
{
  "sub": "myClientId",
  "aud": "audByScope",
  "nbf": 1616416942,
  "iss": "http://localhost:54905/issuer1",
  "exp": 1616417062,
  "iat": 1616416942,
  "jti": "28697333-6f25-4b1f-b2c2-409ce010933a"
}
```

#### Docker

Build to local docker daemon

```gradle
./gradlew -Djib.from.platforms=linux/amd64 jibDockerBuild # or alternatively -Djib.from.platforms=linux/arm64 for ARM64
```

Run container

```gradle
docker run -p 8080:8080 $IMAGE_NAME
```

#### Docker-Compose

In order to get container-to-container networking to work smoothly alongside browser interaction you must specify a host entry in your `hosts` file, `127.0.0.1 host.docker.internal` and set `hostname` in the **mock-oauth2-server** service in your `docker-compose.yaml` file:

```yaml
version: '3.7'
services:
  your_app:
    build: .
    ports:
      - 8080:8080
  mock-oauth2-server:
    image: ghcr.io/navikt/mock-oauth2-server:$MOCK_OAUTH2_SERVER_VERSION
    ports:
      - 8080:8080
    hostname: host.docker.internal
```

#### Debugger

The debugger is a OAuth2 client implementing the `authorization_code` flow with a UI for debugging (e.g. request parameters).
Point your browser to [http://localhost:8080/default/debugger](http://localhost:8080/default/debugger) to check it out.

### Enabling HTTPS

In order to enable HTTPS you can either provide your own keystore or let the server generate one for you.

#### Unit tests

You need to supply the server with an SSL config, in order to do that you must specify your chosen server type in `OAuth2Config` and
pass in the SSL config to your server.

*Generate keystore:*
```kotlin
val ssl = Ssl()
val server = MockOAuth2Server(
    OAuth2Config(httpServer = MockWebServerWrapper(ssl))
)
```
*This will generate a SSL certificate for `localhost` and can be added to your client's truststore by getting the ssl config:
`ssl.sslKeystore.keyStore`*

*Bring your own:*
```kotlin
val ssl = Ssl(
    SslKeystore(
        keyPassword = "",
        keystoreFile = File("src/test/resources/localhost.p12"),
        keystorePassword = "",
        keystoreType = SslKeystore.KeyStoreType.PKCS12
    )
)
val server = MockOAuth2Server(
    OAuth2Config(httpServer = MockWebServerWrapper(ssl))
)
```

#### Docker / Standalone mode - JSON_CONFIG

In order to enable HTTPS for the server in Docker or standalone mode
you can either make the server generate the keystore or bring your own.

*Generate keystore:*

```json
{
  "httpServer" : {
    "type" : "NettyWrapper",
    "ssl" : {}
  }
}
```

*Bring your own:*

```json

{
    "httpServer" : {
        "type" : "NettyWrapper",
        "ssl" : {
            "keyPassword" : "",
            "keystoreFile" : "src/test/resources/localhost.p12",
            "keystoreType" : "PKCS12",
            "keystorePassword" : ""
        }
    }
}
```

## Upgrading the gradle wrapper
Find the newest version of gradle here: https://gradle.org/releases/
Then run this command:
```./gradlew wrapper --gradle-version $gradleVersion```

Remeber to also update the gradle version in the build.gradle.kts file
``` gradleVersion = "$gradleVersion"```

## 👥 Contact

This project is currently maintained by the organisation [@navikt](https://github.com/navikt).

If you need to raise an issue or question about this library, please create an issue here and tag it with the appropriate label.

For contact requests within the [@navikt](https://github.com/navikt) org, you can use the Slack channel #pig_sikkerhet

If you need to contact anyone directly, please see contributors.

## ✏ Contributing

To get started, please fork the repo and checkout a new branch. You can then build the library with the Gradle wrapper

```shell script
./gradlew build
```

See more info in [CONTRIBUTING.md](CONTRIBUTING.md)

## ⚖ License
This library is licensed under the [MIT License](LICENSE.md)


![Accompanist logo](docs/header.png)

Accompanist is a group of libraries that aim to supplement [Jetpack Compose][compose] with features that are commonly required by developers but not yet available.

Accompanist is a labs like environment for new Compose APIs. We use it to help fill known gaps in the Compose toolkit, experiment with new APIs and to gather insight into the development experience of developing a Compose library. The goal of these libraries is to upstream them into the official toolkit, at which point they will be deprecated and removed from Accompanist.

For more details like, why does this library exist? Why is it not part of AndroidX? Will you be releasing more libraries? Check out our [Accompanist FAQ](https://medium.com/p/b55117b02712).

## Compose versions

Each [release](https://github.com/google/accompanist/releases) outlines what version of the Compose UI libraries it depends on. We are currently releasing multiple versions of Accompanist for the different versions of Compose:

  Compose 1.0 (1.0.x)

  Compose 1.1 (1.1.x)

  Compose UI 1.2 (1.2.x)

  Compose UI 1.3 (1.3.x)

  Compose UI 1.4 (1.4.x)

  Compose UI 1.5 (1.5.x)

  Compose UI 1.6 (1.6.x)

  Compose UI 1.7 (1.7.x)

For stable versions of Compose, we use the latest *stable* version of the Compose compiler. For non-stable versions (alpha, beta, etc), we use the latest compiler at the time of release.

> :warning: **Ensure you are using the Accompanist version that matches with your Compose UI version**: If you upgrade Accompanist, it will upgrade your Compose libraries version via transitive dependencies.

## Libraries

### 📫 [Permissions](./permissions/)
A library that provides [Android runtime permissions][runtimepermissions] support for Jetpack Compose.

### 🖌 [Drawable Painter](./drawablepainter/)
A library which provides a way to use Android Drawables as Jetpack Compose Painters.

### 📜 [Adaptive](./adaptive/)
A library providing a collection of utilities for adaptive layouts.

### ⬇ [Swipe to Refresh](./swiperefresh/) (Deprecated)
See our [Migration Guide](https://google.github.io/accompanist/swiperefresh/) for migrating to PullRefresh in Compose Material.

### 🎨 [AppCompat Theme Adapter](./appcompat-theme/) (Deprecated)
See our [Migration Guide](https://google.github.io/accompanist/appcompat-theme/) for migrating to the new artifact in Accompanist.

### 📖 [Pager](./pager/) (Deprecated)
See our [Migration Guide](https://google.github.io/accompanist/pager/) for migrating to Pager in Compose.

### 🌊 [Flow Layouts](./flowlayout/) (Deprecated)
See our [Migration Guide](https://google.github.io/accompanist/flowlayout/) for migrating to FlowLayout in Compose.

### 🧭✨[Navigation-Animation](./navigation-animation/) (Deprecated)
See our [Migration Guide](https://google.github.io/accompanist/navigation-animation/) for migrating to using built in support for animations in Jetpack Navigation Compose.

### 🧭🎨 [Navigation-Material](./navigation-material/) (Deprecated)
See our [Migration Guide](https://google.github.io/accompanist/navigation-material/) for migrating to using built in material-navigation support.

### ⏳ [Placeholder](./placeholder/) (Deprecated)
A library that provides easy-to-use modifiers for displaying a placeholder UI while content is loading.

### 🍫 [System UI Controller](./systemuicontroller/) (Deprecated)
We recommend migrating to edge to edge. See our [Migration Guide](https://google.github.io/accompanist/systemuicontroller/) for more details.

### 🎨 [AppCompat Theme Adapter](./themeadapter-appcompat/) (Deprecated)
A library that enables the reuse of [AppCompat][appcompat] XML themes, for theming in Jetpack Compose.

### 🎨 [Material Theme Adapter](./themeadapter-material/) (Deprecated)
A library that enables the reuse of [MDC-Android][mdc] Material 2 XML themes, for theming in Jetpack Compose.

### 🎨 [Material 3 Theme Adapter](./themeadapter-material3/) (Deprecated)
A library that enables the reuse of [MDC-Android][mdc] Material 3 XML themes, for theming in Jetpack Compose.

### 🌏 [Web](./web/) (Deprecated)
A wrapper around WebView for basic WebView support in Jetpack Compose.

### 🗜 [Test Harness](./testharness/) (Deprecated)
Utilities for testing Compose layouts.

### 📐 [Insets](./insets/) (Deprecated & Removed)
See our [Migration Guide](https://google.github.io/accompanist/insets/) for migrating to Insets in Compose.

---

## Future?

Any of the features available in this group of libraries may become obsolete in the future, at which point they will (probably) become deprecated.

We will aim to provide a migration path (where possible), to whatever supersedes the functionality.

## Snapshots

Snapshots of the current development version of Accompanist are available, which track the latest commit. See [here](docs/using-snapshot-version.md) for more information.

---

### Why the name?

The library is all about adding some utilities around Compose. Music composing is done by a
composer, and since this library is about supporting composition, the supporting role of an [accompanist](https://en.wikipedia.org/wiki/Accompaniment) felt like a good name.

## Contributions

Please contribute! We will gladly review any pull requests.
Make sure to read the [Contributing](CONTRIBUTING.md) page first though.

## License

```
Copyright 2020 The Android Open Source Project

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

    https://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.
```

[appcompat]: https://developer.android.com/jetpack/androidx/releases/appcompat
[compose]: https://developer.android.com/jetpack/compose
[snap]: https://oss.sonatype.org/content/repositories/snapshots/com/google/accompanist/
[mdc]: https://github.com/material-components/material-components-android
[windowinsets]: https://developer.android.com/reference/kotlin/android/view/WindowInsets
[viewpager]: https://developer.android.com/reference/kotlin/androidx/viewpager/widget/ViewPager
[runtimepermissions]: https://developer.android.com/guide/topics/permissions/overview


Specmatic
========
[![Maven Central](https://img.shields.io/maven-central/v/in.specmatic/specmatic-core.svg)](https://mvnrepository.com/artifact/in.specmatic/specmatic-core) [![GitHub release](https://img.shields.io/github/v/release/znsio/specmatic.svg)](https://github.com/znsio/specmatic/releases) ![CI Build](https://github.com/znsio/specmatic/workflows/CI%20Build/badge.svg) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=znsio_specmatic&branch=main&metric=alert_status)](https://sonarcloud.io/dashboard?id=znsio_specmatic&branch=main) [![Twitter Follow](https://img.shields.io/twitter/follow/specmatic.svg?style=social&label=Follow)](https://twitter.com/specmatic) [![Docker Pulls](https://img.shields.io/docker/pulls/znsio/specmatic.svg)](https://hub.docker.com/r/znsio/specmatic)

### Context

In a complex, interdependent eco-system, where each service is evolving rapidly, we want to make the dependencies between them explicit in the form of executable contracts. [Contract Driven Development](https://specmatic.in/contract_driven_development.html) leverages API specifications like OpenAPI, AsyncAPI, etc. as executable contracts allowing teams to get instantaneous feedback while making changes to avoid accidental breakage.

With this ability, we can now independently deploy, at will, any service at any time without having to depend on expensive and fragile integration tests.

### What is Specmatic
Specmatic embodies [contract driven development](https://specmatic.in/contract_driven_development.html) (CDD) by leveraging API specifications as executable contracts.
* [Contract as Tests](https://specmatic.in/#contract-as-test) - Generating free tests on the fly based only on you API specifications making sure that your implementation is always adhering to your API specification
* [Contract as Stub](https://specmatic.in/#contract-as-stub) - Stubbing a service based on its API specification, that too with the guarantee that your response mappings will always be in sync with your API specs
* [Backward Compatibility Testing](https://specmatic.in/#contract-vs-contract) (#NOCODE) - Identify backward breaking changes well ahead of time even before write any code based only on your API specifications
* [Central Contract Repository](https://specmatic.in/#contract-as-code) - Single source of truth for your API Specifications
* [API First Design](https://youtu.be/uaaevRw0TN4?list=PL9Z-JgiTsOYRERcsy9o3y6nsi5yK3IB_w&t=1306) - CDD encourages putting API design first rather than design being a byproduct of service implementation

### Our Goal is to support various types of Interactions
Systems interact with each other through several means. Specmatic hopes to address all these mechanisms and not just web interactions.
* API calls (**JSon REST**, **SOAP XML**, gRPC, Thrift, other binary protocols)
* Events via Messaging (**Kafka**, Redis, ActiveMQ, RabbitMQ, Kinesis, etc.)
* DB, Other Data Stores
* File system
* Libraries, SDK
* OS Level Pipes

[Specmatic's Product Roadmap](https://specmatic.in/roadmap/)

Learn more at [specmatic.in](https://specmatic.in/#features)

[Get started now](https://specmatic.in/getting_started.html)

[![Specmatic - Contract Driven Development - YouTube playlist](https://img.youtube.com/vi/KWCnTi-ifME/0.jpg)](https://www.youtube.com/watch?v=KWCnTi-ifME&list=PL9Z-JgiTsOYRERcsy9o3y6nsi5yK3IB_w&index=2)

[Youtube playlist](https://www.youtube.com/watch?v=3HPgpvd8MGg&list=PL9Z-JgiTsOYRERcsy9o3y6nsi5yK3IB_w)


# Claw for [lobste.rs](https://lobste.rs) [![CI](https://github.com/msfjarvis/compose-lobsters/actions/workflows/ci.yml/badge.svg)](https://github.com/msfjarvis/compose-lobsters/actions/workflows/ci.yml)

Unofficial Android app for read-only access to [lobste.rs](https://lobste.rs), built with [Jetpack Compose](https://developer.android.com/jetpack/compose).

> [!NOTE]
> Daily builds are published to the Google Play 'Open Testing' channel (if there are any changes), which can be opted into via this link: [[Android]](https://play.google.com/store/apps/details?id=dev.msfjarvis.claw.android) [[Web]](https://play.google.com/apps/testing/dev.msfjarvis.claw.android)

## License

See [LICENSE](LICENSE)


# RADAR-Schemas

[Avro schemas](https://avro.apache.org/docs/1.9.2/spec.html) used in RADAR-base. The schemas are organized as follows:

- The `commons` directory contains all schemas used inside Kafka and data fed into Kafka.
  - In the `active` subdirectory, add schemas for active data collection, like questionnaires or assignments.
  - In the `catalogue` subdirectory, modify schemas for cataloguing data types.
  - In the `kafka` subdirectory, add schemas used throughtout Kafka, like record keys.
  - In the `monitor` subdirectory, add schemas for monitoring applications that gather data.
  - In the `passive` subdirectory, add schemas for passive data collection, like wearables.
  - In the `stream` subdirectory, add schemas used in Kafka Streams.
- The `specifications` directory contains specifications of what data types are collected through which devices.
  - Java SDKs for each of the components are provided in the `java-sdk` folder, see installation instructions there. They are automatically generated from the Avro schemas using the Avro specification (version in [Versions.kt](java-sdk/buildSrc/src/main/kotlin/Versions.kt)).

## Usage

This project can be used in RADAR-base by using the `radarbase/kafka-init` Docker image. The schemas and specifications can be extended by locally creating a directory structure that includes a `commons` and `specifications` directory and mounting it to the image, to the `/schema/conf/commons` and `/schema/conf/specifications` directories, respectively. You can provide a file path in `CONFIG_YAML` that points to a `config.yaml` file that is mounted in the docker container. The config file has the following format:

```yaml
# Specify any Kafka properties needed to connect to the Kafka cluster
kafka:
  security.protocol: PLAINTEXT

# Configure additional topics, or specify the properties of a topic listed elsewhere.
topics:
  my_custom_topic:
    # Enable configuration of this topic
    enabled: true
    # Number of partitions to use, if newly created
    partitions: 3
    # Replication factor, if newly created
    replicationFactor: 2
    # Topic properties in Kafka. See
    # <https://docs.confluent.io/platform/current/installation/configuration/topic-configs.html#ak-topic-configurations-for-cp>
    properties:
      cleanup.policy: compact
    # Key schema for the topic
    keySchema: my.key.Schema
    # Value schema for the topic
    valueSchema: my.value.Schema
    # Whether to register the schemas to the Schema Registry
    registerSchema: false

# Schema configuration. This refers to the files in the commons directory.
schemas:
  # Only include given schema directory files. You can use File glob syntax as described in <https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String->
  # If include is specified, exclude will be ignored. The glob pattern should start from the commons directory.
  include: []
  # Exclude all given schema directory files. You can use File glob syntax as described in <https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String->
  # If include is specified, exclude will be ignored. The glob pattern should start from the commons directory.
  exclude:
    - active/**
  # You can specify additional schemas, using the format for each respective specification directory.
  monitor:
    # The object name is the path it would have, the value is a plain string containing a JSON object
    application/application_uptime2.avsc: >
      {
        "namespace": "org.radarcns.monitor.application",
        "type": "record",
        "name": "ApplicationUptime2",
        "doc": "Length of application uptime.",
        "fields": [
          { "name": "time", "type": "double", "doc": "Device timestamp in UTC (s)." },
          { "name": "uptime", "type": "double", "doc": "Time since last app start (s)." }
        ]
      }

# Source configuration. This refers to the files in the specifications directory.
sources:
  # Only include given specification directory files. You can use File glob syntax as described in <https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String->
  # If include is specified, exclude will be ignored. The glob pattern should start from the specifications directory.
  include:
    - passive/*
  # Exclude all given specification directory files. You can use File glob syntax as described in <https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String->
  # If include is specified, exclude will be ignored. The glob pattern should start from the specifications directory.
  exclude: []
  # You can specify additional sources, using the format for each respective specification directory.
  monitor:
    - vender: test
      model: test
      version: 1.0.0
      data:
        type: UPTIME
        topic: application_uptime2
        value_schema: .monitor.application.ApplicationUptime2
```

Please see the inline comments for more information on their values.

## Contributing

The Avro schemas should follow the [Google JSON style guide](https://google.github.io/styleguide/jsoncstyleguide.xml).

In addition, schemas in the `commons` directory should follow the following guidelines:

- Try to avoid abbreviations in the field names and write out the field name instead.
- There should be no need to add `value` at the end of a field name.
- Enumerator items should be written in uppercase characters separated by underscores.
- Add documentation (the `doc` property) to each schema, each field, and each enum. The documentation should show in text what is being measured, how, and what units or ranges are applicable. Abbreviations and acronyms in the documentation should be written out. Each doc property should start with a capital and end with a period.
- Prefer a categorical specification (an Avro enum) over a free string if that categorization is expected to remain very stable. This disambiguates the possible values for analysis. If a field is expected to be extended outside this project or very often within this project, use a free string instead.
- Prefer a flat record over a hierarchical record. This simplifies the organization of the data downstream, for example, when mapping to CSV.
- Prefer written out fields to arrays. This simplifies the organization of the data downstream, for example, when mapping to CSV.
- Give each schema a proper namespace, preferably `org.radarcns.passive.<vendor>` fully in lowercase, without any numbers, uppercase letters or symbols (except `.`). For the Empatica E4, the vendor is Empatica, so the namespace is `org.radarcns.passive.empatica`. For generic types, like a phone, Android Wear device or Android application, the namespace could just be `org.radarcns.passive.phone`, `org.radarcns.passive.wear`, or `org.radarcns.monitor.application`.
- In the schema name, use upper camel case and name the device explicitly (for example, `EmpaticaE4Temperature`).
- For fields that are inherent to a record, and will never be removed or renamed, no default value is needed. For all other fields:
  - if the type is an enum, use an `UNKNOWN` symbol as default value
  - otherwise, set the type to a union of `["null", <intended type>]` and set the default value to `null`.

### Validation phase

Avro schemas are automatically validated against RADAR-base guide lines while building. For more details, check [catalog validator](java-sdk/radar-schemas-tools).

### Test setup

The RADAR schema tools can be tested locally using Docker. To run the tools, first install Docker. Then run

```shell
docker-compose build
docker-compose up -d zookeeper-1 kafka-1 schema-registry-1
```
Now you can run tools commands with
```shell
# usage
docker-compose run --rm tools
# validation
docker-compose run --rm tools radar-schemas-tools validate /schema/merged
# list topic information
docker-compose run --rm tools radar-schemas-tools list /schema/merged
# register schemas with the schema registry
docker-compose run --rm tools radar-schemas-tools register http://schema-registry-1:8081 /schema/merged
# create topics with zookeeper
docker-compose run --rm tools radar-schemas-tools create -s kafka-1:9092 -b 1 -r 1 -p 1 /schema/merged
# run source-catalogue webservice
docker-compose run -p 8080:8080 --rm tools radar-catalog-server -p 8080 /schema/merged
# and in a separate console, run
curl localhost:8080/source-types
# back up the _schemas topic
docker-compose run --rm tools radar-schemas-tools schema-topic --backup -f schema.json -b 1 -s kafka-1:9092 -f /schema/conf/backup.json /schema/merged
# ensure the validity of the _schemas topic
docker-compose run --rm tools radar-schemas-tools schema-topic --ensure -f schema.json -b 1 -s kafka-1:9092 -f /schema/conf/backup.json -r 1 /schema/merged
```

### Using radar-schema-tools with Confluent Cloud

1. Create topics on Confluent Cloud

    1.1. Create a `config.yaml` file. A Confluent Cloud config for Java application based on this [template](https://github.com/confluentinc/configuration-templates/blob/master/clients/cloud/java-sr.config).

    ```yaml

    kafka:
      bootstrap.servers: {{ BROKER_ENDPOINT }}
      security.protocol: SASL_SSL
      sasl.jaas.config: org.apache.kafka.common.security.plain.PlainLoginModule required username="{{ CLUSTER_API_KEY }}" password="{{ CLUSTER_API_SECRET }}";
      ssl.endpoint.identification.algorithm: https
      sasl.mechanism: PLAIN
    ```

    1.2. Run `create` command

    ```
    docker run --rm -v "$PWD/config.yaml:/etc/radar-schemas-tools/config.yaml" radarbase/radar-schemas-tools radar-schemas-tools create -c /etc/radar-schemas-tools/config.yaml /schema/merged
    ```

2. Register schemas on Confluent Cloud schema registry

    ```
    docker run --rm -v "$PWD/config.yaml:/etc/radar-schemas-tools/config.yaml" radarbase/radar-schemas-tools radar-schemas-tools register -c /etc/radar-schemas-tools/config.yaml -u SR_API_KEY -p SR_API_SECRET SR_ENDPOINT /schema/merged
    ```

   Note that the `SR_ENDPOINT` and `/schema/merged` are positional arguments and should be placed at the end of the command.


Pact-JVM
========

[![Pact-JVM Build](https://github.com/pact-foundation/pact-jvm/workflows/Pact-JVM%20Build/badge.svg)](https://github.com/pact-foundation/pact-jvm/actions?query=workflow%3A%22Pact-JVM+Build%22)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/au.com.dius.pact.core/model/badge.svg?style=flat)](https://maven-badges.herokuapp.com/maven-central/au.com.dius.pact.core/model)

JVM implementation of the consumer driven contract library [pact](https://github.com/pact-foundation/pact-specification).

From the [Ruby Pact website](https://github.com/pact-foundation/pact-ruby):

> Define a pact between service consumers and providers, enabling "consumer driven contract" testing.
>
>Pact provides an RSpec DSL for service consumers to define the HTTP requests they will make to a service provider and the HTTP responses they expect back.
>These expectations are used in the consumers specs to provide a mock service provider. The interactions are recorded, and played back in the service provider
>specs to ensure the service provider actually does provide the response the consumer expects.
>
>This allows testing of both sides of an integration point using fast unit tests.
>
>This gem is inspired by the concept of "Consumer driven contracts". See https://martinfowler.com/articles/consumerDrivenContracts.html for more information.

Read [Getting started with Pact](https://dius.com.au/2016/02/03/pact-101-getting-started-with-pact-and-consumer-driven-contract-testing/) for more information on
how to get going.

## Contact

* Twitter: [@pact_up](https://twitter.com/pact_up)
* Slack: [Join the chat at https://slack.pact.io/](https://slack.pact.io/)
* Stack Overflow: https://stackoverflow.com/questions/tagged/pact

## Links

* For examples of using pact-jvm with spring boot, have a look at https://github.com/Mikuu/Pact-JVM-Example and https://github.com/mstine/microservices-pact

## Tutorial (60 minutes)

Learn everything in Pact in 60 minutes: https://github.com/pact-foundation/pact-workshop-jvm-spring.

The workshop takes you through all of the key concepts of consumer and provider testing using a Spring boot application.

## Documentation

Additional documentation can be found at [docs.pact.io](http://docs.pact.io), in the [Pact Wiki](https://github.com/realestate-com-au/pact/wiki),
and in the [Pact-JVM wiki](https://github.com/DiUS/pact-jvm/wiki). [Stack Overflow](https://stackoverflow.com/questions/tagged/pact) is also a good source of help, as is the [Slack workspace](https://slack.pact.io).

## Supported JDK and specification versions:

| Branch                                                                 | Specification | JDK        | Kotlin Version | Latest Version | Notes |
|------------------------------------------------------------------------|---------------|------------|----------------|----------------|-------|
| [4.6.x](https://github.com/DiUS/pact-jvm/blob/v4.6.x/README.md) master | V4 + plugins  | 17+        | 1.8.22         | 4.6.9          |       |
| [4.5.x](https://github.com/DiUS/pact-jvm/blob/v4.5.x/README.md)        | V4 + plugins  | 11+/17+(1) | 1.7.20         | 4.5.9          |       |
| [4.1.x](https://github.com/DiUS/pact-jvm/blob/v4.1.x/README.md)        | V3            | 8-12       | 1.3.72         | 4.1.42         |       |

**Notes:**
* **1:** Spring6 support library requires JDK 17+. The rest of Pact-JVM 4.5.x libs require 11+.

### Previous versions (not actively supported)

| Branch                                                                    | Specification | JDK       | Kotlin Version | Scala Versions | Latest Version |
|---------------------------------------------------------------------------|---------------|-----------|----------------|----------------|----------------|
| [4.4.x](https://github.com/DiUS/pact-jvm/blob/v4.4.x/README.md)           | V4 + plugins  | 11+       | 1.6.21         | N/A            | 4.4.9          |
| [4.3.x](https://github.com/DiUS/pact-jvm/blob/v4.3.x/README.md)           | V4            | 11+       | 1.6.21         | N/A            | 4.3.19         |
| [4.2.x](https://github.com/DiUS/pact-jvm/blob/v4.2.x/README.md)           | V4 (1)        | 11-15 (2) | 1.4.32         | N/A            | 4.2.21         |
| [4.0.x](https://github.com/DiUS/pact-jvm/blob/v4.x/README.md)             | V3            | 8-12      | 1.3.71         | N/A            | 4.0.10         |
| [3.6.x](https://github.com/DiUS/pact-jvm/blob/v3.6.x/README.md)           | V3            | 8         | 1.3.71         | 2.12           | 3.6.15         |
| [3.5.x](https://github.com/DiUS/pact-jvm/blob/v3.5.x/README.md)           | V3            | 8         | 1.1.4-2        | 2.12, 2.11     | 3.5.25         |
| [3.5.x-jre7](https://github.com/DiUS/pact-jvm/blob/v3.5.x-jre7/README.md) | V3            | 7         | 1.1.4-2        | 2.11           | 3.5.7-jre7.0   |
| [2.4.x](https://github.com/DiUS/pact-jvm/blob/v2.x/README.md)             | V2            | 6         | N/A            | 2.10, 2.11     | 2.4.20         |

**Notes:**
* **1:** V4 specification support is only partially implemented with 4.2.x
* **2:** v4.2.x may run on JDK 16, but the build for it does not.

**NOTE:** The JARs produced by this project have changed with 4.1.x to better align with Java 9 JPMS. The artefacts are now:

```
au.com.dius.pact:consumer
au.com.dius.pact.consumer:groovy
au.com.dius.pact.consumer:junit
au.com.dius.pact.consumer:junit5
au.com.dius.pact.consumer:java8
au.com.dius.pact.consumer:specs2_2.13
au.com.dius.pact:pact-jvm-server
au.com.dius.pact:provider
au.com.dius.pact.provider:scalatest_2.13
au.com.dius.pact.provider:spring
au.com.dius.pact.provider:maven
au.com.dius.pact:provider
au.com.dius.pact.provider:junit
au.com.dius.pact.provider:junit5
au.com.dius.pact.provider:scalasupport_2.13
au.com.dius.pact.provider:lein
au.com.dius.pact.provider:gradle
au.com.dius.pact.provider:specs2_2.13
au.com.dius.pact.provider:junit5spring
au.com.dius.pact.core:support
au.com.dius.pact.core:model
au.com.dius.pact.core:matchers
au.com.dius.pact.core:pactbroker
```

## Service Consumers

Pact-JVM has a number of ways you can write your service consumer tests.

### I Use Scala

You want to look at: [pact4s](https://github.com/jbwheatley/pact4s).

### I Use Java

You want to look at: [junit](consumer/junit) for JUnit 4 tests and
[junit5](consumer/junit5) for JUnit 5 tests. Also, if you are using Java 11 or above, there is [an
updated DSL for consumer tests](/consumer).

**NOTE:** If you are using Java 8, there is no separate Java 8 support library anymore, see the above library.

### I Use Groovy or Grails

You want to look at: [groovy](consumer/groovy) or [junit](consumer/junit)

### (Use Clojure I)

Clojure can call out to Java, so have a look at [junit](consumer/junit). For an example
look at [example_clojure_consumer_pact_test.clj](https://github.com/DiUS/pact-jvm/blob/master/consumer/junit/src/test/clojure/au/com/dius/pact/consumer/junit/example_clojure_consumer_pact_test.clj).

### I Use some other jvm language or test framework

You want to look at: [Consumer](consumer)

### My Consumer interacts with a Message Queue

As part of the V3 pact specification, we have defined a new pact file for interactions with message queues. For an
  implementation of a Groovy consumer test with a message pact, have a look at [PactMessageBuilderSpec.groovy](https://github.com/DiUS/pact-jvm/blob/master/consumer/groovy/src/test/groovy/au/com/dius/pact/consumer/groovy/messaging/PactMessageBuilderSpec.groovy).

## Service Providers

Once you have run your consumer tests, you will have generated some Pact files. You can then verify your service providers
with these files.

### I am writing a provider and want to ...

#### verify pacts with SBT

You want to look at: [pact4s](https://github.com/jbwheatley/pact4s) or [scala-pact](https://github.com/ITV/scala-pact)

#### verify pacts with Gradle

You want to look at: [pact gradle plugin](provider/gradle)

#### verify pacts with Maven

You want to look at: [pact maven plugin](provider/maven)

#### verify pacts with JUnit tests

You want to look at: [junit provider support](provider/junit) for JUnit 4 tests and
 [junit5](provider/junit5) for JUnit 5 tests

#### verify pacts with Leiningen

You want to look at: [pact leiningen plugin](provider/lein)

#### verify pacts with a Spring MVC project

Have a look at [spring](provider/spring) or [Spring MVC Pact Test Runner](https://github.com/realestate-com-au/pact-jvm-provider-spring-mvc) (Not maintained).

#### I want to verify pacts but don't want to use sbt or gradle or leiningen

You want to look at: [provider](provider)

#### verify interactions with a message queue

As part of the V3 pact specification, we have defined a new pact file for interactions with message queues. The Gradle
pact plugin supports a mechanism where you can verify V3 message pacts, have a look at [pact gradle plugin](provider/gradle#verifying-a-message-provider).
The JUnit pact library also supports verification of V3 message pacts, have a look at [junit](provider/junit#verifying-a-message-provider).

### I Use Ruby or Go or something else
The pact-jvm libraries are pure jvm technologies and do not have any native dependencies.

However, if you have a ruby provider, the json produced by this library is compatible with the ruby pact library.
You'll want to look at: [Ruby Pact](https://github.com/pact-foundation/pact-ruby).

For .Net, there is [Pact-net](https://github.com/pact-foundation/pact-net).

For JS, there is [Pact-JS](https://github.com/pact-foundation/pact-js).

For Go, there is [Pact-go](https://github.com/pact-foundation/pact-go).

For Rust, there is [Pact-Rust](https://github.com/pact-foundation/pact-reference/tree/master/rust/pact_consumer).

Have a look at [implementations in other languages](https://github.com/realestate-com-au/pact/wiki#implementations-in-other-languages).

### I Use something completely different

There's a limit to how much we can help, however check out [pact-jvm-server](pact-jvm-server)

## How do I transport my pacts from consumers to providers?

You want to look at:
[Pact Broker](https://github.com/pact-foundation/pact_broker)

Which is a project that aims at providing tooling to coordinate pact generation and delivery between projects.

## I want to contribute

[Documentation for contributors is here](https://github.com/DiUS/pact-jvm/blob/master/CONTRIBUTING.md).

# Test Analytics

We are tracking anonymous analytics to gather important usage statistics like JVM version
and operating system. To disable tracking, set the 'pact_do_not_track' system property or environment
variable to 'true'.


[![Build Status](https://github.com/dkandalov/live-plugin/workflows/CI/badge.svg)](https://github.com/dkandalov/live-plugin/actions)

# LivePlugin
Plugin for [IntelliJ](https://github.com/JetBrains/intellij-community)-based IDEs to create plugins at runtime
using [Kotlin](http://kotlinlang.org) and [Groovy](http://groovy.codehaus.org).
To install search for "LivePlugin" in `IDE Preferences -> Plugins -> Marketplace`
or use the "Install" button on the [Plugin Marketplace website](http://plugins.jetbrains.com/plugin/7282).

<img src="https://raw.github.com/dkandalov/live-plugin/master/screenshots/live-plugin-demo.gif" alt="demo" title="demo" align="middle"/>

## Why?
 - **Minimal setup** — no need to set up a separate project for plugin development
 - **Fast feedback loop** — plugins are (re)loaded in the same JVM instance as IDE without restart
 - **Usable IDE API** — LivePlugin has a small API with entry points for common IDE APIs

## Examples
Hello world (Groovy):
```groovy
import static liveplugin.PluginUtil.show
show("Hello world") // Shows balloon notification popup with "Hello world" text
```
Insert New Line Above action (Kotlin):
```kotlin
import com.intellij.openapi.actionSystem.AnActionEvent
import liveplugin.*

// Action to insert a new line above the current line.
// Based on this post https://martinfowler.com/bliki/InternalReprogrammability.html
// Note that there is also built-in "Start New Line Before Current" action (ctrl+alt+enter).
registerAction(id = "Insert New Line Above", keyStroke = "ctrl alt shift ENTER") { event ->
    val project = event.project ?: return@registerAction
    val editor = event.editor ?: return@registerAction
    executeCommand(editor.document, project) { document ->
        val caretModel = editor.caretModel
        val lineStartOffset = document.getLineStartOffset(caretModel.logicalPosition.line)
        document.insertString(lineStartOffset, "\n")
        caretModel.moveToOffset(caretModel.offset + 1)
    }
}
show("Loaded 'Insert New Line Above' action<br/>Use 'ctrl+alt+shift+Enter' to run it")
```

## Getting started
Make sure "hello world" works fine:
- In the `Plugins` tool window select "hello-world" plugin and click "Run" button to execute the plugin (`Run Plugin`
  action with `ctrl+shift+L` or `alt+C, alt+E` shortcut). It should display a message.
- Make a small modification in `plugin.groovy`/`plugin.kts` and rerun the plugin.
  On the second run, the previous version of the plugin will be unloaded before the code is evaluated again.
- Modify `plugin.groovy`/`plugin.kts` file again so that it fails to compile/run.
  You should see an error message in the `Run` tool window.
- Note that plugins are just folders with `plugin.groovy` or `plugin.kts` scripts as entry points.
  This means that you can, for example, copy the path to the plugin folder using the `Copy Path` action (`ctrl/cmd+alt+C` shortcut).

Try bundled examples:
- In the `Plugins` tool window click the "Plus" button (`Add Plugin` action) to add Kotlin or Groovy examples.
- It might be useful to install [Kotlin](https://plugins.jetbrains.com/plugin/6954-kotlin) or
[Groovy](http://plugins.jetbrains.com/plugin/1524?pr=idea) plugin if your IDE supports them.

Take a look at settings in the `Plugins` toowindow:
- `Run Plugins on IDE Start` — run all plugins on IDE start.
- `Run Project Specific Plugins` — run all plugins in `.live-plugins` project directory when
the project is opened and unload them when the project is closed.
- `Add LivePlugin and IDE Jars to Project` — useful for Groovy plugins
to get auto-completion and code navigation in plugin code.
(Adding jars unrelated to your project is a bit of a hack but there seems to be no major problems with it.)
Note that Kotlin plugins should have auto-completion and code navigation without it.

Learn more about IntelliJ API:
- Read (or at least skim) [plugin development fundamentals](https://plugins.jetbrains.com/docs/intellij/fundamentals.html).
- Explore [IntelliJ source code](https://github.com/JetBrains/intellij-community)
by cloning it, browsing it on GitHub or in
[Upsource](https://upsource.jetbrains.com/idea-ce/structure/idea-ce-ba0c8fc9ab9bf23a71a6a963cd84fc89b09b9fc8/).
  One useful strategy is to search for text you can see in IDE UI and then figure out
  how it's connected to the code which does the actual work.
- [PluginUtil](https://github.com/dkandalov/live-plugin/blob/master/src/plugin-api-groovy/liveplugin/PluginUtil.groovy) class
  and [liveplugin](https://github.com/dkandalov/live-plugin/tree/master/src/plugin-api-kotlin/liveplugin) package
  might have some good starting points to explore IntelliJ API.

Once your plugin has grown, you can move it to a proper plugin project
[still using live plugin for reloading](https://github.com/dkandalov/live-plugin/wiki/Liveplugin-as-an-entry-point-for-standard-plugins)
and maybe then convert it to become a [dynamic plugin](https://plugins.jetbrains.com/docs/intellij/dynamic-plugins.html).

If something doesn't work or doesn't make sense, please feel free to ask
in `#plugin-live-plugin` channel on [Jetbrains platform slack](https://plugins.jetbrains.com/slack)
or [report an issue](https://github.com/dkandalov/live-plugin/issues)
(it's ok to report an issue even if it's just a question).

## How does LivePlugin work?
Overall, the idea is just to load and run plugin Groovy or Kotlin classes in the IDE JVM at runtime.
More specifically the steps are:
- if there is an instance of `pluginDisposable` from previous execution, then dispose it (on EDT)
- create a new classloader with dependencies on other plugins and jars (on a background thread)
- compile code if necessary and load classes in the classloader (on a background thread)
- run the plugin code (on EDT)

This means that plugin code can use any internal IDE API and observe/change IDE state.
There are some limitations of course, such as `final` fields and IDE APIs which are not designed to be re-initialized.

Most IntelliJ-based IDEs come with a bundled Groovy jar which is used for loading and running live plugins
(otherwise, the groovy-all jar will be downloaded). LivePlugin uses its own version of Kotlin stdlib and compiler because
the version bundled with IDEs changes quite often and seems to be harder to rely on.

## Some practical use cases
- project-specific workflow automation
- integrating shell scripts with IDE
- prototyping plugins, experimenting with IntelliJ API

## More examples
 - [intellij-emacs](https://github.com/kenfox/intellij-emacs) - macros for making IntelliJ more friendly to emacs users (see also [blog post](http://spin.atomicobject.com/2014/08/07/intellij-emacs/))
 - [Simplistic "compile and run haskell" action](https://gist.github.com/dkandalov/11051113) - this can also be done for other languages/environments
 - [Google quick search popup](https://gist.github.com/dkandalov/277800d12ecbfc533fcd) - prototype of google popup search mini-plugin
 - [Scripting a macros](https://github.com/dkandalov/live-plugin/wiki/Scripting-a-macros) - example of finding and invoking built-in actions
 - [Console filter/transform example](https://github.com/dkandalov/live-plugin/wiki/Console-filtering) - example of filtering and changing console output
 - [VCS update listener example](https://gist.github.com/dkandalov/8840509) - example of adding callback on VCS update
 - [Find class dependencies](https://gist.github.com/dkandalov/6976133) - simple action to find all class dependencies within current project
 - [Module transitive dependencies](https://gist.github.com/dkandalov/80d8d4f71bef54290a71) - finds all transitive dependencies for modules in IDEA project
 - [Show text diff](https://gist.github.com/dkandalov/6728950) - really lame example of opening IntelliJ text diff window (please don't use it!)
 - [Find all recursive methods in project (for Java)](https://gist.github.com/dkandalov/7248184) - quick plugin as a follow-up for this [talk](http://skillsmatter.com/podcast/nosql/using-graphs-for-source-code-analysis)
 - [Watching projects open/close events](https://gist.github.com/dkandalov/6427087) - an example of reloadable project listener
 - [Minimalistic view for java code](https://gist.github.com/dkandalov/708664109a37c3c0ff15) - collapses most of Java keywords and types leaving only variable names
 - [Symbolize keywords](https://gist.github.com/dkandalov/5553999) - collapses Java keywords into shorter symbols
 - [Change List Size Watchdog](https://gist.github.com/dkandalov/5004622) - micro-plugin to show warning when change list size exceeds threshold (see also [Limited WIP plugin](https://github.com/dkandalov/limited-wip))
 - [Template completion on "Tab"](https://gist.github.com/dkandalov/5222759) - simplistic prototype for auto-completion on tab key (in case built-in live templates are not enough)
 - [Completion contributor example](https://gist.github.com/dkandalov/5977888) - only gives an idea which part of IntelliJ API to use
 - [Google auto-completion contributor example](https://github.com/dkandalov/live-plugin/wiki/Google-auto-complete) - same as above but with Google search plugged in
 - [Add custom search example](https://gist.github.com/dkandalov/5956923) - only gives an idea which part of IntelliJ API to use
 - [Get files from last commits example](https://gist.github.com/dkandalov/5984577) - gets VirtualFiles from several last commits
 - [Show PSI view dialog](https://gist.github.com/dkandalov/5979943) - one-liner to show PSI viewer dialog. Normally it's only enabled in plugin projects.
 - [Simplistic "generify return type"](https://gist.github.com/dkandalov/5992191) - attempt to pattern-match PSI tree
 - [No copy-paste](https://gist.github.com/dkandalov/5430282) - disables copy/paste actions
 - [Text munging actions](https://gist.github.com/dkandalov/34daca651fb3fbb9b33f) - simple actions on text (sort, unique, keep/delete lines)
 - [Wrap selection](https://gist.github.com/dkandalov/5129543) - micro-plugin to wrap long lines with separator
 - [Wrap selected text to column width](https://gist.github.com/dkandalov/5557393) - copy of this plugin https://github.com/abrookins/WrapToColumn
 - [Create .jar patch file for current change list](https://gist.github.com/dkandalov/5502872) - that's what it does
 - [Create .jar patch file for specified favorites list](https://gist.github.com/chanshuikay/9850327817fbedceba75) - similar to the above mini-plugin
 - [Remove getters/setters](https://gist.github.com/dkandalov/5476562) - removes all setters or getters in a class
 - [ISO DateTime / Epoch timestamp converter](https://gist.github.com/xhanin/4948901) - converts Epoch time to/from ISO format
 - [Make cursor move in circle](https://gist.github.com/dkandalov/11326385) - definitely not practical but gives an idea about threading
 - [Word Cloud](https://github.com/dkandalov/intellij-wordcloud) - shows world cloud for the selected item (file/package/folder)
 - [Project TreeMap View](https://github.com/dkandalov/project-treemap) - shows project structure (packages/classes) as treemap based on size of classes
 - [Method History](https://github.com/dkandalov/history-slider-plugin) - combines built-in method history based on selection and method history based on method name
 - [Evaluate selection as Groovy](https://gist.github.com/dkandalov/5024580) - that's exactly what it does
 - [Taskbar Icon Changer](https://gist.github.com/markusmo3/ee46e5fe81d4dacea7110134f4ca953f) - Changes the Windows Taskbar icon depending on the project name to provide a better overview when working with multiple projects
 - [Refocus Pinned Find Window](https://gist.github.com/fc1943s/411540e9e29a1296650bcaa8f9a27eec) - Shortcut to refocus the 'Find in Path' dialog with the Pin option enabled after selecting a result entry

## Similar plugins
The idea of running code inside IntelliJ is not original.
There are/were similar plugins:
 - [Flora](http://plugins.intellij.net/plugin?id=17669) - a similar plugin from JetBrains Hackathon
 - [IDE Scripting Console](https://youtrack.jetbrains.com/issue/IDEA-138252) - experimental feature bundled since IntelliJ 14.1
 - [Script Monkey](http://plugins.intellij.net/plugin?pr=idea&pluginId=3674) (out-of-date)
 - [PMIP - Poor Mans IDE Plugin](http://plugins.intellij.net/plugin/?idea&pluginId=4571) (no longer available)
 - [Remote Groovy Console](http://plugins.intellij.net/plugin/?id=5373) (out-of-date)
 - [Groovy Console Plugin](http://plugins.intellij.net/plugin?pr=idea&pluginId=4660) (out-of-date)
 - [HotPlugin](http://plugins.intellij.net/plugin?pr=idea&pluginId=1020) (out-of-date)

## Contributing
Please see [CONTRIBUTING.md](https://github.com/dkandalov/live-plugin/blob/master/CONTRIBUTING.md).