#179668: JDK 6 cleanup, modules N-Z.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/openide.util/src/org/openide/util/WeakSet.java Wed Jan 20 17:59:42 2010 -0500
1.3 @@ -0,0 +1,579 @@
1.4 +/*
1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
1.6 + *
1.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
1.8 + *
1.9 + * The contents of this file are subject to the terms of either the GNU
1.10 + * General Public License Version 2 only ("GPL") or the Common
1.11 + * Development and Distribution License("CDDL") (collectively, the
1.12 + * "License"). You may not use this file except in compliance with the
1.13 + * License. You can obtain a copy of the License at
1.14 + * http://www.netbeans.org/cddl-gplv2.html
1.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
1.16 + * specific language governing permissions and limitations under the
1.17 + * License. When distributing the software, include this License Header
1.18 + * Notice in each file and include the License file at
1.19 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
1.20 + * particular file as subject to the "Classpath" exception as provided
1.21 + * by Sun in the GPL Version 2 section of the License file that
1.22 + * accompanied this code. If applicable, add the following below the
1.23 + * License Header, with the fields enclosed by brackets [] replaced by
1.24 + * your own identifying information:
1.25 + * "Portions Copyrighted [year] [name of copyright owner]"
1.26 + *
1.27 + * Contributor(s):
1.28 + *
1.29 + * The Original Software is NetBeans. The Initial Developer of the Original
1.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
1.31 + * Microsystems, Inc. All Rights Reserved.
1.32 + *
1.33 + * If you wish your version of this file to be governed by only the CDDL
1.34 + * or only the GPL Version 2, indicate your decision by adding
1.35 + * "[Contributor] elects to include this software in this distribution
1.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
1.37 + * single choice of license, a recipient has the option to distribute
1.38 + * your version of this file under either the CDDL, the GPL Version 2 or
1.39 + * to extend the choice of license to its licensees as provided above.
1.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
1.41 + * Version 2 license, then the option applies only if the new code is
1.42 + * made subject to such option by the copyright holder.
1.43 + */
1.44 +
1.45 +package org.openide.util;
1.46 +
1.47 +import java.io.IOException;
1.48 +import java.io.ObjectInputStream;
1.49 +import java.io.ObjectOutputStream;
1.50 +import java.io.Serializable;
1.51 +import java.lang.ref.ReferenceQueue;
1.52 +import java.lang.ref.WeakReference;
1.53 +import java.util.AbstractSet;
1.54 +import java.util.ArrayList;
1.55 +import java.util.Collection;
1.56 +import java.util.ConcurrentModificationException;
1.57 +import java.util.Iterator;
1.58 +import java.util.logging.Level;
1.59 +import java.util.logging.Logger;
1.60 +
1.61 +/** Set which holds its members by using of WeakReferences.
1.62 +* MT level: unsafe.
1.63 + * <p><strong>Note:</strong> you can instead use
1.64 + * <pre>
1.65 + * Set<T> s = Collections.newSetFromMap(new WeakHashMap<T, Boolean>());
1.66 + * </pre>
1.67 +*
1.68 +* @author Ales Novak
1.69 +*/
1.70 +public class WeakSet<E> extends AbstractSet<E> implements Cloneable, Serializable {
1.71 + static final long serialVersionUID = 3062376055928236721L;
1.72 +
1.73 + /** load factor */
1.74 + private float loadFactor;
1.75 +
1.76 + /** Number of items. */
1.77 + private int size;
1.78 +
1.79 + /** Modification count */
1.80 + private long modcount;
1.81 +
1.82 + /** Reference queue of collected weak refs */
1.83 + private transient ReferenceQueue<E> refq;
1.84 +
1.85 + /** Count of <tt>null</tt> in this set */
1.86 + long nullCount;
1.87 +
1.88 + /** An array of Entries */
1.89 + private transient Entry<E>[] entries;
1.90 + transient Entry<E> iterChain;
1.91 +
1.92 + /** Constructs a new set. */
1.93 + public WeakSet() {
1.94 + this(11, 0.75f);
1.95 + }
1.96 +
1.97 + /** Constructs a new set containing the elements in the specified collection.
1.98 + * @param c a collection to add
1.99 + */
1.100 + public WeakSet(Collection<? extends E> c) {
1.101 + this();
1.102 + addAll(c);
1.103 + }
1.104 +
1.105 + /** Constructs a new, empty set;
1.106 + * @param initialCapacity initial capacity
1.107 + */
1.108 + public WeakSet(int initialCapacity) {
1.109 + this(initialCapacity, 0.75f);
1.110 + }
1.111 +
1.112 + /** Constructs a new, empty set;
1.113 + *
1.114 + * @param initialCapacity initial capacity
1.115 + * @param loadFactor load factor
1.116 + */
1.117 + public WeakSet(int initialCapacity, float loadFactor) {
1.118 + if ((initialCapacity <= 0) || (loadFactor <= 0)) {
1.119 + throw new IllegalArgumentException();
1.120 + }
1.121 +
1.122 + size = 0;
1.123 + modcount = 0;
1.124 + this.loadFactor = loadFactor;
1.125 + nullCount = 0;
1.126 + refq = new ReferenceQueue<E>();
1.127 + entries = Entry.createArray(initialCapacity);
1.128 + iterChain = null;
1.129 + }
1.130 +
1.131 + /**
1.132 + * logs iterator chain (for debugging)
1.133 + * @param msg
1.134 + */
1.135 + void logIterChain(String msg) {
1.136 + Logger log = Logger.getLogger(WeakSet.class.getName());
1.137 + log.log(Level.FINE, msg);
1.138 + if (iterChain == null) {
1.139 + log.log(Level.FINE, "Empty");
1.140 + return;
1.141 + }
1.142 + StringBuilder str = new StringBuilder();
1.143 + Entry<E> it = iterChain;
1.144 + str.append(size + ": ");
1.145 + while (it != null) {
1.146 + str.append(it.get() + "(" + it.hashcode + ")" + "->");
1.147 + it = it.iterChainNext;
1.148 + }
1.149 + log.log(Level.FINE, str.toString());
1.150 + }
1.151 +
1.152 + /** Adds the specified element to this set if it is not already present.
1.153 + *
1.154 + * @param o an Object to add
1.155 + */
1.156 + public boolean add(E o) {
1.157 + if (o == null) {
1.158 + size++;
1.159 + nullCount++;
1.160 + modcount++;
1.161 +
1.162 + return true;
1.163 + }
1.164 +
1.165 + Entry e = object2Entry(o);
1.166 +
1.167 + if (e != null) {
1.168 + return false;
1.169 + }
1.170 +
1.171 + modcount++;
1.172 + size++;
1.173 +
1.174 + int hash = hashIt(o);
1.175 + Entry<E> next = entries[hash];
1.176 + iterChain = entries[hash] = new Entry<E>(this, o, refq, next, iterChain);
1.177 + rehash();
1.178 +
1.179 + return true;
1.180 + }
1.181 +
1.182 + /** Removes all of the elements from this set. */
1.183 + public void clear() {
1.184 + for (int i = 0; i < entries.length; i++) {
1.185 + entries[i] = null;
1.186 + }
1.187 +
1.188 + nullCount = 0;
1.189 + modcount++;
1.190 + size = 0;
1.191 + iterChain = null;
1.192 + }
1.193 +
1.194 + /** Returns a shallow copy of this WeakSet instance: the elements themselves are not cloned. */
1.195 + public Object clone() {
1.196 + WeakSet<E> nws = new WeakSet<E>(1, loadFactor);
1.197 + nws.size = size;
1.198 + nws.nullCount = nullCount;
1.199 +
1.200 + Entry<E>[] cloned = Entry.createArray(entries.length);
1.201 + nws.entries = cloned;
1.202 +
1.203 + for (int i = 0; i < cloned.length; i++) {
1.204 + Object ref;
1.205 +
1.206 + if ((entries[i] == null) || ((ref = entries[i].get()) == null)) {
1.207 + cloned[i] = null;
1.208 + } else {
1.209 + cloned[i] = ((entries[i] == null) ? null : entries[i].clone(nws.refq));
1.210 + ref = null;
1.211 + }
1.212 +
1.213 + // chains into nws iterator chain
1.214 + Entry<E> entry = cloned[i];
1.215 +
1.216 + while (entry != null) {
1.217 + entry.chainIntoIter(nws.iterChain);
1.218 + nws.iterChain = entry;
1.219 + entry = entry.next;
1.220 + }
1.221 + }
1.222 +
1.223 + return nws;
1.224 + }
1.225 +
1.226 + /** Returns true if this set contains the specified element.
1.227 + *
1.228 + * @param o an Object to examine
1.229 + */
1.230 + public boolean contains(Object o) {
1.231 + if (o == null) {
1.232 + return nullCount > 0;
1.233 + }
1.234 +
1.235 + return object2Entry(o) != null;
1.236 + }
1.237 +
1.238 + /** Returns true if this set contains no elements.
1.239 + */
1.240 + public boolean isEmpty() {
1.241 + return ((nullCount == 0) && (size() == 0));
1.242 + }
1.243 +
1.244 + /** Returns an iterator over the elements in this set. */
1.245 + public Iterator<E> iterator() {
1.246 + return new WeakSetIterator();
1.247 + }
1.248 +
1.249 + /** Removes the given element from this set if it is present.
1.250 + *
1.251 + * @param o an Object to remove
1.252 + * @return <tt>true</tt> if and only if the Object was successfuly removed.
1.253 + */
1.254 + public boolean remove(Object o) {
1.255 + if (o == null) {
1.256 + if (nullCount > 0) {
1.257 + nullCount--;
1.258 + modcount++;
1.259 + size--;
1.260 + }
1.261 +
1.262 + return true;
1.263 + }
1.264 +
1.265 + Entry e = object2Entry(o);
1.266 +
1.267 + if (e != null) {
1.268 + modcount++;
1.269 + size--;
1.270 + e.remove();
1.271 + rehash();
1.272 +
1.273 + return true;
1.274 + }
1.275 +
1.276 + return false;
1.277 + }
1.278 +
1.279 + /** @return the number of elements in this set (its cardinality). */
1.280 + public int size() {
1.281 + checkRefQueue();
1.282 +
1.283 + return size;
1.284 + }
1.285 +
1.286 + public <T> T[] toArray(T[] array) {
1.287 + ArrayList<E> list = new ArrayList<E>(array.length);
1.288 + Iterator<E> it = iterator();
1.289 +
1.290 + while (it.hasNext()) {
1.291 + list.add(it.next());
1.292 + }
1.293 +
1.294 + return list.toArray(array);
1.295 + }
1.296 +
1.297 + public Object[] toArray() {
1.298 + ArrayList<E> list = new ArrayList<E>();
1.299 + Iterator<E> it = iterator();
1.300 +
1.301 + while (it.hasNext()) {
1.302 + list.add(it.next());
1.303 + }
1.304 +
1.305 + return list.toArray();
1.306 + }
1.307 +
1.308 + // #14772
1.309 + public String toString() {
1.310 + StringBuffer buf = new StringBuffer();
1.311 + Iterator e = iterator();
1.312 + buf.append("[");
1.313 +
1.314 + while (e.hasNext()) {
1.315 + buf.append(String.valueOf(e.next()));
1.316 +
1.317 + if (e.hasNext()) {
1.318 + buf.append(", ");
1.319 + }
1.320 + }
1.321 +
1.322 + buf.append("]");
1.323 +
1.324 + return buf.toString();
1.325 + }
1.326 +
1.327 + /** Checks if the queue is empty if not pending weak refs are removed. */
1.328 + void checkRefQueue() {
1.329 + for (;;) {
1.330 + Entry entry = Entry.class.cast(refq.poll());
1.331 +
1.332 + if (entry == null) {
1.333 + break;
1.334 + }
1.335 +
1.336 + entry.remove();
1.337 + size--;
1.338 + }
1.339 + }
1.340 +
1.341 + /** @return modcount */
1.342 + long modCount() {
1.343 + return modcount;
1.344 + }
1.345 +
1.346 + /** @return an index to entries array */
1.347 + int hashIt(Object o) {
1.348 + return (o.hashCode() & 0x7fffffff) % entries.length;
1.349 + }
1.350 +
1.351 + /** rehashes this Set */
1.352 + void rehash() {
1.353 + /*
1.354 + float currentLF = ((float) size) / ((float) entries.length);
1.355 + if (currentLF < loadFactor) {
1.356 + return;
1.357 + }
1.358 + */
1.359 + }
1.360 +
1.361 + /** @return an Entry with given object */
1.362 + private Entry object2Entry(Object o) {
1.363 + checkRefQueue(); // clear ref q
1.364 +
1.365 + int hash = hashIt(o);
1.366 + Entry e = entries[hash];
1.367 +
1.368 + if (e == null) {
1.369 + return null;
1.370 + }
1.371 +
1.372 + while ((e != null) && !e.equals(o)) {
1.373 + e = e.next;
1.374 + }
1.375 +
1.376 + return e;
1.377 + }
1.378 +
1.379 + private void writeObject(ObjectOutputStream obtos)
1.380 + throws IOException {
1.381 + obtos.defaultWriteObject();
1.382 + obtos.writeObject(toArray());
1.383 + }
1.384 +
1.385 + @SuppressWarnings("unchecked")
1.386 + private void readObject(ObjectInputStream obtis) throws IOException, ClassNotFoundException {
1.387 + obtis.defaultReadObject();
1.388 +
1.389 + Object[] arr = (Object[]) obtis.readObject();
1.390 + entries = new Entry[(int) (size * 1.5)];
1.391 + refq = new ReferenceQueue<E>();
1.392 +
1.393 + for (int i = 0; i < arr.length; i++) {
1.394 + add((E)arr[i]);
1.395 + }
1.396 + }
1.397 +
1.398 + class WeakSetIterator implements Iterator<E> {
1.399 + Entry<E> current;
1.400 + Entry<E> next;
1.401 + E currentObj;
1.402 + E nextObj;
1.403 + final long myModcount;
1.404 + long myNullCount;
1.405 +
1.406 + WeakSetIterator() {
1.407 + myModcount = modCount();
1.408 + myNullCount = nullCount;
1.409 + current = null;
1.410 + next = null;
1.411 +
1.412 + Entry<E> ee = iterChain;
1.413 +
1.414 + if (ee == null) {
1.415 + return;
1.416 + }
1.417 +
1.418 + E o = ee.get();
1.419 +
1.420 + while (ee.isEnqueued()) {
1.421 + ee = ee.iterChainNext;
1.422 +
1.423 + if (ee == null) {
1.424 + return;
1.425 + }
1.426 +
1.427 + o = ee.get();
1.428 + }
1.429 +
1.430 + nextObj = o;
1.431 + next = ee;
1.432 + }
1.433 +
1.434 + public boolean hasNext() {
1.435 + checkModcount();
1.436 +
1.437 + return ((myNullCount > 0) || (next != null));
1.438 + }
1.439 +
1.440 + public E next() {
1.441 + checkModcount();
1.442 + checkRefQueue();
1.443 +
1.444 + if (myNullCount > 0) {
1.445 + myNullCount--;
1.446 +
1.447 + return null;
1.448 + } else {
1.449 + if (next == null) {
1.450 + throw new java.util.NoSuchElementException();
1.451 + }
1.452 +
1.453 + current = next;
1.454 + currentObj = nextObj;
1.455 +
1.456 + // move to next requested
1.457 + do {
1.458 + next = next.iterChainNext;
1.459 +
1.460 + if (next == null) {
1.461 + break;
1.462 + }
1.463 +
1.464 + nextObj = next.get();
1.465 + } while (next.isEnqueued());
1.466 +
1.467 + return currentObj;
1.468 + }
1.469 + }
1.470 +
1.471 + public void remove() {
1.472 + checkModcount();
1.473 +
1.474 + if (current == null) {
1.475 + throw new IllegalStateException();
1.476 + }
1.477 +
1.478 + current.remove();
1.479 + size--;
1.480 + }
1.481 +
1.482 + void checkModcount() {
1.483 + if (myModcount != modCount()) {
1.484 + throw new ConcurrentModificationException();
1.485 + }
1.486 + }
1.487 + }
1.488 +
1.489 + /** Entries of this set */
1.490 + static class Entry<E> extends WeakReference<E> {
1.491 + /** reference to outer WeakSet */
1.492 + private WeakSet<E> set;
1.493 +
1.494 + // double linked list
1.495 + Entry<E> prev;
1.496 + Entry<E> next;
1.497 + private final int hashcode;
1.498 + Entry<E> iterChainNext;
1.499 + Entry<E> iterChainPrev;
1.500 +
1.501 + Entry(WeakSet<E> set, E referenced, ReferenceQueue<E> q, Entry<E> next, Entry<E> nextInIter) {
1.502 + super(referenced, q);
1.503 + this.set = set;
1.504 +
1.505 + this.next = next;
1.506 + this.prev = null;
1.507 +
1.508 + if (next != null) {
1.509 + next.prev = this;
1.510 + }
1.511 +
1.512 + if (referenced != null) {
1.513 + hashcode = set.hashIt(referenced);
1.514 + } else {
1.515 + hashcode = 0;
1.516 + }
1.517 +
1.518 + chainIntoIter(nextInIter);
1.519 + }
1.520 +
1.521 + @SuppressWarnings("unchecked")
1.522 + static final <E> Entry<E>[] createArray(int size) {
1.523 + return new Entry[size];
1.524 + }
1.525 +
1.526 + void chainIntoIter(Entry<E> nextInIter) {
1.527 + iterChainNext = nextInIter;
1.528 +
1.529 + if (nextInIter != null) {
1.530 + nextInIter.iterChainPrev = this;
1.531 + }
1.532 + }
1.533 +
1.534 + /** deques itself */
1.535 + void remove() {
1.536 + if (prev != null) {
1.537 + prev.next = next;
1.538 + }
1.539 +
1.540 + if (next != null) {
1.541 + next.prev = prev;
1.542 + }
1.543 +
1.544 + if (iterChainNext != null) {
1.545 + iterChainNext.iterChainPrev = iterChainPrev;
1.546 + }
1.547 +
1.548 + if (iterChainPrev != null) {
1.549 + iterChainPrev.iterChainNext = iterChainNext;
1.550 + } else { // root
1.551 + set.iterChain = iterChainNext;
1.552 + }
1.553 +
1.554 + if (set.entries[hashcode] == this) {
1.555 + set.entries[hashcode] = next;
1.556 + }
1.557 +
1.558 + prev = null;
1.559 + next = null;
1.560 + iterChainNext = null;
1.561 + iterChainPrev = null;
1.562 + }
1.563 +
1.564 + public int hashCode() {
1.565 + return hashcode;
1.566 + }
1.567 +
1.568 + public boolean equals(Object o) {
1.569 + Object oo = get();
1.570 +
1.571 + if (oo == null) {
1.572 + return false;
1.573 + } else {
1.574 + return oo.equals(o);
1.575 + }
1.576 + }
1.577 +
1.578 + public Entry<E> clone(ReferenceQueue<E> q) {
1.579 + return new Entry<E>(set, get(), q, next != null ? next.clone(q) : null, null);
1.580 + }
1.581 + }
1.582 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/openide.util/test/unit/src/org/openide/util/UtilitiesTest.java Wed Jan 20 17:59:42 2010 -0500
2.3 @@ -0,0 +1,643 @@
2.4 +/*
2.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2.6 + *
2.7 + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
2.8 + *
2.9 + * The contents of this file are subject to the terms of either the GNU
2.10 + * General Public License Version 2 only ("GPL") or the Common
2.11 + * Development and Distribution License("CDDL") (collectively, the
2.12 + * "License"). You may not use this file except in compliance with the
2.13 + * License. You can obtain a copy of the License at
2.14 + * http://www.netbeans.org/cddl-gplv2.html
2.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
2.16 + * specific language governing permissions and limitations under the
2.17 + * License. When distributing the software, include this License Header
2.18 + * Notice in each file and include the License file at
2.19 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
2.20 + * particular file as subject to the "Classpath" exception as provided
2.21 + * by Sun in the GPL Version 2 section of the License file that
2.22 + * accompanied this code. If applicable, add the following below the
2.23 + * License Header, with the fields enclosed by brackets [] replaced by
2.24 + * your own identifying information:
2.25 + * "Portions Copyrighted [year] [name of copyright owner]"
2.26 + *
2.27 + * Contributor(s):
2.28 + *
2.29 + * The Original Software is NetBeans. The Initial Developer of the Original
2.30 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
2.31 + * Microsystems, Inc. All Rights Reserved.
2.32 + *
2.33 + * If you wish your version of this file to be governed by only the CDDL
2.34 + * or only the GPL Version 2, indicate your decision by adding
2.35 + * "[Contributor] elects to include this software in this distribution
2.36 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
2.37 + * single choice of license, a recipient has the option to distribute
2.38 + * your version of this file under either the CDDL, the GPL Version 2 or
2.39 + * to extend the choice of license to its licensees as provided above.
2.40 + * However, if you add GPL Version 2 code and therefore, elected the GPL
2.41 + * Version 2 license, then the option applies only if the new code is
2.42 + * made subject to such option by the copyright holder.
2.43 + */
2.44 +
2.45 +package org.openide.util;
2.46 +
2.47 +import java.awt.Button;
2.48 +import java.awt.Canvas;
2.49 +import java.awt.Checkbox;
2.50 +import java.awt.CheckboxMenuItem;
2.51 +import java.awt.Choice;
2.52 +import java.awt.Component;
2.53 +import java.awt.Cursor;
2.54 +import java.awt.Desktop;
2.55 +import java.awt.Dialog;
2.56 +import java.awt.Dialog.ModalExclusionType;
2.57 +import java.awt.Dialog.ModalityType;
2.58 +import java.awt.Dimension;
2.59 +import java.awt.EventQueue;
2.60 +import java.awt.FileDialog;
2.61 +import java.awt.Font;
2.62 +import java.awt.FontMetrics;
2.63 +import java.awt.Frame;
2.64 +import java.awt.HeadlessException;
2.65 +import java.awt.Image;
2.66 +import java.awt.Label;
2.67 +import java.awt.Menu;
2.68 +import java.awt.MenuBar;
2.69 +import java.awt.MenuItem;
2.70 +import java.awt.Panel;
2.71 +import java.awt.Point;
2.72 +import java.awt.PopupMenu;
2.73 +import java.awt.PrintJob;
2.74 +import java.awt.ScrollPane;
2.75 +import java.awt.Scrollbar;
2.76 +import java.awt.TextArea;
2.77 +import java.awt.TextField;
2.78 +import java.awt.Toolkit;
2.79 +import java.awt.Window;
2.80 +import java.awt.datatransfer.Clipboard;
2.81 +import java.awt.dnd.DragGestureEvent;
2.82 +import java.awt.dnd.InvalidDnDOperationException;
2.83 +import java.awt.dnd.peer.DragSourceContextPeer;
2.84 +import java.awt.event.ActionEvent;
2.85 +import java.awt.event.ActionListener;
2.86 +import java.awt.event.KeyEvent;
2.87 +import java.awt.im.InputMethodHighlight;
2.88 +import java.awt.image.BufferedImage;
2.89 +import java.awt.image.ColorModel;
2.90 +import java.awt.image.ImageObserver;
2.91 +import java.awt.image.ImageProducer;
2.92 +import java.awt.peer.ButtonPeer;
2.93 +import java.awt.peer.CanvasPeer;
2.94 +import java.awt.peer.CheckboxMenuItemPeer;
2.95 +import java.awt.peer.CheckboxPeer;
2.96 +import java.awt.peer.ChoicePeer;
2.97 +import java.awt.peer.DesktopPeer;
2.98 +import java.awt.peer.DialogPeer;
2.99 +import java.awt.peer.FileDialogPeer;
2.100 +import java.awt.peer.FontPeer;
2.101 +import java.awt.peer.FramePeer;
2.102 +import java.awt.peer.LabelPeer;
2.103 +import java.awt.peer.ListPeer;
2.104 +import java.awt.peer.MenuBarPeer;
2.105 +import java.awt.peer.MenuItemPeer;
2.106 +import java.awt.peer.MenuPeer;
2.107 +import java.awt.peer.PanelPeer;
2.108 +import java.awt.peer.PopupMenuPeer;
2.109 +import java.awt.peer.ScrollPanePeer;
2.110 +import java.awt.peer.ScrollbarPeer;
2.111 +import java.awt.peer.TextAreaPeer;
2.112 +import java.awt.peer.TextFieldPeer;
2.113 +import java.awt.peer.WindowPeer;
2.114 +import java.io.File;
2.115 +import java.net.URL;
2.116 +import java.util.ArrayList;
2.117 +import java.util.Arrays;
2.118 +import java.util.List;
2.119 +import java.util.Locale;
2.120 +import java.util.Map;
2.121 +import java.util.Properties;
2.122 +import java.util.concurrent.Semaphore;
2.123 +import javax.swing.AbstractAction;
2.124 +import javax.swing.AbstractButton;
2.125 +import javax.swing.Action;
2.126 +import javax.swing.JButton;
2.127 +import javax.swing.JMenuItem;
2.128 +import javax.swing.JPopupMenu;
2.129 +import javax.swing.JSeparator;
2.130 +import javax.swing.KeyStroke;
2.131 +import junit.framework.Assert;
2.132 +import org.netbeans.junit.MockServices;
2.133 +import org.netbeans.junit.NbTestCase;
2.134 +import org.netbeans.modules.openide.util.AWTBridge;
2.135 +import org.netbeans.modules.openide.util.NamedServicesProvider;
2.136 +import org.openide.util.actions.Presenter;
2.137 +import org.openide.util.lookup.AbstractLookup;
2.138 +import org.openide.util.lookup.InstanceContent;
2.139 +import org.openide.util.lookup.Lookups;
2.140 +import org.openide.util.test.MockLookup;
2.141 +
2.142 +/**
2.143 + * @author Jiri Rechtacek et al.
2.144 + */
2.145 +public class UtilitiesTest extends NbTestCase {
2.146 +
2.147 + public UtilitiesTest (String testName) {
2.148 + super (testName);
2.149 + }
2.150 +
2.151 + private String originalOsName;
2.152 +
2.153 + @Override
2.154 + protected void setUp() throws Exception {
2.155 + super.setUp();
2.156 + Utilities.resetOperatingSystem ();
2.157 + originalOsName = System.getProperty("os.name");
2.158 + }
2.159 +
2.160 + @Override
2.161 + protected void tearDown() throws Exception {
2.162 + System.setProperty("os.name", originalOsName);
2.163 + super.tearDown();
2.164 + }
2.165 +
2.166 + public void testGetOperatingSystemWinNT () {
2.167 + System.setProperty ("os.name", "Windows NT");
2.168 + //assertEquals ("System.getProperty (os.name) returns Windows NT", "Windows NT", System.getProperty ("os.name"));
2.169 + assertEquals ("Windows NT recognized as OS_WINNT", Utilities.OS_WINNT, Utilities.getOperatingSystem ());
2.170 + }
2.171 +
2.172 + public void testGetOperatingSystemFreebsd () {
2.173 + System.setProperty ("os.name", "FreeBSD");
2.174 + assertEquals ("System.getProperty (os.name) returns FreeBSD", "FreeBSD", System.getProperty ("os.name"));
2.175 + assertEquals ("System.getProperty (os.name) returns freebsd", "freebsd", System.getProperty ("os.name").toLowerCase (Locale.US));
2.176 + assertEquals ("FreeBSD recognized as OS_FREEBSD", Utilities.OS_FREEBSD, Utilities.getOperatingSystem ());
2.177 + }
2.178 +
2.179 + public void testGetOperatingSystemFreeBSDLowerCase () {
2.180 + System.setProperty ("os.name", "freebsd");
2.181 + assertEquals ("FreeBSD recognized as OS_FREEBSD", Utilities.OS_FREEBSD, Utilities.getOperatingSystem ());
2.182 + }
2.183 +
2.184 + public void testGetUnknownOperatingSystem () {
2.185 + System.setProperty ("os.name", "Unknown");
2.186 + if (File.pathSeparatorChar == ':') {
2.187 + assertTrue("Unknown os.name should be recognized as Unix.", Utilities.isUnix());
2.188 + } else {
2.189 + assertEquals("Unknown os.name not OS_OTHER.", Utilities.OS_OTHER, Utilities.getOperatingSystem());
2.190 + }
2.191 + }
2.192 +
2.193 + public void testWhatIsWinXP () {
2.194 + System.setProperty ("os.name", "Windows XP");
2.195 + assertTrue ("Windows XP isWindows", Utilities.isWindows ());
2.196 + assertFalse ("Windows XP not isUnix", Utilities.isUnix ());
2.197 + }
2.198 +
2.199 + public void testWhatIsLinux () {
2.200 + System.setProperty ("os.name", "Linux");
2.201 + assertFalse ("Linux not isWindows", Utilities.isWindows ());
2.202 + assertTrue ("Linux isUnix", Utilities.isUnix ());
2.203 + }
2.204 +
2.205 + public void testWhatIsMac () {
2.206 + System.setProperty ("os.name", "Mac OS X");
2.207 + assertFalse ("Mac not isWindows", Utilities.isWindows ());
2.208 + assertTrue ("Mac isMac", Utilities.isMac ());
2.209 + }
2.210 +
2.211 + public void testWhatIsFreeBSD () {
2.212 + System.setProperty ("os.name", "freebsd");
2.213 + assertFalse ("freebsd is not isWindows", Utilities.isWindows ());
2.214 + assertTrue ("freebsd isUnix", Utilities.isUnix ());
2.215 + }
2.216 +
2.217 + public void testCustomCursorNotSupported() {
2.218 + NoCustomCursorToolkit toolkit = new NoCustomCursorToolkit();
2.219 + CustomToolkitComponent c = new CustomToolkitComponent( toolkit );
2.220 + Image icon = new BufferedImage( 16, 16, BufferedImage.TYPE_BYTE_BINARY );
2.221 + Cursor cursor = Utilities.createCustomCursor( c, icon, "junittest" );
2.222 + assertTrue( "fallback to wait cursor", Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ).equals( cursor ) );
2.223 + assertTrue( "getBestCursorSize was called", toolkit.getBestCursorSizeCalled );
2.224 + assertFalse( "no custom cursor created", toolkit.createCustomCursorCalled );
2.225 + }
2.226 +
2.227 + public void testKeyConversions() throws Exception {
2.228 + assertEquals("CS-F1", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_F1, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK)));
2.229 + assertEquals(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, KeyEvent.ALT_MASK), Utilities.stringToKey("A-EQUALS"));
2.230 + // XXX stringToKeys, Mac support, various more exotic conditions...
2.231 + }
2.232 +
2.233 + public void testKeyConversionsPortable() throws Exception {
2.234 + if (Utilities.isMac()) {
2.235 + assertEquals("SD-D", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.SHIFT_MASK | KeyEvent.META_MASK), true));
2.236 + assertEquals("SO-D", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.SHIFT_MASK | KeyEvent.CTRL_MASK), true));
2.237 + assertEquals("A-RIGHT", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_MASK), true));
2.238 + } else {
2.239 + assertEquals("SD-D", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.SHIFT_MASK | KeyEvent.CTRL_MASK), true));
2.240 + assertEquals("O-RIGHT", Utilities.keyToString(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_MASK), true));
2.241 + }
2.242 + }
2.243 +
2.244 + public void testSpecialKeyworksOn14AsWell15 () throws Exception {
2.245 + KeyStroke ks = Utilities.stringToKey("C-CONTEXT_MENU");
2.246 + assertNotNull ("key stroke created", ks);
2.247 + KeyStroke alt = KeyStroke.getKeyStroke(ks.getKeyCode(), KeyEvent.ALT_MASK);
2.248 + String s = Utilities.keyToString(alt);
2.249 + assertEquals ("Correctly converted", "A-CONTEXT_MENU", s);
2.250 + }
2.251 +
2.252 + public void testSpecialKeyworksOn14AsWell15WithoutModificators () throws Exception {
2.253 + KeyStroke ks = Utilities.stringToKey("CONTEXT_MENU");
2.254 + assertNotNull ("key stroke created", ks);
2.255 + String s = Utilities.keyToString(ks);
2.256 + assertEquals ("Correctly converted", "CONTEXT_MENU", s);
2.257 + }
2.258 +
2.259 + public void testActionsToPopupWithLookup() throws Exception {
2.260 + MockServices.setServices(AwtBridgeImpl.class);
2.261 + final List<String> commands = new ArrayList<String>();
2.262 + class BasicAction extends AbstractAction {
2.263 + public BasicAction(String name) {
2.264 + super(name);
2.265 + }
2.266 + public void actionPerformed(ActionEvent e) {
2.267 + commands.add((String) getValue(Action.NAME));
2.268 + }
2.269 + }
2.270 + class ContextAction extends BasicAction implements ContextAwareAction {
2.271 + public ContextAction(String name) {
2.272 + super(name);
2.273 + }
2.274 + public Action createContextAwareInstance(final Lookup actionContext) {
2.275 + return new AbstractAction() {
2.276 + public void actionPerformed(ActionEvent e) {
2.277 + commands.add(ContextAction.this.getValue(Action.NAME) + "/" + actionContext.lookup(String.class));
2.278 + }
2.279 + };
2.280 + }
2.281 + }
2.282 + class SpecialMenuAction extends BasicAction implements Presenter.Popup {
2.283 + public SpecialMenuAction(String name) {
2.284 + super(name);
2.285 + }
2.286 + public JMenuItem getPopupPresenter() {
2.287 + JMenuItem item = new JMenuItem((String) getValue(Action.NAME));
2.288 + item.addActionListener(new ActionListener() {
2.289 + public void actionPerformed(ActionEvent e) {
2.290 + commands.add(((String) getValue(Action.NAME)) + "/popup");
2.291 + }
2.292 + });
2.293 + return item;
2.294 + }
2.295 + }
2.296 + Action duplicated = new BasicAction("duplicated");
2.297 + Action[] actions = new Action[] {
2.298 + null,
2.299 + null,
2.300 + new BasicAction("first"),
2.301 + duplicated,
2.302 + null,
2.303 + null,
2.304 + new BasicAction("second"),
2.305 + duplicated,
2.306 + null,
2.307 + new ContextAction("context"),
2.308 + new SpecialMenuAction("presenter"),
2.309 + null,
2.310 + new BasicAction("top"),
2.311 + new BasicAction("HIDDEN"),
2.312 + null,
2.313 + new BasicAction("bottom"),
2.314 + null,
2.315 + null,
2.316 + };
2.317 + Lookup l = Lookups.singleton("thing");
2.318 + JPopupMenu menu = Utilities.actionsToPopup(actions, l);
2.319 + for (Component element : menu.getComponents()) { // including separators
2.320 + if (element instanceof AbstractButton) {
2.321 + ((AbstractButton) element).doClick();
2.322 + } else {
2.323 + commands.add(null);
2.324 + }
2.325 + }
2.326 + String[] expectedCommands = new String[] {
2.327 + // leading separators must be stripped
2.328 + "first",
2.329 + "duplicated",
2.330 + null, // adjacent separators must be collapsed
2.331 + "second",
2.332 + // do not add the same action twice
2.333 + null,
2.334 + "context/thing", // ContextAwareAction was checked for
2.335 + "presenter/popup", // Presenter.Popup was checked for
2.336 + null,
2.337 + "top",
2.338 + // exclude HIDDEN because of AwtBridgeImpl.convertComponents
2.339 + // separator should however remain
2.340 + null,
2.341 + "bottom",
2.342 + // trailing separators must be stripped
2.343 + };
2.344 + assertEquals("correct generated menu", Arrays.asList(expectedCommands), commands);
2.345 + }
2.346 +
2.347 + public void testActionsForPath() throws Exception {
2.348 + MockLookup.setInstances(new NamedServicesProvider() {
2.349 + public Lookup create(String path) {
2.350 + if (!path.equals("stuff/")) {
2.351 + return Lookup.EMPTY;
2.352 + }
2.353 + InstanceContent content = new InstanceContent();
2.354 + InstanceContent.Convertor<String,Action> actionConvertor = new InstanceContent.Convertor<String,Action>() {
2.355 + public Action convert(final String obj) {
2.356 + return new AbstractAction() {
2.357 + public void actionPerformed(ActionEvent e) {}
2.358 + public @Override String toString() {
2.359 + return obj;
2.360 + }
2.361 +
2.362 + };
2.363 + }
2.364 + public Class<? extends Action> type(String obj) {
2.365 + return AbstractAction.class;
2.366 + }
2.367 + public String id(String obj) {
2.368 + return obj;
2.369 + }
2.370 + public String displayName(String obj) {
2.371 + return id(obj);
2.372 + }
2.373 + };
2.374 + InstanceContent.Convertor<Boolean,JSeparator> separatorConvertor = new InstanceContent.Convertor<Boolean,JSeparator>() {
2.375 + public JSeparator convert(Boolean obj) {
2.376 + Assert.fail("should not be creating the JSeparator yet");
2.377 + return new JSeparator();
2.378 + }
2.379 + public Class<? extends JSeparator> type(Boolean obj) {
2.380 + return JSeparator.class;
2.381 + }
2.382 + public String id(Boolean obj) {
2.383 + return "sep";
2.384 + }
2.385 + public String displayName(Boolean obj) {
2.386 + return id(obj);
2.387 + }
2.388 + };
2.389 + content.add("hello", actionConvertor);
2.390 + content.add(true, separatorConvertor);
2.391 + content.add("there", actionConvertor);
2.392 + return new AbstractLookup(content);
2.393 + }
2.394 + });
2.395 + // #156829: ensure that no tree lock is acquired.
2.396 + final Semaphore ready = new Semaphore(0);
2.397 + final Semaphore done = new Semaphore(0);
2.398 + EventQueue.invokeLater(new Runnable() {
2.399 + public void run() {
2.400 + synchronized (new JSeparator().getTreeLock()) {
2.401 + ready.release();
2.402 + try {
2.403 + done.acquire();
2.404 + } catch (InterruptedException ex) {
2.405 + Exceptions.printStackTrace(ex);
2.406 + }
2.407 + }
2.408 + }
2.409 + });
2.410 + ready.acquire();
2.411 + try {
2.412 + assertEquals("[hello, null, there]", Utilities.actionsForPath("stuff").toString());
2.413 + } finally {
2.414 + done.release();
2.415 + }
2.416 + }
2.417 +
2.418 + private static class CustomToolkitComponent extends Component {
2.419 + private Toolkit customToolkit;
2.420 +
2.421 + public CustomToolkitComponent( Toolkit t ) {
2.422 + this.customToolkit = t;
2.423 + }
2.424 +
2.425 + public Toolkit getToolkit() {
2.426 + return customToolkit;
2.427 + }
2.428 + }
2.429 +
2.430 + private static class NoCustomCursorToolkit extends Toolkit {
2.431 + public FontMetrics getFontMetrics(Font font) {
2.432 + return Toolkit.getDefaultToolkit().getFontMetrics( font );
2.433 + }
2.434 +
2.435 + protected TextFieldPeer createTextField(TextField target) throws HeadlessException {
2.436 + throw new IllegalStateException("Method not implemented");
2.437 + }
2.438 +
2.439 + protected ListPeer createList(java.awt.List target) throws HeadlessException {
2.440 + throw new IllegalStateException("Method not implemented");
2.441 + }
2.442 +
2.443 + protected MenuBarPeer createMenuBar(MenuBar target) throws HeadlessException {
2.444 + throw new IllegalStateException("Method not implemented");
2.445 + }
2.446 +
2.447 + public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException {
2.448 + return Toolkit.getDefaultToolkit().createDragSourceContextPeer( dge );
2.449 + }
2.450 +
2.451 + public boolean prepareImage(Image image, int width, int height, ImageObserver observer) {
2.452 + return Toolkit.getDefaultToolkit().prepareImage( image, width, height, observer );
2.453 + }
2.454 +
2.455 + public int checkImage(Image image, int width, int height, ImageObserver observer) {
2.456 + return Toolkit.getDefaultToolkit().checkImage( image, width, height, observer );
2.457 + }
2.458 +
2.459 + protected PopupMenuPeer createPopupMenu(PopupMenu target) throws HeadlessException {
2.460 + throw new IllegalStateException("Method not implemented");
2.461 + }
2.462 +
2.463 + public PrintJob getPrintJob(Frame frame, String jobtitle, Properties props) {
2.464 + return Toolkit.getDefaultToolkit().getPrintJob( frame, jobtitle, props );
2.465 + }
2.466 +
2.467 + protected ButtonPeer createButton(Button target) throws HeadlessException {
2.468 + throw new IllegalStateException("Method not implemented");
2.469 + }
2.470 +
2.471 + public Image createImage(ImageProducer producer) {
2.472 + return Toolkit.getDefaultToolkit().createImage( producer );
2.473 + }
2.474 +
2.475 + protected CanvasPeer createCanvas(Canvas target) {
2.476 + throw new IllegalStateException("Method not implemented");
2.477 + }
2.478 +
2.479 + protected ScrollbarPeer createScrollbar(Scrollbar target) throws HeadlessException {
2.480 + throw new IllegalStateException("Method not implemented");
2.481 + }
2.482 +
2.483 + public Image getImage(String filename) {
2.484 + return Toolkit.getDefaultToolkit().getImage( filename );
2.485 + }
2.486 +
2.487 + public Image createImage(String filename) {
2.488 + return Toolkit.getDefaultToolkit().createImage( filename );
2.489 + }
2.490 +
2.491 + protected MenuPeer createMenu(Menu target) throws HeadlessException {
2.492 + throw new IllegalStateException("Method not implemented");
2.493 + }
2.494 +
2.495 + protected MenuItemPeer createMenuItem(MenuItem target) throws HeadlessException {
2.496 + throw new IllegalStateException("Method not implemented");
2.497 + }
2.498 +
2.499 + public Map mapInputMethodHighlight(InputMethodHighlight highlight) throws HeadlessException {
2.500 + return Toolkit.getDefaultToolkit().mapInputMethodHighlight( highlight );
2.501 + }
2.502 +
2.503 + public Image createImage(byte[] imagedata, int imageoffset, int imagelength) {
2.504 + return Toolkit.getDefaultToolkit().createImage( imagedata, imageoffset, imagelength );
2.505 + }
2.506 +
2.507 + public Image getImage(URL url) {
2.508 + return Toolkit.getDefaultToolkit().getImage( url );
2.509 + }
2.510 +
2.511 + protected CheckboxPeer createCheckbox(Checkbox target) throws HeadlessException {
2.512 + throw new IllegalStateException("Method not implemented");
2.513 + }
2.514 +
2.515 + public Image createImage(URL url) {
2.516 + return Toolkit.getDefaultToolkit().createImage( url );
2.517 + }
2.518 +
2.519 + protected TextAreaPeer createTextArea(TextArea target) throws HeadlessException {
2.520 + throw new IllegalStateException("Method not implemented");
2.521 + }
2.522 +
2.523 + protected FileDialogPeer createFileDialog(FileDialog target) throws HeadlessException {
2.524 + throw new IllegalStateException("Method not implemented");
2.525 + }
2.526 +
2.527 + protected ScrollPanePeer createScrollPane(ScrollPane target) throws HeadlessException {
2.528 + throw new IllegalStateException("Method not implemented");
2.529 + }
2.530 +
2.531 + protected DialogPeer createDialog(Dialog target) throws HeadlessException {
2.532 + throw new IllegalStateException("Method not implemented");
2.533 + }
2.534 +
2.535 + protected PanelPeer createPanel(Panel target) {
2.536 + throw new IllegalStateException("Method not implemented");
2.537 + }
2.538 +
2.539 + protected ChoicePeer createChoice(Choice target) throws HeadlessException {
2.540 + throw new IllegalStateException("Method not implemented");
2.541 + }
2.542 +
2.543 + protected FramePeer createFrame(Frame target) throws HeadlessException {
2.544 + throw new IllegalStateException("Method not implemented");
2.545 + }
2.546 +
2.547 + protected LabelPeer createLabel(Label target) throws HeadlessException {
2.548 + throw new IllegalStateException("Method not implemented");
2.549 + }
2.550 +
2.551 + protected FontPeer getFontPeer(String name, int style) {
2.552 + throw new IllegalStateException("Method not implemented");
2.553 + }
2.554 +
2.555 + protected CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) throws HeadlessException {
2.556 + throw new IllegalStateException("Method not implemented");
2.557 + }
2.558 +
2.559 + protected WindowPeer createWindow(Window target) throws HeadlessException {
2.560 + throw new IllegalStateException("Method not implemented");
2.561 + }
2.562 +
2.563 + public void sync() {
2.564 + Toolkit.getDefaultToolkit().sync();
2.565 + }
2.566 +
2.567 + protected EventQueue getSystemEventQueueImpl() {
2.568 + return Toolkit.getDefaultToolkit().getSystemEventQueue();
2.569 + }
2.570 +
2.571 + public Clipboard getSystemClipboard() throws HeadlessException {
2.572 + return Toolkit.getDefaultToolkit().getSystemClipboard();
2.573 + }
2.574 +
2.575 + public Dimension getScreenSize() throws HeadlessException {
2.576 + return Toolkit.getDefaultToolkit().getScreenSize();
2.577 + }
2.578 +
2.579 + public int getScreenResolution() throws HeadlessException {
2.580 + return Toolkit.getDefaultToolkit().getScreenResolution();
2.581 + }
2.582 +
2.583 + public String[] getFontList() {
2.584 + return Toolkit.getDefaultToolkit().getFontList();
2.585 + }
2.586 +
2.587 + public ColorModel getColorModel() throws HeadlessException {
2.588 + return Toolkit.getDefaultToolkit().getColorModel();
2.589 + }
2.590 +
2.591 + public void beep() {
2.592 + Toolkit.getDefaultToolkit().beep();
2.593 + }
2.594 +
2.595 + boolean createCustomCursorCalled = false;
2.596 + public Cursor createCustomCursor(Image cursor, Point hotSpot, String name) throws IndexOutOfBoundsException, HeadlessException {
2.597 +
2.598 + createCustomCursorCalled = true;
2.599 + return Toolkit.getDefaultToolkit().createCustomCursor(cursor, hotSpot, name);
2.600 + }
2.601 +
2.602 + boolean getBestCursorSizeCalled = false;
2.603 + public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) throws HeadlessException {
2.604 + getBestCursorSizeCalled = true;
2.605 + return new Dimension(0,0);
2.606 + }
2.607 +
2.608 + @Override
2.609 + protected DesktopPeer createDesktopPeer(Desktop target) throws HeadlessException {
2.610 + throw new UnsupportedOperationException("Not supported yet.");
2.611 + }
2.612 +
2.613 + @Override
2.614 + public boolean isModalityTypeSupported(ModalityType modalityType) {
2.615 + throw new UnsupportedOperationException("Not supported yet.");
2.616 + }
2.617 +
2.618 + @Override
2.619 + public boolean isModalExclusionTypeSupported(ModalExclusionType modalExclusionType) {
2.620 + throw new UnsupportedOperationException("Not supported yet.");
2.621 + }
2.622 + }
2.623 +
2.624 + public static final class AwtBridgeImpl extends AWTBridge {
2.625 + public JPopupMenu createEmptyPopup() {
2.626 + return new JPopupMenu();
2.627 + }
2.628 + public JMenuItem createMenuPresenter(Action action) {
2.629 + return new JMenuItem(action);
2.630 + }
2.631 + public JMenuItem createPopupPresenter(Action action) {
2.632 + return new JMenuItem(action);
2.633 + }
2.634 + public Component createToolbarPresenter(Action action) {
2.635 + return new JButton(action);
2.636 + }
2.637 + public Component[] convertComponents(Component comp) {
2.638 + if (comp instanceof JMenuItem && "HIDDEN".equals(((JMenuItem) comp).getText())) {
2.639 + return new Component[0];
2.640 + } else {
2.641 + return new Component[] {comp};
2.642 + }
2.643 + }
2.644 + }
2.645 +
2.646 +}