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;
}
}