/* * (C) Copyright 2006-2012 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed 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. * * Contributors: * bstefanescu, jcarsique */ package org.nuxeo.connect.update.task.update; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; 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.commons.io.IOUtils; import org.nuxeo.connect.update.PackageException; import org.nuxeo.connect.update.xml.XmlWriter; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.SAXException; /** * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> */ public class RegistrySerializer extends XmlWriter { private final static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); /** * @since 5.7 */ public RegistrySerializer() { super(" "); } /** * Serializes the given registry into the given file. * * @param registry * @param file * @throws IOException */ public static void store(Map<String, Entry> registry, File file) throws IOException { RegistrySerializer serializer = new RegistrySerializer(); serializer.write(registry); serializer.write(file); } /** * De-serializes the given file into a Nuxeo packages registry * * @param file * @return The Nuxeo packages registry described by the given file */ public static Map<String, Entry> load(File file) throws PackageException, IOException { RegistrySerializer serializer = new RegistrySerializer(); return serializer.read(file); } protected Map<String, Entry> read(File file) throws PackageException, IOException { FileInputStream in = new FileInputStream(file); try { HashMap<String, Entry> registry = new HashMap<String, Entry>(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(in); read(document.getDocumentElement(), registry); return registry; } catch (ParserConfigurationException | SAXException e) { throw new RuntimeException(e); } finally { IOUtils.closeQuietly(in); } } protected void read(Element element, Map<String, Entry> registry) throws PackageException { Node node = element.getFirstChild(); while (node != null) { if (node.getNodeType() == Node.ELEMENT_NODE && "entry".equals(node.getNodeName())) { Entry entry = readEntryElement((Element) node); registry.put(entry.getKey(), entry); } node = node.getNextSibling(); } } protected Entry readEntryElement(Element element) throws PackageException { Entry entry = new Entry(readKeyAttr(element)); Node node = element.getFirstChild(); while (node != null) { if (node.getNodeType() == Node.ELEMENT_NODE) { String name = node.getNodeName(); if ("version".equals(name)) { Version v = readVersionElement((Element) node); entry.addVersion(v); } else if ("base-version".equals(name)) { Version v = readVersionElement((Element) node); entry.setBaseVersion(v); } } node = node.getNextSibling(); } return entry; } protected String readKeyAttr(Element element) throws PackageException { String key = element.getAttribute("key"); if (key.length() == 0) { throw new PackageException("Invalid entry. No 'key' attribute found!"); } return key; } protected String readNameAttr(Element element) throws PackageException { String version = element.getAttribute("name"); if (version.length() == 0) { throw new PackageException("Invalid version entry. No 'name' attribute found!"); } return version; } protected String readPathAttr(Element element) throws PackageException { String path = element.getAttribute("path"); if (path.length() == 0) { throw new PackageException("Invalid version entry. No 'path' attribute found!"); } return path; } protected Version readVersionElement(Element element) throws PackageException { Version v = new Version(readNameAttr(element)); v.setPath(readPathAttr(element)); Node node = element.getFirstChild(); while (node != null) { if (node.getNodeType() == Node.ELEMENT_NODE && "package".equals(node.getNodeName())) { UpdateOptions opt = new UpdateOptions(); opt.pkgId = ((Element) node).getTextContent().trim(); opt.upgradeOnly = Boolean.parseBoolean(((Element) node).getAttribute("upgradeOnly")); v.addPackage(opt); } node = node.getNextSibling(); } return v; } protected void write(Map<String, Entry> registry) { writeXmlDecl(); start("registry"); startContent(); for (Entry entry : registry.values()) { writeEntry(entry); } end("registry"); } protected void writeEntry(Entry entry) { start("entry"); attr("key", entry.getKey()); startContent(); if (entry.hasBaseVersion()) { writeBaseVersion(entry.getBaseVersion()); } for (Version v : entry) { writeVersion(v); } end("entry"); } protected void writeBaseVersion(Version version) { start("base-version"); attr("name", version.getVersion()); attr("path", version.getPath()); end(); } protected void writeVersion(Version version) { start("version"); attr("name", version.getVersion()); attr("path", version.getPath()); startContent(); Map<String, UpdateOptions> packages = version.getPackages(); for (UpdateOptions opt : packages.values()) { start("package"); if (opt.upgradeOnly) { attr("upgradeOnly", "true"); } // Missing methods to properly append the following without indent text(">" + opt.pkgId + "</package>\n"); // startContent(false); // text(opt.pkgId); // end("package", false); } end("version"); } /** * @param file Output file * @throws IOException * @since 5.7 */ protected void write(File file) throws IOException { Writer writer = new OutputStreamWriter(new FileOutputStream(file)); try { writer.write(sb.toString()); } finally { IOUtils.closeQuietly(writer); } } }