1 11 package org.eclipse.pde.internal.builders; 12 13 import java.util.*; 14 15 import org.eclipse.core.resources.*; 16 import org.eclipse.core.runtime.*; 17 import org.eclipse.osgi.util.NLS; 18 import org.eclipse.pde.internal.*; 19 import org.w3c.dom.*; 20 21 22 public class SchemaErrorReporter extends XMLErrorReporter { 23 24 class StackEntry { 25 String tag; 26 int line; 27 28 public StackEntry(String tag, int line) { 29 this.tag = tag; 30 this.line = line; 31 } 32 } 33 34 public static final String [] forbiddenEndTagKeys = 35 { 36 "area", "base", "basefont", "br", "col", "frame", "hr", "img", "input", "isindex", "link", "meta", "param" }; 50 public static final String [] optionalEndTagKeys = 51 { 52 "body", "colgroup", "dd", "dt", "head", "html", "li", "option", "p", "tbody", "td", "tfoot", "th", "thead", "tr" }; 68 69 public SchemaErrorReporter(IFile file) { 70 super(file); 71 } 72 73 public void validateContent(IProgressMonitor monitor) { 74 Element element = getDocumentRoot(); 75 if (element != null) 76 validateElement(element); 77 } 78 79 private void validateElement(Element element) { 80 if (element.getNodeName().equals("attribute")) validateAttribute(element); 82 83 NodeList children = element.getChildNodes(); 84 for (int i = 0; i < children.getLength(); i++) { 85 Node child = children.item(i); 86 if (child instanceof Element) { 87 if (child.getNodeName().equals("annotation")) { validateAnnotation((Element)child); 89 } else { 90 validateElement((Element)child); 91 } 92 } 93 } 94 } 95 96 private void validateAnnotation(Element element) { 97 NodeList children = element.getChildNodes(); 98 for (int i = 0; i < children.getLength(); i++) { 99 Node child = children.item(i); 100 if (child instanceof Element && child.getNodeName().equals("documentation")) { validateDocumentation((Element)child); 102 } 103 } 104 } 105 106 private void validateDocumentation(Element element) { 107 int flag = CompilerFlags.getFlag(fProject, CompilerFlags.S_OPEN_TAGS); 108 109 NodeList children = element.getChildNodes(); 110 for (int i = 0; i < children.getLength(); i++) { 111 if (children.item(i) instanceof Text) { 112 Text textNode = (Text)children.item(i); 113 StringTokenizer text = new StringTokenizer(textNode.getData(), "<>", true); 115 int lineNumber = getLine(element); 116 Stack stack = new Stack(); 117 boolean errorReported = false; 118 while (text.hasMoreTokens()) { 119 if (errorReported) 120 break; 121 122 String next = text.nextToken(); 123 if (next.equals("<")) { if (text.countTokens() > 2) { 125 String tagName = text.nextToken(); 126 String closing = text.nextToken(); 127 if (closing.equals(">")) { if (tagName.startsWith("!--") || tagName.endsWith("--")) { lineNumber += getLineBreakCount(tagName); 130 continue; 131 } 132 133 if (tagName.endsWith("/")) { tagName = getTagName(tagName.substring(0, tagName.length() - 1)); 135 if (forbiddenEndTag(tagName)) { 136 report(NLS.bind(PDEMessages.Builders_Schema_forbiddenEndTag, tagName), lineNumber, flag); errorReported = true; 138 } 139 } else if (tagName.startsWith("/")) { lineNumber += getLineBreakCount(tagName); 141 tagName = tagName.substring(1).trim(); 142 boolean found = false; 143 while (!stack.isEmpty()) { 144 StackEntry entry = (StackEntry)stack.peek(); 145 if (entry.tag.equalsIgnoreCase(tagName)) { 146 stack.pop(); 147 found = true; 148 break; 149 } else if (optionalEndTag(entry.tag)) { 150 stack.pop(); 151 } else { 152 break; 153 } 154 } 155 if (stack.isEmpty() && !found) { 156 report(NLS.bind(PDEMessages.Builders_Schema_noMatchingStartTag, tagName), lineNumber, flag); errorReported = true; 158 } 159 } else { 160 String shortTag = getTagName(tagName); 161 if (!forbiddenEndTag(shortTag)) 162 stack.push(new StackEntry(shortTag, lineNumber)); 163 lineNumber += getLineBreakCount(tagName); 164 } 165 } 166 } 167 } else { 168 lineNumber += getLineBreakCount(next); 169 } 170 } 171 if (!errorReported) { 172 if (!stack.isEmpty()) { 173 StackEntry entry = (StackEntry)stack.pop(); 174 if (!optionalEndTag(entry.tag)) 175 report(NLS.bind(PDEMessages.Builders_Schema_noMatchingEndTag, entry.tag), entry.line, flag); 176 } 177 stack.clear(); 178 } 179 } 180 } 181 } 182 183 private String getTagName(String text) { 184 StringTokenizer tokenizer = new StringTokenizer(text); 185 return tokenizer.nextToken(); 186 } 187 188 private boolean optionalEndTag(String tag) { 189 for (int i = 0; i < optionalEndTagKeys.length; i++) { 190 if (tag.equalsIgnoreCase(optionalEndTagKeys[i])) 191 return true; 192 } 193 return false; 194 } 195 196 private boolean forbiddenEndTag(String tag) { 197 for (int i = 0; i < forbiddenEndTagKeys.length; i++) { 198 if (tag.equalsIgnoreCase(forbiddenEndTagKeys[i])) 199 return true; 200 } 201 return false; 202 } 203 204 private int getLineBreakCount(String tag){ 205 StringTokenizer tokenizer = new StringTokenizer(tag, "\n", true); int token = 0; 207 while (tokenizer.hasMoreTokens()){ 208 if (tokenizer.nextToken().equals("\n")) token++; 210 } 211 return token; 212 } 213 214 private void validateAttribute(Element element) { 215 validateUse(element); 216 } 217 218 private void validateUse(Element element) { 219 Attr use = element.getAttributeNode("use"); Attr value = element.getAttributeNode("value"); if (use != null && "default".equals(use.getValue()) && value == null) { report(NLS.bind(PDEMessages.Builders_Schema_valueRequired, element.getNodeName()), getLine(element), 224 CompilerFlags.ERROR); 225 } else if (use == null && value != null) { 226 report(NLS.bind(PDEMessages.Builders_Schema_valueNotRequired, element.getNodeName()), getLine(element), 228 CompilerFlags.ERROR); 229 } 230 } 231 232 } 233 | Popular Tags |