You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by st...@apache.org on 2013/11/19 20:02:39 UTC

git commit: DELTASPIKE-442 improve PersistenceConfigurationProvider

Updated Branches:
  refs/heads/master db666c570 -> 4c410f32f


DELTASPIKE-442 improve PersistenceConfigurationProvider

also implement PropertyLoader (taken from Apache OpenWebBeans)
and tweak it to take ProjectStage into account.


Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/4c410f32
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/4c410f32
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/4c410f32

Branch: refs/heads/master
Commit: 4c410f32f951085a0f03d256649c833cd00996a6
Parents: db666c5
Author: Mark Struberg <st...@apache.org>
Authored: Tue Nov 19 19:59:14 2013 +0100
Committer: Mark Struberg <st...@apache.org>
Committed: Tue Nov 19 19:59:14 2013 +0100

----------------------------------------------------------------------
 .../core/api/config/PropertyLoader.java         | 264 +++++++++++++++++++
 .../test/api/config/PropertyLoaderTest.java     |  79 ++++++
 .../core/api/src/test/resources/test.properties |  21 ++
 .../test/resources/test2-UnitTest.properties    |  22 ++
 .../api/src/test/resources/test2.properties     |  21 ++
 .../PersistenceConfigurationProviderImpl.java   |  11 +-
 6 files changed, 415 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4c410f32/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/PropertyLoader.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/PropertyLoader.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/PropertyLoader.java
new file mode 100644
index 0000000..32590e9
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/PropertyLoader.java
@@ -0,0 +1,264 @@
+/*
+ * 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.deltaspike.core.api.config;
+
+import org.apache.deltaspike.core.api.projectstage.ProjectStage;
+import org.apache.deltaspike.core.spi.config.ConfigSource;
+import org.apache.deltaspike.core.util.ClassUtils;
+import org.apache.deltaspike.core.util.ProjectStageProducer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * <p>Utility class to load configuration properties via a list of
+ * artibrary property files by a well defined order.</p>
+ *
+ * <p>This will also pick up property files which are post-fixed with
+ * a -$projectStage.properties </p>
+ * <p>User configurations should start with 'configuration.ordinal'
+ * greater than 100.</p>
+ *
+ */
+public class PropertyLoader
+{
+    public static final int CONFIGURATION_ORDINAL_DEFAULT_VALUE = 100;
+
+
+    private static final String FILE_EXTENSION = ".properties";
+
+
+    private static final Logger LOG = Logger.getLogger(PropertyLoader.class.getName());
+
+
+    private PropertyLoader()
+    {
+        // utility class doesn't have a public ct
+    }
+
+    /**
+     * <p>Look for all property files with the given name (e.g. 'myconfig.properties') in
+     * the classpath. Then load all properties files and sort them by their ascending
+     * configuration order and apply them in this order.</p>
+     *
+     * <p>The idea is to be able to 'override' properties by just providing
+     * a new properties file with the same name but a higher 'deltaspike_ordinal'
+     * than the old one.</p>
+     *
+     * <p>If a property file defines no 'configuration.ordinal' property than a default
+     * value of {@link #CONFIGURATION_ORDINAL_DEFAULT_VALUE} is assumed. Any sensitive
+     * default which is provided by the system parsing for the configuration should
+     * have a 'configuration.ordinal' value lower than 10. In most cases a value of 1</p>
+     *
+     * <p>If 2 property files have the same ordinal 'configuraiton.order' the outcome
+     * is not really defined. The Properties file which got found first will be
+     * processed first and thus get overwritten by the one found later.</p> 
+     *
+     * @param propertyFileName the name of the properties file, without the extension '.properties'
+     * @return the final property values
+     */
+    public static synchronized Properties getProperties(String propertyFileName)
+    {
+        if (propertyFileName == null)
+        {
+            throw new IllegalArgumentException("propertyFileName must not be null!");
+        }
+
+        try
+        {
+            if (propertyFileName.endsWith(FILE_EXTENSION))
+            {
+                // if the given propertyFileName already contains the extension, then remove it.
+                propertyFileName = propertyFileName.substring(0, propertyFileName.length() - FILE_EXTENSION.length());
+            }
+
+            List<Properties> allProperties = loadAllProperties(propertyFileName);
+            if (allProperties == null)
+            {
+                return null;
+            }
+            
+            List<Properties> sortedProperties = sortProperties(allProperties);
+            Properties properties = mergeProperties(sortedProperties);
+            return properties;
+        }
+        catch (IOException e)
+        {
+            LOG.log(Level.SEVERE, "Error while loading the propertyFile " + propertyFileName, e);
+            return null;
+        }
+    }
+
+    private static List<Properties> loadAllProperties(String propertyFileName)
+        throws IOException
+    {
+        ClassLoader cl = ClassUtils.getClassLoader(null);
+
+        List<Properties> properties = new ArrayList<Properties>();
+
+        // read the normal property file names
+        Enumeration<URL> propertyUrls = cl.getResources(propertyFileName + FILE_EXTENSION);
+        while (propertyUrls != null && propertyUrls.hasMoreElements())
+        {
+            URL propertyUrl = propertyUrls.nextElement();
+            fillProperties(properties, propertyUrl);
+        }
+
+        // and also read the ones post-fixed with the projectStage
+        ProjectStage ps = ProjectStageProducer.getInstance().getProjectStage();
+
+        propertyUrls = cl.getResources(propertyFileName + "-" + ps + FILE_EXTENSION);
+        while (propertyUrls != null && propertyUrls.hasMoreElements())
+        {
+            URL propertyUrl = propertyUrls.nextElement();
+            fillProperties(properties, propertyUrl);
+        }
+
+        if (properties.isEmpty())
+        {
+            if (LOG.isLoggable(Level.INFO))
+            {
+                LOG.info("could not find any property files with name " + propertyFileName);
+            }
+
+            return null;
+        }
+
+        return properties;
+    }
+
+    private static void fillProperties(List<Properties> properties, URL propertyUrl) throws IOException
+    {
+        InputStream is = null;
+        try
+        {
+            is = propertyUrl.openStream();
+            Properties prop = new Properties();
+            prop.load(is);
+            properties.add(prop);
+
+            // a bit debugging output
+            int ordinal = getConfigurationOrdinal(prop);
+            if (LOG.isLoggable(Level.FINE))
+            {
+                LOG.fine("loading properties with ordinal " + ordinal + " from file " + propertyUrl.getFile());
+            }
+        }
+        finally
+        {
+            if (is != null)
+            {
+                is.close();
+            }
+        }
+    }
+
+    /**
+     * Implement a quick and dirty sorting mechanism for the given Properties.
+     * @param allProperties
+     * @return the Properties list sorted by it's 'configuration.ordinal' in ascending order.
+     */
+    private static List<Properties> sortProperties(List<Properties> allProperties)
+    {
+        List<Properties> sortedProperties = new ArrayList<Properties>();
+        for (Properties p : allProperties)
+        {
+            int configOrder = getConfigurationOrdinal(p);
+
+            int i;
+            for (i = 0; i < sortedProperties.size(); i++)
+            {
+                int listConfigOrder = getConfigurationOrdinal(sortedProperties.get(i));
+                if (listConfigOrder > configOrder)
+                {
+                    // only go as far as we found a higher priority Properties file
+                    break;
+                }
+            }
+            sortedProperties.add(i, p);
+        }
+        return sortedProperties;
+    }
+
+    /**
+     * Determine the 'configuration.ordinal' of the given properties.
+     * {@link #CONFIGURATION_ORDINAL_DEFAULT_VALUE} if
+     * {@link ConfigSource#DELTASPIKE_ORDINAL} is not set in the
+     * Properties file.
+     *
+     * @param p the Properties from the file.
+     * @return the ordinal number of the given Properties file.
+     */
+    private static int getConfigurationOrdinal(Properties p)
+    {
+        int configOrder = CONFIGURATION_ORDINAL_DEFAULT_VALUE;
+
+        String configOrderString = p.getProperty(ConfigSource.DELTASPIKE_ORDINAL);
+        if (configOrderString != null && configOrderString.length() > 0)
+        {
+            try
+            {
+                configOrder = Integer.parseInt(configOrderString);
+            }
+            catch (NumberFormatException nfe)
+            {
+                LOG.severe(ConfigSource.DELTASPIKE_ORDINAL + " must be an integer value!");
+                throw nfe;
+            }
+        }
+
+        return configOrder;
+    }
+
+    /**
+     * Merge the given Properties in order of appearance.
+     * @param sortedProperties
+     * @return the merged Properties
+     */
+    private static Properties mergeProperties(List<Properties> sortedProperties)
+    {
+        Properties mergedProperties = new Properties();
+        for (Properties p : sortedProperties)
+        {
+            for (Map.Entry<?,?> entry : p.entrySet())
+            {
+                String key = (String) entry.getKey();
+                String value = (String) entry.getValue();
+
+                if (!key.equals(ConfigSource.DELTASPIKE_ORDINAL))
+                {
+                    // simply overwrite the old properties with the new ones.
+                    mergedProperties.setProperty(key, value);
+                }
+            }
+        }
+
+        return mergedProperties;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4c410f32/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/PropertyLoaderTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/PropertyLoaderTest.java b/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/PropertyLoaderTest.java
new file mode 100644
index 0000000..3dcb23a
--- /dev/null
+++ b/deltaspike/core/api/src/test/java/org/apache/deltaspike/test/api/config/PropertyLoaderTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.deltaspike.test.api.config;
+
+import org.apache.deltaspike.core.api.config.ConfigResolver;
+import org.apache.deltaspike.core.api.config.PropertyLoader;
+import org.apache.deltaspike.core.api.projectstage.ProjectStage;
+import org.apache.deltaspike.core.util.ProjectStageProducer;
+import org.apache.deltaspike.test.category.SeCategory;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+import java.util.Properties;
+
+public class PropertyLoaderTest
+{
+    @Before
+    public void init()
+    {
+        ProjectStageProducer.setProjectStage(ProjectStage.UnitTest);
+    }
+
+
+    @Test
+    public void testNotExistingPropertyLoading() throws Exception
+    {
+        Assert.assertNull(PropertyLoader.getProperties("notexistingProperty"));
+        Assert.assertNull(PropertyLoader.getProperties("notexistingProperty.properties"));
+    }
+
+    @Test
+    public void testStandardPropertyLoading() throws Exception
+    {
+        checkProperties("test", "1");
+        checkProperties("test.properties", "1");
+    }
+
+    @Test
+    public void testProjectStagedPropertyLoading() throws Exception
+    {
+        checkProperties("test2", "2");
+        checkProperties("test2.properties", "2");
+    }
+
+
+    private void checkProperties(String propertyFile, String expectedValue)
+    {
+        Properties p = PropertyLoader.getProperties(propertyFile);
+        Assert.assertNotNull(p);
+        Assert.assertEquals(1, p.size());
+        Assert.assertEquals(expectedValue, p.get("test.value"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4c410f32/deltaspike/core/api/src/test/resources/test.properties
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/test/resources/test.properties b/deltaspike/core/api/src/test/resources/test.properties
new file mode 100644
index 0000000..77365f4
--- /dev/null
+++ b/deltaspike/core/api/src/test/resources/test.properties
@@ -0,0 +1,21 @@
+#####################################################################################
+# 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.
+#####################################################################################
+
+
+test.value=1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4c410f32/deltaspike/core/api/src/test/resources/test2-UnitTest.properties
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/test/resources/test2-UnitTest.properties b/deltaspike/core/api/src/test/resources/test2-UnitTest.properties
new file mode 100644
index 0000000..c586672
--- /dev/null
+++ b/deltaspike/core/api/src/test/resources/test2-UnitTest.properties
@@ -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.
+#####################################################################################
+
+deltaspike_ordinal=120
+
+test.value=2
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4c410f32/deltaspike/core/api/src/test/resources/test2.properties
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/test/resources/test2.properties b/deltaspike/core/api/src/test/resources/test2.properties
new file mode 100644
index 0000000..77365f4
--- /dev/null
+++ b/deltaspike/core/api/src/test/resources/test2.properties
@@ -0,0 +1,21 @@
+#####################################################################################
+# 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.
+#####################################################################################
+
+
+test.value=1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4c410f32/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/entitymanager/PersistenceConfigurationProviderImpl.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/entitymanager/PersistenceConfigurationProviderImpl.java b/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/entitymanager/PersistenceConfigurationProviderImpl.java
index f99c870..9aec0d6 100644
--- a/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/entitymanager/PersistenceConfigurationProviderImpl.java
+++ b/deltaspike/modules/jpa/impl/src/main/java/org/apache/deltaspike/jpa/impl/entitymanager/PersistenceConfigurationProviderImpl.java
@@ -23,10 +23,12 @@ import javax.enterprise.context.ApplicationScoped;
 
 import java.util.Properties;
 
+import org.apache.deltaspike.core.api.config.PropertyLoader;
 import org.apache.deltaspike.jpa.spi.entitymanager.PersistenceConfigurationProvider;
 
 /**
- * Default implementation of the PersistenceConfigurationProvider
+ * Default implementation of the PersistenceConfigurationProvider.
+ *
  */
 @ApplicationScoped
 public class PersistenceConfigurationProviderImpl implements PersistenceConfigurationProvider
@@ -34,9 +36,12 @@ public class PersistenceConfigurationProviderImpl implements PersistenceConfigur
     @Override
     public Properties getEntityManagerFactoryConfiguration(String persistenceUnitName)
     {
-        Properties unitProperties = new Properties();
+        Properties unitProperties = PropertyLoader.getProperties("persistence-" + persistenceUnitName);
 
-        //X TODO fill properties
+        if (unitProperties == null)
+        {
+            unitProperties = new Properties();
+        }
 
         return unitProperties;
     }