package tk.eclipse.plugin.xmleditor.editors; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.HashMap; import java.util.Map; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.preference.IPreferenceStore; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.ext.EntityResolver2; import tk.eclipse.plugin.htmleditor.HTMLPlugin; import tk.eclipse.plugin.htmleditor.HTMLUtil; /** * An implementation of <code>EntityResolver</code> * to load DTDs or XSDs from locacl file system. * * @author Naoki Takezoe */ public class DTDResolver implements EntityResolver2 { // private static HashMap namedXSDMap = new HashMap(); private HashMap<String, String> map = new HashMap<String, String>(); private IDTDResolver[] resolvers = null; private File basedir; public DTDResolver(IDTDResolver[] resolvers){ this(resolvers, null); } public DTDResolver(IDTDResolver[] resolvers, File basedir) { super(); this.resolvers = resolvers; this.basedir = basedir; // load from preference store IPreferenceStore store = HTMLPlugin.getDefault().getPreferenceStore(); String[] uri = store.getString(HTMLPlugin.PREF_DTD_URI).split("\n"); String[] path = store.getString(HTMLPlugin.PREF_DTD_PATH).split("\n"); for(int i=0;i<uri.length;i++){ if(!uri[i].trim().equals("") && !path[i].trim().equals("")){ map.put(uri[i].trim(),path[i].trim()); } } } public InputSource getExternalSubset(String name, String baseURI) throws SAXException, IOException { // nothing to do return null; } public InputSource resolveEntity(String name, String publicId, String baseURI, String systemId) throws SAXException, IOException { InputStream in = getInputStream(systemId); if(in!=null){ return new InputSource(in); } return null; } /** * Returns InputStream of DTD or XSD. * * @param url URL * @return InputStream */ public InputStream getInputStream(String url){ InputStream in = null; // get from contributed IDTDResolver for(int i=0;i<resolvers.length;i++){ in = resolvers[i].getInputStream(url); if(in!=null){ return in; } } // get from preferences String path = map.get(url); if(path!=null){ File file = new File(path); if(file.exists() && file.isFile()){ try { return new FileInputStream(file); } catch(Exception ex){ HTMLPlugin.logException(ex); } } } // get from internal DTDs/XSDs Map innerDTD = HTMLPlugin.getInnerDTD(); if(innerDTD.get(url)!=null){ return getClass().getResourceAsStream((String)innerDTD.get(url)); } // get from local file system if(url.indexOf(':')<0){ in = getFileInputStream(url); if(in != null){ return in; } } // retry only file name if(url.indexOf('/') >= 0 && (url.endsWith(".xsd") || url.endsWith(".dtd"))){ in = getInputStream(url.substring(url.lastIndexOf('/') + 1)); if(in!=null){ return in; } } // get directly try { return getStreamFromURL(url); } catch(Exception ex){ } return null; } private InputStream getFileInputStream(String path){ File file = new File(path); try { if(file.exists() && file.isFile()){ return new FileInputStream(file); } if(basedir != null){ file = new File(basedir, path); if(file.exists() && file.isFile()){ return new FileInputStream(file); } } } catch(IOException ex){ HTMLPlugin.logException(ex); } return null; } private InputStream getStreamFromURL(String url){ // when caching configuration is disabled IPreferenceStore store = HTMLPlugin.getDefault().getPreferenceStore(); if(!store.getBoolean(HTMLPlugin.PREF_DTD_CACHE) || url.startsWith("file:")){ try { return new URL(url).openStream(); } catch(Exception ex){ } return null; } // get file name String name = url.substring(url.lastIndexOf("/")+1); if(name.indexOf("\\")>0){ name = name.substring(name.lastIndexOf("\\")+1); } // create cache directory File cacheDir = new File(Platform.getStateLocation( HTMLPlugin.getDefault().getBundle()).toFile(),"dtd"); if(!cacheDir.exists() || !cacheDir.isDirectory()){ cacheDir.mkdirs(); } // use cache file if that exists File cacheFile = new File(cacheDir,name); try { // create cache file InputStream in = new URL(url).openStream(); byte[] buf = HTMLUtil.readStream(in); FileOutputStream out = new FileOutputStream(cacheFile); out.write(buf); out.close(); in.close(); // register to the preference store String uri = store.getString(HTMLPlugin.PREF_DTD_URI); String path = store.getString(HTMLPlugin.PREF_DTD_PATH); store.setValue(HTMLPlugin.PREF_DTD_URI ,uri + "\n" + url); store.setValue(HTMLPlugin.PREF_DTD_PATH ,path + "\n" + cacheFile.getAbsolutePath()); HTMLPlugin.getDefault().savePluginPreferences(); return new ByteArrayInputStream(buf); } catch(Exception ex){ } return null; } public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { if(systemId!=null){ InputStream in = getInputStream(systemId); if(in!=null){ return new InputSource(in); } } return null; } }