001    /*
002     @license.text@
003     */
004    package biz.hammurapi.config;
005    
006    import java.io.FileInputStream;
007    import java.io.FileNotFoundException;
008    import java.io.IOException;
009    import java.io.InputStream;
010    import java.net.MalformedURLException;
011    import java.net.URL;
012    import java.text.MessageFormat;
013    
014    import javax.xml.parsers.DocumentBuilderFactory;
015    import javax.xml.parsers.FactoryConfigurationError;
016    import javax.xml.parsers.ParserConfigurationException;
017    
018    import org.w3c.dom.Document;
019    import org.xml.sax.SAXException;
020    
021    /**
022     * Helper class to read XML configuration from file, url or classloader
023     * resource.
024     * 
025     * @author Pavel Vlasov
026     * @version $Revision: 1.2 $
027     */
028    public class XmlSource implements Parameterizable {
029    
030        private String prefix;
031    
032        private Class masterClass;
033    
034        private String defaultResourceExtension;
035    
036        /**
037         * Constructor
038         * 
039         * @param prefix
040         *            Prefix for configuration parameters. Parameter specifying
041         *            configruration file would be <prefix>-file, url -
042         *            <prefix>-url, resource - <prefix>-resource
043         * @param masterClass
044         *            Master class' classloader will be used to load resources and
045         *            default resource would be masterClass name with
046         *            defaultResourceExtension. If master class is null then this
047         *            class classloader will be used and no default resource will be
048         *            loaded.
049         * @param defaultResourceExtension
050         *            Extension for default resource. If it is null then default
051         *            resource will not be loaded.
052         */
053        public XmlSource(String prefix, Class masterClass,
054                String defaultResourceExtension) {
055            this.prefix = prefix;
056            this.masterClass = masterClass;
057            this.defaultResourceExtension = defaultResourceExtension;
058        }
059    
060        private static final String CONFIG_ERROR_MESSAGE = "'{0}-file', "
061                + "'{0}-resource', and '{0}-url' parameters are mutually exclusive";
062    
063        private String resource;
064    
065        private String url;
066    
067        private String file;
068    
069        private Document document;
070    
071        /**
072         * @return parsed XML or null if config not found.
073         * @throws ConfigurationException
074         */
075        public Document getConfigDocument() throws ConfigurationException {
076            if (document == null) {
077                try {
078                    InputStream configStream = getStream();
079    
080                    if (configStream!=null) { 
081                            document = DocumentBuilderFactory.newInstance()
082                                    .newDocumentBuilder().parse(configStream);
083                            configStream.close();
084                    }
085                } catch (IOException e) {
086                    throw new ConfigurationException("Cannot load document, "
087                            + e.getMessage(), e);
088                } catch (SAXException e) {
089                    throw new ConfigurationException("Cannot load document, "
090                            + e.getMessage(), e);
091                } catch (ParserConfigurationException e) {
092                    throw new ConfigurationException("Cannot load document, "
093                            + e.getMessage(), e);
094                } catch (FactoryConfigurationError e) {
095                    throw new ConfigurationException("Cannot load document, "
096                            + e.getMessage(), e);
097                }
098            }
099    
100            return document;
101        }
102    
103        /**
104         * @return Stream
105         * @throws FileNotFoundException
106         * @throws IOException
107         * @throws MalformedURLException
108         * @throws ConfigurationException
109         */
110        public InputStream getStream() throws ConfigurationException {
111            try {
112                    Class clazz = masterClass==null ? getClass() : masterClass;
113                    if (file != null) {
114                        return new FileInputStream(file);
115                    } else if (url != null) {
116                        return new URL(url).openStream();
117                    } else if (resource != null) {
118                        
119                        InputStream configStream = clazz.getClassLoader().getResourceAsStream(resource);
120                        if (configStream == null) {
121                            throw new ConfigurationException("Resource not found: " + resource);
122                        }
123                        
124                                    return configStream;
125                    } else {
126                        if (defaultResourceExtension==null) {
127                            return null;
128                        }
129                        
130                                    String className = clazz.getName();
131                                    int idx = className.lastIndexOf('.');
132                                    String rName = (idx == -1 ? className : className
133                                            .substring(idx + 1))
134                                            + defaultResourceExtension;
135                                    return clazz.getResourceAsStream(rName);
136                    }
137            } catch (IOException e) {
138                throw new ConfigurationException("Cannot open stream, " + e.getMessage(), e);
139            }
140        }
141    
142        public boolean setParameter(String name, Object value)
143                throws ConfigurationException {
144            if ((prefix+"-file").equals(name)) {
145                if (resource != null) {
146                    throw new ConfigurationException(MessageFormat.format(CONFIG_ERROR_MESSAGE, new Object[] {prefix}));
147                }
148                if (url != null) {
149                    throw new ConfigurationException(MessageFormat.format(CONFIG_ERROR_MESSAGE, new Object[] {prefix}));
150                }
151                file = value.toString();
152            } else if ((prefix+"-resource").equals(name)) {
153                if (file != null) {
154                    throw new ConfigurationException(MessageFormat.format(CONFIG_ERROR_MESSAGE, new Object[] {prefix}));
155                }
156                if (url != null) {
157                    throw new ConfigurationException(MessageFormat.format(CONFIG_ERROR_MESSAGE, new Object[] {prefix}));
158                }
159                resource = value.toString();
160            } else if ((prefix+"-url").equals(name)) {
161                if (file != null) {
162                    throw new ConfigurationException(MessageFormat.format(CONFIG_ERROR_MESSAGE, new Object[] {prefix}));
163                }
164                if (resource != null) {
165                    throw new ConfigurationException(MessageFormat.format(CONFIG_ERROR_MESSAGE, new Object[] {prefix}));
166                }
167                url = value.toString();
168            } else {
169                return false;
170            }
171            return true;
172        }
173    }