PageRenderTime 28ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/netbeans-7.3/html.validation/src/org/netbeans/modules/html/validation/ValidationTransaction.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 1169 lines | 903 code | 128 blank | 138 comment | 164 complexity | f11f8654e84d81995ea182c20f34f8a6 MD5 | raw file
  1. /*
  2. * Copyright (c) 2005, 2006 Henri Sivonen
  3. * Copyright (c) 2007-2010 Mozilla Foundation
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. * and/or sell copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. */
  23. package org.netbeans.modules.html.validation;
  24. import com.thaiopensource.relaxng.impl.CombineValidator;
  25. import com.thaiopensource.util.PropertyMap;
  26. import com.thaiopensource.util.PropertyMapBuilder;
  27. import com.thaiopensource.validate.*;
  28. import com.thaiopensource.validate.auto.AutoSchemaReader;
  29. import com.thaiopensource.validate.prop.rng.RngProperty;
  30. import com.thaiopensource.validate.prop.wrap.WrapProperty;
  31. import com.thaiopensource.validate.rng.CompactSchemaReader;
  32. import com.thaiopensource.xml.sax.XMLReaderCreator;
  33. import java.io.*;
  34. import java.lang.ref.SoftReference;
  35. import java.net.URL;
  36. import java.util.*;
  37. import java.util.logging.Handler;
  38. import java.util.logging.Level;
  39. import java.util.logging.LogRecord;
  40. import java.util.logging.Logger;
  41. import java.util.regex.Pattern;
  42. import javax.xml.parsers.ParserConfigurationException;
  43. import javax.xml.parsers.SAXParser;
  44. import javax.xml.parsers.SAXParserFactory;
  45. import nu.validator.htmlparser.common.*;
  46. import nu.validator.htmlparser.sax.HtmlParser;
  47. import nu.validator.messages.MessageEmitterAdapter;
  48. import nu.validator.messages.TooManyErrorsException;
  49. import nu.validator.servlet.ParserMode;
  50. import nu.validator.source.SourceCode;
  51. import nu.validator.spec.Spec;
  52. import nu.validator.spec.html5.Html5SpecBuilder;
  53. import nu.validator.xml.*;
  54. import nu.validator.xml.dataattributes.DataAttributeDroppingSchemaWrapper;
  55. import nu.validator.xml.langattributes.XmlLangAttributeDroppingSchemaWrapper;
  56. import org.netbeans.api.progress.ProgressHandle;
  57. import org.netbeans.api.progress.ProgressHandleFactory;
  58. import org.netbeans.modules.html.editor.lib.api.HtmlVersion;
  59. import org.netbeans.modules.html.editor.lib.api.ProblemDescription;
  60. import org.netbeans.modules.html.validation.patched.BufferingRootNamespaceSniffer;
  61. import org.netbeans.modules.html.validation.patched.LocalCacheEntityResolver;
  62. import org.netbeans.modules.html.validation.patched.RootNamespaceSniffer;
  63. import org.openide.util.NbBundle;
  64. import org.whattf.checker.XmlPiChecker;
  65. import org.whattf.checker.jing.CheckerSchema;
  66. import org.whattf.io.DataUri;
  67. import org.xml.sax.*;
  68. import org.xml.sax.ext.LexicalHandler;
  69. /**
  70. * This class code was mainly extracted from the original class {@link VerifierServletTransaction}.
  71. *
  72. * @author hsivonen, mfukala@netbeans.org
  73. */
  74. public class ValidationTransaction implements DocumentModeHandler, SchemaResolver {
  75. private static final Logger LOGGER = Logger.getLogger(ValidationTransaction.class.getCanonicalName());
  76. public static void enableDebug() {
  77. LOGGER.setLevel(Level.FINE);
  78. LOGGER.addHandler(new Handler() {
  79. @Override
  80. public void publish(LogRecord record) {
  81. System.out.println(record.getMessage());
  82. }
  83. @Override
  84. public void flush() {
  85. }
  86. @Override
  87. public void close() throws SecurityException {
  88. }
  89. });
  90. }
  91. private static final Pattern SPACE = Pattern.compile("\\s+");
  92. protected static final int HTML5_SCHEMA = 3;
  93. protected static final int XHTML1STRICT_SCHEMA = 2;
  94. protected static final int XHTML1FRAMESET_SCHEMA = 4;
  95. protected static final int XHTML1TRANSITIONAL_SCHEMA = 1;
  96. protected static final int XHTML5_SCHEMA = 7;
  97. private static Spec html5spec;
  98. private static int[] presetDoctypes;
  99. private static String[] presetLabels;
  100. private static String[] presetUrls;
  101. private static String[] presetNamespaces;
  102. // XXX SVG!!!
  103. private static final String[] KNOWN_CONTENT_TYPES = {
  104. "application/atom+xml", "application/docbook+xml",
  105. "application/xhtml+xml", "application/xv+xml", "image/svg+xml"};
  106. private static final String[] NAMESPACES_FOR_KNOWN_CONTENT_TYPES = {
  107. "http://www.w3.org/2005/Atom", "http://docbook.org/ns/docbook",
  108. "http://www.w3.org/1999/xhtml", "http://www.w3.org/1999/xhtml",
  109. "http://www.w3.org/2000/svg"};
  110. private static final String[] ALL_CHECKERS = {
  111. "http://c.validator.nu/table/", "http://c.validator.nu/nfc/",
  112. "http://c.validator.nu/text-content/",
  113. "http://c.validator.nu/unchecked/",
  114. "http://c.validator.nu/usemap/", "http://c.validator.nu/obsolete/",
  115. "http://c.validator.nu/xml-pi/"};
  116. private static final String[] ALL_CHECKERS_HTML4 = {
  117. "http://c.validator.nu/table/", "http://c.validator.nu/nfc/",
  118. "http://c.validator.nu/unchecked/", "http://c.validator.nu/usemap/"};
  119. private static boolean INITIALIZED = false;
  120. private static String INTERNAL_ERROR_MSG_SEE_LOG = NbBundle.getMessage(ValidationTransaction.class, "MSG_Unexpected_Validator_Error_See_IDE_Log"); //NOI18N
  121. private static String INTERNAL_ERROR_MSG = NbBundle.getMessage(ValidationTransaction.class, "MSG_Unexpected_Validator_Error"); //NOI18N
  122. protected String document = null;
  123. ParserMode parser = ParserMode.AUTO;
  124. private boolean laxType = false;
  125. protected MessageEmitterAdapter errorHandler;
  126. protected final AttributesImpl attrs = new AttributesImpl();
  127. private PropertyMap jingPropertyMap;
  128. protected LocalCacheEntityResolver entityResolver;
  129. private static String[] preloadedSchemaUrls;
  130. private static Schema[] preloadedSchemas;
  131. private String schemaUrls = null;
  132. protected Validator validator = null;
  133. private BufferingRootNamespaceSniffer bufferingRootNamespaceSniffer = null;
  134. private String contentType = null;
  135. protected HtmlParser htmlParser = null;
  136. protected SAXParser xmlParser = null;
  137. protected XMLReader reader;
  138. private CharacterHandlerReader sourceReader;
  139. protected TypedInputSource documentInput;
  140. protected PrudentHttpEntityResolver httpRes;
  141. protected DataUriEntityResolver dataRes;
  142. protected ContentTypeParser contentTypeParser;
  143. private Map<String, Validator> loadedValidatorUrls = new HashMap<String, Validator>();
  144. private boolean checkNormalization = false;
  145. private boolean rootNamespaceSeen = false;
  146. private SourceCode sourceCode = new SourceCode();
  147. private boolean showSource;
  148. private BaseUriTracker baseUriTracker = null;
  149. private String charsetOverride = null;
  150. private Set<String> filteredNamespaces = new LinkedHashSet<String>(); // linked
  151. private LexicalHandler lexicalHandler;
  152. private String codeToValidate;
  153. private long validationTime;
  154. private ProblemsHandler problemsHandler = new ProblemsHandler();
  155. private LinesMapper linesMapper = new LinesMapper();
  156. private HtmlVersion version;
  157. private String encoding;
  158. public static synchronized ValidationTransaction create(HtmlVersion version) {
  159. return new ValidationTransaction(version);
  160. }
  161. private static void initializeLocalEntities_HACK() {
  162. //some of the validator's resources are read directly by URLConnection-s
  163. //using no entity resolver. The URLs are first checked in System properties
  164. //and if there's no property value defined the default network URL (http://...)
  165. //is used. This causes the support not working offline and if online
  166. //makes the initialization really slow.
  167. //hacked by loading the resources from the internall files cache via
  168. //returned internall URLs.
  169. //IMO should be fixed in validator.nu by using the local cache entity resolver.
  170. //MessageEmitterAdapter:
  171. URL url = LocalCacheEntityResolver.getResource("http://wiki.whatwg.org/wiki/MicrosyntaxDescriptions");
  172. System.setProperty("nu.validator.spec.microsyntax-descriptions", url.toExternalForm());
  173. url = LocalCacheEntityResolver.getResource("http://wiki.whatwg.org/wiki/Validator.nu_alt_advice");
  174. System.setProperty("nu.validator.spec.alt-advice", url.toExternalForm());
  175. //CharsetData:
  176. url = LocalCacheEntityResolver.getResource("http://www.iana.org/assignments/character-sets");
  177. System.setProperty("org.whattf.datatype.charset-registry", url.toExternalForm());
  178. //LanguageData:
  179. url = LocalCacheEntityResolver.getResource("http://www.iana.org/assignments/language-subtag-registry");
  180. System.setProperty("org.whattf.datatype.lang-registry", url.toExternalForm());
  181. }
  182. private static synchronized void initialize() {
  183. if (INITIALIZED) {
  184. return;
  185. }
  186. ProgressHandle progress = ProgressHandleFactory.createHandle(
  187. NbBundle.getMessage(ValidationTransaction.class, "MSG_InitHTMLValidation")); //NOI18N
  188. progress.start();
  189. progress.switchToIndeterminate();
  190. initializeLocalEntities_HACK();
  191. try {
  192. LOGGER.fine("Starting initialization.");
  193. BufferedReader r = new BufferedReader(new InputStreamReader(LocalCacheEntityResolver.getPresetsAsStream(), "UTF-8"));
  194. String line;
  195. List<String> doctypes = new LinkedList<String>();
  196. List<String> namespaces = new LinkedList<String>();
  197. List<String> labels = new LinkedList<String>();
  198. List<String> urls = new LinkedList<String>();
  199. LOGGER.fine("Starting to loop over config file lines.");
  200. while ((line = r.readLine()) != null) {
  201. if ("".equals(line.trim())) {
  202. break;
  203. }
  204. String s[] = line.split("\t");
  205. doctypes.add(s[0]);
  206. namespaces.add(s[1]);
  207. labels.add(s[2]);
  208. urls.add(s[3]);
  209. }
  210. // progress.start(10 * (urls.size() + 50) /* reading the html spec */);
  211. // progress.progress(NbBundle.getMessage(ValidationTransaction.class, "MSG_LoadingSchemaFiles"));
  212. LOGGER.fine("Finished reading config.");
  213. String[] presetDoctypesAsStrings = doctypes.toArray(new String[0]);
  214. presetNamespaces = namespaces.toArray(new String[0]);
  215. presetLabels = labels.toArray(new String[0]);
  216. presetUrls = urls.toArray(new String[0]);
  217. LOGGER.fine("Converted config to arrays.");
  218. for (int i = 0; i < presetNamespaces.length; i++) {
  219. String str = presetNamespaces[i];
  220. if ("-".equals(str)) {
  221. presetNamespaces[i] = null;
  222. } else {
  223. presetNamespaces[i] = presetNamespaces[i].intern();
  224. }
  225. }
  226. LOGGER.fine("Prepared namespace array.");
  227. presetDoctypes = new int[presetDoctypesAsStrings.length];
  228. for (int i = 0; i < presetDoctypesAsStrings.length; i++) {
  229. presetDoctypes[i] = Integer.parseInt(presetDoctypesAsStrings[i]);
  230. }
  231. LOGGER.fine("Parsed doctype numbers into ints.");
  232. // String prefix = System.getProperty("nu.validator.servlet.cachepathprefix");
  233. // log4j.fine("The cache path prefix is: " + prefix);
  234. ErrorHandler eh = new SystemErrErrorHandler();
  235. LocalCacheEntityResolver er = new LocalCacheEntityResolver(new NullEntityResolver());
  236. er.setAllowRnc(true);
  237. PropertyMapBuilder pmb = new PropertyMapBuilder();
  238. pmb.put(ValidateProperty.ERROR_HANDLER, eh);
  239. pmb.put(ValidateProperty.ENTITY_RESOLVER, er);
  240. pmb.put(ValidateProperty.XML_READER_CREATOR,
  241. new XMLReaderCreatorImpl(eh, er));
  242. RngProperty.CHECK_ID_IDREF.add(pmb);
  243. PropertyMap pMap = pmb.toPropertyMap();
  244. LOGGER.fine("Parsing set up. Starting to read schemas.");
  245. SortedMap<String, Schema> schemaMap = new TreeMap<String, Schema>();
  246. schemaMap.put("http://c.validator.nu/table/",
  247. CheckerSchema.TABLE_CHECKER);
  248. schemaMap.put("http://hsivonen.iki.fi/checkers/table/",
  249. CheckerSchema.TABLE_CHECKER);
  250. schemaMap.put("http://c.validator.nu/nfc/",
  251. CheckerSchema.NORMALIZATION_CHECKER);
  252. schemaMap.put("http://hsivonen.iki.fi/checkers/nfc/",
  253. CheckerSchema.NORMALIZATION_CHECKER);
  254. schemaMap.put("http://c.validator.nu/debug/",
  255. CheckerSchema.DEBUG_CHECKER);
  256. schemaMap.put("http://hsivonen.iki.fi/checkers/debug/",
  257. CheckerSchema.DEBUG_CHECKER);
  258. schemaMap.put("http://c.validator.nu/text-content/",
  259. CheckerSchema.TEXT_CONTENT_CHECKER);
  260. schemaMap.put("http://hsivonen.iki.fi/checkers/text-content/",
  261. CheckerSchema.TEXT_CONTENT_CHECKER);
  262. schemaMap.put("http://c.validator.nu/usemap/",
  263. CheckerSchema.USEMAP_CHECKER);
  264. schemaMap.put("http://n.validator.nu/checkers/usemap/",
  265. CheckerSchema.USEMAP_CHECKER);
  266. schemaMap.put("http://c.validator.nu/unchecked/",
  267. CheckerSchema.UNCHECKED_SUBTREE_WARNER);
  268. schemaMap.put("http://s.validator.nu/html5/assertions.sch",
  269. CheckerSchema.ASSERTION_SCH);
  270. schemaMap.put("http://c.validator.nu/obsolete/",
  271. CheckerSchema.CONFORMING_BUT_OBSOLETE_WARNER);
  272. schemaMap.put("http://c.validator.nu/xml-pi/",
  273. CheckerSchema.XML_PI_CHECKER);
  274. for (int i = 0; i < presetUrls.length; i++) {
  275. String[] urls1 = SPACE.split(presetUrls[i]);
  276. for (int j = 0; j < urls1.length; j++) {
  277. String url = urls1[j];
  278. if (schemaMap.get(url) == null && !isCheckerUrl(url)) {
  279. Schema sch = proxySchemaByUrl(url, er, pMap);
  280. schemaMap.put(url, sch);
  281. // progress.progress(10);
  282. }
  283. }
  284. }
  285. LOGGER.fine("Schemas read.");
  286. preloadedSchemaUrls = new String[schemaMap.size()];
  287. preloadedSchemas = new Schema[schemaMap.size()];
  288. int i = 0;
  289. for (Map.Entry<String, Schema> entry : schemaMap.entrySet()) {
  290. preloadedSchemaUrls[i] = entry.getKey().intern();
  291. Schema s = entry.getValue();
  292. String u = entry.getKey();
  293. if (isDataAttributeDroppingSchema(u)) {
  294. s = new DataAttributeDroppingSchemaWrapper(
  295. s);
  296. }
  297. if (isXmlLangAllowingSchema(u)) {
  298. s = new XmlLangAttributeDroppingSchemaWrapper(s);
  299. }
  300. preloadedSchemas[i] = s;
  301. i++;
  302. }
  303. // progress.progress(NbBundle.getMessage(ValidationTransaction.class, "MSG_LoadingHtmlSpecification"));
  304. LOGGER.fine("Reading spec.");
  305. html5spec = Html5SpecBuilder.parseSpec(LocalCacheEntityResolver.getHtml5SpecAsStream());
  306. // progress.progress(50);
  307. LOGGER.fine("Spec read.");
  308. LOGGER.fine("Initialization complete.");
  309. INITIALIZED = true;
  310. } catch (Exception e) {
  311. throw new RuntimeException(e);
  312. } finally {
  313. progress.finish();
  314. }
  315. }
  316. private static boolean isDataAttributeDroppingSchema(String key) {
  317. return ("http://s.validator.nu/html5/html5full.rnc".equals(key)
  318. || "http://s.validator.nu/html5/html5full-aria.rnc".equals(key)
  319. || "http://s.validator.nu/html5/xhtml5full-xhtml.rnc".equals(key)
  320. || "http://s.validator.nu/xhtml5-aria-rdf-svg-mathml.rnc".equals(key) || "http://s.validator.nu/html5-aria-svg-mathml.rnc".equals(key));
  321. }
  322. private static boolean isXmlLangAllowingSchema(String key) {
  323. return ("http://s.validator.nu/html5/html5full.rnc".equals(key)
  324. || "http://s.validator.nu/html5/html5full-aria.rnc".equals(key)
  325. || "http://s.validator.nu/html5/xhtml5full-xhtml.rnc".equals(key)
  326. || "http://s.validator.nu/xhtml5-aria-rdf-svg-mathml.rnc".equals(key) || "http://s.validator.nu/html5-aria-svg-mathml.rnc".equals(key));
  327. }
  328. private static boolean isCheckerUrl(String url) {
  329. if ("http://c.validator.nu/all/".equals(url)
  330. || "http://hsivonen.iki.fi/checkers/all/".equals(url)) {
  331. return true;
  332. } else if ("http://c.validator.nu/all-html4/".equals(url)
  333. || "http://hsivonen.iki.fi/checkers/all-html4/".equals(url)) {
  334. return true;
  335. }
  336. for (int i = 0; i < ALL_CHECKERS.length; i++) {
  337. if (ALL_CHECKERS[i].equals(url)) {
  338. return true;
  339. }
  340. }
  341. return false;
  342. }
  343. public ValidationTransaction(HtmlVersion version) {
  344. this.version = version;
  345. initialize();
  346. }
  347. public List<ProblemDescription> getFoundProblems() {
  348. return problemsHandler.getProblems();
  349. }
  350. /** return a list of problems with the given severity and higher (more severe issues) */
  351. public List<ProblemDescription> getFoundProblems(int ofThisTypeAndMoreSevere) {
  352. return getFoundProblems(new ProblemDescriptionFilter.SeverityFilter(ofThisTypeAndMoreSevere));
  353. }
  354. public List<ProblemDescription> getFoundProblems(ProblemDescriptionFilter filter) {
  355. List<ProblemDescription> filtered = new ArrayList<ProblemDescription>();
  356. for (ProblemDescription pd : getFoundProblems()) {
  357. if (filter.accepts(pd)) {
  358. filtered.add(pd);
  359. }
  360. }
  361. return filtered;
  362. }
  363. public long getValidationTime() {
  364. return validationTime;
  365. }
  366. public void validateCode(String code, String sourceURI, Set<String> filteredNamespaces, String encoding) throws SAXException {
  367. long from = System.currentTimeMillis();
  368. codeToValidate = code;
  369. document = sourceURI; //represents an URI where the document can be loaded
  370. parser = htmlVersion2ParserMode(version);
  371. LOGGER.fine(String.format("Using %s parser.", parser.name()));
  372. // charsetOverride = "UTF-8";
  373. this.encoding = encoding;
  374. this.filteredNamespaces = filteredNamespaces;
  375. if (!filteredNamespaces.isEmpty()) {
  376. StringBuilder fns = new StringBuilder();
  377. for (String ns : filteredNamespaces) {
  378. fns.append(ns).append(", ");
  379. }
  380. LOGGER.fine(String.format("Filtering following namespaces: %s", fns));
  381. }
  382. int lineOffset = 0;
  383. errorHandler = new MessageEmitterAdapter(sourceCode,
  384. showSource, null, lineOffset,
  385. new NbMessageEmitter(problemsHandler, linesMapper, true));
  386. errorHandler.setLoggingOk(true);
  387. errorHandler.setErrorsOnly(false);
  388. validate();
  389. validationTime = System.currentTimeMillis() - from;
  390. }
  391. public boolean isSuccess() {
  392. return getFoundProblems(ProblemDescription.WARNING).isEmpty();
  393. }
  394. private ParserMode htmlVersion2ParserMode(HtmlVersion version) {
  395. if (version.isXhtml()) {
  396. return ParserMode.XML_NO_EXTERNAL_ENTITIES; //we do not use the parser for validation, no need to load external entities
  397. } else {
  398. switch (version) {
  399. case HTML41_STRICT:
  400. return ParserMode.HTML401_STRICT;
  401. case HTML41_TRANSATIONAL:
  402. return ParserMode.HTML401_TRANSITIONAL;
  403. case HTML41_FRAMESET:
  404. return ParserMode.AUTO; //???
  405. case HTML5:
  406. return ParserMode.HTML;
  407. default:
  408. return ParserMode.AUTO;
  409. }
  410. }
  411. }
  412. private boolean isHtmlUnsafePreset() {
  413. if ("".equals(schemaUrls)) {
  414. return false;
  415. }
  416. boolean preset = false;
  417. for (int i = 0; i < presetUrls.length; i++) {
  418. if (presetUrls[i].equals(schemaUrls)) {
  419. preset = true;
  420. break;
  421. }
  422. }
  423. if (!preset) {
  424. return false;
  425. }
  426. return !(schemaUrls.startsWith("http://s.validator.nu/xhtml10/xhtml-basic.rnc")
  427. || schemaUrls.startsWith("http://s.validator.nu/xhtml10/xhtml-strict.rnc")
  428. || schemaUrls.startsWith("http://s.validator.nu/xhtml10/xhtml-transitional.rnc")
  429. || schemaUrls.startsWith("http://s.validator.nu/xhtml10/xhtml-frameset.rnc")
  430. || schemaUrls.startsWith("http://s.validator.nu/html5/html5full.rnc")
  431. || schemaUrls.startsWith("http://s.validator.nu/html5/html5full-aria.rnc") || schemaUrls.startsWith("http://s.validator.nu/html5-aria-svg-mathml.rnc"));
  432. }
  433. @SuppressWarnings("deprecation")
  434. void validate() throws SAXException {
  435. // httpRes = new PrudentHttpEntityResolver(SIZE_LIMIT, laxType,
  436. // errorHandler);
  437. // dataRes = new DataUriEntityResolver(httpRes, laxType, errorHandler);
  438. // contentTypeParser = new ContentTypeParser(errorHandler, laxType);
  439. // entityResolver = new LocalCacheEntityResolver(dataRes);
  440. entityResolver = new LocalCacheEntityResolver(new NullEntityResolver());
  441. setAllowRnc(true);
  442. try {
  443. this.errorHandler.start(document);
  444. PropertyMapBuilder pmb = new PropertyMapBuilder();
  445. pmb.put(ValidateProperty.ERROR_HANDLER, errorHandler);
  446. pmb.put(ValidateProperty.ENTITY_RESOLVER, entityResolver);
  447. pmb.put(ValidateProperty.XML_READER_CREATOR,
  448. new XMLReaderCreatorImpl(errorHandler,
  449. entityResolver));
  450. pmb.put(ValidateProperty.SCHEMA_RESOLVER, this);
  451. RngProperty.CHECK_ID_IDREF.add(pmb);
  452. jingPropertyMap = pmb.toPropertyMap();
  453. // tryToSetupValidator();
  454. setAllowRnc(false);
  455. loadDocAndSetupParser();
  456. if (htmlParser != null) {
  457. setErrorProfile();
  458. }
  459. reader.setErrorHandler(errorHandler);
  460. contentType = documentInput.getType();
  461. sourceCode.initialize(documentInput);
  462. WiretapXMLReaderWrapper wiretap = new WiretapXMLReaderWrapper(
  463. reader);
  464. boolean isXhtml = parser == ParserMode.XML_EXTERNAL_ENTITIES_NO_VALIDATION
  465. || parser == ParserMode.XML_NO_EXTERNAL_ENTITIES;
  466. ContentHandler recorder = isXhtml
  467. ? new XercesInaccurateLocatorWorkaround(sourceCode.getLocationRecorder(), linesMapper)
  468. : sourceCode.getLocationRecorder();
  469. if (baseUriTracker == null) {
  470. wiretap.setWiretapContentHander(recorder);
  471. } else {
  472. wiretap.setWiretapContentHander(new CombineContentHandler(
  473. recorder, baseUriTracker));
  474. }
  475. wiretap.setWiretapLexicalHandler((LexicalHandler) recorder);
  476. reader = wiretap;
  477. if (htmlParser != null) {
  478. htmlParser.addCharacterHandler(linesMapper);
  479. htmlParser.addCharacterHandler(sourceCode);
  480. htmlParser.setMappingLangToXmlLang(true);
  481. htmlParser.setErrorHandler(errorHandler.getExactErrorHandler());
  482. htmlParser.setTreeBuilderErrorHandlerOverride(errorHandler);
  483. errorHandler.setHtml(true);
  484. } else if (xmlParser != null) {
  485. // this must be after wiretap!
  486. if (!filteredNamespaces.isEmpty()) {
  487. reader = new NamespaceDroppingXMLReaderWrapper(reader,
  488. filteredNamespaces);
  489. }
  490. xmlParser.getXMLReader().setErrorHandler(errorHandler.getExactErrorHandler());
  491. sourceReader.addCharacterHandler(linesMapper);
  492. } else {
  493. throw new RuntimeException("Bug. Unreachable.");
  494. }
  495. reader = new AttributesPermutingXMLReaderWrapper(reader); // make
  496. // RNG
  497. // validation
  498. // better
  499. if (charsetOverride != null) {
  500. String charset = documentInput.getEncoding();
  501. if (charset == null) {
  502. errorHandler.warning(new SAXParseException(
  503. "Overriding document character encoding from none to \u201C"
  504. + charsetOverride + "\u201D.", null));
  505. } else {
  506. errorHandler.warning(new SAXParseException(
  507. "Overriding document character encoding from \u201C"
  508. + charset + "\u201D to \u201C"
  509. + charsetOverride + "\u201D.", null));
  510. }
  511. documentInput.setEncoding(charsetOverride);
  512. }
  513. reader.parse(documentInput);
  514. } catch (ParserConfigurationException e) {
  515. LOGGER.log(Level.INFO, getDocumentErrorMsg(), e);
  516. errorHandler.internalError(
  517. e,
  518. INTERNAL_ERROR_MSG_SEE_LOG);
  519. } catch (TooManyErrorsException e) {
  520. LOGGER.log(Level.FINE, getDocumentErrorMsg(), e);
  521. errorHandler.fatalError(e);
  522. } catch (SAXException e) {
  523. LOGGER.log(Level.FINE, getDocumentErrorMsg(), e);
  524. } catch (IOException e) {
  525. LOGGER.log(Level.INFO, getDocumentErrorMsg(), e);
  526. errorHandler.ioError(e);
  527. } catch (IncorrectSchemaException e) {
  528. LOGGER.log(Level.INFO, getDocumentErrorMsg(), e);
  529. errorHandler.schemaError(e);
  530. } catch (RuntimeException e) {
  531. String message = reportRuntimeExceptionOnce(e)
  532. ? INTERNAL_ERROR_MSG_SEE_LOG
  533. : INTERNAL_ERROR_MSG;
  534. errorHandler.internalError(e, message);
  535. } catch (Error e) {
  536. LOGGER.log(Level.INFO, getDocumentInternalErrorMsg(), e);
  537. errorHandler.internalError(
  538. e,
  539. INTERNAL_ERROR_MSG_SEE_LOG);
  540. } finally {
  541. errorHandler.end(successMessage(), failureMessage());
  542. }
  543. }
  544. private static final Set<Marker> REPORTED_RUNTIME_EXCEPTIONS = new HashSet<Marker>();
  545. /**
  546. * Report REs only once per ide session and use lower log levels for known issues
  547. *
  548. * @return true if the exception has been logged and is visible in the IDE log
  549. */
  550. private boolean reportRuntimeExceptionOnce(RuntimeException e) {
  551. int hash = document.hashCode();
  552. hash = 21 * hash + e.getClass().hashCode();
  553. if(e.getMessage() != null) {
  554. hash = 21 * hash + e.getMessage().hashCode();
  555. } else {
  556. //no message provided, so use the whole stacktrace hashcode
  557. StringWriter sw = new StringWriter();
  558. PrintWriter pw = new PrintWriter(sw);
  559. e.printStackTrace(pw);
  560. pw.flush();
  561. sw.flush();
  562. hash = 21 * hash + sw.toString().hashCode();
  563. }
  564. Level level = isKnownProblem(e) ? Level.FINE : Level.INFO;
  565. Marker marker = new Marker(hash);
  566. if(REPORTED_RUNTIME_EXCEPTIONS.add(marker)) {
  567. LOGGER.log(level, getDocumentInternalErrorMsg(), e);
  568. }
  569. return LOGGER.isLoggable(level);
  570. }
  571. private static boolean isKnownProblem(RuntimeException e) {
  572. //issue #194939
  573. Class eClass = e.getClass();
  574. if(eClass.equals(StringIndexOutOfBoundsException.class)) {
  575. StackTraceElement[] stelements = e.getStackTrace();
  576. if(stelements.length >= 1) {
  577. if(stelements[1].getClassName().equals("com.thaiopensource.validate.schematron.OutputHandler") //NOI18N
  578. && stelements[1].getMethodName().equals("startElement")) { //NOI18N
  579. return true;
  580. }
  581. }
  582. } else if(eClass.equals(IllegalStateException.class)) {
  583. //Bug 199647 - Failed validation and IllegalStateException during pojects scanning
  584. String msg = "Two cells in effect cannot start on the same column, so this should never happen!"; //NOI18N
  585. return e.getMessage() != null && e.getMessage().indexOf(msg) != -1;
  586. }
  587. return false;
  588. }
  589. private String getDocumentErrorMsg() {
  590. return new StringBuilder().append("An error occurred during validation of ").append(document).toString(); //NOI18N
  591. }
  592. private String getDocumentInternalErrorMsg() {
  593. return new StringBuilder().append("An internal error occurred during validation of ").append(document).toString(); //NOI18N
  594. }
  595. /**
  596. * @return
  597. * @throws SAXException
  598. */
  599. protected String successMessage() throws SAXException {
  600. return "The document validates according to the specified schema(s).";
  601. }
  602. protected String failureMessage() throws SAXException {
  603. return "There were errors.";
  604. }
  605. /**
  606. * @throws SAXException
  607. * @throws IOException
  608. * @throws IncorrectSchemaException
  609. */
  610. protected void tryToSetupValidator() throws SAXException, IOException,
  611. IncorrectSchemaException {
  612. validator = validatorByUrls(schemaUrls);
  613. }
  614. protected void setErrorProfile() {
  615. // profile = request.getParameter("profile");
  616. HashMap<String, String> profileMap = new HashMap<String, String>();
  617. // if ("pedagogical".equals(profile)) {
  618. // profileMap.put("xhtml1", "warn");
  619. // } else if ("polyglot".equals(profile)) {
  620. // profileMap.put("xhtml1", "warn");
  621. // profileMap.put("xhtml2", "warn");
  622. // } else {
  623. // return; // presumed to be permissive
  624. // }
  625. htmlParser.setErrorProfile(profileMap);
  626. }
  627. /**
  628. * @throws SAXException
  629. * @throws IOException
  630. * @throws IncorrectSchemaException
  631. * @throws SAXNotRecognizedException
  632. * @throws SAXNotSupportedException
  633. */
  634. protected void loadDocAndSetupParser() throws SAXException, IOException,
  635. IncorrectSchemaException, SAXNotRecognizedException,
  636. SAXNotSupportedException, ParserConfigurationException {
  637. switch (parser) {
  638. case HTML_AUTO:
  639. case HTML:
  640. case HTML401_STRICT:
  641. case HTML401_TRANSITIONAL:
  642. if (isHtmlUnsafePreset()) {
  643. String message = "The chosen preset schema is not appropriate for HTML.";
  644. SAXException se = new SAXException(message);
  645. errorHandler.schemaError(se);
  646. throw se;
  647. }
  648. setAllowGenericXml(false);
  649. setAllowHtml(true);
  650. setAcceptAllKnownXmlTypes(false);
  651. setAllowXhtml(false);
  652. loadDocumentInput(false);
  653. newHtmlParser();
  654. DoctypeExpectation doctypeExpectation;
  655. int schemaId;
  656. switch (parser) {
  657. case HTML:
  658. doctypeExpectation = DoctypeExpectation.HTML;
  659. schemaId = HTML5_SCHEMA;
  660. break;
  661. case HTML401_STRICT:
  662. doctypeExpectation = DoctypeExpectation.HTML401_STRICT;
  663. schemaId = XHTML1STRICT_SCHEMA;
  664. break;
  665. case HTML401_TRANSITIONAL:
  666. doctypeExpectation = DoctypeExpectation.HTML401_TRANSITIONAL;
  667. schemaId = XHTML1TRANSITIONAL_SCHEMA;
  668. break;
  669. default:
  670. doctypeExpectation = DoctypeExpectation.AUTO;
  671. schemaId = 0;
  672. break;
  673. }
  674. htmlParser.setDoctypeExpectation(doctypeExpectation);
  675. htmlParser.setDocumentModeHandler(this);
  676. // htmlParser.setProperty("http://validator.nu/properties/body-fragment-context-mode", bodyFragmentContextMode);
  677. reader = htmlParser;
  678. if (validator == null) {
  679. LOGGER.fine(String.format("Using following schemas: %s", getSchemasForDoctypeId(schemaId)));
  680. validator = validatorByDoctype(schemaId);
  681. }
  682. if (validator != null) {
  683. reader.setContentHandler(validator.getContentHandler());
  684. }
  685. break;
  686. case XML_NO_EXTERNAL_ENTITIES:
  687. case XML_EXTERNAL_ENTITIES_NO_VALIDATION:
  688. setAllowGenericXml(true);
  689. setAllowHtml(false);
  690. setAcceptAllKnownXmlTypes(true);
  691. setAllowXhtml(true);
  692. loadDocumentInput(true);
  693. if (version != null) {
  694. switch (version) {
  695. case XHTML10_TRANSATIONAL:
  696. schemaId = XHTML1TRANSITIONAL_SCHEMA;
  697. break;
  698. case XHTML10_STICT:
  699. schemaId = XHTML1STRICT_SCHEMA;
  700. break;
  701. case XHTML10_FRAMESET:
  702. schemaId = XHTML1FRAMESET_SCHEMA;
  703. break;
  704. default:
  705. schemaId = 0;
  706. }
  707. if (schemaId != 0) {
  708. validator = validatorByDoctype(schemaId);
  709. LOGGER.fine(String.format("Using following schemas: %s", getSchemasForDoctypeId(schemaId)));
  710. }
  711. }
  712. setupXmlParser();
  713. break;
  714. default:
  715. setAllowGenericXml(true);
  716. setAllowHtml(true);
  717. setAcceptAllKnownXmlTypes(true);
  718. setAllowXhtml(true);
  719. loadDocumentInput(false);
  720. if ("text/html".equals(documentInput.getType())) {
  721. if (isHtmlUnsafePreset()) {
  722. String message = "The Content-Type was \u201Ctext/html\u201D, but the chosen preset schema is not appropriate for HTML.";
  723. SAXException se = new SAXException(message);
  724. errorHandler.schemaError(se);
  725. throw se;
  726. }
  727. errorHandler.info("The Content-Type was \u201Ctext/html\u201D. Using the HTML parser.");
  728. newHtmlParser();
  729. htmlParser.setDoctypeExpectation(DoctypeExpectation.AUTO);
  730. htmlParser.setDocumentModeHandler(this);
  731. reader = htmlParser;
  732. if (validator != null) {
  733. reader.setContentHandler(validator.getContentHandler());
  734. }
  735. } else {
  736. errorHandler.info("The Content-Type was \u201C"
  737. + documentInput.getType()
  738. + "\u201D. Using the XML parser (not resolving external entities).");
  739. setupXmlParser();
  740. }
  741. break;
  742. }
  743. }
  744. /**
  745. *
  746. */
  747. protected void newHtmlParser() {
  748. htmlParser = new HtmlParser();
  749. htmlParser.setCommentPolicy(XmlViolationPolicy.ALLOW);
  750. htmlParser.setContentNonXmlCharPolicy(XmlViolationPolicy.ALLOW);
  751. htmlParser.setContentSpacePolicy(XmlViolationPolicy.ALTER_INFOSET);
  752. htmlParser.setNamePolicy(XmlViolationPolicy.ALLOW);
  753. htmlParser.setStreamabilityViolationPolicy(XmlViolationPolicy.FATAL);
  754. htmlParser.setXmlnsPolicy(XmlViolationPolicy.ALTER_INFOSET);
  755. htmlParser.setMappingLangToXmlLang(true);
  756. htmlParser.setHtml4ModeCompatibleWithXhtml1Schemata(true);
  757. htmlParser.setHeuristics(Heuristics.ALL);
  758. htmlParser.setEntityResolver(entityResolver);
  759. }
  760. protected Validator validatorByDoctype(int schemaId) throws SAXException,
  761. IOException, IncorrectSchemaException {
  762. if (schemaId == 0) {
  763. return null;
  764. }
  765. for (int i = 0; i < presetDoctypes.length; i++) {
  766. if (presetDoctypes[i] == schemaId) {
  767. return validatorByUrls(presetUrls[i]);
  768. }
  769. }
  770. throw new RuntimeException("Doctype mappings not initialized properly.");
  771. }
  772. /**
  773. * @param entityResolver2
  774. * @return
  775. * @throws SAXNotRecognizedException
  776. * @throws SAXNotSupportedException
  777. */
  778. protected void setupXmlParser() throws SAXNotRecognizedException,
  779. SAXNotSupportedException,
  780. ParserConfigurationException,
  781. SAXException {
  782. SAXParserFactory factory = SAXParserFactory.newInstance();
  783. factory.setNamespaceAware(true);
  784. factory.setValidating(false);
  785. xmlParser = factory.newSAXParser();
  786. // xmlParser.getXMLReader().setFeature(
  787. // "http://apache.org/xml/features/continue-after-fatal-error",
  788. // true);
  789. sourceReader.addCharacterHandler(sourceCode);
  790. reader = new IdFilter(xmlParser.getXMLReader());
  791. if (lexicalHandler != null) {
  792. xmlParser.setProperty("http://xml.org/sax/properties/lexical-handler",
  793. (LexicalHandler) lexicalHandler);
  794. }
  795. reader.setFeature("http://xml.org/sax/features/string-interning", true);
  796. reader.setFeature(
  797. "http://xml.org/sax/features/external-general-entities",
  798. parser == ParserMode.XML_EXTERNAL_ENTITIES_NO_VALIDATION);
  799. reader.setFeature(
  800. "http://xml.org/sax/features/external-parameter-entities",
  801. parser == ParserMode.XML_EXTERNAL_ENTITIES_NO_VALIDATION);
  802. if (parser == ParserMode.XML_EXTERNAL_ENTITIES_NO_VALIDATION) {
  803. reader.setEntityResolver(entityResolver);
  804. } else {
  805. reader.setEntityResolver(new NullEntityResolver());
  806. }
  807. if (validator == null) {
  808. bufferingRootNamespaceSniffer = new BufferingRootNamespaceSniffer(
  809. this);
  810. reader.setContentHandler(bufferingRootNamespaceSniffer);
  811. } else {
  812. reader.setContentHandler(new RootNamespaceSniffer(this,
  813. validator.getContentHandler()));
  814. reader.setDTDHandler(validator.getDTDHandler());
  815. }
  816. }
  817. /**
  818. * @param validator
  819. * @return
  820. * @throws SAXException
  821. * @throws IOException
  822. * @throws IncorrectSchemaException
  823. */
  824. private Validator validatorByUrls(String schemaList) throws SAXException,
  825. IOException, IncorrectSchemaException {
  826. Validator v = null;
  827. String[] schemas = SPACE.split(schemaList);
  828. for (int i = schemas.length - 1; i > -1; i--) {
  829. String url = schemas[i];
  830. if ("http://c.validator.nu/all/".equals(url)
  831. || "http://hsivonen.iki.fi/checkers/all/".equals(url)) {
  832. for (int j = 0; j < ALL_CHECKERS.length; j++) {
  833. v = combineValidatorByUrl(v, ALL_CHECKERS[j]);
  834. }
  835. } else if ("http://c.validator.nu/all-html4/".equals(url)
  836. || "http://hsivonen.iki.fi/checkers/all-html4/".equals(url)) {
  837. for (int j = 0; j < ALL_CHECKERS_HTML4.length; j++) {
  838. v = combineValidatorByUrl(v, ALL_CHECKERS_HTML4[j]);
  839. }
  840. } else {
  841. v = combineValidatorByUrl(v, url);
  842. }
  843. }
  844. return v;
  845. }
  846. /**
  847. * @param val
  848. * @param url
  849. * @return
  850. * @throws SAXException
  851. * @throws IOException
  852. * @throws IncorrectSchemaException
  853. */
  854. private Validator combineValidatorByUrl(Validator val, String url)
  855. throws SAXException, IOException, IncorrectSchemaException {
  856. if (!"".equals(url)) {
  857. Validator v = validatorByUrl(url);
  858. if (val == null) {
  859. val = v;
  860. } else {
  861. val = new CombineValidator(v, val);
  862. }
  863. }
  864. return val;
  865. }
  866. /**
  867. * @param url
  868. * @return
  869. * @throws SAXException
  870. * @throws IOException
  871. * @throws IncorrectSchemaException
  872. */
  873. private Validator validatorByUrl(String url) throws SAXException,
  874. IOException, IncorrectSchemaException {
  875. Validator v = loadedValidatorUrls.get(url);
  876. if (v != null) {
  877. return v;
  878. }
  879. if ("http://s.validator.nu/html5/html5full-aria.rnc".equals(url)
  880. || "http://s.validator.nu/xhtml5-aria-rdf-svg-mathml.rnc".equals(url)
  881. || "http://s.validator.nu/html5/html5full.rnc".equals(url)
  882. || "http://s.validator.nu/html5/xhtml5full-xhtml.rnc".equals(url)
  883. || "http://s.validator.nu/html5-aria-svg-mathml.rnc".equals(url)) {
  884. errorHandler.setSpec(html5spec);
  885. }
  886. Schema sch = resolveSchema(url, jingPropertyMap);
  887. Validator validatorInstance = sch.createValidator(jingPropertyMap);
  888. if (validatorInstance.getContentHandler() instanceof XmlPiChecker) {
  889. lexicalHandler = (LexicalHandler) validatorInstance.getContentHandler();
  890. }
  891. loadedValidatorUrls.put(url, v);
  892. return validatorInstance;
  893. }
  894. public Schema resolveSchema(String url, PropertyMap options)
  895. throws SAXException, IOException, IncorrectSchemaException {
  896. int i = Arrays.binarySearch(preloadedSchemaUrls, url);
  897. if (i > -1) {
  898. Schema rv = preloadedSchemas[i];
  899. if (options.contains(WrapProperty.ATTRIBUTE_OWNER)) {
  900. if(rv instanceof ProxySchema && ((ProxySchema)rv).getWrappedSchema() instanceof CheckerSchema) {
  901. errorHandler.error(new SAXParseException(
  902. "A non-schema checker cannot be used as an attribute schema.",
  903. null, url, -1, -1));
  904. throw new IncorrectSchemaException();
  905. } else {
  906. // ugly fall through
  907. }
  908. } else {
  909. return rv;
  910. }
  911. }
  912. //this code line should not normally be encountered since the necessary
  913. //schemas have been preloaded
  914. LOGGER.log(Level.INFO, "Going to create a non preloaded Schema for {0}", url); //NOI18N
  915. TypedInputSource schemaInput = (TypedInputSource) entityResolver.resolveEntity(
  916. null, url);
  917. SchemaReader sr = null;
  918. if ("application/relax-ng-compact-syntax".equals(schemaInput.getType())) {
  919. sr = CompactSchemaReader.getInstance();
  920. } else {
  921. sr = new AutoSchemaReader();
  922. }
  923. Schema sch = sr.createSchema(schemaInput, options);
  924. return sch;
  925. }
  926. private static Schema proxySchemaByUrl(String uri, EntityResolver resolver, PropertyMap pMap) {
  927. return new ProxySchema(uri, resolver, pMap);
  928. }
  929. /**
  930. * @param url
  931. * @return
  932. * @throws SAXException
  933. * @throws IOException
  934. * @throws IncorrectSchemaException
  935. */
  936. private static Schema schemaByUrl(String url, EntityResolver resolver,
  937. PropertyMap pMap) throws SAXException, IOException,
  938. IncorrectSchemaException {
  939. LOGGER.fine(String.format("Will load schema: %s", url));
  940. long a = System.currentTimeMillis();
  941. TypedInputSource schemaInput;
  942. try {
  943. schemaInput = (TypedInputSource) resolver.resolveEntity(
  944. null, url);
  945. } catch (ClassCastException e) {
  946. LOGGER.log(Level.SEVERE, url, e);
  947. throw e;
  948. }
  949. SchemaReader sr = null;
  950. if ("application/relax-ng-compact-syntax".equals(schemaInput.getType())) {
  951. sr = CompactSchemaReader.getInstance();
  952. LOGGER.log(Level.FINE, "Used CompactSchemaReader");
  953. } else {
  954. sr = new AutoSchemaReader();
  955. LOGGER.log(Level.FINE, "Used AutoSchemaReader");
  956. }
  957. long c = System.currentTimeMillis();
  958. Schema sch = sr.createSchema(schemaInput, pMap);
  959. LOGGER.log(Level.FINE, String.format("Schema created in %s ms.", (System.currentTimeMillis() - c)));
  960. return sch;
  961. }
  962. protected String shortenDataUri(String uri) {
  963. if (DataUri.startsWithData(uri)) {
  964. return "data:\u2026";
  965. } else {
  966. return uri;
  967. }
  968. }
  969. public void rootNamespace(String namespace, Locator locator) throws SAXException {
  970. if (validator == null) {
  971. int index = -1;
  972. for (int i = 0; i < presetNamespaces.length; i++) {
  973. if (namespace.equals(presetNamespaces[i])) {
  974. index = i;
  975. break;
  976. }
  977. }
  978. if (index == -1) {
  979. String message = "Cannot find preset schema for namespace: \u201C"
  980. + namespace + "\u201D.";
  981. SAXException se = new SAXException(message);
  982. errorHandler.schemaError(se);
  983. throw se;
  984. }
  985. String label = presetLabels[index];
  986. String urls = presetUrls[index];
  987. errorHandler.info("Using the preset for " + label
  988. + " based on the root namespace " + namespace);
  989. try {
  990. validator = validatorByUrls(urls);
  991. } catch (IOException ioe) {
  992. // At this point the schema comes from memory.
  993. throw new RuntimeException(ioe);
  994. } catch (IncorrectSchemaException e) {
  995. // At this point the schema comes from memory.
  996. throw new RuntimeException(e);
  997. }
  998. if (bufferingRootNamespaceSniffer == null) {
  999. throw new RuntimeException(
  1000. "Bug! bufferingRootNamespaceSniffer was null.");
  1001. }
  1002. bufferingRootNamespaceSniffer.setContentHandler(validator.getContentHandler());
  1003. }
  1004. if (!rootNamespaceSeen) {
  1005. rootNamespaceSeen = true;
  1006. if (contentType != null) {
  1007. int i;
  1008. if ((i = Arrays.binarySearch(KNOWN_CONTENT_TYPES, contentType)) > -1) {
  1009. if (!NAMESPACES_FOR_KNOWN_CONTENT_TYPES[i].equals(namespace)) {
  1010. String message = "".equals(namespace) ? "\u201C"
  1011. + contentType
  1012. + "\u201D is not an appropriate Content-Type for a document whose root element is not in a namespace."
  1013. : "\u201C"
  1014. + contentType
  1015. + "\u201D is not an appropriate Content-Type for a document whose root namespace is \u201C"
  1016. + namespace + "\u201D.";
  1017. SAXParseException spe = new SAXParseException(message,
  1018. locator);
  1019. errorHandler.warning(spe);
  1020. }
  1021. }
  1022. }
  1023. }
  1024. }
  1025. public void documentMode(DocumentMode mode, String publicIdentifier,
  1026. String systemIdentifier, boolean html4SpecificAdditionalErrorChecks)
  1027. throws SAXException {
  1028. if (validator == null) {
  1029. try {
  1030. if ("-//W3C//DTD XHTML 1.0 Transitional//EN".equals(publicIdentifier)) {
  1031. errorHandler.info("XHTML 1.0 Transitional doctype seen. Appendix C is not supported. Proceeding anyway for your convenience. The parser is still an HTML parser, so namespace processing is not performed and \u201Cxml:*\u201D attributes are not supported. Using the schema for "
  1032. + getPresetLabel(XHTML1TRANSITIONAL_SCHEMA)
  1033. + "."
  1034. + (html4SpecificAdditionalErrorChecks ? " HTML4-specific tokenization errors are enabled."
  1035. : ""));
  1036. validator = validatorByDoctype(XHTML1TRANSITIONAL_SCHEMA);
  1037. } else if ("-//W3C//DTD XHTML 1.0 Strict//EN".equals(publicIdentifier)) {
  1038. errorHandler.info("XHTML 1.0 Strict doctype seen. Appendix C is not supported. Proceeding anyway for your convenience. The parser is still an HTML parser, so namespace processing is not performed and \u201Cxml:*\u201D attributes are not supported. Using the schema for "
  1039. + getPresetLabel(XHTML1STRICT_SCHEMA)
  1040. + "."
  1041. + (html4SpecificAdditionalErrorChecks ? " HTM