Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
DeclarationConfigParser |
|
|
3.6;3.6 |
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.context; |
|
17 | ||
18 | import static de.smartics.properties.api.core.domain.ConfigMessageBean.systemId; |
|
19 | ||
20 | import java.io.BufferedInputStream; |
|
21 | import java.io.IOException; |
|
22 | import java.io.InputStream; |
|
23 | import java.net.URL; |
|
24 | import java.util.List; |
|
25 | import java.util.Locale; |
|
26 | ||
27 | import org.apache.commons.io.IOUtils; |
|
28 | import org.apache.commons.lang.StringUtils; |
|
29 | import org.jdom.Document; |
|
30 | import org.jdom.Element; |
|
31 | import org.jdom.JDOMException; |
|
32 | import org.jdom.Namespace; |
|
33 | import org.jdom.input.SAXBuilder; |
|
34 | ||
35 | import de.smartics.properties.api.core.domain.ConfigCode; |
|
36 | import de.smartics.properties.api.core.domain.ConfigException; |
|
37 | import de.smartics.properties.api.core.domain.PropertiesContext; |
|
38 | import de.smartics.properties.api.core.domain.PropertiesContext.Builder; |
|
39 | import de.smartics.properties.spi.core.util.ClassLoaderUtils; |
|
40 | import de.smartics.util.lang.classpath.ClassPathContext; |
|
41 | ||
42 | /** |
|
43 | * Parses the configuration file for properties. |
|
44 | */ |
|
45 | public final class DeclarationConfigParser |
|
46 | { |
|
47 | // ********************************* Fields ********************************* |
|
48 | ||
49 | // --- constants ------------------------------------------------------------ |
|
50 | ||
51 | /** |
|
52 | * The namespace accepted by this parser. |
|
53 | */ |
|
54 | 0 | private static final Namespace NS = Namespace |
55 | .getNamespace("http://smartics.de/properties/declaration/1"); |
|
56 | ||
57 | // --- members -------------------------------------------------------------- |
|
58 | ||
59 | /** |
|
60 | * Helper to determine the supported locales by analyzing the property set |
|
61 | * reports. |
|
62 | */ |
|
63 | 0 | private final LocaleFinder localeFinder = new LocaleFinder(); |
64 | ||
65 | // ****************************** Initializer ******************************* |
|
66 | ||
67 | // ****************************** Constructors ****************************** |
|
68 | ||
69 | // ****************************** Inner Classes ***************************** |
|
70 | ||
71 | // ********************************* Methods ******************************** |
|
72 | ||
73 | // --- init ----------------------------------------------------------------- |
|
74 | ||
75 | // --- get&set -------------------------------------------------------------- |
|
76 | ||
77 | // --- business ------------------------------------------------------------- |
|
78 | ||
79 | /** |
|
80 | * Default constructor. |
|
81 | */ |
|
82 | public DeclarationConfigParser() |
|
83 | 0 | { |
84 | 0 | } |
85 | ||
86 | // --- object basics -------------------------------------------------------- |
|
87 | ||
88 | /** |
|
89 | * Convenience method using a class' class loader to locate the configuration |
|
90 | * file to parse the configuration file at |
|
91 | * {@link PropertiesContext#DECLARATION_FILE}. |
|
92 | * |
|
93 | * @param type the type whose class loader to use to locate the configuration |
|
94 | * file. |
|
95 | * @return the read configuration, never <code>null</code>. |
|
96 | * @throws ConfigException on any problem loading the file. |
|
97 | */ |
|
98 | public PropertiesContext parse(final Class<?> type) throws ConfigException |
|
99 | { |
|
100 | 0 | final String archivePath = ClassLoaderUtils.calcArchivePath(type); |
101 | 0 | final ClassPathContext context = |
102 | new ClassPathContext(type.getClassLoader(), archivePath); |
|
103 | 0 | return parse(context); |
104 | } |
|
105 | ||
106 | /** |
|
107 | * Parses the configuration file at {@link PropertiesContext#DECLARATION_FILE} |
|
108 | * . |
|
109 | * |
|
110 | * @param context the context to use to locate the configuration file. |
|
111 | * @return the read configuration, never <code>null</code>. |
|
112 | * @throws ConfigException on any problem loading the file. |
|
113 | */ |
|
114 | public PropertiesContext parse(final ClassPathContext context) |
|
115 | throws ConfigException |
|
116 | { |
|
117 | 0 | final URL url = context.getResource(PropertiesContext.DECLARATION_FILE); |
118 | 0 | if (url != null) |
119 | { |
|
120 | 0 | final String systemId = url.toExternalForm(); |
121 | 0 | final List<Locale> locales = localeFinder.find(systemId, context); |
122 | ||
123 | 0 | InputStream in = null; |
124 | try |
|
125 | { |
|
126 | try |
|
127 | { |
|
128 | 0 | in = new BufferedInputStream(url.openStream()); |
129 | } |
|
130 | 0 | catch (final IOException e) |
131 | { |
|
132 | 0 | throw new ConfigException(systemId( |
133 | ConfigCode.CONFIG_FILE_CANNOT_BE_READ, e, |
|
134 | PropertiesContext.DECLARATION_FILE)); |
|
135 | 0 | } |
136 | 0 | return parse(systemId, locales, in); |
137 | } |
|
138 | finally |
|
139 | { |
|
140 | 0 | IOUtils.closeQuietly(in); |
141 | } |
|
142 | } |
|
143 | 0 | throw new ConfigException(systemId(ConfigCode.CONFIG_FILE_NOT_FOUND, |
144 | PropertiesContext.DECLARATION_FILE)); |
|
145 | } |
|
146 | ||
147 | private PropertiesContext parse(final String systemId, |
|
148 | final List<Locale> locales, final InputStream input) |
|
149 | throws ConfigException |
|
150 | { |
|
151 | try |
|
152 | { |
|
153 | 0 | final SAXBuilder parser = new SAXBuilder(); |
154 | 0 | final Document document = parser.build(input, systemId); |
155 | ||
156 | 0 | final PropertiesContext.Builder builder = new PropertiesContext.Builder(); |
157 | 0 | builder.withLocales(locales); |
158 | ||
159 | 0 | final Element rootNode = document.getRootElement(); |
160 | 0 | final String homePageUrl = rootNode.getChildText("homepage-url", NS); |
161 | 0 | final String propertiesReportUrl = |
162 | rootNode.getChildText("properties-report-url", NS); |
|
163 | 0 | if (StringUtils.isNotBlank(propertiesReportUrl)) |
164 | { |
|
165 | 0 | builder.withHomePageUrl(homePageUrl).withPropertiesReportUrl( |
166 | propertiesReportUrl); |
|
167 | } |
|
168 | ||
169 | 0 | handleAliases(rootNode, builder); |
170 | ||
171 | 0 | return builder.build(); |
172 | } |
|
173 | 0 | catch (final JDOMException e) |
174 | { |
|
175 | 0 | throw new ConfigException(systemId(ConfigCode.CONFIG_FILE_CANNOT_BE_READ, |
176 | e, systemId)); |
|
177 | } |
|
178 | 0 | catch (final IOException e) |
179 | { |
|
180 | 0 | throw new ConfigException(systemId(ConfigCode.CONFIG_FILE_CANNOT_BE_READ, |
181 | e, systemId)); |
|
182 | } |
|
183 | } |
|
184 | ||
185 | @SuppressWarnings("unchecked") |
|
186 | private void handleAliases(final Element rootNode, final Builder builder) |
|
187 | { |
|
188 | 0 | final Element aliases = rootNode.getChild("aliases", NS); |
189 | 0 | if (aliases != null) |
190 | { |
|
191 | 0 | final List<Element> aliasElements = aliases.getChildren("alias", NS); |
192 | 0 | for (final Element aliasElement : aliasElements) |
193 | { |
|
194 | 0 | final String alias = aliasElement.getTextNormalize(); |
195 | 0 | final String physical = aliasElement.getAttributeValue("for", NS); |
196 | 0 | builder.withAlias(alias, physical); |
197 | 0 | } |
198 | } |
|
199 | 0 | } |
200 | } |