diff --git a/.travis.yml b/.travis.yml index 6e8ce604..aa51e4e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,13 +14,13 @@ cache: directories: - $HOME/.m2 -before_install: -- openssl aes-256-cbc -K $encrypted_8dafc9c32687_key -iv $encrypted_8dafc9c32687_iv - -in gpg.tar.enc -out gpg.tar -d -- tar xvf gpg.tar - install: mvn clean install -DskipTests=true -V -U -script: mvn test +script: mvn test -Dkumuluzee.plugin.test.skip=true after_success: -- mvn source:jar javadoc:jar deploy -Pdeploy -DskipTests=true --settings ./settings.xml +# Deploy to OSSHR +- if [[ $TRAVIS_PULL_REQUEST == "false" && ($TRAVIS_BRANCH == "master" || $TRAVIS_TAG) ]]; then + openssl aes-256-cbc -K $encrypted_047edc09e660_key -iv $encrypted_047edc09e660_iv -in gpg.tar.gz.enc -out gpg.tar.gz -d; + tar xvf gpg.tar.gz; + mvn source:jar javadoc:jar deploy -Pdeploy -DskipTests=true --settings ./settings.xml; + fi \ No newline at end of file diff --git a/README.md b/README.md index 64fb9d80..47821b70 100644 --- a/README.md +++ b/README.md @@ -3,17 +3,16 @@ > Lightweight open-source framework for developing microservices using standard Java EE technologies and migrating Java EE to cloud-native architecture. -KumuluzEE is a lightweight framework for developing microservices using standard Java EE technologies and migrating -existing Java EE applications to microservices. KumuluzEE packages microservices as standalone JARs. -KumuluzEE microservices are lightweight and optimized for size and start-up time. -They fit perfectly with Docker containers. +KumuluzEE is a lightweight framework for developing microservices using standard Java EE technologies and migrating existing Java EE applications to microservices. KumuluzEE packages microservices as standalone JARs. KumuluzEE microservices are lightweight and optimized for size and start-up time. +They fit perfectly with Docker containers. KumuluzEE microservices are fully compatible with Kubernetes. -KumuluzEE also provides extensions for developing common patterns in cloud-native architectures, -including configuration, logging, discovery, circuit-breakers, metrics, security, event streaming and more. +KumuluzEE also provides extensions for developing common patterns in cloud-native architectures, including configuration, logging, discovery, fault tolerance with circuit-breakers, metrics, security, event streaming and more. -KumuluzEE has been designed to use the standard Java EE technologies and APIs with optional extensions for easier -development of cloud-native microservices. Therefore, it is particularly suitable for existing enterprise Java EE developers, -who would like to leverage their skills, but progressively move from monolithic to microservice design patterns. +KumuluzEE has been designed to use the standard Java EE technologies and APIs with optional extensions for easier development of cloud-native microservices. Therefore, it is particularly suitable for existing enterprise Java EE developers, who would like to leverage their skills, but progressively move from monolithic to microservice design patterns. + +KumuluzEE is Eclipse MicroProfile compliant and provides support for MicroProfile 1.0 and MicroProfile 1.1. It implements MicroProfile Config 1.1, MicroProfile Health 1.0, MicroProfile Fault Tolerance 1.0 and MicroProfile Metrics 1.0 APIs. + +## Features Primary features: @@ -21,50 +20,75 @@ Primary features: and Docker-like environments - Allows you to develop microservices using standard Java EE technologies. - Allows you to gradually migrate existing Java EE applications to microservices and cloud-native architecture. -- Complete control over what Java EE components and its implementations are included. Only include what you need and make -your app lightweight. +- Complete control over what Java EE components and its implementations are included. Only include what you need and make your app lightweight. - Minimal to no configuration settings up the base server. Develop like any other Java EE application - Quick startup time, low resource consumption and stateless scalability accelerates development -- Extend your microservices with common cloud-native patterns, such as config, discovery, logging, circuit-breakers, -etc. KumuluzEE provides all the building blocks. +- Extend your microservices with common cloud-native patterns, such as config, discovery, logging, fault tolerance, circuit-breakers, etc. KumuluzEE provides all the building blocks. + +KumuluzEE provides support for various Java EE APIs and components. The goal is to support as many Java EE components as possible (contributions welcome). -The goal is to support as many Java EE components as possible. Currently the following components are -supported with more being added over time: +## Java EE components + +Currently the following components are supported with more being added over time: - Servlet 3.1 (Jetty) -- WebSocket 1.1 (Jetty) +- CDI 1.2 (RI Weld) +- JAX-RS 2.1. (RI Jersey) +- JSON-P 1.0 (RI JSONP) - JSP 2.3 (Jetty Apache Jasper) +- JPA 2.1 (RI EclipseLink) +- JPA 2.1 (RI Hibernate) - EL 3.0 (RI UEL) -- CDI 1.2 (RI Weld) -- JPA 2.1 (RI EclipseLink, Hibernate) -- JAX-RS 2.0 (RI Jersey) +- JAX-WS (RI Metro) - JSF 2.2 (RI Mojarra) +- WebSocket 1.1 (Jetty) - Bean Validation 1.1 (RI Hibernate validator) -- JSON-P 1.0 (RI JSONP) +- JTA 1.2 (Narayana) + +## Additional features + +KumuluzEE provides additional features, which are described on the [project Wiki]( https://github.com/kumuluz/kumuluzee/wiki), particularly: +- [Configuration framework](https://github.com/kumuluz/kumuluzee/wiki/Configuration) for easy and efficient configuration of microservices from various sources, such as environment variables, configuration files (yaml), properties, etc. +- [TLS/SSL support](https://github.com/kumuluz/kumuluzee/wiki/TLS-SSL-support) for configuring TLS/SSL. + +KumuluzEE also provides support for [**Uber JARs**](https://github.com/kumuluz/kumuluzee/wiki/Uber-JAR-support). With the KumuluzEE Maven plugin, you can pack and run each microservice as a single, self-contained Uber-JAR. Details are described later in this document. ## KumuluzEE extensions -In addition to the standard Java EE components, KumuluzEE also comes with several extensions that complement and extend -its functionality. The extensions will follow the same modular concept as the Java EE components in which you can chose -if you want to use it as well as the underlying implementation of the extension. Most extensions are geared towards creating -cloud-native microservices including configuration, logging, discovery, circuit-breakers, metrics, security, event streaming and more. -As such they will be part of the KumuluzEE Cloud project with some exceptions. Currently the following -extensions are available with more planned soon: +In addition to the standard Java EE components, KumuluzEE also comes with several extensions that complement and extend its functionality. The extensions will follow the same modular concept as the Java EE components in which you can chose if you want to use it as well as the underlying implementation of the extension. Most extensions are geared towards creating cloud-native microservices including configuration, logging, discovery, fault tolerance including circuit-breakers, metrics, security, event streaming and more. +The following extensions are available with more planned soon: + +- [KumuluzEE Config](https://github.com/kumuluz/kumuluzee/wiki/Configuration) (File and environment variables) +- [KumuluzEE Config with config server](https://github.com/kumuluz/kumuluzee-config) (Config server etcd/Consul) +- [KumuluzEE REST](https://github.com/kumuluz/kumuluzee-rest) (For implementation of common, advanced and flexible REST API functionalities and patterns. Includes support for exposing JPA entities through REST) +- [KumuluzEE Logs](https://github.com/kumuluz/kumuluzee-logs) (For advanced microservice framework for logging) +- [KumuluzEE Discovery](https://github.com/kumuluz/kumuluzee-discovery) (For dynamic service discovery (etcd or Consul). Fully compatible with Kubernetes) +- [KumuluzEE Metrics](https://github.com/kumuluz/kumuluzee-metrics) (For easy collection and reporting of performance metrics) +- [KumuluzEE Security](https://github.com/kumuluz/kumuluzee-security) (For easy integration with OAuth2/OpenID identity and access management providers) +- [KumuluzEE Health](https://github.com/kumuluz/kumuluzee-health) (For implementing health checks and exposing microservice health information) +- [KumuluzEE Fault Tolerance](https://github.com/kumuluz/kumuluzee-fault-tolerance) (For implementing fault tolerance patterns with microservices including circuit breakers and decoupling microservices) +- [KumuluzEE Event Streaming](https://github.com/kumuluz/kumuluzee-streaming) (For event streaming support using Apache Kafka) +- [KumuluzEE CORS](https://github.com/kumuluz/kumuluzee-cors) (For Cross-Origin Resource Sharing (CORS) support) + +If you already know how to use Java EE, then you already know how to use KumuluzEE. It is simple and straightforward. See the [getting started](https://github.com/kumuluz/KumuluzEE/wiki/Getting-started) wiki section to create your first light-weight standalone Java EE app in 5 minutes. Refer to [samples](https://github.com/kumuluz/kumuluzee-samples) for more examples. -- [KumuluzEE Config (File and environment variables built-in)](https://github.com/kumuluz/kumuluzee/wiki/Configuration) -- [KumuluzEE Logs](https://github.com/kumuluz/kumuluzee-logs) +## MicroProfile -If you already know how to use Java EE, then you already know how to use KumuluzEE. Its dead simple, -see the [getting started](https://github.com/kumuluz/KumuluzEE/wiki/Getting-started) wiki section to create your first light-weight standalone -Java EE app in 5 minutes. +KumuluzEE is Eclipse MicroProfile compliant and provides support for: +- MicroProfile 1.0 +- MicroProfile 1.1 + +It implements the following MicroProfile APIs: +- [MicroProfile Config 1.1](https://github.com/kumuluz/kumuluzee-config-mp) +- [MicroProfile Health 1.0](https://github.com/kumuluz/kumuluzee-health) +- [MicroProfile Fault Tolerance 1.0](https://github.com/kumuluz/kumuluzee-fault-tolerance) +- [MicroProfile Metrics 1.0](https://github.com/kumuluz/kumuluzee-metrics) ## Usage -KumuluzEE ships with a BOM (bill of materials) which you can use to easily add the various components you need without -worrying about the versions and their compatibility as it is required that all components are the same version. +KumuluzEE ships with a BOM (bill of materials) which you can use to easily add the various components you need without worrying about the versions and their compatibility as it is required that all components are the same version. -Using maven add the BOM module of the library as a dependency to your project. The `${kumuluzee.version}` -variables represents the most current minor version. You can see the available version on the +Using maven add the BOM module of the library as a dependency to your project. The `${kumuluzee.version}` variables represents the most current minor version. You can see the available version on the [Release Page](https://github.com/kumuluz/KumuluzEE/releases). ```xml @@ -84,6 +108,7 @@ variables represents the most current minor version. You can see the available v Now you can either choose any single combinations of Java EE components or use one of the common pre-built profiles that ship as part of KumuluzEE. You can chose any of the following profiles: +MicroProfile 1.0 ```xml @@ -92,8 +117,16 @@ ship as part of KumuluzEE. You can chose any of the following profiles: ``` -To choose your Java EE components with fine grain control include them as your dependencies. You can chose any of the -following artifacts: +MicroProfile 1.1 +```xml + + + com.kumuluz.ee + kumuluzee-microProfile-1.1 + +``` + +To choose your Java EE components with fine grain control include them as your dependencies. You can chose any of the following artifacts: ```xml @@ -146,6 +179,12 @@ following artifacts: kumuluzee-jax-rs-jersey + + + com.kumuluz.ee + kumuluzee-jax-ws-metro + + com.kumuluz.ee @@ -163,16 +202,74 @@ following artifacts: com.kumuluz.ee kumuluzee-json-p-jsonp + + + + com.kumuluz.ee + kumuluzee-jta-narayana + ``` -To choose your KumuluzEE extensions include them as your dependencies. You can find the available implementations and -options at their respected project pages: +To choose your KumuluzEE extensions include them as your dependencies. You can find the available implementations and options at their respected project pages. -- [KumuluzEE Logs](https://github.com/kumuluz/kumuluzee-logs) +## Pack and run microservice as Uber JAR + +KumuluzEE (since version 2.4) provides support for packing and running microservices as Uber JARs. It also includes a Maven plugin that correctly packages the microservice. + +To package a Kumuluz EE microservice into an Uber JAR, you need to add the following plugin declaration into your +REST module pom.xml: + +```xml + + com.kumuluz.ee + kumuluzee-maven-plugin + ${kumuluz.version} + + + package + + repackage + + + + + + + + + + +``` + +#### Parameters + +* __finalName__ + + Final name of the generated "uber" JAR. + + __Default value is__: `${project.build.finalName}` or `${project.artifactId}-${project.version}` + +* __outputDirectory__ + + Directory containing the generated JAR. + + __Default value is__: `${project.build.directory}` + + +### Run +Start the application using the following command: +```cmd +java -jar ${project.build.finalName}.jar +``` +Example: +```cmd +java -jar my-app-1.0.0-SNAPSHOT.jar +``` ## Getting started You can find the getting started guide on the projects [wiki](https://github.com/kumuluz/KumuluzEE/wiki/Getting-started). +You can find samples [for Java EE and KumuluzEE]( https://github.com/kumuluz/kumuluzee-samples) ## Building diff --git a/bom/pom.xml b/bom/pom.xml index d81b7ced..03482c5a 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -5,7 +5,7 @@ kumuluzee com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom @@ -22,6 +22,11 @@ kumuluzee-micro-profile ${project.version} + + com.kumuluz.ee + kumuluzee-microProfile-1.1 + ${project.version} + com.kumuluz.ee @@ -88,6 +93,11 @@ kumuluzee-json-p-jsonp ${project.version} + + com.kumuluz.ee + kumuluzee-jta-narayana + ${project.version} + diff --git a/common/pom.xml b/common/pom.xml index ba2de753..ff47b1c3 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -5,7 +5,7 @@ kumuluzee com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -30,7 +30,6 @@ com.zaxxer HikariCP - org.yaml snakeyaml diff --git a/common/src/main/java/com/kumuluz/ee/common/Component.java b/common/src/main/java/com/kumuluz/ee/common/Component.java index de4a49df..14003301 100644 --- a/common/src/main/java/com/kumuluz/ee/common/Component.java +++ b/common/src/main/java/com/kumuluz/ee/common/Component.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common; import com.kumuluz.ee.common.config.EeConfig; diff --git a/common/src/main/java/com/kumuluz/ee/common/ConfigExtension.java b/common/src/main/java/com/kumuluz/ee/common/ConfigExtension.java new file mode 100644 index 00000000..14a6c35e --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/ConfigExtension.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common; + +import com.kumuluz.ee.configuration.ConfigurationSource; + +import java.util.Collections; +import java.util.List; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public interface ConfigExtension extends Extension { + + /** + * @deprecated Use {@link #getConfigurationSources()} instead. + */ + @Deprecated + ConfigurationSource getConfigurationSource(); + + default List getConfigurationSources() { + return Collections.emptyList(); + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/Extension.java b/common/src/main/java/com/kumuluz/ee/common/Extension.java new file mode 100644 index 00000000..80356cb6 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/Extension.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common; + +import com.kumuluz.ee.common.config.EeConfig; +import com.kumuluz.ee.common.wrapper.KumuluzServerWrapper; + +import java.util.List; +import java.util.Optional; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public interface Extension { + + void load(); + + void init(KumuluzServerWrapper server, EeConfig eeConfig); +} diff --git a/common/src/main/java/com/kumuluz/ee/common/KumuluzServer.java b/common/src/main/java/com/kumuluz/ee/common/KumuluzServer.java index 44d8b062..4f5337cd 100644 --- a/common/src/main/java/com/kumuluz/ee/common/KumuluzServer.java +++ b/common/src/main/java/com/kumuluz/ee/common/KumuluzServer.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common; import com.kumuluz.ee.common.config.ServerConfig; diff --git a/common/src/main/java/com/kumuluz/ee/common/LogsExtension.java b/common/src/main/java/com/kumuluz/ee/common/LogsExtension.java new file mode 100644 index 00000000..e1a5578b --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/LogsExtension.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common; + +import java.util.Optional; +import java.util.logging.Handler; +import java.util.logging.LogManager; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public interface LogsExtension extends Extension { + + Optional> getJavaUtilLogManagerClass(); + + Optional getJavaUtilLogHandler(); +} diff --git a/common/src/main/java/com/kumuluz/ee/common/ServletServer.java b/common/src/main/java/com/kumuluz/ee/common/ServletServer.java index 3a68d2a4..e9e2dc96 100644 --- a/common/src/main/java/com/kumuluz/ee/common/ServletServer.java +++ b/common/src/main/java/com/kumuluz/ee/common/ServletServer.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common; import javax.servlet.DispatcherType; diff --git a/common/src/main/java/com/kumuluz/ee/common/attributes/ClasspathAttributes.java b/common/src/main/java/com/kumuluz/ee/common/attributes/ClasspathAttributes.java index 7855db89..d3be2e6d 100644 --- a/common/src/main/java/com/kumuluz/ee/common/attributes/ClasspathAttributes.java +++ b/common/src/main/java/com/kumuluz/ee/common/attributes/ClasspathAttributes.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.attributes; /** @@ -6,6 +26,8 @@ */ public class ClasspathAttributes { + public static final String jar = "^((?!lib|/lib).)*$"; + public static final String exploded = ".*/classes/.*"; public static final String exploded_test = ".*/test-classes/.*"; diff --git a/common/src/main/java/com/kumuluz/ee/common/config/DataSourceConfig.java b/common/src/main/java/com/kumuluz/ee/common/config/DataSourceConfig.java index 7521b753..ebd9b2fb 100644 --- a/common/src/main/java/com/kumuluz/ee/common/config/DataSourceConfig.java +++ b/common/src/main/java/com/kumuluz/ee/common/config/DataSourceConfig.java @@ -1,64 +1,168 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.config; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + /** * @author Tilen Faganel * @since 2.1.0 */ public class DataSourceConfig { + public static class Builder { + + private String jndiName; + private String driverClass; + private String dataSourceClass; + private String connectionUrl; + private String username; + private String password; + + private DataSourcePoolConfig.Builder pool = new DataSourcePoolConfig.Builder(); + + private Map props = new HashMap<>(); + + @Deprecated + private Integer maxPoolSize; + + public Builder jndiName(String jndiName) { + this.jndiName = jndiName; + return this; + } + + public Builder driverClass(String driverClass) { + this.driverClass = driverClass; + return this; + } + + public Builder dataSourceClass(String dataSourceClass) { + this.dataSourceClass = dataSourceClass; + return this; + } + + public Builder connectionUrl(String connectionUrl) { + this.connectionUrl = connectionUrl; + return this; + } + + public Builder username(String username) { + this.username = username; + return this; + } + + public Builder password(String password) { + this.password = password; + return this; + } + + public Builder pool(DataSourcePoolConfig.Builder pool) { + this.pool = pool; + return this; + } + + public Builder prop(String key, String value) { + this.props.put(key, value); + return this; + } + + @Deprecated + public Builder maxPoolSize(Integer maxPoolSize) { + this.maxPoolSize = maxPoolSize; + return this; + } + + public DataSourceConfig build() { + + DataSourceConfig dataSourceConfig = new DataSourceConfig(); + dataSourceConfig.jndiName = jndiName; + dataSourceConfig.driverClass = driverClass; + dataSourceConfig.dataSourceClass = dataSourceClass; + dataSourceConfig.connectionUrl = connectionUrl; + dataSourceConfig.username = username; + dataSourceConfig.password = password; + + dataSourceConfig.pool = pool.build(); + + dataSourceConfig.props = Collections.unmodifiableMap(props); + + dataSourceConfig.maxPoolSize = maxPoolSize; + + return dataSourceConfig; + } + } + private String jndiName; private String driverClass; + private String dataSourceClass; private String connectionUrl; private String username; private String password; + private DataSourcePoolConfig pool; + + private Map props; + + @Deprecated private Integer maxPoolSize; - public String getJndiName() { - return jndiName; + private DataSourceConfig() { } - public void setJndiName(String jndiName) { - this.jndiName = jndiName; + public String getJndiName() { + return jndiName; } public String getDriverClass() { return driverClass; } - public void setDriverClass(String driverClass) { - this.driverClass = driverClass; + public String getDataSourceClass() { + return dataSourceClass; } public String getConnectionUrl() { return connectionUrl; } - public void setConnectionUrl(String connectionUrl) { - this.connectionUrl = connectionUrl; - } - public String getUsername() { return username; } - public void setUsername(String username) { - this.username = username; - } - public String getPassword() { return password; } - public void setPassword(String password) { - this.password = password; + public DataSourcePoolConfig getPool() { + return pool; } - public Integer getMaxPoolSize() { - return maxPoolSize; + public Map getProps() { + return props; } - public void setMaxPoolSize(Integer maxPoolSize) { - this.maxPoolSize = maxPoolSize; + @Deprecated + public Integer getMaxPoolSize() { + return maxPoolSize; } } diff --git a/common/src/main/java/com/kumuluz/ee/common/config/DataSourcePoolConfig.java b/common/src/main/java/com/kumuluz/ee/common/config/DataSourcePoolConfig.java new file mode 100644 index 00000000..5ef2ccaf --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/config/DataSourcePoolConfig.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.config; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class DataSourcePoolConfig { + + public static class Builder { + + private Boolean autoCommit = true; + private Long connectionTimeout = 30000L; + private Long idleTimeout = 600000L; + private Long maxLifetime = 1800000L; + private Integer minIdle; + private Integer maxSize = 10; + private String name; + private Long initializationFailTimeout = 1L; + private Boolean isolateInternalQueries = false; + private Boolean allowPoolSuspension = false; + private Boolean readOnly = false; + private Boolean registerMbeans = false; + private String connectionInitSql; + private String transactionIsolation; + private Long validationTimeout = 5000L; + private Long leakDetectionThreshold = 0L; + + public Builder autoCommit(Boolean autoCommit) { + this.autoCommit = autoCommit; + return this; + } + + public Builder connectionTimeout(Long connectionTimeout) { + this.connectionTimeout = connectionTimeout; + return this; + } + + public Builder idleTimeout(Long idleTimeout) { + this.idleTimeout = idleTimeout; + return this; + } + + public Builder maxLifetime(Long maxLifetime) { + this.maxLifetime = maxLifetime; + return this; + } + + public Builder minIdle(Integer minIdle) { + this.minIdle = minIdle; + return this; + } + + public Builder maxSize(Integer maxSize) { + this.maxSize = maxSize; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder initializationFailTimeout(Long initializationFailTimeout) { + this.initializationFailTimeout = initializationFailTimeout; + return this; + } + + public Builder isolateInternalQueries(Boolean isolateInternalQueries) { + this.isolateInternalQueries = isolateInternalQueries; + return this; + } + + public Builder allowPoolSuspension(Boolean allowPoolSuspension) { + this.allowPoolSuspension = allowPoolSuspension; + return this; + } + + public Builder readOnly(Boolean readOnly) { + this.readOnly = readOnly; + return this; + } + + public Builder registerMbeans(Boolean registerMbeans) { + this.registerMbeans = registerMbeans; + return this; + } + + public Builder connectionInitSql(String connectionInitSql) { + this.connectionInitSql = connectionInitSql; + return this; + } + + public Builder transactionIsolation(String transactionIsolation) { + this.transactionIsolation = transactionIsolation; + return this; + } + + public Builder validationTimeout(Long validationTimeout) { + this.validationTimeout = validationTimeout; + return this; + } + + public Builder leakDetectionThreshold(Long leakDetectionThreshold) { + this.leakDetectionThreshold = leakDetectionThreshold; + return this; + } + + public DataSourcePoolConfig build() { + + DataSourcePoolConfig dataSourcePoolConfig = new DataSourcePoolConfig(); + dataSourcePoolConfig.autoCommit = autoCommit; + dataSourcePoolConfig.connectionTimeout = connectionTimeout; + dataSourcePoolConfig.idleTimeout = idleTimeout; + dataSourcePoolConfig.maxLifetime = maxLifetime; + dataSourcePoolConfig.minIdle = minIdle; + dataSourcePoolConfig.maxSize = maxSize; + dataSourcePoolConfig.name = name; + dataSourcePoolConfig.initializationFailTimeout = initializationFailTimeout; + dataSourcePoolConfig.isolateInternalQueries = isolateInternalQueries; + dataSourcePoolConfig.allowPoolSuspension = allowPoolSuspension; + dataSourcePoolConfig.readOnly = readOnly; + dataSourcePoolConfig.registerMbeans = registerMbeans; + dataSourcePoolConfig.connectionInitSql = connectionInitSql; + dataSourcePoolConfig.transactionIsolation = transactionIsolation; + dataSourcePoolConfig.validationTimeout = validationTimeout; + dataSourcePoolConfig.leakDetectionThreshold = leakDetectionThreshold; + + return dataSourcePoolConfig; + } + } + + private Boolean autoCommit; + private Long connectionTimeout; + private Long idleTimeout; + private Long maxLifetime; + private Integer minIdle; + private Integer maxSize; + private String name; + private Long initializationFailTimeout; + private Boolean isolateInternalQueries; + private Boolean allowPoolSuspension; + private Boolean readOnly; + private Boolean registerMbeans; + private String connectionInitSql; + private String transactionIsolation; + private Long validationTimeout; + private Long leakDetectionThreshold; + + private DataSourcePoolConfig() { + } + + public Boolean getAutoCommit() { + return autoCommit; + } + + public Long getConnectionTimeout() { + return connectionTimeout; + } + + public Long getIdleTimeout() { + return idleTimeout; + } + + public Long getMaxLifetime() { + return maxLifetime; + } + + public Integer getMinIdle() { + return minIdle; + } + + public Integer getMaxSize() { + return maxSize; + } + + public String getName() { + return name; + } + + public Long getInitializationFailTimeout() { + return initializationFailTimeout; + } + + public Boolean getIsolateInternalQueries() { + return isolateInternalQueries; + } + + public Boolean getAllowPoolSuspension() { + return allowPoolSuspension; + } + + public Boolean getReadOnly() { + return readOnly; + } + + public Boolean getRegisterMbeans() { + return registerMbeans; + } + + public String getConnectionInitSql() { + return connectionInitSql; + } + + public String getTransactionIsolation() { + return transactionIsolation; + } + + public Long getValidationTimeout() { + return validationTimeout; + } + + public Long getLeakDetectionThreshold() { + return leakDetectionThreshold; + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/config/DevConfig.java b/common/src/main/java/com/kumuluz/ee/common/config/DevConfig.java new file mode 100644 index 00000000..26b009f2 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/config/DevConfig.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.config; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class DevConfig { + + public static class Builder { + + private String webappDir; + + public Builder webappDir(String webappDir) { + this.webappDir = webappDir; + return this; + } + + public DevConfig build() { + + DevConfig devConfig = new DevConfig(); + devConfig.webappDir = webappDir; + + return devConfig; + } + } + + private String webappDir; + + private DevConfig() { + } + + public String getWebappDir() { + return webappDir; + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/config/EeConfig.java b/common/src/main/java/com/kumuluz/ee/common/config/EeConfig.java index c3d19f19..078ddbae 100644 --- a/common/src/main/java/com/kumuluz/ee/common/config/EeConfig.java +++ b/common/src/main/java/com/kumuluz/ee/common/config/EeConfig.java @@ -1,8 +1,27 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.config; -import com.kumuluz.ee.configuration.utils.ConfigurationUtil; - import java.util.*; +import java.util.stream.Collectors; /** * @author Tilen Faganel @@ -10,68 +29,158 @@ */ public class EeConfig { - private String version; + public static class Builder { - private ServerConfig serverConfig = new ServerConfig(); - private List persistenceConfigs = new ArrayList<>(); - private List datasources = new ArrayList<>(); + private String name; + private String version = "1.0.0"; + private Boolean debug = false; - public EeConfig() { - this.version = ResourceBundle.getBundle("version").getString("version"); + private EnvConfig.Builder env = new EnvConfig.Builder(); + private DevConfig.Builder dev = new DevConfig.Builder(); + private ServerConfig.Builder server = new ServerConfig.Builder(); + private List datasources = new ArrayList<>(); + private List xaDatasources = new ArrayList<>(); - persistenceConfigs.add(new PersistenceConfig()); + private PersistenceConfig.Builder persistenceConfig = new PersistenceConfig.Builder(); - ConfigurationUtil cfg = ConfigurationUtil.getInstance(); + public Builder name(String name) { + this.name = name; + return this; + } - Optional dsSizeOpt = cfg.getListSize("kumuluzee.datasources"); + public Builder version(String version) { + this.version = version; + return this; + } - if (dsSizeOpt.isPresent()) { - Integer dsSize = dsSizeOpt.get(); + public Builder debug(Boolean debug) { + this.debug = debug; + return this; + } - for (int i = 0; i < dsSize; i++) { + public Builder env(EnvConfig.Builder env) { + this.env = env; + return this; + } - DataSourceConfig dsc = new DataSourceConfig(); + public Builder dev(DevConfig.Builder dev) { + this.dev = dev; + return this; + } - Optional jndiName = cfg.get("kumuluzee.datasources[" + i + "].jndi-name"); - Optional driverClass = cfg.get("kumuluzee.datasources[" + i + "].driver-class"); - Optional conUrl = cfg.get("kumuluzee.datasources[" + i + "].connection-url"); - Optional user = cfg.get("kumuluzee.datasources[" + i + "].username"); - Optional pass = cfg.get("kumuluzee.datasources[" + i + "].password"); - Optional maxPool = cfg.getInteger("kumuluzee.datasources[" + i + "].max-pool-size"); + public Builder server(ServerConfig.Builder server) { + this.server = server; + return this; + } - jndiName.ifPresent(dsc::setJndiName); - driverClass.ifPresent(dsc::setDriverClass); - conUrl.ifPresent(dsc::setConnectionUrl); - user.ifPresent(dsc::setUsername); - pass.ifPresent(dsc::setPassword); - maxPool.ifPresent(dsc::setMaxPoolSize); + public Builder datasource(DataSourceConfig.Builder datasource) { + this.datasources.add(datasource); + return this; + } + + public Builder xaDatasource(XaDataSourceConfig.Builder xaDatasource) { + this.xaDatasources.add(xaDatasource); + return this; + } - datasources.add(dsc); - } + public Builder persistenceConfig(PersistenceConfig.Builder persistenceConfig) { + this.persistenceConfig = persistenceConfig; + return this; + } + + public EeConfig build() { + + List constructedDatasources = + datasources.stream().map(DataSourceConfig.Builder::build).collect(Collectors.toList()); + + List constructedXaDatasources = + xaDatasources.stream().map(XaDataSourceConfig.Builder::build).collect(Collectors.toList()); + + EeConfig eeConfig = new EeConfig(); + eeConfig.name = name; + eeConfig.version = version; + eeConfig.debug = debug; + eeConfig.env = env.build(); + eeConfig.dev = dev.build(); + eeConfig.server = server.build(); + eeConfig.datasources = Collections.unmodifiableList(constructedDatasources); + eeConfig.xaDatasources = Collections.unmodifiableList(constructedXaDatasources); + + eeConfig.persistenceConfig = persistenceConfig.build(); + + return eeConfig; } } + private static EeConfig instance; + + private String name; + private String version; + private Boolean debug; + + private EnvConfig env; + private DevConfig dev; + private ServerConfig server; + private List datasources; + private List xaDatasources; + + private PersistenceConfig persistenceConfig; + + private EeConfig() { + } + + public static void initialize(EeConfig eeConfig) { + + if (instance != null) { + throw new IllegalStateException("The EeConfig was already initialized."); + } + + instance = eeConfig; + } + + public static EeConfig getInstance() { + + if (instance == null) { + throw new IllegalStateException("The EeConfig was not yet initialized."); + } + + return instance; + } + + public String getName() { + return name; + } + public String getVersion() { return version; } - public void setVersion(String version) { - this.version = version; + public Boolean getDebug() { + return debug; } - public ServerConfig getServerConfig() { - return serverConfig; + public EnvConfig getEnv() { + return env; } - public void setServerConfig(ServerConfig serverConfig) { - this.serverConfig = serverConfig; + public DevConfig getDev() { + return dev; } - public List getPersistenceConfigs() { - return persistenceConfigs; + public ServerConfig getServer() { + return server; } public List getDatasources() { return datasources; } + + public List getXaDatasources() { + return xaDatasources; + } + + @Deprecated + public PersistenceConfig getPersistenceConfig() { + return persistenceConfig; + } } diff --git a/common/src/main/java/com/kumuluz/ee/common/config/EnvConfig.java b/common/src/main/java/com/kumuluz/ee/common/config/EnvConfig.java new file mode 100644 index 00000000..20b28051 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/config/EnvConfig.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.config; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class EnvConfig { + + public static class Builder { + + private String name; + + public Builder name(String name) { + this.name = name; + return this; + } + + public EnvConfig build() { + + EnvConfig envConfig = new EnvConfig(); + envConfig.name = name; + + return envConfig; + } + } + + private String name; + + private EnvConfig() { + } + + public String getName() { + return name; + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/config/PersistenceConfig.java b/common/src/main/java/com/kumuluz/ee/common/config/PersistenceConfig.java index 4dea55d1..e97fefe7 100644 --- a/common/src/main/java/com/kumuluz/ee/common/config/PersistenceConfig.java +++ b/common/src/main/java/com/kumuluz/ee/common/config/PersistenceConfig.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.config; import com.kumuluz.ee.common.utils.EnvUtils; @@ -6,61 +26,69 @@ * @author Tilen Faganel * @since 1.0.0 */ +@Deprecated public class PersistenceConfig { - public static final String DB_UNIT_ENV = "DATABASE_UNIT"; + public static class Builder { - public static final String DB_URL_ENV = "DATABASE_URL"; + private String unitName; + private String url; + private String username; + private String password; - public static final String DB_USER_ENV = "DATABASE_USER"; + public Builder unitName(String unitName) { + this.unitName = unitName; + return this; + } - public static final String DB_PASS_ENV = "DATABASE_PASS"; + public Builder url(String url) { + this.url = url; + return this; + } - private String unitName; + public Builder username(String username) { + this.username = username; + return this; + } - private String url; + public Builder password(String password) { + this.password = password; + return this; + } - private String username; + public PersistenceConfig build() { - private String password; + PersistenceConfig persistenceConfig = new PersistenceConfig(); + persistenceConfig.unitName = unitName; + persistenceConfig.url = url; + persistenceConfig.username = username; + persistenceConfig.password = password; - public PersistenceConfig() { + return persistenceConfig; + } + } + + private String unitName; + private String url; + private String username; + private String password; - EnvUtils.getEnv(DB_UNIT_ENV, this::setUnitName); - EnvUtils.getEnv(DB_URL_ENV, this::setUrl); - EnvUtils.getEnv(DB_USER_ENV, this::setUsername); - EnvUtils.getEnv(DB_PASS_ENV, this::setPassword); + private PersistenceConfig() { } public String getUnitName() { return unitName; } - public void setUnitName(String unitName) { - this.unitName = unitName; - } - public String getUrl() { return url; } - public void setUrl(String url) { - this.url = url; - } - public String getUsername() { return username; } - public void setUsername(String username) { - this.username = username; - } - public String getPassword() { return password; } - - public void setPassword(String password) { - this.password = password; - } } diff --git a/common/src/main/java/com/kumuluz/ee/common/config/ServerConfig.java b/common/src/main/java/com/kumuluz/ee/common/config/ServerConfig.java index 3d60839d..aaad41d3 100644 --- a/common/src/main/java/com/kumuluz/ee/common/config/ServerConfig.java +++ b/common/src/main/java/com/kumuluz/ee/common/config/ServerConfig.java @@ -1,112 +1,142 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.config; -import com.kumuluz.ee.common.utils.EnvUtils; - /** * @author Tilen Faganel * @since 1.0.0 */ public class ServerConfig { - public static final String PORT_ENV = "PORT"; - - public static final String MIN_THREADS_ENV = "MIN_THREADS"; + public static class Builder { - public static final String MAX_THREADS_ENV = "MAX_THREADS"; + private String baseUrl; + private String contextPath = "/"; + private Boolean dirBrowsing = false; + private Integer minThreads = 5; + private Integer maxThreads = 100; + private Boolean forceHttps = false; - public static final String REQUEST_HEADER_SIZE = "REQUEST_HEADER_SIZE"; + private ServerConnectorConfig.Builder http = new ServerConnectorConfig.Builder(); + private ServerConnectorConfig.Builder https = new ServerConnectorConfig.Builder(); - public static final String RESPONSE_HEADER_SIZE = "RESPONSE_HEADER_SIZE"; + public Builder baseUrl(String baseUrl) { + this.baseUrl = baseUrl; + return this; + } - public static final String CONTEXT_PATH_ENV = "CONTEXT_PATH"; + public Builder contextPath(String contextPath) { + this.contextPath = contextPath; + return this; + } - private Integer port = 8080; + public Builder dirBrowsing(Boolean dirBrowsing) { + this.dirBrowsing = dirBrowsing; + return this; + } - private String contextPath = "/"; + public Builder minThreads(Integer minThreads) { + this.minThreads = minThreads; + return this; + } - private Integer idleTimeout = 60 * 60 * 1000; + public Builder maxThreads(Integer maxThreads) { + this.maxThreads = maxThreads; + return this; + } - private Integer soLingerTime = -1; + public Builder forceHttps(Boolean forceHttps) { + this.forceHttps = forceHttps; + return this; + } - private Integer minThreads = 5; + public Builder http(ServerConnectorConfig.Builder http) { + this.http = http; + return this; + } - private Integer maxThreads = 100; + public Builder https(ServerConnectorConfig.Builder https) { + this.https = https; + return this; + } - private Integer requestHeaderSize = 8 * 1024; + public ServerConfig build() { - private Integer responseHeaderSize = 8 * 1024; + ServerConfig serverConfig = new ServerConfig(); + serverConfig.baseUrl = baseUrl; + serverConfig.contextPath = contextPath; + serverConfig.dirBrowsing = dirBrowsing; + serverConfig.minThreads = minThreads; + serverConfig.maxThreads = maxThreads; + serverConfig.forceHttps = forceHttps; - public ServerConfig() { + serverConfig.http = http.build(); + serverConfig.https = https.build(); - EnvUtils.getEnvAsInteger(PORT_ENV, this::setPort); - EnvUtils.getEnvAsInteger(MIN_THREADS_ENV, this::setMinThreads); - EnvUtils.getEnvAsInteger(MAX_THREADS_ENV, this::setMaxThreads); - EnvUtils.getEnvAsInteger(REQUEST_HEADER_SIZE, this::setRequestHeaderSize); - EnvUtils.getEnvAsInteger(RESPONSE_HEADER_SIZE, this::setResponseHeaderSize); - EnvUtils.getEnv(CONTEXT_PATH_ENV, this::setContextPath); + return serverConfig; + } } - public Integer getPort() { - return port; - } - - public void setPort(Integer port) { - this.port = port; - } - - public String getContextPath() { - return contextPath; - } + private String baseUrl; + private String contextPath; + private Boolean dirBrowsing; + private Integer minThreads; + private Integer maxThreads; + private Boolean forceHttps; - public void setContextPath(String contextPath) { - this.contextPath = contextPath; - } + private ServerConnectorConfig http; + private ServerConnectorConfig https; - public Integer getIdleTimeout() { - return idleTimeout; + private ServerConfig() { } - public void setIdleTimeout(Integer idleTimeout) { - this.idleTimeout = idleTimeout; + public String getBaseUrl() { + return baseUrl; } - public Integer getSoLingerTime() { - return soLingerTime; + public String getContextPath() { + return contextPath; } - public void setSoLingerTime(Integer soLingerTime) { - this.soLingerTime = soLingerTime; + public Boolean getDirBrowsing() { + return dirBrowsing; } public Integer getMinThreads() { return minThreads; } - public void setMinThreads(Integer minThreads) { - this.minThreads = minThreads; - } - public Integer getMaxThreads() { return maxThreads; } - public void setMaxThreads(Integer maxThreads) { - this.maxThreads = maxThreads; - } - - public Integer getRequestHeaderSize() { - return requestHeaderSize; - } - - public void setRequestHeaderSize(Integer requestHeaderSize) { - this.requestHeaderSize = requestHeaderSize; + public Boolean getForceHttps() { + return forceHttps; } - public Integer getResponseHeaderSize() { - return responseHeaderSize; + public ServerConnectorConfig getHttp() { + return http; } - public void setResponseHeaderSize(Integer responseHeaderSize) { - this.responseHeaderSize = responseHeaderSize; + public ServerConnectorConfig getHttps() { + return https; } } diff --git a/common/src/main/java/com/kumuluz/ee/common/config/ServerConnectorConfig.java b/common/src/main/java/com/kumuluz/ee/common/config/ServerConnectorConfig.java new file mode 100644 index 00000000..1a188c4f --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/config/ServerConnectorConfig.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.config; + +import java.util.Collections; +import java.util.List; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class ServerConnectorConfig { + + public static class Builder { + + public final static Integer DEFAULT_HTTP_PORT = 8080; + public final static Integer DEFAULT_HTTPS_PORT = 8443; + + private Integer port; + private String address; + private Boolean enabled; + private Boolean http2 = false; + private Boolean proxyForwarding = false; + private Integer requestHeaderSize = 8 * 1024; + private Integer responseHeaderSize = 8 * 1024; + private Integer idleTimeout = 60 * 60 * 1000; + private Integer soLingerTime = -1; + + private String keystorePath = System.getProperty("javax.net.ssl.keyStore"); + private String keystorePassword = System.getProperty("javax.net.ssl.keyStorePassword"); + private String keyAlias; + private String keyPassword; + private List sslProtocols; + private List sslCiphers; + + public Builder port(Integer port) { + this.port = port; + return this; + } + + public Builder address(String address) { + this.address = address; + return this; + } + + public Builder enabled(Boolean enabled) { + this.enabled = enabled; + return this; + } + + public Builder http2(Boolean http2) { + this.http2 = http2; + return this; + } + + public Builder proxyForwarding(Boolean proxyForwarding) { + this.proxyForwarding = proxyForwarding; + return this; + } + + public Builder requestHeaderSize(Integer requestHeaderSize) { + this.requestHeaderSize = requestHeaderSize; + return this; + } + + public Builder responseHeaderSize(Integer responseHeaderSize) { + this.responseHeaderSize = responseHeaderSize; + return this; + } + + public Builder idleTimeout(Integer idleTimeout) { + this.idleTimeout = idleTimeout; + return this; + } + + public Builder soLingerTime(Integer soLingerTime) { + this.soLingerTime = soLingerTime; + return this; + } + + public Builder keystorePath(String keystorePath) { + this.keystorePath = keystorePath; + return this; + } + + public Builder keystorePassword(String keystorePassword) { + this.keystorePassword = keystorePassword; + return this; + } + + public Builder keyAlias(String keyAlias) { + this.keyAlias = keyAlias; + return this; + } + + public Builder keyPassword(String keyPassword) { + this.keyPassword = keyPassword; + return this; + } + + public Builder sslProtocols(List sslProtocols) { + this.sslProtocols = Collections.unmodifiableList(sslProtocols); + return this; + } + + public Builder sslCiphers(List sslCiphers) { + this.sslCiphers = Collections.unmodifiableList(sslCiphers); + return this; + } + + public ServerConnectorConfig build() { + + ServerConnectorConfig serverConnectorConfig = new ServerConnectorConfig(); + serverConnectorConfig.port = port; + serverConnectorConfig.address = address; + serverConnectorConfig.enabled = enabled; + serverConnectorConfig.http2 = http2; + serverConnectorConfig.proxyForwarding = proxyForwarding; + serverConnectorConfig.requestHeaderSize = requestHeaderSize; + serverConnectorConfig.responseHeaderSize = responseHeaderSize; + serverConnectorConfig.idleTimeout = idleTimeout; + serverConnectorConfig.soLingerTime = soLingerTime; + serverConnectorConfig.keystorePath = keystorePath; + serverConnectorConfig.keystorePassword = keystorePassword; + serverConnectorConfig.keyAlias = keyAlias; + serverConnectorConfig.keyPassword = keyPassword; + serverConnectorConfig.sslProtocols = sslProtocols; + serverConnectorConfig.sslCiphers = sslCiphers; + + return serverConnectorConfig; + } + } + + private Integer port; + private String address; + private Boolean enabled; + private Boolean http2; + private Boolean proxyForwarding; + private Integer requestHeaderSize; + private Integer responseHeaderSize; + private Integer idleTimeout; + private Integer soLingerTime; + + private String keystorePath; + private String keystorePassword; + private String keyAlias; + private String keyPassword; + private List sslProtocols; + private List sslCiphers; + + private ServerConnectorConfig() { + } + + public Integer getPort() { + return port; + } + + public String getAddress() { + return address; + } + + public Boolean getEnabled() { + return enabled; + } + + public Boolean getHttp2() { + return http2; + } + + public Boolean getProxyForwarding() { + return proxyForwarding; + } + + public Integer getRequestHeaderSize() { + return requestHeaderSize; + } + + public Integer getResponseHeaderSize() { + return responseHeaderSize; + } + + public Integer getIdleTimeout() { + return idleTimeout; + } + + public Integer getSoLingerTime() { + return soLingerTime; + } + + public String getKeystorePath() { + return keystorePath; + } + + public String getKeystorePassword() { + return keystorePassword; + } + + public String getKeyAlias() { + return keyAlias; + } + + public String getKeyPassword() { + return keyPassword; + } + + public List getSslProtocols() { + return sslProtocols; + } + + public List getSslCiphers() { + return sslCiphers; + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/config/XaDataSourceConfig.java b/common/src/main/java/com/kumuluz/ee/common/config/XaDataSourceConfig.java new file mode 100644 index 00000000..be25cd4e --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/config/XaDataSourceConfig.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.config; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public class XaDataSourceConfig { + + public static class Builder { + + private String jndiName; + private String xaDatasourceClass; + private String username; + private String password; + + private Map props = new HashMap<>(); + + public Builder jndiName(String jndiName) { + this.jndiName = jndiName; + return this; + } + + public Builder xaDatasourceClass(String xaDatasourceClass) { + this.xaDatasourceClass = xaDatasourceClass; + return this; + } + + public Builder username(String username) { + this.username = username; + return this; + } + + public Builder password(String password) { + this.password = password; + return this; + } + + public Builder prop(String key, String value) { + this.props.put(key, value); + return this; + } + + public XaDataSourceConfig build() { + + XaDataSourceConfig xaDataSourceConfig = new XaDataSourceConfig(); + xaDataSourceConfig.jndiName = jndiName; + xaDataSourceConfig.xaDatasourceClass = xaDatasourceClass; + xaDataSourceConfig.username = username; + xaDataSourceConfig.password = password; + + xaDataSourceConfig.props = Collections.unmodifiableMap(props); + + return xaDataSourceConfig; + } + } + + private String jndiName; + private String xaDatasourceClass; + private String username; + private String password; + + private Map props; + + private XaDataSourceConfig() { + } + + public String getJndiName() { + return jndiName; + } + + public String getXaDatasourceClass() { + return xaDatasourceClass; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public Map getProps() { + return props; + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/datasources/NonJtaXAConnectionWrapper.java b/common/src/main/java/com/kumuluz/ee/common/datasources/NonJtaXAConnectionWrapper.java new file mode 100644 index 00000000..44c91c5a --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/datasources/NonJtaXAConnectionWrapper.java @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.datasources; + +import javax.sql.XAConnection; +import java.sql.*; +import java.util.Collections; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public class NonJtaXAConnectionWrapper implements Connection { + + private Boolean isClosed = false; + + private XAConnection xaConnection; + + public NonJtaXAConnectionWrapper(XAConnection xaConnection) { + this.xaConnection = xaConnection; + } + + @Override + public Statement createStatement() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().createStatement(); + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().prepareStatement(sql); + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().prepareCall(sql); + } + + @Override + public String nativeSQL(String sql) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().nativeSQL(sql); + } + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().setAutoCommit(autoCommit); + } + + @Override + public boolean getAutoCommit() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().getAutoCommit(); + } + + @Override + public void commit() throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().commit(); + } + + @Override + public void rollback() throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().rollback(); + } + + @Override + public void close() throws SQLException { + + if (isClosed) return; + + isClosed = true; + + if (xaConnection != null) { + + xaConnection.close(); + xaConnection = null; + } + } + + @Override + public boolean isClosed() throws SQLException { + + return isClosed; + } + + @Override + public DatabaseMetaData getMetaData() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().getMetaData(); + } + + @Override + public void setReadOnly(boolean readOnly) throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().setReadOnly(readOnly); + } + + @Override + public boolean isReadOnly() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().isReadOnly(); + } + + @Override + public void setCatalog(String catalog) throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().setCatalog(catalog); + } + + @Override + public String getCatalog() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().getCatalog(); + } + + @Override + public void setTransactionIsolation(int level) throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().setTransactionIsolation(level); + } + + @Override + public int getTransactionIsolation() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().getTransactionIsolation(); + } + + @Override + public SQLWarning getWarnings() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().getWarnings(); + } + + @Override + public void clearWarnings() throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().clearWarnings(); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().createStatement(resultSetType, resultSetConcurrency); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().prepareStatement(sql, resultSetType, resultSetConcurrency); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().prepareCall(sql, resultSetType, resultSetConcurrency); + } + + @Override + public Map> getTypeMap() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().getTypeMap(); + } + + @Override + public void setTypeMap(Map> map) throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().setTypeMap(map); + } + + @Override + public void setHoldability(int holdability) throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().setHoldability(holdability); + } + + @Override + public int getHoldability() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().getHoldability(); + } + + @Override + public Savepoint setSavepoint() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().setSavepoint(); + } + + @Override + public Savepoint setSavepoint(String name) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().setSavepoint(name); + } + + @Override + public void rollback(Savepoint savepoint) throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().rollback(); + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().releaseSavepoint(savepoint); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().prepareStatement(sql, autoGeneratedKeys); + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().prepareStatement(sql, columnIndexes); + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().prepareStatement(sql, columnNames); + } + + @Override + public Clob createClob() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().createClob(); + } + + @Override + public Blob createBlob() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().createBlob(); + } + + @Override + public NClob createNClob() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().createNClob(); + } + + @Override + public SQLXML createSQLXML() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().createSQLXML(); + } + + @Override + public boolean isValid(int timeout) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().isValid(timeout); + } + + @Override + public void setClientInfo(String name, String value) throws SQLClientInfoException { + + try { + checkIfValid(); + + xaConnection.getConnection().setClientInfo(name, value); + } catch (SQLException e) { + throw new SQLClientInfoException(Collections.emptyMap(), e); + } + } + + @Override + public void setClientInfo(Properties properties) throws SQLClientInfoException { + + try { + checkIfValid(); + + xaConnection.getConnection().setClientInfo(properties); + } catch (SQLException e) { + throw new SQLClientInfoException(Collections.emptyMap(), e); + } + } + + @Override + public String getClientInfo(String name) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().getClientInfo(name); + } + + @Override + public Properties getClientInfo() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().getClientInfo(); + } + + @Override + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().createArrayOf(typeName, elements); + } + + @Override + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().createStruct(typeName, attributes); + } + + @Override + public void setSchema(String schema) throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().setSchema(schema); + } + + @Override + public String getSchema() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().getSchema(); + } + + @Override + public void abort(Executor executor) throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().abort(executor); + } + + @Override + public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().setNetworkTimeout(executor, milliseconds); + } + + @Override + public int getNetworkTimeout() throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().getNetworkTimeout(); + } + + @Override + public T unwrap(Class iface) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().isWrapperFor(iface); + } + + private void checkIfValid() throws SQLException { + + if (isClosed) throw new SQLException("The connection is closed"); + if (xaConnection == null) throw new SQLException("The connection is invalid"); + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/datasources/NonJtaXADataSourceWrapper.java b/common/src/main/java/com/kumuluz/ee/common/datasources/NonJtaXADataSourceWrapper.java new file mode 100644 index 00000000..d61f0e08 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/datasources/NonJtaXADataSourceWrapper.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.datasources; + +import javax.sql.DataSource; +import javax.sql.XAConnection; +import javax.sql.XADataSource; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.Wrapper; +import java.util.logging.Logger; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public class NonJtaXADataSourceWrapper implements XADataSourceWrapper { + + protected XADataSource xaDataSource; + + public NonJtaXADataSourceWrapper(XADataSource xaDataSource) { + this.xaDataSource = xaDataSource; + } + + @Override + public Connection getConnection() throws SQLException { + + checkIfValid(); + + XAConnection xaConnection = xaDataSource.getXAConnection(); + + return new NonJtaXAConnectionWrapper(xaConnection); + } + + @Override + public Connection getConnection(String username, String password) throws SQLException { + + checkIfValid(); + + XAConnection xaConnection = xaDataSource.getXAConnection(username, password); + + return new NonJtaXAConnectionWrapper(xaConnection); + } + + @Override + public T unwrap(Class iface) throws SQLException { + + if (xaDataSource == null) { + throw new SQLException("The underlying XADataSource is invalid or cannot be found"); + } else if (iface.isInstance(xaDataSource)) { + return iface.cast(xaDataSource); + } else if (xaDataSource instanceof Wrapper) { + return ((java.sql.Wrapper) xaDataSource).unwrap(iface); + } else { + throw new SQLException("The requested interface cannot be unwrapped"); + } + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + + if (xaDataSource == null) { + throw new SQLException("The underlying XADataSource is invalid or cannot be found"); + } else if (iface.isInstance(xaDataSource)) { + return true; + } else if (xaDataSource instanceof Wrapper) { + return ((java.sql.Wrapper) xaDataSource).isWrapperFor(iface); + } + + return false; + } + + @Override + public PrintWriter getLogWriter() throws SQLException { + + checkIfValid(); + + return xaDataSource.getLogWriter(); + } + + @Override + public void setLogWriter(PrintWriter out) throws SQLException { + + checkIfValid(); + + xaDataSource.setLogWriter(out); + } + + @Override + public void setLoginTimeout(int seconds) throws SQLException { + + checkIfValid(); + + xaDataSource.setLoginTimeout(seconds); + } + + @Override + public int getLoginTimeout() throws SQLException { + + checkIfValid(); + + return xaDataSource.getLoginTimeout(); + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + + checkIfValid(); + + return xaDataSource.getParentLogger(); + } + + protected void checkIfValid() { + + if (xaDataSource == null) throw new IllegalStateException("The XADataSource is invalid or cannot be found"); + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/datasources/XADataSourceBuilder.java b/common/src/main/java/com/kumuluz/ee/common/datasources/XADataSourceBuilder.java new file mode 100644 index 00000000..fc31da3f --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/datasources/XADataSourceBuilder.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.datasources; + +import com.kumuluz.ee.common.config.XaDataSourceConfig; +import com.kumuluz.ee.common.exceptions.KumuluzServerException; + +import javax.sql.XADataSource; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public class XADataSourceBuilder { + + private XaDataSourceConfig xaDataSourceConfig; + + public XADataSourceBuilder(XaDataSourceConfig xaDataSourceConfig) { + this.xaDataSourceConfig = xaDataSourceConfig; + } + + public XADataSource constructXaDataSource() { + + if (xaDataSourceConfig == null) { + + throw new KumuluzServerException("The XADataSource configuration object for creating a XADataSource cannot be null."); + } + + if (xaDataSourceConfig.getXaDatasourceClass() == null) { + + throw new KumuluzServerException("The XADataSource class config property 'xa-datasource-class' for creating a XADataSource must be provided."); + } + + XADataSource xaDataSource = createXaDataSourceObject(); + + setProperty(xaDataSource, "user", xaDataSourceConfig.getUsername()); + setProperty(xaDataSource, "password", xaDataSourceConfig.getPassword()); + + xaDataSourceConfig.getProps().forEach((k, v) -> setProperty(xaDataSource, k, v)); + + return xaDataSource; + } + + private XADataSource createXaDataSourceObject() { + + try { + return (XADataSource) Class.forName(xaDataSourceConfig.getXaDatasourceClass()).newInstance(); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | ClassCastException e) { + + String msg = "The XADataSource class '" + xaDataSourceConfig.getXaDatasourceClass() + + "' is either incorrect or is not present in the classpath."; + + throw new KumuluzServerException(msg, e); + } + } + + private void setProperty(Object object, String name, String value) { + + name = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); + + Method[] methods = object.getClass().getMethods(); + + Method matchingMethod = null; + + for (Method method : methods) { + + if (method.getName().equalsIgnoreCase(name) && method.getParameterTypes().length == 1) { + // ignores overloading, just takes the first match it finds. + matchingMethod = method; + break; + } + } + + if (matchingMethod == null) { + + String msg = "The XADataSource configuration property '" + name + "' is either incorrect or doesn't exist."; + + throw new KumuluzServerException(msg); + } + + Class type = matchingMethod.getParameterTypes()[0]; + Object argument = value; + + if (type == Integer.TYPE) { + argument = Integer.valueOf(value); + } + if (type == Boolean.TYPE) { + argument = Boolean.valueOf(value); + } + + try { + matchingMethod.invoke(object, argument); + } catch (IllegalAccessException | InvocationTargetException e) { + + String msg = "The XADataSource configuration property '" + name + "' is either incorrect or doesn't exist."; + + throw new KumuluzServerException(msg, e); + } + } +} diff --git a/common/src/main/java/com/kumuluz/ee/logs/enums/LogLevel.java b/common/src/main/java/com/kumuluz/ee/common/datasources/XADataSourceWrapper.java similarity index 85% rename from common/src/main/java/com/kumuluz/ee/logs/enums/LogLevel.java rename to common/src/main/java/com/kumuluz/ee/common/datasources/XADataSourceWrapper.java index 5ce200d6..f9b78d1a 100644 --- a/common/src/main/java/com/kumuluz/ee/logs/enums/LogLevel.java +++ b/common/src/main/java/com/kumuluz/ee/common/datasources/XADataSourceWrapper.java @@ -18,17 +18,13 @@ * software. See the License for the specific language governing permissions and * limitations under the License. */ +package com.kumuluz.ee.common.datasources; -package com.kumuluz.ee.logs.enums; +import javax.sql.DataSource; /** - * @author Rok Povse - * @author Marko Skrjanec + * @author Tilen Faganel + * @since 2.3.0 */ -public enum LogLevel { - TRACE, - INFO, - DEBUG, - WARN, - ERROR, +public interface XADataSourceWrapper extends DataSource { } diff --git a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentDef.java b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentDef.java index c28377f5..717bc74d 100644 --- a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentDef.java +++ b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentDef.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.dependencies; import java.lang.annotation.ElementType; diff --git a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentDependencies.java b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentDependencies.java index 08b32083..1f4db539 100644 --- a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentDependencies.java +++ b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentDependencies.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.dependencies; import java.lang.annotation.ElementType; diff --git a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentDependency.java b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentDependency.java index 2c43451c..6210d0fd 100644 --- a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentDependency.java +++ b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentDependency.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.dependencies; import java.lang.annotation.*; diff --git a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentOptional.java b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentOptional.java index f6ed4ce8..31417d12 100644 --- a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentOptional.java +++ b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentOptional.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.dependencies; import java.lang.annotation.*; diff --git a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentOptionals.java b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentOptionals.java index 0043952a..e6dd677d 100644 --- a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentOptionals.java +++ b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentOptionals.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.dependencies; import java.lang.annotation.ElementType; diff --git a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentType.java b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentType.java index 7cd2960f..6679d486 100644 --- a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentType.java +++ b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeComponentType.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.dependencies; /** diff --git a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeExtensionDef.java b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeExtensionDef.java new file mode 100644 index 00000000..c38c4f6e --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeExtensionDef.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.dependencies; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface EeExtensionDef { + + String name(); + + String group(); +} diff --git a/common/src/main/java/com/kumuluz/ee/common/dependencies/EeExtensionGroup.java b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeExtensionGroup.java new file mode 100644 index 00000000..f0891a87 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/dependencies/EeExtensionGroup.java @@ -0,0 +1,15 @@ +package com.kumuluz.ee.common.dependencies; + +public class EeExtensionGroup { + + public final static String CONFIG = "config"; + public final static String LOGS = "logs"; + + public final static String DISCOVERY = "discovery"; + public final static String SECURITY = "security"; + public final static String FAULT_TOLERANCE = "fault.tolerance"; + public final static String STREAMING = "streaming"; + public final static String METRICS = "metrics"; + public final static String HEALTH = "health"; + public final static String CORS = "cors"; +} diff --git a/common/src/main/java/com/kumuluz/ee/common/dependencies/ServerDef.java b/common/src/main/java/com/kumuluz/ee/common/dependencies/ServerDef.java index fefea568..5807d2aa 100644 --- a/common/src/main/java/com/kumuluz/ee/common/dependencies/ServerDef.java +++ b/common/src/main/java/com/kumuluz/ee/common/dependencies/ServerDef.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.dependencies; import java.lang.annotation.ElementType; diff --git a/common/src/main/java/com/kumuluz/ee/common/exceptions/ComponentsException.java b/common/src/main/java/com/kumuluz/ee/common/exceptions/ComponentsException.java index 54af6a46..f2be5dab 100644 --- a/common/src/main/java/com/kumuluz/ee/common/exceptions/ComponentsException.java +++ b/common/src/main/java/com/kumuluz/ee/common/exceptions/ComponentsException.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.exceptions; /** diff --git a/common/src/main/java/com/kumuluz/ee/common/exceptions/KumuluzServerException.java b/common/src/main/java/com/kumuluz/ee/common/exceptions/KumuluzServerException.java index 690c3762..a073e3cd 100644 --- a/common/src/main/java/com/kumuluz/ee/common/exceptions/KumuluzServerException.java +++ b/common/src/main/java/com/kumuluz/ee/common/exceptions/KumuluzServerException.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.exceptions; /** diff --git a/common/src/main/java/com/kumuluz/ee/common/filters/PoweredByFilter.java b/common/src/main/java/com/kumuluz/ee/common/filters/PoweredByFilter.java index 0ef33af6..5c5f0ef1 100644 --- a/common/src/main/java/com/kumuluz/ee/common/filters/PoweredByFilter.java +++ b/common/src/main/java/com/kumuluz/ee/common/filters/PoweredByFilter.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.filters; import javax.servlet.*; diff --git a/common/src/main/java/com/kumuluz/ee/common/runtime/EeRuntime.java b/common/src/main/java/com/kumuluz/ee/common/runtime/EeRuntime.java new file mode 100644 index 00000000..55f2feae --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/runtime/EeRuntime.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.runtime; + +import java.util.List; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class EeRuntime { + + private EeRuntimeInternal internalRuntime; + + private static EeRuntime instance; + + protected EeRuntime() { + } + + private EeRuntime(EeRuntimeInternal internalRuntime) { + this.internalRuntime = internalRuntime; + } + + public static void initialize(EeRuntimeInternal runtimeInternal) { + + if (instance != null) { + throw new IllegalStateException("The EeRuntime was already initialized."); + } + + instance = new EeRuntime(runtimeInternal); + } + + public static EeRuntime getInstance() { + + if (instance == null) { + throw new IllegalStateException("The EeRuntime was not yet initialized."); + } + + return instance; + } + + public String getInstanceId() { + return internalRuntime.getInstanceId(); + } + + public String getVersion() { + return internalRuntime.getVersion(); + } + + public List getEeComponents() { + return internalRuntime.getEeComponents(); + } + + public List getEeExtensions() { + return internalRuntime.getEeExtensions(); + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/runtime/EeRuntimeComponent.java b/common/src/main/java/com/kumuluz/ee/common/runtime/EeRuntimeComponent.java new file mode 100644 index 00000000..557ad72a --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/runtime/EeRuntimeComponent.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.runtime; + +import com.kumuluz.ee.common.dependencies.EeComponentType; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class EeRuntimeComponent { + + private EeComponentType type; + private String implementationName; + + public EeRuntimeComponent(EeComponentType type, String implementationName) { + this.type = type; + this.implementationName = implementationName; + } + + public EeComponentType getType() { + return type; + } + + public String getImplementationName() { + return implementationName; + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/runtime/EeRuntimeExtension.java b/common/src/main/java/com/kumuluz/ee/common/runtime/EeRuntimeExtension.java new file mode 100644 index 00000000..cc08b6a2 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/runtime/EeRuntimeExtension.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.runtime; + +/** + * @author Jan Meznarič + * @since 2.5.0 + */ +public class EeRuntimeExtension { + + private String group; + private String implementationName; + + public EeRuntimeExtension(String group, String implementationName) { + this.group = group; + this.implementationName = implementationName; + } + + public String getGroup() { + return group; + } + + public String getImplementationName() { + return implementationName; + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/runtime/EeRuntimeInternal.java b/common/src/main/java/com/kumuluz/ee/common/runtime/EeRuntimeInternal.java new file mode 100644 index 00000000..105ea504 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/runtime/EeRuntimeInternal.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.runtime; + +import java.util.Collections; +import java.util.List; +import java.util.ResourceBundle; +import java.util.UUID; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class EeRuntimeInternal { + + private String instanceId = UUID.randomUUID().toString(); + private String version = ResourceBundle.getBundle("META-INF/kumuluzee/versions").getString("version"); + private List eeComponents = Collections.emptyList(); + private List eeExtensions = Collections.emptyList(); + + public String getInstanceId() { + return instanceId; + } + + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public List getEeComponents() { + return eeComponents; + } + + public void setEeComponents(List eeComponents) { + this.eeComponents = Collections.unmodifiableList(eeComponents); + } + + public List getEeExtensions() { + return eeExtensions; + } + + public void setEeExtensions(List eeExtensions) { + this.eeExtensions = Collections.unmodifiableList(eeExtensions); + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/utils/ClassUtils.java b/common/src/main/java/com/kumuluz/ee/common/utils/ClassUtils.java index 902ab2cd..31f30fa1 100644 --- a/common/src/main/java/com/kumuluz/ee/common/utils/ClassUtils.java +++ b/common/src/main/java/com/kumuluz/ee/common/utils/ClassUtils.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.utils; /** diff --git a/common/src/main/java/com/kumuluz/ee/common/utils/EnvUtils.java b/common/src/main/java/com/kumuluz/ee/common/utils/EnvUtils.java index fdaa2e7b..40c843dc 100644 --- a/common/src/main/java/com/kumuluz/ee/common/utils/EnvUtils.java +++ b/common/src/main/java/com/kumuluz/ee/common/utils/EnvUtils.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.utils; import com.kumuluz.ee.common.exceptions.KumuluzServerException; @@ -6,7 +26,8 @@ import java.util.function.Consumer; /** - * @author Tilen + * @author Tilen Faganel + * @since 1.0.0 */ public class EnvUtils { @@ -14,7 +35,7 @@ public static void getEnv(String var, Consumer consumer) { Optional.ofNullable(System.getenv(var)) .filter(s -> !s.isEmpty()) - .ifPresent(consumer::accept); + .ifPresent(consumer); } public static void getEnvAsInteger(String var, Consumer consumer) { diff --git a/common/src/main/java/com/kumuluz/ee/common/utils/ResourceUtils.java b/common/src/main/java/com/kumuluz/ee/common/utils/ResourceUtils.java index 757197fe..70d4b221 100644 --- a/common/src/main/java/com/kumuluz/ee/common/utils/ResourceUtils.java +++ b/common/src/main/java/com/kumuluz/ee/common/utils/ResourceUtils.java @@ -1,6 +1,35 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.utils; +import com.kumuluz.ee.common.config.DevConfig; +import com.kumuluz.ee.common.config.EeConfig; +import com.kumuluz.ee.common.exceptions.KumuluzServerException; + +import java.io.IOException; +import java.net.URISyntaxException; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; /** * @author Tilen Faganel @@ -10,24 +39,71 @@ public class ResourceUtils { public static String getProjectWebResources() { - URL webapp = ResourceUtils.class.getClassLoader().getResource("webapp"); + // First check the `webapp` directory in the compiled resources + URL webApp = ResourceUtils.class.getClassLoader().getResource("webapp"); + + if (webApp != null) { + + return webApp.toString(); + } + + // Next check if running inside an IDE and try to find the `src/main/webapp` dir + URL resourceRoot = ResourceUtils.class.getClassLoader().getResource("."); + + if (resourceRoot != null) { + + try { + + Path resourceRootPath = Paths.get(resourceRoot.toURI()); + + // If running with maven + if (Files.isDirectory(resourceRootPath) && resourceRootPath.getFileName().toString().equals("classes") + && resourceRootPath.getParent() != null && resourceRootPath.getParent().getFileName().toString().equals("target")) { + + DevConfig devConfig = EeConfig.getInstance().getDev(); - if (webapp != null) { + Path sibling = devConfig.getWebappDir() == null ? + Paths.get( "src", "main", "webapp") : + Paths.get(devConfig.getWebappDir()); - return webapp.toString(); + Path sourceWebApp = resourceRootPath.getParent().resolveSibling(sibling); + + if (Files.isDirectory(sourceWebApp)) { + + return sourceWebApp.toString(); + } + } + } catch (URISyntaxException e) { + + throw new KumuluzServerException("Could not retrieve the class loaders' resource dir.", e); + } } - return null; + // Finally if nothing is found, create a temp directory and delete it on shutdown + try { + + final Path tempWebApp = Files.createTempDirectory("kumuluzee-tmp-webapp"); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + + try { + Files.delete(tempWebApp); + } catch (IOException ignored) { + } + })); + + return tempWebApp.toString(); + } catch (IOException e) { + + throw new KumuluzServerException("Could not initialize a temporary webapp directory.", e); + } } public static boolean isRunningInJar() { URL jar = ResourceUtils.class.getClassLoader().getResource("webapp"); - if (jar == null) - throw new IllegalStateException("Base resource folder does not exists. Please check " + - "your project configuration and make sure you are using maven"); - - return jar.toString().toLowerCase().startsWith("jar:"); + return (jar == null || jar.toString().toLowerCase().startsWith("jar:")) + && ResourceUtils.class.getClassLoader().getClass().getName().equals("com.kumuluz.ee.loader.EeClassLoader"); } } diff --git a/common/src/main/java/com/kumuluz/ee/common/utils/StringUtils.java b/common/src/main/java/com/kumuluz/ee/common/utils/StringUtils.java new file mode 100644 index 00000000..49b86b96 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/utils/StringUtils.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.common.utils; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public class StringUtils { + + /** + * Parse upper camel case to lower hyphen case. + * + * @param s string in upper camel case format + * @return string in lower hyphen case format + */ + public static String camelCaseToHyphenCase(String s) { + + StringBuilder parsedString = new StringBuilder(s.substring(0, 1).toLowerCase()); + + for (char c : s.substring(1).toCharArray()) { + + if (Character.isUpperCase(c)) { + parsedString.append("-").append(Character.toLowerCase(c)); + } else { + parsedString.append(c); + } + } + + return parsedString.toString(); + } + + /** + * Parse lower hyphen case to upper camel case. + * + * @param s string in lower hyphen case format + * @return string in upper camel case format + */ + public static String hyphenCaseToCamelCase(String s) { + + List words = Stream.of(s.split("-")).filter(w -> !"".equals(w)).collect(Collectors.toList()); + + if (words.size() < 2) { + return s; + } + + StringBuilder parsedString = new StringBuilder(words.get(0)); + + for (int i = 1; i < words.size(); i++) { + + parsedString.append(Character.toUpperCase(words.get(i).charAt(0))).append(words.get(i).substring(1)); + } + + return parsedString.toString(); + } + + /** + * Check whether the string is null or empty + * + * @param s string to check. + * @return 'true' if string is null or empty, 'false' otherwise. + */ + public static boolean isNullOrEmpty(String s) { + return s == null || s.isEmpty(); + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/wrapper/ComponentWrapper.java b/common/src/main/java/com/kumuluz/ee/common/wrapper/ComponentWrapper.java index f0a1a8e3..9929b4b1 100644 --- a/common/src/main/java/com/kumuluz/ee/common/wrapper/ComponentWrapper.java +++ b/common/src/main/java/com/kumuluz/ee/common/wrapper/ComponentWrapper.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.wrapper; import com.kumuluz.ee.common.Component; @@ -18,7 +38,6 @@ public class ComponentWrapper { private EeComponentDependency[] dependencies; private EeComponentOptional[] optionalDependencies; - public ComponentWrapper(Component component, String name, EeComponentDependency[] dependencies, EeComponentOptional[] optionalDependencies) { diff --git a/common/src/main/java/com/kumuluz/ee/common/wrapper/EeComponentWrapper.java b/common/src/main/java/com/kumuluz/ee/common/wrapper/EeComponentWrapper.java index 1272356d..97ca84b7 100644 --- a/common/src/main/java/com/kumuluz/ee/common/wrapper/EeComponentWrapper.java +++ b/common/src/main/java/com/kumuluz/ee/common/wrapper/EeComponentWrapper.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.wrapper; import com.kumuluz.ee.common.Component; diff --git a/common/src/main/java/com/kumuluz/ee/common/wrapper/ExtensionWrapper.java b/common/src/main/java/com/kumuluz/ee/common/wrapper/ExtensionWrapper.java new file mode 100644 index 00000000..771fbc77 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/common/wrapper/ExtensionWrapper.java @@ -0,0 +1,62 @@ +package com.kumuluz.ee.common.wrapper; + +import com.kumuluz.ee.common.Extension; +import com.kumuluz.ee.common.dependencies.EeComponentDependency; +import com.kumuluz.ee.common.dependencies.EeComponentOptional; + +public class ExtensionWrapper { + + private T extension; + private String name; + private String group; + private EeComponentDependency[] dependencies; + private EeComponentOptional[] optionalDependencies; + + public ExtensionWrapper(T extension, String name, String group, EeComponentDependency[] dependencies, EeComponentOptional[] optionalDependencies) { + this.extension = extension; + this.name = name; + this.group = group; + this.dependencies = dependencies; + this.optionalDependencies = optionalDependencies; + } + + public T getExtension() { + return extension; + } + + public void setExtension(T extension) { + this.extension = extension; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public EeComponentDependency[] getDependencies() { + return dependencies; + } + + public void setDependencies(EeComponentDependency[] dependencies) { + this.dependencies = dependencies; + } + + public EeComponentOptional[] getOptionalDependencies() { + return optionalDependencies; + } + + public void setOptionalDependencies(EeComponentOptional[] optionalDependencies) { + this.optionalDependencies = optionalDependencies; + } +} diff --git a/common/src/main/java/com/kumuluz/ee/common/wrapper/KumuluzServerWrapper.java b/common/src/main/java/com/kumuluz/ee/common/wrapper/KumuluzServerWrapper.java index b93e86ed..46cd6c9e 100644 --- a/common/src/main/java/com/kumuluz/ee/common/wrapper/KumuluzServerWrapper.java +++ b/common/src/main/java/com/kumuluz/ee/common/wrapper/KumuluzServerWrapper.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.common.wrapper; import com.kumuluz.ee.common.KumuluzServer; diff --git a/common/src/main/java/com/kumuluz/ee/logs/messages/MethodCallExitLogMessage.java b/common/src/main/java/com/kumuluz/ee/configuration/ConfigurationListener.java similarity index 83% rename from common/src/main/java/com/kumuluz/ee/logs/messages/MethodCallExitLogMessage.java rename to common/src/main/java/com/kumuluz/ee/configuration/ConfigurationListener.java index a975f065..86d2895b 100644 --- a/common/src/main/java/com/kumuluz/ee/logs/messages/MethodCallExitLogMessage.java +++ b/common/src/main/java/com/kumuluz/ee/configuration/ConfigurationListener.java @@ -18,12 +18,14 @@ * software. See the License for the specific language governing permissions and * limitations under the License. */ - -package com.kumuluz.ee.logs.messages; +package com.kumuluz.ee.configuration; /** - * @author Rok Povse - * @author Marko Skrjanec + * @author Tilen Faganel + * @since 2.3.0 */ -public interface MethodCallExitLogMessage extends LogMessage { +@FunctionalInterface +public interface ConfigurationListener { + + void onChange(String key, String value); } diff --git a/common/src/main/java/com/kumuluz/ee/configuration/ConfigurationSource.java b/common/src/main/java/com/kumuluz/ee/configuration/ConfigurationSource.java index cb5641a4..5d574360 100644 --- a/common/src/main/java/com/kumuluz/ee/configuration/ConfigurationSource.java +++ b/common/src/main/java/com/kumuluz/ee/configuration/ConfigurationSource.java @@ -1,5 +1,28 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.configuration; +import com.kumuluz.ee.configuration.utils.ConfigurationDispatcher; + +import java.util.List; import java.util.Optional; /** @@ -8,7 +31,9 @@ */ public interface ConfigurationSource { - void init(); + String CONFIG_ORDINAL = "config_ordinal"; + + void init(ConfigurationDispatcher configurationDispatcher); Optional get(String key); @@ -16,12 +41,18 @@ public interface ConfigurationSource { Optional getInteger(String key); + Optional getLong(String key); + Optional getDouble(String key); Optional getFloat(String key); Optional getListSize(String key); + Optional> getMapKeys(String key); + + void watch(String key); + void set(String key, String value); void set(String key, Boolean value); @@ -31,4 +62,8 @@ public interface ConfigurationSource { void set(String key, Double value); void set(String key, Float value); + + default Integer getOrdinal() { + return getInteger(CONFIG_ORDINAL).orElse(100); + } } diff --git a/common/src/main/java/com/kumuluz/ee/logs/markers/Marker.java b/common/src/main/java/com/kumuluz/ee/configuration/enums/ConfigurationValueType.java similarity index 82% rename from common/src/main/java/com/kumuluz/ee/logs/markers/Marker.java rename to common/src/main/java/com/kumuluz/ee/configuration/enums/ConfigurationValueType.java index 4e4ccef8..b24ec414 100644 --- a/common/src/main/java/com/kumuluz/ee/logs/markers/Marker.java +++ b/common/src/main/java/com/kumuluz/ee/configuration/enums/ConfigurationValueType.java @@ -18,15 +18,19 @@ * software. See the License for the specific language governing permissions and * limitations under the License. */ - -package com.kumuluz.ee.logs.markers; +package com.kumuluz.ee.configuration.enums; /** - * Kumuluz-logs logger interface - * - * @author Rok Povse - * @author Marko Skrjanec + * @author Jan Meznarič + * @since 2.3.0 */ -public interface Marker { - String toString(); +public enum ConfigurationValueType { + STRING, + INTEGER, + LONG, + DOUBLE, + FLOAT, + BOOLEAN, + LIST, + MAP } diff --git a/common/src/main/java/com/kumuluz/ee/configuration/sources/EnvironmentConfigurationSource.java b/common/src/main/java/com/kumuluz/ee/configuration/sources/EnvironmentConfigurationSource.java index aafcbc2c..8992a8d0 100644 --- a/common/src/main/java/com/kumuluz/ee/configuration/sources/EnvironmentConfigurationSource.java +++ b/common/src/main/java/com/kumuluz/ee/configuration/sources/EnvironmentConfigurationSource.java @@ -1,8 +1,29 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.configuration.sources; import com.kumuluz.ee.configuration.ConfigurationSource; +import com.kumuluz.ee.configuration.utils.ConfigurationDispatcher; -import java.util.Optional; +import java.util.*; import java.util.logging.Logger; /** @@ -11,24 +32,19 @@ */ public class EnvironmentConfigurationSource implements ConfigurationSource { - private static final Logger log = Logger.getLogger(EnvironmentConfigurationSource.class.getName()); - private static EnvironmentConfigurationSource instance; - - public static EnvironmentConfigurationSource getInstance() { - if (instance == null) { - instance = new EnvironmentConfigurationSource(); - } - return instance; - } - @Override - public void init() { + public void init(ConfigurationDispatcher configurationDispatcher) { } @Override public Optional get(String key) { String value = System.getenv(parseKeyNameForEnvironmentVariables(key)); + + if (value == null) { + value = System.getenv(parseKeyNameForEnvironmentVariablesLegacy(key)); + } + return (value == null) ? Optional.empty() : Optional.of(value); } @@ -37,21 +53,33 @@ public Optional getBoolean(String key) { Optional value = get(key); + return value.map(Boolean::valueOf); + } + + @Override + public Optional getInteger(String key) { + + Optional value = get(key); + if (value.isPresent()) { - return Optional.of(Boolean.valueOf(value.get())); + try { + return Optional.of(Integer.valueOf(value.get())); + } catch (NumberFormatException e) { + return Optional.empty(); + } } else { return Optional.empty(); } } @Override - public Optional getInteger(String key) { + public Optional getLong(String key) { Optional value = get(key); if (value.isPresent()) { try { - return Optional.of(Integer.valueOf(value.get())); + return Optional.of(Long.valueOf(value.get())); } catch (NumberFormatException e) { return Optional.empty(); } @@ -114,33 +142,48 @@ public Optional getListSize(String key) { } @Override - public void set(String key, String value) { + public Optional> getMapKeys(String key) { + return Optional.empty(); + } + + @Override + public void watch(String key) { + } + @Override + public void set(String key, String value) { } @Override public void set(String key, Boolean value) { - } @Override public void set(String key, Integer value) { - } @Override public void set(String key, Double value) { - } @Override public void set(String key, Float value) { + } + @Override + public Integer getOrdinal() { + return getInteger(CONFIG_ORDINAL).orElse(300); } private String parseKeyNameForEnvironmentVariables(String key) { - return key.toUpperCase().replaceAll("\\.", "_"); + return key.toUpperCase().replaceAll("\\[", "").replaceAll("\\]", "") + .replaceAll("-", "").replaceAll("\\.", "_"); } + + private String parseKeyNameForEnvironmentVariablesLegacy(String key) { + + return key.toUpperCase().replaceAll("\\.", "_"); + } } diff --git a/common/src/main/java/com/kumuluz/ee/configuration/sources/FileConfigurationSource.java b/common/src/main/java/com/kumuluz/ee/configuration/sources/FileConfigurationSource.java index 9c6b24f7..56a122f1 100644 --- a/common/src/main/java/com/kumuluz/ee/configuration/sources/FileConfigurationSource.java +++ b/common/src/main/java/com/kumuluz/ee/configuration/sources/FileConfigurationSource.java @@ -1,14 +1,35 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.configuration.sources; import com.kumuluz.ee.configuration.ConfigurationSource; +import com.kumuluz.ee.configuration.utils.ConfigurationDispatcher; +import com.kumuluz.ee.logs.LogDeferrer; import org.yaml.snakeyaml.Yaml; import java.io.IOException; import java.io.InputStream; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Properties; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; import java.util.logging.Logger; /** @@ -17,30 +38,47 @@ */ public class FileConfigurationSource implements ConfigurationSource { - private static final Logger log = Logger.getLogger(FileConfigurationSource.class.getName()); - private static FileConfigurationSource instance; + private Logger log; + private LogDeferrer logDeferrer; private String ymlFileName; private String yamlFileName; private String propertiesFileName; + private String microProfilePropertiesFileName; private Map config; private Properties properties; public FileConfigurationSource() { + this.ymlFileName = "config.yml"; this.yamlFileName = "config.yaml"; this.propertiesFileName = "config.properties"; - } + this.microProfilePropertiesFileName = "META-INF/microprofile-config.properties"; + + String configurationFileName = System.getProperty("com.kumuluz.ee.configuration.file"); - public static FileConfigurationSource getInstance() { - if (instance == null) { - instance = new FileConfigurationSource(); + if (configurationFileName != null && !configurationFileName.isEmpty()) { + this.ymlFileName = configurationFileName; + this.yamlFileName = configurationFileName; + this.propertiesFileName = configurationFileName; } - return instance; + + this.logDeferrer = new LogDeferrer<>(); + + this.logDeferrer.init(() -> Logger.getLogger(FileConfigurationSource.class.getName())); + } + + public void postInit() { + + logDeferrer.execute(); + logDeferrer = null; + + log = Logger.getLogger(FileConfigurationSource.class.getName()); } @Override - public void init() { + @SuppressWarnings("unchecked") + public void init(ConfigurationDispatcher configurationDispatcher) { // read yaml file to Map InputStream file; @@ -52,48 +90,55 @@ public void init() { file = getClass().getClassLoader().getResourceAsStream(yamlFileName); } + if (file == null) { + try { + file = Files.newInputStream(Paths.get(ymlFileName)); + } catch (IOException ignored) { + } + } + + if (file == null) { + try { + file = Files.newInputStream(Paths.get(yamlFileName)); + } catch (IOException ignored) { + } + } + if (file != null) { - log.info("Loading configuration from YAML file."); + + logDeferrer.defer(l -> l.info("Loading configuration from YAML file.")); Object yamlParsed = yaml.load(file); if (yamlParsed instanceof Map) { config = (Map) yamlParsed; } else { - log.info("Configuration YAML is malformed as it contains an array at the root level. Skipping."); + + logDeferrer.defer(l -> l.info("Configuration YAML is malformed as it contains an array at the " + + "root level. Skipping.")); } file.close(); } } catch (IOException e) { - log.info("Couldn't successfully process the YAML configuration file." + - "All your properties may not be correctly loaded"); + logDeferrer.defer(l -> + l.info("Couldn't successfully process the YAML configuration file." + + "All your properties may not be correctly loaded")); } - // parse yaml file to Map + // parse properties file if (config == null) { - - try { - InputStream inputStream = getClass().getClassLoader().getResourceAsStream(propertiesFileName); - - if (inputStream != null) { - - log.info("Loading configuration from .properties file " + propertiesFileName); - - properties = new Properties(); - properties.load(inputStream); - } - - inputStream.close(); - } catch (Exception e) { - log.info("Properties file not found."); + loadProperties(propertiesFileName); + if (properties == null) { + loadProperties(microProfilePropertiesFileName); } - } + if (config != null || properties != null) { - log.info("Configuration successfully read."); + logDeferrer.defer(l -> l.info("Configuration successfully read.")); } else { - log.info("Unable to load configuration from file. No configuration files were found."); + logDeferrer.defer(l -> l.info("Unable to load configuration from file. No configuration files were found" + + ".")); } } @@ -124,21 +169,33 @@ public Optional getBoolean(String key) { Optional value = get(key); + return value.map(Boolean::valueOf); + } + + @Override + public Optional getInteger(String key) { + + Optional value = get(key); + if (value.isPresent()) { - return Optional.of(Boolean.valueOf(value.get())); + try { + return Optional.of(Integer.valueOf(value.get())); + } catch (NumberFormatException e) { + return Optional.empty(); + } } else { return Optional.empty(); } } @Override - public Optional getInteger(String key) { + public Optional getLong(String key) { Optional value = get(key); if (value.isPresent()) { try { - return Optional.of(Integer.valueOf(value.get())); + return Optional.of(Long.valueOf(value.get())); } catch (NumberFormatException e) { return Optional.empty(); } @@ -194,28 +251,51 @@ public Optional getListSize(String key) { } @Override - public void set(String key, String value) { + @SuppressWarnings("unchecked") + public Optional> getMapKeys(String key) { + + Object o = getValue(key); + Map map = null; + + if (o instanceof Map) { + map = (Map) o; + } + + if (map == null || map.isEmpty()) { + return Optional.empty(); + } + + return Optional.of(new ArrayList<>(map.keySet())); } @Override - public void set(String key, Boolean value) { + public void watch(String key) { + } + @Override + public void set(String key, String value) { } @Override - public void set(String key, Integer value) { + public void set(String key, Boolean value) { + } + @Override + public void set(String key, Integer value) { } @Override public void set(String key, Double value) { - } @Override public void set(String key, Float value) { + } + @Override + public Integer getOrdinal() { + return getInteger(CONFIG_ORDINAL).orElse(100); } /** @@ -229,11 +309,8 @@ private boolean representsArray(String key) { int openingBracket = key.indexOf("["); int closingBracket = key.indexOf("]"); - if (closingBracket == key.length() - 1 && openingBracket != -1) { - return true; - } + return closingBracket == key.length() - 1 && openingBracket != -1; - return false; } /** @@ -264,7 +341,11 @@ private Object getValue(String key) { try { arrayIndex = Integer.parseInt(splittedKey.substring(openingBracket + 1, closingBracket)); } catch (NumberFormatException e) { - log.severe("Cannot cast array index."); + + if (log != null) { + log.severe("Cannot cast array index."); + } + return null; } @@ -290,6 +371,31 @@ private Object getValue(String key) { } return value; + } + + private void loadProperties(String fileName) { + + try { + InputStream inputStream = getClass().getClassLoader().getResourceAsStream(fileName); + + if (inputStream == null) { + try { + inputStream = Files.newInputStream(Paths.get(fileName)); + } catch (IOException ignored) { + } + } + + if (inputStream != null) { + + logDeferrer.defer(l -> l.info("Loading configuration from .properties file: " + propertiesFileName)); + properties = new Properties(); + properties.load(inputStream); + + inputStream.close(); + } + } catch (IOException e) { + logDeferrer.defer(l -> l.info("Properties file: " + fileName + " not found.")); + } } } diff --git a/common/src/main/java/com/kumuluz/ee/configuration/sources/SystemPropertyConfigurationSource.java b/common/src/main/java/com/kumuluz/ee/configuration/sources/SystemPropertyConfigurationSource.java new file mode 100644 index 00000000..7580e166 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/configuration/sources/SystemPropertyConfigurationSource.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.configuration.sources; + +import com.kumuluz.ee.configuration.ConfigurationSource; +import com.kumuluz.ee.configuration.utils.ConfigurationDispatcher; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Properties; + +/** + * @author Urban Malc + * @since 2.4.0 + */ +public class SystemPropertyConfigurationSource implements ConfigurationSource { + + @Override + public void init(ConfigurationDispatcher configurationDispatcher) { + } + + @Override + public Optional get(String key) { + return Optional.ofNullable(System.getProperty(key)); + } + + @Override + public Optional getBoolean(String key) { + + Optional value = get(key); + + return value.map(Boolean::valueOf); + } + + @Override + public Optional getInteger(String key) { + + Optional value = get(key); + + if (value.isPresent()) { + try { + return Optional.of(Integer.valueOf(value.get())); + } catch (NumberFormatException e) { + return Optional.empty(); + } + } else { + return Optional.empty(); + } + } + + @Override + public Optional getLong(String key) { + + Optional value = get(key); + + if (value.isPresent()) { + try { + return Optional.of(Long.valueOf(value.get())); + } catch (NumberFormatException e) { + return Optional.empty(); + } + } else { + return Optional.empty(); + } + } + + @Override + public Optional getDouble(String key) { + Optional value = get(key); + + if (value.isPresent()) { + try { + return Optional.of(Double.valueOf(value.get())); + } catch (NumberFormatException e) { + return Optional.empty(); + } + } else { + return Optional.empty(); + } + } + + @Override + public Optional getFloat(String key) { + Optional value = get(key); + + if (value.isPresent()) { + try { + return Optional.of(Float.valueOf(value.get())); + } catch (NumberFormatException e) { + return Optional.empty(); + } + + } else { + return Optional.empty(); + } + } + + @Override + public Optional getListSize(String key) { + int listSize = 0; + while(get(key + "[" + listSize + "]").isPresent()) { + listSize++; + } + + if(listSize > 0) { + return Optional.of(listSize); + } else { + return Optional.empty(); + } + } + + @Override + public Optional> getMapKeys(String key) { + + List mapKeys = new ArrayList<>(); + + Properties p = System.getProperties(); + for(String propertyKey : p.stringPropertyNames()) { + String mapKey = ""; + + if(propertyKey.startsWith(key)) { + int index = key.length() + 1; + if(index < propertyKey.length() && propertyKey.charAt(index-1) == '.') { + mapKey = propertyKey.substring(index); + } + } + + if(!mapKey.isEmpty()) { + int index = mapKey.indexOf("."); + if(index > 0) { + mapKey = mapKey.substring(0, index); + } + + mapKeys.add(mapKey); + } + } + + if(mapKeys.isEmpty()) { + return Optional.empty(); + } + + return Optional.of(mapKeys); + } + + @Override + public void watch(String key) { + } + + @Override + public void set(String key, String value) { + } + + @Override + public void set(String key, Boolean value) { + } + + @Override + public void set(String key, Integer value) { + } + + @Override + public void set(String key, Double value) { + } + + @Override + public void set(String key, Float value) { + } + + @Override + public Integer getOrdinal() { + return getInteger(CONFIG_ORDINAL).orElse(400); + } +} diff --git a/common/src/main/java/com/kumuluz/ee/configuration/utils/ConfigurationDispatcher.java b/common/src/main/java/com/kumuluz/ee/configuration/utils/ConfigurationDispatcher.java new file mode 100644 index 00000000..90477b12 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/configuration/utils/ConfigurationDispatcher.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.configuration.utils; + +import com.kumuluz.ee.configuration.ConfigurationListener; + +import java.util.ArrayList; +import java.util.List; + + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +// Fire configuration events and notify subscription +public class ConfigurationDispatcher { + + private List subscriptions = new ArrayList<>(); + + public void notifyChange(String key, String value) { + + for (ConfigurationListener subscription : subscriptions) { + subscription.onChange(key, value); + } + } + + public void subscribe(ConfigurationListener listener) { + subscriptions.add(listener); + } + + public void unsubscribe(ConfigurationListener listener) { + subscriptions.remove(listener); + } +} diff --git a/common/src/main/java/com/kumuluz/ee/configuration/utils/ConfigurationImpl.java b/common/src/main/java/com/kumuluz/ee/configuration/utils/ConfigurationImpl.java new file mode 100644 index 00000000..95f033b8 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/configuration/utils/ConfigurationImpl.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.configuration.utils; + +import com.kumuluz.ee.configuration.ConfigurationSource; +import com.kumuluz.ee.configuration.sources.EnvironmentConfigurationSource; +import com.kumuluz.ee.configuration.sources.FileConfigurationSource; +import com.kumuluz.ee.configuration.sources.SystemPropertyConfigurationSource; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +/** + * @author Tilen Faganel + * @since 2.1.0 + */ +public class ConfigurationImpl { + + private Logger utilLogger; + private ConfigurationDispatcher dispatcher; + private List configurationSources; + + private EnvironmentConfigurationSource environmentConfigurationSource; + private SystemPropertyConfigurationSource systemPropertyConfigurationSource; + private FileConfigurationSource fileConfigurationSource; + + public ConfigurationImpl() { + init(); + } + + private void init() { + + environmentConfigurationSource = new EnvironmentConfigurationSource(); + systemPropertyConfigurationSource = new SystemPropertyConfigurationSource(); + fileConfigurationSource = new FileConfigurationSource(); + + // specify sources + configurationSources = new ArrayList<>(); + configurationSources.add(environmentConfigurationSource); + configurationSources.add(systemPropertyConfigurationSource); + configurationSources.add(fileConfigurationSource); + + dispatcher = new ConfigurationDispatcher(); + + // initialise sources + for (ConfigurationSource configurationSource : configurationSources) { + + configurationSource.init(dispatcher); + } + } + + public void postInit() { + + fileConfigurationSource.postInit(); + + utilLogger = Logger.getLogger(ConfigurationUtil.class.getName()); + } + + public Boolean isUtilLoggerAvailable() { + return utilLogger != null; + } + + public Logger getUtilLogger() { + return utilLogger; + } + + public ConfigurationDispatcher getDispatcher() { + return dispatcher; + } + + public List getConfigurationSources() { + return configurationSources; + } +} diff --git a/common/src/main/java/com/kumuluz/ee/configuration/utils/ConfigurationUtil.java b/common/src/main/java/com/kumuluz/ee/configuration/utils/ConfigurationUtil.java index bdd267c5..c447a705 100644 --- a/common/src/main/java/com/kumuluz/ee/configuration/utils/ConfigurationUtil.java +++ b/common/src/main/java/com/kumuluz/ee/configuration/utils/ConfigurationUtil.java @@ -1,12 +1,30 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.configuration.utils; +import com.kumuluz.ee.configuration.ConfigurationListener; import com.kumuluz.ee.configuration.ConfigurationSource; -import com.kumuluz.ee.configuration.sources.EnvironmentConfigurationSource; -import com.kumuluz.ee.configuration.sources.FileConfigurationSource; +import com.kumuluz.ee.configuration.enums.ConfigurationValueType; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.logging.Logger; /** @@ -15,39 +33,43 @@ */ public class ConfigurationUtil { - private static final Logger log = Logger.getLogger(ConfigurationUtil.class.getName()); private static ConfigurationUtil instance; - private List configurationSources; + + private ConfigurationImpl config; protected ConfigurationUtil() { } - public static ConfigurationUtil getInstance() { - if (instance == null) { - instance = new ConfigurationUtil(); - instance.init(); - } - return instance; + private ConfigurationUtil(ConfigurationImpl config) { + this.config = config; } - private void init() { + public static void initialize(ConfigurationImpl config) { - // specify sources - configurationSources = new ArrayList<>(); - configurationSources.add(new EnvironmentConfigurationSource()); - configurationSources.add(new FileConfigurationSource()); + if (instance != null) { + throw new IllegalStateException("The ConfigurationUtil was already initialized."); + } - // initialise sources - for (ConfigurationSource configurationSource : configurationSources) { - log.info("Initialising configuration source: " + configurationSource.getClass().getSimpleName()); - configurationSource.init(); + instance = new ConfigurationUtil(config); + } + + public static ConfigurationUtil getInstance() { + + if (instance == null) { + throw new IllegalStateException("The ConfigurationUtil was not yet initialized."); } + + return instance; } public Optional get(String key) { + return get(key, new HashSet<>()); + } - for (ConfigurationSource configurationSource : configurationSources) { - Optional value = configurationSource.get(key); + public Optional getBoolean(String key) { + + for (ConfigurationSource configurationSource : config.getConfigurationSources()) { + Optional value = configurationSource.getBoolean(key); if (value.isPresent()) { return value; } @@ -55,10 +77,10 @@ public Optional get(String key) { return Optional.empty(); } - public Optional getBoolean(String key) { + public Optional getInteger(String key) { - for (ConfigurationSource configurationSource : configurationSources) { - Optional value = configurationSource.getBoolean(key); + for (ConfigurationSource configurationSource : config.getConfigurationSources()) { + Optional value = configurationSource.getInteger(key); if (value.isPresent()) { return value; } @@ -66,10 +88,10 @@ public Optional getBoolean(String key) { return Optional.empty(); } - public Optional getInteger(String key) { + public Optional getLong(String key) { - for (ConfigurationSource configurationSource : configurationSources) { - Optional value = configurationSource.getInteger(key); + for (ConfigurationSource configurationSource : config.getConfigurationSources()) { + Optional value = configurationSource.getLong(key); if (value.isPresent()) { return value; } @@ -79,7 +101,7 @@ public Optional getInteger(String key) { public Optional getDouble(String key) { - for (ConfigurationSource configurationSource : configurationSources) { + for (ConfigurationSource configurationSource : config.getConfigurationSources()) { Optional value = configurationSource.getDouble(key); if (value.isPresent()) { return value; @@ -90,7 +112,7 @@ public Optional getDouble(String key) { public Optional getFloat(String key) { - for (ConfigurationSource configurationSource : configurationSources) { + for (ConfigurationSource configurationSource : config.getConfigurationSources()) { Optional value = configurationSource.getFloat(key); if (value.isPresent()) { return value; @@ -102,7 +124,7 @@ public Optional getFloat(String key) { public Optional getListSize(String key) { int listSize = -1; - for (ConfigurationSource configurationSource : configurationSources) { + for (ConfigurationSource configurationSource : config.getConfigurationSources()) { Optional currentListSize = configurationSource.getListSize(key); if (currentListSize.isPresent() && currentListSize.get() > listSize) { listSize = currentListSize.get(); @@ -116,22 +138,150 @@ public Optional getListSize(String key) { } public void set(String key, String value) { - configurationSources.get(0).set(key, value); + config.getConfigurationSources().get(0).set(key, value); } public void set(String key, Boolean value) { - configurationSources.get(0).set(key, value); + config.getConfigurationSources().get(0).set(key, value); } public void set(String key, Integer value) { - configurationSources.get(0).set(key, value); + config.getConfigurationSources().get(0).set(key, value); } public void set(String key, Double value) { - configurationSources.get(0).set(key, value); + config.getConfigurationSources().get(0).set(key, value); } public void set(String key, Float value) { - configurationSources.get(0).set(key, value); + config.getConfigurationSources().get(0).set(key, value); + } + + public Optional getType(String key) { + + // check if key type is a list or a map + if (getListSize(key).isPresent()) { + return Optional.of(ConfigurationValueType.LIST); + } + + if (getMapKeys(key).isPresent()) { + return Optional.of(ConfigurationValueType.MAP); + } + + // get the key value from sources according to priorities and determine its type + Optional value = get(key); + + if (!value.isPresent()) { + return Optional.empty(); + } + + if ("true".equals(value.get().toLowerCase()) || "false".equals(value.get().toLowerCase())) { + return Optional.of(ConfigurationValueType.BOOLEAN); + } + + try { + Integer.valueOf(value.get()); + return Optional.of(ConfigurationValueType.INTEGER); + } catch (NumberFormatException ignored) { + } + + try { + Long.valueOf(value.get()); + return Optional.of(ConfigurationValueType.LONG); + } catch (NumberFormatException ignored) { + } + + try { + Float f = Float.valueOf(value.get()); + if (!f.isInfinite()) { + return Optional.of(ConfigurationValueType.FLOAT); + } + } catch (NumberFormatException ignored) { + } + + try { + Double.valueOf(value.get()); + return Optional.of(ConfigurationValueType.DOUBLE); + } catch (NumberFormatException ignored) { + } + + return Optional.of(ConfigurationValueType.STRING); + + } + + public Optional> getMapKeys(String key) { + + Set mapKeys = new HashSet<>(); + + for (ConfigurationSource configurationSource : config.getConfigurationSources()) { + Optional> value = configurationSource.getMapKeys(key); + if (value.isPresent()) { + for (String s : value.get()) { + if (!mapKeys.contains(s.replace("-", ""))) { + mapKeys.add(s); + } + } + } + } + + if (mapKeys.isEmpty()) { + return Optional.empty(); + } + + return Optional.of(new ArrayList<>(mapKeys)); + } + + public void subscribe(String key, ConfigurationListener listener) { + + config.getDispatcher().subscribe(listener); + + for (ConfigurationSource configurationSource : config.getConfigurationSources()) { + configurationSource.watch(key); + } + } + + public void unsubscribe(ConfigurationListener listener) { + config.getDispatcher().unsubscribe(listener); + } + + //// Private methods + + private Optional get(String key, Set processingKeys) { + + for (ConfigurationSource configurationSource : config.getConfigurationSources()) { + Optional value = configurationSource.get(key); + if (value.isPresent()) { + return Optional.of(interpolateString(key, value.get(), processingKeys)); + } + } + return Optional.empty(); + } + + private String interpolateString(String key, String s, Set processingKeys) { + + if(processingKeys.contains(key)) { + + if (config.isUtilLoggerAvailable()) { + + config.getUtilLogger().warning("Detected cycle when interpolating configuration key: " + key); + } + + return ""; + } + + processingKeys.add(key); + + int startIndex; + while((startIndex = s.indexOf("${")) >= 0) { + int endIndex = s.indexOf("}", startIndex + 2); + String newKey = s.substring(startIndex + 2, endIndex); + + String replacement = get(newKey, processingKeys).orElse(""); + processingKeys.remove(newKey); + + s = s.substring(0, startIndex) + replacement + s.substring(endIndex + 1); + } + + return s; } } diff --git a/common/src/main/java/com/kumuluz/ee/logs/LogCommons.java b/common/src/main/java/com/kumuluz/ee/logs/LogCommons.java deleted file mode 100644 index bef1f2ea..00000000 --- a/common/src/main/java/com/kumuluz/ee/logs/LogCommons.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2014-2017 Kumuluz and/or its affiliates - * and other contributors as indicated by the @author tags and - * the contributor list. - * - * Licensed under the MIT License (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://opensource.org/licenses/MIT - * - * 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. See the License for the specific language governing permissions and - * limitations under the License. -*/ - -package com.kumuluz.ee.logs; - -import com.kumuluz.ee.logs.enums.LogLevel; -import com.kumuluz.ee.logs.markers.Marker; -import com.kumuluz.ee.logs.types.LogMethodContext; -import com.kumuluz.ee.logs.types.LogMethodMessage; -import com.kumuluz.ee.logs.types.LogResourceContext; -import com.kumuluz.ee.logs.types.LogResourceMessage; - -/** - * Kumuluz-logs logger interface - * - * @author Rok Povse - * @author Marko Skrjanec - */ -public interface LogCommons { - - /** - * Creates a new logger - * - * @param logName String name of the logger - * @return Logger instance - */ - LogCommons getCommonsLogger(String logName); - - /** - * Returns logger name - * - * @return String logger name - */ - String getName(); - - /** - * Set the level for logging. Default is TRACE - * - * @param logLevel LogLevel object defining LogCommons - */ - void setDefaultLevel(LogLevel logLevel); - - /** - * Log Method entry - * - * @param logMethodMessage LogMethodMessage object with details about log content - * @return LogMethodContext object, which is passed to logMethodExit - */ - LogMethodContext logMethodEntry(LogMethodMessage logMethodMessage); - - /** - * Log Method entry with custom LogLevel definition - * - * @param level LogLevel - * @param logMethodMessage LogMethodMessage object with details about log content - * @return LogMethodContext object, which is passed to logMethodExit - */ - LogMethodContext logMethodEntry(LogLevel level, LogMethodMessage logMethodMessage); - - /** - * Log Method entry with custom LogLevel definition - * - * @param marker Marker object defining type of resource - * @param logMethodMessage LogMethodMessage object with details about log content - * @return LogMethodContext object, which is passed to logMethodExit - */ - LogMethodContext logMethodEntry(Marker marker, LogMethodMessage logMethodMessage); - - /** - * Log Method entry with custom LogLevel definition - * - * @param level LogLevel - * @param marker Marker object defining type of resource - * @param logMethodMessage LogMethodMessage object with details about log content - * @return LogMethodContext object, which is passed to logMethodExit - */ - LogMethodContext logMethodEntry(LogLevel level, Marker marker, LogMethodMessage logMethodMessage); - - /** - * Log Method exit - * - * @param logMethodContext LogMethodContext object with details returned from Entry log - */ - void logMethodExit(LogMethodContext logMethodContext); - - /** - * Log Resource invokation start - * - * @param logResourceMessage LogResourceMessage object with details about invoked resource and configuration - * @return LogResourceContext object, which is passed to logResourceEnd - */ - LogResourceContext logResourceStart(LogResourceMessage logResourceMessage); - - /** - * Log Resource invokation start - * - * @param level LogLevel - * @param logResourceMessage LogResourceMessage object with details about invoked resource and configuration - * @return LogResourceContext object, which is passed to logResourceEnd - */ - LogResourceContext logResourceStart(LogLevel level, LogResourceMessage logResourceMessage); - - - /** - * Log Resource invokation start - * - * @param marker Marker object defining type of resource - * @param logResourceMessage LogResourceMessage object with details about invoked resource and configuration - * @return LogResourceContext object, which is passed to logResourceEnd - */ - LogResourceContext logResourceStart(Marker marker, LogResourceMessage logResourceMessage); - - /** - * Log Resource invokation start - * - * @param level LogLevel - * @param marker Marker object defining type of resource - * @param logResourceMessage LogResourceMessage object with details about invoked resource and configuration - * @return LogResourceContext object, which is passed to logResourceEnd - */ - LogResourceContext logResourceStart(LogLevel level, Marker marker, LogResourceMessage logResourceMessage); - - /** - * Log end of Resource invoke - * - * @param logResourceContext LogResourceContext object with details returned from logResourceStart method - */ - void logResourceEnd(LogResourceContext logResourceContext); - -} diff --git a/common/src/main/java/com/kumuluz/ee/logs/LogDeferrer.java b/common/src/main/java/com/kumuluz/ee/logs/LogDeferrer.java new file mode 100644 index 00000000..d69260fe --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/logs/LogDeferrer.java @@ -0,0 +1,47 @@ +package com.kumuluz.ee.logs; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class LogDeferrer { + + private Supplier logger; + private List> logs = new ArrayList<>(); + private Boolean finished = false; + + public void init(Supplier logger) { + + if (this.logger != null) { + + throw new IllegalStateException("The LogDeferrer was already initiated with a logger instance"); + } + + this.logger = logger; + } + + public void defer(Consumer log) { + + this.logs.add(log); + } + + public void execute() { + + if (finished) { + + throw new IllegalStateException("The LogDeferrer was already executed. Please create a new one."); + } + + T loggerInstance = logger.get(); + + for (Consumer log : logs) { + + log.accept(loggerInstance); + } + + this.logger = null; + this.logs.clear(); + this.finished = true; + } +} diff --git a/common/src/main/java/com/kumuluz/ee/logs/LogManager.java b/common/src/main/java/com/kumuluz/ee/logs/LogManager.java deleted file mode 100644 index b07e3b16..00000000 --- a/common/src/main/java/com/kumuluz/ee/logs/LogManager.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2014-2017 Kumuluz and/or its affiliates - * and other contributors as indicated by the @author tags and - * the contributor list. - * - * Licensed under the MIT License (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://opensource.org/licenses/MIT - * - * 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. See the License for the specific language governing permissions and - * limitations under the License. -*/ - -package com.kumuluz.ee.logs; - -import com.kumuluz.ee.logs.enums.LogLevel; - -/** - * @author Rok Povse - * @author Marko Skrjanec - */ -public class LogManager { - - /** - * Returns Logger instance. Use this method for retrieval of Logger instances in your code. - * - * @param loggerName String logger name - * @return Logger instance - */ - public static Logger getLogger(String loggerName) { - return LogUtil.getInstance().getLogInstance(loggerName); - } - - /** - * Returns LogCommons instance. Use this method for retrieval of LogCommons instances in your code. - * - * @param loggerName String logger name - * @return LogCommons instance - */ - public static LogCommons getCommonsLogger(String loggerName) { - return LogUtil.getInstance().getLogCommonsInstance(loggerName); - } - - /** - * Method for getting currently set logger level from code - * - * @param loggerName String logger name - * @return LogLevel object - */ - public static LogLevel getLogLevel(String loggerName) { - return LogUtil.getInstance().getLogConfigurator().getLevel(loggerName); - } - - /** - * Method for changing logger level from code - * - * @param loggerName String logger name - * @param logLevel LogLevel object - */ - public static void setLogLevel(String loggerName, LogLevel logLevel) { - LogUtil.getInstance().getLogConfigurator().setLevel(loggerName, logLevel); - } -} diff --git a/common/src/main/java/com/kumuluz/ee/logs/LogUtil.java b/common/src/main/java/com/kumuluz/ee/logs/LogUtil.java deleted file mode 100644 index 563c80f9..00000000 --- a/common/src/main/java/com/kumuluz/ee/logs/LogUtil.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2014-2017 Kumuluz and/or its affiliates - * and other contributors as indicated by the @author tags and - * the contributor list. - * - * Licensed under the MIT License (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://opensource.org/licenses/MIT - * - * 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. See the License for the specific language governing permissions and - * limitations under the License. -*/ - -package com.kumuluz.ee.logs; - -import java.util.*; - -/** - * @author Rok Povse - * @author Marko Skrjanec - */ -public class LogUtil { - - private static LogUtil logUtil; - - private Logger loggerInstance; - private LogCommons logCommonsInstance; - private LogConfigurator logConfigurator; - - private Map loggers; - private Map loggersCommons; - - private LogUtil() { - loggers = new HashMap<>(); - loggersCommons = new HashMap<>(); - initInstances(); - } - - /** - * Returns a singleton LogUtil instance - * - * @return LogUtil instance - */ - public static LogUtil getInstance() { - if (logUtil == null) { - logUtil = new LogUtil(); - } - - return logUtil; - } - - /** - * Returns Logger Instance if it exists for this name - * If not, it first creates it. - * - * @param loggerName String name of the logger - * @return Log insntace - */ - public Logger getLogInstance(String loggerName) { - if (!loggers.containsKey(loggerName)) { - loggers.put(loggerName, loggerInstance.getLogger(loggerName)); - } - return loggers.get(loggerName); - } - - /** - * Returns LogCommons Instance if it exists for this name - * If not, it first creates it. - * - * @param loggerName String name of the logger - * @return LogCommons insntace - */ - public LogCommons getLogCommonsInstance(String loggerName) { - if (!loggersCommons.containsKey(loggerName)) { - loggersCommons.put(loggerName, logCommonsInstance.getCommonsLogger(loggerName)); - } - return loggersCommons.get(loggerName); - } - - /** - * @return LogConfigurator instance - */ - public LogConfigurator getLogConfigurator() { - return logConfigurator; - } - - /** - * Searches and initializes inital instances - * for logger, commons logger and log configurator - */ - private void initInstances() { - - List loggerImpl = new ArrayList<>(); - ServiceLoader.load(Logger.class).forEach(loggerImpl::add); - - List logCommonsImpl = new ArrayList<>(); - ServiceLoader.load(LogCommons.class).forEach(logCommonsImpl::add); - - List logConfiguratorsConfigImpl = new ArrayList<>(); - ServiceLoader.load(LogConfigurator.class).forEach(logConfiguratorsConfigImpl::add); - - if (loggerImpl.isEmpty() || loggerImpl.size() > 1) { - throw new IllegalArgumentException( - " Please provide exactly one implementation " + - " of class com.kumuluz.ee.logs.Logger"); - } - - if (logCommonsImpl.isEmpty() || logCommonsImpl.size() > 1) { - throw new IllegalArgumentException(" Please provide exactly one implementation " + - "of class com.kumuluz.ee.logs.LogCommons"); - } - - if (logConfiguratorsConfigImpl.isEmpty() || logConfiguratorsConfigImpl.size() > 1) { - throw new IllegalArgumentException(" Please provide exactly one implementation " + - "of class com.kumuluz.ee.logs.LogConfigurator"); - } - - loggerInstance = loggerImpl.get(0); - logCommonsInstance = logCommonsImpl.get(0); - logConfigurator = logConfiguratorsConfigImpl.get(0); - } -} diff --git a/common/src/main/java/com/kumuluz/ee/logs/Logger.java b/common/src/main/java/com/kumuluz/ee/logs/Logger.java deleted file mode 100644 index 88b8e989..00000000 --- a/common/src/main/java/com/kumuluz/ee/logs/Logger.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2014-2017 Kumuluz and/or its affiliates - * and other contributors as indicated by the @author tags and - * the contributor list. - * - * Licensed under the MIT License (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://opensource.org/licenses/MIT - * - * 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. See the License for the specific language governing permissions and - * limitations under the License. -*/ - -package com.kumuluz.ee.logs; - -import com.kumuluz.ee.logs.enums.LogLevel; -import com.kumuluz.ee.logs.messages.LogMessage; - -/** - * Kumuluz-logs logger interface - * - * @author Rok Povse - * @author Marko Skrjanec - */ -public interface Logger { - - Logger getLogger(String logName); - - String getName(); - - void log(LogLevel level, String message); - - void log(LogLevel level, String message, Object... args); - - void log(LogLevel level, String message, Throwable thrown); - - void log(LogLevel level, Throwable thrown); - - void log(LogLevel level, LogMessage message); - - void log(LogLevel level, LogMessage message, Throwable thrown); - - void trace(String message); - - void trace(String message, Object... args); - - void trace(String message, Throwable thrown); - - void trace(Throwable thrown); - - void trace(LogMessage message); - - void trace(LogMessage message, Throwable thrown); - - void info(String message); - - void info(String message, Object... args); - - void info(String message, Throwable thrown); - - void info(Throwable thrown); - - void info(LogMessage message); - - void info(LogMessage message, Throwable thrown); - - void debug(String message); - - void debug(String message, Object... args); - - void debug(String message, Throwable thrown); - - void debug(Throwable thrown); - - void debug(LogMessage message); - - void debug(LogMessage message, Throwable thrown); - - void warn(String message); - - void warn(String message, Object... args); - - void warn(String message, Throwable thrown); - - void warn(Throwable thrown); - - void warn(LogMessage message); - - void warn(LogMessage message, Throwable thrown); - - void error(String message); - - void error(String message, Object... args); - - void error(String message, Throwable thrown); - - void error(Throwable thrown); - - void error(LogMessage message); - - void error(LogMessage message, Throwable thrown); -} diff --git a/common/src/main/java/com/kumuluz/ee/logs/impl/JavaUtilConsoleHandler.java b/common/src/main/java/com/kumuluz/ee/logs/impl/JavaUtilConsoleHandler.java new file mode 100644 index 00000000..d66b7fcb --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/logs/impl/JavaUtilConsoleHandler.java @@ -0,0 +1,48 @@ +package com.kumuluz.ee.logs.impl; + +import java.io.UnsupportedEncodingException; +import java.util.logging.*; + +public class JavaUtilConsoleHandler extends StreamHandler { + + /** + * Create a JavaUtilConsoleHandler for System.out. + */ + public JavaUtilConsoleHandler() { + + setLevel(Level.INFO); + setFormatter(new JavaUtilFormatter()); + setOutputStream(System.out); + + try { + setEncoding(null); + } catch (UnsupportedEncodingException ignored) { + } + } + + /** + * Publish a LogRecord. + *

+ * The logging request was made initially to a Logger object, + * which initialized the LogRecord and forwarded it here. + *

+ * @param record description of the log event. A null record is + * silently ignored and is not published + */ + @Override + public void publish(LogRecord record) { + super.publish(record); + + flush(); + } + + /** + * Override StreamHandler.close to do a flush but not + * to close the output stream. That is, we do not + * close System.out. + */ + @Override + public void close() { + flush(); + } +} diff --git a/common/src/main/java/com/kumuluz/ee/logs/impl/JavaUtilDefaultLogConfigurator.java b/common/src/main/java/com/kumuluz/ee/logs/impl/JavaUtilDefaultLogConfigurator.java new file mode 100644 index 00000000..f340f229 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/logs/impl/JavaUtilDefaultLogConfigurator.java @@ -0,0 +1,44 @@ +package com.kumuluz.ee.logs.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.util.logging.*; + +public class JavaUtilDefaultLogConfigurator { + + public static void init() { + + String javaUtilConfig = System.getProperty("java.util.logging.config.file"); + + if (javaUtilConfig == null) { + + LogManager.getLogManager().reset(); + + Logger rootLogger = LogManager.getLogManager().getLogger(""); + + JavaUtilConsoleHandler handler = new JavaUtilConsoleHandler(); + + rootLogger.addHandler(handler); + } else { + + InputStream javaUtilConfigStream = JavaUtilDefaultLogConfigurator.class.getClassLoader() + .getResourceAsStream(javaUtilConfig); + + if (javaUtilConfigStream != null) { + + try { + LogManager.getLogManager().readConfiguration(javaUtilConfigStream); + } catch (IOException ignored) { + } + } + } + } + + public static void initSoleHandler(Handler handler) { + + LogManager.getLogManager().reset(); + + Logger rootLogger = LogManager.getLogManager().getLogger(""); + rootLogger.addHandler(handler); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/kumuluz/ee/logs/impl/JavaUtilFormatter.java b/common/src/main/java/com/kumuluz/ee/logs/impl/JavaUtilFormatter.java new file mode 100644 index 00000000..4a658b10 --- /dev/null +++ b/common/src/main/java/com/kumuluz/ee/logs/impl/JavaUtilFormatter.java @@ -0,0 +1,41 @@ +package com.kumuluz.ee.logs.impl; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.logging.Formatter; +import java.util.logging.LogRecord; + +public class JavaUtilFormatter extends Formatter { + + private static final DateTimeFormatter timestampFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + + @Override + public String format(LogRecord record) { + + ZonedDateTime zonedDateTime = Instant.ofEpochMilli(record.getMillis()).atZone(ZoneId.systemDefault()); + + String source = record.getSourceClassName() != null ? record.getSourceClassName() : record.getLoggerName(); + String message = formatMessage(record); + String throwable = ""; + + if (record.getThrown() != null) { + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + pw.println(); + record.getThrown().printStackTrace(pw); + pw.close(); + throwable = sw.toString(); + } + + return zonedDateTime.format(timestampFormat) + " " + + record.getLevel().getName() + " -- " + + source + " -- " + + message + throwable + "\n"; + } +} diff --git a/common/src/main/java/com/kumuluz/ee/logs/messages/ResourceInvokeEndLogMessage.java b/common/src/main/java/com/kumuluz/ee/logs/messages/ResourceInvokeEndLogMessage.java deleted file mode 100644 index a7c2c821..00000000 --- a/common/src/main/java/com/kumuluz/ee/logs/messages/ResourceInvokeEndLogMessage.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2014-2017 Kumuluz and/or its affiliates - * and other contributors as indicated by the @author tags and - * the contributor list. - * - * Licensed under the MIT License (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://opensource.org/licenses/MIT - * - * 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. See the License for the specific language governing permissions and - * limitations under the License. -*/ - -package com.kumuluz.ee.logs.messages; - -/** - * @author Rok Povse - * @author Marko Skrjanec - */ -public interface ResourceInvokeEndLogMessage extends LogMessage { -} diff --git a/common/src/main/java/com/kumuluz/ee/logs/messages/ResourceInvokeLogMessage.java b/common/src/main/java/com/kumuluz/ee/logs/messages/ResourceInvokeLogMessage.java deleted file mode 100644 index be6ece71..00000000 --- a/common/src/main/java/com/kumuluz/ee/logs/messages/ResourceInvokeLogMessage.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2014-2017 Kumuluz and/or its affiliates - * and other contributors as indicated by the @author tags and - * the contributor list. - * - * Licensed under the MIT License (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://opensource.org/licenses/MIT - * - * 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. See the License for the specific language governing permissions and - * limitations under the License. -*/ - -package com.kumuluz.ee.logs.messages; - -/** - * @author Rok Povse - * @author Marko Skrjanec - */ -public interface ResourceInvokeLogMessage extends LogMessage { -} diff --git a/common/src/main/java/com/kumuluz/ee/logs/types/LogMethodContext.java b/common/src/main/java/com/kumuluz/ee/logs/types/LogMethodContext.java deleted file mode 100644 index 627d7e5a..00000000 --- a/common/src/main/java/com/kumuluz/ee/logs/types/LogMethodContext.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.kumuluz.ee.logs.types; - -import com.kumuluz.ee.logs.enums.LogLevel; -import com.kumuluz.ee.logs.markers.Marker; -import com.kumuluz.ee.logs.messages.MethodCallExitLogMessage; -import com.kumuluz.ee.logs.messages.MethodCallLogMessage; - -/** - * @author Tilen Faganel - */ -public class LogMethodContext { - - private LogLevel level; - private Marker marker; - - private Boolean callEnabled; - private Boolean metricsEnabled; - - private MethodCallLogMessage callMessage; - - private MethodCallExitLogMessage callExitMessage; - private LogMetrics logMetrics; - - public LogMethodContext(LogMethodMessage entryMessage, LogLevel level, Marker marker) { - - this.callEnabled = entryMessage.isCallEnabled(); - this.metricsEnabled = entryMessage.isMetricsEnabled(); - - if (this.metricsEnabled != null && this.metricsEnabled) { - this.logMetrics = new LogMetrics(); - } - - this.callMessage = entryMessage.getCallMessage(); - - this.level = level; - - this.marker = marker; - } - - public LogMethodContext(LogMethodMessage entryMessage, LogLevel level) { - this(entryMessage,level,null); - } - - public Boolean isCallEnabled() { - return callEnabled; - } - - public Boolean isMetricsEnabled() { - return metricsEnabled; - } - - public MethodCallLogMessage getCallMessage() { - return callMessage; - } - - public MethodCallExitLogMessage getCallExitMessage() { - return callExitMessage; - } - - public void setCallExitMessage(MethodCallExitLogMessage callExitMessage) { - this.callExitMessage = callExitMessage; - } - - public LogLevel getLevel() { - return level; - } - - public LogMetrics getLogMetrics() { - return logMetrics; - } - - public Marker getMarker() { - return marker; - } -} diff --git a/common/src/main/java/com/kumuluz/ee/logs/types/LogMethodMessage.java b/common/src/main/java/com/kumuluz/ee/logs/types/LogMethodMessage.java deleted file mode 100644 index 3d4f60fa..00000000 --- a/common/src/main/java/com/kumuluz/ee/logs/types/LogMethodMessage.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.kumuluz.ee.logs.types; - -import com.kumuluz.ee.logs.messages.MethodCallLogMessage; - -/** - * @author Tilen Faganel - */ -public class LogMethodMessage { - - private Boolean callEnabled; - private Boolean metricsEnabled; - - private MethodCallLogMessage callMessage; - - public LogMethodMessage enableCall(MethodCallLogMessage callMessage) { - this.callMessage = callMessage; - this.callEnabled = true; - - return this; - } - - public LogMethodMessage enableMetrics() { - this.metricsEnabled = true; - - return this; - } - - public Boolean isCallEnabled() { - return callEnabled; - } - - public Boolean isMetricsEnabled() { - return metricsEnabled; - } - - public MethodCallLogMessage getCallMessage() { - return callMessage; - } -} diff --git a/common/src/main/java/com/kumuluz/ee/logs/types/LogMetrics.java b/common/src/main/java/com/kumuluz/ee/logs/types/LogMetrics.java deleted file mode 100644 index c8397768..00000000 --- a/common/src/main/java/com/kumuluz/ee/logs/types/LogMetrics.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) Sunesis d.o.o. - */ -package com.kumuluz.ee.logs.types; - -/** - * Kumuluz-logs logger interface - * - * @author Rok Povse - * @author Marko Skrjanec - */ -public class LogMetrics { - - private Long timerStart; - - public LogMetrics() { - this.timerStart = System.currentTimeMillis(); - } - - public Long getTimeElapsed() { - return System.currentTimeMillis()-this.timerStart; - } -} diff --git a/common/src/main/java/com/kumuluz/ee/logs/types/LogResourceContext.java b/common/src/main/java/com/kumuluz/ee/logs/types/LogResourceContext.java deleted file mode 100644 index a3d4635f..00000000 --- a/common/src/main/java/com/kumuluz/ee/logs/types/LogResourceContext.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (c) Sunesis d.o.o. - */ -package com.kumuluz.ee.logs.types; - -import com.kumuluz.ee.logs.enums.LogLevel; -import com.kumuluz.ee.logs.markers.Marker; -import com.kumuluz.ee.logs.messages.ResourceInvokeEndLogMessage; -import com.kumuluz.ee.logs.messages.ResourceInvokeLogMessage; - -/** - * @author Tilen Faganel - */ -public class LogResourceContext { - - private LogLevel level; - private Marker marker; - - private Boolean invokeEnabled; - private Boolean metricsEnabled; - - private ResourceInvokeLogMessage invokeMessage; - - private ResourceInvokeEndLogMessage invokeEndMessage; - private LogMetrics logMetrics; - - public LogResourceContext(LogResourceMessage resourceMessage, LogLevel level, Marker marker) { - this.invokeEnabled = resourceMessage.isInvokeEnabled(); - this.metricsEnabled = resourceMessage.isMetricsEnabled(); - - if (this.metricsEnabled != null && this.metricsEnabled) { - this.logMetrics = new LogMetrics(); - } - - this.invokeMessage = resourceMessage.getInvokeMessage(); - - this.level = level; - this.marker = marker; - } - - public Boolean isInvokeEnabled() { - return invokeEnabled; - } - - public Boolean isMetricsEnabled() { - return metricsEnabled; - } - - public ResourceInvokeLogMessage getInvokeMessage() { - return invokeMessage; - } - - public ResourceInvokeEndLogMessage getInvokeEndMessage() { - return invokeEndMessage; - } - - public void setInvokeEndMessage(ResourceInvokeEndLogMessage invokeEndMessage) { - this.invokeEndMessage = invokeEndMessage; - } - - public LogLevel getLevel() { - return level; - } - - public Marker getMarker() { - return marker; - } - - public LogMetrics getLogMetrics() { - return logMetrics; - } -} diff --git a/common/src/main/java/com/kumuluz/ee/logs/types/LogResourceMessage.java b/common/src/main/java/com/kumuluz/ee/logs/types/LogResourceMessage.java deleted file mode 100644 index 4676c309..00000000 --- a/common/src/main/java/com/kumuluz/ee/logs/types/LogResourceMessage.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) Sunesis d.o.o. - */ -package com.kumuluz.ee.logs.types; - - -import com.kumuluz.ee.logs.messages.ResourceInvokeLogMessage; - -/** - * @author Tilen Faganel - */ -public class LogResourceMessage { - - private Boolean invokeEnabled; - private Boolean metricsEnabled; - - private ResourceInvokeLogMessage invokeMessage; - - public LogResourceMessage enableInvoke(ResourceInvokeLogMessage invokeMessage) { - this.invokeMessage = invokeMessage; - this.invokeEnabled = true; - - return this; - } - - public LogResourceMessage enableMetrics() { - this.metricsEnabled = true; - - return this; - } - - public Boolean isInvokeEnabled() { - return invokeEnabled; - } - - public Boolean isMetricsEnabled() { - return metricsEnabled; - } - - public ResourceInvokeLogMessage getInvokeMessage() { - return invokeMessage; - } -} diff --git a/common/src/main/resources/version.properties b/common/src/main/resources/META-INF/kumuluzee/versions.properties similarity index 100% rename from common/src/main/resources/version.properties rename to common/src/main/resources/META-INF/kumuluzee/versions.properties diff --git a/components/bean-validation/hibernate-validator/pom.xml b/components/bean-validation/hibernate-validator/pom.xml index 7331289e..a63dd5da 100644 --- a/components/bean-validation/hibernate-validator/pom.xml +++ b/components/bean-validation/hibernate-validator/pom.xml @@ -5,7 +5,7 @@ kumuluzee-bean-validation com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -14,10 +14,6 @@ KumuluzEE Bean Validation Hibernate Validator KumuluzEE Bean Validation component implemented by Hibernate Validator - - 5.3.3.Final - - com.kumuluz.ee @@ -33,6 +29,52 @@ org.hibernate hibernate-validator ${hibernate.validator.version} + + + org.jboss.logging + jboss-logging + + + + + org.jboss.logging + jboss-logging + + + + org.glassfish.jersey.ext + jersey-bean-validation + ${jersey.version} + + + org.glassfish.hk2.external + javax.inject + + + org.glassfish.jersey.core + jersey-common + + + org.glassfish.jersey.core + jersey-server + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + javax.el + javax.el-api + + + org.glassfish.web + javax.el + + diff --git a/components/bean-validation/hibernate-validator/src/main/java/com/kumuluz/ee/beanvalidation/BeanValidationComponent.java b/components/bean-validation/hibernate-validator/src/main/java/com/kumuluz/ee/beanvalidation/BeanValidationComponent.java index 1bf69177..e20bfb9e 100644 --- a/components/bean-validation/hibernate-validator/src/main/java/com/kumuluz/ee/beanvalidation/BeanValidationComponent.java +++ b/components/bean-validation/hibernate-validator/src/main/java/com/kumuluz/ee/beanvalidation/BeanValidationComponent.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.beanvalidation; import com.kumuluz.ee.common.Component; diff --git a/components/bean-validation/hibernate-validator/src/test/java/com/kumuluz/ee/beanvalidation/test/HibernateValidatorTest.java b/components/bean-validation/hibernate-validator/src/test/java/com/kumuluz/ee/beanvalidation/test/HibernateValidatorTest.java index 75c63cb8..f34ea9fa 100644 --- a/components/bean-validation/hibernate-validator/src/test/java/com/kumuluz/ee/beanvalidation/test/HibernateValidatorTest.java +++ b/components/bean-validation/hibernate-validator/src/test/java/com/kumuluz/ee/beanvalidation/test/HibernateValidatorTest.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.beanvalidation.test; import com.kumuluz.ee.beanvalidation.test.beans.Project; diff --git a/components/bean-validation/hibernate-validator/src/test/java/com/kumuluz/ee/beanvalidation/test/beans/Project.java b/components/bean-validation/hibernate-validator/src/test/java/com/kumuluz/ee/beanvalidation/test/beans/Project.java index cff1b3d5..426c2376 100644 --- a/components/bean-validation/hibernate-validator/src/test/java/com/kumuluz/ee/beanvalidation/test/beans/Project.java +++ b/components/bean-validation/hibernate-validator/src/test/java/com/kumuluz/ee/beanvalidation/test/beans/Project.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.beanvalidation.test.beans; import javax.validation.constraints.NotNull; diff --git a/components/bean-validation/hibernate-validator/src/test/java/com/kumuluz/ee/beanvalidation/test/beans/User.java b/components/bean-validation/hibernate-validator/src/test/java/com/kumuluz/ee/beanvalidation/test/beans/User.java index 21f601a8..457599ac 100644 --- a/components/bean-validation/hibernate-validator/src/test/java/com/kumuluz/ee/beanvalidation/test/beans/User.java +++ b/components/bean-validation/hibernate-validator/src/test/java/com/kumuluz/ee/beanvalidation/test/beans/User.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.beanvalidation.test.beans; import java.util.Date; diff --git a/components/bean-validation/pom.xml b/components/bean-validation/pom.xml index 1fd7ad2a..69f223ff 100644 --- a/components/bean-validation/pom.xml +++ b/components/bean-validation/pom.xml @@ -5,7 +5,7 @@ kumuluzee-components com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom diff --git a/components/cdi/pom.xml b/components/cdi/pom.xml index f688117c..27913f26 100644 --- a/components/cdi/pom.xml +++ b/components/cdi/pom.xml @@ -5,7 +5,7 @@ kumuluzee-components com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom diff --git a/components/cdi/weld/pom.xml b/components/cdi/weld/pom.xml index ad2bfb8c..379ad9a3 100644 --- a/components/cdi/weld/pom.xml +++ b/components/cdi/weld/pom.xml @@ -5,7 +5,7 @@ kumuluzee-cdi com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -14,11 +14,6 @@ kumuluzee-cdi-weld - - 2.4.1.Final - 2.24.1 - - com.kumuluz.ee @@ -47,12 +42,21 @@ org.jboss.spec.javax.interceptor jboss-interceptors-api_1.2_spec + + org.jboss.logging + jboss-logging + org.jboss jandex + + org.jboss.logging + jboss-logging + + org.glassfish.jersey.ext.cdi jersey-cdi1x diff --git a/components/cdi/weld/src/main/java/com/kumuluz/ee/cdi/CdiComponent.java b/components/cdi/weld/src/main/java/com/kumuluz/ee/cdi/CdiComponent.java index adbc7bc1..182126cd 100644 --- a/components/cdi/weld/src/main/java/com/kumuluz/ee/cdi/CdiComponent.java +++ b/components/cdi/weld/src/main/java/com/kumuluz/ee/cdi/CdiComponent.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.cdi; import com.kumuluz.ee.common.Component; diff --git a/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/ConfigBundle.java b/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/ConfigBundle.java index 07e1169a..79754cbc 100644 --- a/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/ConfigBundle.java +++ b/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/ConfigBundle.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.configuration.cdi; import javax.enterprise.util.Nonbinding; @@ -16,4 +36,6 @@ @Retention(RetentionPolicy.RUNTIME) public @interface ConfigBundle { @Nonbinding String value() default ""; + + @Nonbinding boolean watch() default false; } diff --git a/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/ConfigValue.java b/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/ConfigValue.java index 4a95d03b..7f74bc45 100644 --- a/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/ConfigValue.java +++ b/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/ConfigValue.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.configuration.cdi; import javax.enterprise.util.Nonbinding; @@ -7,7 +27,8 @@ import java.lang.annotation.Target; /** - * Annotation specifies key name for automatic initialisation of a field from configuration. + * Annotation specifies key name for automatic initialisation of a field from configuration. If attribute watch is + * set to true, key is subscribed to dynamic configuration events. * * @author Tilen Faganel * @since 2.1.0 @@ -16,4 +37,6 @@ @Target({ElementType.FIELD}) public @interface ConfigValue { @Nonbinding String value() default ""; + + @Nonbinding boolean watch() default false; } diff --git a/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/interceptors/ConfigBundleInterceptor.java b/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/interceptors/ConfigBundleInterceptor.java index 40e6025c..8ea64150 100644 --- a/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/interceptors/ConfigBundleInterceptor.java +++ b/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/interceptors/ConfigBundleInterceptor.java @@ -1,5 +1,26 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.configuration.cdi.interceptors; +import com.kumuluz.ee.common.utils.StringUtils; import com.kumuluz.ee.configuration.cdi.ConfigBundle; import com.kumuluz.ee.configuration.cdi.ConfigValue; import com.kumuluz.ee.configuration.utils.ConfigurationUtil; @@ -8,14 +29,18 @@ import javax.annotation.Priority; import javax.interceptor.Interceptor; import javax.interceptor.InvocationContext; +import java.lang.reflect.Array; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.Optional; +import java.util.*; +import java.util.logging.Logger; /** * Interceptor class for ConfigBundle annotation. * * @author Tilen Faganel + * @author Jan Meznaric * @since 2.1.0 */ @Interceptor @@ -23,6 +48,11 @@ @Priority(Interceptor.Priority.LIBRARY_BEFORE) public class ConfigBundleInterceptor { + private static final Logger log = Logger.getLogger(ConfigBundleInterceptor.class.getName()); + private static final ConfigurationUtil configurationUtil = ConfigurationUtil.getInstance(); + private final Class[] primitives = {String.class, Boolean.class, Float.class, Double.class, Integer.class, Long + .class, boolean.class, float.class, double.class, int.class, long.class}; + /** * Method initialises class fields from configuration. */ @@ -36,58 +66,185 @@ public Object loadConfiguration(InvocationContext ic) throws Exception { targetClass = targetClass.getSuperclass(); } - ConfigurationUtil configurationUtil = ConfigurationUtil.getInstance(); + ConfigBundle configBundleAnnotation = (ConfigBundle) targetClass.getDeclaredAnnotation(ConfigBundle.class); - // invoke setters for fields which are defined in configuration - for (Method m : targetClass.getMethods()) { + processConfigBundleBeanSetters(target, targetClass, getKeyPrefix(targetClass), new HashMap<>(), + configBundleAnnotation.watch()); - if (m.getName().substring(0, 3).equals("set") && m.getParameters().length == 1) { + return ic.proceed(); + } - if (m.getParameters()[0].getType().equals(String.class)) { + /** + * Processes and invokes all setters in Bean annotated with @ConfigBundle + * + * @param target target object + * @param targetClass target class + * @param keyPrefix a prefix for generating key names + * @param processedClassRelations class pairs that have already been processed (for cycle detection) + * @param watchAllFields if true, enable watch on all fields + * @return returns true, if at least one field was successfully populated from configuration sources + * @throws Exception + */ + private boolean processConfigBundleBeanSetters(Object target, Class targetClass, String keyPrefix, Map + processedClassRelations, boolean watchAllFields) throws Exception { - Optional value = configurationUtil.get(getKeyName(targetClass, m.getName())); + boolean isConfigBundleEmpty = true; - if (value.isPresent()) { - m.invoke(target, value.get()); - } + // invoke setters + for (Method method : targetClass.getMethods()) { - } else if (m.getParameters()[0].getType().equals(Boolean.class)) { + if (method.getName().substring(0, 3).equals("set") && method.getParameters().length == 1) { - Optional value = configurationUtil.getBoolean(getKeyName(targetClass, m.getName())); + Class parameterType = method.getParameters()[0].getType(); - if (value.isPresent()) { - m.invoke(target, value.get()); + // get field annotation - @ConfigValue + Field field = targetClass.getDeclaredField(setterToField(method.getName())); + ConfigValue fieldAnnotation = null; + if (field != null) { + fieldAnnotation = field.getAnnotation(ConfigValue.class); + } + + // watch nested class or list if all fields in the bean are annotated with watch or if a field is + // annotated with watch + boolean watchNestedClass = watchAllFields; + if (watchNestedClass == false) { + if (fieldAnnotation != null) { + watchNestedClass = fieldAnnotation.watch(); } + } - } else if (m.getParameters()[0].getType().equals(Float.class)) { + // process primitives + if (Arrays.asList(primitives).contains(parameterType)) { - Optional value = configurationUtil.getFloat(getKeyName(targetClass, m.getName())); + Optional value = getValueOfPrimitive(parameterType, getKeyName(targetClass, method + .getName(), keyPrefix)); if (value.isPresent()) { - m.invoke(target, value.get()); + isConfigBundleEmpty = false; + method.invoke(target, value.get()); + } + + if (watchAllFields || (fieldAnnotation != null && fieldAnnotation.watch())) { + deployWatcher(target, method, getKeyName(targetClass, method.getName(), keyPrefix)); } - } else if (m.getParameters()[0].getType().equals(Double.class)) { + // process nested objeccts + } else if (!parameterType.isArray()) { - Optional value = configurationUtil.getDouble(getKeyName(targetClass, m.getName())); + processedClassRelations.put(targetClass, parameterType); - if (value.isPresent()) { - m.invoke(target, value.get()); + Object nestedTarget = processNestedObject(targetClass, method, parameterType, keyPrefix, + processedClassRelations, -1, watchNestedClass); + + // invoke setter method with initialised instance + if (nestedTarget != null) { + method.invoke(target, nestedTarget); } - } else if (m.getParameters()[0].getType().equals(Integer.class)) { + // process arrays + } else { - Optional value = configurationUtil.getInteger(getKeyName(targetClass, m.getName())); + Class componentType = parameterType.getComponentType(); - if (value.isPresent()) { - m.invoke(target, value.get()); + Object array = Array.newInstance(componentType, configurationUtil.getListSize(getKeyName + (targetClass, method.getName(), keyPrefix)).orElse(0)); + + // process list of primitives + if (Arrays.asList(primitives).contains(componentType)) { + for (int i = 0; i < Array.getLength(array); i++) { + Array.set(array, i, getValueOfPrimitive(componentType, getKeyName(targetClass, method + .getName(), keyPrefix) + "[" + i + "]").get()); + } + + // process list of nested classes + } else { + for (int i = 0; i < Array.getLength(array); i++) { + Object nestedTarget = processNestedObject(targetClass, method, componentType, keyPrefix, + processedClassRelations, i, watchNestedClass); + if (nestedTarget != null) { + Array.set(array, i, nestedTarget); + } + + } } + method.invoke(target, array); + } } } + return isConfigBundleEmpty; + } + + /** + * Returns a value of a primitive configuration type + * + * @param type configuration value type + * @param key configuration value key + * @return + */ + private Optional getValueOfPrimitive(Class type, String key) { + + if (type.equals(String.class)) { + return configurationUtil.get(key); + } else if (type.equals(Boolean.class) || type.equals(boolean.class)) { + return configurationUtil.getBoolean(key); + } else if (type.equals(Float.class) || type.equals(float.class)) { + return configurationUtil.getFloat(key); + } else if (type.equals(Double.class) || type.equals(double.class)) { + return configurationUtil.getDouble(key); + } else if (type.equals(Integer.class) || type.equals(int.class)) { + return configurationUtil.getInteger(key); + } else if (type.equals(Long.class) || type.equals(long.class)) { + return configurationUtil.getLong(key); + } else { + return Optional.empty(); + } - return ic.proceed(); + } + + /** + * Create a new instance for nested class, check for cycles and populate nested instance. + * + * @param targetClass target class + * @param method processed method + * @param parameterType parameter type + * @param keyPrefix prefix used for generation of a configuration key + * @param processedClassRelations class pairs that have already been processed (for cycle detection) + * @param arrayIndex array index for arrays of nested objects + * @param watchAllFields if true, enable watch on all fields + * @return + * @throws Exception + */ + private Object processNestedObject(Class targetClass, Method method, Class parameterType, String keyPrefix, + Map processedClassRelations, int arrayIndex, boolean + watchAllFields) throws Exception { + + Object nestedTarget = parameterType.getConstructor().newInstance(); + Class nestedTargetClass = nestedTarget.getClass(); + + // check for cycles + if (processedClassRelations.containsKey(nestedTargetClass) && processedClassRelations.get(nestedTargetClass) + .equals(targetClass)) { + log.warning("There is a cycle in the configuration class tree. ConfigBundle class may not " + + "be populated as expected."); + } else { + + String key = getKeyName(targetClass, method.getName(), keyPrefix); + + if (arrayIndex >= 0) { + key += "[" + arrayIndex + "]"; + } + + boolean isEmpty = processConfigBundleBeanSetters(nestedTarget, nestedTargetClass, key, + processedClassRelations, watchAllFields); + + if (isEmpty) { + return null; + } + } + + return nestedTarget; } /** @@ -95,16 +252,15 @@ public Object loadConfiguration(InvocationContext ic) throws Exception { * * @param targetClass target class * @param setter name of the setter method + * @param keyPrefix prefix used for generation of a configuration key * @return key in format prefix.key-name */ - private String getKeyName(Class targetClass, String setter) throws Exception { - - String key; + private String getKeyName(Class targetClass, String setter, String keyPrefix) throws Exception { - // get prefix - String prefix = ((ConfigBundle) targetClass.getAnnotation(ConfigBundle.class)).value(); - if (prefix.isEmpty()) { - prefix = camelCaseToHyphenCase(targetClass.getSimpleName()); + StringBuilder key = new StringBuilder(); + key.append(keyPrefix); + if (!key.toString().isEmpty()) { + key.append("."); } // get ConfigValue @@ -115,48 +271,45 @@ private String getKeyName(Class targetClass, String setter) throws Exception { } if (fieldAnnotation != null && !fieldAnnotation.value().isEmpty()) { - key = prefix + "." + camelCaseToHyphenCase(fieldAnnotation.value()); + key.append(StringUtils.camelCaseToHyphenCase(fieldAnnotation.value())); } else { - key = prefix + "." + camelCaseToHyphenCase(setter.substring(3)); + key.append(StringUtils.camelCaseToHyphenCase(setter.substring(3))); } - return key; + return key.toString(); } /** - * Parse setter name to field name. + * Generate a key prefix from annotation, class name, or parent prefix in case of nested classes. * - * @param setter name of the setter method - * @return field name - */ - private String setterToField(String setter) { - return Character.toLowerCase(setter.charAt(3)) + setter.substring(4); - } - - /** - * Parse upper camel case to lower hyphen case. - * - * @param s string in upper camel case format - * @return string in lower hyphen case format + * @param targetClass target class + * @return key prefix */ - private String camelCaseToHyphenCase(String s) { - - String parsedString = s.substring(0, 1).toLowerCase(); + private String getKeyPrefix(Class targetClass) { - for (char c : s.substring(1).toCharArray()) { + String prefix = ((ConfigBundle) targetClass.getAnnotation(ConfigBundle.class)).value(); - if (Character.isUpperCase(c)) { - parsedString += "-" + Character.toLowerCase(c); - } else { - parsedString += c; - } + if (prefix.isEmpty()) { + prefix = StringUtils.camelCaseToHyphenCase(targetClass.getSimpleName()); + } + if (".".equals(prefix)) { + prefix = ""; } - return parsedString; + return prefix; + } + /** + * Parse setter name to field name. + * + * @param setter name of the setter method + * @return field name + */ + private String setterToField(String setter) { + return Character.toLowerCase(setter.charAt(3)) + setter.substring(4); } /** @@ -168,6 +321,69 @@ private String camelCaseToHyphenCase(String s) { private boolean targetClassIsProxied(Class targetClass) { return targetClass.getCanonicalName().contains("$Proxy"); } + + /** + * Subscribes to an event dispatcher and starts a watch for a given key. + * + * @param target target instance + * @param method method to invoke + * @param watchedKey watched key + * @throws Exception + */ + private void deployWatcher(Object target, Method method, String watchedKey) throws Exception { + + configurationUtil.subscribe(watchedKey, (key, value) -> { + + if (Objects.equals(watchedKey, key)) { + + try { + if (String.class.equals(method.getParameters()[0].getType())) { + method.invoke(target, value); + } else if (Boolean.class.equals(method.getParameters()[0].getType()) || boolean.class.equals(method + .getParameters()[0].getType())) { + method.invoke(target, Boolean.parseBoolean(value)); + } else if (Float.class.equals(method.getParameters()[0].getType()) || float.class.equals(method + .getParameters()[0].getType())) { + try { + method.invoke(target, Float.parseFloat(value)); + } catch (NumberFormatException e) { + log.severe("Exception while storing new value: Number format exception. " + + "Expected: Float. Value: " + value); + } + } else if (Double.class.equals(method.getParameters()[0].getType()) || double.class.equals(method + .getParameters()[0].getType())) { + try { + method.invoke(target, Double.parseDouble(value)); + } catch (NumberFormatException e) { + log.severe("Exception while storing new value: Number format exception. Expected:" + + " Double. Value: " + value); + } + } else if (Integer.class.equals(method.getParameters()[0].getType()) || int.class.equals(method + .getParameters()[0].getType())) { + try { + method.invoke(target, Integer.parseInt(value)); + } catch (NumberFormatException e) { + log.severe("Exception while storing new value: Number format exception. Expected:" + + " Integer. Value: " + value); + } + } else if (Long.class.equals(method.getParameters()[0].getType()) || long.class.equals(method + .getParameters()[0].getType())) { + try { + method.invoke(target, Long.parseLong(value)); + } catch (NumberFormatException e) { + log.severe("Exception while storing new value: Number format exception. Expected:" + + " Long. Value: " + value); + } + } + } catch (IllegalAccessException e) { + log.severe("Illegal access exception: " + e.toString()); + } catch (InvocationTargetException e) { + log.severe("Invocation target exception: " + e.toString()); + } + + } + }); + } } diff --git a/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/producers/ConfigurationUtilProducer.java b/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/producers/ConfigurationUtilProducer.java index 5f3c1756..3ae8e60d 100644 --- a/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/producers/ConfigurationUtilProducer.java +++ b/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/producers/ConfigurationUtilProducer.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.configuration.cdi.producers; import com.kumuluz.ee.configuration.utils.ConfigurationUtil; diff --git a/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/producers/EeConfigProducer.java b/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/producers/EeConfigProducer.java new file mode 100644 index 00000000..685b3384 --- /dev/null +++ b/components/cdi/weld/src/main/java/com/kumuluz/ee/configuration/cdi/producers/EeConfigProducer.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.configuration.cdi.producers; + +import com.kumuluz.ee.common.config.EeConfig; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class EeConfigProducer { + + @Produces + @ApplicationScoped + public EeConfig getConfigurationUtil() { + return EeConfig.getInstance(); + } +} diff --git a/components/cdi/weld/src/main/java/com/kumuluz/ee/logs/cdi/Log.java b/components/cdi/weld/src/main/java/com/kumuluz/ee/logs/cdi/Log.java deleted file mode 100644 index cc903d67..00000000 --- a/components/cdi/weld/src/main/java/com/kumuluz/ee/logs/cdi/Log.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) Sunesis d.o.o. - */ -package com.kumuluz.ee.logs.cdi; - -import javax.enterprise.util.Nonbinding; -import javax.interceptor.InterceptorBinding; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * @author Rok Povse - * @author Marko Skrjanec - */ -@Inherited -@InterceptorBinding -@Retention(RUNTIME) -@Target({ElementType.TYPE, ElementType.METHOD}) -public @interface Log { - @Nonbinding LogParams[] value() default {}; - @Nonbinding boolean methodCall() default true; -} \ No newline at end of file diff --git a/components/cdi/weld/src/main/java/com/kumuluz/ee/logs/cdi/LogParams.java b/components/cdi/weld/src/main/java/com/kumuluz/ee/logs/cdi/LogParams.java deleted file mode 100644 index 7f51c64b..00000000 --- a/components/cdi/weld/src/main/java/com/kumuluz/ee/logs/cdi/LogParams.java +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Copyright (c) Sunesis d.o.o. - */ -package com.kumuluz.ee.logs.cdi; - -/** - * @author Rok Povse - * @author Marko Skrjanec - */ -public enum LogParams { - METRICS, -} diff --git a/components/cdi/weld/src/main/java/com/kumuluz/ee/logs/cdi/interceptors/LogInterceptor.java b/components/cdi/weld/src/main/java/com/kumuluz/ee/logs/cdi/interceptors/LogInterceptor.java deleted file mode 100644 index d72f289b..00000000 --- a/components/cdi/weld/src/main/java/com/kumuluz/ee/logs/cdi/interceptors/LogInterceptor.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (c) Sunesis d.o.o. - */ -package com.kumuluz.ee.logs.cdi.interceptors; - -import com.kumuluz.ee.logs.LogCommons; -import com.kumuluz.ee.logs.LogManager; -import com.kumuluz.ee.logs.cdi.Log; -import com.kumuluz.ee.logs.cdi.LogParams; -import com.kumuluz.ee.logs.messages.SimpleLogMessage; -import com.kumuluz.ee.logs.types.LogMethodContext; -import com.kumuluz.ee.logs.types.LogMethodMessage; - -import javax.annotation.Priority; -import javax.interceptor.AroundInvoke; -import javax.interceptor.Interceptor; -import javax.interceptor.InvocationContext; -import java.util.Arrays; -import java.util.HashMap; - - -/** - * @author Rok Povse - * @author Marko Skrjanec - */ -@Log -@Interceptor -@Priority(Interceptor.Priority.APPLICATION) -public class LogInterceptor { - - @AroundInvoke - public Object logMethodEntryAndExit(InvocationContext context) throws Exception { - - // get annotation either from class or method - Log annotation = context.getMethod().getDeclaredAnnotation(Log.class) != null ? context.getMethod() - .getDeclaredAnnotation(Log.class) : context.getMethod().getDeclaringClass().getDeclaredAnnotation(Log - .class); - - // get annotation params - LogParams[] value = annotation.value(); - boolean methodCall = annotation.methodCall(); - - // get logger - LogCommons logger = LogManager.getCommonsLogger(context.getTarget().getClass().getSuperclass().getName()); - - // set message - LogMethodMessage message = new LogMethodMessage(); - - // set metrics - for (LogParams logParam : value) { - if (LogParams.METRICS.equals(logParam)) { - message.enableMetrics(); - break; - } - } - - SimpleLogMessage msg = new SimpleLogMessage(); - msg.setMessage("Entering method."); - msg.setFields(new HashMap()); - - // set method call - if (methodCall) { - msg.getFields().put("class", context.getMethod().getDeclaringClass().getName()); - msg.getFields().put("method", context.getMethod().getName()); - - if (context.getParameters() != null && context.getParameters().length > 0) { - msg.getFields().put("parameters", Arrays.toString(context.getParameters())); - } - - } - message.enableCall(msg); - - // log entry - LogMethodContext logMethodContext = logger.logMethodEntry(message); - - Object result = context.proceed(); - - // set method call - msg.setMessage("Exiting method."); - msg.getFields().put("result", result != null ? result.toString() : null); - logMethodContext.setCallExitMessage(msg); - - // log exit - logger.logMethodExit(logMethodContext); - - return result; - } -} \ No newline at end of file diff --git a/components/cdi/weld/src/main/java/com/kumuluz/ee/runtime/cdi/producers/EeRuntimeProducer.java b/components/cdi/weld/src/main/java/com/kumuluz/ee/runtime/cdi/producers/EeRuntimeProducer.java new file mode 100644 index 00000000..7b5297a6 --- /dev/null +++ b/components/cdi/weld/src/main/java/com/kumuluz/ee/runtime/cdi/producers/EeRuntimeProducer.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.runtime.cdi.producers; + +import com.kumuluz.ee.common.runtime.EeRuntime; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class EeRuntimeProducer { + + @Produces + @ApplicationScoped + public EeRuntime getConfigurationUtil() { + return EeRuntime.getInstance(); + } +} diff --git a/components/ejb/openejb/pom.xml b/components/ejb/openejb/pom.xml index e7011ffd..ebf5bbd5 100644 --- a/components/ejb/openejb/pom.xml +++ b/components/ejb/openejb/pom.xml @@ -5,7 +5,7 @@ kumuluzee-ejb com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 diff --git a/components/ejb/pom.xml b/components/ejb/pom.xml index a5b6ccf3..02d8a621 100644 --- a/components/ejb/pom.xml +++ b/components/ejb/pom.xml @@ -5,7 +5,7 @@ kumuluzee-components com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom diff --git a/components/el/pom.xml b/components/el/pom.xml index 3c862585..2d5ca3dd 100644 --- a/components/el/pom.xml +++ b/components/el/pom.xml @@ -5,7 +5,7 @@ kumuluzee-components com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom diff --git a/components/el/uel/pom.xml b/components/el/uel/pom.xml index 110addfe..f663aa7a 100644 --- a/components/el/uel/pom.xml +++ b/components/el/uel/pom.xml @@ -5,7 +5,7 @@ kumuluzee-el com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -14,10 +14,6 @@ kumuluzee-el-uel - - 3.0.0 - - com.kumuluz.ee diff --git a/components/el/uel/src/main/java/com/kumuluz/ee/el/ElComponent.java b/components/el/uel/src/main/java/com/kumuluz/ee/el/ElComponent.java index f607df76..541ed991 100644 --- a/components/el/uel/src/main/java/com/kumuluz/ee/el/ElComponent.java +++ b/components/el/uel/src/main/java/com/kumuluz/ee/el/ElComponent.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.el; import com.kumuluz.ee.common.Component; diff --git a/components/jax-rs/jersey/pom.xml b/components/jax-rs/jersey/pom.xml index ea8815d1..38d6cae2 100644 --- a/components/jax-rs/jersey/pom.xml +++ b/components/jax-rs/jersey/pom.xml @@ -5,7 +5,7 @@ kumuluzee-jax-rs com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -14,11 +14,6 @@ kumuluzee-jax-rs-jersey - - 2.24.1 - 2.8.5 - - com.kumuluz.ee @@ -69,23 +64,6 @@ jackson-annotations ${jackson.version} - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/components/jax-rs/jersey/src/main/java/com/kumuluz/ee/jaxrs/JaxRsComponent.java b/components/jax-rs/jersey/src/main/java/com/kumuluz/ee/jaxrs/JaxRsComponent.java index 787f9d5f..80b3a385 100644 --- a/components/jax-rs/jersey/src/main/java/com/kumuluz/ee/jaxrs/JaxRsComponent.java +++ b/components/jax-rs/jersey/src/main/java/com/kumuluz/ee/jaxrs/JaxRsComponent.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jaxrs; import com.kumuluz.ee.common.Component; diff --git a/components/jax-rs/pom.xml b/components/jax-rs/pom.xml index c2f559d1..95c61c9c 100644 --- a/components/jax-rs/pom.xml +++ b/components/jax-rs/pom.xml @@ -5,7 +5,7 @@ kumuluzee-components com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom diff --git a/components/jax-ws/metro/pom.xml b/components/jax-ws/metro/pom.xml index c015d87d..599e654c 100644 --- a/components/jax-ws/metro/pom.xml +++ b/components/jax-ws/metro/pom.xml @@ -5,7 +5,7 @@ kumuluzee-jax-ws com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -14,10 +14,6 @@ kumuluzee-jax-ws-metro - - 2.3.1 - - com.kumuluz.ee diff --git a/components/jax-ws/metro/src/main/java/com/kumuluz/ee/jaxws/metro/JaxWsComponent.java b/components/jax-ws/metro/src/main/java/com/kumuluz/ee/jaxws/metro/JaxWsComponent.java index eccd773b..3b5a9998 100644 --- a/components/jax-ws/metro/src/main/java/com/kumuluz/ee/jaxws/metro/JaxWsComponent.java +++ b/components/jax-ws/metro/src/main/java/com/kumuluz/ee/jaxws/metro/JaxWsComponent.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jaxws.metro; import com.kumuluz.ee.common.Component; diff --git a/components/jax-ws/pom.xml b/components/jax-ws/pom.xml index 34167233..f1c2b13c 100644 --- a/components/jax-ws/pom.xml +++ b/components/jax-ws/pom.xml @@ -5,7 +5,7 @@ kumuluzee-components com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom diff --git a/components/jpa/common/pom.xml b/components/jpa/common/pom.xml index 351a26d7..fb3aef28 100644 --- a/components/jpa/common/pom.xml +++ b/components/jpa/common/pom.xml @@ -5,7 +5,7 @@ kumuluzee-jpa com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -19,15 +19,21 @@ com.kumuluz.ee kumuluzee-common + + + org.eclipse.persistence + javax.persistence + + com.kumuluz.ee kumuluzee-cdi-weld provided - - org.eclipse.persistence - javax.persistence + com.kumuluz.ee + kumuluzee-jta-common + provided diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/JpaService.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/JpaService.java deleted file mode 100644 index f9f33ddd..00000000 --- a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/JpaService.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.kumuluz.ee.jpa.common; - -import com.kumuluz.ee.jpa.common.resources.PersistenceContextResourceFactory; -import com.kumuluz.ee.jpa.common.resources.PersistenceUnitHolder; -import com.kumuluz.ee.jpa.common.resources.PersistenceUnitResourceFactory; -import org.jboss.weld.injection.spi.JpaInjectionServices; -import org.jboss.weld.injection.spi.ResourceReferenceFactory; - -import javax.annotation.Priority; -import javax.enterprise.inject.spi.InjectionPoint; -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.PersistenceContext; -import javax.persistence.PersistenceUnit; - -/** - * @author Tilen Faganel - * @since 1.0.0 - */ -@Priority(1) -public class JpaService implements JpaInjectionServices { - - @Override - public ResourceReferenceFactory registerPersistenceContextInjectionPoint - (InjectionPoint injectionPoint) { - - PersistenceContext pc = injectionPoint.getAnnotated().getAnnotation(PersistenceContext - .class); - - EntityManagerFactory factory = PersistenceUnitHolder.getInstance() - .getEntityManagerFactory(pc.unitName()); - - return new PersistenceContextResourceFactory(factory); - } - - @Override - public ResourceReferenceFactory registerPersistenceUnitInjectionPoint - (InjectionPoint injectionPoint) { - - PersistenceUnit pu = injectionPoint.getAnnotated().getAnnotation(PersistenceUnit.class); - - EntityManagerFactory factory = PersistenceUnitHolder.getInstance() - .getEntityManagerFactory(pu.unitName()); - - return new PersistenceUnitResourceFactory(factory); - } - - @Override - public EntityManager resolvePersistenceContext(InjectionPoint injectionPoint) { - - throw new UnsupportedOperationException(); - } - - @Override - public EntityManagerFactory resolvePersistenceUnit(InjectionPoint injectionPoint) { - - throw new UnsupportedOperationException(); - } - - @Override - public void cleanup() { - } -} diff --git a/common/src/main/java/com/kumuluz/ee/logs/messages/LogMessage.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/PersistenceSettings.java similarity index 84% rename from common/src/main/java/com/kumuluz/ee/logs/messages/LogMessage.java rename to components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/PersistenceSettings.java index 8ec2501b..1ee1c6a7 100644 --- a/common/src/main/java/com/kumuluz/ee/logs/messages/LogMessage.java +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/PersistenceSettings.java @@ -18,17 +18,15 @@ * software. See the License for the specific language governing permissions and * limitations under the License. */ - -package com.kumuluz.ee.logs.messages; +package com.kumuluz.ee.jpa.common; import java.util.Map; /** - * @author Rok Povse - * @author Marko Skrjanec + * @author Tilen Faganel + * @since 2.3.0 */ -public interface LogMessage { +public interface PersistenceSettings { - Map getFields(); - String getMessage(); + Map getPersistenceUnitProperties(); } diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/PersistenceUnitHolder.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/PersistenceUnitHolder.java new file mode 100644 index 00000000..d21e9122 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/PersistenceUnitHolder.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common; + +import com.kumuluz.ee.common.config.PersistenceConfig; +import com.kumuluz.ee.jpa.common.utils.PersistenceUtils; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import java.util.*; + +/** + * @author Tilen Faganel + * @since 1.0.0 + */ +public class PersistenceUnitHolder { + + private PersistenceSettings providerProperties; + private PersistenceConfig config; + + private String defaultUnitName; + + private Map factories = new HashMap<>(); + + private static final PersistenceUnitHolder instance = new PersistenceUnitHolder(); + + private PersistenceUnitHolder() { + + defaultUnitName = PersistenceUtils.getDefaultUnitName().orElse(""); + } + + public static PersistenceUnitHolder getInstance() { + return instance; + } + + public synchronized PersistenceWrapper getEntityManagerFactory(String unitName) { + + PersistenceWrapper wrapper = factories.get(unitName); + + if (wrapper == null) { + + Properties properties = new Properties(); + + if (providerProperties != null && providerProperties.getPersistenceUnitProperties() != null) { + properties.putAll(providerProperties.getPersistenceUnitProperties()); + } + + if (config != null && unitName.equals(config.getUnitName())) { + + Optional.ofNullable(config.getUrl()).ifPresent(u -> properties.put("javax.persistence.jdbc.url", u)); + Optional.ofNullable(config.getUsername()).ifPresent(u -> properties.put("javax.persistence.jdbc.user", u)); + Optional.ofNullable(config.getPassword()).ifPresent(p -> properties.put("javax.persistence.jdbc.password", p)); + } + + EntityManagerFactory factory = Persistence.createEntityManagerFactory(unitName, properties); + TransactionType transactionType = PersistenceUtils.getEntityManagerFactoryTransactionType(factory); + + wrapper = new PersistenceWrapper(factory, transactionType); + + factories.put(unitName, wrapper); + } + + return wrapper; + } + + public String getDefaultUnitName() { + return defaultUnitName; + } + + public void setConfig(PersistenceConfig config) { + this.config = config; + } + + public void setProviderProperties(PersistenceSettings providerProperties) { + this.providerProperties = providerProperties; + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/PersistenceWrapper.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/PersistenceWrapper.java new file mode 100644 index 00000000..307d8c50 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/PersistenceWrapper.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common; + +import javax.persistence.EntityManagerFactory; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public class PersistenceWrapper { + + private EntityManagerFactory entityManagerFactory; + private TransactionType transactionType; + + public PersistenceWrapper(EntityManagerFactory entityManagerFactory, TransactionType transactionType) { + this.entityManagerFactory = entityManagerFactory; + this.transactionType = transactionType; + } + + public EntityManagerFactory getEntityManagerFactory() { + return entityManagerFactory; + } + + public TransactionType getTransactionType() { + return transactionType; + } +} diff --git a/common/src/main/java/com/kumuluz/ee/logs/messages/MethodCallLogMessage.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/TransactionType.java similarity index 87% rename from common/src/main/java/com/kumuluz/ee/logs/messages/MethodCallLogMessage.java rename to components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/TransactionType.java index feaffd9b..b557f506 100644 --- a/common/src/main/java/com/kumuluz/ee/logs/messages/MethodCallLogMessage.java +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/TransactionType.java @@ -18,12 +18,14 @@ * software. See the License for the specific language governing permissions and * limitations under the License. */ - -package com.kumuluz.ee.logs.messages; +package com.kumuluz.ee.jpa.common; /** - * @author Rok Povse - * @author Marko Skrjanec + * @author Tilen Faganel + * @since 2.3.0 */ -public interface MethodCallLogMessage extends LogMessage { +public enum TransactionType { + + RESOURCE_LOCAL, + JTA } diff --git a/common/src/main/java/com/kumuluz/ee/logs/markers/StatusMarker.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/exceptions/NoDefaultPersistenceUnit.java similarity index 72% rename from common/src/main/java/com/kumuluz/ee/logs/markers/StatusMarker.java rename to components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/exceptions/NoDefaultPersistenceUnit.java index 897bcbf7..a8eb584c 100644 --- a/common/src/main/java/com/kumuluz/ee/logs/markers/StatusMarker.java +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/exceptions/NoDefaultPersistenceUnit.java @@ -18,23 +18,16 @@ * software. See the License for the specific language governing permissions and * limitations under the License. */ - -package com.kumuluz.ee.logs.markers; +package com.kumuluz.ee.jpa.common.exceptions; /** - * @author Rok Povse - * @author Marko Skrjanec + * @author Tilen Faganel + * @since 2.3.0 */ -public enum StatusMarker implements Marker { - ENTRY("ENTRY"), EXIT("EXIT"), INVOKE("INVOKE"), RESPOND("RESPOND"); - - private String marker; - - private StatusMarker(String marker) { - this.marker = marker; - } +public class NoDefaultPersistenceUnit extends RuntimeException { - public String toString() { - return marker; + public NoDefaultPersistenceUnit() { + super("Cannot determine a default persistence unit. Either the configuration does not exist or " + + "there are more then one configurations or units defined"); } } diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/EntityManagerWrapper.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/EntityManagerWrapper.java new file mode 100644 index 00000000..659c76a8 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/EntityManagerWrapper.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.injection; + +import javax.persistence.EntityManager; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public interface EntityManagerWrapper { + + EntityManager getEntityManager(); + + void close(); +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/JpaService.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/JpaService.java new file mode 100644 index 00000000..d271c9e6 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/JpaService.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.injection; + +import com.kumuluz.ee.jpa.common.PersistenceUnitHolder; +import com.kumuluz.ee.jpa.common.PersistenceWrapper; +import com.kumuluz.ee.jpa.common.exceptions.NoDefaultPersistenceUnit; +import org.jboss.weld.injection.spi.JpaInjectionServices; +import org.jboss.weld.injection.spi.ResourceReferenceFactory; + +import javax.annotation.Priority; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.PersistenceContext; +import javax.persistence.PersistenceUnit; + +/** + * @author Tilen Faganel + * @since 1.0.0 + */ +@Priority(1) +public class JpaService implements JpaInjectionServices { + + @Override + public ResourceReferenceFactory registerPersistenceContextInjectionPoint + (InjectionPoint injectionPoint) { + + PersistenceUnitHolder holder = PersistenceUnitHolder.getInstance(); + + PersistenceContext pc = injectionPoint.getAnnotated().getAnnotation(PersistenceContext + .class); + String unitName = pc.unitName(); + + if (unitName.isEmpty()) { + + unitName = holder.getDefaultUnitName(); + + if (unitName.isEmpty()) { + throw new NoDefaultPersistenceUnit(); + } + } + + PersistenceWrapper wrapper = holder.getEntityManagerFactory(unitName); + + return new PersistenceContextResourceFactory(unitName, wrapper.getEntityManagerFactory(), + wrapper.getTransactionType(), pc.synchronization()); + } + + @Override + public ResourceReferenceFactory registerPersistenceUnitInjectionPoint + (InjectionPoint injectionPoint) { + + PersistenceUnitHolder holder = PersistenceUnitHolder.getInstance(); + + PersistenceUnit pu = injectionPoint.getAnnotated().getAnnotation(PersistenceUnit.class); + String unitName = pu.unitName(); + + if (unitName.isEmpty()) { + + unitName = holder.getDefaultUnitName(); + + if (unitName.isEmpty()) { + throw new NoDefaultPersistenceUnit(); + } + } + + PersistenceWrapper wrapper = holder.getEntityManagerFactory(unitName); + + return new PersistenceUnitResourceFactory(wrapper.getEntityManagerFactory()); + } + + @Override + public EntityManager resolvePersistenceContext(InjectionPoint injectionPoint) { + + throw new UnsupportedOperationException(); + } + + @Override + public EntityManagerFactory resolvePersistenceUnit(InjectionPoint injectionPoint) { + + throw new UnsupportedOperationException(); + } + + @Override + public void cleanup() { + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/NonTxEntityManagerWrapper.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/NonTxEntityManagerWrapper.java new file mode 100644 index 00000000..a9167dc3 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/NonTxEntityManagerWrapper.java @@ -0,0 +1,29 @@ +package com.kumuluz.ee.jpa.common.injection; + +import javax.persistence.EntityManager; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class NonTxEntityManagerWrapper implements EntityManagerWrapper { + + private EntityManager em; + + public NonTxEntityManagerWrapper(EntityManager em) { + this.em = em; + } + + @Override + public EntityManager getEntityManager() { + return em; + } + + @Override + public void close() { + + if (em.isOpen()) { + em.close(); + } + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/PersistenceContextResource.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/PersistenceContextResource.java new file mode 100644 index 00000000..0c9eeaf9 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/PersistenceContextResource.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.injection; + +import org.jboss.weld.injection.spi.ResourceReference; + +import javax.persistence.EntityManager; + +/** + * @author Tilen Faganel + * @since 1.0.0 + */ +public class PersistenceContextResource implements ResourceReference { + + private EntityManagerWrapper entityManagerWrapper; + + public PersistenceContextResource(EntityManagerWrapper entityManagerWrapper) { + + this.entityManagerWrapper = entityManagerWrapper; + } + + @Override + public EntityManager getInstance() { + + return entityManagerWrapper.getEntityManager(); + } + + @Override + public void release() { + + entityManagerWrapper.close(); + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/PersistenceContextResourceFactory.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/PersistenceContextResourceFactory.java new file mode 100644 index 00000000..b6c3117c --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/PersistenceContextResourceFactory.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.injection; + +import com.kumuluz.ee.jpa.common.TransactionType; +import com.kumuluz.ee.jpa.common.jta.TxScopedEntityManagerFactory; +import com.kumuluz.ee.jta.common.JtaTransactionHolder; +import com.kumuluz.ee.jpa.common.jta.TxScopedEntityManager; +import org.jboss.weld.injection.spi.ResourceReference; +import org.jboss.weld.injection.spi.ResourceReferenceFactory; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.SynchronizationType; +import javax.transaction.TransactionManager; +import javax.transaction.TransactionSynchronizationRegistry; + +/** + * @author Tilen Faganel + * @since 1.0.0 + */ +public class PersistenceContextResourceFactory implements ResourceReferenceFactory { + + private String unitName; + private EntityManagerFactory emf; + private SynchronizationType sync; + private TransactionType transactionType; + + public PersistenceContextResourceFactory(String unitName, EntityManagerFactory emf, TransactionType transactionType, SynchronizationType sync) { + this.unitName = unitName; + this.emf = emf; + this.sync = sync; + this.transactionType = transactionType; + } + + @Override + public ResourceReference createResource() { + + EntityManagerWrapper emWrapper; + + if (transactionType == TransactionType.JTA) { + + emWrapper = TxScopedEntityManagerFactory.buildEntityManagerWrapper(unitName, emf, sync); + } else { + emWrapper = new NonTxEntityManagerWrapper(emf.createEntityManager()); + } + + return new PersistenceContextResource(emWrapper); + } +} \ No newline at end of file diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/PersistenceUnitResource.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/PersistenceUnitResource.java new file mode 100644 index 00000000..809f47c8 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/PersistenceUnitResource.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.injection; + +import org.jboss.weld.injection.spi.ResourceReference; + +import javax.persistence.EntityManagerFactory; + +/** + * @author Tilen Faganel + * @since 1.0.0 + */ +public class PersistenceUnitResource implements ResourceReference { + + private EntityManagerFactory emf; + + public PersistenceUnitResource(EntityManagerFactory emf) { + + this.emf = emf; + } + + @Override + public EntityManagerFactory getInstance() { + + return emf; + } + + @Override + public void release() { + + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/PersistenceUnitResourceFactory.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/PersistenceUnitResourceFactory.java new file mode 100644 index 00000000..c813d832 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/injection/PersistenceUnitResourceFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.injection; + +import org.jboss.weld.injection.spi.ResourceReference; +import org.jboss.weld.injection.spi.ResourceReferenceFactory; + +import javax.persistence.EntityManagerFactory; + +/** + * @author Tilen Faganel + * @since 1.0.0 + */ +public class PersistenceUnitResourceFactory implements + ResourceReferenceFactory { + + private EntityManagerFactory emf; + + public PersistenceUnitResourceFactory(EntityManagerFactory emf) { + + this.emf = emf; + } + + @Override + public ResourceReference createResource() { + + return new PersistenceUnitResource(emf); + } +} diff --git a/common/src/main/java/com/kumuluz/ee/logs/markers/CommonsMarker.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/NonTxEntityManagerHolder.java similarity index 74% rename from common/src/main/java/com/kumuluz/ee/logs/markers/CommonsMarker.java rename to components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/NonTxEntityManagerHolder.java index d8e7b0c1..9b455860 100644 --- a/common/src/main/java/com/kumuluz/ee/logs/markers/CommonsMarker.java +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/NonTxEntityManagerHolder.java @@ -18,23 +18,23 @@ * software. See the License for the specific language governing permissions and * limitations under the License. */ +package com.kumuluz.ee.jpa.common.jta; -package com.kumuluz.ee.logs.markers; +import javax.persistence.EntityManager; /** - * @author Rok Povse - * @author Marko Skrjanec + * @author Tilen Faganel + * @since 2.4.0 */ -public enum CommonsMarker implements Marker { - METHOD("METHOD"), RESOURCE("RESOURCE"); +public class NonTxEntityManagerHolder { - private String marker; + private EntityManager em; - private CommonsMarker(String marker) { - this.marker = marker; + public EntityManager getEntityManager() { + return em; } - public String toString() { - return marker; + public void setEntityManager(EntityManager em) { + this.em = em; } } diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/NonTxQueryWrapper.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/NonTxQueryWrapper.java new file mode 100644 index 00000000..14afe7e1 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/NonTxQueryWrapper.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.jta; + +import javax.persistence.*; +import java.util.*; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class NonTxQueryWrapper implements Query { + + private Query query; + private EntityManager em; + + public NonTxQueryWrapper(Query query, EntityManager em) { + this.query = query; + this.em = em; + } + + @Override + public List getResultList() { + + List resultList = query.getResultList(); + + em.clear(); + + return resultList; + } + + @Override + public Object getSingleResult() { + + Object singleResult = query.getSingleResult(); + + em.clear(); + + return singleResult; + } + + @Override + public int executeUpdate() { + return query.executeUpdate(); + } + + @Override + public Query setMaxResults(int maxResult) { + query.setMaxResults(maxResult); + return this; + } + + @Override + public int getMaxResults() { + return query.getMaxResults(); + } + + @Override + public Query setFirstResult(int startPosition) { + query.setFirstResult(startPosition); + return this; + } + + @Override + public int getFirstResult() { + return query.getFirstResult(); + } + + @Override + public Query setHint(String hintName, Object value) { + query.setHint(hintName, value); + return this; + } + + @Override + public Map getHints() { + return query.getHints(); + } + + @Override + public Query setParameter(Parameter param, T value) { + query.setParameter(param, value); + return this; + } + + @Override + public Query setParameter(Parameter param, Calendar value, TemporalType temporalType) { + query.setParameter(param, value, temporalType); + return this; + } + + @Override + public Query setParameter(Parameter param, Date value, TemporalType temporalType) { + query.setParameter(param, value, temporalType); + return this; + } + + @Override + public Query setParameter(String name, Object value) { + query.setParameter(name, value); + return this; + } + + @Override + public Query setParameter(String name, Calendar value, TemporalType temporalType) { + query.setParameter(name, value, temporalType); + return this; + } + + @Override + public Query setParameter(String name, Date value, TemporalType temporalType) { + query.setParameter(name, value, temporalType); + return this; + } + + @Override + public Query setParameter(int position, Object value) { + query.setParameter(position, value); + return this; + } + + @Override + public Query setParameter(int position, Calendar value, TemporalType temporalType) { + query.setParameter(position, value, temporalType); + return this; + } + + @Override + public Query setParameter(int position, Date value, TemporalType temporalType) { + query.setParameter(position, value, temporalType); + return this; + } + + @Override + public Set> getParameters() { + return query.getParameters(); + } + + @Override + public Parameter getParameter(String name) { + return query.getParameter(name); + } + + @Override + public Parameter getParameter(String name, Class type) { + return query.getParameter(name, type); + } + + @Override + public Parameter getParameter(int position) { + return query.getParameter(position); + } + + @Override + public Parameter getParameter(int position, Class type) { + return query.getParameter(position, type); + } + + @Override + public boolean isBound(Parameter param) { + return query.isBound(param); + } + + @Override + public T getParameterValue(Parameter param) { + return query.getParameterValue(param); + } + + @Override + public Object getParameterValue(String name) { + return query.getParameterValue(name); + } + + @Override + public Object getParameterValue(int position) { + return query.getParameterValue(position); + } + + @Override + public Query setFlushMode(FlushModeType flushMode) { + query.setFlushMode(flushMode); + return this; + } + + @Override + public FlushModeType getFlushMode() { + return query.getFlushMode(); + } + + @Override + public Query setLockMode(LockModeType lockMode) { + query.setLockMode(lockMode); + return this; + } + + @Override + public LockModeType getLockMode() { + return query.getLockMode(); + } + + @Override + public T unwrap(Class cls) { + return query.unwrap(cls); + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/NonTxStoredProcedureQueryWrapper.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/NonTxStoredProcedureQueryWrapper.java new file mode 100644 index 00000000..89eb36be --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/NonTxStoredProcedureQueryWrapper.java @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.jta; + +import javax.persistence.*; +import java.util.*; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class NonTxStoredProcedureQueryWrapper implements StoredProcedureQuery { + + private StoredProcedureQuery storedProcedureQuery; + private EntityManager em; + + public NonTxStoredProcedureQueryWrapper(StoredProcedureQuery storedProcedureQuery, EntityManager em) { + this.storedProcedureQuery = storedProcedureQuery; + this.em = em; + } + + @Override + public StoredProcedureQuery setHint(String hintName, Object value) { + storedProcedureQuery.setHint(hintName, value); + return this; + } + + @Override + public Map getHints() { + return storedProcedureQuery.getHints(); + } + + @Override + public StoredProcedureQuery setParameter(Parameter param, T value) { + storedProcedureQuery.setParameter(param, value); + return this; + } + + @Override + public StoredProcedureQuery setParameter(Parameter param, Calendar value, TemporalType temporalType) { + storedProcedureQuery.setParameter(param, value, temporalType); + return this; + } + + @Override + public StoredProcedureQuery setParameter(Parameter param, Date value, TemporalType temporalType) { + storedProcedureQuery.setParameter(param, value, temporalType); + return this; + } + + @Override + public StoredProcedureQuery setParameter(String name, Object value) { + storedProcedureQuery.setParameter(name, value); + return this; + } + + @Override + public StoredProcedureQuery setParameter(String name, Calendar value, TemporalType temporalType) { + storedProcedureQuery.setParameter(name, value, temporalType); + return this; + } + + @Override + public StoredProcedureQuery setParameter(String name, Date value, TemporalType temporalType) { + storedProcedureQuery.setParameter(name, value, temporalType); + return this; + } + + @Override + public StoredProcedureQuery setParameter(int position, Object value) { + storedProcedureQuery.setParameter(position, value); + return this; + } + + @Override + public StoredProcedureQuery setParameter(int position, Calendar value, TemporalType temporalType) { + storedProcedureQuery.setParameter(position, value, temporalType); + return this; + } + + @Override + public StoredProcedureQuery setParameter(int position, Date value, TemporalType temporalType) { + storedProcedureQuery.setParameter(position, value, temporalType); + return this; + } + + @Override + public Set> getParameters() { + return storedProcedureQuery.getParameters(); + } + + @Override + public Parameter getParameter(String name) { + return storedProcedureQuery.getParameter(name); + } + + @Override + public Parameter getParameter(String name, Class type) { + return storedProcedureQuery.getParameter(name, type); + } + + @Override + public Parameter getParameter(int position) { + return storedProcedureQuery.getParameter(position); + } + + @Override + public Parameter getParameter(int position, Class type) { + return storedProcedureQuery.getParameter(position, type); + } + + @Override + public boolean isBound(Parameter param) { + return storedProcedureQuery.isBound(param); + } + + @Override + public T getParameterValue(Parameter param) { + return storedProcedureQuery.getParameterValue(param); + } + + @Override + public Object getParameterValue(String name) { + return storedProcedureQuery.getParameterValue(name); + } + + @Override + public Object getParameterValue(int position) { + return storedProcedureQuery.getParameterValue(position); + } + + @Override + public StoredProcedureQuery setFlushMode(FlushModeType flushMode) { + storedProcedureQuery.setFlushMode(flushMode); + return this; + } + + @Override + public FlushModeType getFlushMode() { + return storedProcedureQuery.getFlushMode(); + } + + @Override + public Query setLockMode(LockModeType lockMode) { + storedProcedureQuery.setLockMode(lockMode); + return this; + } + + @Override + public LockModeType getLockMode() { + return storedProcedureQuery.getLockMode(); + } + + @Override + public T unwrap(Class cls) { + return storedProcedureQuery.unwrap(cls); + } + + @Override + public StoredProcedureQuery registerStoredProcedureParameter(int position, Class type, ParameterMode mode) { + storedProcedureQuery.registerStoredProcedureParameter(position, type, mode); + return this; + } + + @Override + public StoredProcedureQuery registerStoredProcedureParameter(String parameterName, Class type, ParameterMode mode) { + storedProcedureQuery.registerStoredProcedureParameter(parameterName, type, mode); + return this; + } + + @Override + public Object getOutputParameterValue(int position) { + return storedProcedureQuery.getOutputParameterValue(position); + } + + @Override + public Object getOutputParameterValue(String parameterName) { + return storedProcedureQuery.getOutputParameterValue(parameterName); + } + + @Override + public boolean execute() { + return storedProcedureQuery.execute(); + } + + @Override + public int executeUpdate() { + return storedProcedureQuery.executeUpdate(); + } + + @Override + public Query setMaxResults(int maxResult) { + storedProcedureQuery.setMaxResults(maxResult); + return this; + } + + @Override + public int getMaxResults() { + return storedProcedureQuery.getMaxResults(); + } + + @Override + public Query setFirstResult(int startPosition) { + storedProcedureQuery.setFirstResult(startPosition); + return this; + } + + @Override + public int getFirstResult() { + return storedProcedureQuery.getFirstResult(); + } + + @Override + public List getResultList() { + + List resultList = storedProcedureQuery.getResultList(); + + em.clear(); + + return resultList; + } + + @Override + public Object getSingleResult() { + + Object singleResult = storedProcedureQuery.getSingleResult(); + + em.clear(); + + return singleResult; + } + + @Override + public boolean hasMoreResults() { + return storedProcedureQuery.hasMoreResults(); + } + + @Override + public int getUpdateCount() { + return storedProcedureQuery.getUpdateCount(); + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/NonTxTypedQueryWrapper.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/NonTxTypedQueryWrapper.java new file mode 100644 index 00000000..dccfbc24 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/NonTxTypedQueryWrapper.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.jta; + +import javax.persistence.*; +import java.util.*; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class NonTxTypedQueryWrapper implements TypedQuery { + + private TypedQuery typedQuery; + private EntityManager em; + + public NonTxTypedQueryWrapper(TypedQuery typedQuery, EntityManager em) { + this.typedQuery = typedQuery; + this.em = em; + } + + @Override + public List getResultList() { + + List resultList = typedQuery.getResultList(); + + em.clear(); + + return resultList; + } + + @Override + public X getSingleResult() { + + X singleResult = typedQuery.getSingleResult(); + + em.clear(); + + return singleResult; + } + + @Override + public int executeUpdate() { + return typedQuery.executeUpdate(); + } + + @Override + public TypedQuery setMaxResults(int maxResult) { + typedQuery.setMaxResults(maxResult); + return this; + } + + @Override + public int getMaxResults() { + return typedQuery.getMaxResults(); + } + + @Override + public TypedQuery setFirstResult(int startPosition) { + typedQuery.setFirstResult(startPosition); + return this; + } + + @Override + public int getFirstResult() { + return typedQuery.getFirstResult(); + } + + @Override + public TypedQuery setHint(String hintName, Object value) { + typedQuery.setHint(hintName, value); + return this; + } + + @Override + public Map getHints() { + return typedQuery.getHints(); + } + + @Override + public TypedQuery setParameter(Parameter param, T value) { + typedQuery.setParameter(param, value); + return this; + } + + @Override + public TypedQuery setParameter(Parameter param, Calendar value, TemporalType temporalType) { + typedQuery.setParameter(param, value, temporalType); + return this; + } + + @Override + public TypedQuery setParameter(Parameter param, Date value, TemporalType temporalType) { + typedQuery.setParameter(param, value, temporalType); + return this; + } + + @Override + public TypedQuery setParameter(String name, Object value) { + typedQuery.setParameter(name, value); + return this; + } + + @Override + public TypedQuery setParameter(String name, Calendar value, TemporalType temporalType) { + typedQuery.setParameter(name, value, temporalType); + return this; + } + + @Override + public TypedQuery setParameter(String name, Date value, TemporalType temporalType) { + typedQuery.setParameter(name, value, temporalType); + return this; + } + + @Override + public TypedQuery setParameter(int position, Object value) { + typedQuery.setParameter(position, value); + return this; + } + + @Override + public TypedQuery setParameter(int position, Calendar value, TemporalType temporalType) { + typedQuery.setParameter(position, value, temporalType); + return this; + } + + @Override + public TypedQuery setParameter(int position, Date value, TemporalType temporalType) { + typedQuery.setParameter(position, value, temporalType); + return this; + } + + @Override + public Set> getParameters() { + return typedQuery.getParameters(); + } + + @Override + public Parameter getParameter(String name) { + return typedQuery.getParameter(name); + } + + @Override + public Parameter getParameter(String name, Class type) { + return typedQuery.getParameter(name, type); + } + + @Override + public Parameter getParameter(int position) { + return typedQuery.getParameter(position); + } + + @Override + public Parameter getParameter(int position, Class type) { + return typedQuery.getParameter(position, type); + } + + @Override + public boolean isBound(Parameter param) { + return typedQuery.isBound(param); + } + + @Override + public T getParameterValue(Parameter param) { + return typedQuery.getParameterValue(param); + } + + @Override + public Object getParameterValue(String name) { + return typedQuery.getParameterValue(name); + } + + @Override + public Object getParameterValue(int position) { + return typedQuery.getParameterValue(position); + } + + @Override + public TypedQuery setFlushMode(FlushModeType flushMode) { + typedQuery.setFlushMode(flushMode); + return this; + } + + @Override + public FlushModeType getFlushMode() { + return typedQuery.getFlushMode(); + } + + @Override + public TypedQuery setLockMode(LockModeType lockMode) { + typedQuery.setLockMode(lockMode); + return this; + } + + @Override + public LockModeType getLockMode() { + return typedQuery.getLockMode(); + } + + @Override + public T unwrap(Class cls) { + return typedQuery.unwrap(cls); + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/SyncEntityManagerWrapper.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/SyncEntityManagerWrapper.java new file mode 100644 index 00000000..bf82d13a --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/SyncEntityManagerWrapper.java @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.jta; + +import javax.persistence.*; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaDelete; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.CriteriaUpdate; +import javax.persistence.metamodel.Metamodel; +import java.util.List; +import java.util.Map; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class SyncEntityManagerWrapper implements EntityManager { + + private EntityManager em; + private SynchronizationType sync; + + public SyncEntityManagerWrapper(EntityManager em, SynchronizationType sync) { + this.em = em; + this.sync = sync; + } + + public SynchronizationType getSynchronizationType() { + return sync; + } + + @Override + public void persist(Object entity) { + em.persist(entity); + } + + @Override + public T merge(T entity) { + return em.merge(entity); + } + + @Override + public void remove(Object entity) { + em.remove(entity); + } + + @Override + public T find(Class entityClass, Object primaryKey) { + return em.find(entityClass, primaryKey); + } + + @Override + public T find(Class entityClass, Object primaryKey, Map properties) { + return em.find(entityClass, primaryKey, properties); + } + + @Override + public T find(Class entityClass, Object primaryKey, LockModeType lockMode) { + return em.find(entityClass, primaryKey, lockMode); + } + + @Override + public T find(Class entityClass, Object primaryKey, LockModeType lockMode, Map properties) { + return em.find(entityClass, primaryKey, lockMode, properties); + } + + @Override + public T getReference(Class entityClass, Object primaryKey) { + return em.getReference(entityClass, primaryKey); + } + + @Override + public void flush() { + em.flush(); + } + + @Override + public void setFlushMode(FlushModeType flushMode) { + em.setFlushMode(flushMode); + } + + @Override + public FlushModeType getFlushMode() { + return em.getFlushMode(); + } + + @Override + public void lock(Object entity, LockModeType lockMode) { + em.lock(entity, lockMode); + } + + @Override + public void lock(Object entity, LockModeType lockMode, Map properties) { + em.lock(entity, lockMode, properties); + } + + @Override + public void refresh(Object entity) { + em.refresh(entity); + } + + @Override + public void refresh(Object entity, Map properties) { + em.refresh(entity, properties); + } + + @Override + public void refresh(Object entity, LockModeType lockMode) { + em.refresh(entity, lockMode); + } + + @Override + public void refresh(Object entity, LockModeType lockMode, Map properties) { + em.refresh(entity, lockMode, properties); + } + + @Override + public void clear() { + em.clear(); + } + + @Override + public void detach(Object entity) { + em.detach(entity); + } + + @Override + public boolean contains(Object entity) { + return em.contains(entity); + } + + @Override + public LockModeType getLockMode(Object entity) { + return em.getLockMode(entity); + } + + @Override + public void setProperty(String propertyName, Object value) { + em.setProperty(propertyName, value); + } + + @Override + public Map getProperties() { + return em.getProperties(); + } + + @Override + public Query createQuery(String qlString) { + return em.createQuery(qlString); + } + + @Override + public TypedQuery createQuery(CriteriaQuery criteriaQuery) { + return em.createQuery(criteriaQuery); + } + + @Override + public Query createQuery(CriteriaUpdate updateQuery) { + return em.createQuery(updateQuery); + } + + @Override + public Query createQuery(CriteriaDelete deleteQuery) { + return em.createQuery(deleteQuery); + } + + @Override + public TypedQuery createQuery(String qlString, Class resultClass) { + return em.createQuery(qlString, resultClass); + } + + @Override + public Query createNamedQuery(String name) { + return em.createNamedQuery(name); + } + + @Override + public TypedQuery createNamedQuery(String name, Class resultClass) { + return em.createNamedQuery(name, resultClass); + } + + @Override + public Query createNativeQuery(String sqlString) { + return em.createNativeQuery(sqlString); + } + + @Override + public Query createNativeQuery(String sqlString, Class resultClass) { + return em.createNativeQuery(sqlString, resultClass); + } + + @Override + public Query createNativeQuery(String sqlString, String resultSetMapping) { + return em.createNativeQuery(sqlString, resultSetMapping); + } + + @Override + public StoredProcedureQuery createNamedStoredProcedureQuery(String name) { + return em.createNamedStoredProcedureQuery(name); + } + + @Override + public StoredProcedureQuery createStoredProcedureQuery(String procedureName) { + return em.createNamedStoredProcedureQuery(procedureName); + } + + @Override + public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) { + return em.createStoredProcedureQuery(procedureName, resultClasses); + } + + @Override + public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) { + return em.createStoredProcedureQuery(procedureName, resultSetMappings); + } + + @Override + public void joinTransaction() { + em.joinTransaction(); + } + + @Override + public boolean isJoinedToTransaction() { + return em.isJoinedToTransaction(); + } + + @Override + public T unwrap(Class cls) { + return em.unwrap(cls); + } + + @Override + public Object getDelegate() { + return em.getDelegate(); + } + + @Override + public void close() { + em.close(); + } + + @Override + public boolean isOpen() { + return em.isOpen(); + } + + @Override + public EntityTransaction getTransaction() { + return em.getTransaction(); + } + + @Override + public EntityManagerFactory getEntityManagerFactory() { + return em.getEntityManagerFactory(); + } + + @Override + public CriteriaBuilder getCriteriaBuilder() { + return em.getCriteriaBuilder(); + } + + @Override + public Metamodel getMetamodel() { + return em.getMetamodel(); + } + + @Override + public EntityGraph createEntityGraph(Class rootType) { + return em.createEntityGraph(rootType); + } + + @Override + public EntityGraph createEntityGraph(String graphName) { + return em.createEntityGraph(graphName); + } + + @Override + public EntityGraph getEntityGraph(String graphName) { + return em.getEntityGraph(graphName); + } + + @Override + public List> getEntityGraphs(Class entityClass) { + return em.getEntityGraphs(entityClass); + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/TxScopedEntityManager.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/TxScopedEntityManager.java new file mode 100644 index 00000000..567b12d9 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/TxScopedEntityManager.java @@ -0,0 +1,557 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.jta; + +import com.kumuluz.ee.jta.common.utils.TxUtils; + +import javax.persistence.*; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaDelete; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.CriteriaUpdate; +import javax.persistence.metamodel.Metamodel; +import javax.transaction.TransactionManager; +import javax.transaction.TransactionSynchronizationRegistry; +import java.util.List; +import java.util.Map; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class TxScopedEntityManager implements EntityManager { + + private String unitName; + private EntityManagerFactory emf; + private SynchronizationType sync; + private TransactionManager transactionManager; + private TransactionSynchronizationRegistry transactionSynchronizationRegistry; + private NonTxEntityManagerHolder nonTxEmHolder; + + public TxScopedEntityManager(String unitName, EntityManagerFactory emf, SynchronizationType sync, TransactionManager transactionManager, TransactionSynchronizationRegistry transactionSynchronizationRegistry, NonTxEntityManagerHolder nonTxEmHolder) { + this.unitName = unitName; + this.emf = emf; + this.sync = sync; + this.transactionManager = transactionManager; + this.transactionSynchronizationRegistry = transactionSynchronizationRegistry; + this.nonTxEmHolder = nonTxEmHolder; + } + + @Override + public void persist(Object entity) { + + validateActiveTransaction(); + + getEntityManager().persist(entity); + } + + @Override + public T merge(T entity) { + + validateActiveTransaction(); + + return getEntityManager().merge(entity); + } + + @Override + public void remove(Object entity) { + + validateActiveTransaction(); + + getEntityManager().remove(entity); + } + + @Override + public T find(Class entityClass, Object primaryKey) { + + EntityManager em = getEntityManager(); + + T result = em.find(entityClass, primaryKey); + + detachLoadedNonTxEntities(em); + + return result; + } + + @Override + public T find(Class entityClass, Object primaryKey, Map properties) { + + EntityManager em = getEntityManager(); + + T result = em.find(entityClass, primaryKey, properties); + + detachLoadedNonTxEntities(em); + + return result; + } + + @Override + public T find(Class entityClass, Object primaryKey, LockModeType lockMode) { + + EntityManager em = getEntityManager(); + + T result = em.find(entityClass, primaryKey, lockMode); + + detachLoadedNonTxEntities(em); + + return result; + } + + @Override + public T find(Class entityClass, Object primaryKey, LockModeType lockMode, Map properties) { + + EntityManager em = getEntityManager(); + + T result = em.find(entityClass, primaryKey, lockMode, properties); + + detachLoadedNonTxEntities(em); + + return result; + } + + @Override + public T getReference(Class entityClass, Object primaryKey) { + + EntityManager em = getEntityManager(); + + T result = em.getReference(entityClass, primaryKey); + + detachLoadedNonTxEntities(em); + + return result; + } + + @Override + public void flush() { + + getEntityManager().flush(); + } + + @Override + public void setFlushMode(FlushModeType flushMode) { + + getEntityManager().setFlushMode(flushMode); + } + + @Override + public FlushModeType getFlushMode() { + + return getEntityManager().getFlushMode(); + } + + @Override + public void lock(Object entity, LockModeType lockMode) { + + getEntityManager().lock(entity, lockMode); + } + + @Override + public void lock(Object entity, LockModeType lockMode, Map properties) { + + getEntityManager().lock(entity, lockMode, properties); + } + + @Override + public void refresh(Object entity) { + + validateActiveTransaction(); + + getEntityManager().refresh(entity); + } + + @Override + public void refresh(Object entity, Map properties) { + + validateActiveTransaction(); + + getEntityManager().refresh(entity, properties); + } + + @Override + public void refresh(Object entity, LockModeType lockMode) { + + validateActiveTransaction(); + + getEntityManager().refresh(entity, lockMode); + } + + @Override + public void refresh(Object entity, LockModeType lockMode, Map properties) { + + validateActiveTransaction(); + + getEntityManager().refresh(entity, lockMode, properties); + } + + @Override + public void clear() { + + getEntityManager().clear(); + } + + @Override + public void detach(Object entity) { + + getEntityManager().detach(entity); + } + + @Override + public boolean contains(Object entity) { + + return getEntityManager().contains(entity); + } + + @Override + public LockModeType getLockMode(Object entity) { + + return getEntityManager().getLockMode(entity); + } + + @Override + public void setProperty(String propertyName, Object value) { + + getEntityManager().setProperty(propertyName, value); + } + + @Override + public Map getProperties() { + + return getEntityManager().getProperties(); + } + + @Override + public Query createQuery(String qlString) { + + EntityManager em = getEntityManager(); + + Query query = em.createQuery(qlString); + + return detachLoadedNonTxQueryEntities(query, em); + } + + @Override + public TypedQuery createQuery(CriteriaQuery criteriaQuery) { + + EntityManager em = getEntityManager(); + + TypedQuery typedQuery = em.createQuery(criteriaQuery); + + return detachLoadedNonTxTypedQueryEntities(typedQuery, em); + } + + @Override + public Query createQuery(CriteriaUpdate updateQuery) { + + return getEntityManager().createQuery(updateQuery); + } + + @Override + public Query createQuery(CriteriaDelete deleteQuery) { + + return getEntityManager().createQuery(deleteQuery); + } + + @Override + public TypedQuery createQuery(String qlString, Class resultClass) { + + EntityManager em = getEntityManager(); + + TypedQuery typedQuery = em.createQuery(qlString, resultClass); + + return detachLoadedNonTxTypedQueryEntities(typedQuery, em); + } + + @Override + public Query createNamedQuery(String name) { + + EntityManager em = getEntityManager(); + + Query query = em.createNamedQuery(name); + + return detachLoadedNonTxQueryEntities(query, em); + } + + @Override + public TypedQuery createNamedQuery(String name, Class resultClass) { + + EntityManager em = getEntityManager(); + + TypedQuery typedQuery = em.createNamedQuery(name, resultClass); + + return detachLoadedNonTxTypedQueryEntities(typedQuery, em); + } + + @Override + public Query createNativeQuery(String sqlString) { + + EntityManager em = getEntityManager(); + + Query query = em.createNativeQuery(sqlString); + + return detachLoadedNonTxQueryEntities(query, em); + } + + @Override + public Query createNativeQuery(String sqlString, Class resultClass) { + + EntityManager em = getEntityManager(); + + Query query = em.createNativeQuery(sqlString, resultClass); + + return detachLoadedNonTxQueryEntities(query, em); + } + + @Override + public Query createNativeQuery(String sqlString, String resultSetMapping) { + + EntityManager em = getEntityManager(); + + Query query = em.createNativeQuery(sqlString, resultSetMapping); + + return detachLoadedNonTxQueryEntities(query, em); + } + + @Override + public StoredProcedureQuery createNamedStoredProcedureQuery(String name) { + + EntityManager em = getEntityManager(); + + StoredProcedureQuery storedProcedureQuery = em.createNamedStoredProcedureQuery(name); + + return detachLoadedNonTxStoredProcedureQueryEntities(storedProcedureQuery, em); + } + + @Override + public StoredProcedureQuery createStoredProcedureQuery(String procedureName) { + + EntityManager em = getEntityManager(); + + StoredProcedureQuery storedProcedureQuery = em.createStoredProcedureQuery(procedureName); + + return detachLoadedNonTxStoredProcedureQueryEntities(storedProcedureQuery, em); + } + + @Override + public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) { + + EntityManager em = getEntityManager(); + + StoredProcedureQuery storedProcedureQuery = em.createStoredProcedureQuery(procedureName, resultClasses); + + return detachLoadedNonTxStoredProcedureQueryEntities(storedProcedureQuery, em); + } + + @Override + public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) { + + EntityManager em = getEntityManager(); + + StoredProcedureQuery storedProcedureQuery = em.createStoredProcedureQuery(procedureName, resultSetMappings); + + return detachLoadedNonTxStoredProcedureQueryEntities(storedProcedureQuery, em); + } + + @Override + public void joinTransaction() { + + getEntityManager().joinTransaction(); + } + + @Override + public boolean isJoinedToTransaction() { + + return getEntityManager().isJoinedToTransaction(); + } + + @Override + public T unwrap(Class cls) { + + return getEntityManager().unwrap(cls); + } + + @Override + public Object getDelegate() { + + return getEntityManager().getDelegate(); + } + + @Override + public void close() { + + throw new IllegalStateException("Cannot closed a transaction managed entity manager."); + } + + @Override + public boolean isOpen() { + + return getEntityManager().isOpen(); + } + + @Override + public EntityTransaction getTransaction() { + + return getEntityManager().getTransaction(); + } + + @Override + public EntityManagerFactory getEntityManagerFactory() { + + return getEntityManager().getEntityManagerFactory(); + } + + @Override + public CriteriaBuilder getCriteriaBuilder() { + + return getEntityManager().getCriteriaBuilder(); + } + + @Override + public Metamodel getMetamodel() { + + return getEntityManager().getMetamodel(); + } + + @Override + public EntityGraph createEntityGraph(Class rootType) { + + return getEntityManager().createEntityGraph(rootType); + } + + @Override + public EntityGraph createEntityGraph(String graphName) { + + return getEntityManager().createEntityGraph(graphName); + } + + @Override + public EntityGraph getEntityGraph(String graphName) { + + return getEntityManager().getEntityGraph(graphName); + } + + @Override + public List> getEntityGraphs(Class entityClass) { + + return getEntityManager().getEntityGraphs(entityClass); + } + + //// Private logic methods + + private EntityManager getEntityManager() { + + EntityManager em; + + if (TxUtils.isActive(transactionManager)) { + + em = (EntityManager) transactionSynchronizationRegistry.getResource(unitName); + + if (em == null) { + + em = createEntityManager(); + + transactionSynchronizationRegistry.registerInterposedSynchronization(new TxSynchronization(em)); + transactionSynchronizationRegistry.putResource(unitName, em); + } else { + + validateCompatibleSyncTypes(em); + } + } else { + + em = nonTxEmHolder.getEntityManager(); + + if (em == null) { + + em = createEntityManager(); + + nonTxEmHolder.setEntityManager(em); + } + } + + return em; + } + + private EntityManager createEntityManager() { + + if (sync.equals(SynchronizationType.UNSYNCHRONIZED)) { + + return new SyncEntityManagerWrapper(emf.createEntityManager(sync), sync); + } + + return emf.createEntityManager(); + } + + private void detachLoadedNonTxEntities(EntityManager em) { + + if (!TxUtils.isActive(transactionManager)) { + + em.clear(); + } + } + + private Query detachLoadedNonTxQueryEntities(Query query, EntityManager em) { + + if (!TxUtils.isActive(transactionManager)) { + + return new NonTxQueryWrapper(query, em); + } + + return query; + } + + private TypedQuery detachLoadedNonTxTypedQueryEntities(TypedQuery query, EntityManager em) { + + if (!TxUtils.isActive(transactionManager)) { + + return new NonTxTypedQueryWrapper<>(query, em); + } + + return query; + } + + private StoredProcedureQuery detachLoadedNonTxStoredProcedureQueryEntities(StoredProcedureQuery procedureQuery, EntityManager em) { + + if (!TxUtils.isActive(transactionManager)) { + + return new NonTxStoredProcedureQueryWrapper(procedureQuery, em); + } + + return procedureQuery; + } + + private void validateActiveTransaction() { + + if (!TxUtils.isActive(transactionManager)) { + + throw new TransactionRequiredException("An active transaction is required in order to perform this function."); + } + } + + private void validateCompatibleSyncTypes(EntityManager existingEm) { + + if (existingEm instanceof SyncEntityManagerWrapper && + ((SyncEntityManagerWrapper) existingEm).getSynchronizationType().equals(sync)) { + + throw new IllegalStateException("Incompatible SynchronizationType for the same PersistenceContext across " + + "multiple injection points. The SynchronizationType can not be SYNCHRONIZED if a " + + "previous one that is UNSYCHRONIZED already exists."); + } + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/TxScopedEntityManagerFactory.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/TxScopedEntityManagerFactory.java new file mode 100644 index 00000000..f6750b0b --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/TxScopedEntityManagerFactory.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.jta; + +import com.kumuluz.ee.jpa.common.injection.EntityManagerWrapper; +import com.kumuluz.ee.jta.common.JtaTransactionHolder; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.SynchronizationType; +import javax.transaction.TransactionManager; +import javax.transaction.TransactionSynchronizationRegistry; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class TxScopedEntityManagerFactory { + + public static EntityManagerWrapper buildEntityManagerWrapper(String unitName, EntityManagerFactory emf, SynchronizationType sync) { + + JtaTransactionHolder jtaHolder = JtaTransactionHolder.getInstance(); + + TransactionManager transactionManager = jtaHolder.getTransactionManager(); + TransactionSynchronizationRegistry transactionSynchronizationRegistry = jtaHolder.getTransactionSynchronizationRegistry(); + + NonTxEntityManagerHolder emHolder = new NonTxEntityManagerHolder(); + + EntityManager em = new TxScopedEntityManager(unitName, emf, sync, transactionManager, transactionSynchronizationRegistry, emHolder); + + return new TxScopedEntityManagerWrapper(em, emHolder); + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/TxScopedEntityManagerWrapper.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/TxScopedEntityManagerWrapper.java new file mode 100644 index 00000000..6b94ada5 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/TxScopedEntityManagerWrapper.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.jta; + +import com.kumuluz.ee.jpa.common.injection.EntityManagerWrapper; +import com.kumuluz.ee.jpa.common.jta.NonTxEntityManagerHolder; + +import javax.persistence.EntityManager; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class TxScopedEntityManagerWrapper implements EntityManagerWrapper { + + private EntityManager em; + private NonTxEntityManagerHolder nonTxEmHolder; + + public TxScopedEntityManagerWrapper(EntityManager em, NonTxEntityManagerHolder nonTxEmHolder) { + this.em = em; + this.nonTxEmHolder = nonTxEmHolder; + } + + @Override + public EntityManager getEntityManager() { + return em; + } + + @Override + public void close() { + + EntityManager nonTxEm = nonTxEmHolder.getEntityManager(); + + if (nonTxEm != null && nonTxEm.isOpen()) { + + nonTxEm.close(); + + nonTxEmHolder.setEntityManager(null); + } + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/TxSynchronization.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/TxSynchronization.java new file mode 100644 index 00000000..44935869 --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/jta/TxSynchronization.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.jta; + +import javax.persistence.EntityManager; +import javax.transaction.Synchronization; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class TxSynchronization implements Synchronization { + + private EntityManager em; + + public TxSynchronization(EntityManager em) { + this.em = em; + } + + @Override + public void beforeCompletion() { + } + + @Override + public void afterCompletion(int status) { + + if (em != null && em.isOpen()) { + + em.close(); + } + } +} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceContextResource.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceContextResource.java deleted file mode 100644 index d0e3f8cc..00000000 --- a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceContextResource.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.kumuluz.ee.jpa.common.resources; - -import org.jboss.weld.injection.spi.ResourceReference; - -import javax.persistence.EntityManager; - -/** - * @author Tilen Faganel - * @since 1.0.0 - */ -public class PersistenceContextResource implements ResourceReference { - - private EntityManager em; - - public PersistenceContextResource(EntityManager em) { - - this.em = em; - } - - @Override - public EntityManager getInstance() { - - return em; - } - - @Override - public void release() { - - em.close(); - } -} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceContextResourceFactory.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceContextResourceFactory.java deleted file mode 100644 index 05fbb91a..00000000 --- a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceContextResourceFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.kumuluz.ee.jpa.common.resources; - -import org.jboss.weld.injection.spi.ResourceReference; -import org.jboss.weld.injection.spi.ResourceReferenceFactory; - -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; - -/** - * @author Tilen Faganel - * @since 1.0.0 - */ -public class PersistenceContextResourceFactory implements ResourceReferenceFactory { - - private EntityManagerFactory emf; - - public PersistenceContextResourceFactory(javax.persistence.EntityManagerFactory emf) { - - this.emf = emf; - } - - @Override - public ResourceReference createResource() { - - return new PersistenceContextResource(emf.createEntityManager()); - } -} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceUnitHolder.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceUnitHolder.java deleted file mode 100644 index 6360c413..00000000 --- a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceUnitHolder.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.kumuluz.ee.jpa.common.resources; - -import com.kumuluz.ee.common.config.PersistenceConfig; - -import javax.persistence.EntityManagerFactory; -import javax.persistence.Persistence; -import java.util.*; - -/** - * @author Tilen Faganel - * @since 1.0.0 - */ -public class PersistenceUnitHolder { - - private List configs; - - private Map factories = new HashMap<>(); - - private static final PersistenceUnitHolder instance = new PersistenceUnitHolder(); - - public synchronized EntityManagerFactory getEntityManagerFactory(String unitName) { - - EntityManagerFactory factory = factories.get(unitName); - - if (factory == null) { - - Properties properties = new Properties(); - - Optional config = configs.stream() - .filter(c -> unitName.equals(c.getUnitName())) - .findFirst(); - - config.ifPresent(c -> { - - Optional.ofNullable(c.getUrl()).ifPresent(u -> properties.put("javax.persistence.jdbc.url", u)); - Optional.ofNullable(c.getUsername()).ifPresent(u -> properties.put("javax.persistence.jdbc.user", u)); - Optional.ofNullable(c.getPassword()).ifPresent(p -> properties.put("javax.persistence.jdbc.password", p)); - }); - - factory = Persistence.createEntityManagerFactory(unitName, properties); - - factories.put(unitName, factory); - } - - return factory; - } - - public void setConfigs(List configs) { - - this.configs = configs; - } - - public static PersistenceUnitHolder getInstance() { - - return instance; - } -} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceUnitResource.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceUnitResource.java deleted file mode 100644 index a9fe9383..00000000 --- a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceUnitResource.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.kumuluz.ee.jpa.common.resources; - -import org.jboss.weld.injection.spi.ResourceReference; - -import javax.persistence.EntityManagerFactory; - -/** - * @author Tilen Faganel - * @since 1.0.0 - */ -public class PersistenceUnitResource implements ResourceReference { - - private EntityManagerFactory emf; - - public PersistenceUnitResource(EntityManagerFactory emf) { - - this.emf = emf; - } - - @Override - public EntityManagerFactory getInstance() { - - return emf; - } - - @Override - public void release() { - - } -} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceUnitResourceFactory.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceUnitResourceFactory.java deleted file mode 100644 index 714f80af..00000000 --- a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/resources/PersistenceUnitResourceFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.kumuluz.ee.jpa.common.resources; - -import org.jboss.weld.injection.spi.ResourceReference; -import org.jboss.weld.injection.spi.ResourceReferenceFactory; - -import javax.persistence.EntityManagerFactory; - -/** - * @author Tilen Faganel - * @since 1.0.0 - */ -public class PersistenceUnitResourceFactory implements - ResourceReferenceFactory { - - private EntityManagerFactory emf; - - public PersistenceUnitResourceFactory(EntityManagerFactory emf) { - - this.emf = emf; - } - - @Override - public ResourceReference createResource() { - - return new PersistenceUnitResource(emf); - } -} diff --git a/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/utils/PersistenceUtils.java b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/utils/PersistenceUtils.java new file mode 100644 index 00000000..8c692c3a --- /dev/null +++ b/components/jpa/common/src/main/java/com/kumuluz/ee/jpa/common/utils/PersistenceUtils.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.common.utils; + +import com.kumuluz.ee.jpa.common.TransactionType; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; +import java.util.Optional; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public class PersistenceUtils { + + private static final String PERSISTENCE_XML = "META-INF/persistence.xml"; + + public static TransactionType getEntityManagerFactoryTransactionType(EntityManagerFactory emf) { + + EntityManager manager = emf.createEntityManager(); + + try { + manager.getTransaction(); + + return TransactionType.RESOURCE_LOCAL; + } catch (IllegalStateException e) { + + manager.close(); + return TransactionType.JTA; + } + } + + public static Optional getDefaultUnitName() { + + Document document; + + try { + Enumeration enumeration = PersistenceUtils.class.getClassLoader().getResources(PERSISTENCE_XML); + + if (!enumeration.hasMoreElements()) { + return Optional.empty(); + } + + enumeration.nextElement(); + + if (enumeration.hasMoreElements()) { + return Optional.empty(); + } + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + + document = builder.parse(PersistenceUtils.class.getClassLoader() + .getResourceAsStream(PERSISTENCE_XML)); + + } catch (IOException | ParserConfigurationException | SAXException ex) { + return Optional.empty(); + } + + String rootElementName = document.getDocumentElement().getTagName(); + + if (!rootElementName.equals("persistence")) { + return Optional.empty(); + } + + NodeList childNodes = document.getDocumentElement().getElementsByTagName("persistence-unit"); + + if (childNodes.getLength() != 1) { + return Optional.empty(); + } + + String pu = childNodes.item(0).getNodeName(); + + if (!pu.equals("persistence-unit")) { + return Optional.empty(); + } + + String puName = childNodes.item(0).getAttributes().getNamedItem("name").getNodeValue(); + + if (puName != null && !puName.isEmpty()) { + return Optional.of(puName); + } + + return Optional.empty(); + } +} diff --git a/components/jpa/common/src/main/resources/META-INF/services/org.jboss.weld.bootstrap.api.Service b/components/jpa/common/src/main/resources/META-INF/services/org.jboss.weld.bootstrap.api.Service index 5c2ccd7c..8b5bc979 100644 --- a/components/jpa/common/src/main/resources/META-INF/services/org.jboss.weld.bootstrap.api.Service +++ b/components/jpa/common/src/main/resources/META-INF/services/org.jboss.weld.bootstrap.api.Service @@ -1 +1 @@ -com.kumuluz.ee.jpa.common.JpaService \ No newline at end of file +com.kumuluz.ee.jpa.common.injection.JpaService \ No newline at end of file diff --git a/components/jpa/eclipselink/pom.xml b/components/jpa/eclipselink/pom.xml index 5f234281..cdd96eaf 100644 --- a/components/jpa/eclipselink/pom.xml +++ b/components/jpa/eclipselink/pom.xml @@ -5,7 +5,7 @@ kumuluzee-jpa com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -14,10 +14,6 @@ kumuluzee-jpa-eclipselink - - 2.6.4 - - com.kumuluz.ee @@ -35,6 +31,12 @@ + + + com.kumuluz.ee + kumuluzee-jta-common + provided + \ No newline at end of file diff --git a/common/src/main/java/com/kumuluz/ee/logs/messages/SimpleLogMessage.java b/components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/EclipseLinkSettings.java similarity index 57% rename from common/src/main/java/com/kumuluz/ee/logs/messages/SimpleLogMessage.java rename to components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/EclipseLinkSettings.java index 8e504dad..7363783b 100644 --- a/common/src/main/java/com/kumuluz/ee/logs/messages/SimpleLogMessage.java +++ b/components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/EclipseLinkSettings.java @@ -18,45 +18,35 @@ * software. See the License for the specific language governing permissions and * limitations under the License. */ +package com.kumuluz.ee.jpa.eclipselink; -package com.kumuluz.ee.logs.messages; +import com.kumuluz.ee.jpa.common.PersistenceSettings; +import org.eclipse.persistence.config.PersistenceUnitProperties; import java.util.HashMap; import java.util.Map; /** - * @author Rok Povse - * @author Marko Skrjanec + * @author Tilen Faganel + * @since 2.3.0 */ -public class SimpleLogMessage implements MethodCallLogMessage, MethodCallExitLogMessage, ResourceInvokeLogMessage, - ResourceInvokeEndLogMessage { +public class EclipseLinkSettings implements PersistenceSettings { - private String message; + private Map properties = new HashMap<>(); - private Map fields; + private Boolean jtaPresent; - @Override - public Map getFields() { - return fields; + EclipseLinkSettings(Boolean jtaPresent) { + this.jtaPresent = jtaPresent; } @Override - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } + public Map getPersistenceUnitProperties() { - public void setFields(Map fields) { - this.fields = fields; - } - - public void addField(String key, String value) { - if (fields == null) { - fields = new HashMap(); + if (jtaPresent) { + properties.put(PersistenceUnitProperties.TARGET_SERVER, KumuluzPlatform.class.getName()); } - fields.put(key,value); + + return properties; } } diff --git a/components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/JpaComponent.java b/components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/JpaComponent.java index 0a5d2ab6..06dbf687 100644 --- a/components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/JpaComponent.java +++ b/components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/JpaComponent.java @@ -1,11 +1,32 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jpa.eclipselink; import com.kumuluz.ee.common.Component; import com.kumuluz.ee.common.config.EeConfig; import com.kumuluz.ee.common.dependencies.EeComponentDef; import com.kumuluz.ee.common.dependencies.EeComponentType; +import com.kumuluz.ee.common.runtime.EeRuntime; import com.kumuluz.ee.common.wrapper.KumuluzServerWrapper; -import com.kumuluz.ee.jpa.common.resources.PersistenceUnitHolder; +import com.kumuluz.ee.jpa.common.PersistenceUnitHolder; import java.util.logging.Logger; @@ -21,7 +42,13 @@ public class JpaComponent implements Component { @Override public void init(KumuluzServerWrapper server, EeConfig eeConfig) { - PersistenceUnitHolder.getInstance().setConfigs(eeConfig.getPersistenceConfigs()); + PersistenceUnitHolder holder = PersistenceUnitHolder.getInstance(); + + // Check if JTA is present in the runtime + Boolean jtaPresent = EeRuntime.getInstance().getEeComponents().stream().anyMatch(c -> c.getType().equals(EeComponentType.JTA)); + + holder.setConfig(eeConfig.getPersistenceConfig()); + holder.setProviderProperties(new EclipseLinkSettings(jtaPresent)); } @Override diff --git a/components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/KumuluzPlatform.java b/components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/KumuluzPlatform.java new file mode 100644 index 00000000..24926106 --- /dev/null +++ b/components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/KumuluzPlatform.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.eclipselink; + +import org.eclipse.persistence.platform.server.ServerPlatformBase; +import org.eclipse.persistence.sessions.DatabaseSession; + +/** + * @author Marcos Koch Salvador + * @since 2.3.0 + */ +public class KumuluzPlatform extends ServerPlatformBase { + + public KumuluzPlatform(DatabaseSession newDatabaseSession) { + super(newDatabaseSession); + } + + @Override + public Class getExternalTransactionControllerClass() { + return KumuluzTransactionController.class; + } + +} diff --git a/components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/KumuluzTransactionController.java b/components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/KumuluzTransactionController.java new file mode 100644 index 00000000..cd0896b6 --- /dev/null +++ b/components/jpa/eclipselink/src/main/java/com/kumuluz/ee/jpa/eclipselink/KumuluzTransactionController.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jpa.eclipselink; + +import com.kumuluz.ee.jta.common.JtaTransactionHolder; +import org.eclipse.persistence.transaction.JTATransactionController; + +import javax.transaction.TransactionManager; + +/** + * @author Marcos Koch Salvador + * @since 2.3.0 + */ +public class KumuluzTransactionController extends JTATransactionController { + + @Override + protected TransactionManager acquireTransactionManager() throws Exception { + return JtaTransactionHolder.getInstance().getTransactionManager(); + } +} diff --git a/components/jpa/hibernate/pom.xml b/components/jpa/hibernate/pom.xml index 1a6ab543..3dd3830e 100644 --- a/components/jpa/hibernate/pom.xml +++ b/components/jpa/hibernate/pom.xml @@ -5,7 +5,7 @@ kumuluzee-jpa com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -14,10 +14,6 @@ kumuluzee-jpa-hibernate - - 5.2.5.Final - - com.kumuluz.ee @@ -28,6 +24,16 @@ org.hibernate hibernate-core ${hibernate.version} + + + org.jboss.logging + jboss-logging + + + + + org.jboss.logging + jboss-logging diff --git a/components/jpa/hibernate/src/main/java/com/kumuluz/ee/jpa/hibernate/JpaComponent.java b/components/jpa/hibernate/src/main/java/com/kumuluz/ee/jpa/hibernate/JpaComponent.java index cbf0993c..e6b1f6d1 100644 --- a/components/jpa/hibernate/src/main/java/com/kumuluz/ee/jpa/hibernate/JpaComponent.java +++ b/components/jpa/hibernate/src/main/java/com/kumuluz/ee/jpa/hibernate/JpaComponent.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jpa.hibernate; import com.kumuluz.ee.common.Component; @@ -5,7 +25,7 @@ import com.kumuluz.ee.common.dependencies.EeComponentDef; import com.kumuluz.ee.common.dependencies.EeComponentType; import com.kumuluz.ee.common.wrapper.KumuluzServerWrapper; -import com.kumuluz.ee.jpa.common.resources.PersistenceUnitHolder; +import com.kumuluz.ee.jpa.common.PersistenceUnitHolder; import java.util.logging.Logger; @@ -21,7 +41,7 @@ public class JpaComponent implements Component { @Override public void init(KumuluzServerWrapper server, EeConfig eeConfig) { - PersistenceUnitHolder.getInstance().setConfigs(eeConfig.getPersistenceConfigs()); + PersistenceUnitHolder.getInstance().setConfig(eeConfig.getPersistenceConfig()); } @Override diff --git a/components/jpa/pom.xml b/components/jpa/pom.xml index b0ae37f8..b54410c5 100644 --- a/components/jpa/pom.xml +++ b/components/jpa/pom.xml @@ -5,7 +5,7 @@ kumuluzee-components com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom diff --git a/components/jsf/mojarra/pom.xml b/components/jsf/mojarra/pom.xml index 72d21a2d..08d5177c 100644 --- a/components/jsf/mojarra/pom.xml +++ b/components/jsf/mojarra/pom.xml @@ -5,7 +5,7 @@ kumuluzee-jsf com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -14,10 +14,6 @@ kumuluzee-jsf-mojarra - - 2.2.14 - - com.kumuluz.ee diff --git a/components/jsf/mojarra/src/main/java/com/kumuluz/ee/jsf/mojarra/JsfComponent.java b/components/jsf/mojarra/src/main/java/com/kumuluz/ee/jsf/mojarra/JsfComponent.java index d0972519..ffdd8dc6 100644 --- a/components/jsf/mojarra/src/main/java/com/kumuluz/ee/jsf/mojarra/JsfComponent.java +++ b/components/jsf/mojarra/src/main/java/com/kumuluz/ee/jsf/mojarra/JsfComponent.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jsf.mojarra; import com.kumuluz.ee.common.Component; diff --git a/components/jsf/pom.xml b/components/jsf/pom.xml index d423c5bf..4f3fb9fb 100644 --- a/components/jsf/pom.xml +++ b/components/jsf/pom.xml @@ -5,7 +5,7 @@ kumuluzee-components com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom diff --git a/components/json-p/jsonp/pom.xml b/components/json-p/jsonp/pom.xml index 11d16d7e..4bf37b83 100644 --- a/components/json-p/jsonp/pom.xml +++ b/components/json-p/jsonp/pom.xml @@ -5,7 +5,7 @@ kumuluzee-json-p com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -14,10 +14,6 @@ KumuluzEE JSON-P JSONP KumuluzEE JSOP-P component implemented by JSONP - - 1.0.4 - - com.kumuluz.ee diff --git a/components/json-p/jsonp/src/main/java/com/kumuluz/ee/jsonp/JsonPComponent.java b/components/json-p/jsonp/src/main/java/com/kumuluz/ee/jsonp/JsonPComponent.java index 21143f98..8e036281 100644 --- a/components/json-p/jsonp/src/main/java/com/kumuluz/ee/jsonp/JsonPComponent.java +++ b/components/json-p/jsonp/src/main/java/com/kumuluz/ee/jsonp/JsonPComponent.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jsonp; import com.kumuluz.ee.common.Component; diff --git a/components/json-p/pom.xml b/components/json-p/pom.xml index adac3f2a..805f94ad 100644 --- a/components/json-p/pom.xml +++ b/components/json-p/pom.xml @@ -5,7 +5,7 @@ kumuluzee-components com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom diff --git a/components/jsp/jetty/pom.xml b/components/jsp/jetty/pom.xml index d2d9c166..b653d007 100644 --- a/components/jsp/jetty/pom.xml +++ b/components/jsp/jetty/pom.xml @@ -5,7 +5,7 @@ kumuluzee-jsp com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -14,10 +14,6 @@ KumuluzEE JSP Jetty KumuluzEE JSP component implemented by Jetty (Apache Jasper) - - 9.3.16.v20170120 - - com.kumuluz.ee diff --git a/components/jsp/jetty/src/main/java/com/kumuluz/ee/jsp/JspComponent.java b/components/jsp/jetty/src/main/java/com/kumuluz/ee/jsp/JspComponent.java index b94c57a8..062a2bc4 100644 --- a/components/jsp/jetty/src/main/java/com/kumuluz/ee/jsp/JspComponent.java +++ b/components/jsp/jetty/src/main/java/com/kumuluz/ee/jsp/JspComponent.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jsp; import com.kumuluz.ee.common.Component; diff --git a/components/jsp/jetty/src/test/java/com/kumuluz/ee/jetty/jsp/test/JspTest.java b/components/jsp/jetty/src/test/java/com/kumuluz/ee/jetty/jsp/test/JspTest.java index 7b179ddb..62600e47 100644 --- a/components/jsp/jetty/src/test/java/com/kumuluz/ee/jetty/jsp/test/JspTest.java +++ b/components/jsp/jetty/src/test/java/com/kumuluz/ee/jetty/jsp/test/JspTest.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jetty.jsp.test; import org.junit.Test; diff --git a/components/jsp/jetty/src/test/java/com/kumuluz/ee/jetty/jsp/test/beans/TimeBean.java b/components/jsp/jetty/src/test/java/com/kumuluz/ee/jetty/jsp/test/beans/TimeBean.java index f249f55a..f5cef0dd 100644 --- a/components/jsp/jetty/src/test/java/com/kumuluz/ee/jetty/jsp/test/beans/TimeBean.java +++ b/components/jsp/jetty/src/test/java/com/kumuluz/ee/jetty/jsp/test/beans/TimeBean.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jetty.jsp.test.beans; import java.util.Date; diff --git a/components/jsp/jetty/src/test/java/com/kumuluz/ee/jetty/jsp/test/beans/UserBean.java b/components/jsp/jetty/src/test/java/com/kumuluz/ee/jetty/jsp/test/beans/UserBean.java index d94c47c5..0e1ceb2f 100644 --- a/components/jsp/jetty/src/test/java/com/kumuluz/ee/jetty/jsp/test/beans/UserBean.java +++ b/components/jsp/jetty/src/test/java/com/kumuluz/ee/jetty/jsp/test/beans/UserBean.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jetty.jsp.test.beans; import java.time.LocalDate; diff --git a/components/jsp/pom.xml b/components/jsp/pom.xml index 1b5aa36f..5c776de4 100644 --- a/components/jsp/pom.xml +++ b/components/jsp/pom.xml @@ -5,7 +5,7 @@ kumuluzee-components com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom diff --git a/components/jta/common/pom.xml b/components/jta/common/pom.xml new file mode 100644 index 00000000..cda66dd3 --- /dev/null +++ b/components/jta/common/pom.xml @@ -0,0 +1,35 @@ + + + + kumuluzee-jta + com.kumuluz.ee + 2.5.0-SNAPSHOT + + 4.0.0 + + KumuluzEE JTA Common + KumuluzEE JTA component common utilities, configs and exceptions + + kumuluzee-jta-common + + + + com.kumuluz.ee + kumuluzee-common + + + + javax.transaction + javax.transaction-api + + + + com.kumuluz.ee + kumuluzee-cdi-weld + provided + + + + \ No newline at end of file diff --git a/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/JtaTransactionHolder.java b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/JtaTransactionHolder.java new file mode 100644 index 00000000..25892f05 --- /dev/null +++ b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/JtaTransactionHolder.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jta.common; + +import javax.transaction.Status; +import javax.transaction.TransactionManager; +import javax.transaction.TransactionSynchronizationRegistry; +import javax.transaction.UserTransaction; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * @author Marcos Koch Salvador + * @since 2.3.0 + */ +public class JtaTransactionHolder { + + public static final List TRANSACTION_ACTIVE_STATUS = Arrays.asList( + Status.STATUS_ACTIVE, Status.STATUS_COMMITTING, Status.STATUS_MARKED_ROLLBACK, Status.STATUS_PREPARED, + Status.STATUS_PREPARING, Status.STATUS_ROLLING_BACK + ); + + + private static final JtaTransactionHolder INSTANCE = new JtaTransactionHolder(); + private TransactionAcquirer transactionAcquirer; + + private JtaTransactionHolder() { + } + + public static JtaTransactionHolder getInstance() { + return INSTANCE; + } + + public void setTransactionAcquirer(TransactionAcquirer transactionAcquirer) { + this.transactionAcquirer = transactionAcquirer; + } + + private void validateTransactionAcquirer() { + Objects.requireNonNull(transactionAcquirer, "TransactionAcquirer not found!"); + } + + public TransactionManager getTransactionManager() { + validateTransactionAcquirer(); + return transactionAcquirer.getTransactionManager(); + } + + public UserTransaction getUserTransaction() { + validateTransactionAcquirer(); + return transactionAcquirer.getUserTransaction(); + } + + public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() { + validateTransactionAcquirer(); + return transactionAcquirer.getTransactionSynchronizationRegistry(); + } +} diff --git a/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/JtaTransactionServices.java b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/JtaTransactionServices.java new file mode 100644 index 00000000..576bbe8d --- /dev/null +++ b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/JtaTransactionServices.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jta.common; + +import org.jboss.weld.transaction.spi.TransactionServices; + +import javax.transaction.Synchronization; +import javax.transaction.SystemException; +import javax.transaction.UserTransaction; + +/** + * @author Marcos Koch Salvador + * @since 2.3.0 + */ +public class JtaTransactionServices implements TransactionServices { + + @Override + public void registerSynchronization(Synchronization synchronizedObserver) { + try { + JtaTransactionHolder.getInstance().getTransactionManager().getTransaction().registerSynchronization(synchronizedObserver); + } catch (IllegalStateException | javax.transaction.RollbackException | SystemException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean isTransactionActive() { + try { + int status = JtaTransactionHolder.getInstance().getTransactionManager().getStatus(); + return JtaTransactionHolder.TRANSACTION_ACTIVE_STATUS.contains(status); + } catch (SystemException e) { + throw new RuntimeException(e); + } + } + + @Override + public UserTransaction getUserTransaction() { + return JtaTransactionHolder.getInstance().getUserTransaction(); + } + + @Override + public void cleanup() { + } +} diff --git a/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/TransactionAcquirer.java b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/TransactionAcquirer.java new file mode 100644 index 00000000..d509a8bc --- /dev/null +++ b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/TransactionAcquirer.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jta.common; + +import javax.transaction.TransactionManager; +import javax.transaction.TransactionSynchronizationRegistry; +import javax.transaction.UserTransaction; + +/** + * @author Marcos Koch Salvador + * @since 2.3.0 + */ +public interface TransactionAcquirer { + + UserTransaction getUserTransaction(); + + TransactionManager getTransactionManager(); + + TransactionSynchronizationRegistry getTransactionSynchronizationRegistry(); +} diff --git a/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/datasources/JtaXAConnectionWrapper.java b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/datasources/JtaXAConnectionWrapper.java new file mode 100644 index 00000000..0ec4ba54 --- /dev/null +++ b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/datasources/JtaXAConnectionWrapper.java @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jta.common.datasources; + +import com.kumuluz.ee.jta.common.JtaTransactionHolder; +import com.kumuluz.ee.jta.common.utils.TxUtils; + +import javax.sql.XAConnection; +import javax.transaction.RollbackException; +import javax.transaction.Synchronization; +import javax.transaction.SystemException; +import javax.transaction.TransactionManager; +import java.sql.*; +import java.util.Collections; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; +import java.util.logging.Logger; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public class JtaXAConnectionWrapper implements Connection { + + private Logger log = Logger.getLogger(JtaXAConnectionWrapper.class.getSimpleName()); + + private Boolean isClosed = false; + private Boolean isEnlistedInJTA = false; + private Boolean closeAfterTransactionEnd = false; + + private XAConnection xaConnection; + + private TransactionManager transactionManager; + + public JtaXAConnectionWrapper(XAConnection xaConnection) { + this.xaConnection = xaConnection; + } + + @Override + public Statement createStatement() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + Statement statement = xaConnection.getConnection().createStatement(); + + return (Statement) XAStatementProxy.newInstance(statement, this); + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + PreparedStatement preparedStatement = xaConnection.getConnection().prepareStatement(sql); + + return (PreparedStatement) XAStatementProxy.newInstance(preparedStatement, this); + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + CallableStatement callableStatement = xaConnection.getConnection().prepareCall(sql); + + return (CallableStatement) XAStatementProxy.newInstance(callableStatement, this); + } + + @Override + public String nativeSQL(String sql) throws SQLException { + + checkIfValid(); + + return xaConnection.getConnection().nativeSQL(sql); + } + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().setAutoCommit(autoCommit); + } + + @Override + public boolean getAutoCommit() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().getAutoCommit(); + } + + @Override + public void commit() throws SQLException { + + checkIfValid(); + + xaConnection.getConnection().commit(); + } + + @Override + public void rollback() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().rollback(); + } + + @Override + public void close() throws SQLException { + + if (isClosed) return; + + isClosed = true; + + if (isEnlistedInJTA) { + + closeAfterTransactionEnd = true; + return; + } + + if (xaConnection != null) { + + xaConnection.close(); + xaConnection = null; + } + } + + @Override + public boolean isClosed() throws SQLException { + + if (!isClosed) { + jtaPreInvoke(); + } + + return isClosed; + } + + @Override + public DatabaseMetaData getMetaData() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().getMetaData(); + } + + @Override + public void setReadOnly(boolean readOnly) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().setReadOnly(readOnly); + } + + @Override + public boolean isReadOnly() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().isReadOnly(); + } + + @Override + public void setCatalog(String catalog) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().setCatalog(catalog); + } + + @Override + public String getCatalog() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().getCatalog(); + } + + @Override + public void setTransactionIsolation(int level) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().setTransactionIsolation(level); + } + + @Override + public int getTransactionIsolation() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().getTransactionIsolation(); + } + + @Override + public SQLWarning getWarnings() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().getWarnings(); + } + + @Override + public void clearWarnings() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().clearWarnings(); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + Statement statement = xaConnection.getConnection().createStatement(resultSetType, resultSetConcurrency); + + return (Statement) XAStatementProxy.newInstance(statement, this); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + PreparedStatement preparedStatement = xaConnection.getConnection().prepareStatement(sql, resultSetType, resultSetConcurrency); + + return (PreparedStatement) XAStatementProxy.newInstance(preparedStatement, this); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + CallableStatement callableStatement = xaConnection.getConnection().prepareCall(sql, resultSetType, resultSetConcurrency); + + return (CallableStatement) XAStatementProxy.newInstance(callableStatement, this); + } + + @Override + public Map> getTypeMap() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().getTypeMap(); + } + + @Override + public void setTypeMap(Map> map) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().setTypeMap(map); + } + + @Override + public void setHoldability(int holdability) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().setHoldability(holdability); + } + + @Override + public int getHoldability() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().getHoldability(); + } + + @Override + public Savepoint setSavepoint() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().setSavepoint(); + } + + @Override + public Savepoint setSavepoint(String name) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().setSavepoint(name); + } + + @Override + public void rollback(Savepoint savepoint) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().rollback(); + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().releaseSavepoint(savepoint); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + Statement statement = xaConnection.getConnection().createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); + + return (Statement) XAStatementProxy.newInstance(statement, this); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + PreparedStatement preparedStatement = xaConnection.getConnection().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + + return (PreparedStatement) XAStatementProxy.newInstance(preparedStatement, this); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + CallableStatement callableStatement = xaConnection.getConnection().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + + return (CallableStatement) XAStatementProxy.newInstance(callableStatement, this); + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + PreparedStatement preparedStatement = xaConnection.getConnection().prepareStatement(sql, autoGeneratedKeys); + + return (PreparedStatement) XAStatementProxy.newInstance(preparedStatement, this); + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + PreparedStatement preparedStatement = xaConnection.getConnection().prepareStatement(sql, columnIndexes); + + return (PreparedStatement) XAStatementProxy.newInstance(preparedStatement, this); + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + PreparedStatement preparedStatement = xaConnection.getConnection().prepareStatement(sql, columnNames); + + return (PreparedStatement) XAStatementProxy.newInstance(preparedStatement, this); + } + + @Override + public Clob createClob() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().createClob(); + } + + @Override + public Blob createBlob() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().createBlob(); + } + + @Override + public NClob createNClob() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().createNClob(); + } + + @Override + public SQLXML createSQLXML() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().createSQLXML(); + } + + @Override + public boolean isValid(int timeout) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().isValid(timeout); + } + + @Override + public void setClientInfo(String name, String value) throws SQLClientInfoException { + + try { + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().setClientInfo(name, value); + } catch (SQLException e) { + throw new SQLClientInfoException(Collections.emptyMap(), e); + } + } + + @Override + public void setClientInfo(Properties properties) throws SQLClientInfoException { + + try { + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().setClientInfo(properties); + } catch (SQLException e) { + throw new SQLClientInfoException(Collections.emptyMap(), e); + } + } + + @Override + public String getClientInfo(String name) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().getClientInfo(name); + } + + @Override + public Properties getClientInfo() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().getClientInfo(); + } + + @Override + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().createArrayOf(typeName, elements); + } + + @Override + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().createStruct(typeName, attributes); + } + + @Override + public void setSchema(String schema) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().setSchema(schema); + } + + @Override + public String getSchema() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().getSchema(); + } + + @Override + public void abort(Executor executor) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().abort(executor); + } + + @Override + public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + xaConnection.getConnection().setNetworkTimeout(executor, milliseconds); + } + + @Override + public int getNetworkTimeout() throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().getNetworkTimeout(); + } + + @Override + public T unwrap(Class iface) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + + checkIfValid(); + jtaPreInvoke(); + + return xaConnection.getConnection().isWrapperFor(iface); + } + + private void checkIfValid() throws SQLException { + + if (isClosed) throw new SQLException("The connection is closed"); + if (xaConnection == null) throw new SQLException("The connection is invalid"); + } + + private void jtaPreInvoke() throws SQLException { + + if (isEnlistedInJTA) return; + + try { + + if (transactionManager == null) { + transactionManager = JtaTransactionHolder.getInstance().getTransactionManager(); + } + + if (TxUtils.isActive(transactionManager)) { + + transactionManager.getTransaction().enlistResource(xaConnection.getXAResource()); + transactionManager.getTransaction().registerSynchronization(new Synchronization() { + + @Override + public void beforeCompletion() { + } + + @Override + public void afterCompletion(int status) { + + JtaXAConnectionWrapper jtaXaConnectionWrapper = JtaXAConnectionWrapper.this; + + jtaXaConnectionWrapper.isEnlistedInJTA = false; + + if (jtaXaConnectionWrapper.closeAfterTransactionEnd && jtaXaConnectionWrapper.xaConnection != null) { + + try { + jtaXaConnectionWrapper.xaConnection.close(); + jtaXaConnectionWrapper.xaConnection = null; + } catch (SQLException e) { + + log.severe("There was an error closing the connection after transaction complete"); + } + } + } + }); + + this.isEnlistedInJTA = true; + } + } catch (SystemException | RollbackException | SQLException e) { + throw new SQLException(e); + } + } +} diff --git a/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/datasources/JtaXADataSourceWrapper.java b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/datasources/JtaXADataSourceWrapper.java new file mode 100644 index 00000000..e54b5b1e --- /dev/null +++ b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/datasources/JtaXADataSourceWrapper.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jta.common.datasources; + +import com.kumuluz.ee.common.datasources.NonJtaXADataSourceWrapper; + +import javax.sql.XAConnection; +import javax.sql.XADataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public class JtaXADataSourceWrapper extends NonJtaXADataSourceWrapper { + + public JtaXADataSourceWrapper(XADataSource xaDataSource) { + super(xaDataSource); + } + + @Override + public Connection getConnection() throws SQLException { + + checkIfValid(); + + XAConnection xaConnection = xaDataSource.getXAConnection(); + + return new JtaXAConnectionWrapper(xaConnection); + } + + @Override + public Connection getConnection(String username, String password) throws SQLException { + + checkIfValid(); + + XAConnection xaConnection = xaDataSource.getXAConnection(username, password); + + return new JtaXAConnectionWrapper(xaConnection); + } +} diff --git a/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/datasources/XAStatementProxy.java b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/datasources/XAStatementProxy.java new file mode 100644 index 00000000..758efa45 --- /dev/null +++ b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/datasources/XAStatementProxy.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jta.common.datasources; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public class XAStatementProxy implements InvocationHandler { + + private Statement statement; + private JtaXAConnectionWrapper jtaXaConnectionWrapper; + + + private XAStatementProxy(Statement statement, JtaXAConnectionWrapper jtaXaConnectionWrapper) { + this.statement = statement; + this.jtaXaConnectionWrapper = jtaXaConnectionWrapper; + } + + public static Object newInstance(Statement statement, JtaXAConnectionWrapper jtaXaConnectionWrapper) { + return Proxy.newProxyInstance(statement.getClass().getClassLoader(), new Class[]{Statement.class}, new XAStatementProxy(statement, jtaXaConnectionWrapper)); + } + + public static Object newInstance(PreparedStatement statement, JtaXAConnectionWrapper jtaXaConnectionWrapper) { + return Proxy.newProxyInstance(statement.getClass().getClassLoader(), new Class[]{PreparedStatement.class}, new XAStatementProxy(statement, jtaXaConnectionWrapper)); + } + + public static Object newInstance(CallableStatement statement, JtaXAConnectionWrapper jtaXaConnectionWrapper) { + return Proxy.newProxyInstance(statement.getClass().getClassLoader(), new Class[]{CallableStatement.class}, new XAStatementProxy(statement, jtaXaConnectionWrapper)); + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + + if (jtaXaConnectionWrapper.isClosed()) { + throw new SQLException("The connection associated with this statement is closed"); + } + + return method.invoke(statement, args); + } +} diff --git a/common/src/main/java/com/kumuluz/ee/logs/LogConfigurator.java b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/exceptions/CannotRetrieveTxException.java similarity index 75% rename from common/src/main/java/com/kumuluz/ee/logs/LogConfigurator.java rename to components/jta/common/src/main/java/com/kumuluz/ee/jta/common/exceptions/CannotRetrieveTxException.java index baff88a7..c03ea5a4 100644 --- a/common/src/main/java/com/kumuluz/ee/logs/LogConfigurator.java +++ b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/exceptions/CannotRetrieveTxException.java @@ -18,21 +18,15 @@ * software. See the License for the specific language governing permissions and * limitations under the License. */ - -package com.kumuluz.ee.logs; - -import com.kumuluz.ee.logs.enums.LogLevel; +package com.kumuluz.ee.jta.common.exceptions; /** - * @author Rok Povse - * @author Marko Skrjanec + * @author Tilen Faganel + * @since 2.4.0 */ -public interface LogConfigurator { - - void init(); - - void setLevel(String logName, LogLevel logLevel); - - LogLevel getLevel(String logName); +public class CannotRetrieveTxException extends IllegalStateException { + public CannotRetrieveTxException(Throwable cause) { + super("There was an error retrieving the current threads transaction.", cause); + } } diff --git a/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/utils/TxUtils.java b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/utils/TxUtils.java new file mode 100644 index 00000000..b569a3d0 --- /dev/null +++ b/components/jta/common/src/main/java/com/kumuluz/ee/jta/common/utils/TxUtils.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jta.common.utils; + +import com.kumuluz.ee.jta.common.JtaTransactionHolder; +import com.kumuluz.ee.jta.common.exceptions.CannotRetrieveTxException; + +import javax.transaction.SystemException; +import javax.transaction.Transaction; +import javax.transaction.TransactionManager; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class TxUtils { + + public static Boolean isActive(TransactionManager transactionManager) { + + try { + Transaction tx = transactionManager.getTransaction(); + + return tx != null && JtaTransactionHolder.TRANSACTION_ACTIVE_STATUS.contains(tx.getStatus()); + } catch (SystemException e) { + throw new CannotRetrieveTxException(e); + } + } +} diff --git a/components/jta/common/src/main/resources/META-INF/services/org.jboss.weld.bootstrap.api.Service b/components/jta/common/src/main/resources/META-INF/services/org.jboss.weld.bootstrap.api.Service new file mode 100644 index 00000000..0ca0ac73 --- /dev/null +++ b/components/jta/common/src/main/resources/META-INF/services/org.jboss.weld.bootstrap.api.Service @@ -0,0 +1 @@ +com.kumuluz.ee.jta.common.JtaTransactionServices \ No newline at end of file diff --git a/components/jta/narayana/pom.xml b/components/jta/narayana/pom.xml new file mode 100644 index 00000000..6a29dfea --- /dev/null +++ b/components/jta/narayana/pom.xml @@ -0,0 +1,45 @@ + + + + kumuluzee-jta + com.kumuluz.ee + 2.5.0-SNAPSHOT + + 4.0.0 + + KumuluzEE JTA Narayana + KumuluzEE JTA component implemented by Narayana + + kumuluzee-jta-narayana + + + + com.kumuluz.ee + kumuluzee-jta-common + + + + org.jboss + jboss-transaction-spi + ${jboss-transaction-spi.version} + + + org.jboss.spec.javax.transaction + jboss-transaction-api_1.2_spec + + + org.jboss.spec.javax.resource + jboss-connector-api_1.7_spec + + + + + org.jboss.narayana.jta + narayana-jta + ${narayana.version} + + + + \ No newline at end of file diff --git a/components/jta/narayana/src/main/java/com/kumuluz/ee/jta/narayana/JtaComponent.java b/components/jta/narayana/src/main/java/com/kumuluz/ee/jta/narayana/JtaComponent.java new file mode 100644 index 00000000..955268ea --- /dev/null +++ b/components/jta/narayana/src/main/java/com/kumuluz/ee/jta/narayana/JtaComponent.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jta.narayana; + +import com.arjuna.ats.arjuna.common.arjPropertyManager; +import com.arjuna.ats.jta.utils.JNDIManager; +import com.kumuluz.ee.common.Component; +import com.kumuluz.ee.common.config.EeConfig; +import com.kumuluz.ee.common.dependencies.EeComponentDef; +import com.kumuluz.ee.common.dependencies.EeComponentType; +import com.kumuluz.ee.common.wrapper.KumuluzServerWrapper; +import com.kumuluz.ee.jta.common.JtaTransactionHolder; + +import javax.naming.NamingException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * @author Marcos Koch Salvador + * @since 2.3.0 + */ +@EeComponentDef(name = "Narayana JTA", type = EeComponentType.JTA) +public class JtaComponent implements Component { + + private Logger log = Logger.getLogger(JtaComponent.class.getSimpleName()); + + @Override + public void init(KumuluzServerWrapper server, EeConfig eeConfig) { + JtaTransactionHolder.getInstance().setTransactionAcquirer(new NarayanaTransactionAcquirer()); + } + + @Override + public void load() { + log.info("Initiating Narayana JTA"); + + arjPropertyManager.getObjectStoreEnvironmentBean().setObjectStoreDir("ObjectStore"); + + try { + JNDIManager.bindJTAImplementation(); + } catch (NamingException e) { + log.log(Level.WARNING, e.getMessage(), e); + } + } +} diff --git a/components/jta/narayana/src/main/java/com/kumuluz/ee/jta/narayana/NarayanaTransactionAcquirer.java b/components/jta/narayana/src/main/java/com/kumuluz/ee/jta/narayana/NarayanaTransactionAcquirer.java new file mode 100644 index 00000000..5fceb90b --- /dev/null +++ b/components/jta/narayana/src/main/java/com/kumuluz/ee/jta/narayana/NarayanaTransactionAcquirer.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.jta.narayana; + +import com.arjuna.ats.jta.common.JTAEnvironmentBean; +import com.arjuna.ats.jta.common.jtaPropertyManager; +import com.kumuluz.ee.jta.common.TransactionAcquirer; + +import javax.transaction.TransactionManager; +import javax.transaction.TransactionSynchronizationRegistry; +import javax.transaction.UserTransaction; + +/** + * @author Marcos Koch Salvador + * @since 2.3.0 + */ +public class NarayanaTransactionAcquirer implements TransactionAcquirer { + + private JTAEnvironmentBean jtaEnvironment; + + public NarayanaTransactionAcquirer() { + jtaEnvironment = jtaPropertyManager.getJTAEnvironmentBean(); + } + + @Override + public UserTransaction getUserTransaction() { + return jtaEnvironment.getUserTransaction(); + } + + @Override + public TransactionManager getTransactionManager() { + return jtaEnvironment.getTransactionManager(); + } + + @Override + public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() { + return jtaEnvironment.getTransactionSynchronizationRegistry(); + } +} diff --git a/components/jta/narayana/src/main/resources/META-INF/services/com.kumuluz.ee.common.Component b/components/jta/narayana/src/main/resources/META-INF/services/com.kumuluz.ee.common.Component new file mode 100644 index 00000000..cd96e5c7 --- /dev/null +++ b/components/jta/narayana/src/main/resources/META-INF/services/com.kumuluz.ee.common.Component @@ -0,0 +1 @@ +com.kumuluz.ee.jta.narayana.JtaComponent \ No newline at end of file diff --git a/components/jta/pom.xml b/components/jta/pom.xml new file mode 100644 index 00000000..8146bdb2 --- /dev/null +++ b/components/jta/pom.xml @@ -0,0 +1,23 @@ + + + + kumuluzee-components + com.kumuluz.ee + 2.5.0-SNAPSHOT + + 4.0.0 + pom + + + common + narayana + + + KumuluzEE JTA + KumuluzEE JTA component + + kumuluzee-jta + + \ No newline at end of file diff --git a/components/pom.xml b/components/pom.xml index e3be2297..954ee0c0 100644 --- a/components/pom.xml +++ b/components/pom.xml @@ -5,7 +5,7 @@ kumuluzee com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom @@ -25,6 +25,7 @@ bean-validation jax-ws ejb + jta kumuluzee-components diff --git a/components/websocket/jetty/pom.xml b/components/websocket/jetty/pom.xml index 6ced8423..d4a0fe6b 100644 --- a/components/websocket/jetty/pom.xml +++ b/components/websocket/jetty/pom.xml @@ -5,7 +5,7 @@ kumuluzee-websocket com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -14,10 +14,6 @@ kumuluzee-websocket-jetty - - 9.3.16.v20170120 - - com.kumuluz.ee diff --git a/components/websocket/jetty/src/main/java/com/kumuluz/ee/websocket/jetty/WebSocketComponent.java b/components/websocket/jetty/src/main/java/com/kumuluz/ee/websocket/jetty/WebSocketComponent.java index 6196732c..65615b12 100644 --- a/components/websocket/jetty/src/main/java/com/kumuluz/ee/websocket/jetty/WebSocketComponent.java +++ b/components/websocket/jetty/src/main/java/com/kumuluz/ee/websocket/jetty/WebSocketComponent.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.websocket.jetty; import com.kumuluz.ee.common.Component; diff --git a/components/websocket/pom.xml b/components/websocket/pom.xml index b0ce0fe6..5b782326 100644 --- a/components/websocket/pom.xml +++ b/components/websocket/pom.xml @@ -5,7 +5,7 @@ kumuluzee-components com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom diff --git a/core/pom.xml b/core/pom.xml index 9f9926db..468dfeb7 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -5,7 +5,7 @@ kumuluzee com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -19,6 +19,11 @@ com.kumuluz.ee kumuluzee-common + + com.kumuluz.ee + kumuluzee-jta-common + provided + junit diff --git a/core/src/main/java/com/kumuluz/ee/EeApplication.java b/core/src/main/java/com/kumuluz/ee/EeApplication.java index 7c1f70b5..504403dc 100644 --- a/core/src/main/java/com/kumuluz/ee/EeApplication.java +++ b/core/src/main/java/com/kumuluz/ee/EeApplication.java @@ -1,22 +1,58 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee; -import com.kumuluz.ee.common.Component; -import com.kumuluz.ee.common.KumuluzServer; -import com.kumuluz.ee.common.ServletServer; +import com.kumuluz.ee.common.*; import com.kumuluz.ee.common.config.DataSourceConfig; +import com.kumuluz.ee.common.config.DataSourcePoolConfig; import com.kumuluz.ee.common.config.EeConfig; +import com.kumuluz.ee.common.config.XaDataSourceConfig; +import com.kumuluz.ee.common.datasources.NonJtaXADataSourceWrapper; +import com.kumuluz.ee.common.datasources.XADataSourceBuilder; +import com.kumuluz.ee.common.datasources.XADataSourceWrapper; import com.kumuluz.ee.common.dependencies.*; import com.kumuluz.ee.common.exceptions.KumuluzServerException; import com.kumuluz.ee.common.filters.PoweredByFilter; +import com.kumuluz.ee.common.runtime.EeRuntime; +import com.kumuluz.ee.common.runtime.EeRuntimeComponent; +import com.kumuluz.ee.common.runtime.EeRuntimeExtension; +import com.kumuluz.ee.common.runtime.EeRuntimeInternal; import com.kumuluz.ee.common.utils.ResourceUtils; import com.kumuluz.ee.common.wrapper.ComponentWrapper; import com.kumuluz.ee.common.wrapper.EeComponentWrapper; +import com.kumuluz.ee.common.wrapper.ExtensionWrapper; import com.kumuluz.ee.common.wrapper.KumuluzServerWrapper; -import com.kumuluz.ee.loaders.ComponentLoader; -import com.kumuluz.ee.loaders.ServerLoader; +import com.kumuluz.ee.configuration.ConfigurationSource; +import com.kumuluz.ee.configuration.utils.ConfigurationImpl; +import com.kumuluz.ee.configuration.utils.ConfigurationUtil; +import com.kumuluz.ee.factories.EeConfigFactory; +import com.kumuluz.ee.factories.JtaXADataSourceFactory; +import com.kumuluz.ee.loaders.*; +import com.kumuluz.ee.logs.impl.JavaUtilDefaultLogConfigurator; import com.zaxxer.hikari.HikariDataSource; +import javax.sql.XADataSource; import java.util.*; +import java.util.logging.Handler; +import java.util.logging.LogManager; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -26,18 +62,14 @@ */ public class EeApplication { - private Logger log = Logger.getLogger(EeApplication.class.getSimpleName()); + private Logger log; private EeConfig eeConfig; private KumuluzServerWrapper server; - private List eeComponents; - public EeApplication() { - this.eeConfig = new EeConfig(); - initialize(); } @@ -53,7 +85,53 @@ public static void main(String args[]) { EeApplication app = new EeApplication(); } - public void initialize() { + private void initialize() { + + // Initialize the configuration + ConfigurationImpl configImpl = new ConfigurationImpl(); + + ConfigurationUtil.initialize(configImpl); + + if (this.eeConfig == null) { + this.eeConfig = EeConfigFactory.buildEeConfig(); + } else if (!EeConfigFactory.isEeConfigValid(this.eeConfig)) { + throw new KumuluzServerException("The programmatically supplied EeConfig is malformed." + + "Please check the supplied values and the config reference to fix the missing or invalid values."); + } + + EeConfig.initialize(this.eeConfig); + + // Loading the logs extension and set up logging bridges before any actual logging is done + Optional logsExtensionOptional = LogsExtensionLoader.loadExtension(); + + if (logsExtensionOptional.isPresent()) { + + LogsExtension logsExtension = logsExtensionOptional.get(); + + Optional> logManager = logsExtension.getJavaUtilLogManagerClass(); + Optional logHandler = logsExtension.getJavaUtilLogHandler(); + + if (logManager.isPresent()) { + + System.setProperty("java.util.logging.manager", logManager.get().getName()); + } else logHandler.ifPresent(JavaUtilDefaultLogConfigurator::initSoleHandler); + + logsExtension.load(); + } else { + + JavaUtilDefaultLogConfigurator.init(); + } + + // Create the main class logger + log = Logger.getLogger(EeApplication.class.getSimpleName()); + + // Signal the configuration impl that logging is up and running + configImpl.postInit(); + + for (ConfigurationSource configurationSource : configImpl.getConfigurationSources()) { + + log.info("Initialized configuration source: " + configurationSource.getClass().getSimpleName()); + } log.info("Initializing KumuluzEE"); @@ -63,7 +141,9 @@ public void initialize() { log.info("Checks passed"); - log.info("Initializing components"); + log.info("Initialized main configuration"); + + log.info("Loading available EE components and extensions"); // Loading the kumuluz server and extracting its metadata KumuluzServer kumuluzServer = ServerLoader.loadServletServer(); @@ -71,10 +151,88 @@ public void initialize() { // Loading all the present components, extracting their metadata and process dependencies List components = ComponentLoader.loadComponents(); - processEeComponents(components); + List eeComponents = processEeComponents(components); + + // Loading the config extensions and extracting its metadata + List configExtensions = ConfigExtensionLoader.loadExtensions(); + List> eeConfigExtensions = processSingleEeExtensions(configExtensions, eeComponents); + + List logsExtensions = logsExtensionOptional.map(Collections::singletonList).orElseGet(Collections::emptyList); + List> eeLogsExtensions = processGroupEeExtensions(logsExtensions, eeComponents); + + // Loading the extensions and extracting its metadata + List extensions = ExtensionLoader.loadExtensions(); + List> eeExtensions = processGroupEeExtensions(extensions, eeComponents); + + log.info("EE Components and extensions loaded"); + + log.info("Initializing the KumuluzEE runtime"); + + EeRuntimeInternal eeRuntimeInternal = new EeRuntimeInternal(); + + List eeRuntimeComponents = eeComponents.stream() + .map(e -> new EeRuntimeComponent(e.getType(), e.getName())) + .collect(Collectors.toList()); + + List serverEeRuntimeComponents = Arrays.stream(server.getProvidedEeComponents()) + .map(c -> new EeRuntimeComponent(c, server.getName())) + .collect(Collectors.toList()); + + serverEeRuntimeComponents.addAll(eeRuntimeComponents); + + eeRuntimeInternal.setEeComponents(serverEeRuntimeComponents); + + List eeRuntimeExtensions = eeExtensions.stream() + .map(e -> new EeRuntimeExtension(e.getGroup(), e.getName())).collect(Collectors.toList()); + + eeRuntimeExtensions.addAll(eeConfigExtensions.stream() + .map(e -> new EeRuntimeExtension(e.getGroup(), e.getName())).collect(Collectors.toList())); + + eeRuntimeExtensions.addAll(eeLogsExtensions.stream() + .map(e -> new EeRuntimeExtension(e.getGroup(), e.getName())).collect(Collectors.toList())); + + eeRuntimeInternal.setEeExtensions(eeRuntimeExtensions); + + EeRuntime.initialize(eeRuntimeInternal); + + log.info("Initialized the KumuluzEE runtime"); + + // Initiate the config extensions + log.info("Initializing config extensions"); + + for (ExtensionWrapper extension : eeConfigExtensions) { + + log.info("Found config extension implemented by " + extension.getName()); + + extension.getExtension().load(); + extension.getExtension().init(server, eeConfig); + + List sources = extension.getExtension().getConfigurationSources(); + if (sources == null || sources.size() == 0) { + sources = Collections.singletonList(extension.getExtension().getConfigurationSource()); + } + + for (ConfigurationSource source : sources) { + if (source != null) { + source.init(configImpl.getDispatcher()); + configImpl.getConfigurationSources().add(source); + } + } + } + + configImpl.getConfigurationSources().sort(Comparator.comparingInt(ConfigurationSource::getOrdinal).reversed()); + + log.info("Config extensions initialized"); + + for (ExtensionWrapper extension : eeLogsExtensions) { + + log.info("Found logs extension implemented by " + extension.getName()); + + extension.getExtension().init(server, eeConfig); + } // Initiate the server - server.getServer().setServerConfig(eeConfig.getServerConfig()); + server.getServer().setServerConfig(eeConfig.getServer()); server.getServer().initServer(); // Depending on the server type, initiate server specific functionality @@ -97,19 +255,78 @@ public void initialize() { if (dsc.getDriverClass() != null && !dsc.getDriverClass().isEmpty()) ds.setDriverClassName(dsc.getDriverClass()); - if (dsc.getMaxPoolSize() != null ) + if (dsc.getDataSourceClass() != null && !dsc.getDataSourceClass().isEmpty()) { + ds.setDataSourceClassName(dsc.getDataSourceClass()); + } + + if (dsc.getMaxPoolSize() != null) { ds.setMaximumPoolSize(dsc.getMaxPoolSize()); + } + + DataSourcePoolConfig dscp = dsc.getPool(); + + ds.setAutoCommit(dscp.getAutoCommit()); + ds.setConnectionTimeout(dscp.getConnectionTimeout()); + ds.setIdleTimeout(dscp.getIdleTimeout()); + ds.setMaxLifetime(dscp.getMaxLifetime()); + ds.setMaximumPoolSize(dscp.getMaxSize()); + ds.setPoolName(dscp.getName()); + ds.setInitializationFailTimeout(dscp.getInitializationFailTimeout()); + ds.setIsolateInternalQueries(dscp.getIsolateInternalQueries()); + ds.setAllowPoolSuspension(dscp.getAllowPoolSuspension()); + ds.setReadOnly(dscp.getReadOnly()); + ds.setRegisterMbeans(dscp.getRegisterMbeans()); + ds.setValidationTimeout(dscp.getValidationTimeout()); + ds.setLeakDetectionThreshold(dscp.getLeakDetectionThreshold()); + + if (dscp.getMinIdle() != null) { + ds.setMinimumIdle(dscp.getMinIdle()); + } + + if (dscp.getConnectionInitSql() != null) { + ds.setConnectionInitSql(dscp.getConnectionInitSql()); + } + + if (dscp.getTransactionIsolation() != null) { + ds.setTransactionIsolation(dscp.getTransactionIsolation()); + } + + dsc.getProps().forEach(ds::addDataSourceProperty); servletServer.registerDataSource(ds, dsc.getJndiName()); } } + if (eeConfig.getXaDatasources().size() > 0) { + + Boolean jtaPresent = eeRuntimeInternal.getEeComponents().stream().anyMatch(c -> c.getType().equals(EeComponentType.JTA)); + + for (XaDataSourceConfig xdsc : eeConfig.getXaDatasources()) { + + XADataSourceBuilder XADataSourceBuilder = new XADataSourceBuilder(xdsc); + + XADataSource xaDataSource = XADataSourceBuilder.constructXaDataSource(); + + XADataSourceWrapper xaDataSourceWrapper; + + if (jtaPresent) { + xaDataSourceWrapper = JtaXADataSourceFactory.buildJtaXADataSourceWrapper(xaDataSource); + } else { + xaDataSourceWrapper = new NonJtaXADataSourceWrapper(xaDataSource); + } + + servletServer.registerDataSource(xaDataSourceWrapper, xdsc.getJndiName()); + } + } + // Add all included filters Map filterParams = new HashMap<>(); - filterParams.put("name", "KumuluzEE/" + eeConfig.getVersion()); + filterParams.put("name", "KumuluzEE/" + eeRuntimeInternal.getVersion()); servletServer.registerFilter(PoweredByFilter.class, "/*", filterParams); } + log.info("Initializing components"); + // Initiate every found component in the order specified by the components dependencies for (EeComponentWrapper cw : eeComponents) { @@ -121,6 +338,20 @@ public void initialize() { log.info("Components initialized"); + // Initiate the other extensions + log.info("Initializing extensions"); + + for (ExtensionWrapper extension : eeExtensions) { + + log.info("Found extension implemented by " + extension.getExtension().getClass() + .getDeclaredAnnotation(EeExtensionDef.class).name()); + + extension.getExtension().load(); + extension.getExtension().init(server, eeConfig); + } + + log.info("Extensions Initialized"); + server.getServer().startServer(); log.info("KumuluzEE started successfully"); @@ -133,7 +364,7 @@ private void processKumuluzServer(KumuluzServer kumuluzServer) { server = new KumuluzServerWrapper(kumuluzServer, serverDef.value(), serverDef.provides()); } - private void processEeComponents(List components) { + private List processEeComponents(List components) { Map eeComp = new HashMap<>(); @@ -158,7 +389,8 @@ private void processEeComponents(List components) { throw new KumuluzServerException(msg); } - EeComponentDependency[] dependencies = c.getClass().getDeclaredAnnotationsByType(EeComponentDependency.class); + EeComponentDependency[] dependencies = c.getClass().getDeclaredAnnotationsByType + (EeComponentDependency.class); EeComponentOptional[] optionals = c.getClass().getDeclaredAnnotationsByType(EeComponentOptional.class); eeComp.put(def.type(), new EeComponentWrapper(c, def.name(), def.type(), dependencies, optionals)); @@ -188,7 +420,8 @@ private void processEeComponents(List components) { if (depCompName == null) { String msg = "EE component dependency unfulfilled. The EE component " + cmp.getType().getName() + - " implemented by " + cmp.getName() + " requires " + dep.value().getName() + ", which was not " + + " implemented by " + cmp.getName() + " requires " + dep.value().getName() + ", which was " + + "not " + "found. Please make sure to include the required component."; log.severe(msg); @@ -200,7 +433,8 @@ private void processEeComponents(List components) { !Arrays.asList(dep.implementations()).contains(depCompName)) { String msg = "EE component implementation dependency unfulfilled. The EE component " + - cmp.getType().getName() + " implemented by " + cmp.getName() + " requires " + dep.value().getName() + + cmp.getType().getName() + " implemented by " + cmp.getName() + " requires " + dep.value() + .getName() + " implemented by one of the following implementations: " + Arrays.toString(dep.implementations()) + ". Please make sure you use one of the " + "implementations required by this component."; @@ -230,8 +464,9 @@ private void processEeComponents(List components) { if (depCompName != null && dep.implementations().length > 0 && !Arrays.asList(dep.implementations()).contains(depCompName)) { - String msg = "EE component implementation dependency unfulfilled. The EE component " + - cmp.getType().getName() + "implemented by " + cmp.getName() + " requires " + dep.value().getName() + + String msg = "EE component optional implementation dependency unfulfilled. The EE component " + + cmp.getType().getName() + "implemented by " + cmp.getName() + " requires " + dep.value() + .getName() + " implemented by one of the following implementations: " + Arrays.toString(dep.implementations()) + ". Please make sure you use one of the " + "implementations required by this component."; @@ -243,19 +478,157 @@ private void processEeComponents(List components) { } } - eeComponents = new ArrayList<>(eeComp.values()); + return new ArrayList<>(eeComp.values()); } - private void checkRequirements() { + private List> processGroupEeExtensions(List extensions, List wrappedComponents) { - if (ResourceUtils.getProjectWebResources() == null) { + Map> eeExt = new HashMap<>(); - throw new IllegalStateException("No 'webapp' directory found in the projects " + - "resources folder. Please add it to your resources even if it will be empty " + - "so that the servlet server can bind to it. If you have added it and still " + - "see this error please make sure you have at least one file/class in your " + - "projects as some IDEs don't build the project if its empty"); + // Wrap extensions with their metadata and check for duplicates + for (E e : extensions) { + + EeExtensionDef def = e.getClass().getDeclaredAnnotation(EeExtensionDef.class); + + if (def != null) { + + if (eeExt.containsKey(def.group())) { + + String msg = "Found multiple implementations (" + eeExt.get(def.group()).getName() + + ", " + def.name() + ") of the same EE extension group (" + def.group() + "). " + + "Please check to make sure you only include a single implementation of a specific " + + "EE extension group."; + + log.severe(msg); + + throw new KumuluzServerException(msg); + } + + EeComponentDependency[] dependencies = e.getClass().getDeclaredAnnotationsByType + (EeComponentDependency.class); + EeComponentOptional[] optionals = e.getClass().getDeclaredAnnotationsByType(EeComponentOptional.class); + + eeExt.put(def.group(), new ExtensionWrapper<>(e, def.name(), def.group(), dependencies, optionals)); + } + } + + List> extensionWrappers = new ArrayList<>(eeExt.values()); + + log.info("Processing EE extension dependencies"); + + processEeExtensionDependencies(extensionWrappers, wrappedComponents); + + return extensionWrappers; + } + + private List> processSingleEeExtensions(List extensions, List wrappedComponents) { + + List> extensionWrappers = new ArrayList<>(); + + for (E e : extensions) { + + EeExtensionDef def = e.getClass().getDeclaredAnnotation(EeExtensionDef.class); + + if (def != null) { + + EeComponentDependency[] dependencies = e.getClass().getDeclaredAnnotationsByType(EeComponentDependency.class); + EeComponentOptional[] optionals = e.getClass().getDeclaredAnnotationsByType(EeComponentOptional.class); + + extensionWrappers.add(new ExtensionWrapper<>(e, def.name(), def.group(), dependencies, optionals)); + } + } + + log.info("Processing EE single extensions dependencies"); + + processEeExtensionDependencies(extensionWrappers, wrappedComponents); + + return extensionWrappers; + } + + private void processEeExtensionDependencies(List> extensions, List components) { + + // Check if all dependencies are fulfilled + for (ExtensionWrapper ext : extensions) { + + for (EeComponentDependency dep : ext.getDependencies()) { + + Optional depComp = components.stream() + .filter(c -> c.getType().equals(dep.value())).findFirst(); + + String depCompName = null; + + if (depComp.isPresent()) { + + depCompName = depComp.get().getName(); + } else if (Arrays.asList(server.getProvidedEeComponents()).contains(dep.value())) { + + depCompName = server.getName(); + } + + if (depCompName == null) { + + String msg = "EE extension implementation dependency unfulfilled. The EE extension group " + + ext.getGroup() + "implemented by " + ext.getName() + " requires " + dep.value().getName() + + " implemented by one of the following implementations: " + + Arrays.toString(dep.implementations()) + ". Please make sure you use one of the " + + "implementations required by this component."; + + log.severe(msg); + + throw new KumuluzServerException(msg); + + } + + if (dep.implementations().length > 0 && + !Arrays.asList(dep.implementations()).contains(depCompName)) { + + String msg = "EE extension implementation dependency unfulfilled. The EE extension group " + + ext.getGroup() + " implemented by " + ext.getName() + " requires component " + + dep.value().getName() + " implemented by one of the following implementations: " + + Arrays.toString(dep.implementations()) + ". Please make sure you use one of the " + + "component implementations required by this component."; + + log.severe(msg); + + throw new KumuluzServerException(msg); + } + } + + // Check if all optional dependencies and their implementations are fulfilled + for (EeComponentOptional dep : ext.getOptionalDependencies()) { + + Optional depComp = components.stream() + .filter(c -> c.getType().equals(dep.value())).findFirst(); + + String depCompName = null; + + // Check all posible locations for the dependency (Components and Server) + if (depComp.isPresent()) { + + depCompName = depComp.get().getName(); + } else if (!Arrays.asList(server.getProvidedEeComponents()).contains(dep.value())) { + + depCompName = server.getName(); + } + + if (depCompName != null && dep.implementations().length > 0 && + !Arrays.asList(dep.implementations()).contains(depCompName)) { + + String msg = "EE extension optional implementation dependency unfulfilled. The EE extension group " + + ext.getGroup() + "implemented by " + ext.getName() + " requires component " + + dep.value().getName() + " implemented by one of the following implementations: " + + Arrays.toString(dep.implementations()) + ". Please make sure you use one of the " + + "component implementations required by this component."; + + log.severe(msg); + + throw new KumuluzServerException(msg); + } + } } + } + + private void checkRequirements() { if (ResourceUtils.isRunningInJar()) { diff --git a/core/src/main/java/com/kumuluz/ee/factories/EeConfigFactory.java b/core/src/main/java/com/kumuluz/ee/factories/EeConfigFactory.java new file mode 100644 index 00000000..acb2ca08 --- /dev/null +++ b/core/src/main/java/com/kumuluz/ee/factories/EeConfigFactory.java @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.factories; + +import com.kumuluz.ee.common.config.*; +import com.kumuluz.ee.common.utils.EnvUtils; +import com.kumuluz.ee.common.utils.StringUtils; +import com.kumuluz.ee.configuration.utils.ConfigurationUtil; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class EeConfigFactory { + + private static final String PORT_ENV = "PORT"; + + private static final String LEGACY_MIN_THREADS_ENV = "MIN_THREADS"; + private static final String LEGACY_MAX_THREADS_ENV = "MAX_THREADS"; + private static final String LEGACY_REQUEST_HEADER_SIZE_ENV = "REQUEST_HEADER_SIZE"; + private static final String LEGACY_RESPONSE_HEADER_SIZE_ENV = "RESPONSE_HEADER_SIZE"; + private static final String LEGACY_CONTEXT_PATH_ENV = "CONTEXT_PATH"; + + private static final String LEGACY_DB_UNIT_ENV = "DATABASE_UNIT"; + private static final String LEGACY_DB_URL_ENV = "DATABASE_URL"; + private static final String LEGACY_DB_USER_ENV = "DATABASE_USER"; + private static final String LEGACY_DB_PASS_ENV = "DATABASE_PASS"; + + public static EeConfig buildEeConfig() { + + ConfigurationUtil cfg = ConfigurationUtil.getInstance(); + + EeConfig.Builder eeConfigBuilder = new EeConfig.Builder(); + + Optional appName = cfg.get("kumuluzee.name"); + Optional appVersion = cfg.get("kumuluzee.version"); + Optional appDebug = cfg.getBoolean("kumuluzee.debug"); + + appName.ifPresent(eeConfigBuilder::name); + appVersion.ifPresent(eeConfigBuilder::version); + appDebug.ifPresent(eeConfigBuilder::debug); + + ServerConfig.Builder serverBuilder = new ServerConfig.Builder(); + + Optional> serverCfgOpt = cfg.getMapKeys("kumuluzee.server"); + + EnvUtils.getEnv(LEGACY_CONTEXT_PATH_ENV, serverBuilder::contextPath); + EnvUtils.getEnvAsInteger(LEGACY_MIN_THREADS_ENV, serverBuilder::minThreads); + EnvUtils.getEnvAsInteger(LEGACY_MAX_THREADS_ENV, serverBuilder::maxThreads); + + if (serverCfgOpt.isPresent()) { + + Optional baseUrl = cfg.get("kumuluzee.server.base-url"); + Optional contextPath = cfg.get("kumuluzee.server.context-path"); + Optional dirBrowsing = cfg.getBoolean("kumuluzee.server.dir-browsing"); + Optional minThreads = cfg.getInteger("kumuluzee.server.min-threads"); + Optional maxThreads = cfg.getInteger("kumuluzee.server.max-threads"); + Optional forceHttps = cfg.getBoolean("kumuluzee.server.force-https"); + + baseUrl.ifPresent(serverBuilder::baseUrl); + contextPath.ifPresent(serverBuilder::contextPath); + dirBrowsing.ifPresent(serverBuilder::dirBrowsing); + minThreads.ifPresent(serverBuilder::minThreads); + maxThreads.ifPresent(serverBuilder::maxThreads); + forceHttps.ifPresent(serverBuilder::forceHttps); + } + + ServerConnectorConfig.Builder httpBuilder = + createServerConnectorConfigBuilder("kumuluzee.server.http", + ServerConnectorConfig.Builder.DEFAULT_HTTP_PORT); + + EnvUtils.getEnvAsInteger(PORT_ENV, httpBuilder::port); + + ServerConnectorConfig.Builder httpsBuilder = + createServerConnectorConfigBuilder("kumuluzee.server.https", + ServerConnectorConfig.Builder.DEFAULT_HTTPS_PORT); + + serverBuilder.http(httpBuilder); + serverBuilder.https(httpsBuilder); + + eeConfigBuilder.server(serverBuilder); + + Optional> envCfgOpt = cfg.getMapKeys("kumuluzee.env"); + + if (envCfgOpt.isPresent()) { + + EnvConfig.Builder envBuilder = new EnvConfig.Builder(); + + Optional envName = cfg.get("kumuluzee.env.name"); + + envName.ifPresent(envBuilder::name); + + eeConfigBuilder.env(envBuilder); + } + + Optional> loaderCfgOpt = cfg.getMapKeys("kumuluzee.dev"); + + if (loaderCfgOpt.isPresent()) { + + DevConfig.Builder devBuilder = new DevConfig.Builder(); + + Optional webappDir = cfg.get("kumuluzee.dev.webapp-dir"); + + webappDir.ifPresent(devBuilder::webappDir); + + eeConfigBuilder.dev(devBuilder); + } + + Optional dsSizeOpt = cfg.getListSize("kumuluzee.datasources"); + + if (dsSizeOpt.isPresent()) { + + for (int i = 0; i < dsSizeOpt.get(); i++) { + + DataSourceConfig.Builder dsc = new DataSourceConfig.Builder(); + + Optional jndiName = cfg.get("kumuluzee.datasources[" + i + "].jndi-name"); + Optional driverClass = cfg.get("kumuluzee.datasources[" + i + "].driver-class"); + Optional dataSourceClass = cfg.get("kumuluzee.datasources[" + i + "].datasource-class"); + Optional conUrl = cfg.get("kumuluzee.datasources[" + i + "].connection-url"); + Optional user = cfg.get("kumuluzee.datasources[" + i + "].username"); + Optional pass = cfg.get("kumuluzee.datasources[" + i + "].password"); + Optional maxPool = cfg.getInteger("kumuluzee.datasources[" + i + "].max-pool-size"); + + jndiName.ifPresent(dsc::jndiName); + driverClass.ifPresent(dsc::driverClass); + dataSourceClass.ifPresent(dsc::dataSourceClass); + conUrl.ifPresent(dsc::connectionUrl); + user.ifPresent(dsc::username); + pass.ifPresent(dsc::password); + maxPool.ifPresent(dsc::maxPoolSize); + + Optional> pool = cfg.getMapKeys("kumuluzee.datasources[" + i + "].pool"); + + if (pool.isPresent()) { + + DataSourcePoolConfig.Builder dspc = new DataSourcePoolConfig.Builder(); + + Optional autoCommit = cfg.getBoolean("kumuluzee.datasources[" + i + "].pool.auto-commit"); + Optional connectionTimeout = cfg.getLong("kumuluzee.datasources[" + i + "].pool.connection-timeout"); + Optional idleTimeout = cfg.getLong("kumuluzee.datasources[" + i + "].pool.idle-timeout"); + Optional maxLifetime = cfg.getLong("kumuluzee.datasources[" + i + "].pool.max-lifetime"); + Optional minIdle = cfg.getInteger("kumuluzee.datasources[" + i + "].pool.min-idle"); + Optional maxSize = cfg.getInteger("kumuluzee.datasources[" + i + "].pool.max-size"); + Optional poolName = cfg.get("kumuluzee.datasources[" + i + "].pool.name"); + Optional initializationFailTimeout = cfg.getLong("kumuluzee.datasources[" + i + "].pool.initialization-fail-timeout"); + Optional isolateInternalQueries = cfg.getBoolean("kumuluzee.datasources[" + i + "].pool.isolate-internal-queries"); + Optional allowPoolSuspension = cfg.getBoolean("kumuluzee.datasources[" + i + "].pool.allow-pool-suspension"); + Optional readOnly = cfg.getBoolean("kumuluzee.datasources[" + i + "].pool.read-only"); + Optional registerMbeans = cfg.getBoolean("kumuluzee.datasources[" + i + "].pool.register-mbeans"); + Optional connectionInitSql = cfg.get("kumuluzee.datasources[" + i + "].pool.connection-init-sql"); + Optional transactionIsolation = cfg.get("kumuluzee.datasources[" + i + "].pool.transaction-isolation"); + Optional validationTimeout = cfg.getLong("kumuluzee.datasources[" + i + "].pool.validation-timeout"); + Optional leakDetectionThreshold = cfg.getLong("kumuluzee.datasources[" + i + "].pool.leak-detection-threshold"); + + autoCommit.ifPresent(dspc::autoCommit); + connectionTimeout.ifPresent(dspc::connectionTimeout); + idleTimeout.ifPresent(dspc::idleTimeout); + maxLifetime.ifPresent(dspc::maxLifetime); + minIdle.ifPresent(dspc::minIdle); + maxSize.ifPresent(dspc::maxSize); + poolName.ifPresent(dspc::name); + initializationFailTimeout.ifPresent(dspc::initializationFailTimeout); + isolateInternalQueries.ifPresent(dspc::isolateInternalQueries); + allowPoolSuspension.ifPresent(dspc::allowPoolSuspension); + readOnly.ifPresent(dspc::readOnly); + registerMbeans.ifPresent(dspc::registerMbeans); + connectionInitSql.ifPresent(dspc::connectionInitSql); + transactionIsolation.ifPresent(dspc::transactionIsolation); + validationTimeout.ifPresent(dspc::validationTimeout); + leakDetectionThreshold.ifPresent(dspc::leakDetectionThreshold); + + dsc.pool(dspc); + } + + Optional> props = cfg.getMapKeys("kumuluzee.datasources[" + i + "].props"); + + if (props.isPresent()) { + + for (String propName : props.get()) { + + Optional propValue = cfg.get("kumuluzee.datasources[" + i + "].props." + propName); + + propValue.ifPresent(v -> dsc.prop(StringUtils.hyphenCaseToCamelCase(propName), v)); + } + } + + eeConfigBuilder.datasource(dsc); + } + } + + Optional xDsSizeOpt = cfg.getListSize("kumuluzee.xa-datasources"); + + if (xDsSizeOpt.isPresent()) { + + for (int i = 0; i < xDsSizeOpt.get(); i++) { + + XaDataSourceConfig.Builder xdsc = new XaDataSourceConfig.Builder(); + + Optional jndiName = cfg.get("kumuluzee.xa-datasources[" + i + "].jndi-name"); + Optional xaDatasourceClass = cfg.get("kumuluzee.xa-datasources[" + i + "].xa-datasource-class"); + Optional user = cfg.get("kumuluzee.xa-datasources[" + i + "].username"); + Optional pass = cfg.get("kumuluzee.xa-datasources[" + i + "].password"); + + jndiName.ifPresent(xdsc::jndiName); + xaDatasourceClass.ifPresent(xdsc::xaDatasourceClass); + user.ifPresent(xdsc::username); + pass.ifPresent(xdsc::password); + + Optional> props = cfg.getMapKeys("kumuluzee.xa-datasources[" + i + "].props"); + + if (props.isPresent()) { + + for (String propName : props.get()) { + + Optional propValue = cfg.get("kumuluzee.xa-datasources[" + i + "].props." + propName); + + propValue.ifPresent(v -> xdsc.prop(StringUtils.hyphenCaseToCamelCase(propName), v)); + } + } + + eeConfigBuilder.xaDatasource(xdsc); + } + } + + PersistenceConfig.Builder persistenceBuilder = new PersistenceConfig.Builder(); + + EnvUtils.getEnv(LEGACY_DB_UNIT_ENV, persistenceBuilder::unitName); + EnvUtils.getEnv(LEGACY_DB_URL_ENV, persistenceBuilder::url); + EnvUtils.getEnv(LEGACY_DB_USER_ENV, persistenceBuilder::username); + EnvUtils.getEnv(LEGACY_DB_PASS_ENV, persistenceBuilder::password); + + eeConfigBuilder.persistenceConfig(persistenceBuilder); + + return eeConfigBuilder.build(); + } + + public static Boolean isEeConfigValid(EeConfig eeConfig) { + + return !(eeConfig == null || + eeConfig.getVersion() == null || + eeConfig.getDebug() == null || + eeConfig.getEnv() == null || + eeConfig.getDev() == null || + eeConfig.getServer() == null || + eeConfig.getServer().getContextPath() == null || + eeConfig.getServer().getForceHttps() == null || + eeConfig.getServer().getMinThreads() == null || + eeConfig.getServer().getMaxThreads() == null || + eeConfig.getServer().getHttp() == null || + eeConfig.getServer().getHttps() == null || + eeConfig.getServer().getHttp().getPort() == null || + eeConfig.getServer().getHttp().getHttp2() == null || + eeConfig.getServer().getHttp().getProxyForwarding() == null || + eeConfig.getServer().getHttp().getRequestHeaderSize() == null || + eeConfig.getServer().getHttp().getResponseHeaderSize() == null || + eeConfig.getServer().getHttp().getIdleTimeout() == null || + eeConfig.getServer().getHttp().getSoLingerTime() == null || + eeConfig.getServer().getHttps().getPort() == null || + eeConfig.getServer().getHttps().getHttp2() == null || + eeConfig.getServer().getHttps().getProxyForwarding() == null || + eeConfig.getServer().getHttps().getRequestHeaderSize() == null || + eeConfig.getServer().getHttps().getResponseHeaderSize() == null || + eeConfig.getServer().getHttps().getIdleTimeout() == null || + eeConfig.getServer().getHttps().getSoLingerTime() == null || + eeConfig.getServer().getHttps().getKeystorePath() == null || + eeConfig.getServer().getHttps().getKeystorePassword() == null || + eeConfig.getDatasources().stream().anyMatch(ds -> + (ds == null || ds.getPool() == null || + ds.getPool().getAutoCommit() == null || + ds.getPool().getConnectionTimeout() == null || + ds.getPool().getIdleTimeout() == null || + ds.getPool().getMaxLifetime() == null || + ds.getPool().getMaxSize() == null || + ds.getPool().getInitializationFailTimeout() == null || + ds.getPool().getIsolateInternalQueries() == null || + ds.getPool().getAllowPoolSuspension() == null || + ds.getPool().getReadOnly() == null || + ds.getPool().getRegisterMbeans() == null || + ds.getPool().getValidationTimeout() == null || + ds.getPool().getLeakDetectionThreshold() == null))); + } + + private static ServerConnectorConfig.Builder createServerConnectorConfigBuilder(String prefix, Integer defaultPort) { + + ConfigurationUtil cfg = ConfigurationUtil.getInstance(); + + ServerConnectorConfig.Builder serverConnectorBuilder = new ServerConnectorConfig.Builder(); + + serverConnectorBuilder.port(defaultPort); + + EnvUtils.getEnvAsInteger(LEGACY_REQUEST_HEADER_SIZE_ENV, serverConnectorBuilder::requestHeaderSize); + EnvUtils.getEnvAsInteger(LEGACY_RESPONSE_HEADER_SIZE_ENV, serverConnectorBuilder::responseHeaderSize); + + Optional> serverConnectorCfgOpt = cfg.getMapKeys(prefix); + + if (serverConnectorCfgOpt.isPresent()) { + + Optional port = cfg.getInteger(prefix + ".port"); + Optional address = cfg.get(prefix + ".address"); + Optional enabled = cfg.getBoolean(prefix + ".enabled"); + Optional http2 = cfg.getBoolean(prefix + ".http2"); + Optional proxyForwarding = cfg.getBoolean(prefix + ".proxy-forwarding"); + Optional requestHeaderSize = cfg.getInteger(prefix + ".request-header-size"); + Optional responseHeaderSize = cfg.getInteger(prefix + ".kresponse-header-size"); + Optional idleTimeout = cfg.getInteger(prefix + ".idle-timeout"); + Optional soLingerTime = cfg.getInteger(prefix + ".so-linger-time"); + + Optional keystorePath = cfg.get(prefix + ".keystore-path"); + Optional keystorePassword = cfg.get(prefix + ".keystore-password"); + Optional keyAlias = cfg.get(prefix + ".key-alias"); + Optional keyPassword = cfg.get(prefix + ".key-password"); + Optional sslProtocols = cfg.get(prefix + ".ssl-protocols"); + Optional sslCiphers = cfg.get(prefix + ".ssl-ciphers"); + + port.ifPresent(serverConnectorBuilder::port); + address.ifPresent(serverConnectorBuilder::address); + enabled.ifPresent(serverConnectorBuilder::enabled); + http2.ifPresent(serverConnectorBuilder::http2); + proxyForwarding.ifPresent(serverConnectorBuilder::proxyForwarding); + requestHeaderSize.ifPresent(serverConnectorBuilder::requestHeaderSize); + responseHeaderSize.ifPresent(serverConnectorBuilder::responseHeaderSize); + idleTimeout.ifPresent(serverConnectorBuilder::idleTimeout); + soLingerTime.ifPresent(serverConnectorBuilder::soLingerTime); + + keystorePath.ifPresent(serverConnectorBuilder::keystorePath); + keystorePassword.ifPresent(serverConnectorBuilder::keystorePassword); + keyAlias.ifPresent(serverConnectorBuilder::keyAlias); + keyPassword.ifPresent(serverConnectorBuilder::keyPassword); + sslProtocols.ifPresent(p -> serverConnectorBuilder.sslProtocols(Stream.of(p.split(",")).map(String::trim).collect(Collectors.toList()))); + sslCiphers.ifPresent(c -> serverConnectorBuilder.sslCiphers(Stream.of(c.split(",")).map(String::trim).collect(Collectors.toList()))); + } + + return serverConnectorBuilder; + } +} diff --git a/core/src/main/java/com/kumuluz/ee/factories/JtaXADataSourceFactory.java b/core/src/main/java/com/kumuluz/ee/factories/JtaXADataSourceFactory.java new file mode 100644 index 00000000..ba133737 --- /dev/null +++ b/core/src/main/java/com/kumuluz/ee/factories/JtaXADataSourceFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.factories; + +import com.kumuluz.ee.common.datasources.NonJtaXADataSourceWrapper; +import com.kumuluz.ee.jta.common.datasources.JtaXADataSourceWrapper; + +import javax.sql.XADataSource; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public class JtaXADataSourceFactory { + + public static NonJtaXADataSourceWrapper buildJtaXADataSourceWrapper(XADataSource xaDataSource) { + + return new JtaXADataSourceWrapper(xaDataSource); + } +} diff --git a/core/src/main/java/com/kumuluz/ee/loaders/ComponentLoader.java b/core/src/main/java/com/kumuluz/ee/loaders/ComponentLoader.java index 191be280..ca8f72d5 100644 --- a/core/src/main/java/com/kumuluz/ee/loaders/ComponentLoader.java +++ b/core/src/main/java/com/kumuluz/ee/loaders/ComponentLoader.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.loaders; import com.kumuluz.ee.common.Component; diff --git a/core/src/main/java/com/kumuluz/ee/loaders/ConfigExtensionLoader.java b/core/src/main/java/com/kumuluz/ee/loaders/ConfigExtensionLoader.java new file mode 100644 index 00000000..e4687757 --- /dev/null +++ b/core/src/main/java/com/kumuluz/ee/loaders/ConfigExtensionLoader.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.loaders; + +import com.kumuluz.ee.common.ConfigExtension; +import com.kumuluz.ee.common.dependencies.EeExtensionDef; +import com.kumuluz.ee.common.dependencies.EeExtensionGroup; +import com.kumuluz.ee.common.exceptions.KumuluzServerException; + +import java.util.ArrayList; +import java.util.List; +import java.util.ServiceLoader; +import java.util.logging.Logger; + +/** + * @author Tilen Faganel + * @since 2.3.0 + */ +public class ConfigExtensionLoader { + + private static final Logger log = Logger.getLogger(ConfigExtensionLoader.class.getSimpleName()); + + public static List loadExtensions() { + + log.info("Loading available config extensions"); + + List extensions = scanForAvailableExtensions(); + + for (ConfigExtension e : extensions) { + + EeExtensionDef eeExtensionDef = e.getClass().getDeclaredAnnotation(EeExtensionDef.class); + + if (eeExtensionDef == null) { + + String msg = "The found class \"" + e.getClass().getSimpleName() + "\" is missing an extension" + + "definition annotation. The annotation is required in order to correctly process the " + + "extension type and its dependencies."; + + log.severe(msg); + + throw new KumuluzServerException(msg); + } + + if (!eeExtensionDef.group().equalsIgnoreCase(EeExtensionGroup.CONFIG)) { + + String msg = "The found class \"" + e.getClass().getSimpleName() + "\" does not have the correct " + + "extension group defined. The interface \"ConfigExtension\" requires that the supporting " + + " definition annotations specifies the extension group of \"config\". "; + + log.severe(msg); + + throw new KumuluzServerException(msg); + } + } + + log.info("Config extension loading complete"); + + return extensions; + } + + private static List scanForAvailableExtensions() { + + List extensions = new ArrayList<>(); + + ServiceLoader.load(ConfigExtension.class).forEach(extensions::add); + + return extensions; + } +} diff --git a/core/src/main/java/com/kumuluz/ee/loaders/ExtensionLoader.java b/core/src/main/java/com/kumuluz/ee/loaders/ExtensionLoader.java new file mode 100644 index 00000000..17468de0 --- /dev/null +++ b/core/src/main/java/com/kumuluz/ee/loaders/ExtensionLoader.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.loaders; + +import com.kumuluz.ee.common.Extension; +import com.kumuluz.ee.common.dependencies.EeExtensionDef; +import com.kumuluz.ee.common.dependencies.EeExtensionGroup; +import com.kumuluz.ee.common.exceptions.KumuluzServerException; + +import java.util.ArrayList; +import java.util.List; +import java.util.ServiceLoader; +import java.util.logging.Logger; + +/** + * @author Jan Meznarič + * @since 2.3.0 + */ +public class ExtensionLoader { + + private static final Logger log = Logger.getLogger(ExtensionLoader.class.getSimpleName()); + + public static List loadExtensions() { + + log.info("Loading available extensions"); + + List extensions = scanForAvailableExtensions(); + + for (Extension e : extensions) { + + EeExtensionDef eeExtensionDef = e.getClass().getDeclaredAnnotation(EeExtensionDef.class); + + if (eeExtensionDef == null) { + + String msg = "The found class \"" + e.getClass().getSimpleName() + "\" is missing an extension" + + "definition annotation. The annotation is required in order to correctly process the " + + "extension type and its dependencies."; + + log.severe(msg); + + throw new KumuluzServerException(msg); + } + + if (eeExtensionDef.group().equalsIgnoreCase(EeExtensionGroup.CONFIG)) { + + String msg = "The found class \"" + e.getClass().getSimpleName() + "\" does not have the correct " + + "extension group defined. The extension group \"config\" requires that the class implements " + + "the \"ConfigExtension\" interface."; + + log.severe(msg); + + throw new KumuluzServerException(msg); + } else if (eeExtensionDef.group().equalsIgnoreCase(EeExtensionGroup.LOGS)) { + + String msg = "The found class \"" + e.getClass().getSimpleName() + "\" does not have the correct " + + "extension group defined. The extension group \"logs\" requires that the class implements " + + "the \"LogsExtension\" interface."; + + log.severe(msg); + + throw new KumuluzServerException(msg); + } + } + + log.info("Extension loading complete"); + + return extensions; + } + + private static List scanForAvailableExtensions() { + + List extensions = new ArrayList<>(); + + ServiceLoader.load(Extension.class).forEach(extensions::add); + + return extensions; + } +} diff --git a/core/src/main/java/com/kumuluz/ee/loaders/LogsExtensionLoader.java b/core/src/main/java/com/kumuluz/ee/loaders/LogsExtensionLoader.java new file mode 100644 index 00000000..a8c0292b --- /dev/null +++ b/core/src/main/java/com/kumuluz/ee/loaders/LogsExtensionLoader.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.loaders; + +import com.kumuluz.ee.common.LogsExtension; +import com.kumuluz.ee.common.dependencies.EeExtensionDef; +import com.kumuluz.ee.common.dependencies.EeExtensionGroup; +import com.kumuluz.ee.common.exceptions.KumuluzServerException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.ServiceLoader; +import java.util.logging.Logger; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class LogsExtensionLoader { + + public static Optional loadExtension() { + + List extensions = scanForAvailableExtensions(); + + if (extensions.size() > 1) { + + String implementations = extensions.stream().skip(1) + .map(e -> e.getClass().getSimpleName()) + .reduce(extensions.get(0).getClass().getSimpleName(), (s, e) -> ", " + e.getClass().getSimpleName()); + + Logger log = Logger.getLogger(LogsExtensionLoader.class.getSimpleName()); + + String msg = "Found multiple implementations (" + implementations + ") of the same EE extension group (logs). " + + "Please check to make sure you only include a single implementation of a specific " + + "EE extension group."; + + log.severe(msg); + + throw new KumuluzServerException(msg); + } + + if (extensions.size() == 1) { + + LogsExtension logsExtension = extensions.get(0); + + EeExtensionDef eeExtensionDef = logsExtension.getClass().getDeclaredAnnotation(EeExtensionDef.class); + + if (eeExtensionDef == null) { + + String msg = "The found class \"" + logsExtension.getClass().getSimpleName() + "\" is missing an extension" + + "definition annotation. The annotation is required in order to correctly process the " + + "extension type and its dependencies."; + + Logger log = Logger.getLogger(LogsExtensionLoader.class.getSimpleName()); + + log.severe(msg); + + throw new KumuluzServerException(msg); + } + + if (!eeExtensionDef.group().equalsIgnoreCase(EeExtensionGroup.LOGS)) { + + String msg = "The found class \"" + logsExtension.getClass().getSimpleName() + "\" does not have the correct " + + "extension group defined. The interface \"LogsExtension\" requires that the supporting " + + " definition annotations specifies the extension group of \"logs\". "; + + Logger log = Logger.getLogger(LogsExtensionLoader.class.getSimpleName()); + + log.severe(msg); + + throw new KumuluzServerException(msg); + } + + return Optional.of(logsExtension); + } + + return Optional.empty(); + } + + private static List scanForAvailableExtensions() { + + List extensions = new ArrayList<>(); + + ServiceLoader.load(LogsExtension.class).forEach(extensions::add); + + return extensions; + } +} diff --git a/core/src/main/java/com/kumuluz/ee/loaders/ServerLoader.java b/core/src/main/java/com/kumuluz/ee/loaders/ServerLoader.java index 1aeca9c3..f87971f7 100644 --- a/core/src/main/java/com/kumuluz/ee/loaders/ServerLoader.java +++ b/core/src/main/java/com/kumuluz/ee/loaders/ServerLoader.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.loaders; import com.kumuluz.ee.common.KumuluzServer; diff --git a/core/src/test/java/com/kumuluz/ee/test/ExampleTest.java b/core/src/test/java/com/kumuluz/ee/test/ExampleTest.java index e3c9091b..30ae995c 100644 --- a/core/src/test/java/com/kumuluz/ee/test/ExampleTest.java +++ b/core/src/test/java/com/kumuluz/ee/test/ExampleTest.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.test; import org.junit.Assert; diff --git a/gpg.tar.enc b/gpg.tar.enc deleted file mode 100644 index 9a5177db..00000000 Binary files a/gpg.tar.enc and /dev/null differ diff --git a/gpg.tar.gz.enc b/gpg.tar.gz.enc new file mode 100644 index 00000000..49cded0d Binary files /dev/null and b/gpg.tar.gz.enc differ diff --git a/pom.xml b/pom.xml index a771e9d7..197774bf 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ com.kumuluz.ee kumuluzee pom - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT common core @@ -15,6 +15,7 @@ components bom profiles + tools KumuluzEE @@ -45,12 +46,35 @@ 1.1.0.Final 1.0 3.2 + 1.2 2.0.3.Final - 2.6.1 - 1.11 + 3.3.0.Final + 2.6.3 1.18 4.12 + 3.5.0 + 3.5 + 2.3.0 + + 3.0.2 + 3.0.2 + 3.5 + 3.0.1 + + 3.0.0 + 2.4.4.Final + 5.4.1.Final + 2.25.1 + 2.8.10 + 2.3.1 + 5.2.10.Final + 2.6.4 + 2.2.14 + 1.0.4 + 9.4.6.v20170531 + 5.6.4.Final + 7.6.0.Final @@ -236,6 +260,21 @@ kumuluzee-json-p-jsonp ${project.version} + + com.kumuluz.ee + kumuluzee-jta + ${project.version} + + + com.kumuluz.ee + kumuluzee-jta-common + ${project.version} + + + com.kumuluz.ee + kumuluzee-jta-narayana + ${project.version} + com.kumuluz.ee kumuluzee-bom @@ -258,6 +297,23 @@ kumuluzee-microProfile-1.0 ${project.version} + + com.kumuluz.ee + kumuluzee-tools + ${project.version} + pom + + + com.kumuluz.ee + kumuluzee-loader + ${project.version} + + + com.kumuluz.ee + kumuluzee-maven-plugin + ${project.version} + maven-plugin + @@ -325,6 +381,11 @@ javax.ejb-api ${ejb.version} + + javax.transaction + javax.transaction-api + ${jta.version} + @@ -332,6 +393,11 @@ jandex ${jandex.version} + + org.jboss.logging + jboss-logging + ${jboss-logging.version} + com.zaxxer HikariCP diff --git a/profiles/micro-profile-1.0/pom.xml b/profiles/micro-profile-1.0/pom.xml index ef855556..6e504104 100644 --- a/profiles/micro-profile-1.0/pom.xml +++ b/profiles/micro-profile-1.0/pom.xml @@ -5,7 +5,7 @@ kumuluzee-profiles com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -42,5 +42,4 @@ - \ No newline at end of file diff --git a/profiles/micro-profile-1.1/pom.xml b/profiles/micro-profile-1.1/pom.xml new file mode 100644 index 00000000..2d1d357e --- /dev/null +++ b/profiles/micro-profile-1.1/pom.xml @@ -0,0 +1,55 @@ + + + + kumuluzee-profiles + com.kumuluz.ee + 2.5.0-SNAPSHOT + + 4.0.0 + + KumuluzEE MicroProfile 1.1 + + KumuluzEE MicroProfile 1.1 which includes and tracks the version 1.1 community based specification found at + https://microprofile.io, which focuses on technologies best-suited to build modern Java based cloud + applications that follow the microservice architecture. The main KumuluzEE profile includes the reference + implementations of the profile/specification. + + + kumuluzee-microProfile-1.1 + + + 1.1.0-SNAPSHOT + + + + + com.kumuluz.ee + kumuluzee-core + + + com.kumuluz.ee + kumuluzee-servlet-jetty + + + com.kumuluz.ee + kumuluzee-cdi-weld + + + com.kumuluz.ee + kumuluzee-jax-rs-jersey + + + com.kumuluz.ee + kumuluzee-json-p-jsonp + + + + com.kumuluz.ee.config + kumuluzee-config-mp + ${version.kumuluzee-config-mp} + + + + \ No newline at end of file diff --git a/profiles/micro-profile/pom.xml b/profiles/micro-profile/pom.xml index cdb4c8ec..490aab71 100644 --- a/profiles/micro-profile/pom.xml +++ b/profiles/micro-profile/pom.xml @@ -5,7 +5,7 @@ kumuluzee-profiles com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 diff --git a/profiles/pom.xml b/profiles/pom.xml index 37bfa580..8815a27b 100644 --- a/profiles/pom.xml +++ b/profiles/pom.xml @@ -5,7 +5,7 @@ kumuluzee com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom @@ -18,6 +18,7 @@ micro-profile micro-profile-1.0 + micro-profile-1.1 kumuluzee-profiles diff --git a/servlet/jetty/pom.xml b/servlet/jetty/pom.xml index ec3d24f9..f47df105 100644 --- a/servlet/jetty/pom.xml +++ b/servlet/jetty/pom.xml @@ -5,7 +5,7 @@ kumuluzee-servlet com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 @@ -14,10 +14,6 @@ kumuluzee-servlet-jetty - - 9.3.16.v20170120 - - com.kumuluz.ee @@ -34,6 +30,50 @@ jetty-annotations ${jetty.version} + + org.eclipse.jetty + jetty-jndi + ${jetty.version} + + + org.eclipse.jetty.http2 + http2-server + ${jetty.version} + + + org.eclipse.jetty + jetty-alpn-server + ${jetty.version} + + + org.eclipse.jetty.http2 + http2-http-client-transport + ${jetty.version} + + + + org.glassfish.jersey.connectors + jersey-jetty-connector + ${jersey.version} + + + org.eclipse.jetty + jetty-client + + + org.glassfish.jersey.core + jersey-common + + + org.glassfish.jersey.core + jersey-client + + + javax.ws.rs + javax.ws.rs-api + + + junit diff --git a/servlet/jetty/src/main/java/com/kumuluz/ee/jetty/JettyAttributes.java b/servlet/jetty/src/main/java/com/kumuluz/ee/jetty/JettyAttributes.java index d25b7f81..43b8244b 100644 --- a/servlet/jetty/src/main/java/com/kumuluz/ee/jetty/JettyAttributes.java +++ b/servlet/jetty/src/main/java/com/kumuluz/ee/jetty/JettyAttributes.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jetty; /** @@ -8,4 +28,6 @@ public class JettyAttributes { public static final String jarPattern = "org.eclipse.jetty.server.webapp" + ".ContainerIncludeJarPattern"; + + public static final String dirBrowsing = "org.eclipse.jetty.servlet.Default.dirAllowed"; } diff --git a/servlet/jetty/src/main/java/com/kumuluz/ee/jetty/JettyFactory.java b/servlet/jetty/src/main/java/com/kumuluz/ee/jetty/JettyFactory.java index 43d8cd57..0ed8ef93 100644 --- a/servlet/jetty/src/main/java/com/kumuluz/ee/jetty/JettyFactory.java +++ b/servlet/jetty/src/main/java/com/kumuluz/ee/jetty/JettyFactory.java @@ -1,25 +1,48 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jetty; import com.kumuluz.ee.common.config.ServerConfig; - +import com.kumuluz.ee.common.config.ServerConnectorConfig; +import com.kumuluz.ee.common.utils.StringUtils; +import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory; import org.eclipse.jetty.annotations.AnnotationConfiguration; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.http2.HTTP2Cipher; +import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory; +import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory; import org.eclipse.jetty.plus.webapp.EnvConfiguration; import org.eclipse.jetty.plus.webapp.PlusConfiguration; -import org.eclipse.jetty.server.Connector; -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.server.*; +import org.eclipse.jetty.util.log.JavaUtilLog; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.ThreadPool; -import org.eclipse.jetty.webapp.Configuration; -import org.eclipse.jetty.webapp.FragmentConfiguration; -import org.eclipse.jetty.webapp.JettyWebXmlConfiguration; -import org.eclipse.jetty.webapp.MetaInfConfiguration; -import org.eclipse.jetty.webapp.WebInfConfiguration; -import org.eclipse.jetty.webapp.WebXmlConfiguration; +import org.eclipse.jetty.webapp.*; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Logger; +import java.util.stream.Collectors; /** * @author Tilen Faganel @@ -31,11 +54,6 @@ public class JettyFactory { private ServerConfig serverConfig; - public JettyFactory() { - - this.serverConfig = new ServerConfig(); - } - public JettyFactory(ServerConfig serverConfig) { this.serverConfig = serverConfig; @@ -43,18 +61,18 @@ public JettyFactory(ServerConfig serverConfig) { public Server create() { + Log.setLog(new JavaUtilLog()); + Server server = new Server(createThreadPool()); server.addBean(createClassList()); server.setStopAtShutdown(true); - server.setConnectors(new Connector[]{ - createConnector(server) - }); + server.setConnectors(createConnectors(server)); return server; } - protected ThreadPool createThreadPool() { + private ThreadPool createThreadPool() { QueuedThreadPool threadPool = new QueuedThreadPool(); @@ -67,26 +85,150 @@ protected ThreadPool createThreadPool() { return threadPool; } - protected Connector createConnector(final Server server) { + private Connector[] createConnectors(final Server server) { + + ServerConnectorConfig httpConfig = serverConfig.getHttp(); + ServerConnectorConfig httpsConfig = serverConfig.getHttps(); + + List connectors = new ArrayList<>(); + + if (Boolean.FALSE.equals(httpConfig.getEnabled()) && Boolean.FALSE.equals(httpsConfig.getEnabled())) { + throw new IllegalStateException("Both the HTTP and HTTPS connectors can not be disabled. Please enable at least one."); + } + + if (serverConfig.getForceHttps() && !Boolean.TRUE.equals(httpsConfig.getEnabled())) { + throw new IllegalStateException("You must enable the HTTPS connector in order to force redirects to it (`kumuluzee.server.https.enabled` must be true)."); + } + + if (httpConfig.getEnabled() == null || httpConfig.getEnabled()) { + + HttpConfiguration httpConfiguration = new HttpConfiguration(); + httpConfiguration.setRequestHeaderSize(httpConfig.getRequestHeaderSize()); + httpConfiguration.setResponseHeaderSize(httpConfig.getResponseHeaderSize()); + + if (Boolean.TRUE.equals(httpConfig.getProxyForwarding())) { + httpConfiguration.addCustomizer(new ForwardedRequestCustomizer()); + } + + if (Boolean.TRUE.equals(httpsConfig.getEnabled())) { + httpConfiguration.setSecurePort(httpsConfig.getPort()); + } + + ServerConnector httpConnector; + + HttpConnectionFactory http = new HttpConnectionFactory(httpConfiguration); + + if (httpConfig.getHttp2()) { + + HTTP2CServerConnectionFactory http2c = new HTTP2CServerConnectionFactory(httpConfiguration); + + httpConnector = new ServerConnector(server, http, http2c); + } else { + + httpConnector = new ServerConnector(server, http); + } + + httpConnector.setPort(httpConfig.getPort()); + httpConnector.setHost(httpConfig.getAddress()); + + httpConnector.setIdleTimeout(httpConfig.getIdleTimeout()); + httpConnector.setSoLingerTime(httpConfig.getSoLingerTime()); + + connectors.add(httpConnector); + } + + if (httpsConfig.getEnabled() != null && httpsConfig.getEnabled()) { + + if (StringUtils.isNullOrEmpty(httpsConfig.getKeystorePath())) { + throw new IllegalStateException("Cannot create SSL connector; keystore path not specified."); + } + + if (StringUtils.isNullOrEmpty(httpsConfig.getKeystorePassword())) { + throw new IllegalStateException("Cannot create SSL connector; keystore password not specified."); + } + + if (StringUtils.isNullOrEmpty(httpsConfig.getKeyPassword())) { + throw new IllegalStateException("Cannot create SSL connector; key password not specified."); + } + + ServerConnector httpsConnector; + + HttpConfiguration httpsConfiguration = new HttpConfiguration(); + httpsConfiguration.setRequestHeaderSize(httpsConfig.getRequestHeaderSize()); + httpsConfiguration.setResponseHeaderSize(httpsConfig.getResponseHeaderSize()); + httpsConfiguration.addCustomizer(new SecureRequestCustomizer()); + + if (Boolean.TRUE.equals(httpsConfig.getProxyForwarding())) { + httpsConfiguration.addCustomizer(new ForwardedRequestCustomizer()); + } + + HttpConnectionFactory http = new HttpConnectionFactory(httpsConfiguration); + + SslContextFactory sslContextFactory = new SslContextFactory(); + sslContextFactory.setKeyStorePath(httpsConfig.getKeystorePath()); + sslContextFactory.setKeyStorePassword(httpsConfig.getKeystorePassword()); + + if (httpsConfig.getKeyPassword() != null) { + sslContextFactory.setKeyManagerPassword(httpsConfig.getKeyPassword()); + } + + if (StringUtils.isNullOrEmpty(httpsConfig.getKeyAlias())) { + sslContextFactory.setCertAlias(httpsConfig.getKeyAlias()); + } + + if (httpsConfig.getSslProtocols() != null) { + + sslContextFactory.setIncludeProtocols(httpsConfig.getSslProtocols().toArray(new String[0])); + } + + if (httpsConfig.getSslCiphers() != null) { + + sslContextFactory.setExcludeCipherSuites(); + sslContextFactory.setIncludeCipherSuites(httpsConfig.getSslCiphers().toArray(new String[0])); + } + + if (httpsConfig.getHttp2()) { + + sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR); + sslContextFactory.setUseCipherSuitesOrder(true); + + NegotiatingServerConnectionFactory.checkProtocolNegotiationAvailable(); + + HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfiguration); + + ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory(); + alpn.setDefaultProtocol(HttpVersion.HTTP_1_1.toString()); + + SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, alpn.getProtocol()); + + httpsConnector = new ServerConnector(server, ssl, alpn, h2, http); + } else { + + SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, http.getProtocol()); + + httpsConnector = new ServerConnector(server, ssl, http); + } - HttpConfiguration configuration = new HttpConfiguration(); - configuration.setRequestHeaderSize(serverConfig.getRequestHeaderSize()); - configuration.setResponseHeaderSize(serverConfig.getResponseHeaderSize()); + httpsConnector.setPort(httpsConfig.getPort()); + httpsConnector.setHost(httpsConfig.getAddress()); - ServerConnector connector = new ServerConnector( - server, new HttpConnectionFactory(configuration)); + httpsConnector.setIdleTimeout(httpsConfig.getIdleTimeout()); + httpsConnector.setSoLingerTime(httpsConfig.getSoLingerTime()); - connector.setPort(serverConfig.getPort()); + connectors.add(httpsConnector); + } - connector.setIdleTimeout(serverConfig.getIdleTimeout()); - connector.setSoLingerTime(serverConfig.getSoLingerTime()); + String ports = connectors.stream() + .map(connector -> + String.format("%d [%s]", connector.getPort(), String.join(", ", connector.getProtocols()))) + .collect(Collectors.joining(", ")); - log.info("Starting KumuluzEE on port " + serverConfig.getPort()); + log.info(String.format("Starting KumuluzEE on port(s): %s", ports)); - return connector; + return connectors.toArray(new ServerConnector[connectors.size()]); } - protected Configuration.ClassList createClassList() { + private Configuration.ClassList createClassList() { Configuration.ClassList classList = new Configuration.ClassList(new String[0]); diff --git a/servlet/jetty/src/main/java/com/kumuluz/ee/jetty/JettyServletServer.java b/servlet/jetty/src/main/java/com/kumuluz/ee/jetty/JettyServletServer.java index 23a08d58..c5f9c3f4 100644 --- a/servlet/jetty/src/main/java/com/kumuluz/ee/jetty/JettyServletServer.java +++ b/servlet/jetty/src/main/java/com/kumuluz/ee/jetty/JettyServletServer.java @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ package com.kumuluz.ee.jetty; import com.kumuluz.ee.common.ServletServer; @@ -9,17 +29,18 @@ import com.kumuluz.ee.common.utils.ResourceUtils; import org.eclipse.jetty.plus.jndi.Resource; +import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.HandlerList; +import org.eclipse.jetty.server.handler.SecuredRedirectHandler; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.webapp.WebAppContext; -import java.util.EnumSet; -import java.util.EventListener; -import java.util.Map; +import java.util.*; import java.util.logging.Logger; -import javax.naming.NamingException; +import javax.naming.*; import javax.servlet.DispatcherType; import javax.servlet.Filter; import javax.servlet.Servlet; @@ -61,7 +82,7 @@ public void startServer() { log.severe(e.getMessage()); - throw new KumuluzServerException(e.getMessage(), e.getCause()); + throw new KumuluzServerException(e.getMessage(), e); } } @@ -88,15 +109,24 @@ public void stopServer() { public void initWebContext() { if (server == null) - throw new IllegalStateException("Jetty has to be initialized before adding a web " + - "context"); + throw new IllegalStateException("Jetty has to be initialized before adding a web context"); if (server.isStarted() || server.isStarting()) throw new IllegalStateException("Jetty cannot be started before adding a web context"); appContext = new WebAppContext(); - appContext.setAttribute(JettyAttributes.jarPattern, ClasspathAttributes.exploded); + if (ResourceUtils.isRunningInJar()) { + appContext.setAttribute(JettyAttributes.jarPattern, ClasspathAttributes.jar); + + try { + appContext.setClassLoader(getClass().getClassLoader()); + } catch (Exception e) { + throw new IllegalStateException("Unable to set custom classloader for Jetty"); + } + } else { + appContext.setAttribute(JettyAttributes.jarPattern, ClasspathAttributes.exploded); + } appContext.setParentLoaderPriority(true); @@ -104,9 +134,25 @@ public void initWebContext() { appContext.setContextPath(serverConfig.getContextPath()); + if (!Boolean.TRUE.equals(serverConfig.getDirBrowsing())) { + + appContext.setInitParameter(JettyAttributes.dirBrowsing, "false"); + } + log.info("Starting KumuluzEE with context root '" + serverConfig.getContextPath() + "'"); - server.setHandler(appContext); + // Set the secured redirect handler in case the force https option is selected + if (serverConfig.getForceHttps()) { + + HandlerList handlers = new HandlerList(); + handlers.setHandlers(new Handler[] + { new SecuredRedirectHandler(), appContext}); + + server.setHandler(handlers); + } else { + + server.setHandler(appContext); + } } @Override @@ -208,7 +254,7 @@ public void registerDataSource(DataSource ds, String jndiName) { appContext.setAttribute(jndiName, resource); } catch (NamingException e) { - throw new IllegalArgumentException("Unable to create naming data source entry with jndi name " + jndiName + ""); + throw new IllegalArgumentException("Unable to create naming data source entry with jndi name " + jndiName + "", e); } } diff --git a/servlet/jetty/src/main/resources/META-INF/services/org.glassfish.jersey.client.spi.ConnectorProvider b/servlet/jetty/src/main/resources/META-INF/services/org.glassfish.jersey.client.spi.ConnectorProvider new file mode 100644 index 00000000..beab981a --- /dev/null +++ b/servlet/jetty/src/main/resources/META-INF/services/org.glassfish.jersey.client.spi.ConnectorProvider @@ -0,0 +1 @@ +org.glassfish.jersey.jetty.connector.JettyConnectorProvider \ No newline at end of file diff --git a/servlet/pom.xml b/servlet/pom.xml index d65bd781..6c17acdd 100644 --- a/servlet/pom.xml +++ b/servlet/pom.xml @@ -5,7 +5,7 @@ kumuluzee com.kumuluz.ee - 2.3.0-SNAPSHOT + 2.5.0-SNAPSHOT 4.0.0 pom diff --git a/settings.xml b/settings.xml index 5a098a8a..864e0017 100644 --- a/settings.xml +++ b/settings.xml @@ -28,6 +28,20 @@ ~/build/${env.TRAVIS_REPO_SLUG}/gpg.pub ${env.GPG_PASSPHRASE} + + + + sonatype-snapshots + Sonatype Snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + diff --git a/tools/loader/pom.xml b/tools/loader/pom.xml new file mode 100644 index 00000000..1e3ea047 --- /dev/null +++ b/tools/loader/pom.xml @@ -0,0 +1,16 @@ + + + + kumuluzee-tools + com.kumuluz.ee + 2.5.0-SNAPSHOT + + 4.0.0 + + KumuluzEE Loader + KumuluzEE custom class loader implementation + + kumuluzee-loader + \ No newline at end of file diff --git a/tools/loader/src/main/java/com/kumuluz/ee/loader/EeBootLoader.java b/tools/loader/src/main/java/com/kumuluz/ee/loader/EeBootLoader.java new file mode 100644 index 00000000..62fe915d --- /dev/null +++ b/tools/loader/src/main/java/com/kumuluz/ee/loader/EeBootLoader.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.loader; + +import com.kumuluz.ee.loader.exception.EeClassLoaderException; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * @author Benjamin Kastelic + * + */ +public class EeBootLoader { + + public static void main(String[] args) throws Throwable { + + try { + ResourceBundle bootLoaderProperties = ResourceBundle.getBundle("META-INF/kumuluzee/boot-loader"); + + String mainClass = bootLoaderProperties.getString("main-class"); + + launch(args, mainClass); + } catch (MissingResourceException e) { + + throw new EeClassLoaderException("KumuluzEE Boot Loader config properties are malformed or missing.", e); + } + } + + /** + * Start the boot procedure. + * Use the {@link EeClassLoader} EeClassLoader to find, load and start the main class. + */ + private static void launch(String[] args, String mainClass) throws Throwable { + EeClassLoader classLoader = new EeClassLoader(); + classLoader.invokeMain(mainClass, args); + } +} diff --git a/tools/loader/src/main/java/com/kumuluz/ee/loader/EeClassLoader.java b/tools/loader/src/main/java/com/kumuluz/ee/loader/EeClassLoader.java new file mode 100644 index 00000000..a9fea26d --- /dev/null +++ b/tools/loader/src/main/java/com/kumuluz/ee/loader/EeClassLoader.java @@ -0,0 +1,638 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.loader; + +import com.kumuluz.ee.loader.exception.EeClassLoaderException; +import com.kumuluz.ee.loader.jar.JarEntryInfo; +import com.kumuluz.ee.loader.jar.JarFileInfo; + +import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLDecoder; +import java.security.CodeSource; +import java.security.ProtectionDomain; +import java.security.cert.Certificate; +import java.util.*; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.logging.Logger; + +/** + * @author Benjamin Kastelic + * @since 2.4.0 + */ +public class EeClassLoader extends ClassLoader { + + /** + * Directory name for temporary files. + */ + private static final String TMP_DIRECTORY = "EeClassLoader"; + + private Boolean DEBUG = false; + + private final Thread mainThread = Thread.currentThread(); + + private File tempDir; + private List jarFiles; + private Set deleteOnExit; + private Map> classes; + + /** + * Default constructor. + * Defines system class loader as a parent class loader. + */ + public EeClassLoader() { + this(ClassLoader.getSystemClassLoader()); + } + + /** + * Constructor. + */ + public EeClassLoader(ClassLoader parent) { + super(parent); + + String debugString = System.getProperty("com.kumuluz.ee.loader.debug"); + + if (debugString != null) { + + DEBUG = Boolean.valueOf(debugString); + } + + long startTime = System.currentTimeMillis(); + + debug("Initialising KumuluzEE classloader"); + + classes = new HashMap<>(); + jarFiles = new ArrayList<>(); + deleteOnExit = new HashSet<>(); + + String mainJarURLString; + ProtectionDomain protectionDomain = getClass().getProtectionDomain(); + CodeSource codeSource = protectionDomain.getCodeSource(); + URL mainJarURL = codeSource.getLocation(); + String protocol = mainJarURL.getProtocol(); + + JarFileInfo jarFileInfo; + // Decoding required for 'space char' in URL: + // URL.getFile() returns "/C:/my%20dir/MyApp.jar" for "/C:/my dir/MyApp.jar" + try { + mainJarURLString = URLDecoder.decode(mainJarURL.getFile(), "UTF-8"); + } catch (UnsupportedEncodingException e) { + + String msg = String.format("Failed to decode URL: %s %s", mainJarURL, e.toString()); + + throw new EeClassLoaderException(msg, e); + } + + File mainJarFile = new File(mainJarURLString); + + try { + jarFileInfo = new JarFileInfo(new JarFile(mainJarFile), mainJarFile.getName(), null, protectionDomain, null); + + debug(String.format("Loading from main JAR: '%s' PROTOCOL: '%s'", mainJarURLString, protocol)); + } catch (IOException e) { + + String msg = String.format("Not a JAR: %s %s", mainJarURLString, e.toString()); + + throw new EeClassLoaderException(msg, e); + } + + // load main JAR: + try { + // start recursive JAR loading + loadJar(jarFileInfo); + } catch (Exception e) { + + String msg = String.format("Not a valid URL: %s %s", mainJarURL, e.toString()); + + throw new EeClassLoaderException(msg, e); + } + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + try { + debug("Shutting down and cleaning up ..."); + mainThread.join(); + shutdown(); + } catch (InterruptedException e) { + debug("Failed to shutdown and clean up gracefully."); + } + })); + + debug(String.format("Initialised KumuluzEE classloader @%dms", System.currentTimeMillis() - startTime)); + } + + private File createTempFile(JarEntryInfo jarEntryInfo) throws EeClassLoaderException { + // Temp files directory: + // WinXP: C:/Documents and Settings/username/Local Settings/Temp/EeClassLoader + // Unix: /var/tmp/EeClassLoader + // Win7+: C:/Users/username/AppData/Local/Temp/EeClassLoader + if (tempDir == null) { + File dir = new File(System.getProperty("java.io.tmpdir"), TMP_DIRECTORY); + if (!dir.exists()) { + dir.mkdir(); + } + chmod777(dir); // Unix - allow temp directory RW access to all users. + if (!dir.exists() || !dir.isDirectory()) { + throw new EeClassLoaderException("Cannot create temp directory " + dir.getAbsolutePath()); + } + tempDir = dir; + } + + File tmpFile = null; + try { + tmpFile = File.createTempFile(jarEntryInfo.getName() + ".", null, tempDir); + tmpFile.deleteOnExit(); + chmod777(tmpFile); // Unix - allow temp file deletion by any user + byte[] bytes = jarEntryInfo.getJarBytes(); + BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile)); + os.write(bytes); + os.close(); + return tmpFile; + } catch (IOException e) { + throw new EeClassLoaderException(String.format("Cannot create temp file '%s' for %s", tmpFile, jarEntryInfo.getJarEntry()), e); + } + } + + /** + * Loads specified JAR. + */ + private void loadJar(final JarFileInfo jarFileInfo) { + final String JAR_SUFFIX = ".jar"; + + jarFiles.add(jarFileInfo); + jarFileInfo.getJarFile() + .stream() + .parallel() + .filter(je -> !je.isDirectory() && je.getName().toLowerCase().endsWith(JAR_SUFFIX)) + .forEach(je -> { + try { + JarEntryInfo jarEntryInfo = new JarEntryInfo(jarFileInfo, je); + File tempFile = createTempFile(jarEntryInfo); + + debug(String.format("Loading inner JAR %s from temp file %s", jarEntryInfo.getJarEntry(), getFilenameForLog(tempFile))); + + // Construct ProtectionDomain for this inner JAR: + URL url = tempFile.toURI().toURL(); + ProtectionDomain pdParent = jarFileInfo.getProtectionDomain(); + // 'csParent' is never null: top JAR has it, classloader creates it for child JAR: + CodeSource csParent = pdParent.getCodeSource(); + Certificate[] certParent = csParent.getCertificates(); + CodeSource csChild = certParent == null + ? new CodeSource(url, csParent.getCodeSigners()) + : new CodeSource(url, certParent); + ProtectionDomain pdChild = new ProtectionDomain(csChild, pdParent.getPermissions(), pdParent.getClassLoader(), pdParent.getPrincipals()); + loadJar(new JarFileInfo(new JarFile(tempFile), jarEntryInfo.getName(), jarFileInfo, pdChild, tempFile)); + } catch (IOException e) { + throw new RuntimeException(String.format("Cannot load jar entries from jar %s", je.getName().toLowerCase()), e); + } catch (EeClassLoaderException e) { + throw new RuntimeException("ERROR on loading inner JAR: " + e.getMessageAll()); + } + }); + } + + private JarEntryInfo findJarEntry(String name) { + for (JarFileInfo jarFileInfo : jarFiles) { + JarFile jarFile = jarFileInfo.getJarFile(); + JarEntry jarEntry = jarFile.getJarEntry(name); + if (jarEntry != null) { + return new JarEntryInfo(jarFileInfo, jarEntry); + } + } + return null; + } + + private List findJarEntries(String name) { + + List jarEntryInfoList = new ArrayList<>(); + + for (JarFileInfo jarFileInfo : jarFiles) { + + JarFile jarFile = jarFileInfo.getJarFile(); + JarEntry jarEntry = jarFile.getJarEntry(name); + if (jarEntry != null) { + jarEntryInfoList.add(new JarEntryInfo(jarFileInfo, jarEntry)); + } + } + return jarEntryInfoList; + } + + /** + * Finds native library entry. + * + * @param libraryName Library name. For example for the library name "Native" + * - Windows returns entry "Native.dll" + * - Linux returns entry "libNative.so" + * - Mac returns entry "libNative.jnilib" or "libNative.dylib" + * (depending on Apple or Oracle JDK and/or JDK version) + * @return Native library entry. + */ + private JarEntryInfo findJarNativeEntry(String libraryName) { + String name = System.mapLibraryName(libraryName); + for (JarFileInfo jarFileInfo : jarFiles) { + JarFile jarFile = jarFileInfo.getJarFile(); + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry jarEntry = entries.nextElement(); + if (jarEntry.isDirectory()) { + continue; + } + + // Example: name is "Native.dll" + String jarEntryName = jarEntry.getName(); // "Native.dll" or "abc/xyz/Native.dll" + // name "Native.dll" could be found, for example + // - in the path: abc/Native.dll/xyz/my.dll <-- do not load this one! + // - in the partial name: abc/aNative.dll <-- do not load this one! + String[] token = jarEntryName.split("/"); // the last token is library name + if (token.length > 0 && token[token.length - 1].equals(name)) { + + debug(String.format("Loading native library '%s' found as '%s' in JAR %s", libraryName, jarEntryName, jarFileInfo.getSimpleName())); + + return new JarEntryInfo(jarFileInfo, jarEntry); + } + } + } + return null; + } + + /** + * Loads class from a JAR and searches for all jar-in-jar. + */ + private Class findJarClass(String className) throws EeClassLoaderException { + Class clazz = classes.get(className); + if (clazz != null) { + return clazz; + } + + // Char '/' works for Win32 and Unix. + String fullClassName = className.replace('.', '/') + ".class"; + JarEntryInfo jarEntryInfo = findJarEntry(fullClassName); + String jarSimpleName = null; + if (jarEntryInfo != null) { + jarSimpleName = jarEntryInfo.getJarFileInfo().getSimpleName(); + definePackage(className, jarEntryInfo); + byte[] bytes = jarEntryInfo.getJarBytes(); + try { + clazz = defineClass(className, bytes, 0, bytes.length, jarEntryInfo.getJarFileInfo().getProtectionDomain()); + } catch (ClassFormatError e) { + throw new EeClassLoaderException(null, e); + } + } + if (clazz == null) { + throw new EeClassLoaderException(className); + } + classes.put(className, clazz); + + debug(String.format("Loaded %s by %s from JAR %s", className, getClass().getName(), jarSimpleName)); + + return clazz; + } + + /** + * Called on shutdown to cleanup temporary files. + */ + private void shutdown() { + + debug("Shutting down and cleaning up ..."); + + for (JarFileInfo jarFileInfo : jarFiles) { + try { + jarFileInfo.getJarFile().close(); + } catch (IOException e) { + // Ignore. In the worst case temp files will accumulate. + } + File file = jarFileInfo.getFileDeleteOnExit(); + if (file != null && !file.delete()) { + deleteOnExit.add(file); + } + } + // Private configuration file with failed to delete temporary files: + // WinXP: C:/Documents and Settings/username/.EeClassLoader + // Unix: /export/home/username/.EeClassLoader + // -or- /home/username/.EeClassLoader + File configFile = new File(System.getProperty("user.home") + File.separator + ".EeClassLoader"); + deleteOldTemp(configFile); + persistNewTemp(configFile); + } + + /** + * Deletes temporary files listed in the file. + * The method is called on shutdown(). + * + * @param configFile file with temporary files list. + */ + private void deleteOldTemp(File configFile) { + BufferedReader reader = null; + try { + int count = 0; + reader = new BufferedReader(new FileReader(configFile)); + String line; + while ((line = reader.readLine()) != null) { + File file = new File(line); + if (!file.exists()) { + continue; // already deleted; from command line? + } + if (file.delete()) { + count++; + } else { + // Cannot delete, will try next time. + deleteOnExit.add(file); + } + } + + debug(String.format("Deleted %d old temp files listed in %s", count, configFile.getAbsolutePath())); + } catch (IOException e) { + // Ignore. This file may not exist. + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + // Ignore + } + } + } + } + + /** + * Creates file with temporary files list. This list will be used to + * delete temporary files on the next application launch. + * The method is called from shutdown(). + * + * @param configFile file with temporary files list. + */ + private void persistNewTemp(File configFile) { + if (deleteOnExit.size() == 0) { + + debug("No temp file names to persist on exit."); + + configFile.delete(); // do not pollute disk + return; + } + + debug(String.format("Persisting %d temp file names into %s", deleteOnExit.size(), configFile.getAbsolutePath())); + + BufferedWriter writer = null; + try { + writer = new BufferedWriter(new FileWriter(configFile)); + for (File file : deleteOnExit) { + if (!file.delete()) { + String filePath = file.getCanonicalPath(); + writer.write(filePath); + writer.newLine(); + + debug(String.format("JVM failed to release %s", filePath)); + } + } + } catch (IOException e) { + // Ignore. In the worst case temp files will accumulate. + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + // Ignore + } + } + } + } + + /** + * Checks how the application was loaded: from JAR or file system. + */ + private boolean isLaunchedFromJar() { + return jarFiles != null && !jarFiles.isEmpty(); + } + + /** + * Invokes main() method on class with provided parameters. + */ + public void invokeMain(String className, String[] args) throws Throwable { + + Class clazz = loadClass(className); + + debug(String.format("Launch: %s.main(); Loader: %s", className, clazz.getClassLoader())); + + Method method = clazz.getMethod("main", String[].class); + + if (method == null) { + throw new NoSuchMethodException("The main() method in class \"" + className + "\" not found."); + } + + try { + method.invoke(null, (Object)args); + } catch (InvocationTargetException e) { + throw e.getTargetException(); + } + } + + @Override + protected synchronized Class loadClass(String className, boolean bResolve) throws ClassNotFoundException { + + debug(String.format("LOADING %s (resolve=%b)", className, bResolve)); + + Thread.currentThread().setContextClassLoader(this); // !!! + + Class clazz = null; + + try { + // Step 1. This class is already loaded by system classloader. + if (getClass().getName().equals(className)) { + return EeClassLoader.class; + } + // Step 2. Already loaded class. + clazz = findLoadedClass(className); + if (clazz != null) { + + debug(String.format("Class %s already loaded", className)); + + return clazz; + } + // Step 3. Load from JAR. + if (isLaunchedFromJar()) { + try { + clazz = findJarClass(className); // Do not simplify! See "finally"! + return clazz; + } catch (EeClassLoaderException e) { + if (e.getCause() == null) { + debug(String.format("Not found %s in JAR by %s: %s", className, getClass().getName(), e.getMessage())); + } else { + debug(String.format("Error loading %s in JAR by %s: %s", className, getClass().getName(), e.getCause())); + } + // keep looking... + } + } + // Step 4. Load by parent (usually system) class loader. + try { + ClassLoader classLoader = getParent(); + clazz = classLoader.loadClass(className); + + debug(String.format("Loaded %s by %s", className, classLoader.getClass().getName())); + + return clazz; + } catch (ClassNotFoundException e) { + // Ignore + } + // Nothing else to try ... + throw new ClassNotFoundException("Failure to load: " + className); + } finally { + if (clazz != null && bResolve) { + resolveClass(clazz); + } + } + } + + @Override + protected URL findResource(String name) { + + debug(String.format("findResource: %s", name)); + + if (isLaunchedFromJar()) { + JarEntryInfo inf = findJarEntry(normalizeResourceName(name)); + if (inf != null) { + URL url = inf.getURL(); + + debug(String.format("found resource: %s", url)); + + return url; + } + + debug(String.format("not found resource: %s", name)); + + return null; + } + + return super.findResource(name); + } + + @Override + public Enumeration getResources(String name) throws IOException { + return findResources(name); + } + + @Override + public Enumeration findResources(String name) throws IOException { + + debug(String.format("getResources: %s", name)); + + if (isLaunchedFromJar()) { + List jarEntries = findJarEntries(normalizeResourceName(name)); + List urls = new ArrayList<>(); + for (JarEntryInfo jarEntryInfo : jarEntries) { + URL url = jarEntryInfo.getURL(); + if (url != null) { + urls.add(url); + } + } + return Collections.enumeration(urls); + } + + return super.findResources(name); + } + + @Override + protected String findLibrary(String name) { + + debug(String.format("findLibrary: %s", name)); + + if (isLaunchedFromJar()) { + JarEntryInfo jarEntryInfo = findJarNativeEntry(name); + if (jarEntryInfo != null) { + try { + File file = createTempFile(jarEntryInfo); + + debug(String.format("Loading native library %s from temp file %s", jarEntryInfo.getJarEntry(), getFilenameForLog(file))); + + deleteOnExit.add(file); + return file.getAbsolutePath(); + } catch (EeClassLoaderException e) { + + debug(String.format("Failure to load native library %s: %s", name, e.toString())); + } + } + return null; + } + return super.findLibrary(name); + } + + /** + * The default ClassLoader.defineClass() does not create package + * for the loaded class and leaves it null. Each package referenced by this + * class loader must be created only once before the + * ClassLoader.defineClass() call. + * The base class ClassLoader keeps cache with created packages + * for reuse. + * + * @param className class to load. + * @throws IllegalArgumentException + * If package name duplicates an existing package either in this + * class loader or one of its ancestors. + */ + private void definePackage(String className, JarEntryInfo jarEntryInfo) throws IllegalArgumentException { + int index = className.lastIndexOf('.'); + String packageName = index > 0 ? className.substring(0, index) : ""; + if (getPackage(packageName) == null) { + JarFileInfo jarFileInfo = jarEntryInfo.getJarFileInfo(); + definePackage( + packageName, jarFileInfo.getSpecificationTitle(), jarFileInfo.getSpecificationVersion(), + jarFileInfo.getSpecificationVendor(), jarFileInfo.getImplementationTitle(), + jarFileInfo.getImplementationVersion(), jarFileInfo.getImplementationVendor(), + jarFileInfo.getSealURL() + ); + } + } + + /** + * The system class loader could load resources defined as + * "com/abc/Foo.txt" or "com\abc\Foo.txt". + * This method converts path with '\' to default '/' JAR delimiter. + * + * @param name resource name including path. + * @return normalized resource name. + */ + private String normalizeResourceName(String name) { + return name.replace('\\', '/'); + } + + private void chmod777(File file) { + file.setReadable(true, false); + file.setWritable(true, false); + file.setExecutable(true, false); // Unix: allow content for dir, redundant for file + } + + private String getFilenameForLog(File file) { + try { + // In form "C:\Documents and Settings\..." + return file.getCanonicalPath(); + } catch (IOException e) { + // In form "C:\DOCUME~1\..." + return file.getAbsolutePath(); + } + } + + private void debug(String msg) { + + if (DEBUG) { + System.out.println(msg); + } + } +} diff --git a/tools/loader/src/main/java/com/kumuluz/ee/loader/exception/EeClassLoaderException.java b/tools/loader/src/main/java/com/kumuluz/ee/loader/exception/EeClassLoaderException.java new file mode 100644 index 00000000..05fc4e0a --- /dev/null +++ b/tools/loader/src/main/java/com/kumuluz/ee/loader/exception/EeClassLoaderException.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.loader.exception; + +/** + * @author Benjamin Kastelic + * @since 2.4.0 + */ +public class EeClassLoaderException extends RuntimeException { + + public EeClassLoaderException(String message) { + super(message); + } + + public EeClassLoaderException(String message, Throwable cause) { + super(message, cause); + } + + public String getMessageAll() { + StringBuilder stringBuilder = new StringBuilder(); + + for (Throwable e = this; e != null; e = e.getCause()) { + if (stringBuilder.length() > 0) { + stringBuilder.append(" / "); + } + + String message = e.getMessage(); + if (message == null || message.length() == 0) { + message = e.getClass().getSimpleName(); + } + + stringBuilder.append(message); + } + + return stringBuilder.toString(); + } +} diff --git a/tools/loader/src/main/java/com/kumuluz/ee/loader/jar/JarEntryInfo.java b/tools/loader/src/main/java/com/kumuluz/ee/loader/jar/JarEntryInfo.java new file mode 100644 index 00000000..5439f865 --- /dev/null +++ b/tools/loader/src/main/java/com/kumuluz/ee/loader/jar/JarEntryInfo.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.loader.jar; + +import com.kumuluz.ee.loader.exception.EeClassLoaderException; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.jar.JarEntry; + +/** + * Class with JAR entry information. Keeps JAR file and entry object. + * + * @author Benjamin Kastelic + * @since 2.4.0 + */ +public class JarEntryInfo { + + private JarFileInfo jarFileInfo; + private JarEntry jarEntry; + + public JarEntryInfo(JarFileInfo jarFileInfo, JarEntry jarEntry) { + this.jarFileInfo = jarFileInfo; + this.jarEntry = jarEntry; + } + + public JarFileInfo getJarFileInfo() { + return jarFileInfo; + } + + public void setJarFileInfo(JarFileInfo jarFileInfo) { + this.jarFileInfo = jarFileInfo; + } + + public JarEntry getJarEntry() { + return jarEntry; + } + + public void setJarEntry(JarEntry jarEntry) { + this.jarEntry = jarEntry; + } + + public URL getURL() { // used in findResource() and findResources() + try { + String jarFileName = jarFileInfo.getJarFile().getName().replace("\\", "/"); + return new URL("jar:file:" + jarFileName + "!/" + jarEntry); + } catch (MalformedURLException e) { + return null; + } + } + + public String getName() { // used in createTempFile() and loadJar() + return jarEntry.getName().replace('/', '_'); + } + + /** + * Read JAR entry and return byte array of this JAR entry. + */ + public byte[] getJarBytes() throws EeClassLoaderException { + DataInputStream dataInputStream = null; + byte[] bytes; + + try { + long jarEntrySize = jarEntry.getSize(); + if (jarEntrySize <= 0 || jarEntrySize >= Integer.MAX_VALUE) { + throw new EeClassLoaderException("Invalid size " + jarEntrySize + " for entry " + jarEntry); + } + + bytes = new byte[(int) jarEntrySize]; + + InputStream inputStream = jarFileInfo.getJarFile().getInputStream(jarEntry); + dataInputStream = new DataInputStream(inputStream); + dataInputStream.readFully(bytes); + } catch (IOException e) { + throw new EeClassLoaderException(null, e); + } finally { + if (dataInputStream != null) { + try { + dataInputStream.close(); + } catch (IOException e) { + // Ignore + } + } + } + + return bytes; + } + + @Override + public String toString() { + return "JAR: " + jarFileInfo.getJarFile().getName() + " ENTRY: " + jarEntry; + } +} diff --git a/tools/loader/src/main/java/com/kumuluz/ee/loader/jar/JarFileInfo.java b/tools/loader/src/main/java/com/kumuluz/ee/loader/jar/JarFileInfo.java new file mode 100644 index 00000000..87649ce1 --- /dev/null +++ b/tools/loader/src/main/java/com/kumuluz/ee/loader/jar/JarFileInfo.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.loader.jar; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.ProtectionDomain; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +/** + * Class that holds JAR file information. + * + * @author Benjamin Kastelic + * @since 2.4.0 + */ +public class JarFileInfo { + + private JarFile jarFile; // this is the essence of JarFileInfo wrapper + private String simpleName; // accumulated for logging like: "topJar!childJar!kidJar" + private File fileDeleteOnExit; + private Manifest manifest; // required for package creation + private ProtectionDomain protectionDomain; + + /** + * @param jarFile + * Never null. + * @param simpleName + * Used for logging. Never null. + * @param jarFileParent + * Used to make simpleName for logging. Null for top level JAR. + * @param fileDeleteOnExit + * Used only to delete temporary file on exit. + * Could be null if not required to delete on exit (top level JAR) + */ + public JarFileInfo(JarFile jarFile, String simpleName, JarFileInfo jarFileParent, ProtectionDomain protectionDomain, File fileDeleteOnExit) { + this.simpleName = (jarFileParent == null ? "" : jarFileParent.simpleName + "!") + simpleName; + this.jarFile = jarFile; + this.protectionDomain = protectionDomain; + this.fileDeleteOnExit = fileDeleteOnExit; + try { + this.manifest = jarFile.getManifest(); // 'null' if META-INF directory is missing + } catch (IOException e) { + // Ignore and create blank manifest + } + if (this.manifest == null) { + this.manifest = new Manifest(); + } + } + + public String getSpecificationTitle() { + return manifest.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE); + } + + public String getSpecificationVersion() { + return manifest.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_VERSION); + } + + public String getSpecificationVendor() { + return manifest.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_VENDOR); + } + + public String getImplementationTitle() { + return manifest.getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_TITLE); + } + + public String getImplementationVersion() { + return manifest.getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION); + } + + public String getImplementationVendor() { + return manifest.getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VENDOR); + } + + public URL getSealURL() { + String seal = manifest.getMainAttributes().getValue(Attributes.Name.SEALED); + if (seal != null) { + try { + return new URL(seal); + } catch (MalformedURLException e) { + // Ignore + } + } + return null; + } + + public JarFile getJarFile() { + return jarFile; + } + + public void setJarFile(JarFile jarFile) { + this.jarFile = jarFile; + } + + public String getSimpleName() { + return simpleName; + } + + public void setSimpleName(String simpleName) { + this.simpleName = simpleName; + } + + public File getFileDeleteOnExit() { + return fileDeleteOnExit; + } + + public void setFileDeleteOnExit(File fileDeleteOnExit) { + this.fileDeleteOnExit = fileDeleteOnExit; + } + + public Manifest getManifest() { + return manifest; + } + + public void setManifest(Manifest manifest) { + this.manifest = manifest; + } + + public ProtectionDomain getProtectionDomain() { + return protectionDomain; + } + + public void setProtectionDomain(ProtectionDomain protectionDomain) { + this.protectionDomain = protectionDomain; + } +} diff --git a/tools/maven-plugin/README.md b/tools/maven-plugin/README.md new file mode 100644 index 00000000..5240301d --- /dev/null +++ b/tools/maven-plugin/README.md @@ -0,0 +1,47 @@ +# KumuluzEE Maven Plugin + +> KumuluzEE Maven Plugin for the Kumuluz EE microservice framework + +TODO - description + +## Usage + +Include the plugin in your project: + +```xml + + com.kumuluz.ee + kumuluzee-maven-plugin + 2.4.0-SNAPSHOT + +``` + +### Goals + +* __kumuluzee:copy-dependencies__ + + Copy dependencies and prepare for execution in an exploded class and dependency runtime. + + +* __kumuluzee:repackage__ + + Repackages existing JAR archives so that they can be executed from the command line using `java -jar`. + + ###### Parameters + + * __finalName__ + + Final name of the generated "uber" JAR. + + __Default value is__: `${project.build.finalName}` or `${project.artifactId}-${project.version}` + + * __outputDirectory__ + + Directory containing the generated JAR. + + __Default value is__: `${project.build.directory}` + +* __kumuluzee:run__ + + Run the application in an exploded class and dependency runtime. + \ No newline at end of file diff --git a/tools/maven-plugin/pom.xml b/tools/maven-plugin/pom.xml new file mode 100644 index 00000000..86f6d1ea --- /dev/null +++ b/tools/maven-plugin/pom.xml @@ -0,0 +1,112 @@ + + + + kumuluzee-tools + com.kumuluz.ee + 2.5.0-SNAPSHOT + + 4.0.0 + maven-plugin + + KumuluzEE Maven Plugin + KumuluzEE maven plugin for building single uber jars + + kumuluzee-maven-plugin + + + false + + + + + com.kumuluz.ee + kumuluzee-loader + provided + + + + org.apache.maven + maven-plugin-api + ${maven.plugin.api.version} + provided + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${maven-plugin-annotations.version} + provided + + + + org.twdata.maven + mojo-executor + ${mojo-executor.version} + + + + + + + ${project.build.directory}/generated-resources/loader + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-dependency-plugin + ${maven-dependency-plugin.version} + + + include-loader + generate-resources + + copy + + + ${kumuluzee.plugin.test.skip} + + + com.kumuluz.ee + kumuluzee-loader + ${project.version} + kumuluzee-loader.jar + + + ${project.build.directory}/generated-resources/loader/META-INF/loader + + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + ${maven-plugin-plugin.version} + + true + + + + mojo-descriptor + + descriptor + + + + help-goal + + helpmojo + + + + + + + \ No newline at end of file diff --git a/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/AbstractCopyDependenciesMojo.java b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/AbstractCopyDependenciesMojo.java new file mode 100644 index 00000000..fe9819c5 --- /dev/null +++ b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/AbstractCopyDependenciesMojo.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.maven.plugin; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.BuildPluginManager; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.twdata.maven.mojoexecutor.MojoExecutor.*; + +/** + * @author Benjamin Kastelic + * @since 2.4.0 + */ +public abstract class AbstractCopyDependenciesMojo extends AbstractMojo { + + @Parameter(defaultValue = "${project}", readonly = true, required = true) + protected MavenProject project; + + @Parameter(defaultValue = "${session}", readonly = true, required = true) + protected MavenSession session; + + @Parameter + private String webappDir; + + @Component + protected BuildPluginManager buildPluginManager; + + private String outputDirectory; + private String baseDirectory; + + protected void copyDependencies() + throws MojoExecutionException { + + copyDependencies(null); + } + + /** + * Copies dependencies to /target/dependency or to target/{outputSubdirectory} if the outputSubdirectory parameter is + * provided + */ + protected void copyDependencies(String outputSubdirectory) + throws MojoExecutionException { + + outputDirectory = project.getBuild().getDirectory(); + baseDirectory = project.getBasedir().getAbsolutePath(); + + String outputDirectory = outputSubdirectory == null + ? this.outputDirectory + "/dependency" + : this.outputDirectory + "/" + outputSubdirectory; + + executeMojo( + plugin( + groupId("org.apache.maven.plugins"), + artifactId("maven-dependency-plugin"), + version(MojoConstants.MAVEN_DEPENDENCY_PLUGIN_VERSION) + ), + goal("copy-dependencies"), + configuration( + element("includeScope", "runtime"), + element("overWriteSnapshots", "true"), + element("excludeArtifactIds", "kumuluzee-loader"), + element("outputDirectory", outputDirectory) + ), + executionEnvironment(project, session, buildPluginManager) + ); + + copyOrCreateWebapp(); + } + + private void copyOrCreateWebapp() throws MojoExecutionException { + + boolean webappExists = false; + + // search for target/classes/webapp + Path outputWebApp = Paths.get(outputDirectory, "classes/webapp"); + + if (Files.isDirectory(outputWebApp)) { + + webappExists = true; + } + + // search for src/main/webapp + if (!webappExists) { + + Path sourceWebApp = webappDir == null ? + Paths.get(baseDirectory, "src", "main", "webapp") : + Paths.get(baseDirectory, webappDir); + + getLog().info(sourceWebApp.toAbsolutePath().toString()); + + if (Files.isDirectory(sourceWebApp)) { + + String sourceWebAppDir = webappDir == null ? "src/main/webapp" : webappDir; + + executeMojo( + plugin( + groupId("org.apache.maven.plugins"), + artifactId("maven-resources-plugin"), + version(MojoConstants.MAVEN_RESOURCE_PLUGIN_VERSION) + ), + goal("copy-resources"), + configuration( + element(name("outputDirectory"), "${basedir}/target/classes/webapp"), + element(name("resources"), + element(name("resource"), + element(name("directory"), sourceWebAppDir), + element(name("filtering"), "true") + )) + ), + executionEnvironment(project, session, buildPluginManager) + ); + + // check if webapp resources were successfully copied + if (Files.isDirectory(outputWebApp)) { + + webappExists = true; + } + } + } + + if (!webappExists) { + + try { + + Files.createDirectories(outputWebApp); + + } catch (IOException e) { + + throw new MojoExecutionException("Could not create the necessary `webapp` directory. Please check the target folder permissions.", e); + } + } + } +} diff --git a/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/AbstractPackageMojo.java b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/AbstractPackageMojo.java new file mode 100644 index 00000000..4614f980 --- /dev/null +++ b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/AbstractPackageMojo.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.maven.plugin; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.nio.file.*; +import java.security.CodeSource; +import java.security.ProtectionDomain; +import java.util.List; +import java.util.jar.JarFile; + +import static org.twdata.maven.mojoexecutor.MojoExecutor.*; + +/** + * @author Benjamin Kastelic + * @since 2.4.0 + */ +public abstract class AbstractPackageMojo extends AbstractCopyDependenciesMojo { + + private static final String LOADER_JAR = "META-INF/loader/kumuluzee-loader.jar"; + private static final String TEMP_DIR_NAME_PREFIX = "kumuluzee-loader"; + private static final String CLASS_SUFFIX = ".class"; + + @Parameter(defaultValue = "com.kumuluz.ee.EeApplication") + private String mainClass; + + private String buildDirectory; + private String outputDirectory; + private String finalName; + + protected void repackage() + throws MojoExecutionException { + + buildDirectory = project.getBuild().getDirectory(); + outputDirectory = project.getBuild().getOutputDirectory(); + finalName = project.getBuild().getFinalName(); + + copyDependencies("classes/lib"); + unpackDependencies(); + packageJar(); + renameJars(); + } + + private void unpackDependencies() throws MojoExecutionException { + + getLog().info("Unpacking kumuluzee-loader dependency."); + + try { + + // get plugin JAR + URI pluginJarURI = getPluginJarPath(); + + Path pluginJarFile = Paths.get(pluginJarURI); + + FileSystem pluginJarFs = FileSystems.newFileSystem(pluginJarFile, null); + + Path loaderJarFile = pluginJarFs.getPath(LOADER_JAR); + Path tmpJar = Files.createTempFile(TEMP_DIR_NAME_PREFIX, ".tmp"); + + Files.copy(loaderJarFile, tmpJar, StandardCopyOption.REPLACE_EXISTING); + + JarFile loaderJar = new JarFile(tmpJar.toFile()); + + loaderJar.stream().parallel() + .filter(loaderJarEntry -> loaderJarEntry.getName().toLowerCase().endsWith(CLASS_SUFFIX)) + .forEach(loaderJarEntry -> { + try { + + Path outputPath = Paths.get(outputDirectory, loaderJarEntry.getName()); + + Path outputPathParent = outputPath.getParent(); + + if (outputPathParent != null) { + + Files.createDirectories(outputPathParent); + } + + InputStream inputStream = loaderJar.getInputStream(loaderJarEntry); + + Files.copy(inputStream, outputPath, StandardCopyOption.REPLACE_EXISTING); + + inputStream.close(); + } catch (IOException ignored) { + } + }); + + loaderJar.close(); + + Files.delete(tmpJar); + + // Create the boot loader config file + Path loaderConf = Paths.get(outputDirectory, "META-INF", "kumuluzee", "boot-loader.properties"); + + Path loaderConfParent = loaderConf.getParent(); + + if (!Files.exists(loaderConfParent)) { + + Files.createDirectories(loaderConfParent); + } + + String loaderConfContent = "main-class=" + mainClass; + + Files.write(loaderConf, loaderConfContent.getBytes(StandardCharsets.UTF_8)); + + } catch (IOException e) { + throw new MojoExecutionException("Failed to unpack kumuluzee-loader dependency: " + e.getMessage() + "."); + } + } + + private URI getPluginJarPath() throws MojoExecutionException { + + try { + + ProtectionDomain protectionDomain = RepackageMojo.class.getProtectionDomain(); + CodeSource codeSource = protectionDomain.getCodeSource(); + + if (codeSource == null) { + + throw new MojoExecutionException("Failed to retrieve plugin JAR file path. Unobtainable Code Source."); + } + + return codeSource.getLocation().toURI(); + } catch (URISyntaxException e) { + throw new MojoExecutionException("Failed to retrieve plugin JAR file path.", e); + } + } + + private void packageJar() throws MojoExecutionException { + + executeMojo( + plugin( + groupId("org.apache.maven.plugins"), + artifactId("maven-jar-plugin"), + version(MojoConstants.MAVEN_JAR_PLUGIN_VERSION) + ), + goal("jar"), + configuration( + element("finalName", finalName), + element("outputDirectory", buildDirectory), + element("classifier", "uber"), + element("forceCreation", "true"), + element("archive", + element("manifest", + element("mainClass", "com.kumuluz.ee.loader.EeBootLoader") + ) + ) + ), + executionEnvironment(project, session, buildPluginManager) + ); + } + + private void renameJars() throws MojoExecutionException { + + try { + + Path sourcePath1 = Paths.get(buildDirectory, finalName + ".jar"); + + getLog().info("Repackaging jar: " + sourcePath1.toAbsolutePath()); + + if (Files.exists(sourcePath1)) { + + Files.move( + sourcePath1, + sourcePath1.resolveSibling(finalName + ".jar.original"), + StandardCopyOption.REPLACE_EXISTING + ); + } + + Path sourcePath2 = Paths.get(buildDirectory, finalName + "-uber.jar"); + + if (Files.exists(sourcePath2)) { + + Files.move( + sourcePath2, + sourcePath2.resolveSibling(finalName + ".jar"), + StandardCopyOption.REPLACE_EXISTING + ); + } + + List artifacts = project.getAttachedArtifacts(); + for (Artifact artifact : project.getAttachedArtifacts()) { + if (artifact.hasClassifier() && artifact.getClassifier().equals("uber")) { + artifacts.remove(artifact); + break; + } + } + } catch (IOException e) { + throw new MojoExecutionException("Unable to rename the final build artifact."); + } + } +} diff --git a/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/CopyDependenciesMojo.java b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/CopyDependenciesMojo.java new file mode 100644 index 00000000..e932fa40 --- /dev/null +++ b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/CopyDependenciesMojo.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.maven.plugin; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.BuildPluginManager; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.*; +import org.apache.maven.project.MavenProject; + +/** + * Copy dependencies and prepare for execution in an exploded class and dependency runtime. + * + * @author Benjamin Kastelic + * @since 2.4.0 + */ +@Mojo( + name = "copy-dependencies", + defaultPhase = LifecyclePhase.PACKAGE, + requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, + requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME +) +public class CopyDependenciesMojo extends AbstractCopyDependenciesMojo { + + @Override + public void execute() throws MojoExecutionException { + copyDependencies(); + } +} diff --git a/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/MojoConstants.java b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/MojoConstants.java new file mode 100644 index 00000000..a766f777 --- /dev/null +++ b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/MojoConstants.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.maven.plugin; + +import java.util.ResourceBundle; + +/** + * @author Tilen Faganel + * @since 2.4.0 + */ +public class MojoConstants { + + public static final String MAVEN_JAR_PLUGIN_VERSION = ResourceBundle.getBundle("META-INF/kumuluzee/plugin-versions").getString("maven-jar-plugin.version"); + public static final String MAVEN_RESOURCE_PLUGIN_VERSION = ResourceBundle.getBundle("META-INF/kumuluzee/plugin-versions").getString("maven-resources-plugin.version"); + public static final String MAVEN_DEPENDENCY_PLUGIN_VERSION = ResourceBundle.getBundle("META-INF/kumuluzee/plugin-versions").getString("maven-dependency-plugin.version"); +} diff --git a/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/RepackageMojo.java b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/RepackageMojo.java new file mode 100644 index 00000000..43bfae25 --- /dev/null +++ b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/RepackageMojo.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.maven.plugin; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.BuildPluginManager; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.*; +import org.apache.maven.project.MavenProject; +import org.sonatype.aether.RepositorySystemSession; + +/** + * Repackages existing JAR archives so that they can be executed from the command line using {@literal java -jar}. + * + * @author Benjamin Kastelic + * @since 2.4.0 + */ +@Mojo( + name = "repackage", + defaultPhase = LifecyclePhase.PACKAGE, + threadSafe = true, + requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, + requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME +) +public class RepackageMojo extends AbstractPackageMojo { + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + + repackage(); + } +} diff --git a/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/RunExplodedMojo.java b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/RunExplodedMojo.java new file mode 100644 index 00000000..1e7c7b96 --- /dev/null +++ b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/RunExplodedMojo.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.maven.plugin; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.BuildPluginManager; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.*; +import org.apache.maven.project.MavenProject; + +import java.io.File; + +import static org.twdata.maven.mojoexecutor.MojoExecutor.*; + +/** + * Run the application in an exploded class and dependency runtime. + * + * @author Benjamin Kastelic + * @since 2.4.0 + */ +@Mojo( + name = "run", + defaultPhase = LifecyclePhase.PACKAGE, + requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, + requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME +) +public class RunExplodedMojo extends AbstractCopyDependenciesMojo { + + @Override + public void execute() throws MojoExecutionException { + + final String CLASSPATH_FORMAT = "target%1$sclasses%2$starget%1$sdependency%1$s*"; + + copyDependencies(); + + executeMojo( + plugin( + groupId("org.codehaus.mojo"), + artifactId("exec-maven-plugin"), + version("1.6.0") + ), + goal("java"), + configuration( + element(name("mainClass"), "com.kumuluz.ee.EeApplication"), + element(name("arguments"), + element(name("argument"), "-classpath"), + element(name("argument"), String.format(CLASSPATH_FORMAT, File.separator, File.pathSeparator))) + ), + executionEnvironment(project, session, buildPluginManager) + ); + } +} diff --git a/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/RunJarMojo.java b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/RunJarMojo.java new file mode 100644 index 00000000..ae3cf30e --- /dev/null +++ b/tools/maven-plugin/src/main/java/com/kumuluz/ee/maven/plugin/RunJarMojo.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014-2017 Kumuluz and/or its affiliates + * and other contributors as indicated by the @author tags and + * the contributor list. + * + * Licensed under the MIT License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/MIT + * + * 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. See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.kumuluz.ee.maven.plugin; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.BuildPluginManager; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; + +import static org.twdata.maven.mojoexecutor.MojoExecutor.*; + +/** + * Run the application in an executable JAR archive runtime. + * + * @author Benjamin Kastelic + * @since 2.4.0 + */ +//@Mojo( +// name = "run-jar", +// defaultPhase = LifecyclePhase.PACKAGE, +// requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, +// requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME +//) +public class RunJarMojo extends AbstractPackageMojo { + + @Parameter(defaultValue = "${project.build.directory}") + private String outputDirectory; + + @Parameter(defaultValue = "${project.build.finalName}") + private String finalName; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + + repackage(); + + executeMojo( + plugin( + groupId("org.codehaus.mojo"), + artifactId("exec-maven-plugin"), + version("1.6.0") + ), + goal("exec"), + configuration( + element("executable", "java"), + element(name("arguments"), + element(name("argument"), "-jar"), + element(name("argument"), outputDirectory + "/" + finalName + ".jar") + ) + ), + executionEnvironment(project, session, buildPluginManager) + ); + } +} diff --git a/tools/maven-plugin/src/main/resources/META-INF/kumuluzee/plugin-versions.properties b/tools/maven-plugin/src/main/resources/META-INF/kumuluzee/plugin-versions.properties new file mode 100644 index 00000000..6977a019 --- /dev/null +++ b/tools/maven-plugin/src/main/resources/META-INF/kumuluzee/plugin-versions.properties @@ -0,0 +1,3 @@ +maven-jar-plugin.version=${maven-jar-plugin.version} +maven-resources-plugin.version=${maven-resources-plugin.version} +maven-dependency-plugin.version=${maven-dependency-plugin.version} \ No newline at end of file diff --git a/tools/pom.xml b/tools/pom.xml new file mode 100644 index 00000000..c1783c39 --- /dev/null +++ b/tools/pom.xml @@ -0,0 +1,21 @@ + + + + kumuluzee + com.kumuluz.ee + 2.5.0-SNAPSHOT + + 4.0.0 + pom + + KumuluzEE Tools + Various KumuluzEE tools + + loader + maven-plugin + + + kumuluzee-tools + \ No newline at end of file