| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.wicket.markup.parser.filter; |
| |
| import java.text.ParseException; |
| import java.util.Locale; |
| |
| import org.apache.wicket.markup.ComponentTag; |
| import org.apache.wicket.markup.MarkupElement; |
| import org.apache.wicket.markup.WicketParseException; |
| import org.apache.wicket.markup.parser.AbstractMarkupFilter; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| |
| /** |
| * This is a markup inline filter which by default is not added to the list of markup filter. It can |
| * be added by means of subclassing Application.newMarkupParser() like |
| * |
| * <pre> |
| * Application#init() { |
| * getMarkupSettings().setMarkupParserFactory() { |
| * new MarkupParserFactory() { |
| * MarkupParser newMarkupParser(final MarkupResourceStream resource) { |
| * MarkupParser parser=super.newMarkupParser(resource); |
| * parser.appendMarkupFilter(new HtmlProblemFinder(HtmlProblemFinder.ERR_THROW_EXCEPTION)); |
| * return parser; |
| * } |
| * } |
| * } |
| * } |
| * </pre> |
| * |
| * The purpose of the filter is to find possible HTML issues and to log a warning. |
| * |
| * @author Juergen Donnerstag |
| */ |
| public final class HtmlProblemFinder extends AbstractMarkupFilter |
| { |
| /** Logging */ |
| private static final Logger log = LoggerFactory.getLogger(HtmlProblemFinder.class); |
| |
| /** Ignore the issue detected */ |
| public static final int ERR_INGORE = 3; |
| |
| /** Log a warning on the issue detected */ |
| public static final int ERR_LOG_WARN = 2; |
| |
| /** Log an error on the issue detected */ |
| public static final int ERR_LOG_ERROR = 1; |
| |
| /** Throw an exception on the issue detected */ |
| public static final int ERR_THROW_EXCEPTION = 0; |
| |
| /** Default behavior in case of a potential HTML issue detected */ |
| private final int problemEscalation; |
| |
| /** |
| * Construct. |
| * |
| * @param problemEscalation |
| * How to escalate the issue found. |
| */ |
| public HtmlProblemFinder(final int problemEscalation) |
| { |
| this.problemEscalation = problemEscalation; |
| } |
| |
| @Override |
| protected final MarkupElement onComponentTag(ComponentTag tag) throws ParseException |
| { |
| // Make sure some typical and may be tricky problems are detected and |
| // logged. |
| if ("img".equals(tag.getName()) && (tag.isOpen() || tag.isOpenClose())) |
| { |
| String src = tag.getAttributes().getString("src"); |
| if ((src != null) && (src.trim().length() == 0)) |
| { |
| escalateWarning("Attribute 'src' should not be empty. Location: ", tag); |
| } |
| } |
| |
| // Some people are using a dot "wicket.xxx" instead of a colon |
| // "wicket:xxx" |
| for (String key : tag.getAttributes().keySet()) |
| { |
| if (key != null) |
| { |
| key = key.toLowerCase(Locale.ROOT); |
| String namespaceDot = getWicketNamespace() + '.'; |
| if (key.startsWith(namespaceDot)) |
| { |
| escalateWarning( |
| String.format("You probably want '%s:xxx' rather than '%s.xxx'. Location: ", namespaceDot, namespaceDot), |
| tag); |
| } |
| } |
| } |
| |
| return tag; |
| } |
| |
| /** |
| * Handle the issue. Depending the setting either log a warning, an error, throw an exception or |
| * ignore it. |
| * |
| * @param msg |
| * The message |
| * @param tag |
| * The current tag |
| * @throws WicketParseException |
| */ |
| private void escalateWarning(final String msg, final ComponentTag tag) |
| throws WicketParseException |
| { |
| if (problemEscalation == ERR_LOG_WARN) |
| { |
| log.warn(msg + tag.toUserDebugString()); |
| } |
| else if (problemEscalation == ERR_LOG_ERROR) |
| { |
| log.error(msg + tag.toUserDebugString()); |
| } |
| else if (problemEscalation == ERR_INGORE) |
| { |
| // no action required |
| } |
| else |
| // if (problemEscalation == ERR_THROW_EXCEPTION) |
| { |
| throw new WicketParseException(msg, tag); |
| } |
| } |
| } |