package org.xdams.utility.resource; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import javax.servlet.ServletContext; import org.xdams.xml.builder.XMLBuilder; import org.xdams.xml.builder.exception.XMLException; public class ConfManager { private static ConfManager instance = null; /* * contiene una coppia composta da: long -> ultima data di modifica del file PyCode -> il contenuto del file compilato in byte code */ private HashMap<String, List<Resource>> fileMap = null; private class Resource { public long lastModified; public String path; public Object confResource; public Resource(Object confResource, String path, long lastModified) { this.confResource = confResource; this.path = path; this.lastModified = lastModified; } public Resource() { this(null, "", 0L); } } private ConfManager() { fileMap = new HashMap<String, List<Resource>>(); } public static synchronized ConfManager getInstance() { if (instance == null) { instance = new ConfManager(); } return instance; } public static synchronized void resetInstance() { instance = null; } public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } // TODO: implementarlo usando un ConfLoader public static XMLBuilder getConfXML(String fullPath) { try { return getInstance().getConfigurationXML(fullPath); } catch (Exception e) { System.err.println("file non trovato " + fullPath); try { return new XMLBuilder("root"); } catch (XMLException e1) { return null; } // if (e instanceof RuntimeException) // throw (RuntimeException) e; // throw new RuntimeException(e.getMessage(), e); } } public static String getConfString(String fullPath) { try { return getInstance().getConfigurationString(fullPath); } catch (Exception e) { if (e instanceof RuntimeException) throw (RuntimeException) e; throw new RuntimeException(e.getMessage(), e); } } public static XMLBuilder getConfXML(String fullPath, ServletContext servletContext) { try { return getInstance().getConfigurationXML(fullPath, servletContext); } catch (Exception e) { System.err.println("file non trovato " + fullPath); if (e instanceof RuntimeException) throw (RuntimeException) e; throw new RuntimeException(e.getMessage(), e); } } // TODO: implementarlo usando un ConfLoader public static String getConfString(String fullPath, ServletContext servletContext) { try { return getInstance().getConfigurationString(fullPath, servletContext); } catch (Exception e) { if (e instanceof RuntimeException) throw (RuntimeException) e; throw new RuntimeException(e.getMessage(), e); } } public static String getRealPathString(String fullPath) { try { String realPath = getInstance().getClass().getClassLoader().getResource(fullPath).getPath(); // System.out.println("loading "+realPath); if (realPath.indexOf("%20") != -1) { realPath = realPath.replaceAll("%20", " "); } return realPath; } catch (Exception e) { if (e instanceof RuntimeException) throw (RuntimeException) e; throw new RuntimeException(e.getMessage(), e); } } // TODO: implementare il metodo generico getConf che usa un ConfLoader personalizzato per caricare i file // public static Object getConf(String fullPath, ConfLoader loader){ // return null; // } private XMLBuilder getConfigurationXML(String fullPath) throws FileNotFoundException, IOException, XMLException { String realPath = this.getClass().getClassLoader().getResource(fullPath).getPath(); // System.out.println("loading "+realPath); if (realPath.indexOf("%20") != -1) { realPath = realPath.replaceAll("%20", " "); } XMLBuilder builder = null; if (presentInCache(realPath, XMLBuilder.class)) { builder = (XMLBuilder) (getResource(realPath, XMLBuilder.class).confResource); } else { builder = new XMLBuilder(loadString(realPath), false); Resource res = new Resource(builder, realPath, lastModified(realPath)); setResource(realPath, res); } return builder; } private String getConfigurationString(String fullPath) throws FileNotFoundException, IOException { String theString = null; String realPath = this.getClass().getClassLoader().getResource(fullPath).getPath(); if (realPath.indexOf("%20") != -1) { realPath = realPath.replaceAll("%20", " "); } if (presentInCache(realPath, String.class)) { theString = (String) (getResource(realPath, String.class).confResource); } else { theString = loadString(realPath); Resource res = new Resource(theString, realPath, lastModified(realPath)); setResource(realPath, res); } return theString; } private XMLBuilder getConfigurationXML(String fullPath, ServletContext servletContext) throws FileNotFoundException, IOException, XMLException { String realPath = getRealPath(fullPath, servletContext); if (realPath.indexOf("%20") != -1) { realPath = realPath.replaceAll("%20", " "); } XMLBuilder builder = null; if (presentInCache(realPath, XMLBuilder.class)) { builder = (XMLBuilder) (getResource(realPath, XMLBuilder.class).confResource); } else { builder = new XMLBuilder(loadString(realPath), false); Resource res = new Resource(builder, realPath, lastModified(realPath)); setResource(realPath, res); } return builder; } private String getConfigurationString(String fullPath, ServletContext servletContext) throws FileNotFoundException, IOException { String theString = null; String realPath = getRealPath(fullPath, servletContext); if (realPath.indexOf("%20") != -1) { realPath = realPath.replaceAll("%20", " "); } if (presentInCache(realPath, String.class)) { theString = (String) (getResource(realPath, String.class).confResource); } else { theString = loadString(realPath); Resource res = new Resource(theString, realPath, lastModified(realPath)); setResource(realPath, res); } return theString; } private int resourceIndex(String key, Class type) { List<Resource> l = fileMap.get(key); if (l == null) return -1; for (int i = 0; i < l.size(); i++) { Resource res = l.get(i); if (res.confResource.getClass().equals(type)) return i; } return -1; } private boolean containsList(String key) { if (!fileMap.containsKey(key)) return false; if (fileMap.get(key) == null) return false; return true; } private boolean containsResource(String key, Class type) { if (!fileMap.containsKey(key)) return false; if (resourceIndex(key, type) != -1) return true; return false; } private Resource getResource(String key, Class type) { int idx = resourceIndex(key, type); if (idx != -1) return fileMap.get(key).get(idx); return null; } private void setResource(String key, Resource res) { Class type = res.confResource.getClass(); int idx = resourceIndex(key, type); if (idx != -1) { fileMap.get(key).set(idx, res); } else { if (containsList(key)) { fileMap.get(key).add(res); } else { List l = new ArrayList<Resource>(); l.add(res); fileMap.put(key, l); } } } private synchronized String loadString(String realPath) throws FileNotFoundException, IOException { String theString = ""; FileChannel fc = null; try { File theFile = new File(realPath); if (!theFile.exists()) { System.err.println("not found " + realPath); throw new FileNotFoundException(); } fc = new FileInputStream(theFile).getChannel(); ByteBuffer bb = ByteBuffer.allocate((int) fc.size()); fc.read(bb); bb.flip(); // MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); Charset charset = Charset.forName("ISO-8859-1"); CharsetDecoder decoder = charset.newDecoder(); CharBuffer cb = decoder.decode(bb); theString = cb.toString(); } finally { try { fc.close(); } catch (Exception e) { } } return theString; } private long lastModified(String realPath) { File theFile = new File(realPath); return theFile.lastModified(); } private boolean presentInCache(String realPath, Class type) { Resource res = getResource(realPath, type); if (res == null) return false; if (res.lastModified != lastModified(realPath)) return false; return true; } private String getRealPath(String path, ServletContext servletContext) { String realPath = servletContext.getRealPath("/WEB-INF/classes"); if (!path.startsWith("/") && !path.startsWith("\\")) { path = "/" + path; } realPath += path; realPath = realPath.replaceAll("\\\\", "/").trim(); return realPath; } }