blob: c54131b20080c4f34502c77858fce247334437eb [file] [log] [blame]
/*
* 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.tomcat.util.descriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Map;
import org.apache.tomcat.util.res.StringManager;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.ext.EntityResolver2;
/**
* A resolver for locally cached XML resources.
*/
public class LocalResolver implements EntityResolver2 {
private static final StringManager sm =
StringManager.getManager(Constants.PACKAGE_NAME);
private static final String[] JAVA_EE_NAMESPACES = {
XmlIdentifiers.JAVAEE_1_4_NS,
XmlIdentifiers.JAVAEE_5_NS,
XmlIdentifiers.JAVAEE_7_NS };
private final Map<String,String> publicIds;
private final Map<String,String> systemIds;
private final boolean blockExternal;
/**
* Constructor providing mappings of public and system identifiers to local
* resources. Each map contains a mapping from a well-known identifier to a
* URL for a local resource path.
*
* @param publicIds mapping of well-known public identifiers to local
* resources
* @param systemIds mapping of well-known system identifiers to local
* resources
* @param blockExternal are external resources blocked that are not
* well-known
*/
public LocalResolver(Map<String,String> publicIds,
Map<String,String> systemIds, boolean blockExternal) {
this.publicIds = publicIds;
this.systemIds = systemIds;
this.blockExternal = blockExternal;
}
@Override
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
return resolveEntity(null, publicId, null, systemId);
}
@Override
public InputSource resolveEntity(String name, String publicId,
String base, String systemId) throws SAXException, IOException {
// First try resolving using the publicId
String resolved = publicIds.get(publicId);
if (resolved != null) {
InputSource is = new InputSource(resolved);
is.setPublicId(publicId);
return is;
}
// If there is no systemId, can't try anything else
if (systemId == null) {
throw new FileNotFoundException(sm.getString("localResolver.unresolvedEntity",
name, publicId, systemId, base));
}
// Try resolving with the supplied systemId
resolved = systemIds.get(systemId);
if (resolved != null) {
InputSource is = new InputSource(resolved);
is.setPublicId(publicId);
return is;
}
// Work-around for XML documents that use just the file name for the
// location to refer to a JavaEE schema
for (String javaEENamespace : JAVA_EE_NAMESPACES) {
String javaEESystemId = javaEENamespace + '/' + systemId;
resolved = systemIds.get(javaEESystemId);
if (resolved != null) {
InputSource is = new InputSource(resolved);
is.setPublicId(publicId);
return is;
}
}
// Resolve the supplied systemId against the base
URI systemUri;
try {
if (base == null) {
systemUri = new URI(systemId);
} else {
// Can't use URI.resolve() because "jar:..." URLs are not valid
// hierarchical URIs so resolve() does not work. new URL()
// delegates to the jar: stream handler and it manages to figure
// it out.
URI baseUri = new URI(base);
systemUri = new URL(baseUri.toURL(), systemId).toURI();
}
systemUri = systemUri.normalize();
} catch (URISyntaxException e) {
// May be caused by a | being used instead of a : in an absolute
// file URI on Windows.
if (blockExternal) {
// Absolute paths aren't allowed so block it
throw new MalformedURLException(e.getMessage());
} else {
// See if the URLHandler can resolve it
return new InputSource(systemId);
}
}
if (systemUri.isAbsolute()) {
// Try the resolved systemId
resolved = systemIds.get(systemUri.toString());
if (resolved != null) {
InputSource is = new InputSource(resolved);
is.setPublicId(publicId);
return is;
}
if (!blockExternal) {
InputSource is = new InputSource(systemUri.toString());
is.setPublicId(publicId);
return is;
}
}
throw new FileNotFoundException(sm.getString("localResolver.unresolvedEntity",
name, publicId, systemId, base));
}
@Override
public InputSource getExternalSubset(String name, String baseURI)
throws SAXException, IOException {
return null;
}
}