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: package org.netbeans.modules.vmd.api.model;
042:
043: import org.openide.ErrorManager;
044:
045: import java.util.ArrayList;
046: import java.util.Collection;
047:
048: /**
049: * This class is in the API for debugging purpose only.
050: *<p>
051: * Note: Use for debugging purpose only.
052: *
053: * @author David Kaspar
054: */
055: public class Debug {
056:
057: private Debug() {
058: }
059:
060: private static int stackTraceFriendIndex = Integer.MIN_VALUE;
061:
062: private static void init() {
063: if (stackTraceFriendIndex >= 0)
064: return;
065: StackTraceElement[] stackTrace = Thread.currentThread()
066: .getStackTrace();
067: for (int a = 0; a < stackTrace.length; a++) {
068: StackTraceElement stackTraceElement = stackTrace[a];
069: if (Debug.class.getName().equals(
070: stackTraceElement.getClassName())
071: && "init".equals(stackTraceElement.getMethodName())) {
072: stackTraceFriendIndex = a + 2;
073: return;
074: }
075: }
076: }
077:
078: /**
079: * Prints a warning message.
080: * @param messages the messages
081: */
082: public static void warning(Object... messages) {
083: init();
084: if (messages.length == 1 && messages[0] instanceof Throwable) {
085: ((Throwable) messages[0]).printStackTrace(System.err);
086: return;
087: }
088:
089: StackTraceElement[] stack = Thread.currentThread()
090: .getStackTrace();
091: StringBuilder sb = new StringBuilder();
092: sb.append("WARNING: ").append(stack[stackTraceFriendIndex - 1])
093: .append('\n'); // NOI18N
094: if (stackTraceFriendIndex < stack.length)
095: sb.append(" ").append(stack[stackTraceFriendIndex])
096: .append('\n'); // NOI18N
097: for (Object message : messages)
098: sb.append(" | ").append(message); // NOI18N
099: System.err.println(sb.toString());
100: }
101:
102: /**
103: * Checks whether a method (from where this isFriend method is called) is called from a specified class.
104: * @param clazz the class
105: * @return true if it is called from friend class
106: */
107: public static boolean isFriend(Class clazz) {
108: init();
109: StackTraceElement whoCalled = Thread.currentThread()
110: .getStackTrace()[stackTraceFriendIndex];
111: return whoCalled.getClassName().equals(clazz.getName());
112: }
113:
114: /**
115: * Checks whether a method (from where this isFriend method is called) is called from a specified method of a specified class.
116: * @param clazz the class
117: * @param method the method
118: * @return true if it is called from friend class
119: */
120: public static boolean isFriend(Class clazz, String method) {
121: init();
122: StackTraceElement whoCalled = Thread.currentThread()
123: .getStackTrace()[stackTraceFriendIndex];
124: return whoCalled.getClassName().equals(clazz.getName())
125: && whoCalled.getMethodName().equals(method);
126: }
127:
128: /**
129: * Checks whether a method (from where this isFriend method is called) is called from a specified method of a specified class.
130: * @param className the class name
131: * @param method the method
132: * @return true if it is called from friend class
133: */
134: public static boolean isFriend(String className, String method) {
135: init();
136: StackTraceElement whoCalled = Thread.currentThread()
137: .getStackTrace()[stackTraceFriendIndex];
138: return whoCalled.getClassName().equals(className)
139: && whoCalled.getMethodName().equals(method);
140: }
141:
142: /**
143: * Shows an error dialog with error message.
144: * <p>
145: * Note: Usually used like: throw Debug.error ("message");
146: * @param messages the messages
147: * @return the exception that could be use for escaping from a method
148: */
149: public static RuntimeException error(Object... messages) {
150: init();
151: Throwable exception;
152: if (messages.length == 1 && messages[0] instanceof Throwable) {
153: exception = (Throwable) messages[0];
154: } else {
155: StringBuilder sb = new StringBuilder();
156: StackTraceElement[] stack = Thread.currentThread()
157: .getStackTrace();
158: sb.append("ERROR: ").append(
159: stack[stackTraceFriendIndex - 1]).append('\n'); // NOI18N
160: if (stackTraceFriendIndex < stack.length)
161: sb.append(" ").append(
162: stack[stackTraceFriendIndex]).append('\n'); // NOI18N
163: for (Object message : messages)
164: sb.append(" | ").append(message); // NOI18N
165:
166: exception = new RuntimeException(sb.toString());
167: }
168: ErrorManager.getDefault().notify(ErrorManager.ERROR, exception);
169: throw new RuntimeException(exception);
170: }
171:
172: /**
173: * Shows an error dialog with illegal-state message.
174: * <p/>
175: * Note: Usually used like: throw Debug.illegalState ("message");
176: * @param messages the messages
177: * @return the exception that could be use for escaping from a method
178: */
179: public static RuntimeException illegalState(Object... messages) {
180: init();
181: Throwable exception;
182: if (messages.length == 1 && messages[0] instanceof Throwable) {
183: exception = (Throwable) messages[0];
184: } else {
185: StringBuilder sb = new StringBuilder("ILLEGAL STATE: "); // NOI18N
186: sb
187: .append(Thread.currentThread().getStackTrace()[stackTraceFriendIndex - 1]);
188: sb.append('\n');
189: for (Object message : messages)
190: sb.append(" | ").append(message); // NOI18N
191:
192: exception = new IllegalStateException(sb.toString());
193: }
194: ErrorManager.getDefault().notify(ErrorManager.ERROR, exception);
195: throw new RuntimeException(exception);
196: }
197:
198: /**
199: * Shows an error dialog with illegal-argument message.
200: * <p/>
201: * Note: Usually used like: throw Debug.illegalArgument ("message");
202: * @param messages the messages
203: * @return the exception that could be use for escaping from a method
204: */
205: public static RuntimeException illegalArgument(Object... messages) {
206: init();
207: Throwable exception;
208: if (messages.length == 1 && messages[0] instanceof Throwable) {
209: exception = (Throwable) messages[0];
210: } else {
211: StringBuilder sb = new StringBuilder("ILLEGAL ARGUMENT: "); // NOI18N
212: sb
213: .append(Thread.currentThread().getStackTrace()[stackTraceFriendIndex - 1]);
214: sb.append('\n'); // NOI18N
215: for (Object message : messages)
216: sb.append(" | ").append(message); // NOI18N
217:
218: exception = new IllegalArgumentException(sb.toString());
219: }
220: ErrorManager.getDefault().notify(ErrorManager.ERROR, exception);
221: throw new RuntimeException(exception);
222: }
223:
224: /**
225: * Prints the tree of components stored in the document.
226: * @param document the document
227: */
228: public static void dumpDocument(DesignDocument document) {
229: assert document != null;
230: dumpComponent(document.getRootComponent());
231: }
232:
233: /**
234: * Prints the tree of components of a specific component
235: * @param component the component
236: */
237: public static void dumpComponent(DesignComponent component) {
238: if (component == null) {
239: System.out.println("No component to dump"); // NOI18N
240: return;
241: }
242: System.out.println("Dumping component: "
243: + component.getComponentID()); // NOI18N
244: component.dumpComponent(""); // NOI18N
245: }
246:
247: /**
248: * Collects all component references from a property value.
249: * @param propertyValue the property value for inspection
250: * @param references the hash set of components for storing results
251: */
252: public static void collectAllComponentReferences(
253: PropertyValue propertyValue,
254: Collection<DesignComponent> references) {
255: propertyValue.collectAllComponentReferences(references);
256: }
257:
258: /**
259: * Checks whether a specified component is referenced from the main tree of components under document root.
260: * @param referenceComponent the reference component
261: * @return true, if the reference component is referenced
262: */
263: public static boolean isComponentReferencedInRootTree(
264: DesignComponent referenceComponent) {
265: assert referenceComponent != null;
266: return isComponentReferencedInRootTree(referenceComponent
267: .getDocument().getRootComponent(), referenceComponent);
268: }
269:
270: private static boolean isComponentReferencedInRootTree(
271: DesignComponent treeComponent,
272: DesignComponent referenceComponent) {
273: ArrayList<DesignComponent> referenced = new ArrayList<DesignComponent>();
274: ComponentDescriptor descriptor = treeComponent
275: .getComponentDescriptor();
276:
277: if (descriptor != null) {
278: for (PropertyDescriptor propertyDescriptor : descriptor
279: .getPropertyDescriptors()) {
280: PropertyValue propertyValue = treeComponent
281: .readProperty(propertyDescriptor.getName());
282: referenced.clear();
283: Debug.collectAllComponentReferences(propertyValue,
284: referenced);
285: if (referenced.contains(referenceComponent))
286: return true;
287: }
288: }
289:
290: for (DesignComponent child : treeComponent.getComponents())
291: if (isComponentReferencedInRootTree(child,
292: referenceComponent))
293: return true;
294:
295: return false;
296: }
297:
298: }
|