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 }