diff --git a/.gitignore b/.gitignore
index b0bb852..9a03c6e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
#Idea Files
.idea
*.iml
+*.ipr
*.class
target
@@ -9,3 +10,8 @@ target
*.jar
*.war
*.ear
+
+#Eclipse files
+.project
+.settings
+.classpath
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
index 59d1de1..249422f 100644
--- a/README.md
+++ b/README.md
@@ -5,12 +5,14 @@
* [Project Structure](#project-structure)
* [Property File Creation](#property-file-creation)
* [Property Class Creation](#property-class-creation)
- * [Property Class Initialisation](#property-class-initialisation)
+ * [Property Class Initialization](#property-class-initialiszation)
* [System Properties Overriding](#system-properties-overriding)
* [Properties Priorities](#properties-priority)
+ * [Create Multi File Configuration][create-multi-file-configuration]
+ * [Own Property-Provider][creation-custom-property-provider]
* [Property Loader Extension](#property-loader-extension)
* [Conversion Data Types](#conversion-data-types)
- * [Creating Specific Converter][creation-specific-converter]
+ * [Creating Specific Converter][creation-custom-converter]
В тестах часто приходится работать с переменными окружения. Причем в зависимости от этих переменных поведение тестов
может меняться. Для работы с properties-файлами мы разработали несложную обертку.
@@ -24,7 +26,7 @@
ru.yandex.qatools.propertiesproperties-loader
- 1.3-SNAPSHOT
+ 1.4
```
@@ -109,7 +111,7 @@ public class ProxyProperties {
}
```
-### Property Class Initialisation
+### Property Class Initialization
В конструкторе класса `ProxyProperties` вызывается статический метод `PropertyLoader.populate(this)`,
который инициализирует поля класса из файла `proxy.properties`
@@ -142,6 +144,22 @@ assertThat(proxyProperties.getHost(), equatlTo(3133));
- значения переменных из property-файла. Средний приоритет.
- объявленные значения переменных. Наименьший приоритет.
+Если по какой-то причине вам не нравится существующий приоритет или принцип инициалиции объектов,
+то вы можете переопределить его следуя примеру [Загрузка кофигураций в зависимости от окружения (частный метод)][create-multi-file-configuration]
+или воспользовавшись мануалом по созданию [Cобственного загрузчика пропертей][creation-custom-property-provider].
+
+Уже доступен провайдер, позволяющий превращать пути вида
+```java
+@Resource.Classpath("${system.file.name}.path.${map.scope.value}.properties")
+```
+в реальные пути. Подключить его можно аннотацией
+
+```java
+@With(MapOrSyspropPathReplacerProvider.class)
+```
+Подробнее по применению в [тесте][custom-provider-test]
+
+
## Property Loader Extension
### Conversion Data Types
@@ -186,6 +204,9 @@ private URI aURI;
Если вам по какой-то причине не хватает этих типов, то вы всегда можете сделать и использовать свой конвертер.
О том, как это можно использовать нужно почтитать в статье
-["Создание собственного конвертера"][creation-specific-converter]
+["Создание собственного конвертера"][creation-custom-converter]
-[creation-specific-converter]: https://github.com/yandex-qatools/properties/blob/master/properties-loader/src/site/creation-specific-converter.ru.md
+[custom-provider-test]: https://github.com/yandex-qatools/properties/blob/master/properties-loader/src/test/java/ru/yandex/qatools/properties/CustomPropertyProviderTest.java
+[creation-custom-converter]: https://github.com/yandex-qatools/properties/blob/master/properties-loader/src/site/creation-custom-converter.ru.md
+[create-multi-file-configuration]: https://github.com/yandex-qatools/properties/blob/master/properties-loader/src/site/create-multi-file-configuration.ru.md
+[creation-custom-property-provider]: https://github.com/yandex-qatools/properties/blob/master/properties-loader/src/site/creation-custom-property-provider.ru.md
diff --git a/pom.xml b/pom.xml
index 5afab30..9e66358 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,6 +1,5 @@
-
+4.0.0
@@ -11,7 +10,7 @@
ru.yandex.qatools.propertiesproperties
- 1.3-SNAPSHOT
+ 1.5-SNAPSHOTYandex
@@ -45,7 +44,7 @@
https://github.com/yandex-qatools/propertiesscm:git:git@github.com:yandex-qatools/properties.git
- scm:git:git@github.com:yandex-qatools/proeprties.git
+ scm:git:git@github.com:yandex-qatools/properties.git
@@ -60,54 +59,26 @@
eroshenkoam@yandex-team.ruYandex
+
+ lanwen
+ Merkushev Kirill
+ lanwen@yandex-team.ru
+ Yandex
+
-
- org.apache.maven.plugins
- maven-release-plugin
- 2.4
-
- true
-
- org.apache.maven.pluginsmaven-compiler-plugin2.5.1
- 1.6
- 1.6
+ 1.7
+ 1.7
-
- org.apache.maven.plugins
- maven-source-plugin
- 2.2
-
-
- attach-sources
-
- jar
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 2.7
-
-
- aggregate
-
- aggregate-jar
-
-
-
-
-
\ No newline at end of file
+
diff --git a/properties-loader/pom.xml b/properties-loader/pom.xml
index 76a06fc..9e5f8b0 100644
--- a/properties-loader/pom.xml
+++ b/properties-loader/pom.xml
@@ -1,10 +1,9 @@
-
+propertiesru.yandex.qatools.properties
- 1.3-SNAPSHOT
+ 1.5-SNAPSHOT4.0.0
diff --git a/properties-loader/releasenotes/1.4-releasenotes.ru.md b/properties-loader/releasenotes/1.4-releasenotes.ru.md
new file mode 100644
index 0000000..f272082
--- /dev/null
+++ b/properties-loader/releasenotes/1.4-releasenotes.ru.md
@@ -0,0 +1,17 @@
+# 1.4 Release Notes
+
+## [Pull Req #5](https://github.com/yandex-qatools/properties/pull/5) Use property provider to provide interface for load props
+Теперь, можно легко переопределить последовательность наполнения бина значениями переменных окружения.
+
+~~~ java
+@Resource.Classpath("file.${system.scope.value}.properties")
+@With(SyspropPathReplacerProvider.class)
+public class UseSystemReplacerProviderProperty {
+...
+~~~
+
+[Подробнее](https://github.com/yandex-qatools/properties/blob/master/properties-loader/src/site/creation-custom-property-provider.ru.md)
+
+## [Pull Req #12](https://github.com/yandex-qatools/properties/pull/12) Update java verison to 1.7
+
+Теперь используемая версия java в проекте - **1.7**
\ No newline at end of file
diff --git a/properties-loader/src/main/java/ru/yandex/qatools/properties/PropertyLoader.java b/properties-loader/src/main/java/ru/yandex/qatools/properties/PropertyLoader.java
index de7cc77..9010864 100644
--- a/properties-loader/src/main/java/ru/yandex/qatools/properties/PropertyLoader.java
+++ b/properties-loader/src/main/java/ru/yandex/qatools/properties/PropertyLoader.java
@@ -1,14 +1,15 @@
package ru.yandex.qatools.properties;
-import ru.yandex.qatools.properties.annotations.Resource;
+import ru.yandex.qatools.properties.annotations.With;
import ru.yandex.qatools.properties.decorators.DefaultFieldDecorator;
import ru.yandex.qatools.properties.decorators.FieldDecorator;
+import ru.yandex.qatools.properties.exeptions.PropertyLoaderException;
+import ru.yandex.qatools.properties.providers.DefaultPropertyProvider;
+import ru.yandex.qatools.properties.providers.PropertyProvider;
import java.lang.reflect.Field;
import java.util.Properties;
-import static ru.yandex.qatools.properties.utils.PropertiesUtils.readProperties;
-
/**
* User: eroshenkoam
* Date: 11/13/12, 12:53 PM
@@ -19,11 +20,13 @@ private PropertyLoader() {
}
public static void populate(T bean) {
- populate(bean, loadProperties(bean.getClass()));
+ populate(bean, new Properties());
}
public static void populate(T bean, Properties properties) {
- populate(bean, new DefaultFieldDecorator(properties));
+ PropertyProvider provider = instantiatePropertyProvider(bean);
+ Properties completed = provider.provide(bean, properties);
+ populate(bean, new DefaultFieldDecorator(completed));
}
public static void populate(T bean, FieldDecorator decorator) {
@@ -43,26 +46,28 @@ private static void initFields(FieldDecorator decorator, Object bean, Class> c
field.setAccessible(true);
field.set(bean, value);
} catch (IllegalAccessException e) {
- throw new RuntimeException(e);
+ throw new PropertyLoaderException(
+ String.format("Can not set bean <%s> field <%s> value", bean, field),
+ e);
}
}
}
}
- private static Properties loadProperties(Class> clazz) {
- Properties result = new Properties();
- if (clazz.isAnnotationPresent(Resource.Classpath.class)) {
- String path = clazz.getAnnotation(Resource.Classpath.class).value();
- result.putAll(readProperties(ClassLoader.getSystemResourceAsStream(path)));
- }
-
- if (clazz.isAnnotationPresent(Resource.File.class)) {
- String path = clazz.getAnnotation(Resource.File.class).value();
- result.putAll(readProperties(new java.io.File(path)));
+ private static PropertyProvider instantiatePropertyProvider(T bean) {
+ Class> clazz = bean.getClass();
+ if (clazz.isAnnotationPresent(With.class)) {
+ try {
+ return clazz.getAnnotation(With.class).value().newInstance();
+ } catch (InstantiationException e) {
+ throw new PropertyLoaderException("Can't create instance property provider in class "
+ + bean.getClass().getName(), e);
+ } catch (IllegalAccessException e) {
+ throw new PropertyLoaderException("Can't load property provider in class "
+ + bean.getClass().getName(), e);
+ }
}
-
- result.putAll(System.getProperties());
- return result;
+ return new DefaultPropertyProvider();
}
diff --git a/properties-loader/src/main/java/ru/yandex/qatools/properties/annotations/Property.java b/properties-loader/src/main/java/ru/yandex/qatools/properties/annotations/Property.java
index 5816658..b3b1675 100644
--- a/properties-loader/src/main/java/ru/yandex/qatools/properties/annotations/Property.java
+++ b/properties-loader/src/main/java/ru/yandex/qatools/properties/annotations/Property.java
@@ -11,5 +11,5 @@
@Target({java.lang.annotation.ElementType.FIELD})
public @interface Property {
- public String value();
+ String value();
}
diff --git a/properties-loader/src/main/java/ru/yandex/qatools/properties/annotations/Use.java b/properties-loader/src/main/java/ru/yandex/qatools/properties/annotations/Use.java
index 733dfef..f81332f 100644
--- a/properties-loader/src/main/java/ru/yandex/qatools/properties/annotations/Use.java
+++ b/properties-loader/src/main/java/ru/yandex/qatools/properties/annotations/Use.java
@@ -13,5 +13,5 @@
@Target({java.lang.annotation.ElementType.FIELD})
public @interface Use {
- public Class extends Converter> value();
+ Class extends Converter> value();
}
diff --git a/properties-loader/src/main/java/ru/yandex/qatools/properties/annotations/With.java b/properties-loader/src/main/java/ru/yandex/qatools/properties/annotations/With.java
new file mode 100644
index 0000000..3548202
--- /dev/null
+++ b/properties-loader/src/main/java/ru/yandex/qatools/properties/annotations/With.java
@@ -0,0 +1,18 @@
+package ru.yandex.qatools.properties.annotations;
+
+import ru.yandex.qatools.properties.providers.PropertyProvider;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * User: lanwen
+ * Date: 17.07.13
+ * Time: 17:28
+ */
+@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface With {
+ Class extends PropertyProvider> value();
+}
diff --git a/properties-loader/src/main/java/ru/yandex/qatools/properties/converters/URIConverter.java b/properties-loader/src/main/java/ru/yandex/qatools/properties/converters/URIConverter.java
index 94364ac..8ff0d82 100644
--- a/properties-loader/src/main/java/ru/yandex/qatools/properties/converters/URIConverter.java
+++ b/properties-loader/src/main/java/ru/yandex/qatools/properties/converters/URIConverter.java
@@ -11,7 +11,7 @@
public class URIConverter extends AbstractConverter {
@Override
- protected Object convertToType(Class aClass, Object o) throws Throwable {
+ protected Object convertToType(Class aClass, Object o) {
return URI.create(o.toString());
}
diff --git a/properties-loader/src/main/java/ru/yandex/qatools/properties/decorators/DefaultFieldDecorator.java b/properties-loader/src/main/java/ru/yandex/qatools/properties/decorators/DefaultFieldDecorator.java
index f3d94b1..ac11108 100644
--- a/properties-loader/src/main/java/ru/yandex/qatools/properties/decorators/DefaultFieldDecorator.java
+++ b/properties-loader/src/main/java/ru/yandex/qatools/properties/decorators/DefaultFieldDecorator.java
@@ -53,7 +53,6 @@ public Object decorate(Field field) {
try {
return converter.convert(field.getType(), properties.getProperty(key));
} catch (ConversionException e) {
- System.out.println(e);
return null;
}
}
@@ -70,7 +69,7 @@ private Converter createNewInstanceFromUseAnnotations(Field field) {
try {
return field.getAnnotation(Use.class).value().newInstance();
} catch (Exception e) {
- throw new RuntimeException(e);
+ return null;
}
}
}
diff --git a/properties-loader/src/main/java/ru/yandex/qatools/properties/decorators/FieldDecorator.java b/properties-loader/src/main/java/ru/yandex/qatools/properties/decorators/FieldDecorator.java
index a857ae7..97ad81c 100644
--- a/properties-loader/src/main/java/ru/yandex/qatools/properties/decorators/FieldDecorator.java
+++ b/properties-loader/src/main/java/ru/yandex/qatools/properties/decorators/FieldDecorator.java
@@ -1,7 +1,6 @@
package ru.yandex.qatools.properties.decorators;
import java.lang.reflect.Field;
-import java.util.Properties;
/**
* User: eroshenkoam
@@ -9,5 +8,5 @@
*/
public interface FieldDecorator {
- public Object decorate(Field field);
+ Object decorate(Field field);
}
diff --git a/properties-loader/src/main/java/ru/yandex/qatools/properties/exeptions/PropertyLoaderException.java b/properties-loader/src/main/java/ru/yandex/qatools/properties/exeptions/PropertyLoaderException.java
new file mode 100644
index 0000000..21a8897
--- /dev/null
+++ b/properties-loader/src/main/java/ru/yandex/qatools/properties/exeptions/PropertyLoaderException.java
@@ -0,0 +1,12 @@
+package ru.yandex.qatools.properties.exeptions;
+
+/**
+ * @author Artem Eroshenko eroshenkoam
+ * 5/31/13, 7:03 PM
+ */
+public class PropertyLoaderException extends RuntimeException {
+
+ public PropertyLoaderException(String message, Throwable e) {
+ super(message, e);
+ }
+}
diff --git a/properties-loader/src/main/java/ru/yandex/qatools/properties/providers/DefaultPropertyProvider.java b/properties-loader/src/main/java/ru/yandex/qatools/properties/providers/DefaultPropertyProvider.java
new file mode 100644
index 0000000..a5c0ada
--- /dev/null
+++ b/properties-loader/src/main/java/ru/yandex/qatools/properties/providers/DefaultPropertyProvider.java
@@ -0,0 +1,61 @@
+package ru.yandex.qatools.properties.providers;
+
+import ru.yandex.qatools.properties.annotations.Resource;
+
+import java.lang.annotation.Annotation;
+import java.util.Properties;
+
+import static ru.yandex.qatools.properties.utils.PropertiesUtils.readProperties;
+
+
+/**
+ * User: lanwen
+ * Date: 17.07.13
+ * Time: 17:28
+ */
+public class DefaultPropertyProvider implements PropertyProvider {
+ @Override
+ public Properties provide(T bean, Properties properties) {
+ Class> clazz = bean.getClass();
+
+ if (have(clazz, Resource.Classpath.class)) {
+ String path = classpath(clazz, properties);
+ properties.putAll(readProperties(getClassLoader().getSystemResourceAsStream(path)));
+ }
+
+ if (have(clazz, Resource.File.class)) {
+ String path = filepath(clazz, properties);
+ properties.putAll(readProperties(new java.io.File(path)));
+ }
+
+ properties.putAll(System.getProperties());
+ return properties;
+ }
+
+
+ protected boolean have(Class> clazz, Class extends Annotation> anno) {
+ return clazz.isAnnotationPresent(anno);
+ }
+
+ protected String filepath(Class> clazz, Properties properties) {
+ return clazz.getAnnotation(Resource.File.class).value();
+ }
+
+ protected String classpath(Class> clazz, Properties properties) {
+ return clazz.getAnnotation(Resource.Classpath.class).value();
+ }
+
+ private ClassLoader getClassLoader() {
+ ClassLoader classLoader = null;
+ try {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ } catch (SecurityException e) {
+ // do nothing
+ } finally {
+ if (classLoader == null) {
+ return ClassLoader.getSystemClassLoader();
+ }
+ return classLoader;
+ }
+ }
+}
diff --git a/properties-loader/src/main/java/ru/yandex/qatools/properties/providers/MapOrSyspropPathReplacerProvider.java b/properties-loader/src/main/java/ru/yandex/qatools/properties/providers/MapOrSyspropPathReplacerProvider.java
new file mode 100644
index 0000000..4a1e38b
--- /dev/null
+++ b/properties-loader/src/main/java/ru/yandex/qatools/properties/providers/MapOrSyspropPathReplacerProvider.java
@@ -0,0 +1,47 @@
+package ru.yandex.qatools.properties.providers;
+
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * User: lanwen
+ * Date: 17.07.13
+ * Time: 19:58
+ */
+public class MapOrSyspropPathReplacerProvider extends DefaultPropertyProvider {
+ public static final String MAP_PROP_KEY_PATTERN = "\\$\\{map\\.([^\\}]*)\\}";
+ public static final String SYS_PROP_KEY_PATTERN = "\\$\\{system\\.([^\\}]*)\\}";
+
+ @Override
+ public String filepath(Class> clazz, Properties properties) {
+ String filepath = super.filepath(clazz, properties);
+ String mapreplaced = replaceWithMapProps(filepath, properties);
+ return replaceWithSystemProps(mapreplaced);
+ }
+
+ @Override
+ public String classpath(Class> clazz, Properties properties) {
+ String classpath = super.classpath(clazz, properties);
+ String mapreplaced = replaceWithMapProps(classpath, properties);
+ return replaceWithSystemProps(mapreplaced);
+ }
+
+ private String replaceWithMapProps(String path, Properties properties) {
+ Matcher matcher = Pattern.compile(MAP_PROP_KEY_PATTERN).matcher(path);
+ String replaced = path;
+ while (matcher.find()) {
+ replaced = replaced.replace(matcher.group(0), properties.getProperty(matcher.group(1), ""));
+ }
+ return replaced;
+ }
+
+ private String replaceWithSystemProps(String path) {
+ Matcher matcher = Pattern.compile(SYS_PROP_KEY_PATTERN).matcher(path);
+ String replaced = path;
+ while (matcher.find()) {
+ replaced = replaced.replace(matcher.group(0), System.getProperty(matcher.group(1), ""));
+ }
+ return replaced;
+ }
+}
diff --git a/properties-loader/src/main/java/ru/yandex/qatools/properties/providers/PropertyProvider.java b/properties-loader/src/main/java/ru/yandex/qatools/properties/providers/PropertyProvider.java
new file mode 100644
index 0000000..99b6f6b
--- /dev/null
+++ b/properties-loader/src/main/java/ru/yandex/qatools/properties/providers/PropertyProvider.java
@@ -0,0 +1,12 @@
+package ru.yandex.qatools.properties.providers;
+
+import java.util.Properties;
+
+/**
+ * User: lanwen
+ * Date: 17.07.13
+ * Time: 15:45
+ */
+public interface PropertyProvider {
+ Properties provide(T bean, Properties properties);
+}
diff --git a/properties-loader/src/main/java/ru/yandex/qatools/properties/utils/PropertiesUtils.java b/properties-loader/src/main/java/ru/yandex/qatools/properties/utils/PropertiesUtils.java
index 83cc8f2..64ea5ea 100644
--- a/properties-loader/src/main/java/ru/yandex/qatools/properties/utils/PropertiesUtils.java
+++ b/properties-loader/src/main/java/ru/yandex/qatools/properties/utils/PropertiesUtils.java
@@ -1,6 +1,7 @@
package ru.yandex.qatools.properties.utils;
import java.io.*;
+import java.nio.charset.Charset;
import java.util.Properties;
/**
@@ -24,7 +25,7 @@ public static Properties readProperties(InputStream inputStream) {
if (inputStream == null) {
return new Properties();
} else {
- return readProperties(new InputStreamReader(inputStream));
+ return readProperties(new InputStreamReader(inputStream, Charset.defaultCharset()));
}
}
diff --git a/properties-loader/src/site/create-multi-file-configuration.ru.md b/properties-loader/src/site/create-multi-file-configuration.ru.md
new file mode 100644
index 0000000..47bdf9a
--- /dev/null
+++ b/properties-loader/src/site/create-multi-file-configuration.ru.md
@@ -0,0 +1,63 @@
+# Загрузка кофигураций в зависимости от окружения
+
+Иногда необходимо подключать различные файлы конфигураций для тестирования на разных тестовых средах.
+Допустим нам нужны разные пользователи для авторизации в тестах.
+
+Создадим проперти-файл для тестового окружения 'testing.properties':
+```properties
+user = Ivan
+password = chelovek-divan
+```
+и для предпродакшн окружения 'preprod.properties':
+```properties
+user = Oleg
+password = chelovek-strateg
+```
+
+Создадим класс-обёртку, работающий с этими данными:
+```java
+public class UserProperties {
+ @Property("user")
+ private String user = "defaultUser";
+
+ @Property("password")
+ private String password = "defaultPassword";
+}
+```
+
+Для того, чтобы проперти автоматически подгружались при создании этого класса, нужно добавить конструктор:
+```java
+ public UserProperties() {
+ PropertyLoader.populate(this);
+ }
+```
+
+Осталось научить наш класс работать с разными файлами. Загружать проперти из одного файла очень просто - достаточно
+добавить аннотацию @Resource.Classpath в которой указать имя этого файла:
+```java
+@Resource.Classpath("testing.properties")
+public class UserProperties {
+```
+
+Метод PropertyLoader.populate может принимать на вход Properties, которыми нужно заполнить наш бин. По дефолту,
+PropertyLoader ищет аннотации @Resource.Classpath, @Resource.File, а так же считывает свойства из переменных окружения.
+Нам остётся написать метод, который будет возвращать Properties, считаный из нужного нам файла:
+```java
+ private static Properties loadProperties() {
+ Properties result = new Properties();
+ String filePath = System.getProperty("property.file");
+ if (filePath != null) {
+ result.putAll(readProperties(ClassLoader.getSystemResourceAsStream(filePath)));
+ }
+ return result;
+ }
+```
+
+и передать этот метод в загрузчик в конструкторе нашего класса:
+```java
+ public UserProperties() {
+ PropertyLoader.populate(this, loadProperties());
+ }
+```
+
+Полный пример реализации можно посмотреть в тесте LoadPropertiesDependsOnSystemPropertyTest.
diff --git a/properties-loader/src/site/creation-specific-converter.ru.md b/properties-loader/src/site/creation-custom-converter.ru.md
similarity index 95%
rename from properties-loader/src/site/creation-specific-converter.ru.md
rename to properties-loader/src/site/creation-custom-converter.ru.md
index 4e22a34..f366594 100644
--- a/properties-loader/src/site/creation-specific-converter.ru.md
+++ b/properties-loader/src/site/creation-custom-converter.ru.md
@@ -37,7 +37,7 @@ public class ServersProperties {
```
Если попробовать инициализировать этот класс, то вы увидите эксепшен. Чтобы использование списка стало возможным,
-необходимо зарегистрировать создать свой конвертер и зарегистрировать его.
+необходимо создать свой конвертер и зарегистрировать его.
## Имплементация интерфейса org.apache.commons.beanutils.Converter
@@ -89,4 +89,4 @@ public class ServersProperties {
}
```
-Таким образом можно переопределять существующие конвертеры и добавлять новые.
\ No newline at end of file
+Таким образом можно переопределять существующие конвертеры и добавлять новые.
diff --git a/properties-loader/src/site/creation-custom-property-provider.ru.md b/properties-loader/src/site/creation-custom-property-provider.ru.md
new file mode 100644
index 0000000..b013659
--- /dev/null
+++ b/properties-loader/src/site/creation-custom-property-provider.ru.md
@@ -0,0 +1,121 @@
+## Переопределение способа загрузки пропертей
+
+*since 1.4*
+
+Статья решает проблему, описанную в [Загрузка кофигураций в зависимости от окружения (передача предустановленных пропертей)][create-multi-file-configuration],
+но в более общем виде, позволяя аккуратно вынести грязную работу в отдельный класс,
+предоставив неограниченные возможности манипуляций с пропертями.
+
+Начальные данные:
+- есть необходимость загружать разные файлы пропертей в зависимости от некоторых условий,
+- путь может формироваться на лету по шаблону, используя в одном месте системные проперти, а в другом переменные из кода,
+- задействует это сразу множество классов-пропертей,
+- вдруг может понадобиться возможность игнорирования системных пропертей.
+
+Стратегия загрузки пропертей реализуется при помощи классов-имплементаций для ``PropertyProvider``, у которого нужно реализовать
+метод `` Properties provide(T bean, Properties properties)``. Куда на вход соответственно передается бин пропертей и `Map` из
+предустановленного набора пар ключ-значение.
+
+Когда в конструкторе класса пропертей делается ``PropertyLoader.populate(this);`` или ``PropertyLoader.populate(this, someProperties);``,
+у класса ищется аннотация ``@With`` со значением проперти-провайдера. В случае, если такой аннотации нет, используется дефолтный провайдер,
+который ищет аннотации ``@Resource.Classpath``, ``@Resource.File`` и берет путь загрузки по их значению, а так же считывает свойства из переменных окружения.
+
+Все что описано дальше, уже реализовано в классе ``MapOrSyspropPathReplacerProvider``, который можно подключать и превращать пути
+вида
+```java
+@Resource.Classpath("${system.file.name}.path.${map.scope.value}.properties")
+```
+в реальные пути к файлам пропертей. О том, как создать свой механизм, на примере этого класса - ниже.
+
+Попробуем реализовать возможность формирования пути файла при помощи переменных окружения, указывая место куда нужно вставить значение прямо в пути файла.
+Например, нужно считывать значение системной проперти *scope.value* и добавлять ее после имени файла с пропертями.
+Тогда укажем путь считывания в виде значения аннотации ``@Resource.Classpath("file.${system.scope.value}.properties")``.
+Теперь, нужно искать в этом пути все строки вида `${system.*}` и заменять их на значение.
+
+У ``DefaultPropertyProvider`` есть специальный метод получения пути из аннотации. Создадим наследника, в котором переопределим этот метод.
+
+```java
+public class SyspropPathReplacerProvider extends DefaultPropertyProvider {
+
+ public static final String SYS_PROP_KEY_PATTERN = "\\$\\{system\\.([^\\}]*)\\}";
+
+ @Override
+ public String classpath(Class> clazz, Properties properties) {
+ return replaceWithSystemProps(super.classpath(clazz, properties));
+ }
+
+ private String replaceWithSystemProps(String path) {
+ Matcher matcher = Pattern.compile(SYS_PROP_KEY_PATTERN).matcher(path);
+ while (matcher.find()) {
+ path = path.replace(matcher.group(0), System.getProperty(matcher.group(1), ""));
+ }
+ return path;
+ }
+}
+```
+
+Реализация элементарна - пробегаем по строке пути, попутно заменяя по регулярному выражению все что требуется.
+
+Теперь, подключив к классу пропертей этот провайдер, можно динамически формировать путь, просто указав куда нужно вставить значение.
+
+```java
+@Resource.Classpath("file.${system.scope.value}.properties")
+@With(SyspropPathReplacerProvider.class)
+public class UseSystemReplacerProviderProperty {
+
+ public UseSystemReplacerProviderProperty() {
+ PropertyLoader.populate(this);
+ }
+
+ @Property("property")
+ private String property = "undefined";
+
+ public String getProperty() {
+ return property;
+ }
+}
+```
+
+Похожим образом, можно сделать возможность формирования пути прямо в коде, не используя переменных окружения.
+Для этого нам понадобится метод ``PropertyLoader.populate(this, someProperties);``. Properties - это наследник ``Map``,
+поэтому мы можем сразу передать туда необходимые ключи, которые будут доступны в провайдере.
+Код пропертей будет выглядеть примерно так:
+
+```java
+@Resource.Classpath("file.${map.scope.value}.properties")
+@With(MapPathReplacerProvider.class)
+public class UseMapReplacerProviderProperty {
+
+ public UseMapReplacerProviderProperty(String scope) {
+ Properties map = new Properties();
+ map.put("scope.value", scope);
+ PropertyLoader.populate(this, map);
+ }
+
+ ...
+
+```
+
+Тогда код провайдера изменится следующим образом:
+
+```java
+ @Override
+ public String classpath(Class> clazz, Properties properties) {
+ return replaceWithMapProps(super.classpath(clazz, properties), properties);
+ }
+
+ private String replaceWithMapProps(String path, Properties properties) {
+ Matcher matcher = Pattern.compile(MAP_PROP_KEY_PATTERN).matcher(path);
+ while (matcher.find()) {
+ path = path.replace(matcher.group(0), properties.getProperty(matcher.group(1), ""));
+ }
+ return path;
+ }
+```
+
+Соответственно вызов конструктора с нужным параметром и определит имя файла.
+Рабочие примеры кода можно посмотреть в тесте ``CustomPropertyProviderTest``
+
+[create-multi-file-configuration]: https://github.com/yandex-qatools/properties/blob/master/properties-loader/src/site/create-multi-file-configuration.ru.md
+
+
diff --git a/properties-loader/src/test/java/ru/yandex/qatools/properties/CustomPropertyProviderTest.java b/properties-loader/src/test/java/ru/yandex/qatools/properties/CustomPropertyProviderTest.java
new file mode 100644
index 0000000..fead88a
--- /dev/null
+++ b/properties-loader/src/test/java/ru/yandex/qatools/properties/CustomPropertyProviderTest.java
@@ -0,0 +1,78 @@
+package ru.yandex.qatools.properties;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import ru.yandex.qatools.properties.testdata.UseMapReplacerProviderProperty;
+import ru.yandex.qatools.properties.testdata.UseSystemReplacerProviderProperty;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * User: lanwen
+ * Date: 17.07.13
+ * Time: 20:17
+ */
+public class CustomPropertyProviderTest {
+
+ @BeforeClass
+ public static void clear() throws Exception {
+ System.clearProperty("property");
+ }
+
+ @Test
+ public void loadDefaults() {
+ System.clearProperty("file.name");
+ System.clearProperty("scope.value");
+ UseSystemReplacerProviderProperty mfp = new UseSystemReplacerProviderProperty();
+ assertThat(mfp.getProperty(), equalTo("undefined"));
+ }
+
+ @Test
+ public void loadTestingProperty() {
+ System.setProperty("file.name", "first");
+ System.setProperty("scope.value", "testing");
+ UseSystemReplacerProviderProperty mfp = new UseSystemReplacerProviderProperty();
+ assertThat(mfp.getProperty(), equalTo("testing"));
+ }
+
+ @Test
+ public void loadProductionProperty() {
+ System.setProperty("file.name", "second");
+ System.setProperty("scope.value", "production");
+ UseSystemReplacerProviderProperty mfp = new UseSystemReplacerProviderProperty();
+ assertThat(mfp.getProperty(), equalTo("production"));
+ }
+
+ @Test
+ public void noFileLoadDefaults() {
+ UseMapReplacerProviderProperty mfp = new UseMapReplacerProviderProperty("third", "beta");
+ assertThat(mfp.getProperty(), equalTo("undefined"));
+ }
+
+ @Test
+ public void loadTestingPropertyWithMap() {
+ UseMapReplacerProviderProperty mfp = new UseMapReplacerProviderProperty("first", "testing");
+ assertThat(mfp.getProperty(), equalTo("testing"));
+ }
+
+ @Test
+ public void loadProductionPropertyWithMap() {
+ UseMapReplacerProviderProperty mfp = new UseMapReplacerProviderProperty("second", "production");
+ assertThat(mfp.getProperty(), equalTo("production"));
+ }
+
+ @Test
+ public void loadTestingPropertyBothWithMapAndSysprops() {
+ System.setProperty("file.name", "first");
+ UseMapOrSyspropReplacerProviderProperty mfp = new UseMapOrSyspropReplacerProviderProperty("testing");
+ assertThat(mfp.getProperty(), equalTo("testing"));
+ }
+
+ @Test
+ public void loadProductionPropertyBothWithMapAndSysprops() {
+ System.setProperty("file.name", "second");
+ UseMapOrSyspropReplacerProviderProperty mfp = new UseMapOrSyspropReplacerProviderProperty("production");
+ assertThat(mfp.getProperty(), equalTo("production"));
+ }
+}
diff --git a/properties-loader/src/test/java/ru/yandex/qatools/properties/LoadPropertiesDependsOnSystemPropertyTest.java b/properties-loader/src/test/java/ru/yandex/qatools/properties/LoadPropertiesDependsOnSystemPropertyTest.java
new file mode 100644
index 0000000..d7e8c7e
--- /dev/null
+++ b/properties-loader/src/test/java/ru/yandex/qatools/properties/LoadPropertiesDependsOnSystemPropertyTest.java
@@ -0,0 +1,42 @@
+package ru.yandex.qatools.properties;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import ru.yandex.qatools.properties.testdata.MultiFileProperty;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author artkoshelev
+ */
+public class LoadPropertiesDependsOnSystemPropertyTest {
+
+
+ @BeforeClass
+ public static void clear() throws Exception {
+ System.clearProperty("property");
+ }
+
+ @Test
+ public void loadDefaults() {
+ System.clearProperty("property.file");
+ MultiFileProperty mfp = new MultiFileProperty();
+ assertThat(mfp.getProperty(), equalTo("undefined"));
+ }
+
+ @Test
+ public void loadPublicProperty() {
+ System.setProperty("property.file", "public.properties");
+ MultiFileProperty mfp = new MultiFileProperty();
+ assertThat(mfp.getProperty(), equalTo("public"));
+ }
+
+ @Test
+ public void loadPrivateProperty() {
+ System.setProperty("property.file", "private.properties");
+ MultiFileProperty mfp = new MultiFileProperty();
+ assertThat(mfp.getProperty(), equalTo("private"));
+ }
+
+}
diff --git a/properties-loader/src/test/java/ru/yandex/qatools/properties/OverrideDefaultsFromFilePropertiesTest.java b/properties-loader/src/test/java/ru/yandex/qatools/properties/OverrideDefaultsFromFilePropertiesTest.java
index 7e4bcb8..14b0e12 100644
--- a/properties-loader/src/test/java/ru/yandex/qatools/properties/OverrideDefaultsFromFilePropertiesTest.java
+++ b/properties-loader/src/test/java/ru/yandex/qatools/properties/OverrideDefaultsFromFilePropertiesTest.java
@@ -1,17 +1,17 @@
package ru.yandex.qatools.properties;
-import org.apache.commons.beanutils.ConvertUtils;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import ru.yandex.qatools.properties.testdata.ProxyProperties;
-import ru.yandex.qatools.properties.testdata.ProxyPropertiesFactory;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
import java.io.File;
import java.io.FileReader;
import java.util.Properties;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import ru.yandex.qatools.properties.testdata.ProxyProperties;
+import ru.yandex.qatools.properties.testdata.ProxyPropertiesFactory;
/**
* @author Artem Eroshenko eroshenkoam
diff --git a/properties-loader/src/test/java/ru/yandex/qatools/properties/OverrideDefaultsFromSystemPropertiesTest.java b/properties-loader/src/test/java/ru/yandex/qatools/properties/OverrideDefaultsFromSystemPropertiesTest.java
index b284b85..b342eb7 100644
--- a/properties-loader/src/test/java/ru/yandex/qatools/properties/OverrideDefaultsFromSystemPropertiesTest.java
+++ b/properties-loader/src/test/java/ru/yandex/qatools/properties/OverrideDefaultsFromSystemPropertiesTest.java
@@ -1,16 +1,15 @@
package ru.yandex.qatools.properties;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
+
import ru.yandex.qatools.properties.testdata.ProxyProperties;
import ru.yandex.qatools.properties.testdata.ProxyPropertiesFactory;
-import java.util.Properties;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-
/**
* @author Artem Eroshenko eroshenkoam
* 3/24/13, 12:33 AM
diff --git a/properties-loader/src/test/java/ru/yandex/qatools/properties/UseMapOrSyspropReplacerProviderProperty.java b/properties-loader/src/test/java/ru/yandex/qatools/properties/UseMapOrSyspropReplacerProviderProperty.java
new file mode 100644
index 0000000..91173b3
--- /dev/null
+++ b/properties-loader/src/test/java/ru/yandex/qatools/properties/UseMapOrSyspropReplacerProviderProperty.java
@@ -0,0 +1,29 @@
+package ru.yandex.qatools.properties;
+
+import ru.yandex.qatools.properties.annotations.Property;
+import ru.yandex.qatools.properties.annotations.Resource;
+import ru.yandex.qatools.properties.annotations.With;
+import ru.yandex.qatools.properties.providers.MapOrSyspropPathReplacerProvider;
+
+import java.util.Properties;
+
+/**
+ * @author artkoshelev
+ */
+@Resource.Classpath("${system.file.name}.path.${map.scope.value}.properties")
+@With(MapOrSyspropPathReplacerProvider.class)
+public class UseMapOrSyspropReplacerProviderProperty {
+
+ public UseMapOrSyspropReplacerProviderProperty(String scope) {
+ Properties map = new Properties();
+ map.put("scope.value", scope);
+ PropertyLoader.populate(this, map);
+ }
+
+ @Property("property")
+ private String property = "undefined";
+
+ public String getProperty() {
+ return property;
+ }
+}
\ No newline at end of file
diff --git a/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/MapPathReplacerProvider.java b/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/MapPathReplacerProvider.java
new file mode 100644
index 0000000..8e54fb2
--- /dev/null
+++ b/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/MapPathReplacerProvider.java
@@ -0,0 +1,37 @@
+package ru.yandex.qatools.properties.testdata;
+
+import ru.yandex.qatools.properties.providers.DefaultPropertyProvider;
+
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * User: lanwen
+ * Date: 17.07.13
+ * Time: 19:58
+ */
+public class MapPathReplacerProvider extends DefaultPropertyProvider {
+ public static final String MAP_PROP_KEY_PATTERN = "\\$\\{map\\.([^\\}]*)\\}";
+
+ @Override
+ public String filepath(Class> clazz, Properties properties) {
+ return replaceWithMapProps(super.filepath(clazz, properties), properties);
+ }
+
+ @Override
+ public String classpath(Class> clazz, Properties properties) {
+ return replaceWithMapProps(super.classpath(clazz, properties), properties);
+ }
+
+
+ private String replaceWithMapProps(String path, Properties properties) {
+ Matcher matcher = Pattern.compile(MAP_PROP_KEY_PATTERN).matcher(path);
+ String replaced = path;
+ while (matcher.find()) {
+ replaced = replaced.replace(matcher.group(0), properties.getProperty(matcher.group(1), ""));
+ }
+ return replaced;
+ }
+
+}
diff --git a/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/MultiFileProperty.java b/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/MultiFileProperty.java
new file mode 100644
index 0000000..604367b
--- /dev/null
+++ b/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/MultiFileProperty.java
@@ -0,0 +1,36 @@
+package ru.yandex.qatools.properties.testdata;
+
+import static ru.yandex.qatools.properties.utils.PropertiesUtils.readProperties;
+
+import java.util.Properties;
+
+import ru.yandex.qatools.properties.PropertyLoader;
+import ru.yandex.qatools.properties.annotations.Property;
+
+/**
+ *
+ * @author artkoshelev
+ *
+ */
+public class MultiFileProperty {
+
+ public MultiFileProperty() {
+ PropertyLoader.populate(this, loadProperties());
+ }
+
+ @Property("property")
+ private String property = "undefined";
+
+ public String getProperty() {
+ return property;
+ }
+
+ private static Properties loadProperties() {
+ Properties result = new Properties();
+ String filePath = System.getProperty("property.file");
+ if (filePath != null) {
+ result.putAll(readProperties(ClassLoader.getSystemResourceAsStream(filePath)));
+ }
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/PropertiesWithCustomConverter.java b/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/PropertiesWithCustomConverter.java
index 124d649..6975eb9 100644
--- a/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/PropertiesWithCustomConverter.java
+++ b/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/PropertiesWithCustomConverter.java
@@ -1,14 +1,20 @@
package ru.yandex.qatools.properties.testdata;
+import ru.yandex.qatools.properties.PropertyLoader;
import ru.yandex.qatools.properties.annotations.Property;
+import ru.yandex.qatools.properties.annotations.Resource;
import ru.yandex.qatools.properties.annotations.Use;
+import java.util.Properties;
+
/**
* @author Artem Eroshenko eroshenkoam
* 5/13/13, 8:14 PM
*/
+@Resource.Classpath("${proeprty.load}.property")
public class PropertiesWithCustomConverter {
+
@Property("field")
@Use(UpperCaseStringConverter.class)
public String field;
diff --git a/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/SyspropPathReplacerProvider.java b/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/SyspropPathReplacerProvider.java
new file mode 100644
index 0000000..c023665
--- /dev/null
+++ b/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/SyspropPathReplacerProvider.java
@@ -0,0 +1,34 @@
+package ru.yandex.qatools.properties.testdata;
+
+import ru.yandex.qatools.properties.providers.DefaultPropertyProvider;
+
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * User: lanwen
+ * Date: 17.07.13
+ * Time: 19:58
+ */
+public class SyspropPathReplacerProvider extends DefaultPropertyProvider {
+ public static final String SYS_PROP_KEY_PATTERN = "\\$\\{system\\.([^\\}]*)\\}";
+
+ @Override
+ public String filepath(Class> clazz, Properties properties) {
+ return replaceWithSystemProps(super.filepath(clazz, properties));
+ }
+
+ @Override
+ public String classpath(Class> clazz, Properties properties) {
+ return replaceWithSystemProps(super.classpath(clazz, properties));
+ }
+ private String replaceWithSystemProps(String path) {
+ Matcher matcher = Pattern.compile(SYS_PROP_KEY_PATTERN).matcher(path);
+ String replaced = path;
+ while (matcher.find()) {
+ replaced = replaced.replace(matcher.group(0), System.getProperty(matcher.group(1), ""));
+ }
+ return replaced;
+ }
+}
diff --git a/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/UseMapReplacerProviderProperty.java b/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/UseMapReplacerProviderProperty.java
new file mode 100644
index 0000000..0607a64
--- /dev/null
+++ b/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/UseMapReplacerProviderProperty.java
@@ -0,0 +1,30 @@
+package ru.yandex.qatools.properties.testdata;
+
+import ru.yandex.qatools.properties.PropertyLoader;
+import ru.yandex.qatools.properties.annotations.Property;
+import ru.yandex.qatools.properties.annotations.Resource;
+import ru.yandex.qatools.properties.annotations.With;
+
+import java.util.Properties;
+
+/**
+ * @author artkoshelev
+ */
+@Resource.Classpath("${map.file.name}.path.${map.scope.value}.properties")
+@With(MapPathReplacerProvider.class)
+public class UseMapReplacerProviderProperty {
+
+ public UseMapReplacerProviderProperty(String name, String scope) {
+ Properties map = new Properties();
+ map.put("file.name", name);
+ map.put("scope.value", scope);
+ PropertyLoader.populate(this, map);
+ }
+
+ @Property("property")
+ private String property = "undefined";
+
+ public String getProperty() {
+ return property;
+ }
+}
\ No newline at end of file
diff --git a/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/UseSystemReplacerProviderProperty.java b/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/UseSystemReplacerProviderProperty.java
new file mode 100644
index 0000000..b61567a
--- /dev/null
+++ b/properties-loader/src/test/java/ru/yandex/qatools/properties/testdata/UseSystemReplacerProviderProperty.java
@@ -0,0 +1,31 @@
+package ru.yandex.qatools.properties.testdata;
+
+import ru.yandex.qatools.properties.PropertyLoader;
+import ru.yandex.qatools.properties.annotations.Property;
+import ru.yandex.qatools.properties.annotations.Resource;
+import ru.yandex.qatools.properties.annotations.With;
+
+import java.util.Properties;
+
+import static ru.yandex.qatools.properties.utils.PropertiesUtils.readProperties;
+
+/**
+ *
+ * @author artkoshelev
+ *
+ */
+@Resource.Classpath("${system.file.name}.path.${system.scope.value}.properties")
+@With(SyspropPathReplacerProvider.class)
+public class UseSystemReplacerProviderProperty {
+
+ public UseSystemReplacerProviderProperty() {
+ PropertyLoader.populate(this);
+ }
+
+ @Property("property")
+ private String property = "undefined";
+
+ public String getProperty() {
+ return property;
+ }
+}
\ No newline at end of file
diff --git a/properties-loader/src/test/resources/first.path.testing.properties b/properties-loader/src/test/resources/first.path.testing.properties
new file mode 100644
index 0000000..719f536
--- /dev/null
+++ b/properties-loader/src/test/resources/first.path.testing.properties
@@ -0,0 +1 @@
+property = testing
\ No newline at end of file
diff --git a/properties-loader/src/test/resources/private.properties b/properties-loader/src/test/resources/private.properties
new file mode 100644
index 0000000..e0b418b
--- /dev/null
+++ b/properties-loader/src/test/resources/private.properties
@@ -0,0 +1 @@
+property = private
\ No newline at end of file
diff --git a/properties-loader/src/test/resources/public.properties b/properties-loader/src/test/resources/public.properties
new file mode 100644
index 0000000..cc9b0ef
--- /dev/null
+++ b/properties-loader/src/test/resources/public.properties
@@ -0,0 +1 @@
+property = public
\ No newline at end of file
diff --git a/properties-loader/src/test/resources/second.path.production.properties b/properties-loader/src/test/resources/second.path.production.properties
new file mode 100644
index 0000000..5598c6d
--- /dev/null
+++ b/properties-loader/src/test/resources/second.path.production.properties
@@ -0,0 +1 @@
+property = production
\ No newline at end of file