blob: ba1721daa9967312b698653980534b8fe8d02249 [file] [log] [blame]
/*
* 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;
}
}