/* * Copyright (c) 2010, SQL Power Group Inc. */ package ca.sqlpower.dao; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.Reader; import java.util.Stack; import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; import org.apache.xerces.parsers.SAXParser; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import ca.sqlpower.dao.SPPersister.DataType; import ca.sqlpower.dao.upgrade.UpgradePersisterManager; import ca.sqlpower.util.SQLPowerUtils; public class XMLPersisterReader { private static final Logger logger = Logger .getLogger(XMLPersisterReader.class); private final Reader in; private final SPPersister target; private SPPersister upgradeTarget; private UpgradePersisterManager upgradePersisterManager; public final String PROJECT_TAG; public XMLPersisterReader(Reader in, SPPersister target, UpgradePersisterManager upgradePersisterManager, String projectTag) { this.in = in; this.target = target; this.upgradePersisterManager = upgradePersisterManager; this.PROJECT_TAG = projectTag; } public void read() throws SPPersistenceException { BufferedReader reader = new BufferedReader(in); String line; try { reader.mark(200); line = reader.readLine(); while (!line.contains("<" + PROJECT_TAG)) { line = reader.readLine(); } reader.reset(); } catch (IOException e) { throw new SPPersistenceException(null, e); } int version = Integer.valueOf(line.substring(line.indexOf("file-version=") + "file-version=\"".length(), line.length()-2)); SPUpgradePersister latest = null; SPPersister previousTarget = null; upgradeTarget = target; if (version != upgradePersisterManager.getStateVersion()) { SPUpgradePersister newUpgradeTarget = upgradePersisterManager.getUpgradePersister(version); if (newUpgradeTarget != null) { upgradeTarget = newUpgradeTarget; } latest = upgradePersisterManager.getUpgradePersister(upgradePersisterManager.getStateVersion()-1); if (latest != null) { previousTarget = latest.getNextPersister(); latest.setNextPersister(target, false); } } try { upgradeTarget.begin(); SAXHandler handler = new SAXHandler(); SAXParser parser = new SAXParser(); parser.setContentHandler(handler); parser.parse(new InputSource(reader)); upgradeTarget.commit(); } catch (Exception e) { if (latest != null) { latest.setNextPersister(previousTarget, false); } logger.error("error loading project", e); upgradeTarget.rollback(); throw new SPPersistenceException(null, e); } } private Object castValue(DataType type, String value) { switch (type) { case INTEGER: return Integer.valueOf(value); case LONG: return Long.valueOf(value); case DOUBLE: return Double.valueOf(value); case BOOLEAN: return Boolean.valueOf(value); case NULL: return null; case PNG_IMG: return new ByteArrayInputStream(Base64.decodeBase64(value.getBytes())); case STRING: case REFERENCE: return value; default: throw new IllegalArgumentException("Unknown DataType " + type); } } private class SAXHandler extends DefaultHandler { private Stack<String> currentObject = new Stack<String>(); @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { try { if ("property".equals(localName)) { String name = attributes.getValue("name"); DataType type = DataType.valueOf(attributes.getValue("type")); String value = attributes.getValue("value"); value = SQLPowerUtils.unEscapeNewLines(value); upgradeTarget.persistProperty(currentObject.peek(), name, type, castValue(type, value)); } else if (PROJECT_TAG.equals(localName)) { // ignore } else { logger.debug("Reading element " + localName); String type = localName.replace("..", "$"); String UUID = attributes.getValue("UUID"); int index = Integer.valueOf(attributes.getValue("index")); String parent; if (currentObject.isEmpty()) { parent = ""; } else { parent = currentObject.peek(); } upgradeTarget.persistObject(parent, type, UUID, index); currentObject.push(UUID); } } catch (SPPersistenceException e) { throw new RuntimeException(e); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (!"property".equals(localName) && !PROJECT_TAG.equals(localName)) { currentObject.pop(); } } } }