001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.openide.nodes;
043:
044: import java.util.Hashtable;
045: import org.openide.util.Mutex;
046:
047: /** Class that serves as interface to various parts of OpenAPIs that need
048: * not be present.
049: *
050: * @author Jaroslav Tulach
051: */
052: abstract class TMUtil extends Object {
053: /** variable that will contain the argument to a call and then a result.
054: */
055: private static final ThreadLocal<Object> TALK = new ThreadLocal<Object>();
056:
057: /** maps names of algorithms (that use the ARGUMENT and the RESULT)
058: * and runnables that has to be executed to compute the algorithm
059: * (String, Runnable) or (String, Exception)
060: */
061: private static Hashtable<String, Object> algorithms = new Hashtable<String, Object>(
062: 10);
063: private static java.awt.Frame owner;
064:
065: /** Dynamically loads a class.
066: * @param className name of the class
067: * @return the class
068: */
069: private static Class loadClass(String className) throws Exception {
070: ClassLoader loader = org.openide.util.Lookup.getDefault()
071: .lookup(ClassLoader.class);
072:
073: if (loader == null) {
074: loader = NodeOperation.class.getClassLoader();
075: }
076:
077: return Class.forName(className, true, loader);
078: }
079:
080: /** Creates InstanceCookie, if available.
081: * @param bean the object to create cookie for
082: * @return Node.Cookie or null
083: */
084: static Node.Cookie createInstanceCookie(Object bean) {
085: try {
086: TALK.set(bean);
087:
088: return exec("Bean") ? (Node.Cookie) TALK.get() : null; // NOI18N
089: } finally {
090: TALK.set(null);
091: }
092: }
093:
094: /** Checks whether an object is instance of DialogDescriptor and if
095: * so it used top manager to create its instance.
096: * @param maybeDialogDescriptor an object
097: * @return a dialog or null
098: */
099: static java.awt.Dialog createDialog(Object maybeDialogDescriptor) {
100: try {
101: TALK.set(maybeDialogDescriptor);
102:
103: return exec("Dial") ? (java.awt.Dialog) TALK.get() : null; // NOI18N
104: } finally {
105: TALK.set(null);
106: }
107: }
108:
109: /** Attaches a customizer to given node.
110: * @param node the bean node
111: * @param cust customizer to attach
112: */
113: static void attachCustomizer(Node node, java.beans.Customizer cust) {
114: try {
115: TALK.set(new Object[] { node, cust });
116: exec("Cust"); // NOI18N
117: } finally {
118: TALK.set(null);
119: }
120: }
121:
122: /** Finds main window.
123: * @return main window or null
124: */
125: static java.awt.Frame mainWindow() {
126: try {
127: if (exec("Win")) { // NOI18N
128:
129: return (java.awt.Frame) TALK.get();
130: } else {
131: // default owner for JDialog
132: if (owner == null) {
133: owner = (java.awt.Frame) new javax.swing.JDialog()
134: .getOwner();
135: }
136:
137: return owner;
138: }
139: } finally {
140: TALK.set(null);
141: }
142: }
143:
144: /** Finds usable list cell renderer.
145: */
146: static javax.swing.ListCellRenderer findListCellRenderer() {
147: try {
148: if (exec("Rend")) { // NOI18N
149:
150: return (javax.swing.ListCellRenderer) TALK.get();
151: } else {
152: return new javax.swing.DefaultListCellRenderer();
153: }
154: } finally {
155: TALK.set(null);
156: }
157: }
158:
159: /** Invoke an indexed customizer. */
160: static void showIndexedCustomizer(Index idx) {
161: try {
162: TALK.set(idx);
163:
164: if (!exec("IndexC")) { // NOI18N
165:
166: // Fallback to simple method.
167: final IndexedCustomizer ic = new IndexedCustomizer();
168: ic.setObject(idx);
169: ic.setImmediateReorder(false);
170: Mutex.EVENT.readAccess(new Mutex.Action<Void>() {
171: public Void run() {
172: ic.setVisible(true);
173:
174: return null;
175: }
176: });
177: }
178: } finally {
179: TALK.set(null);
180: }
181: }
182:
183: /** Executes algorithm of given name.
184: * @param name the name of algorithm
185: * @return true iff successfule
186: */
187: private static boolean exec(String name) {
188: Object obj = algorithms.get(name);
189:
190: if (obj == null) {
191: try {
192: Class c = Class.forName("org.openide.nodes.TMUtil$"
193: + name); // NOI18N
194: obj = c.newInstance();
195: } catch (ClassNotFoundException ex) {
196: obj = ex;
197: NodeOp.exception(ex);
198: } catch (InstantiationException ex) {
199: // that is ok, we should not be able to create an
200: // instance if some classes are missing
201: obj = ex;
202: } catch (IllegalAccessException ex) {
203: obj = ex;
204: NodeOp.exception(ex);
205: } catch (NoClassDefFoundError ex) {
206: // that is ok, some classes need not be found
207: obj = ex;
208: }
209:
210: algorithms.put(name, obj);
211: }
212:
213: try {
214: if (obj instanceof Runnable) {
215: ((Runnable) obj).run();
216:
217: return true;
218: }
219: } catch (NoClassDefFoundError ex) {
220: // in case of late linking the error can be thrown
221: // just when the runnable is executed
222: algorithms.put(name, ex);
223: }
224:
225: return false;
226: }
227:
228: /** Creates instance of InstanceCookie for given object.
229: * ARGUMENT contains the bean to create instance for.
230: */
231: static final class Bean implements Runnable,
232: org.openide.cookies.InstanceCookie {
233: private Object bean;
234:
235: public void run() {
236: Bean n = new Bean();
237: n.bean = TALK.get();
238: TALK.set(n);
239: }
240:
241: public String instanceName() {
242: return bean.getClass().getName();
243: }
244:
245: public Class instanceClass() {
246: return bean.getClass();
247: }
248:
249: public Object instanceCreate() {
250: return bean;
251: }
252: }
253:
254: /** Creates dialog from DialogDescriptor
255: * ARGUMENT contains the descriptor.
256: */
257: static final class Dial implements Runnable {
258: public void run() {
259: Object obj = TALK.get();
260:
261: if (obj instanceof org.openide.DialogDescriptor) {
262: TALK.set(org.openide.DialogDisplayer.getDefault()
263: .createDialog(
264: (org.openide.DialogDescriptor) obj));
265: } else {
266: TALK.set(null);
267: }
268: }
269: }
270:
271: /** Attaches the node to a customizer if it implements NodeCustomizer.
272: * ARGUMENT contains array of node and customizer
273: */
274: static final class Cust implements Runnable {
275: private static Class<?> nodeCustomizer;
276: private static java.lang.reflect.Method attach;
277:
278: public void run() {
279: try {
280: if (nodeCustomizer == null) {
281: // load method
282: nodeCustomizer = loadClass("org.openide.explorer.propertysheet.editors.NodeCustomizer"); // NOI18N
283: attach = nodeCustomizer.getMethod("attach",
284: Node.class); // NOI18N
285: }
286:
287: Object[] arr = (Object[]) TALK.get();
288:
289: Node n = (Node) arr[0];
290: Object cust = arr[1];
291:
292: if (nodeCustomizer.isInstance(cust)) {
293: // ((org.openide.explorer.propertysheet.editors.NodeCustomizer)cust).attach (n);
294: attach.invoke(cust, new Object[] { n });
295: }
296: } catch (Exception ex) {
297: throw new IllegalStateException(ex.getMessage());
298: }
299: }
300: }
301:
302: /** Finds the main window.
303: */
304: static final class Win implements Runnable {
305: private static java.lang.reflect.Method getDefault;
306: private static java.lang.reflect.Method getMainWindow;
307:
308: public void run() {
309: try {
310: if (getDefault == null) {
311: // load all methods
312: Class<?> wm = loadClass("org.openide.windows.WindowManager"); // NOI18N
313: getDefault = wm.getMethod("getDefault"); // NOI18N
314: getMainWindow = wm.getMethod("getMainWindow"); // NOI18N
315: }
316:
317: //
318: // call: WindowManager.getDefault().getMainWindow ()
319: //
320: Object[] param = new Object[0];
321: TALK.set(getMainWindow.invoke(getDefault.invoke(null,
322: param), param));
323: } catch (Exception ex) {
324: throw new IllegalStateException(ex.getMessage());
325: }
326: }
327: }
328:
329: /** Finds renderer.
330: */
331: static final class Rend implements Runnable {
332: private static Class nodeRenderer;
333:
334: public void run() {
335: try {
336: if (nodeRenderer == null) {
337: nodeRenderer = loadClass("org.openide.explorer.view.NodeRenderer"); // NOI18N
338: }
339:
340: TALK.set(nodeRenderer.newInstance());
341: } catch (Exception ex) {
342: throw new IllegalStateException(ex.getMessage());
343: }
344: }
345: }
346:
347: static final class IndexC implements Runnable {
348: public void run() {
349: Index idx = (Index) TALK.get();
350: java.awt.Container p = new javax.swing.JPanel();
351: IndexedCustomizer ic = new IndexedCustomizer(p, false);
352: ic.setObject(idx);
353: ic.setImmediateReorder(false);
354:
355: org.openide.DialogDescriptor dd = new org.openide.DialogDescriptor(
356: p, Node.getString("LAB_order"));
357: dd.setModal(true);
358: dd
359: .setOptionType(org.openide.DialogDescriptor.DEFAULT_OPTION);
360:
361: Object result = org.openide.DialogDisplayer.getDefault()
362: .notify(dd);
363:
364: if (result == org.openide.DialogDescriptor.OK_OPTION) {
365: ic.doClose();
366: }
367: }
368: }
369: }
|