http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/etcd/src/test/java/org/apache/tamaya/etcd/EtcdPropertySourceTest.java ---------------------------------------------------------------------- diff --git a/etcd/src/test/java/org/apache/tamaya/etcd/EtcdPropertySourceTest.java b/etcd/src/test/java/org/apache/tamaya/etcd/EtcdPropertySourceTest.java new file mode 100644 index 0000000..898a963 --- /dev/null +++ b/etcd/src/test/java/org/apache/tamaya/etcd/EtcdPropertySourceTest.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.etcd; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Map; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; + +/** + * Created by atsticks on 07.01.16. + */ +public class EtcdPropertySourceTest { + + private final EtcdPropertySource propertySource = new EtcdPropertySource(); + + @BeforeClass + public static void setup(){ + System.setProperty("etcd.server.urls", "http://8.8.8.8:4001,http://192.168.99.105:4001"); + } + + @Test + public void testGetOrdinal() throws Exception { + assertEquals(propertySource.getOrdinal(), 1000); + } + + @Test + public void testGetDefaultOrdinal() throws Exception { + assertEquals(propertySource.getDefaultOrdinal(), 1000); + } + + @Test + public void testGetName() throws Exception { + assertEquals("etcd", propertySource.getName()); + } + + @Test + public void testGet() throws Exception { + Map<String,String> props = propertySource.getProperties(); + for(Map.Entry<String,String> en:props.entrySet()){ + assertNotNull("Key not found: " + en.getKey(), propertySource.get(en.getKey())); + } + } + + @Test + public void testGetProperties() throws Exception { + Map<String,String> props = propertySource.getProperties(); + assertNotNull(props); + } + + @Test + public void testIsScannable() throws Exception { + assertTrue(propertySource.isScannable()); + } +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/jodatime/src/main/java/org/apache/tamaya/jodatime/DurationConverter.java ---------------------------------------------------------------------- diff --git a/jodatime/src/main/java/org/apache/tamaya/jodatime/DurationConverter.java b/jodatime/src/main/java/org/apache/tamaya/jodatime/DurationConverter.java new file mode 100644 index 0000000..36d6fe9 --- /dev/null +++ b/jodatime/src/main/java/org/apache/tamaya/jodatime/DurationConverter.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.jodatime; + +import org.apache.tamaya.spi.ConversionContext; +import org.apache.tamaya.spi.PropertyConverter; +import org.joda.time.Duration; +import org.joda.time.Period; + +import java.util.Objects; + +/** + * <p>A {@link PropertyConverter} for converting a string representation of a + * given duration into a {@link Duration} instance.</p> + * + * <p>This converter supports the following string representations of a + * duration:</p> + * + * <ol> + * <li>ISO8601 format ({@code PTa.bS}). For example, "PT72.345S" represents 1 minute, + * 12 seconds and 345 milliseconds.</li> + * <li>All the period formats as defined in {@link PeriodConverter}.</li> + * </ol> + */ +public class DurationConverter implements PropertyConverter<Duration> { + + private PeriodConverter periodConverter = new PeriodConverter(); + + @Override + public Duration convert(String value, ConversionContext context) { + String trimmed = Objects.requireNonNull(value).trim(); + addSupportedFormats(context); + try { + return Duration.parse(value); + }catch(Exception e){ + Period period = null; + if(value.startsWith("P")){ + period = periodConverter.convert("P0Y0M0W"+value.substring(1), null); + } + if(period == null){ + period = periodConverter.convert("P0000-00-"+value, null); + } + if(period != null){ + return period.toStandardDuration(); + } + } + return null; + } + + private void addSupportedFormats(ConversionContext context) { + context.addSupportedFormats(getClass(), "PTa.bS"); + context.addSupportedFormats(getClass(), "PdDThHmMsS"); + context.addSupportedFormats(getClass(), "ddThh:mm:ss"); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/jodatime/src/test/java/org/apache/tamaya/jodatime/DurationConverterIT.java ---------------------------------------------------------------------- diff --git a/jodatime/src/test/java/org/apache/tamaya/jodatime/DurationConverterIT.java b/jodatime/src/test/java/org/apache/tamaya/jodatime/DurationConverterIT.java new file mode 100644 index 0000000..41288a8 --- /dev/null +++ b/jodatime/src/test/java/org/apache/tamaya/jodatime/DurationConverterIT.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.jodatime; + + +import org.apache.tamaya.spi.PropertyConverter; +import org.apache.tamaya.spi.ServiceContextManager; +import org.junit.Test; + +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.notNullValue; + +public class DurationConverterIT { + @Test + public void durationperiodConverterCanBeFoundAsServiceProvider() { + List<PropertyConverter> formats = ServiceContextManager.getServiceContext() + .getServices(PropertyConverter.class); + + PropertyConverter<?> converter = null; + + for (PropertyConverter format : formats) { + if (format instanceof DurationConverter) { + converter = format; + break; + } + } + + assertThat("Converter not found via service context.", converter, notNullValue()); + assertThat(converter, instanceOf(DurationConverter.class)); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/management/pom.xml ---------------------------------------------------------------------- diff --git a/management/pom.xml b/management/pom.xml new file mode 100644 index 0000000..5af0cf2 --- /dev/null +++ b/management/pom.xml @@ -0,0 +1,81 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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 current 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-sandbox</artifactId> + <version>0.3-incubating-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + + <artifactId>tamaya-management</artifactId> + <name>Apache Tamaya Modules - JMX Support</name> + <packaging>bundle</packaging> + + <properties> + <jdkVersion>1.7</jdkVersion> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.tamaya</groupId> + <artifactId>tamaya-api</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-functions</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.tamaya</groupId> + <artifactId>tamaya-core</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>java-hamcrest</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Package> + org.apache.tamaya.management + </Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/management/src/main/java/org/apache/tamaya/management/ConfigManagementSupport.java ---------------------------------------------------------------------- diff --git a/management/src/main/java/org/apache/tamaya/management/ConfigManagementSupport.java b/management/src/main/java/org/apache/tamaya/management/ConfigManagementSupport.java new file mode 100644 index 0000000..64fa062 --- /dev/null +++ b/management/src/main/java/org/apache/tamaya/management/ConfigManagementSupport.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.management; + + +import org.apache.tamaya.spi.ServiceContextManager; + +import javax.management.InstanceNotFoundException; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import java.lang.management.ManagementFactory; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Accessor singleton for the JMX configuration support module. + */ +public class ConfigManagementSupport { + + /** The logger used. */ + private final static Logger LOG = Logger.getLogger(ConfigManagementSupport.class.getName()); + + /** + * Private singleton constructor. + */ + private ConfigManagementSupport(){} + + /** + * Creates a new instance of a {@link ManagedConfigMBean} instance. This method uses the + * current {@link ServiceContextManager} to resolve the implementation to be used. + * @return a new ManagedConfigMBean instance, or null + * @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the + * maximum priority. + */ + private static ManagedConfigMBean createMBean(){ + return ServiceContextManager.getServiceContext() + .getService(ManagedConfigMBean.class); + } + + /** + * Registers a new instance of {@link ManagedConfigMBean} mbean for accessing config documentation into the local platform + * mbean server. + * @return the registered ObjectName, or null, if no bean could be created. + */ + public static ObjectName registerMBean() { + return registerMBean(null); + } + + /** + * Registers the {@link ManagedConfigMBean} mbean for accessing config documentation into the local platform + * mbean server. + * @param context An optional context parameter to be added to the object name. + * @return the registered ObjectName, or null, if no bean could be created. + */ + public static ObjectName registerMBean(String context) { + try{ + ManagedConfigMBean configMbean = createMBean(); + if(configMbean==null){ + return null; + } + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName on = context==null?new ObjectName("org.apache.tamaya.managemet:type=ManagedConfigMBean"): + new ObjectName("org.apache.tamaya.management:type=ManagedConfigMBean,context="+context); + try{ + mbs.getMBeanInfo(on); + LOG.info("Cannot register mbean " + on + ": already existing."); + return on; + } catch(InstanceNotFoundException e) { + LOG.info("Registering mbean " + on + "..."); + mbs.registerMBean(configMbean, on); + return on; + } + } catch(Exception e){ + LOG.log(Level.WARNING, "Failed to register ManagedConfigMBean.", e); + } + return null; + } + + /** + * Unregisters a new instance of {@link ManagedConfigMBean} mbean for accessing config documentation + * into the local platform mbean server. + * @return the unregistered ObjectName, or null, if no bean could be found. + */ + public static ObjectName unregisterMBean() { + return unregisterMBean(null); + } + + /** + * Unegisters the {@link ManagedConfigMBean} mbean for accessing config documentation into the local + * platform mbean server. + * @param context An optional context parameter to be added to the object name. + * @return the unregistered ObjectName, or null, if no bean could be created. + */ + public static ObjectName unregisterMBean(String context) { + try{ + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName on = context==null?new ObjectName("org.apache.tamaya.managemet:type=ManagedConfigMBean"): + new ObjectName("org.apache.tamaya.management:type=ManagedConfigMBean,context="+context); + try{ + mbs.unregisterMBean(on); + LOG.info("Unregistered mbean " + on + "."); + return on; + } catch(InstanceNotFoundException e) { + LOG.log(Level.INFO, "Unregistering mbean " + on + " failed.", e); + } + } catch(Exception e){ + LOG.log(Level.WARNING, "Failed to unregister ManagedConfigMBean.", e); + } + return null; + } +} + http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/management/src/main/java/org/apache/tamaya/management/ManagedConfig.java ---------------------------------------------------------------------- diff --git a/management/src/main/java/org/apache/tamaya/management/ManagedConfig.java b/management/src/main/java/org/apache/tamaya/management/ManagedConfig.java new file mode 100644 index 0000000..dab3457 --- /dev/null +++ b/management/src/main/java/org/apache/tamaya/management/ManagedConfig.java @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.management; + + +import org.apache.tamaya.Configuration; +import org.apache.tamaya.ConfigurationProvider; +import org.apache.tamaya.functions.ConfigurationFunctions; + +import java.util.Map; +import java.util.Set; + +/** + * Default implementation of the {@link ManagedConfigMBean} interface. Each bean binds to the + * current Configuration instance on creation. + */ +public class ManagedConfig implements ManagedConfigMBean { + + /** + * Classloader that was active when this instance was created. + */ + private ClassLoader classLoader; + + /** + * Constructor, which binds this instance to the current TCCL. In the rare cases where + * the TCCL is null, this class's classloader is used. + */ + public ManagedConfig() { + this.classLoader = Thread.currentThread().getContextClassLoader(); + if (this.classLoader == null) { + this.classLoader = ManagedConfigMBean.class.getClassLoader(); + } + } + + @Override + public String getJsonConfigurationInfo() { + return getConfigurationInternal().query(ConfigurationFunctions.jsonInfo()); + } + + @Override + public String getXmlConfigurationInfo() { + return getConfigurationInternal().query(ConfigurationFunctions.xmlInfo()); + } + + @Override + public Map<String, String> getConfiguration() { + return getConfigurationInternal().getProperties(); + } + + @Override + public Map<String, String> getSection(String area, boolean recursive) { + return getConfigurationInternal().with(ConfigurationFunctions.section(area, recursive)).getProperties(); + } + + @Override + public Set<String> getSections() { + return getConfigurationInternal().query(ConfigurationFunctions.sections()); + } + + @Override + public Set<String> getTransitiveSections() { + return getConfigurationInternal().query(ConfigurationFunctions.transitiveSections()); + } + + @Override + public boolean isAreaExisting(String area) { + return !getConfigurationInternal().with( + ConfigurationFunctions.section(area)).getProperties().isEmpty(); + } + + @Override + public boolean isAreaEmpty(String area) { + return getSection(area, true).isEmpty(); + } + + + /** + * Evaluate the current configuration. By default this class is temporarely setting the + * TCCL to the instance active on bean creation and then calls {@link ConfigurationProvider#getConfiguration()}. + * + * @return the configuration instance to be used. + */ + protected Configuration getConfigurationInternal() { + ClassLoader currentCL = Thread.currentThread().getContextClassLoader(); + try{ + Thread.currentThread().setContextClassLoader(this.classLoader); + return ConfigurationProvider.getConfiguration(); + } finally{ + Thread.currentThread().setContextClassLoader(currentCL); + } + } + +} + http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/management/src/main/java/org/apache/tamaya/management/ManagedConfigMBean.java ---------------------------------------------------------------------- diff --git a/management/src/main/java/org/apache/tamaya/management/ManagedConfigMBean.java b/management/src/main/java/org/apache/tamaya/management/ManagedConfigMBean.java new file mode 100644 index 0000000..7fa1eef --- /dev/null +++ b/management/src/main/java/org/apache/tamaya/management/ManagedConfigMBean.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.management; + +import java.util.Map; +import java.util.Set; + +/** + * Managed bean interface for accessing environment data. + */ +public interface ManagedConfigMBean { + + /** + * Get a general description of the configuration (context) in place, in JSON format: + * <pre> + * Configuration: { + * "class": "org.apache.tamaya.core.internal.DefaultConfiguration", + * "timestamp": 1440426409388, + * "data": { + * "ALLUSERSPROFILE": "C:\ProgramData", + * "APPDATA": "C:\Users\Anatole\AppData\Roaming", + * "COMPUTERNAME": "DEVBOX-WIN", + * "ComSpec": "C:\Windows\system32\cmd.exe", + * "CommonProgramFiles": "C:\Program Files\Common Files", + * "CommonProgramFiles(x86)": "C:\Program Files (x86)\Common Files", + * "CommonProgramW6432": "C:\Program Files\Common Files", + * "FP_NO_HOST_CHECK": "NO", + * "HOMEDRIVE": "C:", + * // ... + * } + * } + * </pre> + * + * @return a JSON formatted meta-information. + */ + String getJsonConfigurationInfo(); + + /** + * Get a general description of the configuration (context) in place, in JSON format: + * <pre> + * ConfigurationContext[gqContextClassName] { + * version = 2345-34334-2333-3434, + * config { + * key = "value", + * key2 = "value2" + * ... + * }, + * filters = [...], + * converters{...}, + * property-sources{...} + * } + * </pre> + * + * @return a JSON formatted meta-information. + */ + String getXmlConfigurationInfo(); + + /** + * Accesses a configuration current a given type as Map. + * + * @return the current configuration map. + * @throws org.apache.tamaya.ConfigException If the configuration is not available. + */ + Map<String, String> getConfiguration(); + + /** + * Accesses a configuration values for current a given config section as Map. + * @param area the target section key, not null. + * @param recursive if set to false only direct child keys of the given section are returned. + * @return the key/values found, including the recursive child values. + * @throws org.apache.tamaya.ConfigException If the configuration is not yet loaded. + */ + Map<String, String> getSection(String area, boolean recursive); + + /** + * Access the defined sections for a given configuration. + * @return the sections defined (only returning the sections that contain properties). + * @throws org.apache.tamaya.ConfigException If the configuration is not yet loaded + */ + Set<String> getSections(); + + /** + * Access the transitive sections for the current configuration. + * @return the transitive sections defined. + * @throws org.apache.tamaya.ConfigException If the configuration is not yet loaded + */ + Set<String> getTransitiveSections(); + + /** + * Allows to determine if an section is existing. + * @param area the target section key, not null. + * @return true, if such an section exists (the section may be empty). + */ + boolean isAreaExisting(String area); + + /** + * Allows to determine if an section is empty. + * @param area the target section key, not null. + * @return true, if such an section exists and is not empty. + */ + boolean isAreaEmpty(String area); + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/management/src/main/resources/META-INF/beans.xml ---------------------------------------------------------------------- diff --git a/management/src/main/resources/META-INF/beans.xml b/management/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000..adee378 --- /dev/null +++ b/management/src/main/resources/META-INF/beans.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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 current 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. +--> +<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://jboss.org/schema/cdi/beans_1_0.xsd"> + +</beans> + http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/management/src/main/resources/META-INF/javaconfiguration.properties ---------------------------------------------------------------------- diff --git a/management/src/main/resources/META-INF/javaconfiguration.properties b/management/src/main/resources/META-INF/javaconfiguration.properties new file mode 100644 index 0000000..333ba9c --- /dev/null +++ b/management/src/main/resources/META-INF/javaconfiguration.properties @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 current 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. +# +a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z=alphabet http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/management/src/main/resources/META-INF/services/org.apache.tamaya.management.ManagedConfigMBean ---------------------------------------------------------------------- diff --git a/management/src/main/resources/META-INF/services/org.apache.tamaya.management.ManagedConfigMBean b/management/src/main/resources/META-INF/services/org.apache.tamaya.management.ManagedConfigMBean new file mode 100644 index 0000000..4ba72b6 --- /dev/null +++ b/management/src/main/resources/META-INF/services/org.apache.tamaya.management.ManagedConfigMBean @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 current 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. +# +org.apache.tamaya.management.ManagedConfig \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/management/src/test/java/org/apache/tamaya/management/internal/ManagedConfigTest.java ---------------------------------------------------------------------- diff --git a/management/src/test/java/org/apache/tamaya/management/internal/ManagedConfigTest.java b/management/src/test/java/org/apache/tamaya/management/internal/ManagedConfigTest.java new file mode 100644 index 0000000..90ad0bf --- /dev/null +++ b/management/src/test/java/org/apache/tamaya/management/internal/ManagedConfigTest.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.management.internal; + +import org.apache.tamaya.management.ConfigManagementSupport; +import org.apache.tamaya.management.ManagedConfig; +import org.apache.tamaya.management.ManagedConfigMBean; + +import javax.management.MBeanServer; +import javax.management.ObjectName; +import java.lang.management.ManagementFactory; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.*; + +/** + * Created by Anatole on 20.08.2015. + */ +public class ManagedConfigTest { + + private final ManagedConfigMBean bean = new ManagedConfig(); + + @org.junit.Test + public void testGetJsonConfigurationInfo() throws Exception { + String info = bean.getJsonConfigurationInfo(); + assertNotNull(info); + assertTrue(info.contains("java.version")); + System.out.println(bean.getJsonConfigurationInfo()); + } + + @org.junit.Test + public void testGetXmlConfigurationInfo() throws Exception { + String info = bean.getXmlConfigurationInfo(); + assertNotNull(info); + assertTrue(info.contains("java.version")); + assertTrue(info.contains("<configuration>")); + System.out.println(bean.getXmlConfigurationInfo()); + } + + @org.junit.Test + public void testGetConfiguration() throws Exception { + Map<String,String> config = bean.getConfiguration(); + assertNotNull(config); + for(Map.Entry<Object, Object> en:System.getProperties().entrySet()){ + assertEquals(config.get(en.getKey()),en.getValue()); + } + } + + @org.junit.Test + public void testGetConfigurationArea() throws Exception { + Map<String,String> cfg = bean.getSection("java", false); + for(Map.Entry<String,String> en:cfg.entrySet()){ + assertEquals(System.getProperty(en.getKey()), en.getValue()); + } + } + + @org.junit.Test + public void testGetAreas() throws Exception { + Set<String> sections = (bean.getSections()); + assertNotNull(sections); + assertTrue(sections.contains("java")); + assertTrue(sections.contains("file")); + } + + @org.junit.Test + public void testGetTransitiveAreas() throws Exception { + Set<String> sections = (bean.getTransitiveSections()); + Set<String> sectionsNT = (bean.getSections()); + assertNotNull(sections); + assertTrue(sections.contains("java")); + assertTrue(sections.contains("sun")); + assertTrue(sections.contains("sun.os")); + assertTrue(sectionsNT.size()<sections.size()); + } + + @org.junit.Test + public void testIsAreaExisting() throws Exception { + assertTrue(bean.isAreaExisting("java")); + assertFalse(bean.isAreaExisting("sd.fldsfl.erlwsf")); + } + + @org.junit.Test + public void testRegisterMBean() throws Exception { + ObjectName on = ConfigManagementSupport.registerMBean(); + ConfigManagementSupport.registerMBean(); + // Lookup object name + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + assertTrue(mbs.getMBeanInfo(on)!=null); + } + + @org.junit.Test + public void testRegisterMBean1() throws Exception { + ObjectName on1 = ConfigManagementSupport.registerMBean("SubContext1"); + ConfigManagementSupport.registerMBean("SubContext1"); + ObjectName on2 = ConfigManagementSupport.registerMBean("SubContext2"); + // Lookup object name + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + assertTrue(mbs.getMBeanInfo(on1)!=null); + assertTrue(mbs.getMBeanInfo(on2)!=null); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/management/src/test/resources/META-INF/beans.xml ---------------------------------------------------------------------- diff --git a/management/src/test/resources/META-INF/beans.xml b/management/src/test/resources/META-INF/beans.xml new file mode 100644 index 0000000..adee378 --- /dev/null +++ b/management/src/test/resources/META-INF/beans.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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 current 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. +--> +<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://jboss.org/schema/cdi/beans_1_0.xsd"> + +</beans> + http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/metamodel/pom.xml ---------------------------------------------------------------------- diff --git a/metamodel/pom.xml b/metamodel/pom.xml new file mode 100644 index 0000000..f7f9dd8 --- /dev/null +++ b/metamodel/pom.xml @@ -0,0 +1,123 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-sandbox</artifactId> + <version>0.3-incubating-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + + <artifactId>tamaya-metamodel</artifactId> + <name>Apache Tamaya Modules - Metamodel</name> + <description>This extension module provides functionality to configure the + configuration system using meta-configuration. + </description> + <packaging>bundle</packaging> + + <properties> + <jdkVersion>1.7</jdkVersion> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.tamaya</groupId> + <artifactId>tamaya-api</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.tamaya</groupId> + <artifactId>tamaya-core</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-injection-api</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-spisupport</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-events</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-formats</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-json</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.apache.johnzon</groupId> + <artifactId>johnzon-core</artifactId> + <version>0.9-incubating</version> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-json_1.0_spec</artifactId> + <version>1.0-alpha-1</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>java-hamcrest</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Package> + org.apache.tamaya.model, + org.apache.tamaya.model.spi + </Export-Package> + <Private-Package> + org.apache.tamaya.model.internal + </Private-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/metamodel/src/main/java/org/apache/tamaya/metamodel/ConfigurationContextBuilder.java ---------------------------------------------------------------------- diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/ConfigurationContextBuilder.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/ConfigurationContextBuilder.java new file mode 100644 index 0000000..a84ab96 --- /dev/null +++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/ConfigurationContextBuilder.java @@ -0,0 +1,354 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.metamodel; + +import org.apache.tamaya.Configuration; +import org.apache.tamaya.TypeLiteral; +import org.apache.tamaya.spi.PropertyConverter; +import org.apache.tamaya.spi.PropertyFilter; +import org.apache.tamaya.spi.PropertySource; +import org.apache.tamaya.spi.PropertySourceProvider; +import org.apache.tamaya.spi.PropertyValueCombinationPolicy; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * Builder to create or change a {@link Configuration}. This build allows to programmatically + * assemble any kind of configuration based on {@link PropertySource}s. It also provides + * methods to change the overall ordering and add the source processors that are configured as + * ServiceLoader services, either directly, or indirectly using the {@link org.apache.tamaya.spi.PropertySourceProvider} + * SPI. + * + * Additionally this builder also implements the SPI that provides the default configuration + * as returned by {@link org.apache.tamaya.ConfigurationProvider#getConfiguration()}, since by definition the + * default configuration equals to the configuration that is created by calling + * <pre> + * ConfigurationContextBuilderFactory factory = ...; + * Configuration config = factory.createBuilder().loadDefaults().build(); + * </pre> + */ +public interface ConfigurationContextBuilder { + + /** + * Adds one or more property filter instances to the configuration to be build. + * + * <pre>{@code PropertyFilter quoteReplacingFilter = new QuoteFilter(); + * PropertyFilter commaRemovingFilter = new CommaFilter(); + * + * builder.addPropertyFilters(commaRemovingFilter, quoteReplacingFilter)}; + * </pre> + * + * @param filters list of property filter instances which should be applied + * to the properties of the configuration to be build. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertyFilter + * @see #getDefaultPropertyFilters() + */ + ConfigurationContextBuilder addPropertyFilters(PropertyFilter... filters); + + /** + * Adds one or more property filter instances to the configuration to be build. + * + * <pre>{@code PropertyFilter quoteReplacingFilter = new QuoteFilter(); + * PropertyFilter commaRemovingFilter = new CommaFilter(); + * + * builder.addPropertyFilters(commaRemovingFilter, quoteReplacingFilter)}; + * </pre> + * + * @param filters list of property filter instances which should be applied + * to the properties of the configuration to be build. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertyFilter + * @see #getDefaultPropertyFilters() + */ + ConfigurationContextBuilder addPropertyFilters(Collection<PropertyFilter> filters); + + /** + * @param propertyValueCombinationPolicy combination policy to use for this builder. + * @return the builder instance currently in use. + */ + ConfigurationContextBuilder setPropertyValueCombinationPolicy( + PropertyValueCombinationPolicy propertyValueCombinationPolicy); + + /** + * Adds a property converter for the a given type to the configuration to + * be build. + * + * <pre>{@code PropertyConverter<MyType> converter = value -> new MyType(value, 42); + * + * builder.addPropertyConverters(MyType.class, converter} + * </pre> + * + * @param <T> the type of the configuration + * @param type the required target type the converter should be applied to + * @param converter the converter to be used to convert the string property + * to the given target type, not null. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertyConverter + * @see #getDefaultPropertyConverters() + */ + <T> ConfigurationContextBuilder addPropertyConverter(Class<T> type, PropertyConverter<T>... converter); + + /** + * Adds a property converter for the a given type to the configuration to + * be build. + * + * <pre>{@code PropertyConverter<MyType> converter = value -> new MyType(value, 42); + * + * builder.addPropertyConverters(MyType.class, converter} + * </pre> + * + * @param <T> the type of the configuration + * @param type the required target type the converter should be applied to + * @param converter the converter to be used to convert the string property + * to the given target type, not null. + * + * @return the builder instance currently used + * + * @see org.apache.tamaya.spi.PropertyConverter + * @see #getDefaultPropertyConverters() + */ + <T> ConfigurationContextBuilder addPropertyConverter(Class<T> type, Collection<PropertyConverter<T>> converter); + + /** + * Adds a propertyConverter of a given type. + * + * @param <T> the type of the configuration + * @param type type literal of this converter. + * @param propertyConverter property converter, not null. + * @return the builder instance currently used + */ + <T> ConfigurationContextBuilder addPropertyConverter(TypeLiteral<T> type, PropertyConverter<T>... propertyConverter); + + /** + * Adds a propertyConverter of a given type. + * + * @param <T> the type of the configuration + * @param type type literal of this converter. + * @param propertyConverter property converter, not null. + * @return the builder instance currently used + */ + <T> ConfigurationContextBuilder addPropertyConverter(TypeLiteral<T> type, Collection<PropertyConverter<T>> propertyConverter); + + /** + * Loads the {@link org.apache.tamaya.spi.PropertyConverter}s provided + * via the SPI API returns them for adding all or parts of it using the + * builder's add methods. + * + * @return the collection of default instances, not yet registered + * within this builder. + * + * @see #addPropertyConverter(TypeLiteral, PropertyConverter...) + * @see #addPropertyConverter(TypeLiteral, Collection) + * @see org.apache.tamaya.spi.PropertyConverter + */ + Map<TypeLiteral<?>, Collection<PropertyConverter<?>>> getDefaultPropertyConverters(); + + + /** + * Loads the {@link org.apache.tamaya.spi.PropertySource}s provided + * via the SPI API, but does not yet register them into this builder. + * + * @return the builder instance currently used + * + * @see #addPropertySources(Collection) + * @see #addPropertySources(PropertySource...) + * @see org.apache.tamaya.spi.PropertySource + */ + Collection<PropertySource> getDefaultPropertySources(); + + + /** + * Loads the {@link org.apache.tamaya.spi.PropertyFilter}s provided via the SPI API, + * but does not register them into this instance. + * + * @return the builder instance currently used + * + * @see #addPropertyFilters(Collection<PropertyFilter>) + * @see org.apache.tamaya.spi.PropertyFilter + */ + Collection<PropertyFilter> getDefaultPropertyFilters(); + + + /** + * Loads the {@link org.apache.tamaya.spi.PropertySourceProvider + * property source providers} provided via the SPI API and + * returns them. No property sources are registered. + * + * @return the builder instance currently used + * + * @see #addPropertySources(Collection) + * @see org.apache.tamaya.spi.PropertySourceProvider + */ + Collection<PropertySourceProvider> getDefaultPropertySourceProviders(); + + /** + * This method loads the default configuration, which involves the following + * steps: + * <ol> + * <li>Loading {@link PropertySource} instances registered with the + * {@link java.util.ServiceLoader}.</li> + * <li>Loading {@link org.apache.tamaya.spi.PropertySourceProvider} instances registered with the + * {@link java.util.ServiceLoader}, extracting the provided processors and add them + * to the list of loaded processors</li> + * <li>Sorting the processors collecting based on {@link PropertySource#getOrdinal()} and the + * fully qualified class name as an additional fallback criteria, when the ordinal + * is the same.</li> + * <li>Putting together a {@link Configuration} instance incorporating this + * chain of processors. Hereby when {@link Configuration#get(String)} is called + * the first processor in the chain is asked for a value. If the processor returns {@code null} + * the processChain is repeated until the end of the chain is reached, or a processor returns + * non non-null value. Hereby each processor can actively decide how and if its parent processors + * will be included for subsequent value evaluation for a given key. In other words a processor + * can either simply provide configuration properties (values) or implement a more active functionality + * such as filtering or value collection.</li> + * </ol> + * @return the builder for further chaining of logic. + */ + ConfigurationContextBuilder loadDefaults(); + + /** + * Get the current number of processors on the chain. + * @return the number of registered processors of this instance. + */ + int getChainSize(); + + /** + * Increses the priority of the given processor instance, meaning moving the processor one + * position ahead in the overall processor chain. This will be done regardless of any + * ordinal value. If the procerssor already has maximal significance (is on the head of + * processors), this method does not have any effect. + * @param processor the target procerssor, not null. + * @return the builder for further chaining of logic. + */ + ConfigurationContextBuilder increasePriority(PropertySource processor); + + /** + * Decreses the priority of the given processor instance, meaning moving the processor one + * position back in the overall processor chain. This will be done regardless of any + * ordinal value. If the procerssor already has minimal significance (is the tail of + * processors), this method does not have any effect. + * @param processor the target procerssor, not null. + * @return the builder for further chaining of logic. + */ + ConfigurationContextBuilder decreasePriority(PropertySource processor); + + /** + * Maximizes the priority of the given processor instance, moving it to the head of the + * processor chain. This will be done regardless of any + * ordinal value. If the procerssor already has minimal significance (is the tail of + * processors), this method does not have any effect. + * @param processor the target procerssor, not null. + * @return the builder for further chaining of logic. + */ + ConfigurationContextBuilder highestPriority(PropertySource processor); + + /** + * Minimizes the priority of the given property source instance, moving it to the tail of the + * property source chain. This will be done regardless of any + * ordinal value. If the property source already has minimal significance (is the tail of + * processors), this method does not have any effect. + * @param propertySource the target property source, not null. + * @return the builder for further chaining of logic. + */ + ConfigurationContextBuilder lowestPriority(PropertySource propertySource); + + /** + * Add the property sources to the property source chain using thei provided ordinals + * for ordering. + * @param propertySources the property sources to add, not null. + * @return the builder for further chaining of logic. + */ + ConfigurationContextBuilder addPropertySources(PropertySource... propertySources); + + /** + * Add the property sources to the property source chain. + * @param propertySources the property sources to add, not null. + * @param index index where the new property sources should be inserted. + * @return the builder for further chaining of logic. + */ + ConfigurationContextBuilder addPropertySources(int index, PropertySource... propertySources); + + /** + * Add the property sources to the property source chain using thei provided ordinals + * for ordering. + * @param propertySources the property sources to add, not null. + * @return the builder for further chaining of logic. + */ + ConfigurationContextBuilder addPropertySources(Collection<PropertySource> propertySources); + + /** + * Add the property sources to the property source chain with highest priority (as new chain head). + * @param propertySources the property sources to add, not null. + * @param index index where the new property sources should be inserted. + * @return the builder for further chaining of logic. + */ + ConfigurationContextBuilder addPropertySources(int index, Collection<PropertySource> propertySources); + + /** + * Removes the given property source from the property source chain. + * @param propertySource the property source. not null. + * @return the builder for further chaining of logic. + */ + ConfigurationContextBuilder removePropertySource(PropertySource propertySource); + + /** + * Access a processor using it's unique property source name. If no such property source + * is present, this method has no effect. + * @param name the property source name, not null. + * @return the builder for further chaining of logic. + */ + PropertySource getPropertySource(String name); + + /** + * Get access to the current chain of property sources. This returns an immutable list. Use the + * methods of this factory to change the ordering or adding/removing of property sources. + * @return the current chain of property sources (immutable list). + */ + List<PropertySource> getPropertySourcesChain(); + + /** + * Get access to the current property sources with a given type. This returns an immutable list. Use the + * methods of this factory to change the ordering or adding/removing of property sources. + * @return the current chain of property sources (immutable list). + */ + List<PropertySource> getPropertySources(Class<? extends PropertySource> type); + + /** + * Get access to the current chain of property sources. This returns an immutable list. Use the + * methods of this factory to change the ordering or adding/removing of property sources. + * @return the current chain of property sources as names (immutable list). + */ + List<String> getPropertySourcesNames(); + + /** + * Builds a new configuration based on the current property sources chain. + * @return a new configuration instance, never null. + */ + Configuration build(); +} + http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/metamodel/src/main/java/org/apache/tamaya/metamodel/Context.java ---------------------------------------------------------------------- diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/Context.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/Context.java new file mode 100644 index 0000000..ce6d99c --- /dev/null +++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/Context.java @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.metamodel; + +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Class managing the configuration system's shared context. This + * context is used by the configuration system to evaluate the + * right properties, e.g. by defining the current stage or labels + * that apply to the current configuration. + */ +public final class Context { + + private static final Map<String,Context> CONTEXTS = new ConcurrentHashMap(); + private final Map<String,String> properties = new ConcurrentHashMap<>(); + + public static Context getInstance(){ + return getInstance(""); + } + + /** + * Access the context with a goven contextId, this allows to manage multiple + * contexts, e.g. for different EE application's deployed. If no such context + * exists a new one will be created. + * @param contextId the contextId, not null. + * @return the corresponding context, never null. + */ + public static Context getInstance(String contextId){ + Context context = CONTEXTS.get(contextId); + if(context==null){ + synchronized (Context.class){ + context = CONTEXTS.get(contextId); + if(context==null){ + context = new Context(); + CONTEXTS.put(contextId, context); + } + } + } + return context; + } + + public String getProperty(String key){ + return getProperty(key, null); + } + + public String getProperty(String key, String defaultValue){ + String value = this.properties.get(key); + if(value==null){ + return defaultValue; + } + return value; + } + + public String setProperty(String key, String value){ + return this.properties.put(key,value); + } + + public void setPropertyIfAbsent(String key, String value){ + String prev = this.properties.get(key); + if(prev==null){ + this.properties.put(key, prev); + } + } + + public void setProperties(Map<String,String> properties){ + this.properties.putAll(properties); + } + + public boolean checkProperties(String... keys){ + for(String key:keys) { + if (getProperty(key, null) == null) { + return false; + } + } + return true; + } + + public boolean checkProperty(String key, String value){ + if(value!=null){ + return value.equals(getProperty(key, null)); + } + return !checkProperties(key); + } + + public Map<String,String> getProperties(){ + return Collections.unmodifiableMap(this.properties); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Context)) return false; + + Context context = (Context) o; + + return getProperties().equals(context.getProperties()); + + } + + @Override + public int hashCode() { + return getProperties().hashCode(); + } + + @Override + public String toString() { + return "Context{" + + properties + + '}'; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/DefaultRefreshablePropertySourceProvider.java ---------------------------------------------------------------------- diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/DefaultRefreshablePropertySourceProvider.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/DefaultRefreshablePropertySourceProvider.java new file mode 100644 index 0000000..f968a15 --- /dev/null +++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/DefaultRefreshablePropertySourceProvider.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.metamodel.internal; + +import org.apache.tamaya.spi.ConfigurationContext; +import org.apache.tamaya.spi.ConfigurationContextBuilder; +import org.apache.tamaya.spi.PropertySource; +import org.apache.tamaya.spi.PropertySourceProvider; + +import java.util.Collection; +import java.util.Objects; + +/** + * Wrapped property source that allows dynamically reassigning the property source's + * ordinal value. This is needed for reordering the property sources to + * match the DSL configured ordering. + */ +public final class DefaultRefreshablePropertySourceProvider implements PropertySourceProvider, Refreshable { + + private SourceConfig sourceConfig; + private PropertySourceProvider wrapped; + private Collection<PropertySource> propertSources; + + public DefaultRefreshablePropertySourceProvider(SourceConfig sourceConfig) + throws IllegalAccessException, InstantiationException, + ClassNotFoundException { + this.sourceConfig = Objects.requireNonNull(sourceConfig); + this.wrapped = Objects.requireNonNull(sourceConfig.create(PropertySourceProvider.class)); + this.propertSources = Objects.requireNonNull(wrapped.getPropertySources()); + } + + @Override + public Collection<PropertySource> getPropertySources() { + return this.propertSources; + } + + @Override + public ConfigurationContext refresh(ConfigurationContext context) { + Collection<PropertySource> newPropertySources = + Objects.requireNonNull(wrapped.getPropertySources()); + ConfigurationContextBuilder builder = context.toBuilder(); + // remove previous sources + builder.removePropertySources(this.propertSources); + // add new sources + builder.addPropertySources(newPropertySources); + return builder.build(); + } + + @Override + public String toString() { + return "WrappedPropertySource{" + + "sourceConfig=" + sourceConfig + + ", wrapped=" + wrapped + + '}'; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/FactoryManager.java ---------------------------------------------------------------------- diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/FactoryManager.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/FactoryManager.java new file mode 100644 index 0000000..dbf8d1f --- /dev/null +++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/FactoryManager.java @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.metamodel.internal; + +import org.apache.tamaya.metamodel.spi.PropertySourceFactory; +import org.apache.tamaya.metamodel.spi.PropertySourceProviderFactory; +import org.apache.tamaya.spi.PropertySource; +import org.apache.tamaya.spi.PropertySourceProvider; +import org.apache.tamaya.spi.ServiceContextManager; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Small manager component to maintain the factories to be referenced by type names. + */ +final class FactoryManager { + + private static final Logger LOG = Logger.getLogger(FactoryManager.class.getName()); + private static final FactoryManager INSTANCE = new FactoryManager(); + + private Map<String, PropertySourceFactory> sourceFactories = new HashMap<>(); + private Map<String, PropertySourceProviderFactory> providerFactories = new HashMap<>(); + + private FactoryManager(){ + for(PropertySourceFactory f: ServiceContextManager.getServiceContext().getServices(PropertySourceFactory.class)){ + this.sourceFactories.put(f.getType(), f); + } + for(PropertySourceProviderFactory f: ServiceContextManager.getServiceContext().getServices(PropertySourceProviderFactory.class)){ + this.providerFactories.put(f.getType(), f); + } + } + + public static FactoryManager getInstance(){ + return INSTANCE; + } + + public PropertySourceFactory getSourceFactory(String type){ + PropertySourceFactory fact = this.sourceFactories.get(type); + if(fact==null){ + try{ + Class<? extends PropertySource> psType = (Class<? extends PropertySource>)Class.forName(type); + fact = new ImplicitPropertySourceFactory(psType); + this.sourceFactories.put(type, fact); + return fact; + }catch(Exception e){ + LOG.log(Level.SEVERE, "Failed to load PropertySourceFactory: " + type); + } + } + throw new IllegalArgumentException("No such PropertySourceFactory: " + type); + } + + public PropertySourceProviderFactory getProviderFactory(String type){ + PropertySourceProviderFactory fact = this.providerFactories.get(type); + if(fact==null){ + try{ + Class<? extends PropertySourceProvider> psType = (Class<? extends PropertySourceProvider>)Class.forName(type); + fact = new ImplicitPropertySourceProviderFactory(psType); + this.providerFactories.put(type, fact); + return fact; + }catch(Exception e){ + LOG.log(Level.SEVERE, "Failed to load PropertySourceProviderFactory: " + type); + } + } + throw new IllegalArgumentException("No such PropertySourceProviderFactory: " + type); + } + + @Override + public String toString() { + return "FactoryManager{" + + "providerFactories=" + providerFactories.keySet() + + ", sourceFactories=" + sourceFactories.keySet() + + '}'; + } + + private static class ImplicitPropertySourceFactory implements PropertySourceFactory{ + + private Class<? extends PropertySource> type; + + ImplicitPropertySourceFactory(Class<? extends PropertySource> type){ + this.type = Objects.requireNonNull(type); + } + + @Override + public PropertySource create(String config, Map<String, String> extendedConfig) { + try { + return this.type.newInstance(); + } catch (Exception e) { + throw new IllegalStateException("Cannot instantiate PropertySource: " + this.type.getName(), e); + } + } + + @Override + public String getType() { + return null; + } + } + + private static class ImplicitPropertySourceProviderFactory implements PropertySourceProviderFactory{ + + private Class<? extends PropertySourceProvider> type; + + ImplicitPropertySourceProviderFactory(Class<? extends PropertySourceProvider> type){ + this.type = Objects.requireNonNull(type); + } + + @Override + public PropertySourceProvider create(String config, Map<String, String> extendedConfig) { + try { + return this.type.newInstance(); + } catch (Exception e) { + throw new IllegalStateException("Cannot instantiate PropertySourceProvider: " + this.type.getName(), e); + } + } + + @Override + public String getType() { + return null; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/Refreshable.java ---------------------------------------------------------------------- diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/Refreshable.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/Refreshable.java new file mode 100644 index 0000000..bd0103e --- /dev/null +++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/Refreshable.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.metamodel.internal; + +import org.apache.tamaya.spi.ConfigurationContext; + +/** + * Common interface for refreshable items. + */ +public interface Refreshable { + + /** + * Refreshes the given configuration context, by applying any changes + * needed to reflect the change. + * @param context the configuration context, not null. + * @return the new configuration context. In case no changes are + * needed or the changes could be applied implicitly, the + * instance passed as input should be returned. + */ + ConfigurationContext refresh(ConfigurationContext context); +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/SourceConfig.java ---------------------------------------------------------------------- diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/SourceConfig.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/SourceConfig.java new file mode 100644 index 0000000..4987111 --- /dev/null +++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/SourceConfig.java @@ -0,0 +1,233 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.metamodel.internal; + + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Resolver to resolve/map DSL related source expressions into PropertySources + * loadable by a ConfigurationContext. Hereby the ordering of loaded property sources must be + * honored if possible by implicitly adapting/Overriding the default ordinal for the sources + * added. + */ +public class SourceConfig { + + private boolean enabled; + private String type; + private String name; + private Integer ordinal; + private long refreshInterval; + private Map<String,String> sourceConfiguration = new HashMap<>(); + + private SourceConfig(Builder builder) { + enabled = builder.enabled; + type = builder.type; + name = builder.name; + refreshInterval = builder.refreshInterval; + ordinal = builder.ordinal; + sourceConfiguration = builder.sourceConfiguration; + } + + /** + * New builder builder. + * + * @param type the type + * @return the builder + */ + public static Builder newBuilder(String type) { + return new Builder(type); + } + + /** + * New builder builder using this instance's settings. + * + * @return the builder + */ + public Builder toBuilder() { + Builder builder = new Builder(this.type); + builder.enabled = this.enabled; + builder.type = this.type; + builder.ordinal = this.ordinal; + builder.name = this.name; + builder.sourceConfiguration = this.sourceConfiguration; + return builder; + } + + /** + * Is enabled boolean. + * + * @return the boolean + */ + public boolean isEnabled() { + return enabled; + } + + /** + * Gets source configuration. + * + * @return the source configuration + */ + public Map<String, String> getSourceConfiguration() { + return sourceConfiguration; + } + + /** + * Gets type. + * + * @return the type + */ + public String getType() { + return type; + } + + /** + * Gets the current refresh interval, default is 0 meaning the property + * source is never refreshed. + * + * @return the refresh interval + */ + public long getRefreshInterval() { + return refreshInterval; + } + + /** + * Gets name. + * + * @return the name + */ + public String getName() { + return name; + } + + @Override + public String toString() { + return "PropertySourceConfig{" + + "enabled=" + enabled + + ", type='" + type + '\'' + + ", name='" + name + '\'' + + ", ordinal=" + ordinal + + ", sourceConfiguration=" + sourceConfiguration + + '}'; + } + + + public <T> T create(Class<T> type) + throws ClassNotFoundException, IllegalAccessException, + InstantiationException { + return (T)Class.forName(this.getType()).newInstance(); + } + + + /** + * {@code PropertySourceConfig} builder static inner class. + */ + public static final class Builder { + private boolean enabled; + private String type; + private String name; + private Integer ordinal; + private long refreshInterval; + private Map<String, String> sourceConfiguration; + + private Builder(String type) { + this.type = Objects.requireNonNull(type); + if(type.trim().isEmpty()){ + throw new IllegalArgumentException("Type is empty."); + } + } + + /** + * Sets the {@code refreshInterval} and returns a reference to this Builder so that the methods can be chained together. + * + * @param val the {@code refreshInterval} to set + * @return a reference to this Builder + */ + public Builder withRefreshInterval(long val) { + refreshInterval = val; + return this; + } + + /** + * Sets the {@code ordinal} and returns a reference to this Builder so that the methods can be chained together. + * + * @param val the {@code ordinal} to set + * @return a reference to this Builder + */ + public Builder withOrdinal(Integer val) { + ordinal = val; + return this; + } + + /** + * Sets the {@code enabled} and returns a reference to this Builder so that the methods can be chained together. + * + * @param val the {@code enabled} to set + * @return a reference to this Builder + */ + public Builder withEnabled(boolean val) { + enabled = val; + return this; + } + + /** + * Sets the {@code type} and returns a reference to this Builder so that the methods can be chained together. + * + * @param val the {@code type} to set + * @return a reference to this Builder + */ + public Builder withType(String val) { + type = val; + return this; + } + + /** + * Sets the {@code name} and returns a reference to this Builder so that the methods can be chained together. + * + * @param val the {@code name} to set + * @return a reference to this Builder + */ + public Builder withName(String val) { + name = val; + return this; + } + + /** + * Sets the {@code sourceConfiguration} and returns a reference to this Builder so that the methods can be chained together. + * + * @param val the {@code sourceConfiguration} to set + * @return a reference to this Builder + */ + public Builder withSourceConfiguration(Map<String, String> val) { + sourceConfiguration = val; + return this; + } + + /** + * Returns a {@code PropertySourceConfig} built from the parameters previously set. + * + * @return a {@code PropertySourceConfig} built with parameters of this {@code PropertySourceConfig.Builder} + */ + public SourceConfig build() { + return new SourceConfig(this); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/metamodel/src/main/java/org/apache/tamaya/metamodel/package-info.java ---------------------------------------------------------------------- diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/package-info.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/package-info.java new file mode 100644 index 0000000..c385da6 --- /dev/null +++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +/** + * Tamaya metamodel programmatic API. + */ +package org.apache.tamaya.metamodel; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/358828fe/metamodel/src/main/java/org/apache/tamaya/metamodel/spi/PropertySourceFactory.java ---------------------------------------------------------------------- diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/spi/PropertySourceFactory.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/spi/PropertySourceFactory.java new file mode 100644 index 0000000..49f72f2 --- /dev/null +++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/spi/PropertySourceFactory.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.tamaya.metamodel.spi; + +import org.apache.tamaya.metamodel.internal.SourceConfig; +import org.apache.tamaya.spi.PropertySource; + +import java.util.Map; + + +/** + * {@link PropertySource} and {@link SourceConfig} instances that + * implement configurable are configured with the according configuration + * settings provided in the {@code tamaya-config.xml} meta-configuration. + */ +public interface PropertySourceFactory { + + /** + * Resolve the given expression (without the key part). + * @param config the source configuration text, or null. + * @param extendedConfig any further extended configuration, not null, but may be + * empty. + * @return the property source, or null. + */ + PropertySource create(String config, Map<String, String> extendedConfig); + + /** + * Get the property source type. The type is used to identify the correct factory instance + * to resolve a configured property source. + * @return the (unique) type key, never null and not empty. + */ + String getType(); +}
