| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.jackrabbit.vault.vlt.meta.xml; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| |
| import org.apache.jackrabbit.vault.util.xml.serialize.OutputFormat; |
| import org.apache.jackrabbit.vault.util.xml.serialize.XMLSerializer; |
| import org.apache.jackrabbit.vault.vlt.VltException; |
| import org.apache.jackrabbit.vault.vlt.VltFile; |
| import org.apache.jackrabbit.vault.vlt.meta.VltEntries; |
| import org.apache.jackrabbit.vault.vlt.meta.VltEntry; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.ContentHandler; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.AttributesImpl; |
| |
| /** |
| * {@code Entries}... |
| * |
| */ |
| public class XmlEntries implements VltEntries { |
| |
| public static final String EN_ENTRIES = "entries"; |
| |
| public static final String AN_PATH = "path"; |
| |
| public static final String AN_AGGREGATE_PATH = "aggregatePath"; |
| |
| private final String path; |
| |
| private Map<String, VltEntry> entries = new HashMap<String, VltEntry>(); |
| |
| private boolean dirty; |
| |
| public XmlEntries(String path) { |
| this.path = path; |
| } |
| |
| public XmlEntries(String path, boolean dirty) { |
| this.path = path; |
| this.dirty = dirty; |
| } |
| |
| public String getPath() { |
| return path; |
| } |
| |
| public static XmlEntries load(InputStream in) throws VltException { |
| InputSource source = new InputSource(in); |
| return load(source); |
| } |
| |
| public static XmlEntries load(InputSource source) throws VltException { |
| try { |
| DocumentBuilderFactory factory = |
| DocumentBuilderFactory.newInstance(); |
| // disable DTD loading (bug #36897) |
| factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); |
| DocumentBuilder builder = factory.newDocumentBuilder(); |
| Document document = builder.parse(source); |
| Element doc = document.getDocumentElement(); |
| if (!doc.getNodeName().equals(EN_ENTRIES)) { |
| throw new VltException(source.getSystemId(), "<entries> expected."); |
| } |
| // get uri |
| String path = doc.getAttribute(AN_PATH); |
| XmlEntries entries = new XmlEntries(path); |
| |
| // get entries |
| NodeList nodes = doc.getChildNodes(); |
| for (int i=0; i<nodes.getLength(); i++) { |
| Node node = nodes.item(i); |
| if (node instanceof Element) { |
| Element elem = (Element) node; |
| if (elem.getNodeName().equals(XmlEntry.EN_ENTRY)) { |
| XmlEntry entry = XmlEntry.load(elem); |
| entries.entries.put(entry.getName(), entry); |
| } else { |
| throw new VltException(source.getSystemId(), |
| "<entry> expected in <entries> element."); |
| } |
| } |
| } |
| entries.dirty = false; |
| return entries; |
| } catch (ParserConfigurationException e) { |
| throw new VltException(source.getSystemId(), |
| "Unable to create configuration XML parser", e); |
| } catch (SAXException e) { |
| throw new VltException(source.getSystemId(), |
| "Configuration file syntax error.", e); |
| } catch (IOException e) { |
| throw new VltException(source.getSystemId(), |
| "Configuration file could not be read.", e); |
| } |
| } |
| |
| /* |
| public void save(File file) throws VltException { |
| if (file.exists() && !isDirty()) { |
| return; |
| } |
| try { |
| FileOutputStream out = new FileOutputStream(file); |
| save(out); |
| out.close(); |
| } catch (IOException e) { |
| throw new VltException(file.getPath(), "Error while saving", e); |
| } |
| } |
| */ |
| |
| public void save(OutputStream out) throws IOException { |
| OutputFormat fmt = new OutputFormat("xml", "UTF-8", true); |
| fmt.setLineWidth(0); |
| fmt.setIndent(2); |
| XMLSerializer ser = new XMLSerializer(out, fmt); |
| try { |
| write(ser); |
| } catch (SAXException e) { |
| throw new IOException(e.toString()); |
| } |
| } |
| |
| private void write(ContentHandler handler) throws SAXException { |
| handler.startDocument(); |
| AttributesImpl attrs = new AttributesImpl(); |
| attrs.addAttribute("", AN_PATH, "", "CDATA", path); |
| handler.startElement("", EN_ENTRIES, "", attrs); |
| for (VltEntry e: entries.values()) { |
| ((XmlEntry) e).write(handler); |
| } |
| handler.endElement("", EN_ENTRIES, ""); |
| handler.endDocument(); |
| dirty = false; |
| } |
| |
| public void update(VltFile file) { |
| VltEntry e = file.getEntry(); |
| if (e == null) { |
| entries.remove(file.getName()); |
| dirty = true; |
| } else { |
| putEntry(e); |
| } |
| } |
| |
| public void putEntry(VltEntry e) { |
| if (entries.get(e.getName()) != e) { |
| dirty = true; |
| entries.put(e.getName(), e); |
| } |
| } |
| |
| public VltEntry getEntry(String localName) { |
| return entries.get(localName); |
| } |
| |
| public VltEntry update(String localName, String aggregatePath, String repoRelPath) { |
| XmlEntry e = new XmlEntry(localName, aggregatePath, repoRelPath); |
| VltEntry old = entries.remove(localName); |
| if (old != null) { |
| e.put(old.work()); |
| e.put(old.base()); |
| e.put(old.mine()); |
| e.put(old.theirs()); |
| } |
| putEntry(e); |
| return e; |
| } |
| |
| public boolean hasEntry(String localName) { |
| return entries.containsKey(localName); |
| } |
| |
| public Collection<VltEntry> entries() { |
| return entries.values(); |
| } |
| |
| public void setDirty(boolean dirty) { |
| this.dirty = dirty; |
| } |
| |
| public boolean isDirty() { |
| if (dirty) { |
| return true; |
| } |
| for (VltEntry e: entries.values()) { |
| if (e.isDirty()) { |
| return dirty = true; |
| } |
| } |
| return false; |
| } |
| } |