1 /**********************************************************************
2 * Copyright (c) 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - Initial API and implementation
10 **********************************************************************/
11 package net.sourceforge.phpdt.monitor.core.internal;
19 import javax.xml.parsers.*;
20 import javax.xml.transform.*;
21 import javax.xml.transform.dom.DOMSource;
22 import javax.xml.transform.stream.StreamResult;
24 * A Memento is a class independent container for persistence
25 * info. It is a reflection of 3 storage requirements.
27 * 1) We need the ability to persist an object and restore it.
28 * 2) The class for an object may be absent. If so we would
29 * like to skip the object and keep reading.
30 * 3) The class for an object may change. If so the new class
31 * should be able to read the old persistence info.
33 * We could ask the objects to serialize themselves into an
34 * ObjectOutputStream, DataOutputStream, or Hashtable. However
35 * all of these approaches fail to meet the second requirement.
37 * Memento supports binary persistance with a version ID.
39 public final class XMLMemento implements IMemento {
40 private Document factory;
41 private Element element;
44 * Answer a memento for the document and element. For simplicity
45 * you should use createReadRoot and createWriteRoot to create the initial
46 * mementos on a document.
48 public XMLMemento(Document doc, Element el) {
56 public IMemento createChild(String type) {
57 Element child = factory.createElement(type);
58 element.appendChild(child);
59 return new XMLMemento(factory, child);
65 public IMemento createChild(String type, String id) {
66 Element child = factory.createElement(type);
67 child.setAttribute(TAG_ID, id);
68 element.appendChild(child);
69 return new XMLMemento(factory, child);
73 * Create a Document from a Reader and answer a root memento for reading
76 protected static XMLMemento createReadRoot(Reader reader) {
77 Document document = null;
79 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
80 DocumentBuilder parser = factory.newDocumentBuilder();
81 document = parser.parse(new InputSource(reader));
82 Node node = document.getFirstChild();
83 if (node instanceof Element)
84 return new XMLMemento(document, (Element) node);
85 } catch (ParserConfigurationException e) {
86 } catch (IOException e) {
87 } catch (SAXException e) {
91 } catch (Exception e) { }
97 * Answer a root memento for writing a document.
99 public static XMLMemento createWriteRoot(String type) {
102 document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
103 Element element = document.createElement(type);
104 document.appendChild(element);
105 return new XMLMemento(document, element);
106 } catch (ParserConfigurationException e) {
114 public IMemento getChild(String type) {
116 NodeList nodes = element.getChildNodes();
117 int size = nodes.getLength();
121 // Find the first node which is a child of this node.
122 for (int nX = 0; nX < size; nX ++) {
123 Node node = nodes.item(nX);
124 if (node instanceof Element) {
125 Element element2 = (Element)node;
126 if (element2.getNodeName().equals(type))
127 return new XMLMemento(factory, element2);
131 // A child was not found.
138 public IMemento [] getChildren(String type) {
140 NodeList nodes = element.getChildNodes();
141 int size = nodes.getLength();
143 return new IMemento[0];
145 // Extract each node with given type.
146 ArrayList list = new ArrayList(size);
147 for (int nX = 0; nX < size; nX ++) {
148 Node node = nodes.item(nX);
149 if (node instanceof Element) {
150 Element element2 = (Element)node;
151 if (element2.getNodeName().equals(type))
156 // Create a memento for each node.
158 IMemento [] results = new IMemento[size];
159 for (int x = 0; x < size; x ++) {
160 results[x] = new XMLMemento(factory, (Element)list.get(x));
166 * Return the contents of this memento as a byte array.
170 public byte[] getContents() throws IOException {
171 ByteArrayOutputStream out = new ByteArrayOutputStream();
173 return out.toByteArray();
177 * Returns an input stream for writing to the disk with a local locale.
179 * @return java.io.InputStream
181 public InputStream getInputStream() throws IOException {
182 ByteArrayOutputStream out = new ByteArrayOutputStream();
184 return new ByteArrayInputStream(out.toByteArray());
190 public Float getFloat(String key) {
191 Attr attr = element.getAttributeNode(key);
194 String strValue = attr.getValue();
196 return new Float(strValue);
197 } catch (NumberFormatException e) {
205 public String getId() {
206 return element.getAttribute(TAG_ID);
212 public String getName() {
213 return element.getNodeName();
219 public Integer getInteger(String key) {
220 Attr attr = element.getAttributeNode(key);
223 String strValue = attr.getValue();
225 return new Integer(strValue);
226 } catch (NumberFormatException e) {
234 public String getString(String key) {
235 Attr attr = element.getAttributeNode(key);
238 return attr.getValue();
241 public List getNames() {
242 NamedNodeMap map = element.getAttributes();
243 int size = map.getLength();
244 List list = new ArrayList();
245 for (int i = 0; i < size; i++) {
246 Node node = map.item(i);
247 String name = node.getNodeName();
254 * Loads a memento from the given filename.
256 * @param in java.io.InputStream
257 * @return org.eclipse.ui.IMemento
258 * @exception java.io.IOException
260 public static IMemento loadMemento(InputStream in) {
261 return createReadRoot(new InputStreamReader(in));
265 * Loads a memento from the given filename.
267 * @param in java.io.InputStream
268 * @return org.eclipse.ui.IMemento
269 * @exception java.io.IOException
271 public static IMemento loadCorruptMemento(InputStream in) {
272 Document document = null;
274 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
275 DocumentBuilder parser = factory.newDocumentBuilder();
276 document = parser.parse(in);
277 Node node = document.getFirstChild();
278 if (node instanceof Element)
279 return new XMLMemento(document, (Element) node);
280 } catch (ParserConfigurationException e) {
281 } catch (IOException e) {
282 } catch (SAXException e) {
286 } catch (Exception e) { }
292 * Loads a memento from the given filename.
294 * @param filename java.lang.String
295 * @return org.eclipse.ui.IMemento
296 * @exception java.io.IOException
298 public static IMemento loadMemento(String filename) throws IOException {
299 return XMLMemento.createReadRoot(new FileReader(filename));
303 * Loads a memento from the given filename.
305 * @param url java.net.URL
306 * @return org.eclipse.ui.IMemento
307 * @exception java.io.IOException
309 public static IMemento loadMemento(URL url) throws IOException {
310 return XMLMemento.createReadRoot(new InputStreamReader(url.openStream()));
316 private void putElement(Element element2) {
317 NamedNodeMap nodeMap = element2.getAttributes();
318 int size = nodeMap.getLength();
319 for (int i = 0; i < size; i++){
320 Attr attr = (Attr)nodeMap.item(i);
321 putString(attr.getName(),attr.getValue());
324 NodeList nodes = element2.getChildNodes();
325 size = nodes.getLength();
326 for (int i = 0; i < size; i ++) {
327 Node node = nodes.item(i);
328 if (node instanceof Element) {
329 XMLMemento child = (XMLMemento)createChild(node.getNodeName());
330 child.putElement((Element)node);
338 public void putFloat(String key, float f) {
339 element.setAttribute(key, String.valueOf(f));
345 public void putInteger(String key, int n) {
346 element.setAttribute(key, String.valueOf(n));
352 public void putMemento(IMemento memento) {
353 XMLMemento xmlMemento = (XMLMemento) memento;
354 putElement(xmlMemento.element);
360 public void putString(String key, String value) {
363 element.setAttribute(key, value);
367 * Save this Memento to a Writer.
369 public void save(Writer writer) throws IOException {
370 Result result = new StreamResult(writer);
371 Source source = new DOMSource(factory);
373 Transformer transformer = TransformerFactory.newInstance().newTransformer();
374 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
375 transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
376 transformer.transform(source, result);
377 } catch (Exception e) {
378 throw (IOException) (new IOException().initCause(e));
383 * Save this Memento to a Writer.
385 public void save(OutputStream os) throws IOException {
386 Result result = new StreamResult(os);
387 Source source = new DOMSource(factory);
389 Transformer transformer = TransformerFactory.newInstance().newTransformer();
390 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
391 transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
392 transformer.transform(source, result);
393 } catch (Exception e) {
394 throw (IOException) (new IOException().initCause(e));
399 * Saves the memento to the given file.
401 * @param filename java.lang.String
402 * @exception java.io.IOException
404 public void saveToFile(String filename) throws IOException {
407 w = new FileWriter(filename);
409 } catch (IOException e) {
411 } catch (Exception e) {
412 throw new IOException(e.getLocalizedMessage());
417 } catch (Exception e) { }
422 public String saveToString() throws IOException {
423 ByteArrayOutputStream out = new ByteArrayOutputStream();
425 return out.toString("UTF-8");
429 * @see IMemento#getBoolean(String)
431 public Boolean getBoolean(String key) {
432 Attr attr = element.getAttributeNode(key);
435 String strValue = attr.getValue();
436 if ("true".equalsIgnoreCase(strValue))
437 return new Boolean(true);
439 return new Boolean(false);
443 * @see IMemento#putBoolean(String, boolean)
445 public void putBoolean(String key, boolean value) {
446 element.setAttribute(key, value ? "true" : "false");