View Javadoc
1   /**
2    *    Copyright 2006-2016 the original author or authors.
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  /*
17   *  Licensed under the Apache License, Version 2.0 (the "License");
18   *  you may not use this file except in compliance with the License.
19   *  You may obtain a copy of the License at
20   *
21   *      http://www.apache.org/licenses/LICENSE-2.0
22   *
23   *  Unless required by applicable law or agreed to in writing, software
24   *  distributed under the License is distributed on an "AS IS" BASIS,
25   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26   *  See the License for the specific language governing permissions and
27   *  limitations under the License.
28   */
29  package org.mybatis.generator.config.xml;
30  
31  import static org.mybatis.generator.internal.util.messages.Messages.getString;
32  
33  import java.io.File;
34  import java.io.FileReader;
35  import java.io.IOException;
36  import java.io.InputStream;
37  import java.io.Reader;
38  import java.util.ArrayList;
39  import java.util.List;
40  import java.util.Properties;
41  
42  import javax.xml.parsers.DocumentBuilder;
43  import javax.xml.parsers.DocumentBuilderFactory;
44  import javax.xml.parsers.ParserConfigurationException;
45  
46  import org.mybatis.generator.codegen.XmlConstants;
47  import org.mybatis.generator.config.Configuration;
48  import org.mybatis.generator.exception.XMLParserException;
49  import org.w3c.dom.Document;
50  import org.w3c.dom.DocumentType;
51  import org.w3c.dom.Element;
52  import org.w3c.dom.Node;
53  import org.xml.sax.InputSource;
54  import org.xml.sax.SAXException;
55  import org.xml.sax.SAXParseException;
56  
57  public class ConfigurationParser {
58  
59      private List<String> warnings;
60      private List<String> parseErrors;
61      private Properties extraProperties;
62  
63      public ConfigurationParser(List<String> warnings) {
64          this(null, warnings);
65      }
66  
67      /**
68       * This constructor accepts a properties object which may be used to specify
69       * an additional property set.  Typically this property set will be Ant or Maven properties
70       * specified in the build.xml file or the POM.
71       * 
72       * If there are name collisions between the different property sets, they will be 
73       * resolved in this order:
74       * 
75       * <ol>
76       *   <li>System properties take highest precedence</li>
77       *   <li>Properties specified in the &lt;properties&gt; configuration
78       *       element are next</li>
79       *   <li>Properties specified in this "extra" property set are
80       *       lowest precedence.</li>
81       * </ol>
82       * 
83       * @param extraProperties an (optional) set of properties used to resolve property
84       *   references in the configuration file
85       * @param warnings
86       */
87      public ConfigurationParser(Properties extraProperties, List<String> warnings) {
88          super();
89          this.extraProperties = extraProperties;
90  
91          if (warnings == null) {
92              this.warnings = new ArrayList<String>();
93          } else {
94              this.warnings = warnings;
95          }
96  
97          parseErrors = new ArrayList<String>();
98      }
99  
100     public Configuration parseConfiguration(File inputFile) throws IOException,
101             XMLParserException {
102 
103         FileReader fr = new FileReader(inputFile);
104 
105         return parseConfiguration(fr);
106     }
107 
108     public Configuration parseConfiguration(Reader reader) throws IOException,
109             XMLParserException {
110 
111         InputSource is = new InputSource(reader);
112 
113         return parseConfiguration(is);
114     }
115 
116     public Configuration parseConfiguration(InputStream inputStream)
117             throws IOException, XMLParserException {
118 
119         InputSource is = new InputSource(inputStream);
120 
121         return parseConfiguration(is);
122     }
123 
124     private Configuration parseConfiguration(InputSource inputSource)
125             throws IOException, XMLParserException {
126         parseErrors.clear();
127         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
128         factory.setValidating(true);
129 
130         try {
131             DocumentBuilder builder = factory.newDocumentBuilder();
132             builder.setEntityResolver(new ParserEntityResolver());
133 
134             ParserErrorHandler handler = new ParserErrorHandler(warnings,
135                     parseErrors);
136             builder.setErrorHandler(handler);
137 
138             Document document = null;
139             try {
140                 document = builder.parse(inputSource);
141             } catch (SAXParseException e) {
142                 throw new XMLParserException(parseErrors);
143             } catch (SAXException e) {
144                 if (e.getException() == null) {
145                     parseErrors.add(e.getMessage());
146                 } else {
147                     parseErrors.add(e.getException().getMessage());
148                 }
149             }
150 
151             if (parseErrors.size() > 0) {
152                 throw new XMLParserException(parseErrors);
153             }
154 
155             Configuration config;
156             Element rootNode = document.getDocumentElement();
157             DocumentType docType = document.getDoctype();
158             if (rootNode.getNodeType() == Node.ELEMENT_NODE
159                     && docType.getPublicId().equals(
160                             XmlConstants.IBATOR_CONFIG_PUBLIC_ID)) {
161                 config = parseIbatorConfiguration(rootNode);
162             } else if (rootNode.getNodeType() == Node.ELEMENT_NODE
163                     && docType.getPublicId().equals(
164                             XmlConstants.MYBATIS_GENERATOR_CONFIG_PUBLIC_ID)) {
165                 config = parseMyBatisGeneratorConfiguration(rootNode);
166             } else {
167                 throw new XMLParserException(getString("RuntimeError.5")); //$NON-NLS-1$
168             }
169 
170             if (parseErrors.size() > 0) {
171                 throw new XMLParserException(parseErrors);
172             }
173 
174             return config;
175         } catch (ParserConfigurationException e) {
176             parseErrors.add(e.getMessage());
177             throw new XMLParserException(parseErrors);
178         }
179     }
180 
181     private Configuration parseIbatorConfiguration(Element rootNode)
182             throws XMLParserException {
183         IbatorConfigurationParser parser = new IbatorConfigurationParser(
184         		extraProperties);
185         return parser.parseIbatorConfiguration(rootNode);
186     }
187 
188     private Configuration parseMyBatisGeneratorConfiguration(Element rootNode)
189             throws XMLParserException {
190         MyBatisGeneratorConfigurationParser parser = new MyBatisGeneratorConfigurationParser(
191         		extraProperties);
192         return parser.parseConfiguration(rootNode);
193     }
194 }