001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020package org.apache.isis.core.commons.xml; 021 022import java.io.File; 023import java.io.FileInputStream; 024import java.io.FileNotFoundException; 025import java.io.FileOutputStream; 026import java.io.FilenameFilter; 027import java.io.IOException; 028import java.io.InputStreamReader; 029import java.io.OutputStreamWriter; 030 031import org.xml.sax.ContentHandler; 032import org.xml.sax.InputSource; 033import org.xml.sax.SAXException; 034import org.xml.sax.SAXParseException; 035import org.xml.sax.XMLReader; 036import org.xml.sax.helpers.XMLReaderFactory; 037 038import org.apache.isis.core.commons.exceptions.IsisException; 039import org.apache.isis.core.commons.util.ToString; 040 041public class XmlFile { 042 private static final String[] ESCAPE_STRING = { "&", "<", ">", """, "'" }; 043 private static final String[] SPECIAL_CHARACTERS = { "&", "<", ">", "\"", "'" }; 044 045 public static String getValueWithSpecialsEscaped(final String s) { 046 String result = s; 047 for (int i = 0; i < SPECIAL_CHARACTERS.length; i++) { 048 final String special = SPECIAL_CHARACTERS[i]; 049 int pos = -1; 050 while (true) { 051 pos = result.indexOf(special, pos + 1); 052 if (pos < 0) { 053 break; 054 } 055 result = result.substring(0, pos) + ESCAPE_STRING[i] + result.substring(pos + special.length()); 056 } 057 } 058 return result; 059 } 060 061 private final String charset; 062 private final File directory; 063 064 public XmlFile(final String charset, final String directory) { 065 this.directory = new File(directory); 066 createDirectoryIfRequired(); 067 this.charset = charset; 068 } 069 070 private void createDirectoryIfRequired() { 071 if (this.directory.exists()) { 072 return; 073 } 074 this.directory.mkdirs(); 075 } 076 077 private void createDirectoryIfRequired(File file) { 078 if(file.exists()) { 079 return; 080 } 081 file.getParentFile().mkdirs(); 082 } 083 084 public File getDirectory() { 085 return directory; 086 } 087 088 private File file(final String fileName) { 089 return new File(directory, fileName + ".xml"); 090 } 091 092 public void writeXml(final String name, final ContentWriter writer) { 093 OutputStreamWriter pw; 094 095 try { 096 final File file = file(name); 097 createDirectoryIfRequired(file); 098 pw = new OutputStreamWriter(new FileOutputStream(file), charset); 099 pw.write("<?xml version=\"1.0\" encoding=\"" + charset + "\" ?>\n"); 100 pw.write("\n"); 101 writer.write(pw); 102 pw.write("\n"); 103 pw.close(); 104 } catch (final IOException e) { 105 throw new IsisException("Problems writing data files", e); 106 } 107 } 108 109 110 public boolean parse(final ContentHandler handler, final String fileName) { 111 XMLReader parser; 112 113 try { 114 parser = XMLReaderFactory.createXMLReader(); 115 } catch (final SAXException e) { 116 try { 117 parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser"); 118 } catch (final SAXException e2) { 119 try { 120 parser = XMLReaderFactory.createXMLReader("org.apache.crimson.parser.XMLReaderImpl"); 121 } catch (final SAXException failed) { 122 throw new IsisException("Couldn't locate a SAX parser"); 123 } 124 } 125 } 126 127 final File file = file(fileName); 128 try { 129 parser.setContentHandler(handler); 130 final FileInputStream fis = new FileInputStream(file); 131 final InputStreamReader isr = new InputStreamReader(fis, charset); 132 final InputSource is = new InputSource(isr); 133 parser.parse(is); 134 135 return true; 136 } catch (final FileNotFoundException e) { 137 return false; 138 } catch (final IOException e) { 139 throw new IsisException("Error reading XML file", e); 140 } catch (final SAXParseException e) { 141 throw new IsisException("Error while parsing: " + e.getMessage() + " in " + file + ")", e); 142 } catch (final SAXException e) { 143 throw new IsisException("Error in file " + file + " ", e); 144 } 145 } 146 147 public void delete(final String fileName) { 148 file(fileName).delete(); 149 } 150 151 /** 152 * The XML store is deemed to be initialised if the directory used to store 153 * the data has no xml files in it. 154 */ 155 public boolean isFixturesInstalled() { 156 final String[] list = directory.list(new FilenameFilter() { 157 @Override 158 public boolean accept(final File dir, final String name) { 159 return name.toLowerCase().endsWith(".xml"); 160 } 161 }); 162 return list.length > 0; 163 } 164 165 @Override 166 public String toString() { 167 return new ToString(this).append("directory", this.directory).toString(); 168 } 169 170}