001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.util.markup.xhtml;
018
019import java.io.File;
020import java.io.FileFilter;
021import java.io.IOException;
022import java.util.HashMap;
023import java.util.Map;
024
025import javax.xml.parsers.DocumentBuilder;
026import javax.xml.parsers.DocumentBuilderFactory;
027import javax.xml.parsers.ParserConfigurationException;
028
029import org.xml.sax.EntityResolver;
030import org.xml.sax.ErrorHandler;
031import org.xml.sax.InputSource;
032import org.xml.sax.SAXException;
033import org.xml.sax.SAXParseException;
034
035/**
036 * Usable by tests to check that the html markup files are well formed.
037 * 
038 * @author akiraly
039 */
040public class WellFormedXmlTestCase
041{
042        private DocumentBuilderFactory factory;
043
044        /**
045         * Checks xml well formedness of html markup files under the current working directory.
046         */
047        // @Test
048        public void markupFiles()
049        {
050                factory = DocumentBuilderFactory.newInstance();
051                factory.setNamespaceAware(true);
052
053                File root = new File("").getAbsoluteFile();
054                processDirectory(root);
055        }
056
057        private void processDirectory(File dir)
058        {
059                for (File f : dir.listFiles(fileFilter))
060                {
061                        if (f.isDirectory())
062                        {
063                                processDirectory(f);
064                        }
065                        else
066                        {
067                                processFile(f);
068                        }
069                }
070        }
071
072        private void processFile(File file)
073        {
074                DocumentBuilder builder;
075
076                try
077                {
078                        builder = factory.newDocumentBuilder();
079                }
080                catch (ParserConfigurationException e)
081                {
082                        throw new RuntimeException("Configuration exception while parsing xml markup.", e);
083                }
084
085                builder.setEntityResolver(entityResolver);
086                builder.setErrorHandler(errorHandler);
087
088                try
089                {
090                        builder.parse(file);
091                }
092                catch (SAXException e)
093                {
094                        throw new RuntimeException("Parsing xml sax failed, file: " + file, e);
095                }
096                catch (IOException e)
097                {
098                        throw new RuntimeException("Parsing xml io failed, file: " + file, e);
099                }
100        }
101
102        private static final FileFilter fileFilter = new FileFilter()
103        {
104                @Override
105                public boolean accept(File pathname)
106                {
107                        String path = pathname.getAbsolutePath().replace('\\', '/');
108                        return !path.contains("/src/test/") && !path.contains("/target/") &&
109                                !"package.html".equals(pathname.getName()) &&
110                                (pathname.isDirectory() || pathname.getName().endsWith(".html"));
111                }
112        };
113
114        private static final ErrorHandler errorHandler = new ErrorHandler()
115        {
116                @Override
117                public void warning(SAXParseException exception) throws SAXException
118                {
119                        throw exception;
120                }
121
122                @Override
123                public void error(SAXParseException exception) throws SAXException
124                {
125                        throw exception;
126                }
127
128                @Override
129                public void fatalError(SAXParseException exception) throws SAXException
130                {
131                        throw exception;
132                }
133
134        };
135
136        private static final EntityResolver entityResolver = new EntityResolver()
137        {
138                private final Map<String, String> systemIdToUri = new HashMap<>();
139
140                {
141                        systemIdToUri.put("http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd",
142                                "xhtml1-transitional.dtd");
143                        systemIdToUri.put("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd",
144                                "xhtml1-strict.dtd");
145
146                        /*
147                         * Cheating: using xhtml dtd-s for html4 files too because the html4 dtd-s are not valid
148                         * xml dtd-s.
149                         */
150                        systemIdToUri.put("http://www.w3.org/TR/html4/loose.dtd", "xhtml1-transitional.dtd");
151                        systemIdToUri.put("http://www.w3.org/TR/html4/strict.dtd", "xhtml1-strict.dtd");
152                }
153
154                @Override
155                public InputSource resolveEntity(String publicId, String systemId) {
156                        String uri = systemIdToUri.get(systemId);
157                        if (uri != null)
158                        {
159                                return new InputSource(WellFormedXmlTestCase.class.getResource(uri).toString());
160                        }
161
162                        return null;
163                }
164        };
165}