1 10 package org.mmbase.util; 11 12 import java.io.InputStream ; 13 import java.io.InputStreamReader ; 14 import java.io.ByteArrayInputStream ; 15 import java.util.Map ; 16 import java.util.Hashtable ; 17 18 import org.mmbase.util.xml.ApplicationReader; 19 import org.mmbase.util.xml.BuilderReader; 20 import org.mmbase.util.xml.ModuleReader; 21 import org.mmbase.util.logging.Logger; 22 import org.mmbase.util.logging.Logging; 23 24 import org.xml.sax.EntityResolver ; 25 import org.xml.sax.InputSource ; 26 27 36 public class XMLEntityResolver implements EntityResolver { 37 38 public static final String DOMAIN = "http://www.mmbase.org/"; 39 public static final String DTD_SUBPATH = "dtd/"; 40 public static final String XMLNS_SUBPATH = "xmlns/"; 41 private static final String XSD_SUBPATH = "xsd/"; 43 private static Logger log = Logging.getLoggerInstance(XMLEntityResolver.class); 44 45 private static final String MMRESOURCES = "/org/mmbase/resources/"; 46 47 private static Map publicIDtoResource = new Hashtable (); 48 51 54 private static Map systemIDtoResource = new Hashtable (); 55 56 59 static class Resource { 60 private Class clazz; 61 private String file; 62 Resource(Class c, String f) { 63 clazz = c; file = f; 64 } 65 66 String getResource() { 67 return "resources/" + file; 68 } 69 String getFileName() { 70 return file; 71 } 72 InputStream getAsStream() { 73 if (log.isDebugEnabled()) log.debug("Getting document definition as resource " + getResource() + " of " + clazz.getName()); 74 return clazz != null ? clazz.getResourceAsStream(getResource()) : null; 75 } 76 public String toString() { 77 return file + ": " + clazz; 78 } 79 80 } 81 82 static { 83 org.mmbase.util.xml.DocumentReader.registerPublicIDs(); 86 BuilderReader.registerPublicIDs(); 87 BuilderReader.registerSystemIDs(); 88 ApplicationReader.registerPublicIDs(); 89 ModuleReader.registerPublicIDs(); 90 org.mmbase.util.xml.UtilReader.registerPublicIDs(); 91 org.mmbase.bridge.util.xml.query.QueryReader.registerSystemIDs(); 92 93 registerSystemID("http://www.w3.org/2001/03/xml.xsd", "xml.xsd", null); 94 registerSystemID("http://www.w3.org/2001/03/XMLSchema.dtd", "XMLSchema.dtd", null); 95 registerSystemID("http://www.w3.org/2001/03/datatypes.dtd", "datatypes.dtd", null); 96 } 97 98 99 107 public static void registerPublicID(String publicID, String dtd, Class c) { 108 publicIDtoResource.put(publicID, new Resource(c, dtd)); 109 if (log.isDebugEnabled()) log.debug("publicIDtoResource: " + publicID + " " + dtd + c.getName()); 110 } 111 112 117 public static void registerSystemID(String systemID, String xsd, Class c) { 118 systemIDtoResource.put(systemID, new Resource(c, xsd)); 119 } 120 121 private String definitionPath; 122 123 private boolean hasDefinition; 125 private boolean validate; 126 private Class resolveBase; 127 128 129 130 133 public XMLEntityResolver() { 134 this(true); 135 } 136 137 public XMLEntityResolver(boolean v) { 138 this(v, null); 139 } 140 141 public XMLEntityResolver(boolean v, Class base) { 142 hasDefinition = false; 143 definitionPath = null; 144 validate = v; 145 resolveBase = base; 146 } 147 148 149 private InputStream getStream(Resource res) { 150 InputStream stream = null; 151 if (res != null) { 152 stream = ResourceLoader.getConfigurationRoot().getResourceAsStream(DTD_SUBPATH + res.getFileName()); 153 if (stream == null) { 154 stream = ResourceLoader.getConfigurationRoot().getResourceAsStream(XMLNS_SUBPATH + res.getFileName()); 155 } 156 if (stream == null) { 157 stream = ResourceLoader.getConfigurationRoot().getResourceAsStream(XSD_SUBPATH + res.getFileName()); 159 } 160 if (stream == null) { 161 stream = res.getAsStream(); 162 } 163 } 164 return stream; 165 } 166 167 170 public InputSource resolveEntity(String publicId, String systemId) { 171 if (log.isDebugEnabled()) { 172 log.debug("resolving PUBLIC " + publicId + " SYSTEM " + systemId); 173 } 174 if (! validate) { 175 log.debug("Not validating, not need to resolve DTD, returning empty resource"); 176 return new InputSource (new ByteArrayInputStream (new byte[0])); 177 } 178 179 InputStream definitionStream = null; 180 181 if (publicId != null) { 183 Resource res = (Resource) publicIDtoResource.get(publicId); 184 definitionStream = getStream(res); 185 } 186 log.debug("Get definition stream by public id: " + definitionStream); 187 188 if (definitionStream == null) { 189 Resource res = (Resource) systemIDtoResource.get(systemId); 190 if (res != null) { 191 definitionStream = getStream(res); 192 } 193 } 194 195 if (definitionStream == null) { 197 if ((systemId == null) || (! systemId.startsWith(DOMAIN))) { 199 202 if (log.isDebugEnabled()) { 203 log.debug("Cannot resolve " + systemId + ", but needed for validation leaving to parser."); 204 log.debug("Find culpit: " + Logging.stackTrace(new Exception ())); 205 } 206 return null; 207 } else { 208 log.debug("mmbase resource"); 209 String mmResource = systemId.substring(22); 210 definitionStream = ResourceLoader.getConfigurationRoot().getResourceAsStream(mmResource); 212 if (definitionStream == null) { 213 Class base = resolveBase; Resource res = null; 215 if (base != null) { 216 if (mmResource.startsWith("xmlns/")) { 217 res = new Resource(base, mmResource.substring(6)); 218 } else { 219 res = new Resource(base, mmResource.substring(4)); } 221 } 222 if (res != null) { 223 definitionStream = res.getAsStream(); 224 if (definitionStream == null) { 225 log.warn("Could not find " + res.getResource() + " in " + base.getName() + ", falling back to " + MMRESOURCES); 226 base = null; } 228 } 229 230 if (base == null) { 231 String resource = MMRESOURCES + mmResource; 232 if (log.isDebugEnabled()) log.debug("Getting document definition as resource " + resource); 233 definitionStream = getClass().getResourceAsStream(resource); 234 } 235 } 236 if (definitionStream == null) { 237 238 if (resolveBase != null) { 239 log.error("Could not find MMBase entity '" + publicId + " " + systemId + "' (did you make a typo?), returning null, system id will be used (needing a connection, or put in config dir)"); 240 } else { 241 log.service("Could not find MMBase entity '" + publicId + " " + systemId + "' (did you make a typo?), returning null, system id will be used (needing a connection, or put in config dir)"); 242 243 } 244 return null; 249 } 250 } 251 } 252 hasDefinition = true; 253 254 InputStreamReader definitionInputStreamReader = new InputStreamReader (definitionStream); 255 InputSource definitionInputSource = new InputSource (); 256 if (systemId != null) { 257 definitionInputSource.setSystemId(systemId); 258 } 259 if (publicId != null) { 260 definitionInputSource.setPublicId(publicId); 261 } 262 definitionInputSource.setCharacterStream(definitionInputStreamReader); 263 return definitionInputSource; 264 } 265 266 269 public boolean hasDTD() { 270 return hasDefinition; 271 } 272 273 276 public String getDTDPath() { 277 return definitionPath; 278 } 279 } 280 | Popular Tags |