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.httpquery.config;
13 import java.io.ByteArrayInputStream;
14 import java.io.ByteArrayOutputStream;
15 import java.io.FileReader;
16 import java.io.FileWriter;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.InputStreamReader;
20 import java.io.OutputStream;
21 import java.io.Reader;
22 import java.io.Writer;
24 import java.util.ArrayList;
25 import java.util.List;
27 import javax.xml.parsers.DocumentBuilder;
28 import javax.xml.parsers.DocumentBuilderFactory;
29 import javax.xml.parsers.ParserConfigurationException;
30 import javax.xml.transform.OutputKeys;
31 import javax.xml.transform.Result;
32 import javax.xml.transform.Source;
33 import javax.xml.transform.Transformer;
34 import javax.xml.transform.TransformerFactory;
35 import javax.xml.transform.dom.DOMSource;
36 import javax.xml.transform.stream.StreamResult;
38 import org.w3c.dom.Attr;
39 import org.w3c.dom.Document;
40 import org.w3c.dom.Element;
41 import org.w3c.dom.NamedNodeMap;
42 import org.w3c.dom.Node;
43 import org.w3c.dom.NodeList;
44 import org.xml.sax.InputSource;
45 import org.xml.sax.SAXException;
47 * A Memento is a class independent container for persistence
48 * info. It is a reflection of 3 storage requirements.
50 * 1) We need the ability to persist an object and restore it.
51 * 2) The class for an object may be absent. If so we would
52 * like to skip the object and keep reading.
53 * 3) The class for an object may change. If so the new class
54 * should be able to read the old persistence info.
56 * We could ask the objects to serialize themselves into an
57 * ObjectOutputStream, DataOutputStream, or Hashtable. However
58 * all of these approaches fail to meet the second requirement.
60 * Memento supports binary persistance with a version ID.
62 public final class XMLMemento implements IMemento {
63 private Document factory;
64 private Element element;
67 * Answer a memento for the document and element. For simplicity
68 * you should use createReadRoot and createWriteRoot to create the initial
69 * mementos on a document.
71 public XMLMemento(Document doc, Element el) {
79 public IMemento createChild(String type) {
80 Element child = factory.createElement(type);
81 element.appendChild(child);
82 return new XMLMemento(factory, child);
88 public IMemento createChild(String type, String id) {
89 Element child = factory.createElement(type);
90 child.setAttribute(TAG_ID, id);
91 element.appendChild(child);
92 return new XMLMemento(factory, child);
96 * Create a Document from a Reader and answer a root memento for reading
99 protected static XMLMemento createReadRoot(Reader reader) {
100 Document document = null;
102 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
103 DocumentBuilder parser = factory.newDocumentBuilder();
104 document = parser.parse(new InputSource(reader));
105 Node node = document.getFirstChild();
106 if (node instanceof Element)
107 return new XMLMemento(document, (Element) node);
108 } catch (ParserConfigurationException e) {
109 } catch (IOException e) {
110 } catch (SAXException e) {
114 } catch (Exception e) { }
120 * Answer a root memento for writing a document.
122 public static XMLMemento createWriteRoot(String type) {
125 document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
126 Element element = document.createElement(type);
127 document.appendChild(element);
128 return new XMLMemento(document, element);
129 } catch (ParserConfigurationException e) {
137 public IMemento getChild(String type) {
139 NodeList nodes = element.getChildNodes();
140 int size = nodes.getLength();
144 // Find the first node which is a child of this node.
145 for (int nX = 0; nX < size; nX ++) {
146 Node node = nodes.item(nX);
147 if (node instanceof Element) {
148 Element element2 = (Element)node;
149 if (element2.getNodeName().equals(type))
150 return new XMLMemento(factory, element2);
154 // A child was not found.
161 public IMemento [] getChildren(String type) {
163 NodeList nodes = element.getChildNodes();
164 int size = nodes.getLength();
166 return new IMemento[0];
168 // Extract each node with given fType.
169 ArrayList list = new ArrayList(size);
170 for (int nX = 0; nX < size; nX ++) {
171 Node node = nodes.item(nX);
172 if (node instanceof Element) {
173 Element element2 = (Element)node;
174 if (element2.getNodeName().equals(type))
179 // Create a memento for each node.
181 IMemento [] results = new IMemento[size];
182 for (int x = 0; x < size; x ++) {
183 results[x] = new XMLMemento(factory, (Element)list.get(x));
189 * Return the contents of this memento as a byte array.
193 public byte[] getContents() throws IOException {
194 ByteArrayOutputStream out = new ByteArrayOutputStream();
196 return out.toByteArray();
200 * Returns an input stream for writing to the disk with a local locale.
202 * @return java.io.InputStream
204 public InputStream getInputStream() throws IOException {
205 ByteArrayOutputStream out = new ByteArrayOutputStream();
207 return new ByteArrayInputStream(out.toByteArray());
213 public Float getFloat(String key) {
214 Attr attr = element.getAttributeNode(key);
217 String strValue = attr.getValue();
219 return new Float(strValue);
220 } catch (NumberFormatException e) {
228 public String getId() {
229 return element.getAttribute(TAG_ID);
235 public String getName() {
236 return element.getNodeName();
242 public Integer getInteger(String key) {
243 Attr attr = element.getAttributeNode(key);
246 String strValue = attr.getValue();
248 return new Integer(strValue);
249 } catch (NumberFormatException e) {
257 public String getString(String key) {
258 Attr attr = element.getAttributeNode(key);
261 return attr.getValue();
264 public List getNames() {
265 NamedNodeMap map = element.getAttributes();
266 int size = map.getLength();
267 List list = new ArrayList();
268 for (int i = 0; i < size; i++) {
269 Node node = map.item(i);
270 String name = node.getNodeName();
277 * Loads a memento from the given filename.
279 * @param in java.io.InputStream
280 * @return org.eclipse.ui.IMemento
281 * @exception java.io.IOException
283 public static IMemento loadMemento(InputStream in) {
284 return createReadRoot(new InputStreamReader(in));
288 * Loads a memento from the given filename.
290 * @param in java.io.InputStream
291 * @return org.eclipse.ui.IMemento
292 * @exception java.io.IOException
294 public static IMemento loadCorruptMemento(InputStream in) {
295 Document document = null;
297 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
298 DocumentBuilder parser = factory.newDocumentBuilder();
299 document = parser.parse(in);
300 Node node = document.getFirstChild();
301 if (node instanceof Element)
302 return new XMLMemento(document, (Element) node);
303 } catch (ParserConfigurationException e) {
304 } catch (IOException e) {
305 } catch (SAXException e) {
309 } catch (Exception e) { }
315 * Loads a memento from the given filename.
317 * @param filename java.lang.String
318 * @return org.eclipse.ui.IMemento
319 * @exception java.io.IOException
321 public static IMemento loadMemento(String filename) throws IOException {
322 return XMLMemento.createReadRoot(new FileReader(filename));
326 * Loads a memento from the given filename.
328 * @param url java.net.URL
329 * @return org.eclipse.ui.IMemento
330 * @exception java.io.IOException
332 public static IMemento loadMemento(URL url) throws IOException {
333 return XMLMemento.createReadRoot(new InputStreamReader(url.openStream()));
339 private void putElement(Element element2) {
340 NamedNodeMap nodeMap = element2.getAttributes();
341 int size = nodeMap.getLength();
342 for (int i = 0; i < size; i++){
343 Attr attr = (Attr)nodeMap.item(i);
344 putString(attr.getName(),attr.getValue());
347 NodeList nodes = element2.getChildNodes();
348 size = nodes.getLength();
349 for (int i = 0; i < size; i ++) {
350 Node node = nodes.item(i);
351 if (node instanceof Element) {
352 XMLMemento child = (XMLMemento)createChild(node.getNodeName());
353 child.putElement((Element)node);
361 public void putFloat(String key, float f) {
362 element.setAttribute(key, String.valueOf(f));
368 public void putInteger(String key, int n) {
369 element.setAttribute(key, String.valueOf(n));
375 public void putMemento(IMemento memento) {
376 XMLMemento xmlMemento = (XMLMemento) memento;
377 putElement(xmlMemento.element);
383 public void putString(String key, String value) {
386 element.setAttribute(key, value);
390 * Save this Memento to a Writer.
392 public void save(Writer writer) throws IOException {
393 Result result = new StreamResult(writer);
394 Source source = new DOMSource(factory);
396 Transformer transformer = TransformerFactory.newInstance().newTransformer();
397 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
398 transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
399 transformer.transform(source, result);
400 } catch (Exception e) {
401 throw (IOException) (new IOException().initCause(e));
406 * Save this Memento to a Writer.
408 public void save(OutputStream os) throws IOException {
409 Result result = new StreamResult(os);
410 Source source = new DOMSource(factory);
412 Transformer transformer = TransformerFactory.newInstance().newTransformer();
413 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
414 transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
415 transformer.transform(source, result);
416 } catch (Exception e) {
417 throw (IOException) (new IOException().initCause(e));
422 * Saves the memento to the given file.
424 * @param filename java.lang.String
425 * @exception java.io.IOException
427 public void saveToFile(String filename) throws IOException {
430 w = new FileWriter(filename);
432 } catch (IOException e) {
434 } catch (Exception e) {
435 throw new IOException(e.getLocalizedMessage());
440 } catch (Exception e) { }
445 public String saveToString() throws IOException {
446 ByteArrayOutputStream out = new ByteArrayOutputStream();
448 return out.toString("UTF-8");
452 * @see IMemento#getBoolean(String)
454 public Boolean getBoolean(String key) {
455 Attr attr = element.getAttributeNode(key);
458 String strValue = attr.getValue();
459 if ("true".equalsIgnoreCase(strValue))
460 return new Boolean(true);
462 return new Boolean(false);
466 * @see IMemento#putBoolean(String, boolean)
468 public void putBoolean(String key, boolean value) {
469 element.setAttribute(key, value ? "true" : "false");