]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.ui/src/org/argeo/cms/ui/internal/text/MarkupValidatorCopy.java
Improve node deployment
[lgpl/argeo-commons.git] / org.argeo.cms.ui / src / org / argeo / cms / ui / internal / text / MarkupValidatorCopy.java
1 package org.argeo.cms.ui.internal.text;
2
3 import java.io.StringReader;
4 import java.text.MessageFormat;
5 import java.util.Arrays;
6 import java.util.HashMap;
7 import java.util.List;
8 import java.util.Map;
9
10 import javax.xml.parsers.SAXParser;
11 import javax.xml.parsers.SAXParserFactory;
12
13 import org.argeo.cms.forms.FormPageViewer;
14 import org.eclipse.rap.rwt.SingletonUtil;
15 import org.eclipse.swt.widgets.Widget;
16 import org.xml.sax.Attributes;
17 import org.xml.sax.InputSource;
18 import org.xml.sax.helpers.DefaultHandler;
19
20 /**
21 * Copy of RAP v2.3 since it is in an internal package.
22 *
23 * FIXME made public to enable validation from the {@link FormPageViewer}
24 */
25 public class MarkupValidatorCopy {
26
27 // Used by Eclipse Scout project
28 public static final String MARKUP_VALIDATION_DISABLED = "org.eclipse.rap.rwt.markupValidationDisabled";
29
30 private static final String DTD = createDTD();
31 private static final Map<String, String[]> SUPPORTED_ELEMENTS = createSupportedElementsMap();
32 private final SAXParser saxParser;
33
34 public static MarkupValidatorCopy getInstance() {
35 return SingletonUtil.getSessionInstance(MarkupValidatorCopy.class);
36 }
37
38 public MarkupValidatorCopy() {
39 saxParser = createSAXParser();
40 }
41
42 public void validate(String text) {
43 StringBuilder markup = new StringBuilder();
44 markup.append(DTD);
45 markup.append("<html>");
46 markup.append(text);
47 markup.append("</html>");
48 InputSource inputSource = new InputSource(new StringReader(
49 markup.toString()));
50 try {
51 saxParser.parse(inputSource, new MarkupHandler());
52 } catch (RuntimeException exception) {
53 throw exception;
54 } catch (Exception exception) {
55 throw new IllegalArgumentException("Failed to parse markup text",
56 exception);
57 }
58 }
59
60 public static boolean isValidationDisabledFor(Widget widget) {
61 return Boolean.TRUE.equals(widget.getData(MARKUP_VALIDATION_DISABLED));
62 }
63
64 private static SAXParser createSAXParser() {
65 SAXParser result = null;
66 SAXParserFactory parserFactory = SAXParserFactory.newInstance();
67 try {
68 result = parserFactory.newSAXParser();
69 } catch (Exception exception) {
70 throw new RuntimeException("Failed to create SAX parser", exception);
71 }
72 return result;
73 }
74
75 private static String createDTD() {
76 StringBuilder result = new StringBuilder();
77 result.append("<!DOCTYPE html [");
78 result.append("<!ENTITY quot \"&#34;\">");
79 result.append("<!ENTITY amp \"&#38;\">");
80 result.append("<!ENTITY apos \"&#39;\">");
81 result.append("<!ENTITY lt \"&#60;\">");
82 result.append("<!ENTITY gt \"&#62;\">");
83 result.append("<!ENTITY nbsp \"&#160;\">");
84 result.append("<!ENTITY ensp \"&#8194;\">");
85 result.append("<!ENTITY emsp \"&#8195;\">");
86 result.append("<!ENTITY ndash \"&#8211;\">");
87 result.append("<!ENTITY mdash \"&#8212;\">");
88 result.append("]>");
89 return result.toString();
90 }
91
92 private static Map<String, String[]> createSupportedElementsMap() {
93 Map<String, String[]> result = new HashMap<String, String[]>();
94 result.put("html", new String[0]);
95 result.put("br", new String[0]);
96 result.put("b", new String[] { "style" });
97 result.put("strong", new String[] { "style" });
98 result.put("i", new String[] { "style" });
99 result.put("em", new String[] { "style" });
100 result.put("sub", new String[] { "style" });
101 result.put("sup", new String[] { "style" });
102 result.put("big", new String[] { "style" });
103 result.put("small", new String[] { "style" });
104 result.put("del", new String[] { "style" });
105 result.put("ins", new String[] { "style" });
106 result.put("code", new String[] { "style" });
107 result.put("samp", new String[] { "style" });
108 result.put("kbd", new String[] { "style" });
109 result.put("var", new String[] { "style" });
110 result.put("cite", new String[] { "style" });
111 result.put("dfn", new String[] { "style" });
112 result.put("q", new String[] { "style" });
113 result.put("abbr", new String[] { "style", "title" });
114 result.put("span", new String[] { "style" });
115 result.put("img", new String[] { "style", "src", "width", "height",
116 "title", "alt" });
117 result.put("a", new String[] { "style", "href", "target", "title" });
118 return result;
119 }
120
121 private static class MarkupHandler extends DefaultHandler {
122
123 @Override
124 public void startElement(String uri, String localName, String name,
125 Attributes attributes) {
126 checkSupportedElements(name, attributes);
127 checkSupportedAttributes(name, attributes);
128 checkMandatoryAttributes(name, attributes);
129 }
130
131 private static void checkSupportedElements(String elementName,
132 Attributes attributes) {
133 if (!SUPPORTED_ELEMENTS.containsKey(elementName)) {
134 throw new IllegalArgumentException(
135 "Unsupported element in markup text: " + elementName);
136 }
137 }
138
139 private static void checkSupportedAttributes(String elementName,
140 Attributes attributes) {
141 if (attributes.getLength() > 0) {
142 List<String> supportedAttributes = Arrays
143 .asList(SUPPORTED_ELEMENTS.get(elementName));
144 int index = 0;
145 String attributeName = attributes.getQName(index);
146 while (attributeName != null) {
147 if (!supportedAttributes.contains(attributeName)) {
148 String message = "Unsupported attribute \"{0}\" for element \"{1}\" in markup text";
149 message = MessageFormat.format(message, new Object[] {
150 attributeName, elementName });
151 throw new IllegalArgumentException(message);
152 }
153 index++;
154 attributeName = attributes.getQName(index);
155 }
156 }
157 }
158
159 private static void checkMandatoryAttributes(String elementName,
160 Attributes attributes) {
161 checkIntAttribute(elementName, attributes, "img", "width");
162 checkIntAttribute(elementName, attributes, "img", "height");
163 }
164
165 private static void checkIntAttribute(String elementName,
166 Attributes attributes, String checkedElementName,
167 String checkedAttributeName) {
168 if (checkedElementName.equals(elementName)) {
169 String attribute = attributes.getValue(checkedAttributeName);
170 try {
171 Integer.parseInt(attribute);
172 } catch (NumberFormatException exception) {
173 String message = "Mandatory attribute \"{0}\" for element \"{1}\" is missing or not a valid integer";
174 Object[] arguments = new Object[] { checkedAttributeName,
175 checkedElementName };
176 message = MessageFormat.format(message, arguments);
177 throw new IllegalArgumentException(message);
178 }
179 }
180 }
181
182 }
183
184 }