/*******************************************************************************
* Copyright (c) 2009 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
* Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.core.util.preferences;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.php.internal.core.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* XML preferences reader for reading XML structures from the preferences store.
* This class works in combination with IXMLPreferencesStorable.
*/
public class XMLPreferencesReader {
public static final char DELIMITER = (char) 5;
protected static final Pattern LT_PATTERN = Pattern.compile("<"); //$NON-NLS-1$
protected static final Pattern GT_PATTERN = Pattern.compile(">"); //$NON-NLS-1$
protected static final Pattern QUOT_PATTERN = Pattern.compile("""); //$NON-NLS-1$
protected static final Pattern APOS_PATTERN = Pattern.compile("'"); //$NON-NLS-1$
protected static final Pattern AMP_PATTERN = Pattern.compile("&"); //$NON-NLS-1$
public static final String STRING_DEFAULT = ""; //$NON-NLS-1$
public static String getUnEscaped(String s) {
s = LT_PATTERN.matcher(s).replaceAll("<"); //$NON-NLS-1$
s = GT_PATTERN.matcher(s).replaceAll(">"); //$NON-NLS-1$
s = QUOT_PATTERN.matcher(s).replaceAll("\""); //$NON-NLS-1$
s = APOS_PATTERN.matcher(s).replaceAll("'"); //$NON-NLS-1$
s = AMP_PATTERN.matcher(s).replaceAll("&"); //$NON-NLS-1$
return s;
}
/**
* Read XML nodes to values map
*
* @param nodeList
* @param skipEmptyNodes
* @return values map
*/
private static Map<String, Object> read(NodeList nodeList, boolean skipEmptyNodes) {
Map<String, Object> map = new HashMap<String, Object>(nodeList.getLength());
for (int i = 0; i < nodeList.getLength(); ++i) {
Node n = nodeList.item(i);
if (n.hasChildNodes()) {
if (n.getFirstChild().getNodeType() == Node.TEXT_NODE) {
map.put(n.getNodeName(), getUnEscaped(n.getFirstChild().getNodeValue()));
} else {
map.put(n.getNodeName(), read(n.getChildNodes(), skipEmptyNodes));
}
} else if (!skipEmptyNodes) {
map.put(n.getNodeName(), ""); //$NON-NLS-1$
}
}
return map;
}
/**
* Converts given XML string to values map
*
* @param str
* @param skipEmptyNodes
* @return values map
*/
protected static Map<String, Object> read(String str, boolean skipEmptyNodes) {
try {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.parse(new ByteArrayInputStream(str.getBytes()));
return read(doc.getChildNodes(), skipEmptyNodes);
} catch (Exception e) {
Logger.logException(e);
}
return null;
}
/**
* Reads a map of elements from the preferences by a given key.
*
* @param store
* @param prefsKey
* @param skipEmptyNodes
* @return a map of elements from the preferences by a given key
*/
public static List<Map<String, Object>> read(IEclipsePreferences store, String prefsKey, boolean skipEmptyNodes) {
String storedValue = store.get(prefsKey, null);
if (storedValue == null)
return new ArrayList<Map<String, Object>>();
return getMapsFromValue(storedValue, skipEmptyNodes);
}
/**
* Returns array of maps with stored values.
*
* @param storedValue
* @param skipEmptyNodes
* @return array of maps with stored values
*/
public static List<Map<String, Object>> getMapsFromValue(String storedValue, boolean skipEmptyNodes) {
List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
StringTokenizer st = new StringTokenizer(storedValue, new String(new char[] { DELIMITER }));
while (st.hasMoreTokens()) {
maps.add(read(st.nextToken(), skipEmptyNodes));
}
return maps;
}
}