    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     */
    017    package org.apache.commons.configuration.resolver;
    018
    019    import java.io.IOException;
    020    import java.io.InputStream;
    021    import java.net.URL;
    022    import java.net.URLConnection;
    023    import java.util.HashMap;
    024    import java.util.Map;
    025
    026    import org.xml.sax.EntityResolver;
    027    import org.xml.sax.InputSource;
    028    import org.xml.sax.SAXException;
    029
    030    /**
    031     * The DefaultEntityResolver used by XML Configurations.
    032     * @author <a
    033     * href="http://commons.apache.org/configuration/team-list.html">Commons
    034     * Configuration team</a>
    035     * @since 1.7
    036     * @version $Id: DefaultEntityResolver.java 1206579 2011-11-26 20:30:51Z oheger $
    037     */
    038    public class DefaultEntityResolver implements EntityResolver, EntityRegistry
    039    {
    040        /** Stores a map with the registered public IDs.*/
    041        private Map<String, URL> registeredEntities = new HashMap<String, URL>();
    042
    043        /**
    044         * <p>
    045         * Registers the specified URL for the specified public identifier.
    046         * </p>
    047         * <p>
    048         * This implementation maps {@code PUBLICID}'s to URLs (from which
    049         * the resource will be loaded). A common use case for this method is to
    050         * register local URLs (possibly computed at runtime by a class loader) for
    051         * DTDs and Schemas. This allows the performance advantage of using a local
    052         * version without having to ensure every {@code SYSTEM} URI on every
    053         * processed XML document is local. This implementation provides only basic
    054         * functionality. If more sophisticated features are required, either calling
    055         * {@code XMLConfiguration.setDocumentBuilder(DocumentBuilder)} to set a custom
    056         * {@code DocumentBuilder} (which also can be initialized with a
    057         * custom {@code EntityResolver}) or creating a custom entity resolver
    058         * and registering it with the XMLConfiguration is recommended.
    059         * </p>
    060         *
    061         * @param publicId Public identifier of the Entity to be resolved
    062         * @param entityURL The URL to use for reading this Entity
    063         * @throws IllegalArgumentException if the public ID is undefined
    064         */
    065        public void registerEntityId(String publicId, URL entityURL)
    066        {
    067            if (publicId == null)
    068            {
    069                throw new IllegalArgumentException("Public ID must not be null!");
    070            }
    071            getRegisteredEntities().put(publicId, entityURL);
    072        }
    073
    074        /**
    075         * Resolves the requested external entity. This is the default
    076         * implementation of the {@code EntityResolver} interface. It checks
    077         * the passed in public ID against the registered entity IDs and uses a
    078         * local URL if possible.
    079         *
    080         * @param publicId the public identifier of the entity being referenced
    081         * @param systemId the system identifier of the entity being referenced
    082         * @return an input source for the specified entity
    083         * @throws org.xml.sax.SAXException if a parsing exception occurs
    084         */
    085        public InputSource resolveEntity(String publicId, String systemId)
    086                throws SAXException
    087        {
    088            // Has this system identifier been registered?
    089            URL entityURL = null;
    090            if (publicId != null)
    091            {
    092                entityURL = (URL) getRegisteredEntities().get(publicId);
    093            }
    094
    095            if (entityURL != null)
    096            {
    097                // Obtain an InputSource for this URL. This code is based on the
    098                // createInputSourceFromURL() method of Commons Digester.
    099                try
    100                {
    101                    URLConnection connection = entityURL.openConnection();
    102                    connection.setUseCaches(false);
    103                    InputStream stream = connection.getInputStream();
    104                    InputSource source = new InputSource(stream);
    105                    source.setSystemId(entityURL.toExternalForm());
    106                    return source;
    107                }
    108                catch (IOException e)
    109                {
    110                    throw new SAXException(e);
    111                }
    112            }
    113            else
    114            {
    115                // default processing behavior
    116                return null;
    117            }
    118        }
    119
    120        /**
    121         * Returns a map with the entity IDs that have been registered using the
    122         * {@code registerEntityId()} method.
    123         *
    124         * @return a map with the registered entity IDs
    125         */
    126        public Map<String, URL> getRegisteredEntities()
    127        {
    128            return registeredEntities;
    129        }
    130    }