/******************************************************************************* * Copyright (c) 2016 Tasktop Technologies and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Tasktop Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.tasks.core.externalization; import java.io.IOException; import java.io.OutputStream; import java.util.Collection; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stream.StreamResult; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; import org.eclipse.mylyn.internal.tasks.core.ITransferList; import org.eclipse.mylyn.internal.tasks.core.SaxRepositoriesWriter; import org.eclipse.mylyn.tasks.core.IRepositoryElement; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; import org.xml.sax.EntityResolver; import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; import org.xml.sax.XMLReader; /** * Adapted from {@link SaxRepositoriesWriter} */ public class SaxTaskListWriter { private static final String ATTRIBUTE_VERSION = "Version"; //$NON-NLS-1$ // Mylyn 3.0 private static final String VALUE_VERSION = "2.0"; //$NON-NLS-1$ private OutputStream outputStream; public void setOutputStream(OutputStream outputStream) { this.outputStream = outputStream; } public void writeTaskListToStream(ITransferList taskList, Document orphans) throws IOException { if (outputStream == null) { throw new IOException("OutputStream not set"); //$NON-NLS-1$ } try { Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.transform(new SAXSource(new TaskListWriter(), new TaskListInputSource(taskList, orphans)), new StreamResult(outputStream)); } catch (TransformerException e) { StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, "Could not write task list", e)); //$NON-NLS-1$ throw new IOException(e.getMessage(), e); } } private static class TaskListInputSource extends InputSource { private final ITransferList taskList; private final Document orphans; public TaskListInputSource(ITransferList taskList, Document orphans) { this.taskList = taskList; this.orphans = orphans; } public ITransferList getTaskList() { return this.taskList; } public Document getOrphans() { return orphans; } } private static class TaskListWriter implements XMLReader { private ContentHandlerWrapper handler; private ErrorHandler errorHandler; public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException { return false; } public void setFeature(String name, boolean value) throws SAXNotRecognizedException, SAXNotSupportedException { } public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException { return null; } public void setProperty(String name, Object value) throws SAXNotRecognizedException, SAXNotSupportedException { } public void setEntityResolver(EntityResolver resolver) { } public EntityResolver getEntityResolver() { return null; } public void setDTDHandler(DTDHandler handler) { } public DTDHandler getDTDHandler() { return null; } public void setContentHandler(ContentHandler handler) { this.handler = new ContentHandlerWrapper(handler); } public ContentHandler getContentHandler() { return handler.getHandler(); } public void setErrorHandler(ErrorHandler handler) { this.errorHandler = handler; } public ErrorHandler getErrorHandler() { return errorHandler; } public void parse(InputSource input) throws IOException, SAXException { if (!(input instanceof TaskListInputSource)) { throw new SAXException("Can only parse writable input sources"); //$NON-NLS-1$ } TaskListInputSource taskListInputSource = (TaskListInputSource) input; handler.getHandler().startDocument(); writeTaskList(taskListInputSource.getTaskList(), taskListInputSource.getOrphans()); handler.getHandler().endDocument(); } private void writeTaskList(ITransferList taskList, Document orphanDocument) throws IOException, SAXException { AttributesWrapper attributes = new AttributesWrapper(); attributes.addAttribute(ATTRIBUTE_VERSION, VALUE_VERSION); handler.startElement(TaskListExternalizationConstants.NODE_TASK_LIST, attributes); writeTaskListElements(new SaxTaskWriter(handler), taskList.getAllTasks()); writeTaskListElements(new SaxCategoryWriter(handler), taskList.getCategories()); writeTaskListElements(new SaxQueryWriter(handler), taskList.getQueries()); writeOrphans(orphanDocument); handler.endElement(TaskListExternalizationConstants.NODE_TASK_LIST); } private <T extends IRepositoryElement> void writeTaskListElements(SaxTaskListElementWriter<T> writer, Collection<T> elements) throws SAXException { for (T element : elements) { writer.writeElement(element); } if (!writer.getErrors().isOK()) { StatusHandler.log(writer.getErrors()); } } private void writeOrphans(Document orphanDocument) throws SAXException { if (orphanDocument != null) { SaxOrphanWriter writer = new SaxOrphanWriter(handler); NodeList orphanNodes = orphanDocument.getChildNodes(); if (orphanNodes.getLength() == 1) { writer.writeOrphans(orphanNodes.item(0).getChildNodes()); } } } public void parse(String systemId) throws IOException, SAXException { throw new SAXException("Can only parse writable input sources"); //$NON-NLS-1$ } } }