~ubuntu-branches/ubuntu/saucy/commons-configuration/saucy

« back to all changes in this revision

Viewing changes to src/main/java/org/apache/commons/configuration/resolver/CatalogResolver.java

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg
  • Date: 2013-07-01 16:29:44 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20130701162944-98waq5gogha5gpn1
Tags: 1.9-1
* New upstream release
* debian/control:
  - Updated Standards-Version to 3.9.4 (no changes)
  - Use canonical URLs for the Vcs-* fields
  - Added new build dependencies (libjavacc-maven-plugin-java, junit4)
  - Upgraded the dependency on the Servlet API (2.5 -> 3.0)
  - Removed the dependency on the Activation Framework (glassfish-activation)
  - Replaced the dependency on glassfish-mail with libgnumail-java
  - Removed the unused dependencies:
    liblog4j1.2-java-doc, libmaven-assembly-plugin-java
  - Replaced the dependency on libcommons-jexl-java by libcommons-jexl2-java
* debian/watch: Changed to point the official Apache distribution server
* Removed the obsolete file debian/ant.properties
* Installed the upstream changelog in the binary packages
* Added the report plugins to maven.ignoreRules
* Added the classpath attribute to the jar manifest

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
 
3
 * contributor license agreements.  See the NOTICE file distributed with
 
4
 * this work for additional information regarding copyright ownership.
 
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
 
6
 * (the "License"); you may not use this file except in compliance with
 
7
 * the License.  You may obtain a copy of the License at
 
8
 *
 
9
 *     http://www.apache.org/licenses/LICENSE-2.0
 
10
 *
 
11
 * Unless required by applicable law or agreed to in writing, software
 
12
 * distributed under the License is distributed on an "AS IS" BASIS,
 
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
 * See the License for the specific language governing permissions and
 
15
 * limitations under the License.
 
16
 */
 
17
package org.apache.commons.configuration.resolver;
 
18
 
 
19
import java.io.IOException;
 
20
import java.io.InputStream;
 
21
import java.net.FileNameMap;
 
22
import java.net.URL;
 
23
import java.net.URLConnection;
 
24
import java.util.Vector;
 
25
 
 
26
import org.apache.commons.configuration.ConfigurationException;
 
27
import org.apache.commons.configuration.ConfigurationUtils;
 
28
import org.apache.commons.configuration.FileSystem;
 
29
import org.apache.commons.lang.text.StrSubstitutor;
 
30
import org.apache.commons.logging.Log;
 
31
import org.apache.commons.logging.LogFactory;
 
32
import org.apache.xml.resolver.CatalogException;
 
33
import org.apache.xml.resolver.readers.CatalogReader;
 
34
import org.xml.sax.EntityResolver;
 
35
import org.xml.sax.InputSource;
 
36
import org.xml.sax.SAXException;
 
37
 
 
38
/**
 
39
 * Thin wrapper around xml commons CatalogResolver to allow list of catalogs
 
40
 * to be provided.
 
41
 * @author <a
 
42
 * href="http://commons.apache.org/configuration/team-list.html">Commons
 
43
 * Configuration team</a>
 
44
 * @since 1.7
 
45
 * @version $Id: CatalogResolver.java 1301991 2012-03-17 20:18:02Z sebb $
 
46
 */
 
47
public class CatalogResolver implements EntityResolver
 
48
{
 
49
    /**
 
50
     * Debug everything.
 
51
     */
 
52
    private static final int DEBUG_ALL = 9;
 
53
 
 
54
    /**
 
55
     * Normal debug setting.
 
56
     */
 
57
    private static final int DEBUG_NORMAL = 4;
 
58
 
 
59
    /**
 
60
     * Debug nothing.
 
61
     */
 
62
    private static final int DEBUG_NONE = 0;
 
63
 
 
64
    /**
 
65
     * The CatalogManager
 
66
     */
 
67
    protected CatalogManager manager = new CatalogManager();
 
68
 
 
69
    /**
 
70
     * The FileSystem in use.
 
71
     */
 
72
    protected FileSystem fs = FileSystem.getDefaultFileSystem();
 
73
 
 
74
    /**
 
75
     * The CatalogResolver
 
76
     */
 
77
    private org.apache.xml.resolver.tools.CatalogResolver resolver;
 
78
 
 
79
    /**
 
80
     * Stores the logger.
 
81
     */
 
82
    private Log log;
 
83
 
 
84
    /**
 
85
     * Constructs the CatalogResolver
 
86
     */
 
87
    public CatalogResolver()
 
88
    {
 
89
        manager.setIgnoreMissingProperties(true);
 
90
        manager.setUseStaticCatalog(false);
 
91
        manager.setFileSystem(fs);
 
92
        setLogger(null);
 
93
    }
 
94
 
 
95
    /**
 
96
     * Set the list of catalog file names
 
97
     *
 
98
     * @param catalogs The delimited list of catalog files.
 
99
     */
 
100
    public void setCatalogFiles(String catalogs)
 
101
    {
 
102
        manager.setCatalogFiles(catalogs);
 
103
    }
 
104
 
 
105
    /**
 
106
     * Set the FileSystem.
 
107
     * @param fileSystem The FileSystem.
 
108
     */
 
109
    public void setFileSystem(FileSystem fileSystem)
 
110
    {
 
111
        this.fs = fileSystem;
 
112
        manager.setFileSystem(fileSystem);
 
113
    }
 
114
 
 
115
    /**
 
116
     * Set the base path.
 
117
     * @param baseDir The base path String.
 
118
     */
 
119
    public void setBaseDir(String baseDir)
 
120
    {
 
121
        manager.setBaseDir(baseDir);
 
122
    }
 
123
 
 
124
    /**
 
125
     * Set the StrSubstitutor.
 
126
     * @param substitutor The StrSubstitutor.
 
127
     */
 
128
    public void setSubstitutor(StrSubstitutor substitutor)
 
129
    {
 
130
        manager.setSubstitutor(substitutor);
 
131
    }
 
132
 
 
133
    /**
 
134
     * Enables debug logging of xml-commons Catalog processing.
 
135
     * @param debug True if debugging should be enabled, false otherwise.
 
136
     */
 
137
    public void setDebug(boolean debug)
 
138
    {
 
139
        if (debug)
 
140
        {
 
141
            manager.setVerbosity(DEBUG_ALL);
 
142
        }
 
143
        else
 
144
        {
 
145
            manager.setVerbosity(DEBUG_NONE);
 
146
        }
 
147
    }
 
148
 
 
149
    /**
 
150
     * Implements the {@code resolveEntity} method
 
151
     * for the SAX interface.
 
152
     * <p/>
 
153
     * <p>Presented with an optional public identifier and a system
 
154
     * identifier, this function attempts to locate a mapping in the
 
155
     * catalogs.</p>
 
156
     * <p/>
 
157
     * <p>If such a mapping is found, the resolver attempts to open
 
158
     * the mapped value as an InputSource and return it. Exceptions are
 
159
     * ignored and null is returned if the mapped value cannot be opened
 
160
     * as an input source.</p>
 
161
     * <p/>
 
162
     * <p>If no mapping is found (or an error occurs attempting to open
 
163
     * the mapped value as an input source), null is returned and the system
 
164
     * will use the specified system identifier as if no entityResolver
 
165
     * was specified.</p>
 
166
     *
 
167
     * @param publicId The public identifier for the entity in question.
 
168
     *                 This may be null.
 
169
     * @param systemId The system identifier for the entity in question.
 
170
     *                 XML requires a system identifier on all external entities, so this
 
171
     *                 value is always specified.
 
172
     * @return An InputSource for the mapped identifier, or null.
 
173
     * @throws SAXException if an error occurs.
 
174
     */
 
175
    public InputSource resolveEntity(String publicId, String systemId)
 
176
            throws SAXException
 
177
    {
 
178
        String resolved = getResolver().getResolvedEntity(publicId, systemId);
 
179
 
 
180
        if (resolved != null)
 
181
        {
 
182
            String badFilePrefix = "file://";
 
183
            String correctFilePrefix = "file:///";
 
184
 
 
185
            // Java 5 has a bug when constructing file URLS
 
186
            if (resolved.startsWith(badFilePrefix) && !resolved.startsWith(correctFilePrefix))
 
187
            {
 
188
                resolved = correctFilePrefix + resolved.substring(badFilePrefix.length());
 
189
            }
 
190
 
 
191
            try
 
192
            {
 
193
                InputStream is = fs.getInputStream(null, resolved);
 
194
                InputSource iSource = new InputSource(resolved);
 
195
                iSource.setPublicId(publicId);
 
196
                iSource.setByteStream(is);
 
197
                return iSource;
 
198
            }
 
199
            catch (Exception e)
 
200
            {
 
201
                log.warn("Failed to create InputSource for " + resolved + " ("
 
202
                                + e.toString() + ")");
 
203
                return null;
 
204
            }
 
205
        }
 
206
 
 
207
        return null;
 
208
    }
 
209
 
 
210
    /**
 
211
     * Returns the logger used by this configuration object.
 
212
     *
 
213
     * @return the logger
 
214
     */
 
215
    public Log getLogger()
 
216
    {
 
217
        return log;
 
218
    }
 
219
 
 
220
    /**
 
221
     * Allows to set the logger to be used by this configuration object. This
 
222
     * method makes it possible for clients to exactly control logging behavior.
 
223
     * Per default a logger is set that will ignore all log messages. Derived
 
224
     * classes that want to enable logging should call this method during their
 
225
     * initialization with the logger to be used.
 
226
     *
 
227
     * @param log the new logger
 
228
     */
 
229
    public void setLogger(Log log)
 
230
    {
 
231
        this.log = (log != null) ? log : LogFactory.getLog(CatalogResolver.class);
 
232
    }
 
233
 
 
234
    private synchronized org.apache.xml.resolver.tools.CatalogResolver getResolver()
 
235
    {
 
236
        if (resolver == null)
 
237
        {
 
238
            resolver = new org.apache.xml.resolver.tools.CatalogResolver(manager);
 
239
        }
 
240
        return resolver;
 
241
    }
 
242
 
 
243
    /**
 
244
     * Extend the CatalogManager to make the FileSystem and base directory accessible.
 
245
     */
 
246
    public static class CatalogManager extends org.apache.xml.resolver.CatalogManager
 
247
    {
 
248
        /** The static catalog used by this manager. */
 
249
        private static org.apache.xml.resolver.Catalog staticCatalog;
 
250
 
 
251
        /** The FileSystem */
 
252
        private FileSystem fs;
 
253
 
 
254
        /** The base directory */
 
255
        private String baseDir = System.getProperty("user.dir");
 
256
 
 
257
        /** The String Substitutor */
 
258
        private StrSubstitutor substitutor;
 
259
 
 
260
        /**
 
261
         * Set the FileSystem
 
262
         * @param fileSystem The FileSystem in use.
 
263
         */
 
264
        public void setFileSystem(FileSystem fileSystem)
 
265
        {
 
266
            this.fs = fileSystem;
 
267
        }
 
268
 
 
269
        /**
 
270
         * Retrieve the FileSystem.
 
271
         * @return The FileSystem.
 
272
         */
 
273
        public FileSystem getFileSystem()
 
274
        {
 
275
            return this.fs;
 
276
        }
 
277
 
 
278
        /**
 
279
         * Set the base directory.
 
280
         * @param baseDir The base directory.
 
281
         */
 
282
        public void setBaseDir(String baseDir)
 
283
        {
 
284
            if (baseDir != null)
 
285
            {
 
286
                this.baseDir = baseDir;
 
287
            }
 
288
        }
 
289
 
 
290
        /**
 
291
         * Return the base directory.
 
292
         * @return The base directory.
 
293
         */
 
294
        public String getBaseDir()
 
295
        {
 
296
            return this.baseDir;
 
297
        }
 
298
 
 
299
        public void setSubstitutor(StrSubstitutor substitutor)
 
300
        {
 
301
            this.substitutor = substitutor;
 
302
        }
 
303
 
 
304
        public StrSubstitutor getStrSubstitutor()
 
305
        {
 
306
            return this.substitutor;
 
307
        }
 
308
 
 
309
 
 
310
        /**
 
311
         * Get a new catalog instance. This method is only overridden because xml-resolver
 
312
         * might be in a parent ClassLoader and will be incapable of loading our Catalog
 
313
         * implementation.
 
314
         *
 
315
         * This method always returns a new instance of the underlying catalog class.
 
316
         * @return the Catalog.
 
317
         */
 
318
        @Override
 
319
        public org.apache.xml.resolver.Catalog getPrivateCatalog()
 
320
        {
 
321
            org.apache.xml.resolver.Catalog catalog = staticCatalog;
 
322
 
 
323
            if (catalog == null || !getUseStaticCatalog())
 
324
            {
 
325
                try
 
326
                {
 
327
                    catalog = new Catalog();
 
328
                    catalog.setCatalogManager(this);
 
329
                    catalog.setupReaders();
 
330
                    catalog.loadSystemCatalogs();
 
331
                }
 
332
                catch (Exception ex)
 
333
                {
 
334
                    ex.printStackTrace();
 
335
                }
 
336
 
 
337
                if (getUseStaticCatalog())
 
338
                {
 
339
                    staticCatalog = catalog;
 
340
                }
 
341
            }
 
342
 
 
343
            return catalog;
 
344
        }
 
345
 
 
346
        /**
 
347
         * Get a catalog instance.
 
348
         *
 
349
         * If this manager uses static catalogs, the same static catalog will
 
350
         * always be returned. Otherwise a new catalog will be returned.
 
351
         * @return The Catalog.
 
352
         */
 
353
        @Override
 
354
        public org.apache.xml.resolver.Catalog getCatalog()
 
355
        {
 
356
            return getPrivateCatalog();
 
357
        }
 
358
    }
 
359
 
 
360
    /**
 
361
     * Overrides the Catalog implementation to use the underlying FileSystem.
 
362
     */
 
363
    public static class Catalog extends org.apache.xml.resolver.Catalog
 
364
    {
 
365
        /** The FileSystem */
 
366
        private FileSystem fs;
 
367
 
 
368
        /** FileNameMap to determine the mime type */
 
369
        private FileNameMap fileNameMap = URLConnection.getFileNameMap();
 
370
 
 
371
        /**
 
372
         * Load the catalogs.
 
373
         * @throws IOException if an error occurs.
 
374
         */
 
375
        @Override
 
376
        public void loadSystemCatalogs() throws IOException
 
377
        {
 
378
            fs = ((CatalogManager) catalogManager).getFileSystem();
 
379
            String base = ((CatalogManager) catalogManager).getBaseDir();
 
380
 
 
381
            // This is safe because the catalog manager returns a vector of strings.
 
382
            @SuppressWarnings("unchecked")
 
383
            Vector<String> catalogs = catalogManager.getCatalogFiles();
 
384
            if (catalogs != null)
 
385
            {
 
386
                for (int count = 0; count < catalogs.size(); count++)
 
387
                {
 
388
                    String fileName = catalogs.elementAt(count);
 
389
 
 
390
                    URL url = null;
 
391
                    InputStream is = null;
 
392
 
 
393
                    try
 
394
                    {
 
395
                        url = ConfigurationUtils.locate(fs, base, fileName);
 
396
                        if (url != null)
 
397
                        {
 
398
                            is = fs.getInputStream(url);
 
399
                        }
 
400
                    }
 
401
                    catch (ConfigurationException ce)
 
402
                    {
 
403
                        String name = (url == null) ? fileName : url.toString();
 
404
                        // Ignore the exception.
 
405
                        catalogManager.debug.message(DEBUG_ALL,
 
406
                            "Unable to get input stream for " + name + ". " + ce.getMessage());
 
407
                    }
 
408
                    if (is != null)
 
409
                    {
 
410
                        String mimeType = fileNameMap.getContentTypeFor(fileName);
 
411
                        try
 
412
                        {
 
413
                            if (mimeType != null)
 
414
                            {
 
415
                                parseCatalog(mimeType, is);
 
416
                                continue;
 
417
                            }
 
418
                        }
 
419
                        catch (Exception ex)
 
420
                        {
 
421
                            // Ignore the exception.
 
422
                            catalogManager.debug.message(DEBUG_ALL,
 
423
                                "Exception caught parsing input stream for " + fileName + ". "
 
424
                                + ex.getMessage());
 
425
                        }
 
426
                        finally
 
427
                        {
 
428
                            is.close();
 
429
                        }
 
430
                    }
 
431
                    parseCatalog(base, fileName);
 
432
                }
 
433
            }
 
434
 
 
435
        }
 
436
 
 
437
        /**
 
438
         * Parse the specified catalog file.
 
439
         * @param baseDir The base directory, if not included in the file name.
 
440
         * @param fileName The catalog file. May be a full URI String.
 
441
         * @throws IOException If an error occurs.
 
442
         */
 
443
        public void parseCatalog(String baseDir, String fileName) throws IOException
 
444
        {
 
445
            base = ConfigurationUtils.locate(fs, baseDir, fileName);
 
446
            catalogCwd = base;
 
447
            default_override = catalogManager.getPreferPublic();
 
448
            catalogManager.debug.message(DEBUG_NORMAL, "Parse catalog: " + fileName);
 
449
 
 
450
            boolean parsed = false;
 
451
 
 
452
            for (int count = 0; !parsed && count < readerArr.size(); count++)
 
453
            {
 
454
                CatalogReader reader = (CatalogReader) readerArr.get(count);
 
455
                InputStream inStream;
 
456
 
 
457
                try
 
458
                {
 
459
                    inStream = fs.getInputStream(base);
 
460
                }
 
461
                catch (Exception ex)
 
462
                {
 
463
                    catalogManager.debug.message(DEBUG_NORMAL, "Unable to access " + base
 
464
                        + ex.getMessage());
 
465
                    break;
 
466
                }
 
467
 
 
468
                try
 
469
                {
 
470
                    reader.readCatalog(this, inStream);
 
471
                    parsed = true;
 
472
                }
 
473
                catch (CatalogException ce)
 
474
                {
 
475
                    catalogManager.debug.message(DEBUG_NORMAL, "Parse failed for " + fileName
 
476
                            + ce.getMessage());
 
477
                    if (ce.getExceptionType() == CatalogException.PARSE_FAILED)
 
478
                    {
 
479
                        break;
 
480
                    }
 
481
                    else
 
482
                    {
 
483
                        // try again!
 
484
                        continue;
 
485
                    }
 
486
                }
 
487
                finally
 
488
                {
 
489
                    try
 
490
                    {
 
491
                        inStream.close();
 
492
                    }
 
493
                    catch (IOException ioe)
 
494
                    {
 
495
                        // Ignore the exception.
 
496
                        inStream = null;
 
497
                    }
 
498
                }
 
499
            }
 
500
 
 
501
            if (parsed)
 
502
            {
 
503
                parsePendingCatalogs();
 
504
            }
 
505
        }
 
506
 
 
507
        /**
 
508
         * Perform character normalization on a URI reference.
 
509
         *
 
510
         * @param uriref The URI reference
 
511
         * @return The normalized URI reference.
 
512
         */
 
513
        @Override
 
514
        protected String normalizeURI(String uriref)
 
515
        {
 
516
            StrSubstitutor substitutor = ((CatalogManager) catalogManager).getStrSubstitutor();
 
517
            String resolved = substitutor != null ? substitutor.replace(uriref) : uriref;
 
518
            return super.normalizeURI(resolved);
 
519
        }
 
520
    }
 
521
}