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.markup.parser.filter;
018
019import java.text.ParseException;
020import java.util.Locale;
021import java.util.Map;
022
023import org.apache.wicket.Application;
024import org.apache.wicket.markup.ComponentTag;
025import org.apache.wicket.markup.MarkupElement;
026import org.apache.wicket.markup.MarkupResourceStream;
027import org.apache.wicket.markup.parser.AbstractMarkupFilter;
028import org.apache.wicket.util.value.IValueMap;
029
030
031/**
032 * This is a markup inline filter. It determines the Wicket namespace name from the markup. Examples
033 * are xmlns:wicket or xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"
034 * though every URI that starts with "http://wicket.apache.org" will work as well.
035 * 
036 * @see org.apache.wicket.markup.MarkupParser
037 * @author Juergen Donnerstag
038 */
039public final class WicketNamespaceHandler extends AbstractMarkupFilter
040{
041        /** Wicket URI */
042        private static final String WICKET_URI = "http://wicket.apache.org";
043
044        /**
045         * namespace prefix: e.g. <html xmlns:wicket="http://wicket.apache.org">
046         */
047        private static final String XMLNS = "xmlns:";
048
049        /**
050         * Construct.
051         * 
052         * @param markup
053         *            The markup created by reading the markup file
054         */
055        public WicketNamespaceHandler(final MarkupResourceStream markup)
056        {
057                super(markup);
058        }
059
060        @Override
061        protected final MarkupElement onComponentTag(ComponentTag tag) throws ParseException
062        {
063                if (tag.isOpen() && "html".equals(tag.getName().toLowerCase(Locale.ROOT)))
064                {
065                        final String namespace = determineWicketNamespace(tag);
066                        if (namespace != null)
067                        {
068                                getMarkupResourceStream().setWicketNamespace(namespace);
069                        }
070                }
071
072                return tag;
073        }
074
075        /**
076         * Determine wicket namespace from xmlns:wicket or xmlns:wicket="http://wicket.apache.org"
077         * 
078         * @param tag
079         * @return Wicket namespace
080         */
081        private String determineWicketNamespace(final ComponentTag tag)
082        {
083                // For all tags attributes
084                final IValueMap attributes = tag.getAttributes();
085                for (Map.Entry<String, Object> entry : attributes.entrySet())
086                {
087                        // Find attributes with namespace "xmlns"
088                        final String attributeName = entry.getKey();
089                        if (attributeName.startsWith(XMLNS))
090                        {
091                                final String xmlnsUrl = (String)entry.getValue();
092
093                                // If Wicket relevant ...
094                                if ((xmlnsUrl == null) || (xmlnsUrl.trim().length() == 0) ||
095                                        xmlnsUrl.startsWith(WICKET_URI))
096                                {
097                                        // Set the Wicket namespace for wicket tags (e.g.
098                                        // <wicket:panel>) and attributes (e.g. wicket:id)
099                                        final String namespace = attributeName.substring(XMLNS.length());
100                                        if (Application.get().getMarkupSettings().getStripWicketTags())
101                                        {
102                                                attributes.remove(attributeName);
103
104                                                // Make sure the parser knows it has been changed
105                                                tag.setModified(true);
106                                        }
107
108                                        return namespace;
109                                }
110                        }
111                }
112
113                return null;
114        }
115}