This project has retired. For details please refer to its
Attic page.
BaseLocaleUrlDefinitionDAO xref
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.tiles.definition.dao;
23
24 import java.io.FileNotFoundException;
25 import java.io.IOException;
26 import java.net.URL;
27 import java.net.URLConnection;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Locale;
32 import java.util.Map;
33 import java.util.Set;
34
35 import org.apache.tiles.Definition;
36 import org.apache.tiles.Initializable;
37 import org.apache.tiles.TilesApplicationContext;
38 import org.apache.tiles.awareness.TilesApplicationContextAware;
39 import org.apache.tiles.definition.DefinitionsFactory;
40 import org.apache.tiles.definition.DefinitionsFactoryException;
41 import org.apache.tiles.definition.DefinitionsReader;
42 import org.apache.tiles.definition.RefreshMonitor;
43 import org.apache.tiles.definition.digester.DigesterDefinitionsReader;
44 import org.apache.tiles.impl.BasicTilesContainer;
45 import org.apache.tiles.reflect.ClassUtil;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 /***
50 * Base abstract class for a DAO that is based on URLs and locale as a
51 * customization key.
52 *
53 * @version $Rev: 797540 $ $Date: 2009-07-24 17:42:00 +0200 (ven, 24 lug 2009) $
54 * @since 2.1.0
55 */
56 @SuppressWarnings("deprecation")
57 public abstract class BaseLocaleUrlDefinitionDAO implements
58 DefinitionDAO<Locale>, Initializable, TilesApplicationContextAware,
59 RefreshMonitor, URLReader {
60
61 /***
62 * The logging object.
63 */
64 private final Logger log = LoggerFactory
65 .getLogger(BaseLocaleUrlDefinitionDAO.class);
66
67 /***
68 * Compatibility constant.
69 *
70 * @deprecated use {@link DefinitionsFactory#DEFINITIONS_CONFIG} to avoid
71 * namespace collisions.
72 */
73 private static final String LEGACY_DEFINITIONS_CONFIG = "definitions-config";
74
75 /***
76 * Contains the URL objects identifying where configuration data is found.
77 *
78 * @since 2.1.0
79 */
80 protected List<URL> sourceURLs;
81
82 /***
83 * Contains the dates that the URL sources were last modified.
84 *
85 * @since 2.1.0
86 */
87 protected Map<String, Long> lastModifiedDates;
88
89 /***
90 * The application context.
91 *
92 * @since 2.1.0
93 */
94 protected TilesApplicationContext applicationContext;
95
96 /***
97 * Reader used to get definitions from the sources.
98 *
99 * @since 2.1.0
100 */
101 protected DefinitionsReader reader;
102
103 /***
104 * Constructor.
105 */
106 public BaseLocaleUrlDefinitionDAO() {
107 sourceURLs = new ArrayList<URL>();
108 lastModifiedDates = new HashMap<String, Long>();
109 }
110
111 /*** {@inheritDoc}*/
112 public void setSourceURLs(List<URL> sourceURLs) {
113 this.sourceURLs = sourceURLs;
114 }
115
116 /*** {@inheritDoc}*/
117 public void setReader(DefinitionsReader reader) {
118 this.reader = reader;
119 }
120
121 /*** {@inheritDoc}*/
122 public void addSourceURL(URL sourceURL) {
123 if (sourceURLs == null) {
124 sourceURLs = new ArrayList<URL>();
125 }
126 sourceURLs.add(sourceURL);
127 }
128
129 /*** {@inheritDoc} */
130 public void setApplicationContext(TilesApplicationContext applicationContext) {
131 this.applicationContext = applicationContext;
132 }
133
134 /*** {@inheritDoc} */
135 public void init(Map<String, String> params) {
136 identifySources(params);
137 String readerClassName = params
138 .get(DefinitionsFactory.READER_IMPL_PROPERTY);
139
140 if (readerClassName != null) {
141 reader = (DefinitionsReader) ClassUtil.instantiate(readerClassName);
142 } else {
143 reader = new DigesterDefinitionsReader();
144 }
145 reader.init(params);
146 }
147
148 /*** {@inheritDoc} */
149 public boolean refreshRequired() {
150 boolean status = false;
151
152 Set<String> urls = lastModifiedDates.keySet();
153
154 try {
155 for (String urlPath : urls) {
156 Long lastModifiedDate = lastModifiedDates.get(urlPath);
157 URL url = new URL(urlPath);
158 URLConnection connection = url.openConnection();
159 connection.connect();
160 long newModDate = connection.getLastModified();
161 if (newModDate != lastModifiedDate) {
162 status = true;
163 break;
164 }
165 }
166 } catch (Exception e) {
167 log.warn("Exception while monitoring update times.", e);
168 return true;
169 }
170 return status;
171 }
172
173 /***
174 * Detects the sources to load.
175 *
176 * @param initParameters The initialization parameters.
177 * @since 2.1.0
178 */
179 protected void identifySources(Map<String, String> initParameters) {
180 if (applicationContext == null) {
181 throw new IllegalStateException(
182 "The TilesApplicationContext cannot be null");
183 }
184
185 String resourceString = getResourceString(initParameters);
186 String[] resources = getResourceNames(resourceString);
187
188 try {
189 for (int i = 0; i < resources.length; i++) {
190 Set<URL> urls = applicationContext.getResources(resources[i]);
191 if (urls != null && !urls.isEmpty()) {
192 for (URL resourceUrl : urls) {
193 if (resourceUrl != null) {
194 if (log.isDebugEnabled()) {
195 log.debug("Adding resource '" + resourceUrl
196 + "' to definitions factory.");
197 }
198 String externalForm = resourceUrl.toExternalForm();
199 if (externalForm.indexOf('_', externalForm
200 .lastIndexOf("/")) < 0) {
201 sourceURLs.add(resourceUrl);
202 } else if (log.isDebugEnabled()) {
203 log.debug("Not adding resource '" + resourceUrl
204 + "' to definitions factory because it is "
205 + "supposed to be an internationalization.");
206 }
207
208 } else {
209 log.warn("Unable to find configured definition '"
210 + resources[i] + "'");
211 }
212 }
213 } else {
214 log.warn("Unable to find resources under the name '"
215 + resources[i] + "'");
216 }
217 }
218 } catch (IOException e) {
219 throw new DefinitionsFactoryException(
220 "Unable to parse definitions from " + resourceString, e);
221 }
222 }
223
224 /***
225 * Derive the resource string from the initialization parameters. If no
226 * parameter {@link DefinitionsFactory#DEFINITIONS_CONFIG} is available,
227 * attempts to retrieve the deprecated
228 * <code>org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG</code>
229 * parameter and {@link #LEGACY_DEFINITIONS_CONFIG}. If neither are
230 * available, returns "/WEB-INF/tiles.xml".
231 *
232 * @param parms The initialization parameters.
233 * @return resource string to be parsed.
234 */
235 protected String getResourceString(Map<String, String> parms) {
236 String resourceStr = parms.get(DefinitionsFactory.DEFINITIONS_CONFIG);
237 if (resourceStr == null) {
238 resourceStr = parms.get(BasicTilesContainer.DEFINITIONS_CONFIG);
239 }
240 if (resourceStr == null) {
241 resourceStr = parms.get(LEGACY_DEFINITIONS_CONFIG);
242 }
243 if (resourceStr == null) {
244 resourceStr = "/WEB-INF/tiles.xml";
245 }
246 return resourceStr;
247 }
248
249 /***
250 * Parse the resourceString into a list of resource paths which can be
251 * loaded by the application context.
252 *
253 * @param resourceString comma separated resources
254 * @return parsed resources
255 */
256 protected String[] getResourceNames(String resourceString) {
257 return resourceString.split(",");
258 }
259
260 /***
261 * Loads definitions from an URL without loading from "parent" URLs.
262 *
263 * @param url The URL to read.
264 * @return The definition map that has been read.
265 */
266 protected Map<String, Definition> loadDefinitionsFromURL(URL url) {
267 Map<String, Definition> defsMap = null;
268 try {
269 URLConnection connection = url.openConnection();
270 connection.connect();
271 lastModifiedDates.put(url.toExternalForm(), connection
272 .getLastModified());
273
274
275
276 defsMap = reader.read(connection.getInputStream());
277 } catch (FileNotFoundException e) {
278
279 if (log.isDebugEnabled()) {
280 log.debug("File " + null + " not found, continue");
281 }
282 } catch (IOException e) {
283 throw new DefinitionsFactoryException(
284 "I/O error processing configuration.", e);
285 }
286
287 return defsMap;
288 }
289 }