diff -r 2cc4cc48034b editor.settings.storage/src/org/netbeans/modules/editor/settings/storage/preferences/PreferencesImpl.java --- a/editor.settings.storage/src/org/netbeans/modules/editor/settings/storage/preferences/PreferencesImpl.java Wed Aug 01 15:09:31 2012 +0200 +++ b/editor.settings.storage/src/org/netbeans/modules/editor/settings/storage/preferences/PreferencesImpl.java Fri Aug 03 15:03:32 2012 +0200 @@ -80,7 +80,7 @@ PreferencesImpl prefs = INSTANCES.get(mimePath); if (prefs == null) { - prefs = new PreferencesImpl(mimePath.getPath()); + prefs = new PreferencesImpl(null, mimePath.getPath(), ""); INSTANCES.put(mimePath, prefs); } @@ -91,45 +91,45 @@ // Preferences API // --------------------------------------------------------------------- - public @Override String absolutePath() { - return SLASH; - } - - public @Override String[] childrenNames() throws BackingStoreException { - return EMPTY_ARRAY; - } +// public @Override String absolutePath() { +// return SLASH; +// } +// +// public @Override String[] childrenNames() throws BackingStoreException { +// return EMPTY_ARRAY; +// } public @Override boolean isUserNode() { return true; } - public @Override String name() { - return EMPTY; - } +// public @Override String name() { +// return EMPTY; +// } - public @Override Preferences node(String path) { - if (path.length() == 0 || path.equals(SLASH)) { - return this; - } else { - throw new IllegalStateException("Editor Preferences does not support children nodes."); //NOI18N - } - } +// public @Override Preferences node(String path) { +// if (path.length() == 0 || path.equals(SLASH)) { +// return this; +// } else { +// throw new IllegalStateException("Editor Preferences does not support children nodes."); //NOI18N +// } +// } +// +// public @Override boolean nodeExists(String path) throws BackingStoreException { +// if (path.length() == 0 || path.equals(SLASH)) { +// return true; +// } else { +// return false; +// } +// } - public @Override boolean nodeExists(String path) throws BackingStoreException { - if (path.length() == 0 || path.equals(SLASH)) { - return true; - } else { - return false; - } - } +// public @Override Preferences parent() { +// return null; +// } - public @Override Preferences parent() { - return null; - } - - public @Override void removeNode() throws BackingStoreException { - throw new IllegalStateException("Can't remove the root!"); //NOI18N - } +// public @Override void removeNode() throws BackingStoreException { +// throw new IllegalStateException("Can't remove the root!"); //NOI18N +// } public @Override final void sync() throws BackingStoreException { flushTask.waitFinished(); @@ -257,28 +257,64 @@ // AbstractPreferences SPI // --------------------------------------------------------------------- - @Override - protected AbstractPreferences getChild(String nodeName) throws BackingStoreException { - throw new IllegalStateException("Should never be called."); //NOI18N +// @Override +// protected AbstractPreferences getChild(String nodeName) throws BackingStoreException { +// throw new IllegalStateException("Should never be called."); //NOI18N +// } +// +// @Override +// protected boolean isRemoved() { +// boolean superRemoved = super.isRemoved(); +// assert superRemoved == false : "super.isRemoved() should always == false"; //NOI18N +// return superRemoved; +// } +// + protected @Override void removeNodeSpi() throws BackingStoreException { + for (String key : keys()) { + remove(key); + } + PreferencesImpl parent = (PreferencesImpl) parent(); + String subnodes = parent.get(SUBNODES_KEY, null); + StringBuilder nue = new StringBuilder(); + String name = name(); + if (subnodes != null) { + for (String sn : subnodes.split(":")) { + if (!sn.equals(name)) { + if (nue.length() > 0) nue.append(":"); + nue.append(sn); + } + } + } + if (nue.length() == 0) + parent.remove(SUBNODES_KEY); + else + parent.put(SUBNODES_KEY, nue.toString()); + } - @Override - protected boolean isRemoved() { - boolean superRemoved = super.isRemoved(); - assert superRemoved == false : "super.isRemoved() should always == false"; //NOI18N - return superRemoved; - } - - protected @Override void removeNodeSpi() throws BackingStoreException { - throw new IllegalStateException("Should never be called."); //NOI18N - } - + private static final String SUBNODES_KEY = "-private-sub-nodes-key"; protected @Override String[] childrenNamesSpi() throws BackingStoreException { - throw new IllegalStateException("Should never be called."); //NOI18N + String subnodes = get(SUBNODES_KEY, null); + if (subnodes == null) return new String[0]; + return subnodes.split(":"); } protected @Override AbstractPreferences childSpi(String name) { - throw new IllegalStateException("Should never be called."); //NOI18N + String subnodes = get(SUBNODES_KEY, null); + boolean found = false; + if (subnodes != null) { + for (String sn : subnodes.split(":")) { + if (sn.equals(name)) { + found = true; + } + } + if (!found) { + put(SUBNODES_KEY, subnodes + ":" + name); + } + } else { + put(SUBNODES_KEY, name); + } + return new PreferencesImpl(this, mimePath, name); } protected @Override void putSpi(String key, String value) { @@ -353,7 +389,7 @@ // changing anything. if (local != null) { try { - storage.save(MimePath.parse(mimePath), null, false, local); + storage.save(MimePath.parse(mimePath), absolutePath().substring(1), false, local); } catch (IOException ioe) { LOG.log(Level.WARNING, "Can't save editor preferences for '" + mimePath + "'", ioe); //NOI18N } @@ -381,7 +417,7 @@ private static final Logger LOG = Logger.getLogger(PreferencesImpl.class.getName()); - private static final Map INSTANCES = + static final Map INSTANCES = new WeakHashMap(); private static final String SLASH = "/"; //NOI18N @@ -451,8 +487,8 @@ private Map local = null; private Preferences inherited = null; - private PreferencesImpl(String mimePath) { - super(null, EMPTY); + private PreferencesImpl(AbstractPreferences parent, String mimePath, String path) { + super(parent, path); this.mimePath = mimePath; this.storage = EditorSettingsStorage.get(PreferencesStorage.ID); @@ -462,7 +498,7 @@ private Map getLocal() { if (local == null) { try { - local = new HashMap(storage.load(MimePath.parse(mimePath), null, false)); + local = new HashMap(storage.load(MimePath.parse(mimePath), absolutePath().substring(1), false)); } catch (IOException ioe) { LOG.log(Level.WARNING, "Can't load editor preferences for '" + mimePath + "'", ioe); //NOI18N local = new HashMap(); diff -r 2cc4cc48034b editor.settings.storage/src/org/netbeans/modules/editor/settings/storage/preferences/PreferencesStorage.java --- a/editor.settings.storage/src/org/netbeans/modules/editor/settings/storage/preferences/PreferencesStorage.java Wed Aug 01 15:09:31 2012 +0200 +++ b/editor.settings.storage/src/org/netbeans/modules/editor/settings/storage/preferences/PreferencesStorage.java Fri Aug 03 15:03:32 2012 +0200 @@ -89,7 +89,7 @@ } public boolean isUsingProfiles() { - return false; + return true; } public String getMimeType() { diff -r 2cc4cc48034b editor.settings.storage/test/unit/src/org/netbeans/modules/editor/settings/storage/preferences/PreferencesImplTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/editor.settings.storage/test/unit/src/org/netbeans/modules/editor/settings/storage/preferences/PreferencesImplTest.java Fri Aug 03 15:03:32 2012 +0200 @@ -0,0 +1,85 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2012 Sun Microsystems, Inc. + */ +package org.netbeans.modules.editor.settings.storage.preferences; + +import java.util.Arrays; +import java.util.prefs.BackingStoreException; +import java.util.prefs.Preferences; +import org.netbeans.api.editor.mimelookup.MimePath; +import org.netbeans.junit.NbTestCase; + +/** + * + * @author lahvac + */ +public class PreferencesImplTest extends NbTestCase { + + public PreferencesImplTest(String name) { + super(name); + } + + public void testSubNodes() throws BackingStoreException, InterruptedException { + PreferencesImpl javaPrefs = PreferencesImpl.get(MimePath.get("text/x-java")); + Preferences subNode = javaPrefs.node("subnode"); + Preferences subSubNode = subNode.node("subsubnode"); + subSubNode.put("foo", "bar"); + subSubNode.flush(); + //XXX: should not be necessary to flush the subNode: + Thread.sleep(500); + PreferencesImpl.INSTANCES.clear(); + javaPrefs = PreferencesImpl.get(MimePath.get("text/x-java")); + assertEquals(Arrays.asList("subnode"), Arrays.asList(javaPrefs.childrenNames())); + subNode = javaPrefs.node("subnode"); + subSubNode = subNode.node("subsubnode"); + assertEquals("bar", subSubNode.get("foo", null)); + subSubNode.removeNode(); + assertEquals(Arrays.asList(), Arrays.asList(subNode.childrenNames())); + //XXX: should not be necessary to flush the subNode: + Thread.sleep(500); + PreferencesImpl.INSTANCES.clear(); + javaPrefs = PreferencesImpl.get(MimePath.get("text/x-java")); + subNode = javaPrefs.node("subnode"); + assertEquals(Arrays.asList(), Arrays.asList(subNode.childrenNames())); + subSubNode = subNode.node("subsubnode"); + assertEquals(null, subSubNode.get("foo", null)); + } +}