View Javadoc

1   /*
2    * Copyright 2012-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.properties.spi.core.classpath;
17  
18  import java.net.URL;
19  import java.net.URLClassLoader;
20  import java.util.Collection;
21  import java.util.Collections;
22  import java.util.Iterator;
23  import java.util.Set;
24  import java.util.regex.Pattern;
25  
26  import org.reflections.Reflections;
27  import org.reflections.scanners.ResourcesScanner;
28  import org.reflections.util.ConfigurationBuilder;
29  
30  import de.smartics.properties.api.core.domain.PropertiesContext;
31  
32  /**
33   * Loads properties files found on the class path.
34   */
35  public final class PropertiesFilesLoader
36  {
37    // ********************************* Fields *********************************
38  
39    // --- constants ------------------------------------------------------------
40  
41    /**
42     * Pattern to filter properties files.
43     * <p>
44     * Every properties file (with file extension <code>properties</code> is
45     * allowed as long as the name does not contain any underscores. Underscores
46     * are used to distinguish localized information (like
47     * <code>my-properties_en.properties</code>) and therefore must not
48     * considered.
49     * </p>
50     *
51     * @impl Note that the pattern here is only the file name pattern without a
52     *       path.
53     */
54    private static final Pattern PROPERTIES_PATTERN = Pattern
55        .compile("[^_]+\\.properties");
56  
57    /**
58     * Pattern to detect boot properties files.
59     *
60     * @impl Note that the pattern here is only the file name pattern without a
61     *       path.
62     */
63    private static final Pattern BOOT_PROPERTIES_PATTERN = Pattern
64        .compile("boot\\.properties");
65  
66    /**
67     * Default scanner to use.
68     */
69    private static final ResourcesScanner SCANNER = new ResourcesScanner();
70  
71    // --- members --------------------------------------------------------------
72  
73    // ****************************** Initializer *******************************
74  
75    // ****************************** Constructors ******************************
76  
77    // ****************************** Inner Classes *****************************
78  
79    // ********************************* Methods ********************************
80  
81    // --- init -----------------------------------------------------------------
82  
83    private static Reflections buildReflections(final Collection<URL> urls)
84    {
85      final ClassLoader classLoader =
86          new URLClassLoader(urls.toArray(new URL[urls.size()]), Thread
87              .currentThread().getContextClassLoader());
88  
89      final ConfigurationBuilder builder = new ConfigurationBuilder();
90      builder.addScanners(SCANNER).addClassLoader(classLoader).addUrls(urls);
91      final Reflections reflections = new Reflections(builder);
92      return reflections;
93    }
94  
95    // --- get&set --------------------------------------------------------------
96  
97    // --- business -------------------------------------------------------------
98  
99    /**
100    * Returns all files with the extension <code>.properties</code>.
101    *
102    * @param urls the class roots to search for files that have the
103    *          <code>.properties</code> file name extension.
104    * @return the names of properties files relative to the class path root.
105    */
106   public Set<String> getPropertiesFiles(final Collection<URL> urls)
107   {
108     if (urls == null || urls.isEmpty())
109     {
110       return Collections.emptySet();
111     }
112 
113     final Reflections reflections = buildReflections(urls);
114     final Set<String> pathes = reflections.getResources(PROPERTIES_PATTERN);
115 
116     return pathes;
117   }
118 
119   /**
120    * Returns all boot properties that are defined to control the configuration
121    * parsing process. Properties are stored in files matching
122    * <code>/{@value de.smartics.properties.api.core.domain.PropertiesContext#META_INF_HOME}/boot.properties</code>
123    * .
124    *
125    * @param urls the URLs to search in.
126    * @return the names of properties files relative to the class path root.
127    */
128   public Set<String> getBootPropertiesFiles(final Collection<URL> urls)
129   {
130     if (urls == null || urls.isEmpty())
131     {
132       return Collections.emptySet();
133     }
134 
135     final Reflections reflections = buildReflections(urls);
136     final Set<String> pathes =
137         reflections.getResources(BOOT_PROPERTIES_PATTERN);
138 
139     for (final Iterator<String> i = pathes.iterator(); i.hasNext();)
140     {
141       final String path = i.next();
142       if (!path.endsWith(PropertiesContext.META_INF_HOME + "/boot.properties"))
143       {
144         i.remove();
145       }
146     }
147 
148     return pathes;
149   }
150 
151   // --- object basics --------------------------------------------------------
152 
153 }