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.junit.jupiter.api.Test;
030import org.xml.sax.EntityResolver;
031import org.xml.sax.ErrorHandler;
032import org.xml.sax.InputSource;
033import org.xml.sax.SAXException;
034import org.xml.sax.SAXParseException;
035
036/**
037 * Usable by tests to check that the html markup files are well formed.
038 * 
039 * @author akiraly
040 */
041public class WellFormedXmlTestCase
042{
043        private DocumentBuilderFactory factory;
044
045        /**
046         * Checks xml well formedness of html markup files under the current working directory.
047         */
048        @Test
049        public void markupFiles()
050        {
051                factory = DocumentBuilderFactory.newInstance();
052                factory.setNamespaceAware(true);
053
054                File root = new File("").getAbsoluteFile();
055                processDirectory(root);
056        }
057
058        private void processDirectory(File dir)
059        {
060                for (File f : dir.listFiles(fileFilter))
061                {
062                        if (f.isDirectory())
063                        {
064                                processDirectory(f);
065                        }
066                        else
067                        {
068                                processFile(f);
069                        }
070                }
071        }
072
073        private void processFile(File file)
074        {
075                DocumentBuilder builder;
076
077                try
078                {
079                        builder = factory.newDocumentBuilder();
080                }
081                catch (ParserConfigurationException e)
082                {
083                        throw new RuntimeException("Configuration exception while parsing xml markup.", e);
084                }
085
086                builder.setEntityResolver(entityResolver);
087                builder.setErrorHandler(errorHandler);
088
089                try
090                {
091                        builder.parse(file);
092                }
093                catch (SAXException e)
094                {
095                        throw new RuntimeException("Parsing xml sax failed, file: " + file, e);
096                }
097                catch (IOException e)
098                {
099                        throw new RuntimeException("Parsing xml io failed, file: " + file, e);
100                }
101        }
102
103        private static final FileFilter fileFilter = new FileFilter()
104        {
105                @Override
106                public boolean accept(File pathname)
107                {
108                        String path = pathname.getAbsolutePath().replace('\\', '/');
109                        return !path.contains("/src/test/") && !path.contains("/target/") &&
110                                !"package.html".equals(pathname.getName()) &&
111                                (pathname.isDirectory() || pathname.getName().endsWith(".html"));
112                }
113        };
114
115        private static final ErrorHandler errorHandler = new ErrorHandler()
116        {
117                @Override
118                public void warning(SAXParseException exception) throws SAXException
119                {
120                        throw exception;
121                }
122
123                @Override
124                public void error(SAXParseException exception) throws SAXException
125                {
126                        throw exception;
127                }
128
129                @Override
130                public void fatalError(SAXParseException exception) throws SAXException
131                {
132                        throw exception;
133                }
134
135        };
136
137        private static final EntityResolver entityResolver = new EntityResolver()
138        {
139                private final Map<String, String> systemIdToUri = new HashMap<>();
140
141                {
142                        systemIdToUri.put("http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd",
143                                "xhtml1-transitional.dtd");
144                        systemIdToUri.put("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd",
145                                "xhtml1-strict.dtd");
146
147                        /*
148                         * Cheating: using xhtml dtd-s for html4 files too because the html4 dtd-s are not valid
149                         * xml dtd-s.
150                         */
151                        systemIdToUri.put("http://www.w3.org/TR/html4/loose.dtd", "xhtml1-transitional.dtd");
152                        systemIdToUri.put("http://www.w3.org/TR/html4/strict.dtd", "xhtml1-strict.dtd");
153                }
154
155                @Override
156                public InputSource resolveEntity(String publicId, String systemId) {
157                        String uri = systemIdToUri.get(systemId);
158                        if (uri != null)
159                        {
160                                return new InputSource(WellFormedXmlTestCase.class.getResource(uri).toString());
161                        }
162
163                        return null;
164                }
165        };
166}