acc36c6be5570e92ef098e34ae0c275283464521
[idea/community.git] / jps / jps-builders / src / org / jetbrains / jps / incremental / java / FormsParsing.java
1 // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package org.jetbrains.jps.incremental.java;
3
4 import com.intellij.openapi.diagnostic.Logger;
5 import com.intellij.openapi.util.Ref;
6 import com.intellij.openapi.util.text.StringUtil;
7 import com.intellij.uiDesigner.UIFormXmlConstants;
8 import net.n3.nanoxml.*;
9 import org.jetbrains.annotations.Nullable;
10
11 import java.io.*;
12 import java.util.Properties;
13
14 /**
15  * @author Eugene Zhuravlev
16  */
17 public class FormsParsing {
18   private static final Logger LOG = Logger.getInstance(FormsParsing.class);
19   private static final String FORM_TAG = "form";
20
21   private FormsParsing() {
22   }
23
24   public static String readBoundClassName(File formFile) throws IOException {
25     try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(formFile))) {
26       final Ref<String> result = new Ref<>(null);
27       parse(in, new IXMLBuilderAdapter() {
28         @Override
29         public void startElement(final String elemName, final String nsPrefix, final String nsURI, final String systemID, final int lineNr)
30           throws Exception {
31           if (!FORM_TAG.equalsIgnoreCase(elemName)) {
32             stop();
33           }
34         }
35
36         @Override
37         public void addAttribute(final String key, final String nsPrefix, final String nsURI, final String value, final String type)
38           throws Exception {
39           if (UIFormXmlConstants.ATTRIBUTE_BIND_TO_CLASS.equals(key)) {
40             result.set(value);
41             stop();
42           }
43         }
44
45         @Override
46         public void elementAttributesProcessed(final String name, final String nsPrefix, final String nsURI) throws Exception {
47           stop();
48         }
49       });
50       return result.get();
51     }
52   }
53
54   public static void parse(final InputStream is, final IXMLBuilder builder) {
55     try {
56       parse(new MyXMLReader(is), builder);
57     }
58     catch(IOException e) {
59       LOG.error(e);
60     }
61     finally {
62
63       try {
64         is.close();
65       }
66       catch (IOException ignore) {
67
68       }
69     }
70   }
71
72   public static void parse(final IXMLReader r, final IXMLBuilder builder) {
73     try {
74       final IXMLParser parser = XMLParserFactory.createDefaultXMLParser();
75       parser.setReader(r);
76       parser.setBuilder(builder);
77       parser.setValidator(new EmptyValidator());
78       parser.setResolver(new EmptyEntityResolver());
79       try {
80         parser.parse();
81       }
82       catch (XMLException e) {
83         if (e.getException() instanceof ParserStoppedException) {
84           return;
85         }
86         LOG.debug(e);
87       }
88     }
89     catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
90       LOG.error(e);
91     }
92   }
93
94   private static class EmptyValidator extends NonValidator {
95     private IXMLEntityResolver myParameterEntityResolver;
96
97     @Override
98     public void setParameterEntityResolver(IXMLEntityResolver resolver) {
99       myParameterEntityResolver = resolver;
100     }
101
102     @Override
103     public IXMLEntityResolver getParameterEntityResolver() {
104       return myParameterEntityResolver;
105     }
106
107     @Override
108     public void parseDTD(String publicID, IXMLReader reader, IXMLEntityResolver entityResolver, boolean external) throws Exception {
109       if (!external) {
110         //super.parseDTD(publicID, reader, entityResolver, external);
111         int cnt = 1;
112         for (char ch = reader.read(); !(ch == ']' && --cnt == 0); ch = reader.read()) {
113           if (ch == '[') cnt ++;
114         }
115       }
116       else {
117         int origLevel = reader.getStreamLevel();
118
119         while (true) {
120           char ch = reader.read();
121
122           if (reader.getStreamLevel() < origLevel) {
123             reader.unread(ch);
124             return; // end external DTD
125           }
126         }
127       }
128     }
129
130     @Override
131     public void elementStarted(String name, String systemId, int lineNr) {
132     }
133
134     @Override
135     public void elementEnded(String name, String systemId, int lineNr) {
136     }
137
138     @Override
139     public void attributeAdded(String key, String value, String systemId, int lineNr) {
140     }
141
142     @Override
143     public void elementAttributesProcessed(String name, Properties extraAttributes, String systemId, int lineNr) {
144     }
145
146     @Override
147     public void PCDataAdded(String systemId, int lineNr)  {
148     }
149   }
150
151   private static class EmptyEntityResolver implements IXMLEntityResolver {
152     @Override
153     public void addInternalEntity(String name, String value) {
154     }
155
156     @Override
157     public void addExternalEntity(String name, String publicID, String systemID) {
158     }
159
160     @Override
161     public Reader getEntity(IXMLReader xmlReader, String name) throws XMLParseException {
162       return new StringReader("");
163     }
164
165     @Override
166     public boolean isExternalEntity(String name) {
167       return false;
168     }
169   }
170
171   private static class MyXMLReader extends StdXMLReader {
172     private String publicId;
173     private String systemId;
174
175     MyXMLReader(final Reader documentReader) {
176       super(documentReader);
177     }
178
179     MyXMLReader(InputStream stream) throws IOException {
180       super(stream);
181     }
182
183     @Override
184     public Reader openStream(String publicId, String systemId) throws IOException {
185       this.publicId = StringUtil.isEmpty(publicId) ? null : publicId;
186       this.systemId = StringUtil.isEmpty(systemId) ? null : systemId;
187
188       return new StringReader(" ");
189     }
190   }
191
192   public static class IXMLBuilderAdapter implements IXMLBuilder {
193
194     @Override
195     public void startBuilding(final String systemID, final int lineNr) throws Exception {
196     }
197
198     @Override
199     public void newProcessingInstruction(final String target, final Reader reader) throws Exception {
200
201     }
202
203     @Override
204     public void startElement(final String name, final String nsPrefix, final String nsURI, final String systemID, final int lineNr)
205         throws Exception {
206     }
207
208     @Override
209     public void addAttribute(final String key, final String nsPrefix, final String nsURI, final String value, final String type)
210         throws Exception {
211     }
212
213     @Override
214     public void elementAttributesProcessed(final String name, final String nsPrefix, final String nsURI) throws Exception {
215     }
216
217     @Override
218     public void endElement(final String name, final String nsPrefix, final String nsURI) throws Exception {
219     }
220
221     @Override
222     public void addPCData(final Reader reader, final String systemID, final int lineNr) throws Exception {
223     }
224
225     @Override
226     @Nullable
227     public Object getResult() throws Exception {
228       return null;
229     }
230
231     protected static void stop() {
232       throw new ParserStoppedException();
233     }
234   }
235
236   public static class ParserStoppedException extends RuntimeException {
237     @Override
238     public Throwable fillInStackTrace() {
239       return this;
240     }
241   }
242
243 }