/** * SPINdle (version 2.2.2) * Copyright (C) 2009-2012 NICTA Ltd. * * This file is part of SPINdle project. * * SPINdle is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SPINdle is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SPINdle. If not, see <http://www.gnu.org/licenses/>. * * @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory */ package spindle.io; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import spindle.core.dom.Conclusion; import spindle.core.dom.ConclusionType; import spindle.core.dom.Literal; import spindle.core.dom.Theory; import spindle.core.dom.TheoryException; import spindle.io.parser.DflTheoryParser2; import spindle.io.parser.XmlTheoryParser2; import spindle.sys.AppConst; import spindle.sys.AppLogger; import spindle.sys.Conf; import spindle.sys.ConfigurationException; import spindle.sys.message.ErrorMessage; import com.app.utils.ClassList; import com.app.utils.FileManager; import com.app.utils.ResourcesUtils; import com.app.utils.Utilities; import com.app.utils.Utilities.ProcessStatus; /** * SPINdle I/O Manager. * <p> * Provides I/O (theories and conclusions) support (and coordination) to SPINdle reasoning engines. * </p> * * @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory * @version Last modified 2011.07.27 * @since version 1.0.0 */ public final class IOManager { private static ClassList classList = new ClassList(); private static Set<String> interfaceFilter = new HashSet<String>(); private static long configurationTimeUsed = 0; private static Map<String, TheoryParser> parsers = null; private static Map<String, TheoryOutputter> outputters = null; static { try { interfaceFilter.add(TheoryParser.class.getName()); interfaceFilter.add(TheoryOutputter.class.getName()); initialize(); } catch (ConfigurationException e) { e.printStackTrace(); System.exit(1); } } public synchronized static void printMessage(PrintStream out, int level, String message, boolean withLineBreak) { if (null == message || "".equals(message.trim())) return; String identator = ""; for (int i = 0; i < level; i++) { identator += AppConst.IDENTATOR; } if (withLineBreak) out.println(identator + message.trim()); else out.print(identator + message.trim()); out.flush(); } public static void printMessage(String message) { printMessage(System.out, 0, message, true); } public static void printMessage(int level, String message) { printMessage(System.out, level, message, true); } public static void printMessage(int level, String message, boolean withLineBreak) { printMessage(System.out, level, message, withLineBreak); } /** * search for I/O classes with TheoryParser and TheoryOutputter interface * * @return * @throws IOException * @throws ClassNotFoundException */ private synchronized static Map<String, Set<String>> searchIOclasses() throws IOException, ClassNotFoundException { return classList.findClass(interfaceFilter, null, null); } private synchronized static Map<String, Set<String>> getIOclassesFromConfigFile() throws ClassNotFoundException, IOException, ParserConfigurationException, SAXException { InputStream ins = null; try { ins = ResourcesUtils.getResourceAsStream(AppConst.IO_CONF_FILE); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = dbf.newDocumentBuilder(); Document doc = documentBuilder.parse(ins); doc.getDocumentElement().normalize(); Set<String> classNames = new HashSet<String>(); NodeList nodeList = doc.getElementsByTagName("io"); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element ioClassEle = (Element) node; String ioClassname = ioClassEle.getAttribute("classname"); if (null != ioClassname) classNames.add(ioClassname); } } return classList.identifyInterface(interfaceFilter, classNames); } finally { if (null != ins) ins.close(); ins = null; } } public synchronized static void initialize() throws ConfigurationException { if (null != parsers && null != outputters) return; // search all the I/O classes in the package // and create the associated parser/outputter class long timeStart = System.currentTimeMillis(); try { Map<String, Set<String>> classes = Conf.isSearchIOclasses() ? searchIOclasses() : getIOclassesFromConfigFile(); parsers = new HashMap<String, TheoryParser>(); outputters = new HashMap<String, TheoryOutputter>(); printMessage(1, "configurating I/O classes - start"); for (Entry<String, Set<String>> entry : classes.entrySet()) { if (TheoryParser.class.getName().equals(entry.getKey())) { for (String parserName : entry.getValue()) { try { printMessage(2, "generating parser [" + parserName + "]", false); TheoryParser parser = Utilities.getInstance(parserName, TheoryParser.class); // Class<?> clazz = Class.forName(parserName); // TheoryParser parser = clazz.asSubclass(TheoryParser.class).newInstance(); printMessage("...success, type=[" + parser.getParserType() + "]"); parsers.put(parser.getParserType(), parser); } catch (Exception e) { if (!AppConst.isDeploy) printMessage("...failed"); throw new ConfigurationException(ErrorMessage.IO_PARSER_INITITATION_ERROR, new String[] { parserName }, e); } } } else if (TheoryOutputter.class.getName().equals(entry.getKey())) { for (String outputterName : entry.getValue()) { try { printMessage(2, "generating outputter [" + outputterName + "]", false); TheoryOutputter outputter = Utilities.getInstance(outputterName, TheoryOutputter.class); // Class<?> clazz = Class.forName(outputterName); // TheoryOutputter outputter = clazz.asSubclass(TheoryOutputter.class).newInstance(); printMessage("...success, type=[" + outputter.getOutputterType() + "]"); outputters.put(outputter.getOutputterType(), outputter); } catch (Exception e) { if (!AppConst.isDeploy) printMessage("...failed"); throw new ConfigurationException(ErrorMessage.IO_OUTPUTTER_INITIATION_ERROR, new String[] { outputterName }, e); } } } } configurationTimeUsed += (System.currentTimeMillis() - timeStart); printMessage(1, "configurating I/O classes - end"); } catch (Exception e) { throw new ConfigurationException(e); } } public static long getConfigurationTimeUsed() { return configurationTimeUsed; } public static final Theory getTheory(final URI uri, final AppLogger logger) throws ParserException, MalformedURLException { try { return getTheory(uri.toURL(), logger); } catch (IOException e) { throw new ParserException(e); } } public static final Theory getTheory(final URL url, final AppLogger logger) throws ParserException, IOException { String filename = url.getFile(); try { URLConnection urlc = url.openConnection(); // get the content type String parserType = FileManager.getFileExtension(filename); if ("".equals(parserType)) { String contentType = urlc.getContentType(); if (null != contentType) { contentType = contentType.toLowerCase(); if (contentType.indexOf(XmlTheoryParser2.PARSER_TYPE) >= 0) parserType = XmlTheoryParser2.PARSER_TYPE; else if (contentType.indexOf(DflTheoryParser2.PARSER_TYPE) >= 0) parserType = DflTheoryParser2.PARSER_TYPE; } // set the default parserType to xml if no theory type info can // be found if ("".equals(parserType)) parserType = DflTheoryParser2.PARSER_TYPE; } return getTheory(urlc.getInputStream(), getParser(parserType), logger); } catch (ParserException e) { throw e; } catch (Exception e) { throw new ParserException(e); } } public static final Theory getTheory(final File filename, final AppLogger logger) throws ParserException, IOException { String parserType = FileManager.getFileExtension(filename); try { return getTheory(new FileInputStream(filename), getParser(parserType), logger); } catch (Exception e) { throw new ParserException(e); } } public static final Theory getTheory(final InputStream ins, String parserType, // final AppLogger logger) throws ParserException, IOException { if (null == parserType) throw new ParserException(ErrorMessage.IO_PARSER_TYPE_UNKNOWN); try { return getTheory(ins, getParser(parserType), logger); } catch (ConfigurationException e) { throw new ParserException(e); } } public static final Theory getTheory(final InputStream ins, TheoryParser parser, // final AppLogger logger) throws ParserException, IOException { if (null == parser) throw new ParserException(ErrorMessage.IO_PARSER_TYPE_UNKNOWN); try { if (null != logger) parser.setAppLogger(logger); return parser.getTheory(ins); } catch (ParserException e) { throw e; } catch (Exception e) { throw new ParserException(e); } finally { parser.resetAppLogger(); if (null != ins) ins.close(); } } public static final Map<Literal, Map<ConclusionType, Conclusion>> getConclusions(final URL url, final AppLogger logger) throws ParserException, IOException { String filename = url.getFile(); try { URLConnection urlc = url.openConnection(); // get the content type String parserType = FileManager.getFileExtension(filename); if ("".equals(parserType)) { String contentType = urlc.getContentType(); if (null != contentType) { contentType = contentType.toLowerCase(); if (contentType.indexOf(XmlTheoryParser2.PARSER_TYPE) >= 0) parserType = XmlTheoryParser2.PARSER_TYPE; else if (contentType.indexOf(DflTheoryParser2.PARSER_TYPE) >= 0) parserType = DflTheoryParser2.PARSER_TYPE; } // set the default parserType to xml if no theory type info can // be found if ("".equals(parserType)) parserType = XmlTheoryParser2.PARSER_TYPE; } return getConclusions(urlc.getInputStream(), getParser(parserType), logger); } catch (ParserException e) { throw e; } catch (Exception e) { throw new ParserException(e); } } public static final Map<Literal, Map<ConclusionType, Conclusion>> getConclusions(File filename,// AppLogger logger) throws ParserException, IOException { String parserType = FileManager.getFileExtension(filename); try { return getConclusions(new FileInputStream(filename), getParser(parserType), logger); } catch (ParserException e) { throw e; } catch (Exception e) { throw new ParserException(e); } } public static final Map<Literal, Map<ConclusionType, Conclusion>> getConclusions(InputStream ins, String parserType,// AppLogger logger) throws ParserException, IOException { if (null == parserType) throw new ParserException("parser type is null"); try { return getConclusions(ins, getParser(parserType), logger); } catch (ParserException e) { throw e; } catch (ConfigurationException e) { throw new ParserException(e); } } public static final Map<Literal, Map<ConclusionType, Conclusion>> getConclusions(InputStream ins, TheoryParser parser, // AppLogger logger) throws ParserException, IOException { if (null == parser) throw new ParserException("parser is null"); try { if (null != logger) parser.setAppLogger(logger); return parser.getConclusions(ins); } catch (ParserException e) { throw e; } catch (Exception e) { throw new ParserException(e); } finally { parser.resetAppLogger(); if (null != ins) ins.close(); } } /** * Return the set of parser types supported. * * @return <code>Set<String></code> Set of parser types. */ public static final Set<String> getParserTypes() { return parsers.keySet(); } public static final TheoryParser getParser(final String parserType) throws ParserException, ConfigurationException { if (null == parsers) initialize(); String type = parserType.toLowerCase(); if (parsers.containsKey(type)) { TheoryParser parser = parsers.get(type); parser.resetAppLogger(); return parser; } else throw new ParserException(ErrorMessage.IO_PARSER_TYPE_UNKNOWN, new Object[] { type }); } /** * Return the set of outputter types supported. * * @return <code>Set<String></code> Set of outputter types. */ public static final Set<String> getOutputterTypes() { return outputters.keySet(); } /** * @param outputterType * the outputter type * @return the associated FileOutputter of the specified file * @throws OutputterException * @throws IOException */ public static final TheoryOutputter getOutputter(final String outputterType) throws ConfigurationException { if (null == outputters) initialize(); String type = outputterType.toLowerCase(); if (outputters.containsKey(type)) { TheoryOutputter outputter = outputters.get(type); outputter.resetAppLogger(); return outputter; } else throw new ConfigurationException(ErrorMessage.IO_OUTPUTTER_TYPE_UNKNOWN, new Object[] { type }); } /** * @param filename * @param theory * @return ProcessStatus.SUCCESS if success, exception throw otherwise * @throws TheoryException */ public static final ProcessStatus save(File filename, Theory theory, AppLogger logger) throws OutputterException { File path = filename.getParentFile(); if (null != path) path.mkdirs(); String outputterType = FileManager.getFileExtension(filename); try { return save(new FileOutputStream(filename), getOutputter(outputterType), theory, logger); } catch (Exception e) { throw new OutputterException(e); } } public static final ProcessStatus save(OutputStream outs, String outputterType,// Theory theory, AppLogger logger) throws OutputterException, IOException { try { return save(outs, getOutputter(outputterType), theory, logger); } catch (ConfigurationException e) { throw new OutputterException(e); } } public static final ProcessStatus save(OutputStream outs, TheoryOutputter outputter,// Theory theory, AppLogger logger) throws OutputterException { try { if (null != logger) outputter.setAppLogger(logger); outputter.save(outs, theory); return ProcessStatus.SUCCESS; } catch (Exception e) { throw new OutputterException("Exception throw while saving theory", e); } finally { outputter.resetAppLogger(); if (null != outs) { try { outs.flush(); outs.close(); } catch (Exception e) { } } } } /** * @param filename * @param conclusionsAsList * @return ProcessStatus.SUCCESS if success, exception throw otherwise * @throws TheoryException */ public static final ProcessStatus save(File filename, List<Conclusion> conclusionsAsList,// AppLogger logger) throws OutputterException { File path = filename.getParentFile(); if (null != path) path.mkdirs(); String outputterType = FileManager.getFileExtension(filename); try { return save(new FileOutputStream(filename), getOutputter(outputterType), conclusionsAsList, logger); } catch (Exception e) { throw new OutputterException(e); } } public static final ProcessStatus save(OutputStream outs, String outputterType,// List<Conclusion> conclusionsAsList, AppLogger logger) throws OutputterException, IOException { try { return save(outs, getOutputter(outputterType), conclusionsAsList, logger); } catch (ConfigurationException e) { throw new OutputterException(e); } } public static final ProcessStatus save(OutputStream outs, TheoryOutputter outputter,// List<Conclusion> conclusionsAsList, AppLogger logger) throws OutputterException, IOException { try { if (null != logger) outputter.setAppLogger(logger); outputter.save(outs, conclusionsAsList); return ProcessStatus.SUCCESS; } catch (Exception e) { throw new OutputterException("Exception throw while saving theory", e); } finally { outputter.resetAppLogger(); if (null != outs) { outs.flush(); outs.close(); } } } }