/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Pref.java
*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.database.text;
import com.sun.electric.Main;
import com.sun.electric.database.id.LibId;
import com.sun.electric.tool.Client;
import com.sun.electric.tool.Job;
import com.sun.electric.tool.user.ActivityLogger;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeMap;
import java.util.prefs.BackingStoreException;
import java.util.prefs.InvalidPreferencesFormatException;
import java.util.prefs.Preferences;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.xml.sax.SAXParseException;
/**
* This class manages appearance options.
* There are two types of options: <I>appearance</I> and <I>meaning</I>.
* Appearance options affect the way that the design is presented to the user.
* Examples are grid dot spacing, layer stipple patterns, etc.
* Meaning options affect the way that a design is produced (for fabrication,
* simulation, and other outputs). Examples are CIF layer names, technology
* options, etc.)
* Meaning options are managed by Setting class now.
* <P>
* Some Prefs can be used in server Jobs, other are client only.
* Server Prefs are created by special factory methods during Electric initialization.
* They can't be created later.
* <P>
* All options are saved in a machine-specific way by the Java Preferences class.
* In addition, "meaning" options are stored in libraries. When the libraries
* are read back into Electric, the stored meaning options are checked against
* the current meaning options, the two are reconciled.
* <P>
* Where are these options stored? It varies with each operating system.
* <UL>
* <LI><B>Windows:</B>
* In the registry.
* Look in: HKEY_CURRENT_USER / Software / JavaSoft / Prefs / com / sun / electric.
* </LI>
* <LI><B>UNIX/Linux:</B>
* In your home directory.
* Look in: ~/.java/.userPrefs/com/sun/electric
* </LI>
* <LI><B>Macintosh System 10:</B>
* In your home directory, under Library/Preferences.
* Look at: ~/Library/Preferences/com.sun.electric.plist
* </LI>
* </UL>
*/
public class Pref {
public final static boolean FROM_THREAD_ENVIRONMENT = false;
private static boolean forbidPreferences;
public static class Group {
private final String relativePath;
private boolean lockCreation;
Preferences preferences;
private final TreeMap<String, Pref> prefs = new TreeMap<String, Pref>();
private Group(String relativePath) {
this.relativePath = relativePath;
}
public String relativePath() {
return relativePath;
}
public Collection<Pref> getPrefs() {
return Collections.unmodifiableCollection(prefs.values());
}
/**
* Prefs can be created only at initialization phase.
* This method forbids further cration of Prefs.
*/
public void lockCreation() {
lockCreation = true;
}
public void setCachedObjsFromPreferences() {
for (Pref pref : prefs.values()) {
pref.setCachedObjFromPreferences();
}
}
private void putValue(String key, Object value) {
if (preferences == null) {
preferences = getPrefRoot().node(relativePath);
}
putValue(preferences, key, value);
if (doFlushing) {
flushOptions(preferences);
} else {
queueForFlushing.add(preferences);
}
}
private void putValue(Preferences preferences, String key, Object value) {
if (value instanceof Boolean) {
preferences.putBoolean(key, ((Boolean) value).booleanValue());
} else if (value instanceof Integer) {
preferences.putInt(key, ((Integer) value).intValue());
} else if (value instanceof Long) {
preferences.putLong(key, ((Long) value).longValue());
} else if (value instanceof Double) {
preferences.putDouble(key, ((Double) value).doubleValue());
} else {
assert value instanceof String;
preferences.put(key, (String) value);
}
}
private Object getValue(String key, Object def) {
if (preferences == null) {
preferences = getPrefRoot().node(relativePath);
}
return getValueImpl(preferences, key, def);
}
private void remove(String key) {
if (preferences == null) {
preferences = getPrefRoot().node(relativePath);
}
remove(preferences, key);
if (doFlushing) {
flushOptions(preferences);
} else {
queueForFlushing.add(preferences);
}
}
private void remove(Preferences preferences, String key) {
preferences.remove(key);
}
}
public static Group groupForPackage(Class classFromPackage) {
String className = classFromPackage.getName();
String mainClassName = "com.sun.electric.";
if (!className.startsWith(mainClassName)) {
throw new IllegalArgumentException("Class is not in Electric tree");
}
className = className.substring(mainClassName.length());
int pkgEndIndex = className.lastIndexOf('.');
String packageName = className.substring(0, pkgEndIndex);
return groupForPackage(packageName.replace('.', '/'));
}
public static Group groupForPackage(String relativePath) {
synchronized (allGroups) {
for (Group group : allGroups) {
if (group.relativePath.equals(relativePath)) {
return group;
}
}
Group newGroup = new Group(relativePath);
allGroups.add(newGroup);
return newGroup;
}
}
private final String name;
private final Group group;
private final boolean serverAccessible;
private Object cachedObj;
private Object factoryObj;
private static final ArrayList<Group> allGroups = new ArrayList<Group>();
private static boolean doFlushing = true;
private static Set<Preferences> queueForFlushing;
private static boolean lockCreation;
private static final HashSet<Pref> reportedAccess = new HashSet<Pref>();
/**
* The constructor for the Pref.
* @param name the name of this Pref.
*/
protected Pref(Group group, String name, boolean serverAccessible, Object factoryObj) {
if (lockCreation && serverAccessible) {
throw new IllegalStateException("Pref " + group.relativePath() + "/" + name + " is created from improper place");
}
this.name = name;
this.group = group;
this.serverAccessible = serverAccessible;
this.factoryObj = factoryObj;
synchronized (group.prefs) {
assert !group.prefs.containsKey(name);
group.prefs.put(name, this);
}
// setCachedObjFromPreferences();
}
/**
* Currently Setting can be created only at initialization phase.
* This method forbids further cration of Settings.
*/
public static void lockCreation() {
lockCreation = true;
}
public static void forbidPreferences() {
forbidPreferences = true;
}
public static void setCachedObjsFromPreferences() {
synchronized (allGroups) {
for (Group group : allGroups) {
group.setCachedObjsFromPreferences();
}
}
}
public static void importPrefs(URL fileURL) {
// import preferences
try {
URLConnection urlCon = fileURL.openConnection();
InputStream inputStream = urlCon.getInputStream();
// reset all preferences to factory values
try {
clearPrefs(getPrefRoot());
} catch (BackingStoreException e) {
System.out.println("Error resetting Electric preferences");
e.printStackTrace();
}
// import preferences
Preferences.importPreferences(inputStream);
inputStream.close();
} catch (InvalidPreferencesFormatException e) {
String message = "Invalid preferences format";
if (e.getCause() instanceof SAXParseException) {
SAXParseException se = (SAXParseException) e.getCause();
message += " (line " + se.getLineNumber() + ")";
}
System.out.println(message + ": " + e.getMessage());
return;
} catch (IOException e) {
System.out.println("Error reading preferences file");
e.printStackTrace();
return;
}
}
private static void clearPrefs(Preferences topNode) throws BackingStoreException {
topNode.clear();
for (String child : topNode.childrenNames()) {
clearPrefs(topNode.node(child));
}
}
/**
* Method to export the preferences to an XML file. This function is public due to the regressions.
* @param fileName the file to write.
*/
public static void exportPrefs(String fileName) {
exportPrefs(fileName, getPrefRoot());
}
/**
* Method to export the preferences to an XML file. This function is public due to the regressions.
* @param fileName the file to write.
*/
public static void exportPrefs(String fileName, Preferences prefRoot) {
if (fileName == null) {
return;
}
// save preferences there
try {
// dump the preferences as a giant XML string (unformatted)
ByteArrayOutputStream bs = new ByteArrayOutputStream();
prefRoot.exportSubtree(bs);
String xmlDump = bs.toString();
// remove the DTD statement (causes trouble)
int sunPos = xmlDump.indexOf("java.sun.com");
String insertDTD = "";
if (sunPos >= 0) {
int openPos = xmlDump.lastIndexOf('<', sunPos);
int closePos = xmlDump.indexOf('>', sunPos);
if (openPos >= 0 && closePos >= 0) {
insertDTD = xmlDump.substring(openPos, closePos + 1);
xmlDump = xmlDump.substring(0, openPos) + xmlDump.substring(closePos + 1);
}
}
// reformat the XML
StreamSource source = new StreamSource(new StringReader(xmlDump));
TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute("indent-number", new Integer(2));
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
OutputStreamWriter outSW = (Client.isOSMac()) ? new OutputStreamWriter(bos) : new OutputStreamWriter(bos, "utf-8");
// OutputStreamWriter outSW = new OutputStreamWriter(bos, "UTF-8");
StreamResult result = new StreamResult(outSW);
transformer.transform(source, result);
// add the removed DTD line back into the XML
String xmlFormatted = bos.toString();
int closePos = xmlFormatted.indexOf('>');
if (closePos >= 0) {
xmlFormatted = xmlFormatted.substring(0, closePos + 1) + "\n" + insertDTD + xmlFormatted.substring(closePos + 1);
}
// save the XML to disk
PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));
printWriter.print(xmlFormatted);
printWriter.close();
} catch (Exception e) {
if (Job.getDebug()) {
e.printStackTrace();
}
System.out.println("Error exporting Preferences");
return;
}
System.out.println("Preferences saved to " + fileName);
}
/**
* Factory methods to create a boolean Pref objects.
* @param name the name of this Pref.
* @param group group of preferences to which a new Pref belongs
* @param factory the "factory" default value (if nothing is stored).
*/
public static Pref makeBooleanPref(String name, Group group, boolean factory) {
return new Pref(group, name, false, Boolean.valueOf(factory));
}
/**
* Factory methods to create an integer Pref objects.
* @param name the name of this Pref.
* @param group group of preferences to which a new Pref belongs
* @param factory the "factory" default value (if nothing is stored).
*/
public static Pref makeIntPref(String name, Group group, int factory) {
return new Pref(group, name, false, Integer.valueOf(factory));
}
/**
* Factory methods to create a long Pref objects.
* @param name the name of this Pref.
* @param group group of preferences to which a new Pref belongs
* @param factory the "factory" default value (if nothing is stored).
*/
public static Pref makeLongPref(String name, Group group, long factory) {
return new Pref(group, name, false, Long.valueOf(factory));
}
/**
* Factory methods to create a double Pref objects.
* @param name the name of this Pref.
* @param group group of preferences to which a new Pref belongs
* @param factory the "factory" default value (if nothing is stored).
*/
public static Pref makeDoublePref(String name, Group group, double factory) {
return new Pref(group, name, false, Double.valueOf(factory));
}
/**
* Factory methods to create a string Pref objects.
* @param name the name of this Pref.
* @param group group of preferences to which a new Pref belongs
* @param factory the "factory" default value (if nothing is stored).
*/
public static Pref makeStringPref(String name, Group group, String factory) {
if (factory == null) {
throw new NullPointerException();
}
return new Pref(group, name, false, factory);
}
/**
* Factory methods to create a boolean Pref objects.
* The Pref is accessible from server Jobs.
* @param name the name of this Pref.
* @param group group of preferences to which a new Pref belongs
* @param factory the "factory" default value (if nothing is stored).
*/
public static Pref makeBooleanServerPref(String name, Group group, boolean factory) {
return new Pref(group, name, true, Boolean.valueOf(factory));
}
/**
* Factory methods to create an integer Pref objects.
* The Pref is accessible from server Jobs.
* @param name the name of this Pref.
* @param group group of preferences to which a new Pref belongs
* @param factory the "factory" default value (if nothing is stored).
*/
public static Pref makeIntServerPref(String name, Group group, int factory) {
return new Pref(group, name, true, Integer.valueOf(factory));
}
/**
* Factory methods to create a string Pref objects.
* The Pref is accessible from server Jobs.
* @param name the name of this Pref.
* @param group group of preferences to which a new Pref belongs
* @param factory the "factory" default value (if nothing is stored).
*/
public static Pref makeStringServerPref(String name, Group group, String factory) {
if (factory == null) {
throw new NullPointerException();
}
return new Pref(group, name, true, factory);
}
/**
* Method to get the boolean value on this Pref object.
* The object must have been created as "boolean".
* @return the boolean value on this Pref object.
*/
public boolean getBoolean() {
return ((Boolean) getValue()).booleanValue();
}
/**
* Method to get the integer value on this Pref object.
* The object must have been created as "integer".
* @return the integer value on this Pref object.
*/
public int getInt() {
return ((Integer) getValue()).intValue();
}
/**
* Method to get the long value on this Pref object.
* The object must have been created as "long".
* @return the long value on this Pref object.
*/
public long getLong() {
return ((Long) getValue()).longValue();
}
/**
* Method to get the double value on this Pref object.
* The object must have been created as "double".
* @return the double value on this Pref object.
*/
public double getDouble() {
return ((Number) getValue()).doubleValue();
}
/**
* Method to get the string value on this Pref object.
* The object must have been created as "string".
* @return the string value on this Pref object.
*/
public String getString() {
return (String) getValue();
}
/**
* Method to get the boolean value on this Pref object.
* The object must have been created as "boolean".
* @param prefRoot root Preferences node
* @return the boolean value on this Pref object.
*/
public boolean getBoolean(Preferences prefRoot) {
return ((Boolean) getValue(prefRoot)).booleanValue();
}
/**
* Method to get the integer value on this Pref object.
* The object must have been created as "integer".
* @param prefRoot root Preferences node
* @return the integer value on this Pref object.
*/
public int getInt(Preferences prefRoot) {
return ((Integer) getValue(prefRoot)).intValue();
}
/**
* Method to get the long value on this Pref object.
* The object must have been created as "long".
* @param prefRoot root Preferences node
* @return the long value on this Pref object.
*/
public long getLong(Preferences prefRoot) {
return ((Long) getValue(prefRoot)).longValue();
}
/**
* Method to get the double value on this Pref object.
* The object must have been created as "double".
* @param prefRoot root Preferences node
* @return the double value on this Pref object.
*/
public double getDouble(Preferences prefRoot) {
return ((Double) getValue(prefRoot)).doubleValue();
}
/**
* Method to get the string value on this Pref object.
* The object must have been created as "string".
* @param prefRoot root Preferences node
* @return the string value on this Pref object.
*/
public String getString(Preferences prefRoot) {
return (String) getValue(prefRoot);
}
/**
* Method to get the factory-default value of this Pref object.
* @return the factory-default value of this Pref object.
*/
public Object getFactoryValue() {
return factoryObj;
}
/**
* Method to get the factory-default boolean value of this Pref object.
* @return the factory-default boolean value of this Pref object.
*/
public boolean getBooleanFactoryValue() {
return ((Boolean) factoryObj).booleanValue();
}
/**
* Method to get the factory-default integer value of this Pref object.
* @return the factory-default integer value of this Pref object.
*/
public int getIntFactoryValue() {
return ((Integer) factoryObj).intValue();
}
/**
* Method to get the factory-default long value of this Pref object.
* @return the factory-default long value of this Pref object.
*/
public long getLongFactoryValue() {
return ((Long) factoryObj).longValue();
}
/**
* Method to get the factory-default double value of this Pref object.
* @return the factory-default double value of this Pref object.
*/
public double getDoubleFactoryValue() {
return ((Double) factoryObj).doubleValue();
}
/**
* Method to get the factory-default String value of this Pref object.
* @return the factory-default String value of this Pref object.
*/
public String getStringFactoryValue() {
return (String) factoryObj;
}
/**
* Method to get the name of this Pref object.
* @return the name of this Pref object.
*/
public String getPrefName() {
return name;
}
/**
* Method to get the pref name of this Pref object.
* @return the name of this Setting object.
*/
public String getPrefPath() {
return group.relativePath() + "/" + name;
}
/**
* Method to get the value of this Pref object as an Object.
* The proper way to get the current value is to use one of the type-specific
* methods such as getInt(), getBoolean(), etc.
* @return the Object value of this Pref object.
*/
public Object getValue() {
if (!Job.isClientThread()) {
if (!serverAccessible && !reportedAccess.contains(this)) {
String msg = getPrefName() + " is accessed from " + Job.getRunningJob();
if (Job.getDebug()) {
ActivityLogger.logMessage(msg);
System.out.println(msg);
}
reportedAccess.add(this);
}
}
if (cachedObj == null) {
setCachedObjFromPreferences();
}
return cachedObj;
}
public Object getValue(Preferences prefRoot) {
return getValueImpl(prefRoot.node(group.relativePath), name, factoryObj);
}
private static Object getValueImpl(Preferences preferences, String key, Object def) {
Object value = def;
if (def instanceof Boolean) {
boolean defV = ((Boolean) def).booleanValue();
boolean v = preferences.getBoolean(key, defV);
if (v != defV) {
value = Boolean.valueOf(v);
}
} else if (def instanceof Integer) {
int defV = ((Integer) def).intValue();
int v = preferences.getInt(key, defV);
if (v != defV) {
value = Integer.valueOf(v);
}
} else if (def instanceof Long) {
long defV = ((Long) def).longValue();
long v = preferences.getLong(key, defV);
if (v != defV) {
value = Long.valueOf(v);
}
} else if (def instanceof Double) {
double defV = ((Double) def).doubleValue();
double v = preferences.getDouble(key, defV);
if (v != defV) {
value = Double.valueOf(v);
}
} else {
assert def instanceof String;
value = preferences.get(key, (String) def);
}
return value;
}
private void setValue(Object value) {
assert value.getClass() == factoryObj.getClass();
cachedObj = value.equals(factoryObj) ? factoryObj : value;
group.putValue(name, cachedObj);
}
private void setCachedObjFromPreferences() {
cachedObj = group.getValue(name, factoryObj);
}
/**
* Method to delay the saving of preferences to disk.
* Since individual saving is time-consuming, batches of preference
* changes are wrapped with this, and "resumePrefFlushing()".
*/
public static void delayPrefFlushing() {
doFlushing = false;
queueForFlushing = new HashSet<Preferences>();
}
/**
* Method to resume the saving of preferences to disk.
* Since individual saving is time-consuming, batches of preference
* changes are wrapped with this, and "resumePrefFlushing()".
* Besides resuming saving, this method also saves anything queued
* while saving was delayed.
*/
public static void resumePrefFlushing() {
doFlushing = true;
for (Preferences p : queueForFlushing) {
flushOptions(p);
}
flushAll();
}
/**
* Returns the root of Preferences subtree with Electric options.
* Currently this is "/com/sun/electric/" subtree.
* @return the root of Preferences subtree with Electric options.
*/
public static Preferences getPrefRoot() {
if (forbidPreferences) {
return getFactoryPrefRoot();
}
return Preferences.userNodeForPackage(Main.class);
}
/**
* Returns the root of Preferences subtree with Electric options for a specified LibId.
* @param libId specified LibId
* @return the root of Preferences subtree with Electric options for a spiceified LibId.
*/
public static Preferences getLibraryPreferences(LibId libId) {
return Pref.getPrefRoot().node("database/hierarchy/" + libId.libName);
}
/**
* Returns the root of dummy Preferences subtree with factory default Electric options.
* @return the root of Preferences subtree with factory default Electric options.
*/
public static Preferences getFactoryPrefRoot() {
return EmptyPreferencesFactory.factoryPrefRoot;
}
/**
* Method to immediately flush all Electric preferences to disk.
*/
public static void flushAll() {
flushOptions(getPrefRoot());
}
/**
* Method to set a new boolean value on this Pref object.
* @param v the new boolean value of this Pref object.
*/
public void setBoolean(boolean v) {
checkModify();
boolean cachedBool = getBoolean();
if (v != cachedBool) {
setValue(Boolean.valueOf(v));
}
}
/**
* Method to set a new integer value on this Pref object.
* @param v the new integer value of this Pref object.
*/
public void setInt(int v) {
checkModify();
int cachedInt = getInt();
if (v != cachedInt) {
setValue(Integer.valueOf(v));
}
}
/**
* Method to set a new long value on this Pref object.
* @param v the new long value of this Pref object.
*/
public void setLong(long v) {
checkModify();
long cachedLong = getLong();
if (v != cachedLong) {
setValue(Long.valueOf(v));
}
}
/**
* Method to set a new double value on this Pref object.
* @param v the new double value of this Pref object.
*/
public void setDouble(double v) {
checkModify();
double cachedDouble = getDouble();
if (v != cachedDouble) {
setValue(Double.valueOf(v));
}
}
/**
* Method to set a new string value on this Pref object.
* @param str the new string value of this Pref object.
*/
public void setString(String str) {
checkModify();
String cachedString = getString();
if (!str.equals(cachedString)) {
setValue(str);
}
}
/**
* Method to set a new boolean value on this Pref object.
* @param v the new boolean value of this Pref object.
*/
public void putBoolean(Preferences prefRoot, boolean removeDefaults, boolean v) {
Preferences prefs = prefRoot.node(group.relativePath);
if (removeDefaults && v == ((Boolean) factoryObj).booleanValue()) {
prefs.remove(name);
} else {
prefs.putBoolean(name, v);
}
}
/**
* Method to set a new integer value on this Pref object.
* @param v the new integer value of this Pref object.
*/
public void putInt(Preferences prefRoot, boolean removeDefaults, int v) {
Preferences prefs = prefRoot.node(group.relativePath);
if (removeDefaults && v == ((Integer) factoryObj).intValue()) {
prefs.remove(name);
} else {
prefs.putInt(name, v);
}
}
/**
* Method to set a new long value on this Pref object.
* @param v the new long value of this Pref object.
*/
public void putLong(Preferences prefRoot, boolean removeDefaults, long v) {
Preferences prefs = prefRoot.node(group.relativePath);
if (removeDefaults && v == ((Long) factoryObj).longValue()) {
prefs.remove(name);
} else {
prefs.putLong(name, v);
}
}
/**
* Method to set a new double value on this Pref object.
* @param v the new double value of this Pref object.
*/
public void putDouble(Preferences prefRoot, boolean removeDefaults, double v) {
Preferences prefs = prefRoot.node(group.relativePath);
if (removeDefaults && v == ((Double) factoryObj).doubleValue()) {
prefs.remove(name);
} else {
prefs.putDouble(name, v);
}
}
/**
* Method to set a new string value on this Pref object.
* @param str the new string value of this Pref object.
*/
public void putString(Preferences prefRoot, boolean removeDefaults, String str) {
Preferences prefs = prefRoot.node(group.relativePath);
if (removeDefaults && str.equals(factoryObj)) {
prefs.remove(name);
} else {
prefs.put(name, str);
}
}
/**
* Method to reset Pref value to factory default.
*/
public void factoryReset() {
if (!Job.isClientThread()) {
throw new IllegalStateException();
}
cachedObj = factoryObj;
group.remove(name);
}
private void checkModify() {
if (!Job.isClientThread()) {
if (!serverAccessible) {
String msg = getPrefName() + " is modified in " + Job.getRunningJob();
if (Job.getDebug()) {
ActivityLogger.logMessage(msg);
System.out.println(msg);
}
}
}
}
public static Collection<Group> getAllGroups() {
return Collections.unmodifiableCollection(allGroups);
}
// private static int numStrings;
// private static int lenStrings;
// private static int numValueStrings = 0;
// private static int lenValueStrings = 0;
//
// public static void printAllPrefs(PrintStream out, Environment environment, boolean all) {
// numValueStrings = lenValueStrings = 0;
// TreeMap<String,Pref> sortedPrefs = new TreeMap<String,Pref>();
// synchronized (allGroups) {
// for (Group group: allGroups) {
// for (Pref pref: group.prefs.values()) {
// if (!all && !pref.serverAccessible) continue;
// sortedPrefs.put(pref.group.relativePath() + "/" + pref.name, pref);
// }
// }
// }
// Preferences rootNode = getPrefRoot();
// numStrings = lenStrings = 0;
// try {
// gatherPrefs(out, 0, rootNode, null);
// } catch (BackingStoreException e) {
// e.printStackTrace();
// }
// out.println(lenStrings + " chars in " + numStrings + " strings");
// out.println(lenValueStrings + " chars in " + numValueStrings + " value strings");
// printAllSettings(out, environment);
// out.println("ELECTRIC USER PREFERENCES");
// int i = 0;
// for (Pref pref: sortedPrefs.values())
// out.println((i++) + pref.group.relativePath() + " " + pref.name + " " + pref.cachedObj);
// for (Technology tech: environment.techPool.values()) {
// i = 0;
// for (Pref.Group group: tech.getTechnologyAllPreferences()) {
// for (Pref pref: group.prefs.values()) {
// if (!all && !pref.serverAccessible) continue;
// out.println((i++) + pref.group.relativePath() + " " + tech + " " + pref.name + " " + pref.cachedObj);
// }
// }
// }
// }
//
// private static void gatherPrefs(PrintStream out, int level, Preferences topNode, List<String> ks) throws BackingStoreException {
// for (int i = 0; i < level; i++) out.print(" ");
// String[] keys = topNode.keys();
// for (int i = 0; i < keys.length; i++) {
// numStrings++;
// lenStrings += keys.length;
// String value = topNode.get(keys[i], null);
// numValueStrings++;
// lenValueStrings += value.length();
// }
// out.println(topNode.name() + " " + keys.length);
// if (topNode.absolutePath().equals("/com/sun/electric/database/hierarchy")) return;
// String[] children = topNode.childrenNames();
// for (int i = 0; i < children.length; i++) {
// String childName = children[i];
// numStrings++;
// lenStrings += children[i].length();
// Preferences childNode = topNode.node(childName);
// gatherPrefs(out, level + 1, childNode, ks);
// }
// }
//
// private static void printAllSettings(PrintStream out, Environment environment) {
// Map<Setting,Object> settings = environment.getSettings();
// TreeMap<String,Setting> sortedSettings = new TreeMap<String,Setting>();
// for (Setting setting: settings.keySet())
// sortedSettings.put(setting.getXmlPath(), setting);
// out.println("PROJECT PREFERENCES");
// int i = 0;
// for (Setting setting: sortedSettings.values())
// out.println((i++) + "\t" + setting.getXmlPath() + " " + settings.get(setting));
// }
/****************************** private methods ******************************/
/**
* Method to force all Preferences to be saved.
*/
private static void flushOptions(Preferences p) {
try {
p.flush();
} catch (Exception e) {
System.out.println("Failed to save preferences");
}
}
}