blob: 6534f88cf0eca40b378de3e2c60af8104f266213 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* Jens Lukowski/Innoopract - initial renaming/restructuring
*
*******************************************************************************/
package org.eclipse.wst.sse.ui.internal.provisional.preferences;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.wst.sse.core.internal.preferences.PreferenceChangeListener;
import org.eclipse.wst.sse.ui.internal.Logger;
import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* @deprecated no longer need a special PreferenceManager for our component.
* All preferences should be accessible using the base preference
* manager.
*/
public abstract class PreferenceManager {
class EmptyNodeList implements NodeList {
protected EmptyNodeList() {
super();
}
public int getLength() {
return 0;
}
public Node item(int param1) {
return null;
}
}
/**
* The PreferenceRuntimeException is often thrown by methods when a
* service we use throws a checked exception, but we want to convert and
* treat as a runtime exception.
*/
class PreferenceRuntimeException extends RuntimeException {
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = 1L;
private Throwable originalException;
public PreferenceRuntimeException() {
super();
}
/**
* This form of the constructor is used to wrapper another exception.
*/
public PreferenceRuntimeException(Throwable t) {
this();
originalException = t;
}
public String getMessage() {
String result = super.getMessage();
if ((result != null) && (!result.endsWith("."))) //$NON-NLS-1$
result = result + "."; //$NON-NLS-1$
if (originalException != null) {
String embeddedMessage = originalException.getMessage();
embeddedMessage = originalException.getClass().getName() + ": " + originalException.getMessage(); //$NON-NLS-1$
// not all exceptions have messages (e.g. many
// NullPointerException)
String originalError = SSEUIMessages.PreferenceManager_0; //$NON-NLS-1$
if (result == null)
result = ""; //$NON-NLS-1$
if (embeddedMessage != null)
result = result + " " + originalError + " " + embeddedMessage; //$NON-NLS-2$//$NON-NLS-1$
else
result = result + " " + originalError + " " + originalException.toString(); //$NON-NLS-2$//$NON-NLS-1$
}
return result;
}
public Throwable getOriginalException() {
return originalException;
}
public String toString() {
// we don't put super.toString or getClass to "hide" that it was a
// SourceEditing exception (otherwise, focus goes on that,
// instead of original exception.
String message = getMessage();
// message should never be null ... but just in case
return (message != null) ? message : super.toString();
}
}
protected Document document = null;
protected String fileName = null;
private List preferenceChangeListeners = new ArrayList(1);
protected Document _getNewDocumentDOM2() {
Document result = null;
// settings
DocumentBuilder builder = getDocumentBuilder();
result = builder.newDocument();
Element settings = result.createElement(getRootElementName());
result.appendChild(settings);
return result;
}
protected Document _getParsedDocumentDOM2(String filename) {
Document result = null;
DocumentBuilder builder = getDocumentBuilder();
try {
Reader inputReader = new FileReader(getFilename());
InputSource inputSource = new InputSource(inputReader);
result = builder.parse(inputSource);
}
catch (FileNotFoundException e) {
// file not found is "ok" ... it'll be created if we return null
result = null;
}
catch (IOException e) {
result = null;
}
catch (SAXException e) {
result = null;
}
return result;
}
public void addPreferenceChangeListener(PreferenceChangeListener l) {
if (!preferenceChangeListeners.contains(l))
preferenceChangeListeners.add(l);
}
/**
* Returns a new document containing the defaults for this manager. This
* SHOULD NOT overwrite the actual document stored within this manager,
* and while a root element MAY BE created by the DOM implementation, it
* is recommended that subclasses NOT RELY upon it being there.
*
* @return org.w3c.dom.Document
*/
public Document createDefaultPreferences() {
Document txobj = null;
txobj = _getNewDocumentDOM2();
return txobj;
}
protected void firePreferenceChangeListeners() {
if (preferenceChangeListeners != null)
for (int i = 0; i < preferenceChangeListeners.size(); ++i)
((PreferenceChangeListener) preferenceChangeListeners.get(i)).preferencesChanged();
}
/**
*
* @return Document
*/
public Document getDocument() {
if (document == null)
load();
return document;
}
private DocumentBuilder getDocumentBuilder() {
DocumentBuilder result = null;
try {
result = DocumentBuilderFactory.newInstance().newDocumentBuilder();
}
catch (ParserConfigurationException e) {
Logger.logException(e);
}
return result;
}
/*************************************************************************
* Takes a single string of the form "a/b/c" and ensures that that
* structure exists below the head element, down through 'c', and returns
* a <em>single</em> element 'c'. For multiple elements (such as
* multiple &lt;macro&gt; elements contained within a single
* &lt;macros&gt; element, full DOM access is required for searching and
* child element manipulation.
************************************************************************/
public Element getElement(String name) {
if (document == null)
load();
if (document != null)
return (Element) getNode(getRootElement(), name);
else
return null;
}
protected abstract String getFilename();
protected Node getNamedChild(Node parent, String childName) {
if (parent == null) {
return null;
}
NodeList childList = parent.getChildNodes();
for (int i = 0; i < childList.getLength(); i++) {
if (childList.item(i).getNodeName().equals(childName))
return childList.item(i);
}
return null;
}
/*************************************************************************
* Takes a single string of the form "a/b/c" and ensures that that
* structure exists below the head element, down through 'c', and returns
* the element 'c'.
************************************************************************/
public Node getNode(Node node, String name) {
StringTokenizer tokenizer = new StringTokenizer(name, "/"); //$NON-NLS-1$
String token = null;
while (tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken();
if (getNamedChild(node, token) == null) {
Document localDocument = node.getOwnerDocument();
node.appendChild(localDocument.createElement(token));
}
node = getNamedChild(node, token);
}
return node;
}
protected Document getParsedDocument(String filename) {
Document result = null;
// file name is almost never null,
// but can be if preferences are being ran
// outside of a workbench application
if (filename != null) {
File existenceTester = new File(filename);
if (!existenceTester.exists())
result = null;
else
result = _getParsedDocumentDOM2(filename);
}
return result;
}
/**
* Returns the root element of the current document
*
* @return org.w3c.dom.Element
*/
public Node getRootElement() {
return getRootElement(getDocument());
}
/**
* Returns the root element of the current document
*
* @return org.w3c.dom.Element
*/
public Node getRootElement(Document doc) {
if (doc == null)
return null;
Node rootElement = doc.getFirstChild();
while (rootElement != null && rootElement.getNodeType() != Node.ELEMENT_NODE && !rootElement.getNodeName().equals(getRootElementName())) {
rootElement = rootElement.getNextSibling();
}
return rootElement;
}
/**
* The intended name for the root Element of the Document; what is also
* listed within the DOCTYPE declaration.
*
* @return String
*/
public String getRootElementName() {
return "settings"; //$NON-NLS-1$
}
public void load() {
document = getParsedDocument(getFilename());
if (document == null) {
document = createDefaultPreferences();
}
}
public void removePreferenceChangeListener(PreferenceChangeListener l) {
preferenceChangeListeners.remove(l);
}
public void save() {
if (document == null) {
document = createDefaultPreferences();
}
try {
// pa_TODO is this still going to be done like this?
FileWriter output = new FileWriter(getFilename());
saveDocument(document, output);
output.flush();
output.close();
}
catch (IOException e) {
Logger.logException("Program Error: PreferenceManager::save. Exception saving preferences ", e); //$NON-NLS-1$
throw new PreferenceRuntimeException(e);
}
firePreferenceChangeListeners();
}
public void saveDocument(Document document, Writer writer) throws IOException {
serialize(document, writer);
}
private void serialize(Document sourceDocument, Writer writer) throws IOException {
Source domSource = new DOMSource(sourceDocument);
try {
Transformer serializer = TransformerFactory.newInstance().newTransformer();
try {
serializer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); //$NON-NLS-1$ //$NON-NLS-2$
}
catch (IllegalArgumentException e) {
// unsupported properties
}
serializer.transform(domSource, new StreamResult(writer));
}
catch (TransformerConfigurationException e) {
throw new IOException(e.getMessage());
}
catch (TransformerFactoryConfigurationError e) {
throw new IOException(e.getMessage());
}
catch (TransformerException e) {
throw new IOException(e.getMessage());
}
}
}