diff -r 2728bff12ca2 core.windows/nbproject/project.xml --- a/core.windows/nbproject/project.xml Wed Sep 16 10:04:32 2009 +0200 +++ b/core.windows/nbproject/project.xml Wed Sep 16 13:46:53 2009 +0200 @@ -215,6 +215,11 @@ + + org.openide.windows + + + diff -r 2728bff12ca2 core.windows/src/org/netbeans/core/windows/RegistryImpl.java --- a/core.windows/src/org/netbeans/core/windows/RegistryImpl.java Wed Sep 16 10:04:32 2009 +0200 +++ b/core.windows/src/org/netbeans/core/windows/RegistryImpl.java Wed Sep 16 13:46:53 2009 +0200 @@ -41,6 +41,8 @@ package org.netbeans.core.windows; +import java.util.Collection; +import java.util.Iterator; import org.openide.nodes.Node; import org.openide.util.WeakSet; import org.openide.windows.TopComponent; @@ -90,7 +92,7 @@ * @return immutable set of {@link TopComponent}s */ public synchronized Set getOpened() { - return java.util.Collections.unmodifiableSet(openSet); + return new SyncSet(); } /** Get the currently selected element. @@ -333,5 +335,72 @@ private static void debugLog(String message) { Debug.log(RegistryImpl.class, message); } - + + private final class SyncSet implements Set { + public int size() { + synchronized (RegistryImpl.this) { + return openSet.size(); + } + } + + public boolean isEmpty() { + synchronized (RegistryImpl.this) { + return openSet.isEmpty(); + } + } + + public boolean contains(Object o) { + synchronized (RegistryImpl.this) { + return openSet.contains(o); + } + } + + public Iterator iterator() { + synchronized (RegistryImpl.this) { + return new HashSet(openSet).iterator(); + } + } + + public Object[] toArray() { + synchronized (RegistryImpl.this) { + return openSet.toArray(); + } + } + + public T[] toArray(T[] a) { + synchronized (RegistryImpl.this) { + return openSet.toArray(a); + } + } + + public boolean containsAll(Collection c) { + synchronized (RegistryImpl.this) { + return openSet.containsAll(c); + } + } + + public boolean add(TopComponent e) { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public void clear() { + throw new UnsupportedOperationException(); + } + } } diff -r 2728bff12ca2 core.windows/test/unit/src/org/netbeans/core/windows/TopComponentRegistryImplTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core.windows/test/unit/src/org/netbeans/core/windows/TopComponentRegistryImplTest.java Wed Sep 16 13:46:53 2009 +0200 @@ -0,0 +1,55 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 2009 Sun Microsystems, Inc. + */ + +package org.netbeans.core.windows; + +import org.openide.windows.TopComponentRegistryTest; + +/** Checks that the same behaviour of the registry is kept in the + * default implementation as well as in the real one. + * + * @author Jaroslav Tulach + */ +public class TopComponentRegistryImplTest extends TopComponentRegistryTest { + + public TopComponentRegistryImplTest(String name) { + super(name); + } + +} diff -r 2728bff12ca2 openide.windows/src/org/openide/windows/DummyWindowManager.java --- a/openide.windows/src/org/openide/windows/DummyWindowManager.java Wed Sep 16 10:04:32 2009 +0200 +++ b/openide.windows/src/org/openide/windows/DummyWindowManager.java Wed Sep 16 13:46:53 2009 +0200 @@ -53,6 +53,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -635,7 +636,18 @@ private PropertyChangeSupport pcs; public R() { - opened = new HashSet(); + opened = new HashSet() { + @Override + public Iterator iterator() { + HashSet copy = new HashSet(); + Iterator it = super.iterator(); + while (it.hasNext()) { + TopComponent topComponent = it.next(); + copy.add(topComponent); + } + return copy.iterator(); + } + }; nodes = new Node[0]; } @@ -676,7 +688,7 @@ } public synchronized Set getOpened() { - return new HashSet(opened); + return Collections.unmodifiableSet(opened); } synchronized void setActive(TopComponent tc) { diff -r 2728bff12ca2 openide.windows/test/unit/src/org/openide/windows/TopComponentRegistryTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.windows/test/unit/src/org/openide/windows/TopComponentRegistryTest.java Wed Sep 16 13:46:53 2009 +0200 @@ -0,0 +1,80 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 2009 Sun Microsystems, Inc. + */ + +package org.openide.windows; + +import java.util.Set; +import org.netbeans.junit.NbTestCase; + +public class TopComponentRegistryTest extends NbTestCase { + public TopComponentRegistryTest(String name) { + super(name); + } + + @Override + protected boolean runInEQ() { + return true; + } + + public void testGetOpenedIsSafeToIterate() { + TopComponent tc1 = new TopComponent(); + TopComponent tc2 = new TopComponent(); + TopComponent tc3 = new TopComponent(); + + Set all = TopComponent.getRegistry().getOpened(); + + tc1.open(); + tc2.open(); + tc3.open(); + + assertEquals("Contains 3 elements: " + all, 3, all.size()); + + assertTrue("tc1 in set: ", all.contains(tc1)); + assertTrue("tc2 in set: ", all.contains(tc2)); + assertTrue("tc3 in set: ", all.contains(tc3)); + + int cnt = 3; + for (TopComponent c : all) { + assertTrue("Can be closed", c.close()); + assertEquals("Now there are ", --cnt, all.size()); + } + + assertTrue("All components are closed", all.isEmpty()); + } +}