package com.meidusa.amoeba.config.loader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.log4j.Logger; import org.apache.log4j.helpers.FileWatchdog; import org.apache.log4j.helpers.LogLog; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.EntityResolver; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import com.meidusa.amoeba.config.UserConfig; import com.meidusa.amoeba.config.loader.UserLoader; import com.meidusa.amoeba.context.ProxyRuntimeContext; import com.meidusa.amoeba.exception.ConfigurationException; import com.meidusa.amoeba.exception.InitialisationException; import com.meidusa.amoeba.util.Initialisable; public class UserFileLoader implements UserLoader, Initialisable{ protected static Logger logger = Logger.getLogger(UserFileLoader.class); private String userFile; @Override public void loadUser() { Map<String, UserConfig> users = ProxyRuntimeContext.getInstance().getUserMap(); DocumentBuilder db; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(true); dbf.setNamespaceAware(false); db = dbf.newDocumentBuilder(); db.setEntityResolver(new EntityResolver() { public InputSource resolveEntity(String publicId, String systemId) { if (systemId.endsWith("user.dtd")) { InputStream in = this.getClass().getResourceAsStream("/com/meidusa/amoeba/xml/user.dtd"); if (in == null) { LogLog.error("Could not find [user.dtd]. Used [" + ProxyRuntimeContext.class.getClassLoader() + "] class loader in the search."); return null; } else { return new InputSource(in); } } else { return null; } } }); db.setErrorHandler(new ErrorHandler() { public void warning(SAXParseException exception) { } public void error(SAXParseException exception) throws SAXException { logger.error(exception.getMessage() + " at (" + exception.getLineNumber() + ":" + exception.getColumnNumber() + ")"); throw exception; } public void fatalError(SAXParseException exception) throws SAXException { logger.fatal(exception.getMessage() + " at (" + exception.getLineNumber() + ":" + exception.getColumnNumber() + ")"); throw exception; } }); Document doc = null; InputStream is = null; try { is = new FileInputStream(new File(userFile)); doc = db.parse(is); } catch (Exception e) { final String s = "Caught exception while loading file " + userFile; logger.error(s, e); throw new ConfigurationException(s, e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { logger.error("Unable to close input stream", e); } } } Element rootElement = doc.getDocumentElement(); NodeList children = rootElement.getChildNodes(); int childSize = children.getLength(); for(int i=0; i<childSize; i++) { Node childNode = children.item(i); if (childNode instanceof Element) { Element current = (Element) childNode; final String nodeName = current.getNodeName(); if (nodeName.equals("user")) { String name = current.getAttribute("name"); String passwd = current.getAttribute("passwd"); String isAdmin = current.getAttribute("isAdmin"); UserConfig user = new UserConfig(name, passwd); if ("true".equals(isAdmin)) { user.setAdmin(true); } users.put(name, user); } } } } catch (Exception e) { logger.fatal("Could not load configuration file, failing", e); throw new ConfigurationException("Error loading configuration file " + userFile, e); } } public String getUserFile() { return userFile; } public void setUserFile(String userFile) { try { this.userFile = (new File(userFile)).getCanonicalPath(); } catch (IOException e) { throw new ConfigurationException(e); } } @Override public void init() throws InitialisationException { UserFileWatchdog dog = new UserFileWatchdog(userFile); dog.setDaemon(true); dog.setDelay(FileWatchdog.DEFAULT_DELAY); dog.start(); } private class UserFileWatchdog extends FileWatchdog { public UserFileWatchdog(String filename) { super(filename); } public void doOnChange() { UserFileLoader.this.userFile = this.filename; UserFileLoader.this.loadUser(); if (logger.isInfoEnabled()) { logger.info(String.format("loaded userMap from: %s", userFile)); } } } }