mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-01-05 15:19:50 +01:00
3.x
Committed-by: Eduard Heimbuch<eduard.heimbuch@cloudogu.com> Pushed-by: Rene Pfeuffer<rene.pfeuffer@cloudogu.com> Co-authored-by: René Pfeuffer<rene.pfeuffer@cloudogu.com> Pushed-by: Eduard Heimbuch<eduard.heimbuch@cloudogu.com> Committed-by: René Pfeuffer<rene.pfeuffer@cloudogu.com>
This commit is contained in:
committed by
René Pfeuffer
parent
d760f46d9d
commit
cf4d9cf20f
6
Jenkinsfile
vendored
6
Jenkinsfile
vendored
@@ -8,7 +8,7 @@ pipeline {
|
||||
|
||||
agent {
|
||||
docker {
|
||||
image 'scmmanager/java-build:11.0.15_10-2'
|
||||
image 'scmmanager/java-build:17.0.9_9'
|
||||
args '-v /var/run/docker.sock:/var/run/docker.sock --group-add 998'
|
||||
label 'scmm-core'
|
||||
}
|
||||
@@ -72,8 +72,8 @@ pipeline {
|
||||
// in parallel with check?
|
||||
stage('Integration Tests') {
|
||||
steps {
|
||||
// TODO remove obligatory rerun flag when flappy tests have been fixed
|
||||
gradle '-PrerunIntegrationTests integrationTest'
|
||||
// To rerun integration tests with each build, add '-PrerunIntegrationTests' to the gradle command
|
||||
gradle 'integrationTest'
|
||||
junit allowEmptyResults: true, testResults: 'scm-it/build/test-results/javaIntegrationTests/*.xml,scm-ui/build/reports/e2e/*.xml'
|
||||
archiveArtifacts allowEmptyArchive: true, artifacts: 'scm-ui/e2e-tests/cypress/videos/*.mp4'
|
||||
archiveArtifacts allowEmptyArchive: true, artifacts: 'scm-ui/e2e-tests/cypress/screenshots/**/*.png'
|
||||
|
||||
@@ -45,6 +45,7 @@ class IntegrationTestPlugin implements Plugin<Project> {
|
||||
it.extension = extension
|
||||
it.waitForCompletion = false
|
||||
it.frontend = false
|
||||
it.configFileDirectory = './src/main/resources'
|
||||
dependsOn 'write-server-config', 'prepare-home'
|
||||
}
|
||||
|
||||
|
||||
@@ -39,14 +39,15 @@ class JavaModulePlugin implements Plugin<Project> {
|
||||
|
||||
project.java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(11)
|
||||
languageVersion = JavaLanguageVersion.of(17)
|
||||
}
|
||||
withJavadocJar()
|
||||
//TODO Fix javadoc errors which breaks the build
|
||||
// withJavadocJar()
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
project.tasks.withType(JavaCompile) {
|
||||
options.release = 11
|
||||
options.release = 17
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
@@ -56,7 +57,7 @@ class JavaModulePlugin implements Plugin<Project> {
|
||||
|
||||
project.sonarqube {
|
||||
properties {
|
||||
property "sonar.java.source", "11"
|
||||
property "sonar.java.source", "17"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,10 @@ class RunTask extends DefaultTask {
|
||||
@Option(option = 'debug-port', description = 'Port for debugger')
|
||||
String debugPort = "5005"
|
||||
|
||||
@Input
|
||||
@Option(option = 'configFileDirectory', description = 'Path to config file')
|
||||
String configFileDirectory = ''
|
||||
|
||||
@TaskAction
|
||||
void exec() {
|
||||
List<Closure<Void>> actions = new ArrayList<>()
|
||||
@@ -85,8 +89,9 @@ class RunTask extends DefaultTask {
|
||||
return
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Thread.sleep(500)
|
||||
ex.printStackTrace()
|
||||
}
|
||||
Thread.sleep(500)
|
||||
}
|
||||
throw new GradleException("scm-server not reachable")
|
||||
}
|
||||
@@ -124,6 +129,9 @@ class RunTask extends DefaultTask {
|
||||
args(new File(project.buildDir, 'server/config.json').toString())
|
||||
environment 'NODE_ENV', 'development'
|
||||
classpath project.buildscript.configurations.classpath
|
||||
if (configFileDirectory != '') {
|
||||
classpath configFileDirectory
|
||||
}
|
||||
systemProperties = runProperties
|
||||
if (debugJvm) {
|
||||
debug = true
|
||||
|
||||
@@ -26,16 +26,15 @@ package com.cloudogu.scm
|
||||
|
||||
import com.google.common.base.Strings
|
||||
import groovy.json.JsonSlurper
|
||||
import org.eclipse.jetty.server.Handler
|
||||
import org.eclipse.jetty.server.HttpConfiguration
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory
|
||||
import org.eclipse.jetty.server.Server
|
||||
import org.eclipse.jetty.server.ServerConnector
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle
|
||||
import org.eclipse.jetty.util.component.LifeCycle
|
||||
import org.eclipse.jetty.webapp.WebAppContext
|
||||
import org.eclipse.jetty.server.Handler
|
||||
import org.eclipse.jetty.server.handler.HandlerList
|
||||
import org.eclipse.jetty.server.handler.ShutdownHandler
|
||||
import org.eclipse.jetty.util.component.LifeCycle
|
||||
import org.eclipse.jetty.webapp.WebAppContext
|
||||
|
||||
import java.awt.Desktop
|
||||
|
||||
@@ -51,7 +50,7 @@ class ScmServer {
|
||||
void start() throws Exception {
|
||||
info('start scm-server at port %s', configuration.port)
|
||||
|
||||
System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
|
||||
System.setProperty("jakarta.xml.parsers.DocumentBuilderFactory", "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
|
||||
|
||||
System.setProperty('scm.home', configuration.home)
|
||||
if (configuration.disableCorePlugins) {
|
||||
@@ -59,10 +58,6 @@ class ScmServer {
|
||||
System.setProperty('sonia.scm.boot.disable-core-plugin-extraction', 'true')
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(configuration.loggingConfiguration)) {
|
||||
System.setProperty('logback.configurationFile', configuration.loggingConfiguration)
|
||||
}
|
||||
|
||||
info('set stage %s', configuration.stage)
|
||||
System.setProperty('scm.stage', configuration.stage)
|
||||
|
||||
@@ -80,7 +75,7 @@ class ScmServer {
|
||||
createShutdownHandler()
|
||||
] as Handler[])
|
||||
server.setHandler(handlerList)
|
||||
server.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener() {
|
||||
server.addEventListener(new LifeCycle.Listener() {
|
||||
@Override
|
||||
void lifeCycleStarted(LifeCycle event) {
|
||||
|
||||
|
||||
@@ -70,8 +70,7 @@ abstract class UploadTask extends DefaultTask {
|
||||
}
|
||||
|
||||
private void doUpload() {
|
||||
SslContextFactory.Client sslContextFactory = new SslContextFactory.Client()
|
||||
HttpClient client = new HttpClient(sslContextFactory)
|
||||
HttpClient client = new HttpClient()
|
||||
try {
|
||||
client.start()
|
||||
ContentResponse response = createRequest(client).send()
|
||||
|
||||
@@ -52,6 +52,9 @@ dependencies {
|
||||
// lombok
|
||||
api libraries.lombok
|
||||
|
||||
// jakarta
|
||||
api libraries.jakartaAnnotationApi
|
||||
|
||||
// servlet api
|
||||
api libraries.servletApi
|
||||
|
||||
|
||||
@@ -4,14 +4,139 @@ subtitle: Various configuration options for the SCM-Server
|
||||
displayToc: true
|
||||
---
|
||||
|
||||
## Https
|
||||
SCM-Manager can be configured in several ways. We recommend using `config.yml` to have most of the settings in
|
||||
one place.
|
||||
However, if required, each option in this configuration can also be set via environment variables.
|
||||
See the relevant topics below for more information.
|
||||
|
||||
In order to use https with scm-server, you need a keystore with a certificate and the corresponding secret key.
|
||||
In the following we will use `openssl` to create a self signed certificate for demonstration purposes.
|
||||
## Change log level
|
||||
|
||||
### Create self signed certificate
|
||||
The log level can be configured in the `config.yml`.
|
||||
You may either change the root log level to change the log level globally for all loggers.
|
||||
Also, new specific logger can be added to control logging in a fine-grained style.
|
||||
|
||||
**Warning**: Do not use self signed certificates in production, this is only for demonstration purposes.
|
||||
#### Example
|
||||
|
||||
```yaml
|
||||
log:
|
||||
# General logging level
|
||||
rootLevel: WARN
|
||||
|
||||
# Custom specific loggers
|
||||
# The "name" has to be the path of the classes to be logged with this logger
|
||||
logger:
|
||||
- name: sonia.scm
|
||||
level: DEBUG
|
||||
- name: com.cloudogu.scm
|
||||
level: DEBUG
|
||||
```
|
||||
|
||||
To override this config with environment variables you could set it like:
|
||||
|
||||
`SCM_LOG_ROOT_LEVEL` to one of the log levels, like `DEBUG`
|
||||
`SCM_LOG_LOGGER` with a comma-separated list of your loggers, like `sonia.scm:DEBUG,com.cloudogu.scm:TRACE`
|
||||
|
||||
Supported log levels are: TRACE, DEBUG, INFO, WARN, ERROR
|
||||
|
||||
### Logback
|
||||
|
||||
If you want to configure more advanced loggers which are beyond this simple configuration, you may still use
|
||||
a logback configuration file.
|
||||
You have to enable your logback configuration by setting the file path with the system
|
||||
property `logback.configurationFile`, like `-Dlogback.configurationFile=logging.xml`.
|
||||
If the logback configuration is enabled, the log configuration of the `config.yml` will be ignored.
|
||||
|
||||
#### Example
|
||||
|
||||
```xml
|
||||
|
||||
<configuration>
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>/var/log/scm/scm-manager.log</file>
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
|
||||
<fileNamePattern>/var/log/scm/scm-manager-%i.log</fileNamePattern>
|
||||
<minIndex>1</minIndex>
|
||||
<maxIndex>10</maxIndex>
|
||||
</rollingPolicy>
|
||||
|
||||
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
|
||||
<maxFileSize>10MB</maxFileSize>
|
||||
</triggeringPolicy>
|
||||
|
||||
<append>true</append>
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%-10X{transaction_id}] %-5level %logger - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%-10X{transaction_id}] %-5level %logger - %msg%n</pattern>
|
||||
</encoder>
|
||||
|
||||
</appender>
|
||||
|
||||
<logger name="sonia.scm" level="INFO"/>
|
||||
<logger name="com.cloudogu.scm" level="INFO"/>
|
||||
|
||||
<!-- suppress massive gzip logging -->
|
||||
<logger name="sonia.scm.filter.GZipFilter" level="WARN"/>
|
||||
<logger name="sonia.scm.filter.GZipResponseStream" level="WARN"/>
|
||||
|
||||
<logger name="sonia.scm.util.ServiceUtil" level="WARN"/>
|
||||
|
||||
<!-- event bus -->
|
||||
<logger name="sonia.scm.event.LegmanScmEventBus" level="INFO"/>
|
||||
|
||||
|
||||
<root level="WARN">
|
||||
<appender-ref ref="FILE"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
```
|
||||
|
||||
## Change host and port
|
||||
|
||||
The listener host and port of your SCM-Server can directly be edited in the top level of your `config.yml`.
|
||||
|
||||
#### Example
|
||||
|
||||
```yaml
|
||||
# This is the host adresse, `0.0.0.0` means it listens on every interface
|
||||
addressBinding: 0.0.0.0
|
||||
# This is the exposed port for your application
|
||||
port: 8080
|
||||
```
|
||||
|
||||
To override this config with environment variables you could set it like:
|
||||
|
||||
`SCM_SERVER_PORT` to your port
|
||||
`SCM_SERVER_ADDRESS_BINDING` to the destination ip / hostname
|
||||
|
||||
## Change context path
|
||||
|
||||
SCM-Server context path can be set directly in the top level of your `config.yml`.
|
||||
If you want your server without a context path (use `root`), you can change this option to be `/`.
|
||||
|
||||
#### Example
|
||||
|
||||
```yaml
|
||||
contextPath: /
|
||||
```
|
||||
|
||||
To override this config with environment variables you could set it like:
|
||||
|
||||
`SCM_SERVER_CONTEXT_PATH` to `/myContextPath`
|
||||
|
||||
## SSL
|
||||
|
||||
In order to use https with SCM-Server, you need a keystore with a certificate and the corresponding secret key.
|
||||
In the following we will use openssl to create a self-signed certificate for demonstration purposes.
|
||||
|
||||
**Warning**: Do not use self-signed certificates in production, this is only for demonstration purposes.
|
||||
|
||||
```bash
|
||||
openssl req -new -x509 -newkey rsa:2048 -sha256 -keyout tls.key -out tls.crt
|
||||
@@ -19,32 +144,32 @@ openssl req -new -x509 -newkey rsa:2048 -sha256 -keyout tls.key -out tls.crt
|
||||
|
||||
This command will ask a few questions about metadata for generated certificate:
|
||||
|
||||
* PEM pass phrase: This is a password to protect the scret key
|
||||
* Country Name (2 letter code)
|
||||
* State or Province Name (full name)
|
||||
* Locality Name (eg, city)
|
||||
* Organization Name (eg, company)
|
||||
* Organizational Unit Name (eg, section)
|
||||
* Common Name (eg, fully qualified host name)
|
||||
* Email Address
|
||||
- PEM pass phrase: This is a password to protect the scret key
|
||||
- Country Name (2 letter code)
|
||||
- State or Province Name (full name)
|
||||
- Locality Name (eg, city)
|
||||
- Organization Name (eg, company)
|
||||
- Organizational Unit Name (eg, section)
|
||||
- Common Name (eg, fully qualified host name)
|
||||
- Email Address
|
||||
|
||||
Make sure that the common name matches the fqdn, which you are using to access SCM-Manager.
|
||||
|
||||
#### Browsers
|
||||
### Browsers
|
||||
|
||||
In order to use a self signed certificate the certificate must be imported into you browser.
|
||||
In order to use a self-signed certificate the certificate must be imported into you browser.
|
||||
|
||||
#### Configure Git
|
||||
### Configure Git
|
||||
|
||||
To use git with a self signed certificate, we have to add the certificate path to the configuration.
|
||||
To use git with a self-signed certificate, we have to add the certificate path to the configuration.
|
||||
|
||||
```bash
|
||||
git config http.sslCAInfo /complete/path/to/tls.crt
|
||||
```
|
||||
|
||||
#### Configure Mercurial
|
||||
### Configure Mercurial
|
||||
|
||||
To use mercurial with a self signed certificate, we have to add the certificate path to the configuration.
|
||||
To use mercurial with a self-signed certificate, we have to add the certificate path to the configuration.
|
||||
|
||||
```ini
|
||||
[web]
|
||||
@@ -53,131 +178,46 @@ cacerts = /complete/path/to/cert.pem
|
||||
|
||||
### Create keystore
|
||||
|
||||
Create a keystore in pkcs12 format.
|
||||
This command can be used with the self signed certificate from above or with a valid certificate from an authority.
|
||||
Create a keystore in pkcs12 format. This command can be used with the self-signed certificate from above or with a valid
|
||||
certificate from an authority.
|
||||
|
||||
```bash
|
||||
openssl pkcs12 -inkey tls.key -in tls.crt -export -out keystore.pkcs12
|
||||
```
|
||||
|
||||
If your secret key is protected with a pass phrase, you have to enter it first.
|
||||
Than you have to enter an export password to protect your keystore.
|
||||
If your secret key is protected with a passphrase, you must enter this first. You must then enter an export password to
|
||||
protect your keystore.
|
||||
|
||||
### Server configuration
|
||||
|
||||
Add the following snippet at the end of your `server-config.xml`, be sure it is inside the `Configure` tag:
|
||||
Adjust your `config.yml` to apply your prepared keystore with configured certificate.
|
||||
|
||||
```xml
|
||||
<!-- ssl configuration start -->
|
||||
#### Example
|
||||
|
||||
<New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory$Server">
|
||||
<!--
|
||||
path to your keystore, it can be a java keystore or in the pkcs12 format
|
||||
-->
|
||||
<Set name="KeyStorePath">
|
||||
<SystemProperty name="basedir" default="."/>/conf/keystore.pkcs12
|
||||
</Set>
|
||||
<!--
|
||||
use pkcs12 or jks for java keystore
|
||||
-->
|
||||
<Set name="KeyStoreType">PKCS12</Set>
|
||||
<!--
|
||||
the password of you keystore
|
||||
-->
|
||||
<Set name="KeyStorePassword">secret</Set>
|
||||
|
||||
<!--
|
||||
For a more up to date list of ciphers and protocols, have a look at the mozilla ssl configurator:
|
||||
https://ssl-config.mozilla.org/#server=jetty&version=9.4.28&config=intermediate&guideline=5.4
|
||||
-->
|
||||
|
||||
<!-- TLS 1.3 requires Java 11 or higher -->
|
||||
<Set name="IncludeProtocols">
|
||||
<Array type="String">
|
||||
<Item>TLSv1.2</Item>
|
||||
<Item>TLSv1.3</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
|
||||
<Set name="IncludeCipherSuites">
|
||||
<Array type="String">
|
||||
<Item>TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384</Item>
|
||||
<Item>TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384</Item>
|
||||
<Item>TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256</Item>
|
||||
<Item>TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256</Item>
|
||||
<Item>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</Item>
|
||||
<Item>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</Item>
|
||||
<Item>TLS_DHE_RSA_WITH_AES_256_GCM_SHA384</Item>
|
||||
<Item>TLS_DHE_RSA_WITH_AES_128_GCM_SHA256</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
|
||||
<Set name="useCipherSuitesOrder">
|
||||
<Property name="jetty.sslContext.useCipherSuitesOrder" default="false" />
|
||||
</Set>
|
||||
</New>
|
||||
|
||||
<New id="sslHttpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
||||
<Arg>
|
||||
<Ref refid="httpConfig"/>
|
||||
</Arg>
|
||||
<Call name="addCustomizer">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.SecureRequestCustomizer">
|
||||
<Arg name="sniRequired" type="boolean"><Property name="jetty.ssl.sniRequired" default="false"/></Arg>
|
||||
<Arg name="sniHostCheck" type="boolean"><Property name="jetty.ssl.sniHostCheck" default="true"/></Arg>
|
||||
<Arg name="stsMaxAgeSeconds" type="int"><Property name="jetty.ssl.stsMaxAgeSeconds" default="-1"/></Arg>
|
||||
<Arg name="stsIncludeSubdomains" type="boolean"><Property name="jetty.ssl.stsIncludeSubdomains" default="false"/></Arg>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
</New>
|
||||
|
||||
<Call name="addConnector">
|
||||
<Arg>
|
||||
<New id="sslConnector" class="org.eclipse.jetty.server.ServerConnector">
|
||||
<Arg name="server">
|
||||
<Ref refid="ScmServer" />
|
||||
</Arg>
|
||||
<Arg name="factories">
|
||||
<Array type="org.eclipse.jetty.server.ConnectionFactory">
|
||||
<Item>
|
||||
<New class="org.eclipse.jetty.server.SslConnectionFactory">
|
||||
<Arg name="next">http/1.1</Arg>
|
||||
<Arg name="sslContextFactory">
|
||||
<Ref refid="sslContextFactory"/>
|
||||
</Arg>
|
||||
</New>
|
||||
</Item>
|
||||
<Item>
|
||||
<New class="org.eclipse.jetty.server.HttpConnectionFactory">
|
||||
<Arg name="config">
|
||||
<Ref refid="sslHttpConfig" />
|
||||
</Arg>
|
||||
</New>
|
||||
</Item>
|
||||
</Array>
|
||||
</Arg>
|
||||
<!--
|
||||
Address to listen 0.0.0.0 means on every interface
|
||||
-->
|
||||
<Set name="host">
|
||||
<SystemProperty name="jetty.host" default="0.0.0.0" />
|
||||
</Set>
|
||||
<!--
|
||||
Port for the https connector
|
||||
-->
|
||||
<Set name="port">
|
||||
<Property name="jetty.ssl.port" default="8443" />
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
<!-- ssl configuration end -->
|
||||
```yaml
|
||||
https:
|
||||
# If the key store path is not set, the https config will be ignored entirely.
|
||||
# This must be set to your created keystore from above.
|
||||
keyStorePath: /conf/keystore.pkcs12
|
||||
# The password of your keystore.
|
||||
keyStorePassword: secret
|
||||
# The type of your keystore. Use pkcs12 or jks for java keystore.
|
||||
keyStoreType: PKCS12
|
||||
# The port of your https connector
|
||||
sslPort: 443
|
||||
# Automatically redirects incoming http requests to this https connector
|
||||
redirectHttpToHttps: true
|
||||
```
|
||||
|
||||
The snipped above assumes your keystore is in the pkcs12 format and is stored at `conf/keystore.pkcs12` with the password `secret`.
|
||||
You have to tweek this settings to match your setup.
|
||||
After modifying your `server-config.xml`, you have to **restart** your SCM-Manager instance.
|
||||
Now SCM-Manager should open a second port with **https** (in the example above **8443**).
|
||||
## Change directories
|
||||
|
||||
The default directories are platform-specific and therefore could be different if you try scm-server on different
|
||||
operation systems. Paths starting with `/` are absolute to your file system. If you use relative paths without a
|
||||
starting `/`, your configured path will be located under the base directory of your scm-server.
|
||||
|
||||
#### Example
|
||||
|
||||
```yaml
|
||||
tempDir: /tmp
|
||||
homeDir: scm-home
|
||||
```
|
||||
|
||||
@@ -15,7 +15,7 @@ Using this has the following implications:
|
||||
- The generated code is not explicit (the lombok plugin generates bytecode)
|
||||
- Especially for `hashCode` and `equals` a lot of code with a high complexity is generated.
|
||||
This has implications for test coverage. Even though lombok supports the generation of `Generated`
|
||||
annotations (own or javax), this has no effect in Sonar.
|
||||
annotations (own or jakarta), this has no effect in Sonar.
|
||||
|
||||
First, this will be used for data transfer objects (DTO) in the REST endpoints. To avoid the mentioned
|
||||
complexity of `hashCode` and `equals`, these should not be generated.
|
||||
@@ -30,7 +30,11 @@ The following lombok annotations will be used for DTOs:
|
||||
|
||||
### /repo/ & /repos/ as URI prefixes
|
||||
|
||||
The URI-format for accessing a repository, be it with a browser, or cloning/pulling via git/hg/svn, is defined to be `/repo/:namespace/:name`. The decision was made to allow users to choose namespaces as they please. If there would not be a prefix, some namespaces (e.g. `user`, `users`) would have to be reserved, since the names are already in use by SCM Manager itself. The `/repos` URI linked to a list of repositories, as well as operations such as creating a repositoriy (`/repos/create`).
|
||||
The URI-format for accessing a repository, be it with a browser, or cloning/pulling via git/hg/svn, is defined to
|
||||
be `/repo/:namespace/:name`. The decision was made to allow users to choose namespaces as they please. If there would
|
||||
not be a prefix, some namespaces (e.g. `user`, `users`) would have to be reserved, since the names are already in use by
|
||||
SCM Manager itself. The `/repos` URI linked to a list of repositories, as well as operations such as creating a
|
||||
repositoriy (`/repos/create`).
|
||||
|
||||
### Error handling
|
||||
|
||||
@@ -57,9 +61,15 @@ For simple objects like users and groups we don't think that we will need more e
|
||||
|
||||
### Logging
|
||||
|
||||
Logging can be cucial when it comes to identify bugs in test or production environments. At implementation time one cannot foresee all possible error cases and therefore cannot determine with full certanty what informations will be needed and what can be neglected. Logging only crucial errors leaves the developer with no idea what events might have lead to the error. On the other hand logging too much will overburden the log, making it harder to handle and maybe hiding interesting steps.
|
||||
Logging can be cucial when it comes to identify bugs in test or production environments. At implementation time one
|
||||
cannot foresee all possible error cases and therefore cannot determine with full certanty what informations will be
|
||||
needed and what can be neglected. Logging only crucial errors leaves the developer with no idea what events might have
|
||||
lead to the error. On the other hand logging too much will overburden the log, making it harder to handle and maybe
|
||||
hiding interesting steps.
|
||||
|
||||
Therefore it is best practice to be able to select the detail level of informations to log (called the "log level"). To support this feature SCM-Manager uses [slf4j](https://www.slf4j.org/). Using this library one can log informations with the following log levels:
|
||||
Therefore it is best practice to be able to select the detail level of informations to log (called the "log level"). To
|
||||
support this feature SCM-Manager uses [slf4j](https://www.slf4j.org/). Using this library one can log informations with
|
||||
the following log levels:
|
||||
|
||||
* ERROR
|
||||
* WARN
|
||||
@@ -67,13 +77,15 @@ Therefore it is best practice to be able to select the detail level of informati
|
||||
* DEBUG
|
||||
* TRACE
|
||||
|
||||
As a default the log level for SCM-Manager is INFO, so that by default all logs with the levels ERROR, WARN and INFO are stored. Finer levels can be enabled manually.
|
||||
As a default the log level for SCM-Manager is INFO, so that by default all logs with the levels ERROR, WARN and INFO are
|
||||
stored. Finer levels can be enabled manually.
|
||||
|
||||
### Log levels to use
|
||||
|
||||
We have agreed to apply to the following guidelines regarding log levels:
|
||||
|
||||
- ERROR should be used for fatal errors that could not be handled by the program and therefore leads to failures for the user, for example
|
||||
- ERROR should be used for fatal errors that could not be handled by the program and therefore leads to failures for the
|
||||
user, for example
|
||||
- IO errors reading a database file
|
||||
- IO errors accessing repositories
|
||||
- WARN should be used for errors that could be handled somewhat graceful, but that should be inspected, for example
|
||||
|
||||
@@ -8,7 +8,11 @@ As a highly extensible product, SCM-Manager offers at least three ways to intera
|
||||
- the REST API, and
|
||||
- the Java API
|
||||
|
||||
Having these three layers, the error handling should be consistent among these. That is, as a developer I would not like to have custom made error codes in the REST layer that I cannot find in the Java API. Furthermore it is essential to get precise error messages with hints how to find a way out (if possible), not only for a programmer making interactive calls, but also for other programs. Last but not least it should be easy for plugin developers to adapt the error handling.
|
||||
Having these three layers, the error handling should be consistent among these. That is, as a developer I would not like
|
||||
to have custom made error codes in the REST layer that I cannot find in the Java API. Furthermore it is essential to get
|
||||
precise error messages with hints how to find a way out (if possible), not only for a programmer making interactive
|
||||
calls, but also for other programs. Last but not least it should be easy for plugin developers to adapt the error
|
||||
handling.
|
||||
|
||||
On the GUI layer, these information have to be translated into messages that can be easily handled.
|
||||
|
||||
@@ -18,21 +22,21 @@ Here are some example error cases:
|
||||
|
||||
*Possible errors:*
|
||||
|
||||
- The repository is missing
|
||||
- There is no such branch
|
||||
- The user is not authorized to read the metadata
|
||||
- The repository is corrupt on file system level
|
||||
- The repository is missing
|
||||
- There is no such branch
|
||||
- The user is not authorized to read the metadata
|
||||
- The repository is corrupt on file system level
|
||||
|
||||
---
|
||||
|
||||
*Use case:* Create a new user
|
||||
*Use case:* Create a new user
|
||||
|
||||
*Possible errors:*
|
||||
*Possible errors:*
|
||||
|
||||
- Invalid characters in name
|
||||
- Missing mandatory property
|
||||
- Conflict with an existing user
|
||||
- Insufficient priviliges
|
||||
- Invalid characters in name
|
||||
- Missing mandatory property
|
||||
- Conflict with an existing user
|
||||
- Insufficient priviliges
|
||||
|
||||
---
|
||||
|
||||
@@ -40,18 +44,24 @@ Here are some example error cases:
|
||||
|
||||
*Possible errors:*
|
||||
|
||||
- The repository does not exist
|
||||
- The repository was modified concurrently
|
||||
- Invalid e-mail address
|
||||
- The repository does not exist
|
||||
- The repository was modified concurrently
|
||||
- Invalid e-mail address
|
||||
|
||||
## Java API
|
||||
|
||||
In SCM-Manager we make heavy use of Java `Exception`s, not only for technical exceptions in the program flow like reading corrupt file systems, but also for "user errors" like illegal values or requests for missing data.
|
||||
In SCM-Manager we make heavy use of Java `Exception`s, not only for technical exceptions in the program flow like
|
||||
reading corrupt file systems, but also for "user errors" like illegal values or requests for missing data.
|
||||
|
||||
These exceptions are handled by JEE [`ExceptionMapper`](https://docs.oracle.com/javaee/7/api/javax/ws/rs/ext/ExceptionMapper.html) s. Doing so, it is possible to concentrate on implementing the "happy path" without the need to explicitly handle error cases everywhere (for example you do not have to check whether got `null` as a result). Nonetheless we still had to decide whether to use checked or unchecked exceptions. We have chosen to use unchecked exceptions due to the following reasons:
|
||||
These exceptions are handled by
|
||||
JEE [`ExceptionMapper`](https://docs.oracle.com/javaee/7/api/jakarta/ws/rs/ext/ExceptionMapper.html) s. Doing so, it is
|
||||
possible to concentrate on implementing the "happy path" without the need to explicitly handle error cases everywhere (
|
||||
for example you do not have to check whether got `null` as a result). Nonetheless we still had to decide whether to use
|
||||
checked or unchecked exceptions. We have chosen to use unchecked exceptions due to the following reasons:
|
||||
|
||||
- Checked exceptions would have had to be declared everywhere.
|
||||
- A checked exception can somehow trigger a "I have to handle this though I don't know how" feeling that would be wrong, because we do have mappers for these exceptions.
|
||||
- Checked exceptions would have had to be declared everywhere.
|
||||
- A checked exception can somehow trigger a "I have to handle this though I don't know how" feeling that would be wrong,
|
||||
because we do have mappers for these exceptions.
|
||||
|
||||
Therefore handling such an exception has to be a concious decision.
|
||||
|
||||
@@ -65,58 +75,84 @@ A `NotFoundException` is thrown, whenever "things" where requested but were not
|
||||
|
||||
#### `AlreadyExistsException`
|
||||
|
||||
This exception is thrown whenever an entity cannot be created, because another entity with the same key identifyer exists.
|
||||
This exception is thrown whenever an entity cannot be created, because another entity with the same key identifyer
|
||||
exists.
|
||||
|
||||
#### `ConcurrentModificationException`
|
||||
|
||||
When you try to modify an entity based on an outdated version, this exception is thrown. For entities like user, group or repository the "last modified" timestamp of `ModelObject` is used to check this.
|
||||
When you try to modify an entity based on an outdated version, this exception is thrown. For entities like user, group
|
||||
or repository the "last modified" timestamp of `ModelObject` is used to check this.
|
||||
|
||||
#### `NativeRepositoryAccessException`
|
||||
|
||||
Failures while accessing native repositories (most of the time) result in `java.io.IOException`s. To distinguish these exceptions from other I/O errors like network exceptions and to make them unchecked, we wrap them in `NativeRepositoryAccessException`.
|
||||
Failures while accessing native repositories (most of the time) result in `java.io.IOException`s. To distinguish these
|
||||
exceptions from other I/O errors like network exceptions and to make them unchecked, we wrap them
|
||||
in `NativeRepositoryAccessException`.
|
||||
|
||||
#### `ResteasyViolationException`
|
||||
|
||||
Input validation is handled using [RESTEasy's validation support](https://docs.jboss.org/resteasy/docs/3.0.0.Final/userguide/html/Validation.html). Constraint violations result in `ResteasyViolationException`s.
|
||||
Input validation is handled
|
||||
using [RESTEasy's validation support](https://docs.jboss.org/resteasy/docs/3.0.0.Final/userguide/html/Validation.html).
|
||||
Constraint violations result in `ResteasyViolationException`s.
|
||||
|
||||
#### All other runtime exceptions
|
||||
|
||||
All other `java.lang.RuntimeException`s can be treated as unexpected errors, that either hint to severe problems (eg. disk access failures) or implementation errors. It is unlikely that these can be handled by the program gracefully. They will be caught by a generic exception handler which will wrap them in a new exception providing further SCM specific information.
|
||||
All other `java.lang.RuntimeException`s can be treated as unexpected errors, that either hint to severe problems (eg.
|
||||
disk access failures) or implementation errors. It is unlikely that these can be handled by the program gracefully. They
|
||||
will be caught by a generic exception handler which will wrap them in a new exception providing further SCM specific
|
||||
information.
|
||||
|
||||
#### Checked exceptions
|
||||
|
||||
Above we mentioned, that we want to use unchecked exceptions only. Therefore we have to wrap checked exceptions for example created by libraries or frarmeworks to make them unchecked. Normally it is sufficiant to wrap them in a RuntimeException using a proper message, except you plan to handle them somewhere else than at resource level (then it would be appropriate to introduce a new exception class extending `RuntimeException`).
|
||||
Above we mentioned, that we want to use unchecked exceptions only. Therefore we have to wrap checked exceptions for
|
||||
example created by libraries or frarmeworks to make them unchecked. Normally it is sufficiant to wrap them in a
|
||||
RuntimeException using a proper message, except you plan to handle them somewhere else than at resource level (then it
|
||||
would be appropriate to introduce a new exception class extending `RuntimeException`).
|
||||
|
||||
### Enrichment of exceptions
|
||||
|
||||
#### Context
|
||||
|
||||
Most of these exceptions must provide information about _what_ could not have been found, updated, whatsoever. This is necessary, because otherwise it may not be clear at what step of a potentionally complex process this exception occured. Though this sounds easy, it has some complexity because for example the access of a file in a repository can fail on many levels (the file is missing in the given revision, the revision is missing, or the repository itself is missing). In these cases you have to know the complete access path (what file in what revision of what changeset in what repository).
|
||||
Most of these exceptions must provide information about _what_ could not have been found, updated, whatsoever. This is
|
||||
necessary, because otherwise it may not be clear at what step of a potentionally complex process this exception occured.
|
||||
Though this sounds easy, it has some complexity because for example the access of a file in a repository can fail on
|
||||
many levels (the file is missing in the given revision, the revision is missing, or the repository itself is missing).
|
||||
In these cases you have to know the complete access path (what file in what revision of what changeset in what
|
||||
repository).
|
||||
|
||||
To ensure that this is done in a reproducable and consistent way, SCM-Manager will provide utility functions to creaate such exceptions.
|
||||
To ensure that this is done in a reproducable and consistent way, SCM-Manager will provide utility functions to creaate
|
||||
such exceptions.
|
||||
|
||||
#### Transaction IDs
|
||||
|
||||
To be able to retrace the cause for exceptions, it is helpful to link log messages to these exceptions. To do so, SCM-Manager introduces transaction ids that are generated for single requests or other related actions like the processing of hooks or cron jobs. This transaction id will be part of every log message and every API response.
|
||||
To be able to retrace the cause for exceptions, it is helpful to link log messages to these exceptions. To do so,
|
||||
SCM-Manager introduces transaction ids that are generated for single requests or other related actions like the
|
||||
processing of hooks or cron jobs. This transaction id will be part of every log message and every API response.
|
||||
|
||||
For http requests, this can be done using MDC filter.
|
||||
|
||||
#### Identification of exceptions
|
||||
|
||||
To be able to identify different types of exceptions even outside of the java ecosystem, each SCM-Manager exception class will get a unique type id that will be created using the `DefaultKeyGenerator` during development. We chose to generate these ids and not "human readable" ones to prevent collisions between plugins.
|
||||
To be able to identify different types of exceptions even outside of the java ecosystem, each SCM-Manager exception
|
||||
class will get a unique type id that will be created using the `DefaultKeyGenerator` during development. We chose to
|
||||
generate these ids and not "human readable" ones to prevent collisions between plugins.
|
||||
|
||||
### Logging of exceptions
|
||||
|
||||
To be able to retrace errors a proper logging is indispensible. So we decided to use the following rules for logging exceptions:
|
||||
To be able to retrace errors a proper logging is indispensible. So we decided to use the following rules for logging
|
||||
exceptions:
|
||||
|
||||
- Native SCM manager exceptions will be logged at log level `INFO` with their message, only. The complete stacktrace will be logged at log level `DEBUG`.
|
||||
- All other exceptions will be logged on level `WARN` with the complete stacktrace, because they indicate something going wrong on a fundamental level.
|
||||
- Native SCM manager exceptions will be logged at log level `INFO` with their message, only. The complete stacktrace
|
||||
will be logged at log level `DEBUG`.
|
||||
- All other exceptions will be logged on level `WARN` with the complete stacktrace, because they indicate something
|
||||
going wrong on a fundamental level.
|
||||
|
||||
## REST API
|
||||
|
||||
### Status codes
|
||||
|
||||
SCM-Manager uses [http status codes](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) to identify types of errors (and successes, that is) and doing so provides a first hint, what may have gone wrong:
|
||||
SCM-Manager uses [http status codes](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) to identify types of
|
||||
errors (and successes, that is) and doing so provides a first hint, what may have gone wrong:
|
||||
|
||||
| Status code | Principal error cause |
|
||||
|-------------|-----------------------|
|
||||
@@ -127,12 +163,14 @@ SCM-Manager uses [http status codes](https://en.wikipedia.org/wiki/List_of_HTTP_
|
||||
| 401 | Missing authentication (not logged in?) |
|
||||
| 403 | Missing authorization |
|
||||
| 404 | The thing you are looking does not exist |
|
||||
| 409 | Your update was rejected because you relate to an outdated version (maybe this item was changed in the meantime) _or_ the item could not be created because the key already exists |
|
||||
| 409 | Your update was rejected because you relate to an outdated version (maybe this item was changed in the meantime) _
|
||||
or_ the item could not be created because the key already exists |
|
||||
| 500 | The "You are not to blame" error; something unexpected went wrong while processing the request |
|
||||
|
||||
### Further information
|
||||
|
||||
Whenever possible, an error response contains useful details about the error in a simple json format. These information are _not_ translated, so this is the responsibility of the frontend.
|
||||
Whenever possible, an error response contains useful details about the error in a simple json format. These information
|
||||
are _not_ translated, so this is the responsibility of the frontend.
|
||||
|
||||
| key | content | availability |
|
||||
|-----|---------|--------------|
|
||||
@@ -144,7 +182,8 @@ Whenever possible, an error response contains useful details about the error in
|
||||
|
||||
Error objects will contain no stack traces.
|
||||
|
||||
For SCM exceptions, the message will be created from the message of the java exception. For other exceptions this will be a generic message in most cases.
|
||||
For SCM exceptions, the message will be created from the message of the java exception. For other exceptions this will
|
||||
be a generic message in most cases.
|
||||
|
||||
Here is an example, how a concrete exception may look like in a json response:
|
||||
|
||||
@@ -153,10 +192,19 @@ Here is an example, how a concrete exception may look like in a json response:
|
||||
"transactionId": "7D82atGf3",
|
||||
"errorCode": "H823fFAt",
|
||||
"context": [
|
||||
{"type": "repository", "id": "scmmanager/test"},
|
||||
{"type": "branch", "id": "master"},
|
||||
{"type": "file", "id": ".gitignore"}
|
||||
],
|
||||
{
|
||||
"type": "repository",
|
||||
"id": "scmmanager/test"
|
||||
},
|
||||
{
|
||||
"type": "branch",
|
||||
"id": "master"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"id": ".gitignore"
|
||||
}
|
||||
],
|
||||
"message": "file not found",
|
||||
"url": "https://www.scm-manager.org/errors/H823fFAt"
|
||||
}
|
||||
@@ -164,27 +212,38 @@ Here is an example, how a concrete exception may look like in a json response:
|
||||
|
||||
### Missing resources (404)
|
||||
|
||||
The http status code 404 is a special case, because it is a fundamental status code that can be created on a lot of events:
|
||||
The http status code 404 is a special case, because it is a fundamental status code that can be created on a lot of
|
||||
events:
|
||||
|
||||
- Your proxy has a misconfiguration and you are talking with a static website instead of SCM-Manager
|
||||
- You are using a path without a valid endpoint in SCM-Manager
|
||||
- You are requesting a entity that does not exists
|
||||
|
||||
Some say, that you should not try to interpret the body of a 404 response, because the origin of the response cannot be taken for granted. Nonetheless we decided to use this http status code to indicate requests for missing resources, because in our view this is what most people would expect.
|
||||
Some say, that you should not try to interpret the body of a 404 response, because the origin of the response cannot be
|
||||
taken for granted. Nonetheless we decided to use this http status code to indicate requests for missing resources,
|
||||
because in our view this is what most people would expect.
|
||||
|
||||
### Internal errors (500)
|
||||
|
||||
Internal errors boil down to the following message: An error occured, that could not be handled in a reasonable way by the program. In these cases often only an administrator can help. Examples are out-of-memory errors, failing disk I/O, timeouts accessing other services, or (to be honest) simple programming errors that have to be fixed in further releases. To be able to trace these errors in the logs one can use the transaction ids.
|
||||
Internal errors boil down to the following message: An error occured, that could not be handled in a reasonable way by
|
||||
the program. In these cases often only an administrator can help. Examples are out-of-memory errors, failing disk I/O,
|
||||
timeouts accessing other services, or (to be honest) simple programming errors that have to be fixed in further
|
||||
releases. To be able to trace these errors in the logs one can use the transaction ids.
|
||||
|
||||
## GUI
|
||||
|
||||
As an end user of the SCM-Manager I would not like to see confusing internals, but rather have a meaningful message in my language of choice. Therefore it is necessary to identify error types on a fine level. This can be done using the errorCode provided in each error object.
|
||||
As an end user of the SCM-Manager I would not like to see confusing internals, but rather have a meaningful message in
|
||||
my language of choice. Therefore it is necessary to identify error types on a fine level. This can be done using the
|
||||
errorCode provided in each error object.
|
||||
|
||||
Basically we have to differentiate between errors the user can handle ("user errors") and technical exceptions. For user errors a meaningful message can be generated giving hints to what the user has done "wrong". All other exceptions can be handled by displaying a "sorry, this did not work as expected" message with the transaction id.
|
||||
Basically we have to differentiate between errors the user can handle ("user errors") and technical exceptions. For user
|
||||
errors a meaningful message can be generated giving hints to what the user has done "wrong". All other exceptions can be
|
||||
handled by displaying a "sorry, this did not work as expected" message with the transaction id.
|
||||
|
||||
## Resources / Best Practices
|
||||
|
||||
While creating this concepts we tried to adhere to best practices considering APIs of Twitter, Facebook, Bing, Spotify and others, as summarized in the following articles:
|
||||
While creating this concepts we tried to adhere to best practices considering APIs of Twitter, Facebook, Bing, Spotify
|
||||
and others, as summarized in the following articles:
|
||||
|
||||
* [RESTful API Design: What About Errors? (Apigee)](https://apigee.com/about/blog/technology/restful-api-design-what-about-errors)
|
||||
* [Best Practices for API Error Handling (Nordic APIS)](https://nordicapis.com/best-practices-api-error-handling/)
|
||||
|
||||
@@ -12,15 +12,15 @@ title: Intellij IDEA Configuration
|
||||
### Settings
|
||||
|
||||
* Build, Execution, Deployment / Compiler
|
||||
* Add runtime assertions for non-null-annotated methods and parameters (must be checked)
|
||||
* Configure annotation ... (of "Add runtime assertions...")
|
||||
* Nullable annotations: select (✓) `javax.annotation.Nullable`
|
||||
* NotNull annotations: select (✓) `javax.annotation.Nonnull` and check Instrument
|
||||
* Add runtime assertions for non-null-annotated methods and parameters (must be checked)
|
||||
* Configure annotation ... (of "Add runtime assertions...")
|
||||
* Nullable annotations: select (✓) `jakarta.annotation.Nullable`
|
||||
* NotNull annotations: select (✓) `jakarta.annotation.Nonnull` and check Instrument
|
||||
|
||||
* Editor / Code Style / Java
|
||||
* Tab Imports
|
||||
* Class count to use import with '*': <MAX_INT>
|
||||
* Names count to use static import with '*': <MAX_INT>
|
||||
* Tab Imports
|
||||
* Class count to use import with '*': <MAX_INT>
|
||||
* Names count to use static import with '*': <MAX_INT>
|
||||
|
||||
## Frontend
|
||||
|
||||
@@ -32,22 +32,22 @@ title: Intellij IDEA Configuration
|
||||
### Settings
|
||||
|
||||
* Languages & Frameworks / Node.js and NPM
|
||||
* Package Manager: yarn
|
||||
* Package Manager: yarn
|
||||
|
||||
* Languages & Frameworks / Javascript / Code Quality Tools / ESLint
|
||||
* Enable
|
||||
* ESLint package: .../node_modules/eslint
|
||||
* -OR- Automatic ESLint configuration
|
||||
* Enable
|
||||
* ESLint package: .../node_modules/eslint
|
||||
* -OR- Automatic ESLint configuration
|
||||
|
||||
* Languages & Frameworks / Javascript / Prettier
|
||||
* Prettier package: .../node_modules/prettier
|
||||
* Prettier package: .../node_modules/prettier
|
||||
|
||||
* Tools / File Watchers
|
||||
* Add Prettier
|
||||
* Deselect: Track only root files
|
||||
* Scope: Current File
|
||||
* Program: $ProjectFileDir$/node_modules/.bin/prettier
|
||||
* Working Directory: $ProjectFileDir$
|
||||
* Add Prettier
|
||||
* Deselect: Track only root files
|
||||
* Scope: Current File
|
||||
* Program: $ProjectFileDir$/node_modules/.bin/prettier
|
||||
* Working Directory: $ProjectFileDir$
|
||||
|
||||
## Both
|
||||
|
||||
@@ -58,16 +58,16 @@ title: Intellij IDEA Configuration
|
||||
### Settings
|
||||
|
||||
* Editor / Copyright / Copyright Profiles
|
||||
* Add Profile
|
||||
* Name: SCM-MIT
|
||||
* Copyright text: *see LICENSE.txt in the main directory*
|
||||
* Regex: MIT License
|
||||
|
||||
* Add Profile
|
||||
* Name: SCM-MIT
|
||||
* Copyright text: *see LICENSE.txt in the main directory*
|
||||
* Regex: MIT License
|
||||
|
||||
* Editor / Copyright
|
||||
* Default project copyright: SCM-MIT
|
||||
* Default project copyright: SCM-MIT
|
||||
|
||||
* Editor / Copyright / Formatting / XML
|
||||
* Use custom formatting options
|
||||
* Use block comment, check prefix each line
|
||||
* Select: Separator before, Length: 0
|
||||
* Separator: *space*
|
||||
* Use custom formatting options
|
||||
* Use block comment, check prefix each line
|
||||
* Select: Separator before, Length: 0
|
||||
* Separator: *space*
|
||||
|
||||
@@ -11,9 +11,11 @@ To migrate an existing SCM-Manager 1.x Plugin, you have to do the following step
|
||||
* create a separate branch for the new version
|
||||
* It might be helpful to start and review the old version of the plugin via `mvn scmp:run` for later reference.
|
||||
* Import .gitignore & .editorconfig from SCMM
|
||||
* You might run the build once and review and fix SCMMv1 deprecation warnings. SCMMv2 gets rids of all deprecated classes.
|
||||
* update the version of the parent artifact (sonia.scm.plugins:scm-plugins) to the minimum version of SCM-Manager 2 you are planning for your plugin
|
||||
* change the packaging type of your plugin to smp
|
||||
* You might run the build once and review and fix SCMMv1 deprecation warnings. SCMMv2 gets rids of all deprecated
|
||||
classes.
|
||||
* update the version of the parent artifact (sonia.scm.plugins:scm-plugins) to the minimum version of SCM-Manager 2 you
|
||||
are planning for your plugin
|
||||
* change the packaging type of your plugin to smp
|
||||
* remove the sonia.scm.maven:scm-maven-plugin from the pom
|
||||
* remove servlet-api from the list of dependencies (not always the case)
|
||||
|
||||
@@ -41,7 +43,7 @@ diff -r a988f4cfb7ab pom.xml
|
||||
<dependencies>
|
||||
|
||||
- <dependency>
|
||||
- <groupId>javax.servlet</groupId>
|
||||
- <groupId>jakarta.servlet</groupId>
|
||||
- <artifactId>servlet-api</artifactId>
|
||||
- <version>${servlet.version}</version>
|
||||
- <scope>provided</scope>
|
||||
@@ -52,7 +54,7 @@ diff -r a988f4cfb7ab pom.xml
|
||||
<artifactId>simple-java-mail</artifactId>
|
||||
<version>2.4</version>
|
||||
@@ -52,18 +46,6 @@
|
||||
<javaxmail.version>1.4.7</javaxmail.version>
|
||||
<jakartamail.version>1.4.7</jakartamail.version>
|
||||
</properties>
|
||||
|
||||
- <build>
|
||||
@@ -74,7 +76,8 @@ diff -r a988f4cfb7ab pom.xml
|
||||
|
||||
### Plugin Descriptor (src/main/resources/META-INF/scm/plugin.xml)
|
||||
|
||||
* add the following dtd to the top of the plugin.xml: `<!DOCTYPE plugin SYSTEM "https://download.scm-manager.org/dtd/plugin/2.0.0-01.dtd">`
|
||||
* add the following dtd to the top of the
|
||||
plugin.xml: `<!DOCTYPE plugin SYSTEM "https://download.scm-manager.org/dtd/plugin/2.0.0-01.dtd">`
|
||||
* add an scm-version element with the value 2 to the plugin.xml
|
||||
* remove resources and packages from plugin.xml
|
||||
|
||||
@@ -120,8 +123,9 @@ diff -r a988f4cfb7ab src/main/resources/META-INF/scm/plugin.xml
|
||||
|
||||
* try to compile the sources: `mvn compile`
|
||||
* fix problems (TODO more help here)
|
||||
* Remove XML accept headers from REST Resource classes -> SCMMv2 supports JSON only
|
||||
* Migrate REST Resources (e.g. `v2`, add to Index Resource, Update Links) - See core plugins Git, Hg, Svn, e.g. [`GitConfigResource`](https://github.com/scm-manager/scm-manager/blob/develop/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigResource.java)
|
||||
* Remove XML accept headers from REST Resource classes -> SCMMv2 supports JSON only
|
||||
* Migrate REST Resources (e.g. `v2`, add to Index Resource, Update Links) - See core plugins Git, Hg, Svn,
|
||||
e.g. [`GitConfigResource`](https://github.com/scm-manager/scm-manager/blob/develop/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigResource.java)
|
||||
|
||||
### UI (src/main/js, src/main/webapp)
|
||||
|
||||
@@ -131,15 +135,15 @@ diff -r a988f4cfb7ab src/main/resources/META-INF/scm/plugin.xml
|
||||
```json
|
||||
{
|
||||
"name": "@scm-manager/name-of-plugin",
|
||||
"license" : "MIT",
|
||||
"license": "MIT",
|
||||
"main": "src/main/js/index.tsx",
|
||||
"scripts": {
|
||||
"build" : "ui-scripts plugin",
|
||||
"watch" : "ui-scripts plugin-watch",
|
||||
"postinstall" : "ui-plugins postinstall"
|
||||
"build": "ui-scripts plugin",
|
||||
"watch": "ui-scripts plugin-watch",
|
||||
"postinstall": "ui-plugins postinstall"
|
||||
},
|
||||
"dependencies": {
|
||||
"@scm-manager/ui-plugins" : "2.0.0"
|
||||
"@scm-manager/ui-plugins": "2.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -162,12 +166,18 @@ diff -r a988f4cfb7ab src/main/resources/META-INF/scm/plugin.xml
|
||||
|
||||
Some more hints:
|
||||
|
||||
* For Configuration UIs use [`ConfigurationBinder`](https://github.com/scm-manager/scm-manager/blob/develop/scm-ui/ui-components/src/config/ConfigurationBinder.tsx) - See core plugins Git, Hg, Svn, e.g. [scm-git-plugin/index.ts](https://github.com/scm-manager/scm-manager/blob/develop/scm-plugins/scm-git-plugin/src/main/js/index.ts).
|
||||
* For Configuration UIs
|
||||
use [`ConfigurationBinder`](https://github.com/scm-manager/scm-manager/blob/develop/scm-ui/ui-components/src/config/ConfigurationBinder.tsx)
|
||||
- See core plugins Git, Hg, Svn,
|
||||
e.g. [scm-git-plugin/index.ts](https://github.com/scm-manager/scm-manager/blob/develop/scm-plugins/scm-git-plugin/src/main/js/index.ts)
|
||||
.
|
||||
Note that `readOnly` property checks if update link is returned by REST resource
|
||||
* Don't forget [i18n for Plugins](../i18n-for-plugins)
|
||||
* Don't forget [i18n for Plugins](../i18n-for-plugins)
|
||||
|
||||
# Further reading
|
||||
|
||||
* [UI Extensions](../../ui-extensions) - Extend the SCM-Manager UI
|
||||
* [scm-manager/ui-components](https://github.com/scm-manager/scm-manager/tree/develop/scm-ui/ui-components) - Reusable UI components within SCM-Manager
|
||||
* [smp-maven-plugin](https://github.com/scm-manager/smp-maven-plugin) - Plugin that facilitates efficient plugin development for SCMM
|
||||
* [scm-manager/ui-components](https://github.com/scm-manager/scm-manager/tree/develop/scm-ui/ui-components) - Reusable
|
||||
UI components within SCM-Manager
|
||||
* [smp-maven-plugin](https://github.com/scm-manager/smp-maven-plugin) - Plugin that facilitates efficient plugin
|
||||
development for SCMM
|
||||
|
||||
@@ -22,5 +22,5 @@
|
||||
# SOFTWARE.
|
||||
#
|
||||
group = sonia.scm
|
||||
version = 2.48.2-SNAPSHOT
|
||||
version = 3.0.0-SNAPSHOT
|
||||
org.gradle.jvmargs=-Xmx1024M
|
||||
|
||||
@@ -1,36 +1,39 @@
|
||||
ext {
|
||||
slf4jVersion = '1.7.36'
|
||||
guiceVersion = '5.0.1'
|
||||
resteasyVersion = '4.7.9.Final'
|
||||
guiceVersion = '7.0.0'
|
||||
resteasyVersion = '6.2.5.Final'
|
||||
|
||||
jacksonVersion = '2.13.4'
|
||||
jacksonVersion = '2.15.2'
|
||||
|
||||
legmanVersion = '2.0.1'
|
||||
|
||||
mapstructVersion = '1.3.1.Final'
|
||||
jaxbVersion = '2.3.3'
|
||||
jaxbVersion = '4.0.1'
|
||||
shiroVersion = '1.12.0'
|
||||
sspVersion = '1.3.0'
|
||||
jjwtVersion = '0.11.5'
|
||||
bouncycastleVersion = '1.75'
|
||||
jettyVersion = '9.4.51.v20230217'
|
||||
bouncycastleVersion = '2.73.3'
|
||||
jettyVersion = '11.0.16'
|
||||
luceneVersion = '8.9.0'
|
||||
|
||||
junitJupiterVersion = '5.9.3'
|
||||
hamcrestVersion = '2.1'
|
||||
mockitoVersion = '3.6.28'
|
||||
jerseyClientVersion = '1.19.4'
|
||||
micrometerVersion = '1.6.4'
|
||||
mockitoVersion = '5.5.0'
|
||||
jerseyVersion = '3.1.3'
|
||||
micrometerVersion = '1.11.4'
|
||||
|
||||
nodeVersion = '16.14.2'
|
||||
yarnVersion = '1.22.18'
|
||||
|
||||
libraries = [
|
||||
// lombok
|
||||
lombok: 'org.projectlombok:lombok:1.18.28',
|
||||
lombok: 'org.projectlombok:lombok:1.18.30',
|
||||
|
||||
// jakarta
|
||||
jakartaAnnotationApi: 'jakarta.annotation:jakarta.annotation-api:2.1.1',
|
||||
|
||||
// servlet api
|
||||
servletApi: 'javax.servlet:javax.servlet-api:3.1.0',
|
||||
servletApi: 'jakarta.servlet:jakarta.servlet-api:6.0.0',
|
||||
|
||||
// logging
|
||||
slf4jApi: "org.slf4j:slf4j-api:${slf4jVersion}",
|
||||
@@ -44,12 +47,11 @@ ext {
|
||||
guiceAssistedinject: "com.google.inject.extensions:guice-assistedinject:${guiceVersion}",
|
||||
|
||||
// rest api
|
||||
jaxRs: 'javax.ws.rs:javax.ws.rs-api:2.1.1',
|
||||
jaxRs: 'jakarta.ws.rs:jakarta.ws.rs-api:3.1.0',
|
||||
resteasyCore: "org.jboss.resteasy:resteasy-core:${resteasyVersion}",
|
||||
resteasyJaxbProvider: "org.jboss.resteasy:resteasy-jaxb-provider:${resteasyVersion}",
|
||||
resteasyJackson2Provider: "org.jboss.resteasy:resteasy-jackson2-provider:${resteasyVersion}",
|
||||
resteasyMultiartProvider: "org.jboss.resteasy:resteasy-multipart-provider:${resteasyVersion}",
|
||||
resteasyGuice: "org.jboss.resteasy:resteasy-guice:${resteasyVersion}",
|
||||
resteasyServletInitializer: "org.jboss.resteasy:resteasy-servlet-initializer:${resteasyVersion}",
|
||||
resteasyValidatorProvider: "org.jboss.resteasy:resteasy-validator-provider:${resteasyVersion}",
|
||||
|
||||
@@ -60,17 +62,18 @@ ext {
|
||||
jacksonCore: "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}!!",
|
||||
jacksonAnnotations: "com.fasterxml.jackson.core:jackson-annotations:${jacksonVersion}!!",
|
||||
jacksonDatabind: "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}!!",
|
||||
jacksonJaxbAnnotations: "com.fasterxml.jackson.module:jackson-module-jaxb-annotations:${jacksonVersion}",
|
||||
jacksonJaxbAnnotations: "com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:${jacksonVersion}",
|
||||
jacksonJaxRsBase: "com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:${jacksonVersion}",
|
||||
jacksonJaxRsJsonProvider: "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:${jacksonVersion}",
|
||||
jacksonJaxRsJsonProvider: "com.fasterxml.jackson.jakarta.rs:jackson-jakarta-rs-json-provider:${jacksonVersion}",
|
||||
jacksonDatatypeJdk8: "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:${jacksonVersion}",
|
||||
jacksonDatatypeJsr310: "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${jacksonVersion}",
|
||||
jacksonDataFormatYaml: "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${jacksonVersion}",
|
||||
|
||||
// hypermedia
|
||||
edison: 'de.otto.edison:edison-hal:2.1.0',
|
||||
|
||||
// openapi
|
||||
swaggerJaxRs: 'io.swagger.core.v3:swagger-jaxrs2:2.1.12',
|
||||
swaggerJaxRs: 'io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.19',
|
||||
|
||||
// dto mapping
|
||||
mapstruct: "org.mapstruct:mapstruct-jdk8:${mapstructVersion}",
|
||||
@@ -86,9 +89,9 @@ ext {
|
||||
jaxbRuntime: "org.glassfish.jaxb:jaxb-runtime:${jaxbVersion}",
|
||||
|
||||
// validation
|
||||
validator: 'org.hibernate.validator:hibernate-validator:6.1.6.Final',
|
||||
elApi: 'javax.el:javax.el-api:3.0.0',
|
||||
elRuntime: 'org.glassfish:javax.el:3.0.1-b11',
|
||||
validator: 'org.hibernate.validator:hibernate-validator:8.0.1.Final',
|
||||
elApi: 'jakarta.el:jakarta.el-api:5.0.1',
|
||||
elRuntime: 'org.glassfish:jakarta.el:4.0.2',
|
||||
|
||||
// utils
|
||||
guava: 'com.google.guava:guava:32.0.1-jre',
|
||||
@@ -98,9 +101,9 @@ ext {
|
||||
commonsLang3: 'org.apache.commons:commons-lang3:3.13.0',
|
||||
|
||||
// security
|
||||
shiroCore: "org.apache.shiro:shiro-core:${shiroVersion}",
|
||||
shiroWeb: "org.apache.shiro:shiro-web:${shiroVersion}",
|
||||
shiroGuice: "org.apache.shiro:shiro-guice:${shiroVersion}",
|
||||
shiroCore: "org.apache.shiro:shiro-core:${shiroVersion}:jakarta",
|
||||
shiroWeb: "org.apache.shiro:shiro-web:${shiroVersion}:jakarta",
|
||||
shiroGuice: "org.apache.shiro:shiro-guice:${shiroVersion}:jakarta",
|
||||
|
||||
ssp: "com.github.sdorra:ssp-lib:${sspVersion}",
|
||||
sspProcessor: "com.github.sdorra:ssp-processor:${sspVersion}",
|
||||
@@ -114,9 +117,9 @@ ext {
|
||||
jjwtJackson: "io.jsonwebtoken:jjwt-jackson:${jjwtVersion}",
|
||||
|
||||
// gpg
|
||||
bouncycastlePg: "org.bouncycastle:bcpg-jdk15to18:${bouncycastleVersion}",
|
||||
bouncycastleProv: "org.bouncycastle:bcprov-jdk15to18:${bouncycastleVersion}",
|
||||
bouncycastlePkix: "org.bouncycastle:bcpkix-jdk15to18:${bouncycastleVersion}",
|
||||
bouncycastlePg: "org.bouncycastle:bcpg-lts8on:${bouncycastleVersion}",
|
||||
bouncycastleProv: "org.bouncycastle:bcprov-lts8on:${bouncycastleVersion}",
|
||||
bouncycastlePkix: "org.bouncycastle:bcpkix-lts8on:${bouncycastleVersion}",
|
||||
|
||||
// service registration
|
||||
metainfServices: 'org.kohsuke.metainf-services:metainf-services:1.8',
|
||||
@@ -128,7 +131,7 @@ ext {
|
||||
mustache: 'com.github.spullara.mustache.java:compiler:0.9.10',
|
||||
|
||||
// static resources
|
||||
webResources: 'com.github.sdorra:web-resources:1.1.1',
|
||||
webResources: 'com.github.sdorra:web-resources:2.0.0',
|
||||
|
||||
// content type detection
|
||||
spotter: 'com.cloudogu.spotter:spotter-core:4.0.0',
|
||||
@@ -145,12 +148,11 @@ ext {
|
||||
jsvc: 'commons-daemon:commons-daemon-native:1.1.0@tar.gz',
|
||||
|
||||
// yaml
|
||||
snakeYml: 'org.yaml:snakeyaml:1.21',
|
||||
snakeYml: 'org.yaml:snakeyaml:2.2',
|
||||
|
||||
// jetty
|
||||
jettyServer: "org.eclipse.jetty:jetty-server:${jettyVersion}",
|
||||
jettyWebapp: "org.eclipse.jetty:jetty-webapp:${jettyVersion}",
|
||||
jettyJmx: "org.eclipse.jetty:jetty-jmx:${jettyVersion}",
|
||||
jettyClient: "org.eclipse.jetty:jetty-client:${jettyVersion}",
|
||||
|
||||
// search
|
||||
@@ -184,8 +186,10 @@ ext {
|
||||
awaitility: 'org.awaitility:awaitility:4.0.2',
|
||||
|
||||
// rest api client for testing
|
||||
jerseyClientApi: "com.sun.jersey:jersey-client:${jerseyClientVersion}",
|
||||
jerseyClientRuntime: "com.sun.jersey.contribs:jersey-apache-client:${jerseyClientVersion}",
|
||||
jerseyCommon: "org.glassfish.jersey.core:jersey-common:${jerseyVersion}",
|
||||
jerseyClientApi: "org.glassfish.jersey.core:jersey-client:${jerseyVersion}",
|
||||
jerseyClientRuntime: "com.sun.jersey.contribs:jersey-apache-client:${jerseyVersion}",
|
||||
jerseyMediaJson: "org.glassfish.jersey.media:jersey-media-json-jackson:${jerseyVersion}",
|
||||
|
||||
// metrics
|
||||
micrometerCore: "io.micrometer:micrometer-core:${micrometerVersion}",
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.annotation;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ConfigElement implements DescriptorElement {
|
||||
|
||||
private final Map<String, String> attributes;
|
||||
private final String type;
|
||||
|
||||
public ConfigElement(Map<String, String> attributes, String type) {
|
||||
this.attributes = attributes;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void append(Document doc, Element root) {
|
||||
|
||||
Element configEl = doc.createElement("config-value");
|
||||
|
||||
for (Map.Entry<String, String> entry : attributes.entrySet()) {
|
||||
Element attributeEl = doc.createElement(entry.getKey());
|
||||
attributeEl.setTextContent(entry.getValue());
|
||||
configEl.appendChild(attributeEl);
|
||||
}
|
||||
|
||||
Element typeEl = doc.createElement("type");
|
||||
typeEl.setTextContent(type);
|
||||
configEl.appendChild(typeEl);
|
||||
|
||||
root.appendChild(configEl);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,8 @@ import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
import org.kohsuke.MetaInfServices;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.w3c.dom.DOMException;
|
||||
@@ -36,6 +38,7 @@ import org.w3c.dom.Document;
|
||||
import org.xml.sax.SAXException;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.annotation.ClassSetElement.ClassWithAttributes;
|
||||
import sonia.scm.config.ConfigValue;
|
||||
import sonia.scm.plugin.PluginAnnotation;
|
||||
import sonia.scm.plugin.Requires;
|
||||
|
||||
@@ -56,8 +59,6 @@ import javax.lang.model.element.VariableElement;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.StandardLocation;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
@@ -75,18 +76,18 @@ import java.lang.annotation.Annotation;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import static javax.lang.model.util.ElementFilter.methodsIn;
|
||||
|
||||
|
||||
/**
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@SupportedAnnotationTypes("*")
|
||||
@MetaInfServices(Processor.class)
|
||||
@SuppressWarnings({"Since16"})
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_11)
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_17)
|
||||
public final class ScmAnnotationProcessor extends AbstractProcessor {
|
||||
|
||||
private static final String DESCRIPTOR_MODULE = "META-INF/scm/module.xml";
|
||||
@@ -96,6 +97,8 @@ public final class ScmAnnotationProcessor extends AbstractProcessor {
|
||||
private static final String PROPERTY_VALUE = "yes";
|
||||
private static final Set<String> SUBSCRIBE_ANNOTATIONS =
|
||||
ImmutableSet.of(Subscribe.class.getName());
|
||||
|
||||
private static final Set<String> CONFIG_ANNOTATIONS = ImmutableSet.of(ConfigValue.class.getName());
|
||||
private static final Set<ClassAnnotation> CLASS_ANNOTATIONS =
|
||||
ImmutableSet.of(new ClassAnnotation("rest-resource", Path.class),
|
||||
new ClassAnnotation("rest-provider", Provider.class),
|
||||
@@ -108,6 +111,7 @@ public final class ScmAnnotationProcessor extends AbstractProcessor {
|
||||
if (!roundEnv.processingOver()) {
|
||||
Set<DescriptorElement> descriptorElements = Sets.newHashSet();
|
||||
Set<TypeElement> subscriberAnnotations = Sets.newHashSet();
|
||||
Set<TypeElement> configAnnotations = Sets.newHashSet();
|
||||
|
||||
for (TypeElement e : annotations) {
|
||||
PluginAnnotation pa = e.getAnnotation(PluginAnnotation.class);
|
||||
@@ -119,6 +123,10 @@ public final class ScmAnnotationProcessor extends AbstractProcessor {
|
||||
if (SUBSCRIBE_ANNOTATIONS.contains(e.getQualifiedName().toString())) {
|
||||
subscriberAnnotations.add(e);
|
||||
}
|
||||
|
||||
if (CONFIG_ANNOTATIONS.contains(e.getQualifiedName().toString())) {
|
||||
configAnnotations.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
for (ClassAnnotation ca : CLASS_ANNOTATIONS) {
|
||||
@@ -134,6 +142,9 @@ public final class ScmAnnotationProcessor extends AbstractProcessor {
|
||||
for (TypeElement annotation : subscriberAnnotations) {
|
||||
scanForSubscriberAnnotations(descriptorElements, roundEnv, annotation);
|
||||
}
|
||||
for (TypeElement annotation : configAnnotations) {
|
||||
scanForConfigAnnotations(descriptorElements, roundEnv, annotation);
|
||||
}
|
||||
|
||||
write(descriptorElements);
|
||||
}
|
||||
@@ -141,6 +152,19 @@ public final class ScmAnnotationProcessor extends AbstractProcessor {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void scanForConfigAnnotations(Set<DescriptorElement> descriptorElements, RoundEnvironment roundEnv, TypeElement annotation) {
|
||||
|
||||
Set<? extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(annotation);
|
||||
|
||||
for (Element element : elementsAnnotatedWith) {
|
||||
Map<String, String> attributesFromAnnotation = getAttributesFromAnnotation(element, annotation);
|
||||
String type = element.asType().toString();
|
||||
|
||||
descriptorElements.add(new ConfigElement(attributesFromAnnotation, type));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private TypeElement findAnnotation(Set<? extends TypeElement> annotations,
|
||||
Class<? extends Annotation> annotationClass) {
|
||||
TypeElement annotation = null;
|
||||
@@ -353,8 +377,8 @@ public final class ScmAnnotationProcessor extends AbstractProcessor {
|
||||
String qn = annotationMirror.getAnnotationType().asElement().toString();
|
||||
|
||||
if (qn.equals(annotation.toString())) {
|
||||
for (Entry<? extends ExecutableElement,
|
||||
? extends AnnotationValue> entry : annotationMirror.getElementValues().entrySet()) {
|
||||
for (Map.Entry<? extends ExecutableElement,
|
||||
? extends AnnotationValue> entry : annotationMirror.getElementValues().entrySet()) {
|
||||
attributes.put(entry.getKey().getSimpleName().toString(),
|
||||
getValue(entry.getValue()));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.config;
|
||||
|
||||
|
||||
import com.google.inject.BindingAnnotation;
|
||||
import sonia.scm.plugin.PluginAnnotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Documented
|
||||
@BindingAnnotation
|
||||
@Target({ ElementType.PARAMETER, ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@PluginAnnotation("config-value")
|
||||
public @interface ConfigValue {
|
||||
String key();
|
||||
String defaultValue();
|
||||
String description() default "";
|
||||
}
|
||||
@@ -25,10 +25,10 @@
|
||||
|
||||
<module>
|
||||
<extension-point>
|
||||
<class>javax.servlet.ServletContextListener</class>
|
||||
<class>jakarta.servlet.ServletContextListener</class>
|
||||
</extension-point>
|
||||
<extension-point>
|
||||
<class>javax.servlet.http.HttpSessionListener</class>
|
||||
<class>jakarta.servlet.http.HttpSessionListener</class>
|
||||
</extension-point>
|
||||
<extension-point>
|
||||
<class>com.google.inject.Module</class>
|
||||
|
||||
@@ -47,6 +47,9 @@ dependencies {
|
||||
annotationProcessor libraries.lombok
|
||||
testAnnotationProcessor libraries.lombok
|
||||
|
||||
// jakarta
|
||||
api libraries.jakartaAnnotationApi
|
||||
|
||||
// servlet api
|
||||
implementation libraries.servletApi
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
package sonia.scm;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import sonia.scm.config.WebappConfigProvider;
|
||||
import sonia.scm.util.SystemUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -35,29 +36,27 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Determines the base directory for SCM-Manager.
|
||||
* This class should not be used directory, use {@link SCMContextProvider#getBaseDirectory()} instead.
|
||||
* Determines the home directory for SCM-Manager aka "scm-home".
|
||||
* This class should not be used directly, use {@link SCMContextProvider#getBaseDirectory()} instead.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
final class BaseDirectory {
|
||||
|
||||
/** Environment variable for the SCM-Manager base directory */
|
||||
static final String ENVIRONMENT_VARIABLE = "SCM_HOME";
|
||||
|
||||
/** Java system property for the SCM-Manager base directory */
|
||||
static final String SYSTEM_PROPERTY = "scm.home";
|
||||
|
||||
/** Classpath resource for the SCM-Manager base directory */
|
||||
/**
|
||||
* Classpath resource for the SCM-Manager base directory
|
||||
*/
|
||||
@SuppressWarnings("java:S1075") // it is already configurable
|
||||
static final String CLASSPATH_RESOURCE = "/scm.properties";
|
||||
|
||||
/** Property name in resource file */
|
||||
/**
|
||||
* Property name in resource file
|
||||
*/
|
||||
static final String RESOURCE_PROPERTY = "scm.home";
|
||||
|
||||
private final Platform platform;
|
||||
private final String classPathResource;
|
||||
private final Map<String,String> environment;
|
||||
private final Map<String, String> environment;
|
||||
private final Properties systemProperties;
|
||||
|
||||
BaseDirectory(Platform platform, String classPathResource, Map<String, String> environment, Properties systemProperties) {
|
||||
@@ -74,21 +73,22 @@ final class BaseDirectory {
|
||||
*/
|
||||
@SuppressWarnings("java:S5304") // it is safe to use environment in this case
|
||||
static Path get() {
|
||||
return new BaseDirectory(
|
||||
SystemUtil.getPlatform(),
|
||||
CLASSPATH_RESOURCE,
|
||||
System.getenv(),
|
||||
System.getProperties()
|
||||
).find();
|
||||
return
|
||||
new BaseDirectory(
|
||||
SystemUtil.getPlatform(),
|
||||
CLASSPATH_RESOURCE,
|
||||
System.getenv(),
|
||||
System.getProperties()
|
||||
)
|
||||
.find()
|
||||
.normalize()
|
||||
.toAbsolutePath();
|
||||
}
|
||||
|
||||
Path find() {
|
||||
String directory = getFromResource();
|
||||
if (Strings.isNullOrEmpty(directory)) {
|
||||
directory = getFromSystemProperty();
|
||||
}
|
||||
if (Strings.isNullOrEmpty(directory)) {
|
||||
directory = getFromEnvironmentVariable();
|
||||
directory = WebappConfigProvider.resolveAsString("homeDir").orElse(null);
|
||||
}
|
||||
if (Strings.isNullOrEmpty(directory)) {
|
||||
directory = getOsSpecificDefault();
|
||||
@@ -98,30 +98,18 @@ final class BaseDirectory {
|
||||
}
|
||||
|
||||
private String getFromResource() {
|
||||
try (InputStream input = BasicContextProvider.class.getResourceAsStream(classPathResource))
|
||||
{
|
||||
if (input != null)
|
||||
{
|
||||
try (InputStream input = BasicContextProvider.class.getResourceAsStream(classPathResource)) {
|
||||
if (input != null) {
|
||||
Properties properties = new Properties();
|
||||
properties.load(input);
|
||||
return properties.getProperty(RESOURCE_PROPERTY);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
} catch (IOException ex) {
|
||||
throw new ConfigurationException("could not load properties form resource " + CLASSPATH_RESOURCE, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getFromEnvironmentVariable() {
|
||||
return environment.get(ENVIRONMENT_VARIABLE);
|
||||
}
|
||||
|
||||
private String getFromSystemProperty() {
|
||||
return systemProperties.getProperty(SYSTEM_PROPERTY);
|
||||
}
|
||||
|
||||
private String getOsSpecificDefault() {
|
||||
if (platform.isMac()) {
|
||||
return getOsxDefault();
|
||||
@@ -132,7 +120,7 @@ final class BaseDirectory {
|
||||
}
|
||||
|
||||
private String getOsxDefault() {
|
||||
return systemProperties.getProperty("user.home") + "/Library/Application Support/SCM-Manager";
|
||||
return systemProperties.getProperty("user.home") + "/Library/Application Support/SCM-Manager";
|
||||
}
|
||||
|
||||
private String getWindowsDefault() {
|
||||
|
||||
@@ -29,15 +29,14 @@ package sonia.scm;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.io.Files;
|
||||
import sonia.scm.config.WebappConfigProvider;
|
||||
import sonia.scm.util.IOUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -55,24 +54,12 @@ public class BasicContextProvider implements SCMContextProvider
|
||||
/** Default version {@link String} */
|
||||
public static final String VERSION_DEFAULT = "unknown";
|
||||
|
||||
/**
|
||||
* System property to override scm-manager version.
|
||||
* <b>Note</b>: This should only be used for testing and never in production.
|
||||
**/
|
||||
public static final String VERSION_PROPERTY = "sonia.scm.version.override";
|
||||
|
||||
/** Default name of the SCM-Manager base directory */
|
||||
public static final String DIRECTORY_DEFAULT = ".scm";
|
||||
|
||||
/** Environment varibale for the SCM-Manager base directory */
|
||||
public static final String DIRECTORY_ENVIRONMENT = "SCM_HOME";
|
||||
|
||||
/** Java system property for the SCM-Manager base directory */
|
||||
public static final String DIRECTORY_PROPERTY = "scm.home";
|
||||
|
||||
/** Classpath resource for the SCM-Manager base directory */
|
||||
public static final String DIRECTORY_RESOURCE = "/scm.properties";
|
||||
|
||||
/** Path to the maven properties file of the scm-core artifact */
|
||||
public static final String MAVEN_PROPERTIES =
|
||||
"/META-INF/scm/build-info.properties";
|
||||
@@ -80,11 +67,6 @@ public class BasicContextProvider implements SCMContextProvider
|
||||
/** Maven property for the version of the artifact */
|
||||
public static final String MAVEN_PROPERTY_VERSION = "version";
|
||||
|
||||
/**
|
||||
* Java system property for the SCM-Manager project stage
|
||||
* @since 1.12
|
||||
*/
|
||||
public static final String STAGE_PROPERTY = "scm.stage";
|
||||
|
||||
public static final String DEVELOPMENT_INSTANCE_ID = "00000000-0000-0000-0000-000000000000";
|
||||
|
||||
@@ -100,7 +82,7 @@ public class BasicContextProvider implements SCMContextProvider
|
||||
{
|
||||
baseDirectory = findBaseDirectory();
|
||||
version = determineVersion();
|
||||
stage = loadProjectStage();
|
||||
stage = Stage.valueOf(WebappConfigProvider.resolveAsString("stage").orElse(Stage.PRODUCTION.name()));
|
||||
instanceId = readOrCreateInstanceId();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -209,37 +191,8 @@ public class BasicContextProvider implements SCMContextProvider
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the current stage.
|
||||
*
|
||||
*
|
||||
* @return current stage
|
||||
*/
|
||||
private Stage loadProjectStage()
|
||||
{
|
||||
Stage s = Stage.PRODUCTION;
|
||||
String stageProperty = System.getProperty(STAGE_PROPERTY);
|
||||
|
||||
if (Util.isNotEmpty(stageProperty))
|
||||
{
|
||||
try
|
||||
{
|
||||
s = Stage.valueOf(stageProperty.toUpperCase(Locale.ENGLISH));
|
||||
}
|
||||
catch (IllegalArgumentException ex)
|
||||
{
|
||||
|
||||
// do not use logger or IOUtil,
|
||||
// http://www.slf4j.org/codes.html#substituteLogger
|
||||
ex.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private String determineVersion() {
|
||||
String v = System.getProperty(VERSION_PROPERTY);
|
||||
String v = WebappConfigProvider.resolveAsString("versionOverride").orElse(null);
|
||||
if (Strings.isNullOrEmpty(v)) {
|
||||
v = loadVersion();
|
||||
}
|
||||
@@ -288,7 +241,7 @@ public class BasicContextProvider implements SCMContextProvider
|
||||
}
|
||||
|
||||
private String readOrCreateInstanceId() throws IOException {
|
||||
if (stage == Stage.DEVELOPMENT) {
|
||||
if (stage != Stage.PRODUCTION) {
|
||||
return DEVELOPMENT_INSTANCE_ID;
|
||||
}
|
||||
File configDirectory = new File(baseDirectory, "config");
|
||||
|
||||
@@ -28,11 +28,11 @@ package sonia.scm;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.Maps;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import sonia.scm.xml.XmlMapStringAdapter;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ package sonia.scm;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import sonia.scm.i18n.I18nMessages;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
@@ -43,7 +43,7 @@ public final class ClientMessages
|
||||
|
||||
/**
|
||||
* Constructs a new instance of ClientMessages. This constructor should not be
|
||||
* used. Use the {@link #get(javax.servlet.http.HttpServletRequest)} method
|
||||
* used. Use the {@link #get(jakarta.servlet.http.HttpServletRequest)} method
|
||||
* instead.
|
||||
*/
|
||||
public ClientMessages() {}
|
||||
|
||||
@@ -26,14 +26,11 @@ package sonia.scm;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import jakarta.servlet.RequestDispatcher;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Detects the ServletContainer.
|
||||
* This class is inspired by
|
||||
|
||||
@@ -26,13 +26,10 @@ package sonia.scm;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import sonia.scm.util.AssertUtil;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* Base class for all objects which supports different types.
|
||||
*
|
||||
|
||||
@@ -29,23 +29,22 @@ import com.google.common.annotations.Beta;
|
||||
import de.otto.edison.hal.HalRepresentation;
|
||||
import de.otto.edison.hal.Link;
|
||||
import de.otto.edison.hal.Links;
|
||||
import jakarta.inject.Provider;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import sonia.scm.config.ConfigurationPermissions;
|
||||
import sonia.scm.store.ConfigurationStore;
|
||||
import sonia.scm.store.ConfigurationStoreFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Provider;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
/**
|
||||
* This can be used as a base class for configuration resources.
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import jakarta.xml.bind.annotation.XmlElementWrapper;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import sonia.scm.ContextEntry;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.util.List;
|
||||
|
||||
@Getter @Setter
|
||||
|
||||
@@ -25,10 +25,9 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@Slf4j
|
||||
public class HalAppenderMapper {
|
||||
|
||||
|
||||
@@ -26,10 +26,9 @@ package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import jakarta.inject.Singleton;
|
||||
import sonia.scm.plugin.Extension;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* The {@link HalEnricherRegistry} is responsible for binding {@link HalEnricher} instances to their source types.
|
||||
*
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import jakarta.ws.rs.core.UriBuilder;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@Getter @Setter
|
||||
public class MergeCommandDto {
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
|
||||
package sonia.scm.auditlog;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import sonia.scm.repository.RepositoryDAO;
|
||||
import sonia.scm.store.ConfigurationStore;
|
||||
import sonia.scm.store.ConfigurationStoreDecoratorFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Set;
|
||||
|
||||
public class AuditLogConfigurationStoreDecoratorFactory implements ConfigurationStoreDecoratorFactory {
|
||||
|
||||
@@ -56,7 +56,6 @@ public interface CliContext {
|
||||
/**
|
||||
* Sets the exit code for the current command execution and stops the execution.
|
||||
* @param exitcode exit code which will be return to the client terminal
|
||||
* @see {@link ExitCode}
|
||||
*/
|
||||
void exit(int exitcode);
|
||||
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
|
||||
package sonia.scm.cli;
|
||||
|
||||
import jakarta.annotation.Nullable;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
@@ -24,15 +24,15 @@
|
||||
|
||||
package sonia.scm.cli;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.validation.ConstraintValidatorFactory;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.MessageInterpolator;
|
||||
import jakarta.validation.Validation;
|
||||
import jakarta.validation.Validator;
|
||||
import jakarta.validation.ValidatorFactory;
|
||||
import picocli.CommandLine;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.validation.ConstraintValidatorFactory;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.MessageInterpolator;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.ValidatorFactory;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
package sonia.scm.cli;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import jakarta.annotation.Nullable;
|
||||
import lombok.Value;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
@@ -27,14 +27,14 @@ package sonia.scm.cli;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.inject.Inject;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.template.Template;
|
||||
import sonia.scm.template.TemplateEngine;
|
||||
import sonia.scm.template.TemplateEngineFactory;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringReader;
|
||||
|
||||
@@ -28,10 +28,10 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ForwardingQueue;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
|
||||
|
||||
@@ -22,13 +22,12 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.security;
|
||||
package sonia.scm.config;
|
||||
|
||||
public class JwtSystemProperties {
|
||||
import lombok.Value;
|
||||
|
||||
public static final String ENDLESS_JWT = "scm.endlessJwt";
|
||||
|
||||
public static boolean isEndlessJwtEnabled() {
|
||||
return Boolean.parseBoolean(System.getProperty(ENDLESS_JWT));
|
||||
}
|
||||
@Value
|
||||
public class ConfigBinding {
|
||||
ConfigElement configElement;
|
||||
Object value;
|
||||
}
|
||||
48
scm-core/src/main/java/sonia/scm/config/ConfigElement.java
Normal file
48
scm-core/src/main/java/sonia/scm/config/ConfigElement.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.config;
|
||||
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@XmlRootElement(name = "config-value")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ConfigElement {
|
||||
private String key;
|
||||
private String defaultValue;
|
||||
private String description;
|
||||
private String type;
|
||||
}
|
||||
@@ -26,6 +26,13 @@ package sonia.scm.config;
|
||||
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import jakarta.xml.bind.annotation.XmlTransient;
|
||||
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.auditlog.AuditEntry;
|
||||
@@ -35,13 +42,6 @@ import sonia.scm.util.HttpUtil;
|
||||
import sonia.scm.xml.XmlCipherStringAdapter;
|
||||
import sonia.scm.xml.XmlSetStringAdapter;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class WebappConfigProvider {
|
||||
|
||||
private WebappConfigProvider() {}
|
||||
|
||||
private static Map<String, String> configBindings = new HashMap<>();
|
||||
|
||||
public static void setConfigBindings(Map<String, String> newBindings) {
|
||||
configBindings = newBindings;
|
||||
}
|
||||
|
||||
public static Optional<String> resolveAsString(String key) {
|
||||
return resolveConfig(key);
|
||||
}
|
||||
|
||||
public static Optional<Boolean> resolveAsBoolean(String key) {
|
||||
return resolveConfig(key).map(Boolean::parseBoolean);
|
||||
}
|
||||
|
||||
public static Optional<Integer> resolveAsInteger(String key) {
|
||||
return resolveConfig(key).map(Integer::parseInt);
|
||||
}
|
||||
|
||||
public static Optional<Long> resolveAsLong(String key) {
|
||||
return resolveConfig(key).map(Long::parseLong);
|
||||
}
|
||||
|
||||
private static Optional<String> resolveConfig(String key) {
|
||||
return Optional.ofNullable(configBindings.get(key));
|
||||
}
|
||||
}
|
||||
@@ -24,22 +24,22 @@
|
||||
|
||||
package sonia.scm.filter;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Provider;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.ext.WriterInterceptor;
|
||||
import jakarta.ws.rs.ext.WriterInterceptorContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.ext.WriterInterceptor;
|
||||
import javax.ws.rs.ext.WriterInterceptorContext;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Locale;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
@javax.ws.rs.ext.Provider
|
||||
@jakarta.ws.rs.ext.Provider
|
||||
public class GZipResponseFilter implements WriterInterceptor {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GZipResponseFilter.class);
|
||||
|
||||
@@ -26,22 +26,17 @@ package sonia.scm.filter;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import jakarta.servlet.ServletOutputStream;
|
||||
import jakarta.servlet.WriteListener;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.WriteListener;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Response stream for gzip encoding.
|
||||
*
|
||||
|
||||
@@ -26,18 +26,15 @@ package sonia.scm.filter;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import jakarta.servlet.ServletOutputStream;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletResponseWrapper;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
|
||||
/**
|
||||
* Response wrapper for gzip encoding.
|
||||
*
|
||||
|
||||
@@ -31,6 +31,9 @@ import com.github.sdorra.ssp.StaticPermissions;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.Lists;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import sonia.scm.BasicPropertiesAware;
|
||||
import sonia.scm.ModelObject;
|
||||
import sonia.scm.ReducedModelObject;
|
||||
@@ -41,9 +44,6 @@ import sonia.scm.search.IndexedType;
|
||||
import sonia.scm.util.Util;
|
||||
import sonia.scm.util.ValidationUtil;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -29,9 +29,9 @@ package sonia.scm.i18n;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import sonia.scm.util.ClassLoaders;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ package sonia.scm.io;
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import jakarta.annotation.Nullable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
package sonia.scm.net;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import jakarta.inject.Inject;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -27,14 +27,14 @@ package sonia.scm.net;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Provider;
|
||||
import lombok.Value;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.KeyManager;
|
||||
|
||||
@@ -26,6 +26,9 @@ package sonia.scm.plugin;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -33,9 +36,6 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@@ -28,11 +28,10 @@ package sonia.scm.plugin;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -27,8 +27,9 @@ package sonia.scm.plugin;
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.inject.Binder;
|
||||
import sonia.scm.config.ConfigBinding;
|
||||
|
||||
import java.util.Collections;
|
||||
import static java.util.Collections.emptySet;
|
||||
|
||||
/**
|
||||
* Process and resolve extensions.
|
||||
@@ -79,6 +80,13 @@ public interface ExtensionProcessor
|
||||
*/
|
||||
Iterable<WebElementExtension> getWebElements();
|
||||
|
||||
/**
|
||||
* @since 3.0.0
|
||||
*/
|
||||
default Iterable<ConfigBinding> getConfigBindings() {
|
||||
return emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all collected indexable types.
|
||||
*
|
||||
@@ -86,6 +94,6 @@ public interface ExtensionProcessor
|
||||
* @since 2.21.0
|
||||
*/
|
||||
default Iterable<Class<?>> getIndexedTypes() {
|
||||
return Collections.emptySet();
|
||||
return emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ public final class InstalledPlugin implements Plugin
|
||||
{
|
||||
|
||||
public static final String UNINSTALL_MARKER_FILENAME = "uninstall";
|
||||
public static final String COMPATIBILITY_MARKER_FILENAME = ".jakarta-compatible";
|
||||
|
||||
/**
|
||||
* Constructs a new plugin wrapper.
|
||||
|
||||
@@ -30,12 +30,12 @@ import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.XmlElementWrapper;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@@ -25,16 +25,16 @@
|
||||
package sonia.scm.plugin;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlAttribute;
|
||||
import jakarta.xml.bind.annotation.XmlValue;
|
||||
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import sonia.scm.version.Version;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlValue;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
|
||||
package sonia.scm.plugin;
|
||||
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import java.util.HashSet;
|
||||
|
||||
@Getter
|
||||
|
||||
@@ -28,17 +28,17 @@ package sonia.scm.plugin;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.XmlElementWrapper;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import sonia.scm.PlatformType;
|
||||
import sonia.scm.SCMContext;
|
||||
import sonia.scm.util.SystemUtil;
|
||||
import sonia.scm.util.Util;
|
||||
import sonia.scm.version.Version;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -26,13 +26,13 @@ package sonia.scm.plugin;
|
||||
|
||||
import com.github.sdorra.ssp.PermissionObject;
|
||||
import com.github.sdorra.ssp.StaticPermissions;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import lombok.Data;
|
||||
import sonia.scm.Validateable;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
|
||||
@@ -28,10 +28,10 @@ package sonia.scm.plugin;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import java.util.Set;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.plugin;
|
||||
|
||||
public class PluginTransformException extends PluginException{
|
||||
public PluginTransformException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public PluginTransformException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -29,17 +29,13 @@ package sonia.scm.plugin;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.io.ByteSource;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
import jakarta.xml.bind.JAXBContext;
|
||||
import jakarta.xml.bind.JAXBException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
/**
|
||||
* Util methods to handle plugins.
|
||||
*
|
||||
|
||||
@@ -25,11 +25,12 @@
|
||||
package sonia.scm.plugin;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import sonia.scm.config.ConfigElement;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -67,6 +68,9 @@ public class ScmModule {
|
||||
@XmlElement(name = "subscriber")
|
||||
private Set<SubscriberElement> subscribers;
|
||||
|
||||
@XmlElement(name = "config-value")
|
||||
private Set<ConfigElement> configElements;
|
||||
|
||||
@XmlElement(name = "web-element")
|
||||
private Set<WebElementDescriptor> webElements;
|
||||
|
||||
@@ -110,6 +114,14 @@ public class ScmModule {
|
||||
return nonNull(indexedTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.0.0
|
||||
|
||||
*/
|
||||
public Iterable<ConfigElement> getConfigElements() {
|
||||
return nonNull(configElements);
|
||||
}
|
||||
|
||||
private <T> Iterable<T> nonNull(Iterable<T> iterable) {
|
||||
if (iterable == null) {
|
||||
iterable = ImmutableSet.of();
|
||||
|
||||
@@ -28,11 +28,10 @@ package sonia.scm.plugin;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -26,12 +26,11 @@ package sonia.scm.plugin;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
/**
|
||||
* Load resources from {@link ServletContext} and from the installed plugins.
|
||||
* The UberWebResourceLoader will first look into the {@link ServletContext} and
|
||||
|
||||
@@ -26,6 +26,11 @@ package sonia.scm.plugin;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -34,11 +39,6 @@ import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import sonia.scm.xml.XmlArrayStringAdapter;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,7 +26,8 @@ package sonia.scm.plugin;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import jakarta.servlet.ServletContext;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,11 +26,11 @@ package sonia.scm.repository;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import sonia.scm.Validateable;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -24,13 +24,12 @@
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import sonia.scm.EagerSingleton;
|
||||
import sonia.scm.Initable;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.plugin.Extension;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@Extension
|
||||
@EagerSingleton
|
||||
final class EventDrivenRepositoryArchiveCheckInitializer implements Initable {
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
package sonia.scm.repository;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import sonia.scm.LastModifiedAware;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -28,10 +28,10 @@ package sonia.scm.repository;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.io.Serializable;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ package sonia.scm.repository;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import jakarta.inject.Inject;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import sonia.scm.plugin.Extension;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
|
||||
@@ -26,13 +26,13 @@ package sonia.scm.repository;
|
||||
|
||||
import com.github.sdorra.ssp.PermissionObject;
|
||||
import com.github.sdorra.ssp.StaticPermissions;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import sonia.scm.auditlog.AuditEntry;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import sonia.scm.EagerSingleton;
|
||||
import sonia.scm.Initable;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.plugin.Extension;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,11 +25,10 @@
|
||||
package sonia.scm.repository;
|
||||
|
||||
import com.github.legman.Subscribe;
|
||||
import jakarta.inject.Inject;
|
||||
import sonia.scm.EagerSingleton;
|
||||
import sonia.scm.plugin.Extension;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static sonia.scm.HandlerEventType.DELETE;
|
||||
|
||||
@@ -29,6 +29,11 @@ import com.github.sdorra.ssp.PermissionObject;
|
||||
import com.github.sdorra.ssp.StaticPermissions;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import jakarta.xml.bind.annotation.XmlTransient;
|
||||
import sonia.scm.BasicPropertiesAware;
|
||||
import sonia.scm.ModelObject;
|
||||
import sonia.scm.auditlog.AuditEntry;
|
||||
@@ -38,11 +43,6 @@ import sonia.scm.search.IndexedType;
|
||||
import sonia.scm.util.Util;
|
||||
import sonia.scm.util.ValidationUtil;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -24,12 +24,11 @@
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import jakarta.xml.bind.annotation.XmlTransient;
|
||||
import sonia.scm.Validateable;
|
||||
import sonia.scm.config.Configuration;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
/**
|
||||
* Basic {@link Repository} configuration class.
|
||||
*
|
||||
|
||||
@@ -24,8 +24,9 @@
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
@@ -24,11 +24,10 @@
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
import sonia.scm.util.ValidationUtil;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
|
||||
public class RepositoryNameConstrainValidator implements ConstraintValidator<RepositoryName, String> {
|
||||
|
||||
private RepositoryName.Namespace namespace;
|
||||
|
||||
@@ -28,13 +28,13 @@ package sonia.scm.repository;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import sonia.scm.security.PermissionObject;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
package sonia.scm.repository;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -26,10 +26,10 @@ package sonia.scm.repository;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import sonia.scm.plugin.ExtensionPoint;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
@@ -28,19 +28,14 @@ package sonia.scm.repository;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
|
||||
@@ -29,14 +29,14 @@ import com.github.sdorra.ssp.StaticPermissions;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Strings;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import sonia.scm.ModelObject;
|
||||
import sonia.scm.auditlog.AuditEntry;
|
||||
import sonia.scm.auditlog.AuditLogEntity;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
@@ -24,8 +24,9 @@
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
import sonia.scm.Type;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,9 +26,9 @@ package sonia.scm.repository.api;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link PushResponse} and {@link PullResponse}.
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
package sonia.scm.repository.api;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import jakarta.annotation.Nullable;
|
||||
import sonia.scm.repository.Person;
|
||||
import sonia.scm.repository.spi.MergeCommand;
|
||||
import sonia.scm.repository.spi.MergeCommandRequest;
|
||||
@@ -33,7 +34,6 @@ import sonia.scm.repository.util.AuthorUtil;
|
||||
import sonia.scm.user.DisplayUser;
|
||||
import sonia.scm.user.EMail;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,15 +26,15 @@ package sonia.scm.repository.api;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Preconditions;
|
||||
import jakarta.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.net.ProxyConfiguration;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.spi.MirrorCommand;
|
||||
import sonia.scm.repository.spi.MirrorCommandRequest;
|
||||
import sonia.scm.security.PublicKey;
|
||||
import sonia.scm.net.ProxyConfiguration;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.google.common.base.Preconditions;
|
||||
import com.google.common.io.ByteSource;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.io.Files;
|
||||
import jakarta.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.repository.Person;
|
||||
@@ -38,7 +39,6 @@ import sonia.scm.repository.work.WorkdirProvider;
|
||||
import sonia.scm.user.EMail;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
package sonia.scm.repository.api;
|
||||
|
||||
import jakarta.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
@@ -40,7 +41,6 @@ import sonia.scm.repository.work.WorkdirProvider;
|
||||
import sonia.scm.security.Authentications;
|
||||
import sonia.scm.user.EMail;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import jakarta.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.HandlerEventType;
|
||||
@@ -61,7 +62,6 @@ import sonia.scm.security.PublicKeyDeletedEvent;
|
||||
import sonia.scm.security.ScmSecurityException;
|
||||
import sonia.scm.user.EMail;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Set;
|
||||
|
||||
import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import jakarta.servlet.ServletConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.api.ScmProtocol;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import jakarta.inject.Provider;
|
||||
import jakarta.servlet.ServletConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import sonia.scm.RootURL;
|
||||
import sonia.scm.api.v2.resources.ScmPathInfoStore;
|
||||
@@ -31,11 +36,6 @@ import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.api.ScmProtocolProvider;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -25,13 +25,13 @@
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import jakarta.annotation.Nullable;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import sonia.scm.net.ProxyConfiguration;
|
||||
import sonia.scm.repository.api.Credential;
|
||||
import sonia.scm.repository.api.MirrorFilter;
|
||||
import sonia.scm.security.PublicKey;
|
||||
import sonia.scm.net.ProxyConfiguration;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import jakarta.servlet.ServletConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface ScmProviderHttpServlet {
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import jakarta.servlet.ServletConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ScmProviderHttpServletDecorator implements ScmProviderHttpServlet {
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
package sonia.scm.repository.spi;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import jakarta.inject.Provider;
|
||||
import sonia.scm.util.Decorators;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@@ -24,14 +24,13 @@
|
||||
|
||||
package sonia.scm.repository.util;
|
||||
|
||||
import jakarta.annotation.Nullable;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import sonia.scm.repository.Person;
|
||||
import sonia.scm.user.EMail;
|
||||
import sonia.scm.user.User;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class AuthorUtil {
|
||||
|
||||
public static void setAuthorIfNotAvailable(CommandWithAuthor request) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user