001: /*
002: * $Id: HtmlProblemFinder.java 461655 2006-07-30 12:37:49Z jdonnerstag $ $Revision:
003: * 1.5 $ $Date: 2006-07-30 14:37:49 +0200 (Sun, 30 Jul 2006) $
004: *
005: * ==============================================================================
006: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
007: * use this file except in compliance with the License. You may obtain a copy of
008: * the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015: * License for the specific language governing permissions and limitations under
016: * the License.
017: */
018: package wicket.markup.parser.filter;
019:
020: import java.text.ParseException;
021: import java.util.Iterator;
022:
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025:
026: import wicket.markup.ComponentTag;
027: import wicket.markup.MarkupElement;
028: import wicket.markup.parser.AbstractMarkupFilter;
029:
030: /**
031: * This is a markup inline filter which by default is not added to the list
032: * of markup filter. It can be added by means of subclassing
033: * Application.newMarkupParser() like
034: * <pre>
035: * public class MyApplication extends Application
036: * {
037: * ...
038: * public IMarkupFilter[] getAdditionalMarkupHandler()
039: * {
040: * return new IMarkupFilter[] { new HtmlProblemFinder(HtmlProblemFinder.ERR_THROW_EXCEPTION) };
041: * }
042: * </pre>
043: *
044: * The purpose of the filter is to find possible HTML issues and to log a
045: * warning.
046: *
047: * @author Juergen Donnerstag
048: */
049: public final class HtmlProblemFinder extends AbstractMarkupFilter {
050: /** Logging */
051: private static final Log log = LogFactory
052: .getLog(HtmlProblemFinder.class);
053:
054: /** Ignore the issue detected */
055: public static final int ERR_INGORE = 3;
056:
057: /** Log a warning on the issue detected */
058: public static final int ERR_LOG_WARN = 2;
059:
060: /** Log an error on the issue detected */
061: public static final int ERR_LOG_ERROR = 1;
062:
063: /** Throw an exception on the issue detected */
064: public static final int ERR_THROW_EXCEPTION = 0;
065:
066: /** Default behavior in case of a potential HTML issue detected */
067: private final int problemEscalation;
068:
069: /**
070: * Construct.
071: *
072: * @param problemEscalation
073: * How to escalate the issue found.
074: */
075: public HtmlProblemFinder(final int problemEscalation) {
076: this .problemEscalation = problemEscalation;
077: }
078:
079: /**
080: * Get the next MarkupElement from the parent MarkupFilter and handle it if
081: * the specific filter criteria are met. Depending on the filter, it may
082: * return the MarkupElement unchanged, modified or it remove by asking the
083: * parent handler for the next tag.
084: *
085: * @see wicket.markup.parser.IMarkupFilter#nextTag()
086: * @return Return the next eligible MarkupElement
087: */
088: public MarkupElement nextTag() throws ParseException {
089: // Get the next tag. If null, no more tags are available
090: final ComponentTag tag = (ComponentTag) getParent().nextTag();
091: if (tag == null) {
092: return tag;
093: }
094:
095: // Make sure some typical and may be tricky problems are detected and
096: // logged.
097: if ("img".equals(tag.getName())
098: && (tag.isOpen() || tag.isOpenClose())) {
099: String src = tag.getAttributes().getString("src");
100: if ((src != null) && (src.trim().length() == 0)) {
101: escalateWarning(
102: "Attribute 'src' should not be empty. Location: ",
103: tag);
104: }
105: }
106:
107: // Some people are using a dot "wicket.xxx" instead of a colon "wicket:xxx"
108: Iterator iter = tag.getAttributes().keySet().iterator();
109: while (iter.hasNext()) {
110: String key = (String) iter.next();
111: if (key != null) {
112: key = key.toLowerCase();
113: if (key.startsWith("wicket.")) {
114: escalateWarning(
115: "You probably want 'wicket:xxx' rather than 'wicket.xxx'. Location: ",
116: tag);
117: }
118: }
119: }
120:
121: return tag;
122: }
123:
124: /**
125: * Handle the issue. Depending the setting either log a warning, an error,
126: * throw an exception or ignore it.
127: *
128: * @param msg The message
129: * @param tag The current tag
130: * @throws ParseException
131: */
132: private void escalateWarning(final String msg,
133: final ComponentTag tag) throws ParseException {
134: if (problemEscalation == ERR_LOG_WARN) {
135: log.warn(msg + tag.toUserDebugString());
136: } else if (problemEscalation == ERR_LOG_ERROR) {
137: log.error(msg + tag.toUserDebugString());
138: } else if (problemEscalation == ERR_INGORE) {
139: // no action required
140: } else // if (problemEscalation == ERR_THROW_EXCEPTION)
141: {
142: throw new ParseException(msg + tag.toUserDebugString(), tag
143: .getPos());
144: }
145: }
146: }
|