├── .gitignore ├── LICENSE ├── NOTICE ├── README.adoc ├── impl ├── ci-suite.xml ├── debug-suite.xml ├── pom.xml ├── src │ ├── main │ │ ├── java │ │ │ └── org │ │ │ │ └── apache │ │ │ │ └── geronimo │ │ │ │ └── config │ │ │ │ ├── ConfigImpl.java │ │ │ │ ├── ConfigValueImpl.java │ │ │ │ ├── DefaultConfigBuilder.java │ │ │ │ ├── DefaultConfigProvider.java │ │ │ │ ├── cdi │ │ │ │ ├── AnyLiteral.java │ │ │ │ ├── ConfigBean.java │ │ │ │ ├── ConfigExtension.java │ │ │ │ ├── ConfigInjectionBean.java │ │ │ │ ├── ConfigInjectionPoint.java │ │ │ │ ├── ConfigurationHandler.java │ │ │ │ ├── DefaultLiteral.java │ │ │ │ ├── ProxyBean.java │ │ │ │ └── configsource │ │ │ │ │ └── Reloadable.java │ │ │ │ ├── configsource │ │ │ │ ├── BaseConfigSource.java │ │ │ │ ├── PropertyFileConfigSource.java │ │ │ │ ├── PropertyFileConfigSourceProvider.java │ │ │ │ ├── SystemEnvConfigSource.java │ │ │ │ └── SystemPropertyConfigSource.java │ │ │ │ └── converters │ │ │ │ ├── BooleanConverter.java │ │ │ │ ├── ByteConverter.java │ │ │ │ ├── CharacterConverter.java │ │ │ │ ├── ClassConverter.java │ │ │ │ ├── DoubleConverter.java │ │ │ │ ├── DurationConverter.java │ │ │ │ ├── FloatConverter.java │ │ │ │ ├── ImplicitConverter.java │ │ │ │ ├── IntegerConverter.java │ │ │ │ ├── LongConverter.java │ │ │ │ ├── ShortConverter.java │ │ │ │ ├── StringConverter.java │ │ │ │ └── URLConverter.java │ │ └── resources │ │ │ └── META-INF │ │ │ ├── beans.xml │ │ │ └── services │ │ │ ├── javax.enterprise.inject.spi.Extension │ │ │ └── org.eclipse.microprofile.config.spi.ConfigProviderResolver │ └── test │ │ ├── java │ │ └── org │ │ │ └── apache │ │ │ └── geronimo │ │ │ └── config │ │ │ └── test │ │ │ ├── GeronimoConfigArchiveProcessor.java │ │ │ ├── GeronimoConfigExtension.java │ │ │ ├── internal │ │ │ ├── ArrayTypeTest.java │ │ │ ├── ConfigInjectionTest.java │ │ │ ├── DefaultNullValueTest.java │ │ │ ├── PropertyFileConfigSourceTest.java │ │ │ ├── ProviderTest.java │ │ │ ├── ProxyTest.java │ │ │ ├── SupplierTest.java │ │ │ ├── SystemEnvConfigSourceTest.java │ │ │ └── SystemPropertyConfigSourceTest.java │ │ │ └── testng │ │ │ └── SystemPropertiesLeakProtector.java │ │ └── resources │ │ └── META-INF │ │ └── services │ │ └── org.jboss.arquillian.core.spi.LoadableExtension └── tck-suite.xml └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | *.iml 3 | .idea 4 | .classpath 5 | .project 6 | .settings 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2009-2018 The Apache Software Foundation 2 | 3 | This product includes software developed at 4 | The Apache Software Foundation (http://www.apache.org/). 5 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | // 2 | // Licensed to the Apache Software Foundation (ASF) under one or more 3 | // contributor license agreements. See the NOTICE file distributed with 4 | // this work for additional information regarding copyright ownership. 5 | // The ASF licenses this file to You under the Apache License, Version 2.0 6 | // (the "License"); you may not use this file except in compliance with 7 | // the License. You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | 18 | # Configuration for Java SE and EE 19 | 20 | ## Status 21 | 22 | Implementation of the MicroProfile Config Specification. 23 | 24 | == Rationale 25 | 26 | Many project artifacts (e.g. WAR, EAR) should only be created once and then get installed at different customers, stages, etc 27 | They need to target those different execution environments without necessity of any repackaging. 28 | In other words: depending on the situation they need different configuration. 29 | 30 | This is easily achievable by having a set of default configuration values inside the project artifact. 31 | But be able to overwrite those default values from external. 32 | 33 | == History 34 | 35 | This very configuration approach has it's roots in the Apache OpenWebBeans internal SPI configuration. 36 | In 2010 it got moved over to the Apache MyFaces CODI project and enhanced to also fit the need of customer projects by Gerhard Petracek and Mark Struberg. 37 | In 2011 we further enhanced it while moving CODI to the Apache DeltaSpike project. 38 | Romain Manni-Bucau (Apache/Tomitribe), Ron Smeral (JBoss) and Anatole Tresch also gave appreciated input in the last years. 39 | 40 | == How it works 41 | 42 | A 'Configuration' consists of the information collected from the registered `ConfigSource` s. 43 | These `ConfigSource`s get sorted according to their _ordinal_. 44 | That way it is possible to overwrite configuration with lower importance from outside. 45 | 46 | By default there are 3 default ConfigSources: 47 | 48 | * `System.getenv()` (ordinal=400) 49 | * `System.getProperties()` (ordinal=300) 50 | * all `META-INF/microprofile-config.properties` files on the ClassPath. (ordinal=100, separately configurable via a config_ordinal property inside each file) 51 | 52 | That means that I can put my default configuration in a `META-INF/microprofile-config.properties` anywhere on the classpath. 53 | And I can later simply e.g set a system property to change this default configuration. 54 | 55 | == Custom ConfigSources 56 | 57 | It is possible to write and register custom `ConfigSource`s. 58 | An example would be a ConfigSource which gets the configured values from a shared database table in a cluster. 59 | 60 | == Building 61 | 62 | Against Apache OpenWebBeans 1.7.x: 63 | `$> mvn clean install` 64 | 65 | Against Apache OpenWebBeans 2.0.x: 66 | `$> mvn clean install -POWB2` 67 | 68 | Against JBoss Weld 3.0.x: 69 | `$> mvn clean install -PWeld3` 70 | 71 | == Adding to your project 72 | 73 | To add Geronimo Config to your project, just add the following dependency. 74 | 75 | [source,xml] 76 | ---- 77 | 78 | org.apache.geronimo.config 79 | geronimo-config-impl 80 | 1.0 81 | 82 | ---- 83 | 84 | 85 | == Config API 86 | 87 | Geronimo Config implements The MicroProfile Config API v1.1 and further information can be found at 88 | 89 | https://github.com/eclipse/microprofile-config/ 90 | 91 | The API is also available as Maven Artifact, which you could use if provided by your container 92 | 93 | [source,xml] 94 | ---- 95 | 96 | org.eclipse.microprofile.config 97 | microprofile-config-api 98 | 1.1 99 | provided 100 | 101 | ---- 102 | 103 | -------------------------------------------------------------------------------- /impl/ci-suite.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /impl/debug-suite.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /impl/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 4.0.0 22 | 23 | 24 | org.apache.geronimo.config 25 | geronimo-config 26 | 1.2.4-SNAPSHOT 27 | 28 | 29 | geronimo-config-impl 30 | Geronimo Microprofile Configuration :: Impl 31 | bundle 32 | 33 | 34 | 35 | 36 | org.jboss.arquillian 37 | arquillian-bom 38 | ${arquillian.version} 39 | pom 40 | import 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.eclipse.microprofile.config 49 | microprofile-config-api 50 | ${microprofile-config.version} 51 | 52 | 53 | 54 | org.eclipse.microprofile.config 55 | microprofile-config-tck 56 | ${microprofile-config.version} 57 | test 58 | 59 | 60 | org.testng 61 | testng 62 | 6.9.9 63 | test 64 | 65 | 66 | 67 | org.apache.geronimo.specs 68 | geronimo-annotation_1.3_spec 69 | 1.1 70 | provided 71 | 72 | 73 | org.apache.geronimo.specs 74 | geronimo-atinject_1.0_spec 75 | 1.1 76 | provided 77 | 78 | 79 | 80 | org.jboss.arquillian.testng 81 | arquillian-testng-container 82 | ${arquillian.version} 83 | test 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | org.apache.felix 94 | maven-bundle-plugin 95 | 4.2.1 96 | true 97 | 98 | 99 | 100 | <_contract>*;effective:='active' 101 | <_define-contract>="1.1" 112 | ]]> 113 | 114 | 115 | 116 | 117 | biz.aQute.bnd 118 | biz.aQute.bndlib 119 | ${bnd.version} 120 | 121 | 122 | 123 | 124 | org.apache.maven.plugins 125 | maven-surefire-plugin 126 | 3.0.0-M5 127 | 128 | 129 | ci-suite.xml 130 | 131 | 132 | value-for-tck-since-we-ignore-empty 133 | value-for-tck-since-we-ignore-empty 134 | value-for-tck-since-we-ignore-empty 135 | value-for-tck-since-we-ignore-empty 136 | value-for-tck-since-we-ignore-empty 137 | value-for-tck-since-we-ignore-empty 138 | value-for-tck-since-we-ignore-empty 139 | value-for-tck-since-we-ignore-empty 140 | 45 141 | true 142 | haha 143 | woohoo 144 | 145 | 146 | 1 147 | 2 148 | 3 149 | 4 150 | 151 | 152 | 153 | 154 | false 155 | pathConfigValue 156 | 157 | 1 158 | true 159 | false 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | OWB 168 | 169 | 170 | 171 | org.apache.geronimo.specs 172 | geronimo-jcdi_1.1_spec 173 | 1.0 174 | provided 175 | 176 | 177 | org.apache.geronimo.specs 178 | geronimo-interceptor_1.2_spec 179 | 1.0 180 | provided 181 | 182 | 183 | org.apache.geronimo.specs 184 | geronimo-el_2.2_spec 185 | 1.0.2 186 | provided 187 | 188 | 189 | 190 | org.apache.openwebbeans 191 | openwebbeans-spi 192 | ${owb.version} 193 | test 194 | 195 | 196 | org.apache.openwebbeans 197 | openwebbeans-impl 198 | ${owb.version} 199 | test 200 | 201 | 202 | org.apache.openwebbeans.arquillian 203 | owb-arquillian-standalone 204 | ${owb.version} 205 | test 206 | 207 | 208 | 209 | 210 | 211 | 212 | OWB2 213 | 214 | true 215 | 216 | 217 | 218 | org.apache.geronimo.specs 219 | geronimo-jcdi_2.0_spec 220 | 1.0 221 | provided 222 | 223 | 224 | org.apache.geronimo.specs 225 | geronimo-interceptor_1.2_spec 226 | 1.0 227 | provided 228 | 229 | 230 | org.apache.geronimo.specs 231 | geronimo-el_2.2_spec 232 | 1.0.2 233 | provided 234 | 235 | 236 | 237 | org.apache.openwebbeans 238 | openwebbeans-spi 239 | ${owb2.version} 240 | test 241 | 242 | 243 | org.apache.openwebbeans 244 | openwebbeans-impl 245 | ${owb2.version} 246 | test 247 | 248 | 249 | org.apache.openwebbeans.arquillian 250 | owb-arquillian-standalone 251 | ${owb2.version} 252 | test 253 | 254 | 255 | 256 | 257 | 258 | Weld3 259 | 260 | 261 | org.jboss.weld.se 262 | weld-se-shaded 263 | ${weld.version} 264 | test 265 | 266 | 267 | org.jboss.arquillian.container 268 | arquillian-weld-embedded 269 | ${arquillian-weld-embedded.version} 270 | test 271 | 272 | 273 | javax.enterprise 274 | cdi-api 275 | ${cdi2-api.version} 276 | 277 | 278 | 279 | 280 | 281 | 282 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config; 18 | 19 | import org.apache.geronimo.config.converters.ByteConverter; 20 | import org.apache.geronimo.config.converters.CharacterConverter; 21 | import org.apache.geronimo.config.converters.ClassConverter; 22 | import org.apache.geronimo.config.converters.DurationConverter; 23 | import org.apache.geronimo.config.converters.ShortConverter; 24 | import org.eclipse.microprofile.config.Config; 25 | import org.eclipse.microprofile.config.spi.ConfigSource; 26 | 27 | import javax.enterprise.inject.Typed; 28 | import javax.enterprise.inject.Vetoed; 29 | import java.lang.reflect.ParameterizedType; 30 | import java.lang.reflect.Type; 31 | import java.net.URL; 32 | import java.time.Duration; 33 | import java.util.ArrayList; 34 | import java.util.Collections; 35 | import java.util.HashMap; 36 | import java.util.List; 37 | import java.util.Map; 38 | import java.util.NoSuchElementException; 39 | import java.util.Optional; 40 | import java.util.Set; 41 | import java.util.concurrent.ConcurrentHashMap; 42 | import java.util.logging.Level; 43 | import java.util.logging.Logger; 44 | import java.util.stream.Collectors; 45 | 46 | import org.apache.geronimo.config.converters.BooleanConverter; 47 | import org.apache.geronimo.config.converters.DoubleConverter; 48 | import org.apache.geronimo.config.converters.FloatConverter; 49 | import org.apache.geronimo.config.converters.ImplicitConverter; 50 | import org.apache.geronimo.config.converters.IntegerConverter; 51 | import org.apache.geronimo.config.converters.LongConverter; 52 | import org.apache.geronimo.config.converters.StringConverter; 53 | import org.apache.geronimo.config.converters.URLConverter; 54 | import org.eclipse.microprofile.config.spi.Converter; 55 | 56 | 57 | import javax.annotation.Priority; 58 | 59 | /** 60 | * @author Mark Struberg 61 | * @author John D. Ament 62 | */ 63 | @Typed 64 | @Vetoed 65 | public class ConfigImpl implements Config, AutoCloseable { 66 | protected Logger logger = Logger.getLogger(ConfigImpl.class.getName()); 67 | 68 | protected List configSources = new ArrayList<>(); 69 | protected Map converters = new HashMap<>(); 70 | protected Map implicitConverters = new ConcurrentHashMap<>(); 71 | 72 | // volatile to a.) make the read/write behave atomic and b.) guarantee multi-thread safety 73 | private volatile long lastChanged = 0; 74 | 75 | 76 | public ConfigImpl() { 77 | registerDefaultConverter(); 78 | } 79 | 80 | private void registerDefaultConverter() { 81 | converters.put(String.class, StringConverter.INSTANCE); 82 | converters.put(Boolean.class, BooleanConverter.INSTANCE); 83 | converters.put(boolean.class, BooleanConverter.INSTANCE); 84 | converters.put(Double.class, DoubleConverter.INSTANCE); 85 | converters.put(double.class, DoubleConverter.INSTANCE); 86 | converters.put(Float.class, FloatConverter.INSTANCE); 87 | converters.put(float.class, FloatConverter.INSTANCE); 88 | converters.put(Integer.class, IntegerConverter.INSTANCE); 89 | converters.put(int.class, IntegerConverter.INSTANCE); 90 | converters.put(Long.class, LongConverter.INSTANCE); 91 | converters.put(long.class, LongConverter.INSTANCE); 92 | converters.put(Byte.class, ByteConverter.INSTANCE); 93 | converters.put(byte.class, ByteConverter.INSTANCE); 94 | converters.put(Short.class, ShortConverter.INSTANCE); 95 | converters.put(short.class, ShortConverter.INSTANCE); 96 | converters.put(Character.class, CharacterConverter.INSTANCE); 97 | converters.put(char.class, CharacterConverter.INSTANCE); 98 | 99 | converters.put(Class.class, ClassConverter.INSTANCE); 100 | converters.put(Duration.class, DurationConverter.INSTANCE); 101 | converters.put(URL.class, URLConverter.INSTANCE); 102 | } 103 | 104 | 105 | @Override 106 | public Optional getOptionalValue(String propertyName, Class asType) { 107 | String value = getValue(propertyName); 108 | if (value != null && value.length() == 0) { 109 | // treat an empty string as not existing 110 | value = null; 111 | } 112 | return Optional.ofNullable(convert(value, asType)); 113 | } 114 | 115 | @Override 116 | public T getValue(String propertyName, Class propertyType) { 117 | String value = getValue(propertyName); 118 | if (value == null) { 119 | throw new NoSuchElementException("No configured value found for config key " + propertyName); 120 | } 121 | 122 | return convert(value, propertyType); 123 | } 124 | 125 | public String getValue(String key) { 126 | for (ConfigSource configSource : configSources) { 127 | String value = configSource.getValue(key); 128 | 129 | if (value != null) { 130 | if (logger.isLoggable(Level.FINE)) { 131 | logger.log(Level.FINE, "found value {0} for key {1} in ConfigSource {2}.", 132 | new Object[]{value, key, configSource.getName()}); 133 | } 134 | 135 | return value; 136 | } 137 | } 138 | 139 | return null; 140 | } 141 | 142 | public T convert(String value, Class asType) { 143 | if (value != null) { 144 | Converter converter = getConverter(asType); 145 | return converter.convert(value); 146 | } 147 | 148 | return null; 149 | } 150 | 151 | private Converter getConverter(Class asType) { 152 | Converter converter = converters.get(asType); 153 | if (converter == null) { 154 | converter = getImplicitConverter(asType); 155 | } 156 | if (converter == null) { 157 | throw new IllegalArgumentException("No Converter registered for class " + asType); 158 | } 159 | return converter; 160 | } 161 | 162 | private Converter getImplicitConverter(Class asType) { 163 | Converter converter = implicitConverters.get(asType); 164 | if (converter == null) { 165 | synchronized (implicitConverters) { 166 | converter = implicitConverters.get(asType); 167 | if (converter == null) { 168 | if (asType.isArray()) { 169 | Converter singleItemConverter = getConverter(asType.getComponentType()); 170 | if (singleItemConverter == null) { 171 | return null; 172 | } 173 | else { 174 | converter = new ImplicitConverter.ImplicitArrayConverter(singleItemConverter, asType.getComponentType()); 175 | implicitConverters.putIfAbsent(asType, converter); 176 | } 177 | } 178 | else { 179 | // try to check whether the class is an 'implicit converter' 180 | converter = ImplicitConverter.getImplicitConverter(asType); 181 | if (converter != null) { 182 | implicitConverters.putIfAbsent(asType, converter); 183 | } 184 | } 185 | } 186 | } 187 | } 188 | return converter; 189 | } 190 | 191 | public ConfigValueImpl access(String key) { 192 | return new ConfigValueImpl<>(this, key); 193 | } 194 | 195 | @Override 196 | public Iterable getPropertyNames() { 197 | return configSources.stream().flatMap(c -> c.getPropertyNames().stream()).collect(Collectors.toSet()); 198 | } 199 | 200 | @Override 201 | public Iterable getConfigSources() { 202 | return Collections.unmodifiableList(configSources); 203 | } 204 | 205 | public synchronized void addConfigSources(List configSourcesToAdd) { 206 | List allConfigSources = new ArrayList<>(configSources); 207 | 208 | // TODO(To Be Fixed): configSourcesToAdd.forEach(cs -> cs.setOnAttributeChange(this::reportConfigChange)); 209 | allConfigSources.addAll(configSourcesToAdd); 210 | 211 | // finally put all the configSources back into the map 212 | configSources = sortDescending(allConfigSources); 213 | } 214 | 215 | 216 | public synchronized void addConverter(Converter converter) { 217 | if (converter == null) { 218 | return; 219 | } 220 | 221 | Type targetType = getTypeOfConverter(converter.getClass()); 222 | if (targetType == null ) { 223 | throw new IllegalStateException("Converter " + converter.getClass() + " must be a ParameterisedType"); 224 | } 225 | 226 | Converter oldConverter = converters.get(targetType); 227 | if (oldConverter == null || getPriority(converter) > getPriority(oldConverter)) { 228 | converters.put(targetType, converter); 229 | } 230 | } 231 | 232 | public void addPrioritisedConverter(DefaultConfigBuilder.PrioritisedConverter prioritisedConverter) { 233 | Converter oldConverter = converters.get(prioritisedConverter.getType()); 234 | if (oldConverter == null || prioritisedConverter.getPriority() >= getPriority(oldConverter)) { 235 | converters.put(prioritisedConverter.getType(), prioritisedConverter.getConverter()); 236 | } 237 | } 238 | 239 | 240 | private int getPriority(Converter converter) { 241 | int priority = 100; 242 | Priority priorityAnnotation = converter.getClass().getAnnotation(Priority.class); 243 | if (priorityAnnotation != null) { 244 | priority = priorityAnnotation.value(); 245 | } 246 | return priority; 247 | } 248 | 249 | 250 | public Map getConverters() { 251 | return converters; 252 | } 253 | 254 | 255 | @Override 256 | public void close() throws Exception { 257 | List exceptions = new ArrayList<>(); 258 | 259 | converters.values().stream() 260 | .filter(c -> c instanceof AutoCloseable) 261 | .map(AutoCloseable.class::cast) 262 | .forEach(c -> { 263 | try { 264 | c.close(); 265 | } 266 | catch (Exception e) { 267 | exceptions.add(e); 268 | } 269 | }); 270 | 271 | configSources.stream() 272 | .filter(c -> c instanceof AutoCloseable) 273 | .map(AutoCloseable.class::cast) 274 | .forEach(c -> { 275 | try { 276 | c.close(); 277 | } 278 | catch (Exception e) { 279 | exceptions.add(e); 280 | } 281 | }); 282 | 283 | if (!exceptions.isEmpty()) { 284 | StringBuilder sb = new StringBuilder(1024); 285 | sb.append("The following Exceptions got detected while shutting down the Config:\n"); 286 | for (Exception exception : exceptions) { 287 | sb.append(exception.getClass().getName()) 288 | .append(" ") 289 | .append(exception.getMessage()) 290 | .append('\n'); 291 | } 292 | 293 | throw new RuntimeException(sb.toString(), exceptions.get(0)); 294 | } 295 | } 296 | 297 | /** 298 | * ConfigSources are sorted with descending ordinal. 299 | * If 2 ConfigSources have the same ordinal, then they get sorted according to their name, alphabetically. 300 | */ 301 | private List sortDescending(List configSources) { 302 | configSources.sort( 303 | (configSource1, configSource2) -> { 304 | int compare = Integer.compare(configSource2.getOrdinal(), configSource1.getOrdinal()); 305 | if (compare == 0) { 306 | return configSource1.getName().compareTo(configSource2.getName()); 307 | } 308 | return compare; 309 | }); 310 | return configSources; 311 | } 312 | 313 | private Type getTypeOfConverter(Class clazz) { 314 | if (clazz.equals(Object.class)) { 315 | return null; 316 | } 317 | 318 | Type[] genericInterfaces = clazz.getGenericInterfaces(); 319 | for (Type genericInterface : genericInterfaces) { 320 | if (genericInterface instanceof ParameterizedType) { 321 | ParameterizedType pt = (ParameterizedType) genericInterface; 322 | if (pt.getRawType().equals(Converter.class)) { 323 | Type[] typeArguments = pt.getActualTypeArguments(); 324 | if (typeArguments.length != 1) { 325 | throw new IllegalStateException("Converter " + clazz + " must be a ParameterisedType"); 326 | } 327 | return typeArguments[0]; 328 | } 329 | } 330 | } 331 | 332 | return getTypeOfConverter(clazz.getSuperclass()); 333 | } 334 | 335 | public void onAttributeChange(Set attributesChanged) 336 | { 337 | // this is to force an incremented lastChanged even on time glitches and fast updates 338 | long newLastChanged = System.nanoTime(); 339 | lastChanged = lastChanged >= newLastChanged ? lastChanged++ : newLastChanged; 340 | } 341 | 342 | /** 343 | * @return the nanoTime when the last change got reported by a ConfigSource 344 | */ 345 | public long getLastChanged() 346 | { 347 | return lastChanged; 348 | } 349 | 350 | 351 | } 352 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/ConfigValueImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config; 18 | 19 | import org.eclipse.microprofile.config.spi.Converter; 20 | 21 | import java.util.ArrayList; 22 | import java.util.Collections; 23 | import java.util.HashSet; 24 | import java.util.List; 25 | import java.util.NoSuchElementException; 26 | import java.util.Optional; 27 | import java.util.Set; 28 | import java.util.concurrent.TimeUnit; 29 | import java.util.logging.Logger; 30 | 31 | import javax.enterprise.inject.Typed; 32 | 33 | /** 34 | * @author Mark Struberg 35 | */ 36 | @Typed 37 | public class ConfigValueImpl { 38 | private static final Logger logger = Logger.getLogger(ConfigValueImpl.class.getName()); 39 | 40 | private final ConfigImpl config; 41 | 42 | private String keyOriginal; 43 | 44 | private String keyResolved; 45 | 46 | private Class configEntryType = String.class; 47 | 48 | private String[] lookupChain; 49 | 50 | private boolean evaluateVariables = false; 51 | 52 | private long cacheTimeNs = -1; 53 | private volatile long reloadAfter = -1; 54 | private long lastReloadedAt = -1; 55 | 56 | private T lastValue = null; 57 | //X will later get added again private ConfigChanged valueChangeListener; 58 | private boolean isList; 59 | private boolean isSet; 60 | 61 | private T defaultValue; 62 | private boolean withDefault; 63 | 64 | /** 65 | * Alternative Converter to be used instead of the default converter 66 | */ 67 | private Converter converter; 68 | 69 | public ConfigValueImpl(ConfigImpl config, String key) { 70 | this.config = config; 71 | this.keyOriginal = key; 72 | } 73 | 74 | //X @Override 75 | public ConfigValueImpl as(Class clazz) { 76 | configEntryType = clazz; 77 | return (ConfigValueImpl) this; 78 | } 79 | 80 | //X @Override 81 | public ConfigValueImpl> asList() { 82 | isList = true; 83 | ConfigValueImpl> listTypedResolver = (ConfigValueImpl>) this; 84 | 85 | if (defaultValue == null) 86 | { 87 | // the default for lists is an empty list instead of null 88 | return listTypedResolver.withDefault(Collections.emptyList()); 89 | } 90 | 91 | return listTypedResolver; 92 | } 93 | 94 | //X @Override 95 | public ConfigValueImpl> asSet() { 96 | isSet = true; 97 | ConfigValueImpl> listTypedResolver = (ConfigValueImpl>) this; 98 | 99 | if (defaultValue == null) 100 | { 101 | // the default for lists is an empty list instead of null 102 | return listTypedResolver.withDefault(Collections.emptySet()); 103 | } 104 | 105 | return listTypedResolver; 106 | } 107 | 108 | //X @Override 109 | public ConfigValueImpl withDefault(T value) { 110 | defaultValue = value; 111 | withDefault = true; 112 | return this; 113 | } 114 | 115 | //X @Override 116 | public ConfigValueImpl withStringDefault(String value) { 117 | if (value == null || value.isEmpty()) { 118 | throw new RuntimeException("Empty String or null supplied as string-default value for property " 119 | + keyOriginal); 120 | } 121 | value = replaceVariables(value); 122 | 123 | if (isList) { 124 | defaultValue = splitAndConvertListValue(value); 125 | } 126 | else { 127 | defaultValue = convert(value); 128 | } 129 | withDefault = true; 130 | return this; 131 | } 132 | 133 | //X @Override 134 | public T getDefaultValue() { 135 | return defaultValue; 136 | } 137 | 138 | //X @Override 139 | public ConfigValueImpl useConverter(Converter converter) { 140 | this.converter = converter; 141 | return this; 142 | } 143 | 144 | //X @Override 145 | public ConfigValueImpl cacheFor(long value, TimeUnit timeUnit) { 146 | this.cacheTimeNs = timeUnit.toNanos(value); 147 | return this; 148 | } 149 | 150 | //X @Override 151 | public ConfigValueImpl evaluateVariables(boolean evaluateVariables) { 152 | this.evaluateVariables = evaluateVariables; 153 | return this; 154 | } 155 | 156 | public ConfigValueImpl withLookupChain(String... postfixNames) { 157 | this.lookupChain = postfixNames; 158 | return this; 159 | } 160 | 161 | //X @Override 162 | public Optional getOptionalValue() { 163 | return Optional.ofNullable(get()); 164 | } 165 | 166 | //X will later get added again @Override 167 | /*X 168 | public ConfigValueImpl onChange(ConfigChanged valueChangeListener) { 169 | this.valueChangeListener = valueChangeListener; 170 | return this; 171 | } 172 | */ 173 | 174 | //X @Override 175 | public List getValueList() { 176 | String rawList = (String) get(false); 177 | List values = new ArrayList(); 178 | StringBuilder sb = new StringBuilder(64); 179 | for (int i= 0; i < rawList.length(); i++) { 180 | char c = rawList.charAt(i); 181 | if ('\\' == c) { 182 | if (i == rawList.length()) { 183 | throw new IllegalStateException("incorrect escaping of key " + keyOriginal + " value: " + rawList); 184 | } 185 | char nextChar = rawList.charAt(i+1); 186 | if (nextChar == '\\') { 187 | sb.append('\\'); 188 | } 189 | else if (nextChar == ',') { 190 | sb.append(','); 191 | } 192 | i++; 193 | } 194 | else if (',' == c) { 195 | addListValue(values, sb); 196 | } 197 | else { 198 | sb.append(c); 199 | } 200 | } 201 | addListValue(values, sb); 202 | 203 | return values; 204 | } 205 | 206 | private void addListValue(List values, StringBuilder sb) { 207 | String val = sb.toString().trim(); 208 | if (!val.isEmpty()) { 209 | values.add(convert(val)); 210 | } 211 | sb.setLength(0); 212 | } 213 | 214 | public T get() { 215 | return get(true); 216 | } 217 | 218 | //X @Override 219 | public T getValue() { 220 | T val = get(); 221 | if (val == null) { 222 | throw new NoSuchElementException("No config value present for key " + keyOriginal); 223 | } 224 | return val; 225 | } 226 | 227 | //X @Override 228 | /*X will come with the next version 229 | public T getValue(ConfigSnapshot configSnapshot) { 230 | ConfigSnapshotImpl snapshotImpl = (ConfigSnapshotImpl) configSnapshot; 231 | 232 | if (!snapshotImpl.getConfigValues().containsKey(this)) 233 | { 234 | throw new IllegalArgumentException("The TypedResolver for key " + getPropertyName() + 235 | " does not belong the given ConfigSnapshot!"); 236 | } 237 | 238 | return (T) snapshotImpl.getConfigValues().get(this); 239 | } 240 | */ 241 | 242 | 243 | private T get(boolean convert) { 244 | long now = -1; 245 | if (cacheTimeNs > 0) 246 | { 247 | now = System.nanoTime(); 248 | if (now <= reloadAfter) 249 | { 250 | // now check if anything in the underlying Config got changed 251 | long lastCfgChange = config.getLastChanged(); 252 | if (lastCfgChange < lastReloadedAt) 253 | { 254 | return lastValue; 255 | } 256 | } 257 | } 258 | 259 | String valueStr = resolveStringValue(); 260 | 261 | if ((valueStr == null || valueStr.isEmpty()) && withDefault) { 262 | return defaultValue; 263 | } 264 | 265 | T value; 266 | if (isList || isSet) { 267 | value = splitAndConvertListValue(valueStr); 268 | if (isSet) { 269 | value = (T) new HashSet((List) value); 270 | } 271 | } 272 | else { 273 | value = convert ? convert(valueStr) : (T) valueStr; 274 | } 275 | 276 | //X will later get added again 277 | /*X 278 | if (valueChangeListener != null && (value != null && !value.equals(lastValue) || (value == null && lastValue != null)) ) 279 | { 280 | valueChangeListener.onValueChange(keyOriginal, lastValue, value); 281 | } 282 | */ 283 | 284 | lastValue = value; 285 | 286 | if (cacheTimeNs > 0) 287 | { 288 | reloadAfter = now + cacheTimeNs; 289 | lastReloadedAt = now; 290 | } 291 | 292 | return value; 293 | } 294 | 295 | private String resolveStringValue() { 296 | String value = null; 297 | 298 | if (lookupChain != null) { 299 | // first we resolve the value 300 | List postfixVals = new ArrayList<>(); 301 | for (String postfix : lookupChain) { 302 | if (postfix.startsWith("${") && postfix.length() > 3) { 303 | String varName = postfix.substring(2, postfix.length()-1); 304 | String varValue = config.getValue(varName); 305 | if (varValue != null && varValue.length() > 0) { 306 | postfixVals.add(varValue); 307 | } 308 | } 309 | else { 310 | postfixVals.add(postfix); 311 | } 312 | } 313 | 314 | // binary count down 315 | for (int mask = (1 << postfixVals.size()) - 1; mask > 0; mask--) { 316 | StringBuilder sb = new StringBuilder(keyOriginal); 317 | for (int loc = 0; loc < postfixVals.size(); loc++) { 318 | int bitPos = 1 << (postfixVals.size() - loc - 1); 319 | if ((mask & bitPos) > 0) { 320 | sb.append('.').append(postfixVals.get(loc)); 321 | } 322 | } 323 | 324 | value = config.getValue(sb.toString()); 325 | if (value != null && value.length() > 0) { 326 | keyResolved = sb.toString(); 327 | break; 328 | } 329 | } 330 | 331 | } 332 | 333 | if (value == null) { 334 | value = config.getValue(keyOriginal); 335 | this.keyResolved = keyOriginal; 336 | } 337 | 338 | if (evaluateVariables && value != null) 339 | { 340 | value = replaceVariables(value); 341 | 342 | } 343 | return value; 344 | } 345 | 346 | private String replaceVariables(String value) 347 | { 348 | // recursively resolve any ${varName} in the value 349 | int startVar = 0; 350 | while ((startVar = value.indexOf("${", startVar)) >= 0) 351 | { 352 | int endVar = value.indexOf("}", startVar); 353 | if (endVar <= 0) 354 | { 355 | break; 356 | } 357 | String varName = value.substring(startVar + 2, endVar); 358 | if (varName.isEmpty()) 359 | { 360 | break; 361 | } 362 | String variableValue = config.access(varName).evaluateVariables(true).get(); 363 | if (variableValue != null) 364 | { 365 | value = value.replace("${" + varName + "}", variableValue); 366 | } 367 | startVar++; 368 | } 369 | return value; 370 | } 371 | 372 | //X @Override 373 | public String getPropertyName() { 374 | return keyOriginal; 375 | } 376 | 377 | //X @Override 378 | public String getResolvedPropertyName() { 379 | return keyResolved; 380 | } 381 | 382 | private T convert(String value) { 383 | if (converter != null) { 384 | return converter.convert(value); 385 | } 386 | 387 | if (String.class == configEntryType) { 388 | return (T) value; 389 | } 390 | 391 | return (T) config.convert(value, configEntryType); 392 | } 393 | 394 | 395 | private T splitAndConvertListValue(String valueStr) { 396 | if (valueStr == null) { 397 | return null; 398 | } 399 | 400 | List list = new ArrayList(); 401 | StringBuilder currentValue = new StringBuilder(); 402 | int length = valueStr.length(); 403 | for (int i = 0; i < length; i++) { 404 | char c = valueStr.charAt(i); 405 | if (c == '\\') { 406 | if (i < length - 1) { 407 | char nextC = valueStr.charAt(i + 1); 408 | currentValue.append(nextC); 409 | i++; 410 | } 411 | } 412 | else if (c == ',') { 413 | String trimedVal = currentValue.toString().trim(); 414 | if (trimedVal.length() > 0) { 415 | list.add(convert(trimedVal)); 416 | } 417 | 418 | currentValue.setLength(0); 419 | } 420 | else { 421 | currentValue.append(c); 422 | } 423 | } 424 | 425 | String trimedVal = currentValue.toString().trim(); 426 | if (trimedVal.length() > 0) { 427 | list.add(convert(trimedVal)); 428 | } 429 | 430 | return (T) list; 431 | } 432 | 433 | } 434 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/DefaultConfigBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config; 18 | 19 | import org.eclipse.microprofile.config.Config; 20 | import org.eclipse.microprofile.config.spi.ConfigBuilder; 21 | import org.eclipse.microprofile.config.spi.ConfigSource; 22 | import org.eclipse.microprofile.config.spi.ConfigSourceProvider; 23 | import org.eclipse.microprofile.config.spi.Converter; 24 | import org.apache.geronimo.config.configsource.PropertyFileConfigSourceProvider; 25 | import org.apache.geronimo.config.configsource.SystemEnvConfigSource; 26 | import org.apache.geronimo.config.configsource.SystemPropertyConfigSource; 27 | 28 | import java.util.ArrayList; 29 | import java.util.Collection; 30 | import java.util.HashMap; 31 | import java.util.List; 32 | import java.util.Map; 33 | import java.util.ServiceLoader; 34 | import java.util.logging.Logger; 35 | import java.util.stream.Collectors; 36 | 37 | import javax.enterprise.inject.Typed; 38 | import javax.enterprise.inject.Vetoed; 39 | 40 | import static java.util.Arrays.asList; 41 | 42 | /** 43 | * @author Romain Manni-Bucau 44 | * @author Mark Struberg 45 | */ 46 | @Typed 47 | @Vetoed 48 | public class DefaultConfigBuilder implements ConfigBuilder { 49 | private ClassLoader forClassLoader; 50 | private final List sources = new ArrayList<>(); 51 | private final List> converters = new ArrayList<>(); 52 | private final Map, PrioritisedConverter> prioritisedConverters = new HashMap<>(); 53 | private boolean ignoreDefaultSources = true; 54 | private boolean ignoreDiscoveredSources = true; 55 | private boolean ignoreDiscoveredConverters = true; 56 | 57 | @Override 58 | public ConfigBuilder addDefaultSources() { 59 | this.ignoreDefaultSources = false; 60 | return this; 61 | } 62 | 63 | @Override 64 | public ConfigBuilder addDiscoveredSources() { 65 | this.ignoreDiscoveredSources = false; 66 | return this; 67 | } 68 | 69 | @Override 70 | public ConfigBuilder forClassLoader(final ClassLoader loader) { 71 | this.forClassLoader = loader; 72 | return this; 73 | } 74 | 75 | @Override 76 | public ConfigBuilder withSources(final ConfigSource... sources) { 77 | this.sources.addAll(asList(sources)); 78 | return this; 79 | } 80 | 81 | @Override 82 | public ConfigBuilder withConverters(Converter... converters) { 83 | this.converters.addAll(asList(converters)); 84 | return this; 85 | } 86 | 87 | @Override 88 | public ConfigBuilder withConverter(Class type, int priority, Converter converter) { 89 | PrioritisedConverter oldPrioritisedConverter = prioritisedConverters.get(type); 90 | if (oldPrioritisedConverter != null) { 91 | if (oldPrioritisedConverter.priority == priority) { 92 | throw new IllegalStateException("Found 2 converters with the same priority for type " + type 93 | + ". This will result in random behaviour -> aborting! Previous Converter: " 94 | + oldPrioritisedConverter.converter.getClass() + " 2nd Converter: " + converter.getClass()); 95 | } 96 | if (oldPrioritisedConverter.priority > priority) { 97 | return this; 98 | } 99 | } 100 | 101 | prioritisedConverters.put(type, new PrioritisedConverter(type, priority, converter)); 102 | 103 | return this; 104 | } 105 | 106 | @Override 107 | public ConfigBuilder addDiscoveredConverters() { 108 | ignoreDiscoveredConverters = false; 109 | return this; 110 | } 111 | 112 | @Override 113 | public Config build() { 114 | List configSources = new ArrayList<>(); 115 | if (forClassLoader == null) { 116 | forClassLoader = Thread.currentThread().getContextClassLoader(); 117 | if (forClassLoader == null) { 118 | forClassLoader = DefaultConfigProvider.class.getClassLoader(); 119 | } 120 | } 121 | 122 | if (!ignoreDefaultSources) { 123 | configSources.addAll(getBuiltInConfigSources(forClassLoader)); 124 | } 125 | configSources.addAll(sources); 126 | 127 | if (!ignoreDiscoveredSources) { 128 | // load all ConfigSource services 129 | ServiceLoader configSourceLoader = ServiceLoader.load(ConfigSource.class, forClassLoader); 130 | configSourceLoader.forEach(configSources::add); 131 | 132 | // load all ConfigSources from ConfigSourceProviders 133 | ServiceLoader configSourceProviderLoader = ServiceLoader.load(ConfigSourceProvider.class, forClassLoader); 134 | configSourceProviderLoader.forEach(configSourceProvider -> 135 | configSourceProvider.getConfigSources(forClassLoader) 136 | .forEach(configSources::add)); 137 | } 138 | 139 | if (!ignoreDiscoveredConverters) { 140 | ServiceLoader converterLoader = ServiceLoader.load(Converter.class, forClassLoader); 141 | converterLoader.forEach(converters::add); 142 | } 143 | 144 | ConfigImpl config = new ConfigImpl(); 145 | config.addConfigSources(configSources); 146 | 147 | for (Converter converter : converters) { 148 | config.addConverter(converter); 149 | } 150 | 151 | for (PrioritisedConverter prioritisedConverter : prioritisedConverters.values()) { 152 | config.addPrioritisedConverter(prioritisedConverter); 153 | } 154 | return config; 155 | } 156 | 157 | protected Collection getBuiltInConfigSources(ClassLoader forClassLoader) { 158 | List configSources = new ArrayList<>(); 159 | 160 | configSources.add(new SystemEnvConfigSource()); 161 | configSources.add(new SystemPropertyConfigSource()); 162 | configSources.addAll(new PropertyFileConfigSourceProvider("META-INF/microprofile-config.properties", true, forClassLoader).getConfigSources(forClassLoader)); 163 | 164 | return configSources; 165 | } 166 | 167 | static class PrioritisedConverter { 168 | private final Class clazz; 169 | private final int priority; 170 | private final Converter converter; 171 | 172 | public PrioritisedConverter(Class clazz, int priority, Converter converter) { 173 | this.clazz = clazz; 174 | this.priority = priority; 175 | this.converter = converter; 176 | } 177 | 178 | public Class getType() { 179 | return clazz; 180 | } 181 | 182 | public int getPriority() { 183 | return priority; 184 | } 185 | 186 | public Converter getConverter() { 187 | return converter; 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/DefaultConfigProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config; 18 | 19 | import java.lang.ref.WeakReference; 20 | import java.util.Collections; 21 | import java.util.Iterator; 22 | import java.util.Map; 23 | import java.util.WeakHashMap; 24 | 25 | import javax.enterprise.inject.Typed; 26 | import javax.enterprise.inject.Vetoed; 27 | 28 | import org.eclipse.microprofile.config.Config; 29 | import org.eclipse.microprofile.config.spi.ConfigBuilder; 30 | import org.eclipse.microprofile.config.spi.ConfigProviderResolver; 31 | 32 | 33 | /** 34 | * @author Mark Struberg 35 | */ 36 | @Typed 37 | @Vetoed 38 | public class DefaultConfigProvider extends ConfigProviderResolver { 39 | 40 | private static Map> configs 41 | = Collections.synchronizedMap(new WeakHashMap>()); 42 | 43 | 44 | @Override 45 | public Config getConfig() { 46 | return getConfig(Thread.currentThread().getContextClassLoader()); 47 | } 48 | 49 | 50 | @Override 51 | public Config getConfig(ClassLoader forClassLoader) { 52 | 53 | Config config = existingConfig(forClassLoader); 54 | if (config == null) { 55 | synchronized (DefaultConfigProvider.class) { 56 | config = existingConfig(forClassLoader); 57 | if (config == null) { 58 | config = getBuilder().forClassLoader(forClassLoader) 59 | .addDefaultSources() 60 | .addDiscoveredSources() 61 | .addDiscoveredConverters() 62 | .build(); 63 | registerConfig(config, forClassLoader); 64 | } 65 | } 66 | } 67 | return config; 68 | } 69 | 70 | Config existingConfig(ClassLoader forClassLoader) { 71 | WeakReference configRef = configs.get(forClassLoader); 72 | return configRef != null ? configRef.get() : null; 73 | } 74 | 75 | 76 | @Override 77 | public void registerConfig(Config config, ClassLoader forClassLoader) { 78 | synchronized (DefaultConfigProvider.class) { 79 | configs.put(forClassLoader, new WeakReference<>(config)); 80 | } 81 | } 82 | 83 | @Override 84 | public ConfigBuilder getBuilder() { 85 | return new DefaultConfigBuilder(); 86 | } 87 | 88 | 89 | @Override 90 | public void releaseConfig(Config config) { 91 | if (config == null) { 92 | // get the config from the current TCCL 93 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 94 | if (classLoader == null) { 95 | classLoader = DefaultConfigProvider.class.getClassLoader(); 96 | } 97 | config = existingConfig(classLoader); 98 | } 99 | 100 | if (config != null) { 101 | synchronized (DefaultConfigProvider.class) { 102 | Iterator>> it = configs.entrySet().iterator(); 103 | while (it.hasNext()) { 104 | Map.Entry> entry = it.next(); 105 | if (entry.getValue().get() != null && entry.getValue().get() == config) { 106 | it.remove(); 107 | break; 108 | } 109 | } 110 | 111 | if (config instanceof AutoCloseable) { 112 | try { 113 | ((AutoCloseable) config).close(); 114 | } 115 | catch (Exception e) { 116 | throw new RuntimeException("Error while closing Config", e); 117 | } 118 | } 119 | } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/cdi/AnyLiteral.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package org.apache.geronimo.config.cdi; 21 | 22 | import javax.enterprise.inject.Any; 23 | import javax.enterprise.util.AnnotationLiteral; 24 | 25 | class AnyLiteral extends AnnotationLiteral implements Any { 26 | public static Any INSTANCE = new AnyLiteral(); 27 | 28 | @Override 29 | public boolean equals(Object other) 30 | { 31 | return other instanceof Any; 32 | } 33 | 34 | @Override 35 | public int hashCode() 36 | { 37 | return 0; 38 | } 39 | 40 | @Override 41 | public String toString() 42 | { 43 | return "@Any"; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/cdi/ConfigBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.cdi; 18 | 19 | import static java.util.Arrays.asList; 20 | import static java.util.Collections.emptySet; 21 | 22 | import java.io.Serializable; 23 | import java.lang.annotation.Annotation; 24 | import java.lang.reflect.Type; 25 | import java.util.HashSet; 26 | import java.util.Set; 27 | 28 | import javax.enterprise.context.ApplicationScoped; 29 | import javax.enterprise.context.spi.CreationalContext; 30 | import javax.enterprise.inject.spi.Bean; 31 | import javax.enterprise.inject.spi.InjectionPoint; 32 | import javax.enterprise.inject.spi.PassivationCapable; 33 | 34 | import org.eclipse.microprofile.config.Config; 35 | 36 | public class ConfigBean implements Bean, PassivationCapable { 37 | private final Set types; 38 | private final Set qualifiers; 39 | private final String id; 40 | private Config config; 41 | 42 | ConfigBean() { 43 | this.qualifiers = new HashSet<>(asList(DefaultLiteral.INSTANCE, AnyLiteral.INSTANCE)); 44 | this.types = new HashSet<>(asList(Config.class, Serializable.class)); 45 | this.id = ConfigBean.class.getName() + "[" + Config.class.getName() + "]"; 46 | } 47 | 48 | void init(final Config config) { 49 | this.config = config; 50 | } 51 | 52 | @Override 53 | public Set getInjectionPoints() { 54 | return emptySet(); 55 | } 56 | 57 | @Override 58 | public Class getBeanClass() { 59 | return Config.class; 60 | } 61 | 62 | @Override 63 | public boolean isNullable() { 64 | return false; 65 | } 66 | 67 | @Override 68 | public Config create(final CreationalContext context) { 69 | return config; 70 | } 71 | 72 | @Override 73 | public void destroy(final Config instance, final CreationalContext context) { 74 | // no-op 75 | } 76 | 77 | @Override 78 | public Set getTypes() { 79 | return types; 80 | } 81 | 82 | @Override 83 | public Set getQualifiers() { 84 | return qualifiers; 85 | } 86 | 87 | @Override 88 | public Class getScope() { 89 | return ApplicationScoped.class; 90 | } 91 | 92 | @Override 93 | public String getName() { 94 | return null; 95 | } 96 | 97 | @Override 98 | public Set> getStereotypes() { 99 | return emptySet(); 100 | } 101 | 102 | @Override 103 | public boolean isAlternative() { 104 | return false; 105 | } 106 | 107 | @Override 108 | public String getId() { 109 | return id; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.cdi; 18 | 19 | import static java.util.stream.Collectors.toList; 20 | 21 | import org.apache.geronimo.config.ConfigImpl; 22 | import org.apache.geronimo.config.DefaultConfigBuilder; 23 | import org.apache.geronimo.config.cdi.configsource.Reloadable; 24 | import org.eclipse.microprofile.config.Config; 25 | import org.eclipse.microprofile.config.ConfigProvider; 26 | import org.eclipse.microprofile.config.inject.ConfigProperty; 27 | import org.eclipse.microprofile.config.spi.ConfigProviderResolver; 28 | 29 | import javax.enterprise.event.Observes; 30 | import javax.enterprise.inject.spi.AfterBeanDiscovery; 31 | import javax.enterprise.inject.spi.AfterDeploymentValidation; 32 | import javax.enterprise.inject.spi.BeanManager; 33 | import javax.enterprise.inject.spi.BeforeShutdown; 34 | import javax.enterprise.inject.spi.DeploymentException; 35 | import javax.enterprise.inject.spi.Extension; 36 | import javax.enterprise.inject.spi.InjectionPoint; 37 | import javax.enterprise.inject.spi.ProcessAnnotatedType; 38 | import javax.enterprise.inject.spi.ProcessInjectionPoint; 39 | import javax.inject.Provider; 40 | 41 | import java.lang.reflect.ParameterizedType; 42 | import java.lang.reflect.Type; 43 | import java.util.ArrayList; 44 | import java.util.HashMap; 45 | import java.util.HashSet; 46 | import java.util.List; 47 | import java.util.Map; 48 | import java.util.Set; 49 | import java.util.function.Function; 50 | import java.util.function.Predicate; 51 | import java.util.stream.Collectors; 52 | import java.util.stream.Stream; 53 | import java.util.stream.StreamSupport; 54 | 55 | /** 56 | * @author Mark Struberg 57 | */ 58 | public class ConfigExtension implements Extension { 59 | private ConfigImpl config; 60 | 61 | private static final Predicate NOT_PROVIDERS = ip -> (ip.getType() instanceof Class) || (ip.getType() instanceof ParameterizedType && ((ParameterizedType)ip.getType()).getRawType() != Provider.class); 62 | private static final Map REPLACED_TYPES = new HashMap<>(); 63 | 64 | static { 65 | REPLACED_TYPES.put(double.class, Double.class); 66 | REPLACED_TYPES.put(int.class, Integer.class); 67 | REPLACED_TYPES.put(float.class, Float.class); 68 | REPLACED_TYPES.put(long.class, Long.class); 69 | REPLACED_TYPES.put(boolean.class, Boolean.class); 70 | REPLACED_TYPES.put(byte.class, Byte.class); 71 | REPLACED_TYPES.put(short.class, Short.class); 72 | REPLACED_TYPES.put(char.class, Character.class); 73 | } 74 | 75 | private Set injectionPoints = new HashSet<>(); 76 | private Set> proxies = new HashSet<>(); 77 | private List> validProxies; 78 | private List> proxyBeans; 79 | private boolean hasConfigProxy; 80 | private ConfigBean configBean; 81 | 82 | public ConfigExtension() { 83 | final Config raw = ConfigProvider.getConfig(); 84 | // ensure to store the ref the whole lifecycle, java gc is aggressive now 85 | this.config = ConfigImpl.class.cast(ConfigImpl.class.isInstance(raw) ? 86 | raw : // custom overrided config, unlikely but possible in wrong setups 87 | new DefaultConfigBuilder() 88 | .forClassLoader(Thread.currentThread().getContextClassLoader()) 89 | .addDefaultSources() 90 | .addDiscoveredSources() 91 | .addDiscoveredConverters() 92 | .build()); 93 | } 94 | 95 | public void findProxies(@Observes ProcessAnnotatedType pat) { 96 | final Class javaClass = pat.getAnnotatedType().getJavaClass(); 97 | if (javaClass.isInterface() && 98 | Stream.of(javaClass.getMethods()).anyMatch(m -> m.isAnnotationPresent(ConfigProperty.class))) { 99 | proxies.add(javaClass); 100 | } 101 | } 102 | 103 | 104 | public void collectConfigProducer(@Observes ProcessInjectionPoint pip) { 105 | ConfigProperty configProperty = pip.getInjectionPoint().getAnnotated().getAnnotation(ConfigProperty.class); 106 | if (configProperty != null) { 107 | injectionPoints.add(pip.getInjectionPoint()); 108 | } 109 | } 110 | 111 | public void registerConfigProducer(@Observes AfterBeanDiscovery abd, BeanManager bm) { 112 | Set types = injectionPoints.stream() 113 | .filter(NOT_PROVIDERS) 114 | .map(ip -> REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType())) 115 | .collect(Collectors.toSet()); 116 | 117 | Set providerTypes = injectionPoints.stream() 118 | .filter(NOT_PROVIDERS.negate()) 119 | .map(ip -> ((ParameterizedType)ip.getType()).getActualTypeArguments()[0]) 120 | .collect(Collectors.toSet()); 121 | 122 | types.addAll(providerTypes); 123 | 124 | types.stream() 125 | .peek(type -> { 126 | if (type == Config.class) { 127 | hasConfigProxy = true; 128 | } 129 | }) 130 | .map(type -> new ConfigInjectionBean(bm, type)) 131 | .forEach(abd::addBean); 132 | 133 | validProxies = proxies.stream() 134 | .filter(this::isValidProxy) 135 | .collect(toList()); 136 | if (validProxies.size() == proxies.size()) { 137 | proxyBeans = validProxies.stream() 138 | .map((Function, ? extends ProxyBean>) ProxyBean::new) 139 | .collect(toList()); 140 | proxyBeans.forEach(abd::addBean); 141 | } // else there are errors 142 | 143 | if (!hasConfigProxy) { 144 | configBean = new ConfigBean(); 145 | abd.addBean(configBean); 146 | } 147 | } 148 | 149 | public void validate(@Observes AfterDeploymentValidation add) { 150 | List deploymentProblems = new ArrayList<>(); 151 | 152 | StreamSupport.stream(config.getConfigSources().spliterator(), false) 153 | .filter(Reloadable.class::isInstance) 154 | .map(Reloadable.class::cast) 155 | .forEach(Reloadable::reload); 156 | 157 | if (!hasConfigProxy) { 158 | configBean.init(config); 159 | } 160 | proxyBeans.forEach(b -> b.init(config)); 161 | proxyBeans.clear(); 162 | 163 | for (InjectionPoint injectionPoint : injectionPoints) { 164 | Type type = injectionPoint.getType(); 165 | 166 | // replace native types with their Wrapper types 167 | type = REPLACED_TYPES.getOrDefault(type, type); 168 | 169 | ConfigProperty configProperty = injectionPoint.getAnnotated().getAnnotation(ConfigProperty.class); 170 | if (type instanceof Class) { 171 | // a direct injection of a ConfigProperty 172 | // that means a Converter must exist. 173 | String key = ConfigInjectionBean.getConfigKey(injectionPoint, configProperty); 174 | if ((isDefaultUnset(configProperty.defaultValue())) 175 | && !config.getOptionalValue(key, (Class) type).isPresent()) { 176 | deploymentProblems.add("No Config Value exists for " + key); 177 | } 178 | } 179 | } 180 | 181 | if (!deploymentProblems.isEmpty()) { 182 | add.addDeploymentProblem(new DeploymentException("Error while validating Configuration\n" 183 | + String.join("\n", deploymentProblems))); 184 | } 185 | 186 | if (validProxies.size() != proxies.size()) { 187 | proxies.stream() 188 | .filter(p -> !validProxies.contains(p)) 189 | .forEach(p -> add.addDeploymentProblem( 190 | new DeploymentException("Invalid proxy: " + p + ". All method should have @ConfigProperty."))); 191 | } 192 | proxies.clear(); 193 | } 194 | 195 | public void shutdown(@Observes BeforeShutdown bsd) { 196 | ConfigProviderResolver.instance().releaseConfig(config); 197 | } 198 | 199 | private boolean isValidProxy(final Class api) { 200 | return Stream.of(api.getMethods()) 201 | .allMatch(m -> m.isAnnotationPresent(ConfigProperty.class) || Object.class == m.getDeclaringClass()); 202 | } 203 | 204 | static boolean isDefaultUnset(String defaultValue) { 205 | return ConfigProperty.UNCONFIGURED_VALUE.equals(defaultValue); 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.cdi; 18 | 19 | import static java.util.Optional.of; 20 | import static java.util.Optional.ofNullable; 21 | 22 | import java.lang.annotation.Annotation; 23 | import java.lang.reflect.ParameterizedType; 24 | import java.lang.reflect.Type; 25 | import java.util.Collections; 26 | import java.util.HashSet; 27 | import java.util.List; 28 | import java.util.NoSuchElementException; 29 | import java.util.Optional; 30 | import java.util.Set; 31 | import java.util.function.Supplier; 32 | 33 | import javax.enterprise.context.Dependent; 34 | import javax.enterprise.context.spi.CreationalContext; 35 | import javax.enterprise.inject.spi.Annotated; 36 | import javax.enterprise.inject.spi.AnnotatedMember; 37 | import javax.enterprise.inject.spi.AnnotatedType; 38 | import javax.enterprise.inject.spi.Bean; 39 | import javax.enterprise.inject.spi.BeanManager; 40 | import javax.enterprise.inject.spi.InjectionPoint; 41 | import javax.enterprise.inject.spi.PassivationCapable; 42 | import javax.enterprise.util.AnnotationLiteral; 43 | import javax.inject.Provider; 44 | 45 | import org.apache.geronimo.config.ConfigImpl; 46 | import org.apache.geronimo.config.ConfigValueImpl; 47 | import org.eclipse.microprofile.config.Config; 48 | import org.eclipse.microprofile.config.ConfigProvider; 49 | import org.eclipse.microprofile.config.inject.ConfigProperty; 50 | 51 | /** 52 | * @author Mark Struberg 53 | */ 54 | public class ConfigInjectionBean implements Bean, PassivationCapable { 55 | 56 | private final static Set QUALIFIERS = new HashSet<>(); 57 | static { 58 | QUALIFIERS.add(new ConfigPropertyLiteral()); 59 | } 60 | 61 | private final BeanManager bm; 62 | private final Class rawType; 63 | private final Set types; 64 | private final String id; 65 | 66 | /** 67 | * only access via {@link #getConfig(} 68 | */ 69 | private ConfigImpl _config; 70 | 71 | public ConfigInjectionBean(BeanManager bm, Type type) { 72 | this.bm = bm; 73 | types = new HashSet<>(); 74 | types.add(type); 75 | rawType = getRawType(type); 76 | this.id = "ConfigInjectionBean_" + types; 77 | } 78 | 79 | private Class getRawType(Type type) { 80 | if (type instanceof Class) { 81 | return (Class) type; 82 | } 83 | else if (type instanceof ParameterizedType) { 84 | ParameterizedType paramType = (ParameterizedType) type; 85 | 86 | return (Class) paramType.getRawType(); 87 | } 88 | 89 | throw new UnsupportedOperationException("No idea how to handle " + type); 90 | } 91 | 92 | @Override 93 | public Set getInjectionPoints() { 94 | return Collections.emptySet(); 95 | } 96 | 97 | @Override 98 | public Class getBeanClass() { 99 | return rawType; 100 | } 101 | 102 | @Override 103 | public boolean isNullable() { 104 | return false; 105 | } 106 | 107 | @Override 108 | public T create(CreationalContext context) { 109 | final InjectionPoint ip = (InjectionPoint)bm.getInjectableReference(new ConfigInjectionPoint(this),context); 110 | if (ip == null) { 111 | throw new IllegalStateException("Could not retrieve InjectionPoint"); 112 | } 113 | final Annotated annotated = ip.getAnnotated(); 114 | final ConfigProperty configProperty = annotated.getAnnotation(ConfigProperty.class); 115 | final String key = getConfigKey(ip, configProperty); 116 | final String defaultValue = configProperty.defaultValue(); 117 | final boolean canBeNull = ConfigProperty.UNCONFIGURED_VALUE.equals(defaultValue); 118 | return toInstance( 119 | annotated.getBaseType(), 120 | key, 121 | canBeNull || ConfigExtension.isDefaultUnset(defaultValue) ? null : defaultValue, 122 | true, 123 | canBeNull); 124 | } 125 | 126 | private T toInstance(final Type baseType, final String key, 127 | final String defaultValue, final boolean skipProviderLevel, 128 | final boolean acceptNull) { 129 | if (baseType instanceof ParameterizedType) { 130 | ParameterizedType paramType = (ParameterizedType) baseType; 131 | Type rawType = paramType.getRawType(); 132 | if (paramType.getActualTypeArguments().length == 0) { 133 | throw new IllegalArgumentException("No argument to " + paramType); 134 | } 135 | 136 | Type arg = paramType.getActualTypeArguments()[0]; 137 | if (!Class.class.isInstance(arg)) { 138 | if (ParameterizedType.class.isInstance(arg)) { 139 | ParameterizedType nested = ParameterizedType.class.cast(arg); 140 | if (rawType == Optional.class) { 141 | return (T) ofNullable(toInstance(nested, key, defaultValue, false, true)); 142 | } 143 | if (rawType == Provider.class) { 144 | if (nested.getActualTypeArguments().length != 1) { 145 | throw new IllegalArgumentException("Invalid arguments for " + paramType); 146 | } 147 | return skipProviderLevel ? 148 | toInstance(nested, key, defaultValue, false, acceptNull) : 149 | (T) (Provider) () -> toInstance(nested, key, defaultValue, false, true); 150 | } 151 | if (rawType == Supplier.class) { 152 | if (nested.getActualTypeArguments().length != 1) { 153 | throw new IllegalArgumentException("Invalid arguments for " + paramType); 154 | } 155 | return (T) (Supplier) () -> toInstance(nested, key, defaultValue, false, true); 156 | } 157 | } 158 | throw new IllegalArgumentException("Unsupported multiple generics level: " + paramType); 159 | } 160 | 161 | Class clazzParam = (Class) arg; 162 | 163 | // handle Provider 164 | if (rawType instanceof Class && rawType == Provider.class && paramType.getActualTypeArguments().length == 1) { 165 | return skipProviderLevel ? 166 | toInstance(clazzParam, key, defaultValue, false, acceptNull) : 167 | (T) (Provider) () -> toInstance(clazzParam, key, defaultValue, false, true); 168 | } 169 | 170 | // handle Optional 171 | if (rawType instanceof Class && rawType == Optional.class && paramType.getActualTypeArguments().length == 1) { 172 | return (T) getConfig().getOptionalValue(key, clazzParam); 173 | } 174 | 175 | if (rawType instanceof Class && rawType == Supplier.class && paramType.getActualTypeArguments().length == 1) { 176 | return (T) (Supplier) () -> toInstance(clazzParam, key, defaultValue, false, true); 177 | } 178 | 179 | if (Set.class.equals(rawType)) { 180 | final List list = getList(key, clazzParam, defaultValue, acceptNull); 181 | return list == null ? null : (T) new HashSet(list); 182 | } 183 | if (List.class.equals(rawType)) { 184 | return (T) getList(key, clazzParam, defaultValue, acceptNull); 185 | } 186 | throw new IllegalStateException("unhandled ConfigProperty"); 187 | } 188 | Class clazz = (Class) baseType; 189 | return getConfigValue(key, defaultValue, clazz, acceptNull); 190 | } 191 | 192 | private List getList(final String key, final Class clazzParam, final String defaultValue, final boolean nullable) { 193 | final ConfigImpl config = getConfig(); 194 | ConfigValueImpl configValue = config 195 | .access(key) 196 | .as(clazzParam) 197 | .asList() 198 | .evaluateVariables(true); 199 | 200 | if (defaultValue != null) 201 | { 202 | configValue.withStringDefault(defaultValue); 203 | } 204 | else if (nullable) // list default is emptyList, reset it for nullable values 205 | { 206 | configValue.withDefault(null); 207 | } 208 | 209 | return (List) configValue.get(); 210 | } 211 | 212 | private T getConfigValue(final String key, final String defaultValue, final Class clazz, final boolean canBeNull) { 213 | final ConfigImpl config = getConfig(); 214 | final T value = (T) config 215 | .access(key) 216 | .as(clazz) 217 | .evaluateVariables(true) 218 | .withDefault(defaultValue == null ? null : config.convert(defaultValue, clazz)) 219 | .get(); 220 | if (value != null || canBeNull) { 221 | return value; 222 | } 223 | throw new NoSuchElementException("No configured value found for config key '" + key + "'"); 224 | } 225 | 226 | /** 227 | * Get the property key to use. 228 | * In case the {@link ConfigProperty#name()} is empty we will try to determine the key name from the InjectionPoint. 229 | */ 230 | static String getConfigKey(InjectionPoint ip, ConfigProperty configProperty) { 231 | String key = configProperty.name(); 232 | if (key.length() > 0) { 233 | return key; 234 | } 235 | if (ip.getAnnotated() instanceof AnnotatedMember) { 236 | AnnotatedMember member = (AnnotatedMember) ip.getAnnotated(); 237 | AnnotatedType declaringType = member.getDeclaringType(); 238 | if (declaringType != null) { 239 | return declaringType.getJavaClass().getCanonicalName() + "." + member.getJavaMember().getName(); 240 | } 241 | } 242 | 243 | throw new IllegalStateException("Could not find default name for @ConfigProperty InjectionPoint " + ip); 244 | } 245 | 246 | public ConfigImpl getConfig() { 247 | if (_config == null) { 248 | _config = (ConfigImpl) ConfigProvider.getConfig(); 249 | } 250 | return _config; 251 | } 252 | 253 | @Override 254 | public void destroy(T instance, CreationalContext context) { 255 | 256 | } 257 | 258 | @Override 259 | public Set getTypes() { 260 | return types; 261 | } 262 | 263 | @Override 264 | public Set getQualifiers() { 265 | return QUALIFIERS; 266 | } 267 | 268 | @Override 269 | public Class getScope() { 270 | return Dependent.class; 271 | } 272 | 273 | @Override 274 | public String getName() { 275 | return null; 276 | } 277 | 278 | @Override 279 | public Set> getStereotypes() { 280 | return Collections.emptySet(); 281 | } 282 | 283 | @Override 284 | public boolean isAlternative() { 285 | return false; 286 | } 287 | 288 | @Override 289 | public String getId() { 290 | return id; 291 | } 292 | 293 | private static class ConfigPropertyLiteral extends AnnotationLiteral implements ConfigProperty { 294 | @Override 295 | public String name() { 296 | return ""; 297 | } 298 | 299 | @Override 300 | public String defaultValue() { 301 | return ""; 302 | } 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/cdi/ConfigInjectionPoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package org.apache.geronimo.config.cdi; 21 | 22 | import javax.enterprise.inject.spi.Annotated; 23 | import javax.enterprise.inject.spi.Bean; 24 | import javax.enterprise.inject.spi.InjectionPoint; 25 | import java.lang.annotation.Annotation; 26 | import java.lang.reflect.Member; 27 | import java.lang.reflect.Type; 28 | import java.util.Collections; 29 | import java.util.Set; 30 | 31 | class ConfigInjectionPoint implements InjectionPoint{ 32 | private final Bean bean; 33 | 34 | ConfigInjectionPoint(Bean bean) { 35 | this.bean = bean; 36 | } 37 | 38 | @Override 39 | public boolean isTransient() { 40 | return false; 41 | } 42 | 43 | @Override 44 | public boolean isDelegate() { 45 | return false; 46 | } 47 | 48 | @Override 49 | public Type getType() { 50 | return InjectionPoint.class; 51 | } 52 | 53 | @Override 54 | public Set getQualifiers() { 55 | return Collections.singleton(DefaultLiteral.INSTANCE); 56 | } 57 | 58 | @Override 59 | public Member getMember() { 60 | return null; 61 | } 62 | 63 | @Override 64 | public Bean getBean() { 65 | return bean; 66 | } 67 | 68 | @Override 69 | public Annotated getAnnotated() { 70 | return null; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/cdi/ConfigurationHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.cdi; 18 | 19 | import static java.util.Optional.ofNullable; 20 | import static java.util.function.Function.identity; 21 | import static java.util.stream.Collectors.toList; 22 | import static java.util.stream.Collectors.toMap; 23 | import static java.util.stream.Collectors.toSet; 24 | 25 | import java.lang.reflect.InvocationHandler; 26 | import java.lang.reflect.InvocationTargetException; 27 | import java.lang.reflect.Method; 28 | import java.lang.reflect.ParameterizedType; 29 | import java.lang.reflect.Type; 30 | import java.util.Collection; 31 | import java.util.Map; 32 | import java.util.Optional; 33 | import java.util.Set; 34 | import java.util.stream.Collector; 35 | import java.util.stream.Stream; 36 | 37 | import org.apache.geronimo.config.ConfigImpl; 38 | import org.eclipse.microprofile.config.Config; 39 | import org.eclipse.microprofile.config.ConfigProvider; 40 | import org.eclipse.microprofile.config.inject.ConfigProperty; 41 | 42 | public class ConfigurationHandler implements InvocationHandler { 43 | private final ConfigImpl config; 44 | private final Map methodMetas; 45 | 46 | ConfigurationHandler(final ConfigImpl config, final Class api) { 47 | this.config = config; 48 | 49 | final String prefix = ofNullable(api.getAnnotation(ConfigProperty.class)) 50 | .map(ConfigProperty::name) 51 | .orElse(""); 52 | this.methodMetas = Stream.of(api.getMethods()) 53 | .filter(m -> m.isAnnotationPresent(ConfigProperty.class)) 54 | .collect(toMap(identity(), e -> new MethodMeta(e, prefix))); 55 | } 56 | 57 | @Override 58 | public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { 59 | if (Object.class == method.getDeclaringClass()) { 60 | try { 61 | return method.invoke(this, args); 62 | } catch (final InvocationTargetException ite) { 63 | throw ite.getTargetException(); 64 | } 65 | } 66 | final MethodMeta methodMeta = methodMetas.get(method); 67 | if (methodMeta != null) { 68 | return methodMeta.read(config); 69 | } 70 | return null; 71 | } 72 | 73 | // todo: list, set etc handling but config API is not that friendly for now (Class vs Type) 74 | private static class MethodMeta { 75 | private final String key; 76 | private final Object defaultValue; 77 | private final Class lookupType; 78 | private final Class collectionConversionType; 79 | private final Collector> collectionCollector; 80 | 81 | private final boolean optional; 82 | 83 | private MethodMeta(final Method m, final String prefix) { 84 | final ConfigProperty annotation = m.getAnnotation(ConfigProperty.class); 85 | optional = Optional.class == m.getReturnType(); 86 | final Type type = optional ? 87 | ParameterizedType.class.cast(m.getGenericReturnType()).getActualTypeArguments()[0] : 88 | m.getGenericReturnType(); 89 | 90 | if (Class.class.isInstance(type)) { 91 | lookupType = Class.class.cast(type); 92 | collectionCollector = null; 93 | collectionConversionType = null; 94 | } else if (ParameterizedType.class.isInstance(type)) { 95 | final ParameterizedType pt = ParameterizedType.class.cast(type); 96 | final Type rawType = pt.getRawType(); 97 | if (!Class.class.isInstance(rawType)) { 98 | throw new IllegalArgumentException("Unsupported parameterized type: " + type); 99 | } 100 | 101 | final Class clazz = Class.class.cast(pt.getRawType()); 102 | if (Collection.class.isAssignableFrom(clazz)) { 103 | final Type arg0 = pt.getActualTypeArguments()[0]; 104 | collectionConversionType = Class.class.cast(ParameterizedType.class.isInstance(arg0) ? 105 | // mainly to tolerate Class as an arg 106 | ParameterizedType.class.cast(arg0).getRawType() : Class.class.cast(arg0)); 107 | lookupType = String.class; 108 | if (Set.class.isAssignableFrom(clazz)) { 109 | collectionCollector = toSet(); 110 | } else { 111 | collectionCollector = toList(); 112 | } 113 | } else { 114 | throw new IllegalArgumentException("Unsupported parameterized type: " + type + ", did you want a Collection?"); 115 | } 116 | } else { 117 | throw new IllegalArgumentException("Unsupported type: " + type); 118 | } 119 | 120 | key = prefix + (annotation.name().isEmpty() ? m.getDeclaringClass().getName() + "." + m.getName() : annotation.name()); 121 | 122 | final String defaultValue = annotation.defaultValue(); 123 | final boolean canBeNull = ConfigProperty.UNCONFIGURED_VALUE.equals(defaultValue); 124 | final boolean hasDefault = !ConfigProperty.UNCONFIGURED_VALUE.equals(defaultValue) && !canBeNull; 125 | 126 | if (hasDefault) { 127 | final Config config = ConfigProvider.getConfig(); 128 | if (lookupType == long.class || lookupType == Long.class) { 129 | this.defaultValue = Long.parseLong(defaultValue); 130 | } else if (lookupType == boolean.class || lookupType == Boolean.class) { 131 | this.defaultValue = Boolean.parseBoolean(defaultValue); 132 | } else if (lookupType == int.class || lookupType == Integer.class) { 133 | this.defaultValue = Integer.parseInt(defaultValue); 134 | } else if (lookupType == double.class || lookupType == Double.class) { 135 | this.defaultValue = Double.parseDouble(defaultValue); 136 | } else if (lookupType == float.class || lookupType == Float.class) { 137 | this.defaultValue = Float.parseFloat(defaultValue); 138 | } else if (lookupType == short.class || lookupType == Short.class) { 139 | this.defaultValue = Short.parseShort(defaultValue); 140 | } else if (lookupType == char.class || lookupType == Character.class) { 141 | this.defaultValue = defaultValue.charAt(0); 142 | } else if (lookupType == byte.class || lookupType == Byte.class) { 143 | this.defaultValue = Byte.parseByte(defaultValue); 144 | } else if (collectionCollector != null) { 145 | this.defaultValue = convert(defaultValue, config); 146 | } else if (lookupType == String.class) { 147 | this.defaultValue = defaultValue; 148 | } else { 149 | throw new IllegalArgumentException("Unsupported default for " + m); 150 | } 151 | } else { 152 | if (lookupType.isPrimitive()) { 153 | if (lookupType == long.class) { 154 | this.defaultValue = 0L; 155 | } else if (lookupType == boolean.class) { 156 | this.defaultValue = false; 157 | } else if (lookupType == int.class ) { 158 | this.defaultValue = 0; 159 | } else if (lookupType == double.class) { 160 | this.defaultValue = 0.0D; 161 | } else if (lookupType == float.class) { 162 | this.defaultValue = 0.0F; 163 | } else if (lookupType == short.class) { 164 | this.defaultValue = (short) 0; 165 | } else if (lookupType == char.class) { 166 | this.defaultValue = '\u0000'; 167 | } else if (lookupType == byte.class) { 168 | this.defaultValue = (byte) 0; 169 | } else { 170 | this.defaultValue = null; 171 | } 172 | } else { 173 | this.defaultValue = null; 174 | } 175 | } 176 | } 177 | 178 | Object read(final ConfigImpl config) { 179 | final Optional optionalValue = ofNullable(config 180 | .access(key) 181 | .as(lookupType) 182 | .evaluateVariables(true) 183 | .get()); 184 | if (optional) { 185 | return processOptional(optionalValue, config); 186 | } 187 | return processOptional(optionalValue, config).orElse(defaultValue); 188 | } 189 | 190 | private Optional processOptional(final Optional optionalValue, final Config config) { 191 | if (collectionCollector != null) { 192 | return optionalValue.map(String.class::cast).map(v -> convert(v, config)); 193 | } 194 | return optionalValue; 195 | } 196 | 197 | private Collection convert(final String o, final Config config) { 198 | final String[] values = o.split(","); 199 | return Stream.of(values) 200 | .map(v -> mapValue(v, config)) 201 | .collect(collectionCollector); 202 | } 203 | 204 | private Object mapValue(final String raw, final Config config) { 205 | if (String.class == collectionConversionType) { 206 | return raw; 207 | } 208 | if (ConfigImpl.class.isInstance(config)) { 209 | return ConfigImpl.class.cast(config).convert(raw, collectionConversionType); 210 | } 211 | throw new IllegalArgumentException("Unsupported conversion if config instance is not a ConfigImpl: " + collectionConversionType); 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/cdi/DefaultLiteral.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package org.apache.geronimo.config.cdi; 21 | 22 | import javax.enterprise.inject.Default; 23 | import javax.enterprise.util.AnnotationLiteral; 24 | 25 | class DefaultLiteral extends AnnotationLiteral implements Default { 26 | public static Default INSTANCE = new DefaultLiteral(); 27 | 28 | @Override 29 | public boolean equals(Object other) 30 | { 31 | return other instanceof Default; 32 | } 33 | 34 | @Override 35 | public int hashCode() 36 | { 37 | return 0; 38 | } 39 | 40 | @Override 41 | public String toString() 42 | { 43 | return "@Default"; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/cdi/ProxyBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.cdi; 18 | 19 | import static java.util.Arrays.asList; 20 | import static java.util.Collections.emptySet; 21 | 22 | import java.io.Serializable; 23 | import java.lang.annotation.Annotation; 24 | import java.lang.reflect.Proxy; 25 | import java.lang.reflect.Type; 26 | import java.util.HashSet; 27 | import java.util.Set; 28 | 29 | import javax.enterprise.context.ApplicationScoped; 30 | import javax.enterprise.context.spi.CreationalContext; 31 | import javax.enterprise.inject.spi.Bean; 32 | import javax.enterprise.inject.spi.InjectionPoint; 33 | import javax.enterprise.inject.spi.PassivationCapable; 34 | 35 | import org.apache.geronimo.config.ConfigImpl; 36 | import org.eclipse.microprofile.config.Config; 37 | 38 | public class ProxyBean implements Bean, PassivationCapable { 39 | private static final Set QUALIFIERS = new HashSet<>( 40 | asList(DefaultLiteral.INSTANCE, AnyLiteral.INSTANCE)); 41 | private final Class beanClass; 42 | private final Set types; 43 | private final Set qualifiers; 44 | private final String id; 45 | private ConfigImpl config; 46 | 47 | ProxyBean(final Class api) { 48 | this.beanClass = api; 49 | this.qualifiers = QUALIFIERS; 50 | this.types = new HashSet<>(asList(api, Serializable.class)); 51 | this.id = ProxyBean.class.getName() + "[" + api.getName() + "]"; 52 | } 53 | 54 | void init(final ConfigImpl config) { 55 | this.config = config; 56 | } 57 | 58 | @Override 59 | public Set getInjectionPoints() { 60 | return emptySet(); 61 | } 62 | 63 | @Override 64 | public Class getBeanClass() { 65 | return beanClass; 66 | } 67 | 68 | @Override 69 | public boolean isNullable() { 70 | return false; 71 | } 72 | 73 | @Override 74 | public T create(final CreationalContext context) { 75 | return (T) Proxy.newProxyInstance( 76 | Thread.currentThread().getContextClassLoader(), 77 | new Class[] { beanClass }, 78 | new ConfigurationHandler(config, beanClass)); 79 | } 80 | 81 | @Override 82 | public void destroy(final T instance, final CreationalContext context) { 83 | // no-op 84 | } 85 | 86 | @Override 87 | public Set getTypes() { 88 | return types; 89 | } 90 | 91 | @Override 92 | public Set getQualifiers() { 93 | return qualifiers; 94 | } 95 | 96 | @Override 97 | public Class getScope() { 98 | return ApplicationScoped.class; 99 | } 100 | 101 | @Override 102 | public String getName() { 103 | return null; 104 | } 105 | 106 | @Override 107 | public Set> getStereotypes() { 108 | return emptySet(); 109 | } 110 | 111 | @Override 112 | public boolean isAlternative() { 113 | return false; 114 | } 115 | 116 | @Override 117 | public String getId() { 118 | return id; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/cdi/configsource/Reloadable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.geronimo.config.cdi.configsource; 20 | 21 | /** 22 | * Enable config source to be reloaded in AfterDeploymentValidation 23 | * phase. Particularly useful for sources relying on a state which can 24 | * be mutated in previous phases like system properties but which 25 | * desire to stay immutable at runtime for perf/lock reasons. 26 | */ 27 | public interface Reloadable { 28 | void reload(); 29 | } 30 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/configsource/BaseConfigSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.geronimo.config.configsource; 20 | 21 | import java.util.logging.Level; 22 | import java.util.logging.Logger; 23 | 24 | import org.eclipse.microprofile.config.spi.ConfigSource; 25 | 26 | 27 | /** 28 | * Base class for all our ConfigSources 29 | * 30 | * @author Mark Struberg 31 | * @author Gerhard Petracek 32 | */ 33 | public abstract class BaseConfigSource implements ConfigSource { 34 | 35 | public final static String CONFIG_ORDINAL = "config_ordinal"; 36 | 37 | protected Logger log = Logger.getLogger(getClass().getName()); 38 | 39 | private int ordinal = 1000; // default 40 | 41 | @Override 42 | public int getOrdinal() { 43 | return ordinal; 44 | } 45 | 46 | /** 47 | * Init method e.g. for initializing the ordinal. 48 | * This method can be used from a subclass to determine 49 | * the ordinal value 50 | * 51 | * @param defaultOrdinal the default value for the ordinal if not set via configuration 52 | */ 53 | protected void initOrdinal(int defaultOrdinal) { 54 | ordinal = defaultOrdinal; 55 | 56 | String configuredOrdinalString = getValue(CONFIG_ORDINAL); 57 | 58 | try { 59 | if (configuredOrdinalString != null) { 60 | ordinal = Integer.parseInt(configuredOrdinalString.trim()); 61 | } 62 | } 63 | catch (NumberFormatException e) { 64 | log.log(Level.WARNING, 65 | "The configured config-ordinal isn't a valid integer. Invalid value: " + configuredOrdinalString); 66 | } 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.configsource; 18 | 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.net.URL; 22 | import java.util.Map; 23 | import java.util.Properties; 24 | import java.util.logging.Level; 25 | import java.util.logging.Logger; 26 | 27 | /** 28 | * @author Mark Struberg 29 | */ 30 | public class PropertyFileConfigSource extends BaseConfigSource { 31 | private static final Logger LOG = Logger.getLogger(PropertyFileConfigSource.class.getName()); 32 | private Map properties; 33 | private String fileName; 34 | 35 | public PropertyFileConfigSource(URL propertyFileUrl) { 36 | fileName = propertyFileUrl.toExternalForm(); 37 | properties = loadProperties(propertyFileUrl); 38 | initOrdinal(100); 39 | } 40 | 41 | /** 42 | * The given key gets used for a lookup via a properties file 43 | * 44 | * @param key for the property 45 | * @return value for the given key or null if there is no configured value 46 | */ 47 | @Override 48 | public String getValue(String key) { 49 | return properties.get(key); 50 | } 51 | 52 | @Override 53 | public String getName() { 54 | return fileName; 55 | } 56 | 57 | 58 | @Override 59 | public Map getProperties() { 60 | return properties; 61 | } 62 | 63 | private Map loadProperties(URL url) { 64 | Properties props = new Properties(); 65 | 66 | InputStream inputStream = null; 67 | try { 68 | inputStream = url.openStream(); 69 | 70 | if (inputStream != null) { 71 | props.load(inputStream); 72 | } 73 | } 74 | catch (IOException e) { 75 | // don't return null on IOException 76 | LOG.log(Level.WARNING, "Unable to read URL "+url, e); 77 | } 78 | finally { 79 | try { 80 | if (inputStream != null) { 81 | inputStream.close(); 82 | } 83 | } 84 | catch (IOException e) { 85 | // no worries, means that the file is already closed 86 | } 87 | } 88 | 89 | return (Map) props; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/configsource/PropertyFileConfigSourceProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.geronimo.config.configsource; 20 | 21 | import java.io.IOException; 22 | import java.net.URL; 23 | import java.util.ArrayList; 24 | import java.util.Collection; 25 | import java.util.Enumeration; 26 | import java.util.HashMap; 27 | import java.util.List; 28 | import java.util.Map; 29 | import java.util.logging.Level; 30 | import java.util.logging.Logger; 31 | 32 | import javax.enterprise.inject.Typed; 33 | import javax.enterprise.inject.Vetoed; 34 | 35 | import org.eclipse.microprofile.config.spi.ConfigSource; 36 | import org.eclipse.microprofile.config.spi.ConfigSourceProvider; 37 | 38 | 39 | /** 40 | * Register all property files with the given propertyFileName 41 | * as {@link ConfigSource}. 42 | * 43 | * @author Mark Struberg 44 | */ 45 | @Typed 46 | @Vetoed 47 | public class PropertyFileConfigSourceProvider implements ConfigSourceProvider { 48 | private static final Logger LOG = Logger.getLogger(PropertyFileConfigSourceProvider.class.getName()); 49 | 50 | private List configSources = new ArrayList(); 51 | 52 | public PropertyFileConfigSourceProvider(String propertyFileName, boolean optional, ClassLoader forClassLoader) { 53 | try { 54 | Collection propertyFileUrls = resolvePropertyFiles(forClassLoader, propertyFileName); 55 | if (!optional && propertyFileUrls.isEmpty()) { 56 | throw new IllegalStateException(propertyFileName + " wasn't found."); 57 | } 58 | 59 | for (URL propertyFileUrl : propertyFileUrls) { 60 | LOG.log(Level.INFO, 61 | "Custom config found by GeronimoConfig. Name: ''{0}'', URL: ''{1}''", 62 | new Object[]{propertyFileName, propertyFileUrl}); 63 | configSources.add(new PropertyFileConfigSource(propertyFileUrl)); 64 | } 65 | } 66 | catch (IOException ioe) { 67 | throw new IllegalStateException("problem while loading GeronimoConfig property files", ioe); 68 | } 69 | 70 | } 71 | 72 | public Collection resolvePropertyFiles(ClassLoader forClassLoader, String propertyFileName) throws IOException { 73 | // de-duplicate 74 | Map propertyFileUrls = resolveUrls(propertyFileName, forClassLoader); 75 | 76 | // and once again with preceding a "/" 77 | propertyFileUrls.putAll(resolveUrls("/" + propertyFileName, forClassLoader)); 78 | 79 | return propertyFileUrls.values(); 80 | } 81 | 82 | private Map resolveUrls(String propertyFileName, ClassLoader forClassLoader) throws IOException { 83 | Map propertyFileUrls = new HashMap<>(); 84 | Enumeration urls = forClassLoader.getResources(propertyFileName); 85 | while (urls.hasMoreElements()) { 86 | URL url = urls.nextElement(); 87 | propertyFileUrls.put(url.toExternalForm(), url); 88 | } 89 | return propertyFileUrls; 90 | } 91 | 92 | 93 | @Override 94 | public List getConfigSources(ClassLoader forClassLoader) { 95 | return configSources; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/configsource/SystemEnvConfigSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.geronimo.config.configsource; 20 | 21 | 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | 25 | import javax.enterprise.inject.Typed; 26 | import javax.enterprise.inject.Vetoed; 27 | 28 | import org.eclipse.microprofile.config.spi.ConfigSource; 29 | 30 | /** 31 | * {@link ConfigSource} which uses {@link System#getenv()} 32 | *

33 | * We also allow to write underlines _ instead of dots _ in the 34 | * environment via export (unix) or SET (windows) 35 | * 36 | * @author Mark Struberg 37 | */ 38 | @Typed 39 | @Vetoed 40 | public class SystemEnvConfigSource extends BaseConfigSource { 41 | private Map configValues; 42 | private Map uppercasePosixValues; 43 | 44 | public SystemEnvConfigSource() { 45 | uppercasePosixValues = new HashMap<>(); 46 | configValues = System.getenv(); 47 | initOrdinal(300); 48 | 49 | for (Map.Entry e : configValues.entrySet()) { 50 | String originalKey = e.getKey(); 51 | String posixKey = replaceNonPosixEnvChars(originalKey).toUpperCase(); 52 | if (!originalKey.equals(posixKey)) { 53 | uppercasePosixValues.put(posixKey, e.getValue()); 54 | } 55 | } 56 | } 57 | 58 | @Override 59 | public String getName() { 60 | return "system_env"; 61 | } 62 | 63 | @Override 64 | public Map getProperties() { 65 | return configValues; 66 | } 67 | 68 | @Override 69 | public String getValue(String key) { 70 | String val = configValues.get(key); 71 | if (val == null) { 72 | key = replaceNonPosixEnvChars(key); 73 | val = configValues.get(key); 74 | } 75 | if (val == null) { 76 | key = key.toUpperCase(); 77 | val = configValues.get(key); 78 | } 79 | if (val == null) { 80 | val = uppercasePosixValues.get(key); 81 | } 82 | 83 | return val; 84 | } 85 | 86 | private String replaceNonPosixEnvChars(String key) { 87 | return key.replaceAll("[^A-Za-z0-9]", "_"); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/configsource/SystemPropertyConfigSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.geronimo.config.configsource; 20 | 21 | import org.apache.geronimo.config.cdi.configsource.Reloadable; 22 | import org.eclipse.microprofile.config.spi.ConfigSource; 23 | 24 | import javax.enterprise.inject.Typed; 25 | import javax.enterprise.inject.Vetoed; 26 | import java.util.Map; 27 | 28 | import static java.lang.Boolean.valueOf; 29 | import static java.util.function.Function.identity; 30 | import static java.util.stream.Collectors.toMap; 31 | 32 | /** 33 | * {@link ConfigSource} which uses {@link System#getProperties()} 34 | * 35 | * @author Mark Struberg 36 | */ 37 | @Typed 38 | @Vetoed 39 | public class SystemPropertyConfigSource extends BaseConfigSource implements Reloadable { 40 | private static final String COPY_PROPERTY = "org.apache.geronimo.config.configsource.SystemPropertyConfigSource.copy"; 41 | private final Map instance; 42 | private final boolean shouldReload; 43 | 44 | public SystemPropertyConfigSource() { 45 | this(valueOf(System.getProperty(COPY_PROPERTY, "true"))); 46 | } 47 | 48 | public SystemPropertyConfigSource(boolean copy) { 49 | instance = load(copy); 50 | shouldReload = copy; 51 | initOrdinal(400); 52 | } 53 | 54 | @Override 55 | public Map getProperties() { 56 | return instance; 57 | } 58 | 59 | @Override 60 | public String getValue(String key) { 61 | return instance.get(key); 62 | } 63 | 64 | @Override 65 | public String getName() { 66 | return "system-properties"; 67 | } 68 | 69 | @Override 70 | public void reload() { 71 | if (!shouldReload) { 72 | return; 73 | } 74 | instance.clear(); 75 | instance.putAll(load(true)); 76 | } 77 | 78 | private Map load(final boolean copy) { 79 | return copy ? 80 | System.getProperties().stringPropertyNames().stream().collect(toMap(identity(), System::getProperty)) : 81 | Map.class.cast(System.getProperties()); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/BooleanConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.converters; 18 | 19 | import org.eclipse.microprofile.config.spi.Converter; 20 | 21 | import javax.annotation.Priority; 22 | import javax.enterprise.inject.Vetoed; 23 | 24 | /** 25 | * @author Mark Struberg 26 | */ 27 | @Priority(1) 28 | @Vetoed 29 | public class BooleanConverter implements Converter { 30 | 31 | public static final BooleanConverter INSTANCE = new BooleanConverter(); 32 | 33 | @Override 34 | public Boolean convert(String value) { 35 | if (value != null) { 36 | return "TRUE".equalsIgnoreCase(value) 37 | || "1".equalsIgnoreCase(value) 38 | || "YES".equalsIgnoreCase(value) 39 | || "Y".equalsIgnoreCase(value) 40 | || "ON".equalsIgnoreCase(value) 41 | || "JA".equalsIgnoreCase(value) 42 | || "J".equalsIgnoreCase(value) 43 | || "OUI".equalsIgnoreCase(value); 44 | } 45 | 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/ByteConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.converters; 18 | 19 | import org.eclipse.microprofile.config.spi.Converter; 20 | 21 | import javax.annotation.Priority; 22 | import javax.enterprise.inject.Vetoed; 23 | 24 | /** 25 | * @author Daniel 'soro' Cunha 26 | */ 27 | 28 | @Priority(1) 29 | @Vetoed 30 | public class ByteConverter implements Converter { 31 | 32 | public static final ByteConverter INSTANCE = new ByteConverter(); 33 | 34 | @Override 35 | public Byte convert(String value) { 36 | return value != null ? Byte.valueOf(value) : null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/CharacterConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.converters; 18 | 19 | import org.eclipse.microprofile.config.spi.Converter; 20 | 21 | import javax.annotation.Priority; 22 | import javax.enterprise.inject.Vetoed; 23 | 24 | /** 25 | * @author Daniel 'soro' Cunha 26 | */ 27 | 28 | @Priority(1) 29 | @Vetoed 30 | public class CharacterConverter implements Converter { 31 | 32 | public static final CharacterConverter INSTANCE = new CharacterConverter(); 33 | 34 | @Override 35 | public Character convert(String value) { 36 | if (value == null || value.length() > 1) { 37 | throw new IllegalArgumentException("Error while converting the value " + value + 38 | " to type " + char.class); 39 | } 40 | 41 | return value.charAt(0); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/ClassConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.geronimo.config.converters; 20 | 21 | import org.eclipse.microprofile.config.spi.Converter; 22 | 23 | import javax.annotation.Priority; 24 | import javax.enterprise.inject.Vetoed; 25 | 26 | @Priority(1) 27 | @Vetoed 28 | public class ClassConverter implements Converter{ 29 | public static final Converter INSTANCE = new ClassConverter(); 30 | @Override 31 | public Class convert(String value) { 32 | if(value == null) { 33 | return null; 34 | } 35 | try { 36 | ClassLoader loader = Thread.currentThread().getContextClassLoader(); 37 | if (loader == null) { 38 | return Class.forName(value); 39 | } 40 | return Class.forName(value, true, loader); 41 | } catch (ClassNotFoundException e) { 42 | throw new IllegalArgumentException(e); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/DoubleConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.converters; 18 | 19 | import org.eclipse.microprofile.config.spi.Converter; 20 | 21 | import javax.annotation.Priority; 22 | import javax.enterprise.inject.Vetoed; 23 | 24 | /** 25 | * @author Mark Struberg 26 | */ 27 | @Priority(1) 28 | @Vetoed 29 | public class DoubleConverter implements Converter { 30 | 31 | public static final DoubleConverter INSTANCE = new DoubleConverter(); 32 | 33 | @Override 34 | public Double convert(String value) { 35 | return value != null ? Double.valueOf(value) : null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/DurationConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.converters; 18 | 19 | import java.time.Duration; 20 | import java.time.format.DateTimeParseException; 21 | 22 | import javax.annotation.Priority; 23 | import javax.enterprise.inject.Vetoed; 24 | 25 | import org.eclipse.microprofile.config.spi.Converter; 26 | 27 | /** 28 | * @author Mark Struberg 29 | */ 30 | @Priority(1) 31 | @Vetoed 32 | public class DurationConverter implements Converter { 33 | 34 | public static final DurationConverter INSTANCE = new DurationConverter(); 35 | 36 | @Override 37 | public Duration convert(String value) { 38 | if (value != null) { 39 | try { 40 | return Duration.parse(value); 41 | } 42 | catch (DateTimeParseException dtpe) { 43 | throw new IllegalArgumentException(dtpe); 44 | } 45 | } 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/FloatConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.converters; 18 | 19 | import javax.annotation.Priority; 20 | import javax.enterprise.inject.Vetoed; 21 | 22 | import org.eclipse.microprofile.config.spi.Converter; 23 | 24 | /** 25 | * @author Mark Struberg 26 | */ 27 | @Priority(1) 28 | @Vetoed 29 | public class FloatConverter implements Converter { 30 | 31 | public static final FloatConverter INSTANCE = new FloatConverter(); 32 | 33 | @Override 34 | public Float convert(String value) { 35 | return value != null ? Float.valueOf(value) : null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/ImplicitConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.converters; 18 | 19 | import org.eclipse.microprofile.config.spi.Converter; 20 | 21 | import java.lang.reflect.Array; 22 | import java.lang.reflect.Constructor; 23 | import java.lang.reflect.Method; 24 | import java.lang.reflect.Modifier; 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | 28 | 29 | 30 | /** 31 | * A Converter factory + impl for 'common sense converters' 32 | * 33 | */ 34 | public abstract class ImplicitConverter { 35 | 36 | public static Converter getImplicitConverter(Class clazz) { 37 | // handle ct with String param 38 | Converter converter = null; 39 | if (converter == null) { 40 | converter = hasConverterMethod(clazz, "of", String.class); 41 | } 42 | if (converter == null) { 43 | converter = hasConverterMethod(clazz, "of", CharSequence.class); 44 | } 45 | if (converter == null) { 46 | converter = hasConverterMethod(clazz, "valueOf", String.class); 47 | } 48 | if (converter == null) { 49 | converter = hasConverterMethod(clazz, "valueOf", CharSequence.class); 50 | } 51 | if (converter == null) { 52 | converter = hasConverterMethod(clazz, "parse", String.class); 53 | } 54 | if (converter == null) { 55 | converter = hasConverterMethod(clazz, "parse", CharSequence.class); 56 | } 57 | if (converter == null) { 58 | converter = hasConverterCt(clazz, String.class); 59 | } 60 | if (converter == null) { 61 | converter = hasConverterCt(clazz, CharSequence.class); 62 | } 63 | return converter; 64 | } 65 | 66 | private static Converter hasConverterCt(Class clazz, Class paramType) { 67 | try { 68 | final Constructor declaredConstructor = clazz.getDeclaredConstructor(paramType); 69 | if (!declaredConstructor.isAccessible()) { 70 | declaredConstructor.setAccessible(true); 71 | } 72 | return new Converter() { 73 | @Override 74 | public Object convert(String value) { 75 | try { 76 | return declaredConstructor.newInstance(value); 77 | } catch (Exception e) { 78 | throw new IllegalArgumentException(e); 79 | } 80 | } 81 | }; 82 | } catch (NoSuchMethodException e) { 83 | // all fine 84 | } 85 | return null; 86 | } 87 | 88 | private static Converter hasConverterMethod(Class clazz, String methodName, Class paramType) { 89 | // handle valueOf with CharSequence param 90 | try { 91 | final Method method = clazz.getDeclaredMethod(methodName, paramType); 92 | if (!method.isAccessible()) { 93 | method.setAccessible(true); 94 | } 95 | if (Modifier.isStatic(method.getModifiers()) && method.getReturnType().equals(clazz)) { 96 | return new Converter() { 97 | @Override 98 | public Object convert(String value) { 99 | try { 100 | return method.invoke(null, value); 101 | } catch (Exception e) { 102 | throw new IllegalArgumentException("Error while converting the value " + value + 103 | " to type " + method.getReturnType()); 104 | } 105 | } 106 | }; 107 | } 108 | } catch (NoSuchMethodException e) { 109 | // all fine 110 | } 111 | return null; 112 | } 113 | 114 | public static class ImplicitArrayConverter implements Converter { 115 | private final Converter converter; 116 | private final Class type; 117 | 118 | public ImplicitArrayConverter(Converter converter, Class type) { 119 | this.converter = converter; 120 | this.type = type; 121 | } 122 | 123 | @Override 124 | public T convert(String valueStr) { 125 | if (valueStr == null) 126 | { 127 | return null; 128 | } 129 | 130 | List list = new ArrayList(); 131 | StringBuilder currentValue = new StringBuilder(); 132 | int length = valueStr.length(); 133 | for (int i = 0; i < length; i++) 134 | { 135 | char c = valueStr.charAt(i); 136 | if (c == '\\') 137 | { 138 | if (i < length - 1) 139 | { 140 | char nextC = valueStr.charAt(i + 1); 141 | currentValue.append(nextC); 142 | i++; 143 | } 144 | } 145 | else if (c == ',') 146 | { 147 | String trimedVal = currentValue.toString().trim(); 148 | if (trimedVal.length() > 0) 149 | { 150 | list.add(converter.convert(trimedVal)); 151 | } 152 | 153 | currentValue.setLength(0); 154 | } 155 | else 156 | { 157 | currentValue.append(c); 158 | } 159 | } 160 | 161 | String trimedVal = currentValue.toString().trim(); 162 | if (trimedVal.length() > 0) 163 | { 164 | list.add(converter.convert(trimedVal)); 165 | } 166 | 167 | // everything else is an Object array 168 | Object array = Array.newInstance(type, list.size()); 169 | for (int i=0; i < list.size(); i++) { 170 | Array.set(array, i, list.get(i)); 171 | } 172 | return (T) array; 173 | } 174 | 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/IntegerConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.converters; 18 | 19 | import javax.annotation.Priority; 20 | import javax.enterprise.inject.Vetoed; 21 | 22 | import org.eclipse.microprofile.config.spi.Converter; 23 | 24 | /** 25 | * @author Mark Struberg 26 | */ 27 | @Priority(1) 28 | @Vetoed 29 | public class IntegerConverter implements Converter { 30 | 31 | public static final IntegerConverter INSTANCE = new IntegerConverter(); 32 | 33 | @Override 34 | public Integer convert(String value) { 35 | return value != null ? Integer.valueOf(value) : null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/LongConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.converters; 18 | 19 | import org.eclipse.microprofile.config.spi.Converter; 20 | 21 | import javax.annotation.Priority; 22 | import javax.enterprise.inject.Vetoed; 23 | 24 | /** 25 | * @author Mark Struberg 26 | */ 27 | @Priority(1) 28 | @Vetoed 29 | public class LongConverter implements Converter { 30 | 31 | public static final LongConverter INSTANCE = new LongConverter(); 32 | 33 | @Override 34 | public Long convert(String value) { 35 | return value != null ? Long.valueOf(value) : null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/ShortConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.converters; 18 | 19 | import org.eclipse.microprofile.config.spi.Converter; 20 | 21 | import javax.annotation.Priority; 22 | import javax.enterprise.inject.Vetoed; 23 | 24 | /** 25 | * @author Daniel 'soro' Cunha 26 | */ 27 | 28 | @Priority(1) 29 | @Vetoed 30 | public class ShortConverter implements Converter { 31 | 32 | public static final ShortConverter INSTANCE = new ShortConverter(); 33 | 34 | @Override 35 | public Short convert(String value) { 36 | return value != null ? Short.valueOf(value) : null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/StringConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.converters; 18 | 19 | import javax.annotation.Priority; 20 | import javax.enterprise.inject.Vetoed; 21 | 22 | import org.eclipse.microprofile.config.spi.Converter; 23 | 24 | /** 25 | * 1:1 string output. Just to make converter logic happy. 26 | * 27 | * @author Mark Struberg 28 | */ 29 | @Priority(1) 30 | @Vetoed 31 | public class StringConverter implements Converter { 32 | 33 | public static final StringConverter INSTANCE = new StringConverter(); 34 | 35 | @Override 36 | public String convert(String value) { 37 | return value; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /impl/src/main/java/org/apache/geronimo/config/converters/URLConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.converters; 18 | 19 | import org.eclipse.microprofile.config.spi.Converter; 20 | 21 | import javax.annotation.Priority; 22 | import javax.enterprise.inject.Vetoed; 23 | import java.net.MalformedURLException; 24 | import java.net.URL; 25 | 26 | @Vetoed 27 | @Priority(1) 28 | public class URLConverter implements Converter { 29 | public static final URLConverter INSTANCE = new URLConverter(); 30 | @Override 31 | public URL convert(String value) { 32 | try { 33 | return new URL(value); 34 | } catch (MalformedURLException e) { 35 | throw new IllegalArgumentException("Invalid url "+value,e); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /impl/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 19 | 20 | -------------------------------------------------------------------------------- /impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy current the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | org.apache.geronimo.config.cdi.ConfigExtension -------------------------------------------------------------------------------- /impl/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigProviderResolver: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy current the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | org.apache.geronimo.config.DefaultConfigProvider -------------------------------------------------------------------------------- /impl/src/test/java/org/apache/geronimo/config/test/GeronimoConfigArchiveProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.test; 18 | 19 | import org.apache.geronimo.config.ConfigImpl; 20 | import org.apache.geronimo.config.DefaultConfigProvider; 21 | import org.apache.geronimo.config.cdi.ConfigExtension; 22 | import org.apache.geronimo.config.configsource.BaseConfigSource; 23 | import org.apache.geronimo.config.converters.BooleanConverter; 24 | import org.eclipse.microprofile.config.spi.ConfigProviderResolver; 25 | import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor; 26 | import org.jboss.arquillian.test.spi.TestClass; 27 | import org.jboss.shrinkwrap.api.Archive; 28 | import org.jboss.shrinkwrap.api.ShrinkWrap; 29 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 30 | import org.jboss.shrinkwrap.api.spec.JavaArchive; 31 | import org.jboss.shrinkwrap.api.spec.WebArchive; 32 | 33 | /** 34 | * Adds the whole Config implementation classes and resources to the 35 | * Arqillian deployment archive. This is needed to have the container 36 | * pick up the beans from within the impl for the TCK tests. 37 | * 38 | * @author Mark Struberg 39 | */ 40 | public class GeronimoConfigArchiveProcessor implements ApplicationArchiveProcessor { 41 | 42 | @Override 43 | public void process(Archive applicationArchive, TestClass testClass) { 44 | if (applicationArchive instanceof WebArchive) { 45 | JavaArchive configJar = ShrinkWrap 46 | .create(JavaArchive.class, "geronimo-config-impl.jar") 47 | .addPackage(ConfigImpl.class.getPackage()) 48 | .addPackage(BooleanConverter.class.getPackage()) 49 | .addPackage(BaseConfigSource.class.getPackage()) 50 | .addPackage(ConfigExtension.class.getPackage()) 51 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml") 52 | .addAsServiceProvider(ConfigProviderResolver.class, DefaultConfigProvider.class); 53 | ((WebArchive) applicationArchive).addAsLibraries(configJar); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /impl/src/test/java/org/apache/geronimo/config/test/GeronimoConfigExtension.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.test; 18 | 19 | import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor; 20 | import org.jboss.arquillian.core.spi.LoadableExtension; 21 | 22 | /** 23 | * @author Mark Struberg 24 | */ 25 | public class GeronimoConfigExtension implements LoadableExtension { 26 | @Override 27 | public void register(ExtensionBuilder extensionBuilder) { 28 | extensionBuilder.service(ApplicationArchiveProcessor.class, GeronimoConfigArchiveProcessor.class); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /impl/src/test/java/org/apache/geronimo/config/test/internal/ArrayTypeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | package org.apache.geronimo.config.test.internal; 21 | 22 | import org.eclipse.microprofile.config.inject.ConfigProperty; 23 | import org.jboss.arquillian.container.test.api.Deployment; 24 | import org.jboss.arquillian.testng.Arquillian; 25 | import org.jboss.shrinkwrap.api.ShrinkWrap; 26 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 27 | import org.jboss.shrinkwrap.api.asset.StringAsset; 28 | import org.jboss.shrinkwrap.api.spec.JavaArchive; 29 | import org.jboss.shrinkwrap.api.spec.WebArchive; 30 | import org.testng.Assert; 31 | import org.testng.annotations.Test; 32 | 33 | import javax.enterprise.context.RequestScoped; 34 | import javax.inject.Inject; 35 | 36 | import java.util.LinkedHashSet; 37 | import java.util.List; 38 | import java.util.Set; 39 | 40 | import static java.util.Arrays.asList; 41 | 42 | public class ArrayTypeTest extends Arquillian { 43 | private static final String SOME_KEY = "org.apache.geronimo.config.test.internal.somekey"; 44 | private static final String SOME_OTHER_KEY = "org.apache.geronimo.config.test.internal.someotherkey"; 45 | 46 | @Deployment 47 | public static WebArchive deploy() { 48 | JavaArchive testJar = ShrinkWrap 49 | .create(JavaArchive.class, "arrayTest.jar") 50 | .addClasses(ArrayTypeTest.class, SomeBean.class) 51 | .addAsManifestResource(new StringAsset( 52 | SOME_KEY + "=1,2,3\n" + 53 | SOME_OTHER_KEY + "=1,2\\\\,3\n" + 54 | "placeholder=4,5,6\n" 55 | ), "microprofile-config.properties") 56 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); 57 | 58 | return ShrinkWrap 59 | .create(WebArchive.class, "arrayTest.war") 60 | .addAsLibrary(testJar); 61 | } 62 | 63 | @Inject 64 | private SomeBean someBean; 65 | 66 | @Test 67 | public void testArraySetListInjection() { 68 | Assert.assertEquals(someBean.getStringValue(), "1,2,3"); 69 | Assert.assertEquals(someBean.getMyconfig(), new int[]{1, 2, 3}); 70 | Assert.assertEquals(someBean.getIntValues(), asList(1, 2, 3)); 71 | Assert.assertEquals(someBean.getIntSet(), new LinkedHashSet<>(asList(1, 2, 3))); 72 | Assert.assertEquals(someBean.getIntSetDefault(), new LinkedHashSet<>(asList(1, 2, 3))); 73 | Assert.assertEquals(someBean.getIntSetPlaceholderDefault(), new LinkedHashSet<>(asList(4, 5, 6))); 74 | } 75 | 76 | @Test 77 | public void testListWithEscaping() { 78 | Assert.assertEquals(someBean.getValues(), asList("1", "2,3")); 79 | } 80 | 81 | @RequestScoped 82 | public static class SomeBean { 83 | 84 | @Inject 85 | @ConfigProperty(name = SOME_KEY) 86 | private int[] myconfig; 87 | 88 | @Inject 89 | @ConfigProperty(name = SOME_KEY) 90 | private List intValues; 91 | 92 | @Inject 93 | @ConfigProperty(name = SOME_KEY) 94 | private Set intSet; 95 | 96 | @Inject 97 | @ConfigProperty(name = SOME_KEY + ".missing", defaultValue = "1,2,3") 98 | private Set intSetDefault; 99 | 100 | @Inject 101 | @ConfigProperty(name = SOME_KEY + ".missing", defaultValue = "${placeholder}") 102 | private Set intSetPlaceholderDefault; 103 | 104 | @Inject 105 | @ConfigProperty(name = SOME_KEY) 106 | private String stringValue; 107 | 108 | @Inject 109 | @ConfigProperty(name = SOME_OTHER_KEY) 110 | private List values; 111 | 112 | public Set getIntSetPlaceholderDefault() { 113 | return intSetPlaceholderDefault; 114 | } 115 | 116 | public Set getIntSetDefault() { 117 | return intSetDefault; 118 | } 119 | 120 | public String getStringValue() { 121 | return stringValue; 122 | } 123 | 124 | public int[] getMyconfig() { 125 | return myconfig; 126 | } 127 | 128 | public List getIntValues() { 129 | return intValues; 130 | } 131 | 132 | public Set getIntSet() { 133 | return intSet; 134 | } 135 | 136 | public List getValues() { 137 | return values; 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /impl/src/test/java/org/apache/geronimo/config/test/internal/ConfigInjectionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.test.internal; 18 | 19 | import javax.inject.Inject; 20 | 21 | import org.eclipse.microprofile.config.Config; 22 | import org.jboss.arquillian.container.test.api.Deployment; 23 | import org.jboss.arquillian.testng.Arquillian; 24 | import org.jboss.shrinkwrap.api.ShrinkWrap; 25 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 26 | import org.jboss.shrinkwrap.api.spec.JavaArchive; 27 | import org.jboss.shrinkwrap.api.spec.WebArchive; 28 | import org.testng.Assert; 29 | import org.testng.annotations.Test; 30 | 31 | public class ConfigInjectionTest extends Arquillian { 32 | @Deployment 33 | public static WebArchive deploy() { 34 | JavaArchive testJar = ShrinkWrap 35 | .create(JavaArchive.class, "configProviderTest.jar") 36 | .addClasses(ConfigInjectionTest.class) 37 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); 38 | 39 | return ShrinkWrap 40 | .create(WebArchive.class, "providerTest.war") 41 | .addAsLibrary(testJar); 42 | } 43 | 44 | @Inject 45 | private Config config; 46 | 47 | @Test 48 | public void testConfigProvider() { 49 | Assert.assertNotNull(config); // is injected 50 | Assert.assertNotNull(config.getValue("java.version", String.class)); // is usable 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /impl/src/test/java/org/apache/geronimo/config/test/internal/DefaultNullValueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.geronimo.config.test.internal; 20 | 21 | import org.eclipse.microprofile.config.inject.ConfigProperty; 22 | import org.jboss.arquillian.container.test.api.Deployment; 23 | import org.jboss.arquillian.testng.Arquillian; 24 | import org.jboss.shrinkwrap.api.Archive; 25 | import org.jboss.shrinkwrap.api.ShrinkWrap; 26 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 27 | import org.jboss.shrinkwrap.api.spec.WebArchive; 28 | import org.testng.annotations.Test; 29 | 30 | import javax.enterprise.context.ApplicationScoped; 31 | import javax.inject.Inject; 32 | import java.net.URL; 33 | import java.time.Duration; 34 | import java.util.List; 35 | import java.util.Optional; 36 | 37 | import static org.testng.Assert.assertNull; 38 | 39 | /** 40 | * @author Daniel 'soro' Cunha 41 | */ 42 | public class DefaultNullValueTest extends Arquillian { 43 | @Deployment 44 | public static Archive archive() { 45 | return ShrinkWrap.create(WebArchive.class, DefaultNullValueTest.class.getSimpleName() + ".war") 46 | .addAsWebInfResource(EmptyAsset.INSTANCE, "classes/META-INF/beans.xml") 47 | .addClasses(DefaultNullValueTest.class, DefaultNullValueTest.Injected.class); 48 | } 49 | 50 | @Inject 51 | private Injected injected; 52 | 53 | @Test 54 | public void testDefaultNullValue() { 55 | assertNull(injected.getBooleanNullValue()); 56 | assertNull(injected.getStringNullValue()); 57 | assertNull(injected.getByteNullValue()); 58 | assertNull(injected.getIntegerNullValue()); 59 | assertNull(injected.getLongNullValue()); 60 | assertNull(injected.getShortNullValue()); 61 | assertNull(injected.getListNullValue()); 62 | assertNull(injected.getClassNullValue()); 63 | assertNull(injected.getDoubleNullValue()); 64 | assertNull(injected.getDurationNullValue()); 65 | } 66 | 67 | @ApplicationScoped 68 | public static class Injected { 69 | 70 | @Inject 71 | @ConfigProperty(name = "boolean.nullvalue.default") 72 | private Optional booleanNullValue; 73 | 74 | @Inject 75 | @ConfigProperty(name = "string.nullvalue.default") 76 | private Optional stringNullValue; 77 | 78 | @Inject 79 | @ConfigProperty(name = "long.nullvalue.default") 80 | private Optional longNullValue; 81 | 82 | @Inject 83 | @ConfigProperty(name = "integer.nullvalue.default") 84 | private Optional integerNullValue; 85 | 86 | @Inject 87 | @ConfigProperty(name = "float.nullvalue.default") 88 | private Optional floatNullValue; 89 | 90 | @Inject 91 | @ConfigProperty(name = "double.nullvalue.default") 92 | private Optional doubleNullValue; 93 | 94 | @Inject 95 | @ConfigProperty(name = "character.nullvalue.default") 96 | private Optional characterNullValue; 97 | 98 | @Inject 99 | @ConfigProperty(name = "short.nullvalue.default") 100 | private Optional shortNullValue; 101 | 102 | @Inject 103 | @ConfigProperty(name = "byte.nullvalue.default") 104 | private Optional byteNullValue; 105 | 106 | @Inject 107 | @ConfigProperty(name = "list.nullvalue.default") 108 | private Optional> listNullValue; 109 | 110 | @Inject 111 | @ConfigProperty(name = "class.nullvalue.default") 112 | private Optional classNullValue; 113 | 114 | @Inject 115 | @ConfigProperty(name = "url.nullvalue.default") 116 | private Optional urlNullValue; 117 | 118 | @Inject 119 | @ConfigProperty(name = "duration.nullvalue.default") 120 | private Optional durationNullValue; 121 | 122 | public Boolean getBooleanNullValue() { 123 | return booleanNullValue.orElse(null); 124 | } 125 | 126 | public String getStringNullValue() { 127 | return stringNullValue.orElse(null); 128 | } 129 | 130 | public Long getLongNullValue() { 131 | return longNullValue.orElse(null); 132 | } 133 | 134 | public Integer getIntegerNullValue() { 135 | return integerNullValue.orElse(null); 136 | } 137 | 138 | public Float getFloatNullValue() { 139 | return floatNullValue.orElse(null); 140 | } 141 | 142 | public Double getDoubleNullValue() { 143 | return doubleNullValue.orElse(null); 144 | } 145 | 146 | public Character getCharacterNullValue() { 147 | return characterNullValue.orElse(null); 148 | } 149 | 150 | public Short getShortNullValue() { 151 | return shortNullValue.orElse(null); 152 | } 153 | 154 | public Byte getByteNullValue() { 155 | return byteNullValue.orElse(null); 156 | } 157 | 158 | public List getListNullValue() { 159 | return listNullValue.orElse(null); 160 | } 161 | 162 | public Class getClassNullValue() { 163 | return classNullValue.orElse(null); 164 | } 165 | 166 | public URL getUrlNullValue() { 167 | return urlNullValue.orElse(null); 168 | } 169 | 170 | public Duration getDurationNullValue() { 171 | return durationNullValue.orElse(null); 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /impl/src/test/java/org/apache/geronimo/config/test/internal/PropertyFileConfigSourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.test.internal; 18 | 19 | import org.apache.geronimo.config.configsource.PropertyFileConfigSource; 20 | import org.testng.annotations.Test; 21 | 22 | import java.net.URL; 23 | import java.nio.file.Paths; 24 | 25 | import static org.testng.AssertJUnit.assertTrue; 26 | 27 | public class PropertyFileConfigSourceTest { 28 | @Test 29 | public void testLoadMissingFile() throws Exception{ 30 | URL url = Paths.get("some/missing/File.txt").toUri().toURL(); 31 | PropertyFileConfigSource propertyFileConfigSource = new PropertyFileConfigSource(url); 32 | assertTrue(propertyFileConfigSource.getProperties().isEmpty()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.test.internal; 18 | 19 | import java.util.Optional; 20 | 21 | import javax.enterprise.context.RequestScoped; 22 | import javax.inject.Inject; 23 | import javax.inject.Provider; 24 | 25 | import org.apache.geronimo.config.test.testng.SystemPropertiesLeakProtector; 26 | import org.eclipse.microprofile.config.inject.ConfigProperty; 27 | import org.jboss.arquillian.container.test.api.Deployment; 28 | import org.jboss.arquillian.testng.Arquillian; 29 | import org.jboss.shrinkwrap.api.ShrinkWrap; 30 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 31 | import org.jboss.shrinkwrap.api.asset.StringAsset; 32 | import org.jboss.shrinkwrap.api.spec.JavaArchive; 33 | import org.jboss.shrinkwrap.api.spec.WebArchive; 34 | import org.testng.Assert; 35 | import org.testng.annotations.Test; 36 | 37 | public class ProviderTest extends Arquillian { 38 | private static final String SOME_KEY = "org.apache.geronimo.config.test.internal.somekey"; 39 | 40 | @Deployment 41 | public static WebArchive deploy() { 42 | JavaArchive testJar = ShrinkWrap 43 | .create(JavaArchive.class, "configProviderTest.jar") 44 | .addClasses(ProviderTest.class, SomeBean.class) 45 | .addAsManifestResource( 46 | new StringAsset(SOME_KEY + "=someval\n"), 47 | "microprofile-config.properties") 48 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); 49 | 50 | return ShrinkWrap 51 | .create(WebArchive.class, "providerTest.war") 52 | .addAsLibrary(testJar); 53 | } 54 | 55 | private @Inject SomeBean someBean; 56 | 57 | 58 | @Test 59 | public void testConfigProvider() { 60 | final SystemPropertiesLeakProtector fixer = new SystemPropertiesLeakProtector(); // lazy way to reset all the system props manipulated by this test 61 | fixer.onStart(null); 62 | 63 | System.setProperty(SOME_KEY, "someval"); 64 | String myconfig = someBean.getMyconfig(); 65 | Assert.assertEquals(myconfig, "someval"); 66 | Assert.assertEquals(someBean.getOptionalProvider().get().get(), "someval"); 67 | Assert.assertEquals(someBean.getProviderOptional().get().get(), "someval"); 68 | 69 | System.setProperty(SOME_KEY, "otherval"); 70 | myconfig = someBean.getMyconfig(); 71 | Assert.assertEquals(myconfig, "otherval"); 72 | 73 | fixer.onFinish(null); 74 | } 75 | 76 | 77 | @RequestScoped 78 | public static class SomeBean { 79 | 80 | @Inject 81 | @ConfigProperty(name=SOME_KEY) 82 | private Provider myconfig; 83 | 84 | @Inject 85 | @ConfigProperty(name=SOME_KEY) 86 | private Optional> optionalProvider; 87 | 88 | @Inject 89 | @ConfigProperty(name=SOME_KEY) 90 | private Provider> providerOptional; 91 | 92 | public Optional> getOptionalProvider() { 93 | return optionalProvider; 94 | } 95 | 96 | public Provider> getProviderOptional() { 97 | return providerOptional; 98 | } 99 | 100 | public String getMyconfig() { 101 | return myconfig.get(); 102 | } 103 | 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /impl/src/test/java/org/apache/geronimo/config/test/internal/ProxyTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.test.internal; 18 | 19 | import static java.util.Arrays.asList; 20 | import static org.testng.Assert.assertEquals; 21 | import static org.testng.Assert.assertFalse; 22 | import static org.testng.Assert.assertNotNull; 23 | import static org.testng.Assert.assertNull; 24 | 25 | import java.net.URL; 26 | import java.time.Duration; 27 | import java.util.Collection; 28 | import java.util.List; 29 | 30 | import javax.inject.Inject; 31 | 32 | import org.eclipse.microprofile.config.inject.ConfigProperty; 33 | import org.jboss.arquillian.container.test.api.Deployment; 34 | import org.jboss.arquillian.testng.Arquillian; 35 | import org.jboss.shrinkwrap.api.ShrinkWrap; 36 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 37 | import org.jboss.shrinkwrap.api.asset.StringAsset; 38 | import org.jboss.shrinkwrap.api.spec.JavaArchive; 39 | import org.jboss.shrinkwrap.api.spec.WebArchive; 40 | import org.testng.annotations.Test; 41 | 42 | public class ProxyTest extends Arquillian { 43 | private static final String LIST_KEY = SomeProxy.class.getName() + ".list"; 44 | private static final String SOME_KEY = SomeProxy.class.getName() + ".key"; 45 | private static final String SOME_OTHER_KEY = SomeProxy.class.getName() + ".key2"; 46 | 47 | @Deployment 48 | public static WebArchive deploy() { 49 | JavaArchive testJar = ShrinkWrap 50 | .create(JavaArchive.class, "PoxyTest.jar") 51 | .addClasses(ProxyTest.class, SomeProxy.class, PrefixedSomeProxy.class) 52 | .addAsManifestResource( 53 | new StringAsset("" + 54 | "interpolated=a,${my_int_property},${MY_STRING_PROPERTY},${my.string.property}\n" + 55 | "list.interpolated=a,${my_int_property},${MY_STRING_PROPERTY},${my.string.property}\n" + 56 | "my.string.property=haha\n" + 57 | "prefix.val=yes\n" + 58 | LIST_KEY + "=a,b,1\n" + 59 | SOME_KEY + "=yeah\n" + 60 | SOME_OTHER_KEY + "=123\n" 61 | ), "microprofile-config.properties") 62 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); 63 | 64 | return ShrinkWrap 65 | .create(WebArchive.class, "providerTest.war") 66 | .addAsLibrary(testJar); 67 | } 68 | 69 | @Inject 70 | private PrefixedSomeProxy prefixed; 71 | 72 | @Inject 73 | private SomeProxy proxy; 74 | 75 | @Test 76 | public void test() { 77 | assertEquals(proxy.key(), "yeah"); 78 | assertEquals(proxy.renamed(), "yeah"); 79 | assertEquals(proxy.key2(), 123); 80 | assertEquals(proxy.key3(), "def"); 81 | assertEquals(proxy.list(), asList("a", "b", "1")); 82 | assertEquals(proxy.listDefaults(), asList(1, 2, 1)); 83 | assertEquals(proxy.listClasses(), asList(String.class, Integer.class)); 84 | 85 | assertNull(proxy.booleanNullValue()); 86 | assertNull(proxy.stringNullValue()); 87 | assertNull(proxy.byteNullValue()); 88 | assertNull(proxy.integerNullValue()); 89 | assertNull(proxy.longNullValue()); 90 | assertNull(proxy.shortNullValue()); 91 | assertNull(proxy.listNullValue()); 92 | assertNull(proxy.classNullValue()); 93 | assertNull(proxy.doubleNullValue()); 94 | assertNull(proxy.durationNullValue()); 95 | 96 | assertFalse(proxy.primitiveBooleanNullValue()); 97 | assertEquals(0, proxy.primitiveLongNullValue()); 98 | assertEquals(0, proxy.primitiveIntegerNullValue()); 99 | assertEquals(0, proxy.primitiveShortNullValue()); 100 | assertEquals(0, proxy.primitiveByteNullValue()); 101 | assertEquals(0.0F, proxy.primitiveFloatNullValue()); 102 | assertEquals(0.0D, proxy.primitiveDoubleNullValue()); 103 | assertEquals('\u0000', proxy.primitiveCharacterNullValue()); 104 | 105 | assertEquals(proxy.interpolated(), "a,45,woohoo,haha"); 106 | assertEquals(proxy.listInterpolatedValue(), asList("a", "45", "woohoo", "haha")); 107 | } 108 | 109 | @Test 110 | public void prefix() { 111 | assertEquals(prefixed.val(), "yes"); 112 | } 113 | 114 | @ConfigProperty(name = "prefix.") 115 | public interface PrefixedSomeProxy { 116 | @ConfigProperty(name = "val") 117 | String val(); 118 | } 119 | 120 | public interface SomeProxy { 121 | @ConfigProperty 122 | int key2(); 123 | 124 | @ConfigProperty(defaultValue = "def") 125 | String key3(); 126 | 127 | @ConfigProperty 128 | String key(); 129 | 130 | @ConfigProperty(name = "org.apache.geronimo.config.test.internal.ProxyTest$SomeProxy.key") 131 | String renamed(); 132 | 133 | @ConfigProperty 134 | Collection list(); 135 | 136 | @ConfigProperty(defaultValue = "java.lang.String,java.lang.Integer") 137 | Collection> listClasses(); 138 | 139 | @ConfigProperty(defaultValue = "1,2,1") 140 | Collection listDefaults(); 141 | 142 | @ConfigProperty(name = "boolean.nullvalue.default") 143 | Boolean booleanNullValue(); 144 | 145 | @ConfigProperty(name = "boolean.nullvalue.default") 146 | boolean primitiveBooleanNullValue(); 147 | 148 | @ConfigProperty(name = "string.nullvalue.default") 149 | String stringNullValue(); 150 | 151 | @ConfigProperty(name = "long.nullvalue.default") 152 | Long longNullValue(); 153 | 154 | @ConfigProperty(name = "long.nullvalue.default") 155 | long primitiveLongNullValue(); 156 | 157 | @ConfigProperty(name = "integer.nullvalue.default") 158 | Integer integerNullValue(); 159 | 160 | @ConfigProperty(name = "integer.nullvalue.default") 161 | int primitiveIntegerNullValue(); 162 | 163 | @ConfigProperty(name = "float.nullvalue.default") 164 | Float floatNullValue(); 165 | 166 | @ConfigProperty(name = "float.nullvalue.default") 167 | float primitiveFloatNullValue(); 168 | 169 | @ConfigProperty(name = "double.nullvalue.default") 170 | Double doubleNullValue(); 171 | 172 | @ConfigProperty(name = "double.nullvalue.default") 173 | double primitiveDoubleNullValue(); 174 | 175 | @ConfigProperty(name = "character.nullvalue.default") 176 | Character characterNullValue(); 177 | 178 | @ConfigProperty(name = "character.nullvalue.default") 179 | char primitiveCharacterNullValue(); 180 | 181 | @ConfigProperty(name = "short.nullvalue.default") 182 | Short shortNullValue(); 183 | 184 | @ConfigProperty(name = "short.nullvalue.default") 185 | short primitiveShortNullValue(); 186 | 187 | @ConfigProperty(name = "byte.nullvalue.default") 188 | Byte byteNullValue(); 189 | 190 | @ConfigProperty(name = "byte.nullvalue.default") 191 | byte primitiveByteNullValue(); 192 | 193 | @ConfigProperty(name = "list.nullvalue.default") 194 | List listNullValue(); 195 | 196 | @ConfigProperty(name = "list.interpolated") 197 | List listInterpolatedValue(); 198 | 199 | @ConfigProperty(name = "interpolated") 200 | String interpolated(); 201 | 202 | @ConfigProperty(name = "class.nullvalue.default") 203 | Class classNullValue(); 204 | 205 | @ConfigProperty(name = "url.nullvalue.default") 206 | URL urlNullValue(); 207 | 208 | @ConfigProperty(name = "duration.nullvalue.default") 209 | Duration durationNullValue(); 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /impl/src/test/java/org/apache/geronimo/config/test/internal/SupplierTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.geronimo.config.test.internal; 20 | 21 | import org.apache.geronimo.config.test.testng.SystemPropertiesLeakProtector; 22 | import org.eclipse.microprofile.config.inject.ConfigProperty; 23 | import org.jboss.arquillian.container.test.api.Deployment; 24 | import org.jboss.arquillian.testng.Arquillian; 25 | import org.jboss.shrinkwrap.api.ShrinkWrap; 26 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 27 | import org.jboss.shrinkwrap.api.asset.StringAsset; 28 | import org.jboss.shrinkwrap.api.spec.JavaArchive; 29 | import org.jboss.shrinkwrap.api.spec.WebArchive; 30 | import org.testng.Assert; 31 | import org.testng.annotations.Test; 32 | 33 | import javax.enterprise.context.RequestScoped; 34 | import javax.inject.Inject; 35 | import java.util.function.Supplier; 36 | 37 | public class SupplierTest extends Arquillian{ 38 | private static final String SOME_KEY = "org.apache.geronimo.config.test.internal.somekey"; 39 | private static final String SUPPLIER_DEFAULT_VALUE = "supplierDefaultValue"; 40 | private static final String SOME_INT_KEY = "some.supplier.int.key"; 41 | 42 | @Deployment 43 | public static WebArchive deploy() { 44 | JavaArchive testJar = ShrinkWrap 45 | .create(JavaArchive.class, "configSupplierTest.jar") 46 | .addClasses(SupplierTest.class, SomeBean.class) 47 | .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml") 48 | .addAsManifestResource( 49 | new StringAsset(SOME_KEY + "=someval\n"), 50 | "microprofile-config.properties") 51 | .as(JavaArchive.class); 52 | 53 | return ShrinkWrap 54 | .create(WebArchive.class, "supplierTest.war") 55 | .addAsLibrary(testJar); 56 | } 57 | 58 | private @Inject SomeBean someBean; 59 | 60 | 61 | @Test 62 | public void testConfigProvider() { 63 | final SystemPropertiesLeakProtector fixer = new SystemPropertiesLeakProtector(); // lazy way to reset all the system props manipulated by this test 64 | fixer.onStart(null); 65 | 66 | String someval = "someval"; 67 | System.setProperty(SOME_KEY, someval); 68 | String myconfig = someBean.getMyconfig(); 69 | Assert.assertEquals(myconfig, someval); 70 | 71 | String otherval = "otherval"; 72 | System.setProperty(SOME_KEY, otherval); 73 | myconfig = someBean.getMyconfig(); 74 | Assert.assertEquals(myconfig, otherval); 75 | 76 | Assert.assertEquals(someBean.getAnotherconfig().get(), SUPPLIER_DEFAULT_VALUE); 77 | 78 | System.setProperty(SOME_INT_KEY, "42"); 79 | Assert.assertEquals(someBean.getSomeInt(), 42); 80 | 81 | Assert.assertNull(someBean.getUndefinedValue().get()); 82 | fixer.onFinish(null); 83 | } 84 | 85 | @RequestScoped 86 | public static class SomeBean { 87 | 88 | @Inject 89 | @ConfigProperty(name=SOME_KEY) 90 | private Supplier myconfig; 91 | 92 | @Inject 93 | @ConfigProperty(name = SOME_INT_KEY) 94 | private Supplier someIntValue; 95 | 96 | @Inject 97 | @ConfigProperty(name="missing.key", defaultValue = SUPPLIER_DEFAULT_VALUE) 98 | private Supplier anotherconfig; 99 | 100 | @Inject 101 | @ConfigProperty(name = "UNDEFINED_VALUE") 102 | private Supplier undefinedValue; 103 | 104 | public int getSomeInt() { 105 | return someIntValue.get(); 106 | } 107 | 108 | public String getMyconfig() { 109 | return myconfig.get(); 110 | } 111 | 112 | public Supplier getAnotherconfig() { 113 | return anotherconfig; 114 | } 115 | 116 | public Supplier getUndefinedValue() { 117 | return undefinedValue; 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /impl/src/test/java/org/apache/geronimo/config/test/internal/SystemEnvConfigSourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.geronimo.config.test.internal; 20 | 21 | import org.eclipse.microprofile.config.Config; 22 | import org.eclipse.microprofile.config.ConfigProvider; 23 | import org.testng.Assert; 24 | import org.testng.annotations.Test; 25 | 26 | /** 27 | * This needs to have some ENV settings set up. 28 | * This is usually done via maven. 29 | * For running the test yourself you have to set the following environment properties: 30 | * 31 | * A_b_c=1 32 | * A_B_C=2 33 | * A_B_D=3 34 | * A_B_e=4 35 | */ 36 | public class SystemEnvConfigSourceTest { 37 | @Test 38 | public void testEnvReplacement() { 39 | Config config = ConfigProvider.getConfig(); 40 | 41 | Assert.assertEquals(config.getValue("A.b#c", Integer.class), Integer.valueOf(1)); 42 | 43 | Assert.assertEquals(config.getValue("a.b.c", Integer.class), Integer.valueOf(2)); 44 | 45 | Assert.assertEquals(config.getValue("a.b.d", Integer.class), Integer.valueOf(3)); 46 | 47 | Assert.assertEquals(config.getValue("a.b.e", Integer.class), Integer.valueOf(4)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /impl/src/test/java/org/apache/geronimo/config/test/internal/SystemPropertyConfigSourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | package org.apache.geronimo.config.test.internal; 20 | 21 | import static org.testng.Assert.assertTrue; 22 | 23 | import javax.enterprise.context.ApplicationScoped; 24 | import javax.enterprise.event.Observes; 25 | import javax.enterprise.inject.spi.AfterBeanDiscovery; 26 | import javax.enterprise.inject.spi.BeforeBeanDiscovery; 27 | import javax.enterprise.inject.spi.BeforeShutdown; 28 | import javax.enterprise.inject.spi.Extension; 29 | import javax.inject.Inject; 30 | 31 | import org.eclipse.microprofile.config.Config; 32 | import org.eclipse.microprofile.config.ConfigProvider; 33 | import org.eclipse.microprofile.config.inject.ConfigProperty; 34 | import org.jboss.arquillian.container.test.api.Deployment; 35 | import org.jboss.arquillian.testng.Arquillian; 36 | import org.jboss.shrinkwrap.api.Archive; 37 | import org.jboss.shrinkwrap.api.ShrinkWrap; 38 | import org.jboss.shrinkwrap.api.asset.EmptyAsset; 39 | import org.jboss.shrinkwrap.api.spec.WebArchive; 40 | import org.testng.Assert; 41 | import org.testng.annotations.Test; 42 | 43 | /** 44 | * It is important to ensure the config is reloaded before going live in case some 45 | * system properties are set during the starting extension lifecycle. 46 | */ 47 | public class SystemPropertyConfigSourceTest extends Arquillian { 48 | @Deployment 49 | public static Archive archive() { 50 | return ShrinkWrap.create(WebArchive.class, SystemPropertyConfigSourceTest.class.getSimpleName() + ".war") 51 | .addAsWebInfResource(EmptyAsset.INSTANCE, "classes/META-INF/beans.xml") 52 | .addAsServiceProvider(Extension.class, InitInExtension.class) 53 | .addClasses(SystemPropertyConfigSourceTest.class, Injected.class); 54 | } 55 | 56 | @Inject 57 | private Injected injected; 58 | 59 | @Test 60 | public void testSystemPropsLoadedExtensionValue() { 61 | assertTrue(injected.getSet()); 62 | } 63 | 64 | @ApplicationScoped 65 | public static class Injected { 66 | @Inject 67 | @ConfigProperty(name = "org.apache.geronimo.config.test.internal.SystemPropertyConfigSourceTest$InitInExtension") 68 | private Boolean set; 69 | 70 | public Boolean getSet() { 71 | return set; 72 | } 73 | } 74 | 75 | public static class InitInExtension implements Extension { 76 | private String originalCopy; 77 | 78 | void eagerInit(@Observes final BeforeBeanDiscovery beforeBeanDiscovery) { 79 | originalCopy = System.getProperty("org.apache.geronimo.config.configsource.SystemPropertyConfigSource.copy"); 80 | // enfore the default, it is overriden for surefire 81 | System.setProperty("org.apache.geronimo.config.configsource.SystemPropertyConfigSource.copy", "true"); 82 | 83 | // eager load -> loads system props and copy 84 | ConfigProvider.getConfig(); 85 | } 86 | 87 | // before validation to ensure config validation passes 88 | void afterBeanDiscovery(@Observes final AfterBeanDiscovery afterBeanDiscovery) { 89 | // with copy this should get ignored but we will reload it before the validation 90 | System.setProperty(InitInExtension.class.getName(), "true"); 91 | } 92 | 93 | void beforeShutdown(@Observes final BeforeShutdown beforeShutdown) { 94 | System.clearProperty(InitInExtension.class.getName()); 95 | if (originalCopy != null) { 96 | System.setProperty("org.apache.geronimo.config.configsource.SystemPropertyConfigSource.copy", originalCopy); 97 | } else { 98 | System.clearProperty("org.apache.geronimo.config.configsource.SystemPropertyConfigSource.copy"); 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /impl/src/test/java/org/apache/geronimo/config/test/testng/SystemPropertiesLeakProtector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.geronimo.config.test.testng; 18 | 19 | import org.testng.ITestContext; 20 | import org.testng.TestListenerAdapter; 21 | 22 | import java.util.Properties; 23 | 24 | public class SystemPropertiesLeakProtector extends TestListenerAdapter { 25 | private Properties props; 26 | 27 | @Override 28 | public void onStart(final ITestContext context) { 29 | props = new Properties(); 30 | props.putAll(System.getProperties()); 31 | props.put("org.apache.geronimo.config.configsource.SystemPropertyConfigSource.copy", "false"); 32 | } 33 | 34 | @Override 35 | public void onFinish(final ITestContext testContext) { 36 | System.getProperties().clear(); // keep the same ref 37 | System.getProperties().putAll(props); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /impl/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy current the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | 21 | org.apache.geronimo.config.test.GeronimoConfigExtension -------------------------------------------------------------------------------- /impl/tck-suite.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 4.0.0 22 | 23 | 24 | org.apache 25 | apache 26 | 18 27 | 28 | 29 | org.apache.geronimo.config 30 | geronimo-config 31 | 1.2.4-SNAPSHOT 32 | pom 33 | Geronimo Microprofile Configuration 34 | 35 | 36 | 37 | Apache License, Version 2.0 38 | https://www.apache.org/licenses/LICENSE-2.0.txt 39 | repo 40 | 41 | 42 | 43 | 44 | scm:git:https://gitbox.apache.org/repos/asf/geronimo-config.git 45 | scm:git:https://gitbox.apache.org/repos/asf/geronimo-config.git 46 | https://gitbox.apache.org/repos/asf/geronimo-config.git 47 | HEAD 48 | 49 | 50 | 51 | 52 | 1.8 53 | 1.8 54 | 1.4 55 | 1.1.14.Final 56 | 2.0.0.Final 57 | 5.0.1 58 | 59 | 60 | 1.7.5 61 | 2.0.20 62 | 63 | 64 | 2.0 65 | 3.0.1.Final 66 | 67 | 68 | 69 | 70 | impl 71 | 72 | 73 | 74 | 75 | 76 | 77 | org.apache.maven.plugins 78 | maven-release-plugin 79 | 80 | false 81 | true 82 | true 83 | clean install 84 | 85 | 86 | 87 | 88 | org.apache.rat 89 | apache-rat-plugin 90 | 0.12 91 | 92 | 93 | rat-check 94 | check 95 | 96 | 97 | 98 | 99 | .travis.yml.* 100 | *.log 101 | 102 | 103 | 104 | 105 | org.apache.maven.plugins 106 | maven-enforcer-plugin 107 | 1.4.1 108 | 109 | 110 | enforce-versions 111 | 112 | enforce 113 | 114 | 115 | 116 | 117 | 3.1.0 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | org.apache.maven.plugins 126 | maven-shade-plugin 127 | 3.2.4 128 | 129 | 130 | package 131 | 132 | shade 133 | 134 | 135 | true 136 | jakarta 137 | false 138 | 139 | 140 | 141 | 142 | 143 | ${project.groupId}:${project.artifactId} 144 | 145 | 146 | 147 | 148 | javax.annotation 149 | jakarta.annotation 150 | 151 | javax.annotation.processing.** 152 | 153 | 154 | 155 | javax.enterprise 156 | jakarta.enterprise 157 | 158 | javax.enterprise.deploy.** 159 | 160 | 161 | 162 | javax.inject 163 | jakarta.inject 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | --------------------------------------------------------------------------------