View Javadoc

1   /*
2    * Copyright 2015 Data Archiving and Networked Services (an institute of
3    * Koninklijke Nederlandse Akademie van Wetenschappen), King's College London,
4    * Georg-August-Universitaet Goettingen Stiftung Oeffentlichen Rechts
5    *
6    * Licensed under the EUPL, Version 1.1 or – as soon they will be approved by
7    * the European Commission - subsequent versions of the EUPL (the "Licence");
8    * You may not use this work except in compliance with the Licence.
9    * You may obtain a copy of the Licence at:
10   *
11   * https://joinup.ec.europa.eu/software/page/eupl
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the Licence is distributed on an "AS IS" basis,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the Licence for the specific language governing
17   * permissions and limitations under the Licence.
18   */
19  
20  package eu.ehri.project.importers.properties;
21  
22  import com.google.common.base.Preconditions;
23  import org.slf4j.Logger;
24  import org.slf4j.LoggerFactory;
25  
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.nio.file.Files;
29  import java.nio.file.Path;
30  import java.nio.file.Paths;
31  import java.util.Properties;
32  import java.util.Set;
33  import java.util.stream.Collectors;
34  
35  /**
36   * wrapper class for the mapping of xml files to be imported.
37   */
38  public class XmlImportProperties implements ImportProperties {
39  
40  
41      private final Properties properties;
42  
43      public XmlImportProperties(String configFile) {
44          properties = PropertyLoader.loadProperties(configFile);
45      }
46  
47      /**
48       * Get the value for the specified key, or null.
49       */
50      @Override
51      public String getProperty(String key) {
52          return properties.getProperty(key);
53      }
54  
55      /**
56       * Get a set of property keys that have a given value
57       *
58       * @param value the value that requested properties must have
59       * @return a set of key names that have the given value
60       */
61      Set<String> getPropertiesWithValue(String value) {
62          return properties.entrySet().stream()
63                  .filter(e -> value.equals(e.getValue()))
64                  .map(e -> e.getKey().toString())
65                  .collect(Collectors.toSet());
66      }
67  
68      public String getFirstPropertyWithValue(String value) {
69          return properties.entrySet().stream()
70                  .filter(e -> value.equals(e.getValue()))
71                  .map(e -> e.getKey().toString())
72                  .findFirst().orElse(null);
73      }
74  
75      @Override
76      public Set<String> getAllNonAttributeValues() {
77          return properties.entrySet().stream()
78                  .filter(e -> !e.getKey().toString().startsWith("@"))
79                  .map(e -> e.getValue().toString())
80                  .collect(Collectors.toSet());
81      }
82  
83      public String getProperty(String key, String defaultValue) {
84          return properties.getProperty(key, defaultValue);
85      }
86  
87      @Override
88      public boolean containsPropertyValue(String value) {
89          return properties.containsValue(value);
90      }
91  
92      @Override
93      public boolean containsProperty(String path) {
94          return properties.containsKey(path);
95      }
96  
97      /**
98       * @param key Attribute key name
99       * @return returns whether this key is mentioned as an attribute in the property file
100      */
101     @Override
102     public boolean hasAttributeProperty(String key) {
103         return containsProperty("@" + key);
104     }
105 
106     @Override
107     public String getAttributeProperty(String key) {
108         return getProperty("@" + key);
109     }
110 }
111 
112 abstract class PropertyLoader {
113 
114     private static final Logger logger = LoggerFactory.getLogger(PropertyLoader.class);
115 
116     private static Properties loadPropertiesFromResource(String name, ClassLoader loader) {
117         logger.debug("loading resource {}...", name);
118         try (InputStream in = loader.getResourceAsStream(name)) {
119             if (in != null) {
120                 Properties result = new Properties();
121                 result.load(in);
122                 return result;
123             } else {
124                 return null;
125             }
126         } catch (IOException e) {
127             return null;
128         }
129     }
130 
131     private static Properties loadPropertiesFromFile(Path path) {
132         logger.debug("loading file {}...", path.toUri());
133         try (InputStream ios = Files.newInputStream(path)) {
134             Properties result = new Properties();
135             result.load(ios); // Can throw IOException
136             return result;
137         } catch (IOException e) {
138             logger.error("Error loading properties file: {}: {}", path, e);
139             return null;
140         }
141     }
142 
143     private static Properties loadPropertiesFromResourceOrFile(String name, ClassLoader loader) {
144         Preconditions.checkNotNull(name, "Property resource name may not be null");
145         if (loader == null) {
146             return loadPropertiesFromResourceOrFile(name, ClassLoader.getSystemClassLoader());
147         } else {
148             Path path = Paths.get(name);
149             if (Files.isRegularFile(path)) {
150                 return loadPropertiesFromFile(path);
151             } else {
152                 return loadPropertiesFromResource(name, loader);
153             }
154         }
155     }
156 
157     /**
158      * Looks up a resource named 'name' in the classpath. The resource must map to a file with .properties extension.
159      * The name is assumed to be absolute and can use either "/" or "." for package segment separation with an optional
160      * leading "/" and optional ".properties" suffix. Thus, the following names refer to the same resource:
161      * <p>
162      * <pre>
163      * some.pkg.Resource
164      * some.pkg.Resource.properties
165      * some/pkg/Resource
166      * some/pkg/Resource.properties
167      * /some/pkg/Resource
168      * /some/pkg/Resource.properties
169      * </pre>
170      *
171      * @param name   classpath resource name [may not be null]
172      * @param loader the ClassLoader through which to load the resource [null is equivalent to the application loader]
173      * @return resource converted to java.util.Properties
174      * @throws IllegalArgumentException if the resource was not found
175      */
176     private static Properties loadProperties(String name, ClassLoader loader) throws IllegalArgumentException {
177         Properties result = loadPropertiesFromResourceOrFile(name, loader);
178         if (result == null) {
179             String err = String.format("could not load [%s] as a classpath resource", name);
180             throw new IllegalArgumentException(err);
181         }
182         return result;
183     }
184 
185     /**
186      * A convenience overload of {@link #loadProperties(String, ClassLoader)} that uses the current thread's context
187      * ClassLoader.
188      */
189     static Properties loadProperties(String name) {
190         return loadProperties(name, Thread.currentThread().getContextClassLoader());
191     }
192 }