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