package com.guit.rebind.guitview; import com.google.gwt.dev.util.collect.Sets; import com.google.gwt.uibinder.rebind.UiBinderGenerator; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import java.io.IOException; import java.io.InputStream; import java.util.Collections; import java.util.Set; /** * Does special handling of external entities encountered by sax xml parser, * e.g. the uri in * * <pre> * <!DOCTYPE gwt:UiBinder SYSTEM "http://google-web-toolkit.googlecode.com/files/xhtml.ent"></pre> * <p> * Specifically, if the requested uri starts with * <code>http://google-web-toolkit.googlecode.com/files</code>, provide the * contents from a built in resource rather than allowing sax to make a network * request. */ class GwtResourceEntityResolver implements EntityResolver { interface ResourceLoader { InputStream fetch(String name); } private static final Set<String> EXTERNAL_PREFIXES = Collections.unmodifiableSet(Sets .create(new String[]{ "http://google-web-toolkit.googlecode.com/files/", "http://dl.google.com/gwt/DTD/", "https://dl-ssl.google.com/gwt/DTD/"})); private static final String RESOURCES = "com/google/gwt/uibinder/resources/"; private final ResourceLoader resourceLoader; public GwtResourceEntityResolver() { this(new ResourceLoader() { public InputStream fetch(String name) { return UiBinderGenerator.class.getClassLoader().getResourceAsStream(name); } }); } /** * For testing. */ GwtResourceEntityResolver(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } private String findMatchingPrefix(String systemId) { for (String prefix : EXTERNAL_PREFIXES) { if (systemId.startsWith(prefix)) { return prefix; } } return null; } public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { String matchingPrefix = findMatchingPrefix(systemId); if (matchingPrefix == null) { // Not our problem, return null and sax will find it return null; } String name = RESOURCES + systemId.substring(matchingPrefix.length()); InputStream resourceStream = resourceLoader.fetch(name); if (resourceStream == null) { /* * They're asking for another DTD resource that we don't short circuit, * Return null and let Sax find it on the interweb. */ return null; } InputSource inputSource = new InputSource(resourceStream); inputSource.setPublicId(publicId); inputSource.setSystemId(systemId); return inputSource; } }