PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/projects/netbeans-7.3/debugger.jpda.ui/src/org/netbeans/modules/debugger/jpda/ui/models/JavaVariablesFilter.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 447 lines | 322 code | 27 blank | 98 comment | 45 complexity | 7f8187a176e716b7e637d4b49e908078 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. package org.netbeans.modules.debugger.jpda.ui.models;
  45. import java.util.HashSet;
  46. import java.util.logging.Logger;
  47. import org.netbeans.api.debugger.jpda.Field;
  48. import org.netbeans.api.debugger.jpda.InvalidExpressionException;
  49. import org.netbeans.api.debugger.jpda.JPDAClassType;
  50. import org.netbeans.api.debugger.jpda.ObjectVariable;
  51. import org.netbeans.api.debugger.jpda.Variable;
  52. import org.netbeans.spi.debugger.jpda.VariablesFilterAdapter;
  53. import org.netbeans.spi.debugger.ui.Constants;
  54. import org.netbeans.spi.viewmodel.TableModel;
  55. import org.netbeans.spi.viewmodel.TreeModel;
  56. import org.netbeans.spi.viewmodel.UnknownTypeException;
  57. import org.openide.util.Exceptions;
  58. /**
  59. *
  60. * @author Jan Jancura
  61. */
  62. public class JavaVariablesFilter extends VariablesFilterAdapter {
  63. public String[] getSupportedTypes () {
  64. return new String[] {
  65. "java.lang.String",
  66. "java.lang.StringBuffer",
  67. "java.lang.StringBuilder",
  68. "java.lang.Character",
  69. "java.lang.Integer",
  70. "java.lang.Float",
  71. "java.lang.Byte",
  72. "java.lang.Boolean",
  73. "java.lang.Double",
  74. "java.lang.Long",
  75. "java.lang.Short",
  76. "java.lang.ref.WeakReference",
  77. "java.lang.ref.SoftReference",
  78. "java.lang.ref.PhantomReference",
  79. "java.util.ArrayList",
  80. "java.util.HashSet",
  81. "java.util.LinkedHashSet",
  82. "java.util.LinkedList",
  83. "java.util.Stack",
  84. "java.util.TreeSet",
  85. "java.util.Vector",
  86. "java.util.Hashtable",
  87. "java.util.Hashtable$Entry",
  88. "java.util.HashMap",
  89. "java.util.HashMap$Entry",
  90. "java.util.IdentityHashMap",
  91. "java.util.AbstractMap$SimpleEntry",
  92. "java.util.TreeMap",
  93. "java.util.TreeMap$Entry",
  94. "java.util.WeakHashMap",
  95. "java.util.LinkedHashMap",
  96. "java.util.LinkedHashMap$Entry",
  97. "java.beans.PropertyChangeSupport"
  98. };
  99. }
  100. public String[] getSupportedAncestors () {
  101. return new String[] {
  102. };
  103. }
  104. /**
  105. * Returns filtered children for given parent on given indexes.
  106. *
  107. * @param original the original tree model
  108. * @throws NoInformationException if the set of children can not be
  109. * resolved
  110. * @throws ComputingException if the children resolving process
  111. * is time consuming, and will be performed off-line
  112. * @throws UnknownTypeException if this TreeModelFilter implementation is not
  113. * able to resolve dchildren for given node type
  114. *
  115. * @return children for given parent on given indexes
  116. */
  117. @Override
  118. public Object[] getChildren (
  119. TreeModel original,
  120. Variable variable,
  121. int from,
  122. int to
  123. ) throws UnknownTypeException {
  124. if (variable instanceof ObjectVariable) {
  125. ObjectVariable ov = (ObjectVariable) variable;
  126. JPDAClassType ct = ov.getClassType();
  127. if (ct == null) {
  128. return original.getChildren (variable, from, to);
  129. }
  130. if (isToArrayType (ct)) {
  131. try {
  132. ov = (ObjectVariable) ov.invokeMethod (
  133. "toArray",
  134. "()[Ljava/lang/Object;",
  135. new Variable [0]
  136. );
  137. if (ov == null) {
  138. return new Object[] {};
  139. }
  140. return original.getChildren(ov, from, to);
  141. } catch (NoSuchMethodException e) {
  142. Field elementData = ov.getField("elementData");
  143. if (elementData != null) {
  144. return original.getChildren(elementData, from, to);
  145. }
  146. } catch (InvalidExpressionException e) {
  147. // Not a supported operation (e.g. J2ME, see #45543)
  148. // Or missing context or any other reason
  149. Logger.getLogger(JavaVariablesFilter.class.getName()).fine("invokeMethod(toArray) "+e.getLocalizedMessage());
  150. return original.getChildren (variable, from, to);
  151. }
  152. }
  153. if (isMapMapType (ct)) {
  154. try {
  155. ov = (ObjectVariable) ov.invokeMethod (
  156. "entrySet",
  157. "()Ljava/util/Set;",
  158. new Variable [0]
  159. );
  160. if (ov != null) {
  161. ov = (ObjectVariable) ov.invokeMethod (
  162. "toArray",
  163. "()[Ljava/lang/Object;",
  164. new Variable [0]
  165. );
  166. if (ov != null) {
  167. return original.getChildren(ov, from, to);
  168. }
  169. }
  170. } catch (NoSuchMethodException e) {
  171. // Nothing to do. Return the original children.
  172. } catch (InvalidExpressionException e) {
  173. // Not a supported operation (e.g. J2ME, see #45543)
  174. // Or missing context or any other reason
  175. Logger.getLogger(JavaVariablesFilter.class.getName()).fine("invokeMethod(entrySet) "+e.getLocalizedMessage());
  176. }
  177. }
  178. if (isMapEntryType (ct)) {
  179. Field[] fs = new Field [2];
  180. // Read fields from AbstractMap.SimpleEntry
  181. fs [0] = ov.getField ("key");
  182. fs [1] = ov.getField ("value");
  183. if (fs[0] != null && fs[1] != null) {
  184. return fs;
  185. }
  186. // Otherwise some mistake in retrieval
  187. }
  188. if (isInstanceOf(ct, "java.lang.ref.Reference")) {
  189. Field[] fs = new Field [2];
  190. fs [0] = ov.getField ("referent");
  191. fs [1] = ov.getField("queue");
  192. if (fs[0] != null && fs[1] != null) {
  193. return fs;
  194. }
  195. // Otherwise some mistake in retrieval
  196. }
  197. String type = ct.getName();
  198. if ("java.beans.PropertyChangeSupport".equals(type)) {
  199. try {
  200. return ((ObjectVariable) ov.invokeMethod (
  201. "getPropertyChangeListeners",
  202. "()[Ljava/beans/PropertyChangeListener;",
  203. new Variable [0]
  204. )).getFields (from, to);
  205. } catch (InvalidExpressionException e) {
  206. // Not a supported operation (e.g. J2ME, see #45543)
  207. // Or missing context or any other reason
  208. Logger.getLogger(JavaVariablesFilter.class.getName()).fine("invokeMethod(getPropertyChangeListeners) "+e.getLocalizedMessage());
  209. } catch (NoSuchMethodException e) {
  210. Logger.getLogger(JavaVariablesFilter.class.getName()).fine("invokeMethod(getPropertyChangeListeners) "+e.getLocalizedMessage());
  211. }
  212. }
  213. }
  214. return original.getChildren (variable, from, to);
  215. }
  216. /**
  217. * Returns number of filtered children for given variable.
  218. *
  219. * @param original the original tree model
  220. * @param variable a variable of returned fields
  221. *
  222. * @throws NoInformationException if the set of children can not be
  223. * resolved
  224. * @throws ComputingException if the children resolving process
  225. * is time consuming, and will be performed off-line
  226. * @throws UnknownTypeException if this TreeModelFilter implementation is not
  227. * able to resolve dchildren for given node type
  228. *
  229. * @return number of filtered children for given variable
  230. */
  231. @Override
  232. public int getChildrenCount (TreeModel original, Variable variable)
  233. throws UnknownTypeException {
  234. return Integer.MAX_VALUE;
  235. }
  236. /**
  237. * Returns true if node is leaf.
  238. *
  239. * @param original the original tree model
  240. * @throws UnknownTypeException if this TreeModel implementation is not
  241. * able to resolve dchildren for given node type
  242. * @return true if node is leaf
  243. */
  244. @Override
  245. public boolean isLeaf (TreeModel original, Variable variable)
  246. throws UnknownTypeException {
  247. String type = variable.getType ();
  248. // PATCH for J2ME
  249. if ( isLeafType (type)
  250. ) return true;
  251. return original.isLeaf (variable);
  252. }
  253. @Override
  254. public Object getValueAt (
  255. TableModel original,
  256. Variable variable,
  257. String columnID
  258. ) throws UnknownTypeException {
  259. if (!(variable instanceof ObjectVariable)) {
  260. return original.getValueAt (variable, columnID);
  261. }
  262. String type = variable.getType ();
  263. ObjectVariable ov = (ObjectVariable) variable;
  264. if ( isMapEntryType (ov.getClassType()) &&
  265. ( columnID == Constants.LOCALS_VALUE_COLUMN_ID ||
  266. columnID == Constants.WATCH_VALUE_COLUMN_ID)
  267. ) {
  268. return ov.getField ("key").getValue () + "=>" +
  269. ov.getField ("value").getValue ();
  270. }
  271. if ( isGetValueType (type) &&
  272. ( columnID == Constants.LOCALS_VALUE_COLUMN_ID ||
  273. columnID == Constants.WATCH_VALUE_COLUMN_ID)
  274. ) {
  275. return ov.getField ("value").getValue ();
  276. }
  277. if ( isToStringValueType (type) &&
  278. ( columnID == Constants.LOCALS_VALUE_COLUMN_ID ||
  279. columnID == Constants.WATCH_VALUE_COLUMN_ID)
  280. ) {
  281. try {
  282. return "\""+ov.getToStringValue ()+"\"";
  283. } catch (InvalidExpressionException ex) {
  284. // Not a supported operation (e.g. J2ME, see #45543)
  285. // Or missing context or any other reason
  286. Logger.getLogger(JavaVariablesFilter.class.getName()).fine("getToStringValue() "+ex.getLocalizedMessage());
  287. if ( (ex.getTargetException () != null) &&
  288. (ex.getTargetException () instanceof
  289. UnsupportedOperationException)
  290. ) {
  291. // PATCH for J2ME. see 45543
  292. return original.getValueAt (variable, columnID);
  293. }
  294. return ex.getLocalizedMessage ();
  295. }
  296. }
  297. return original.getValueAt (variable, columnID);
  298. }
  299. @Override
  300. public void setValueAt(TableModel original, Variable variable,
  301. String columnID, Object value) throws UnknownTypeException {
  302. String type = variable.getType();
  303. if (isToStringValueType(type) &&
  304. (columnID == Constants.LOCALS_VALUE_COLUMN_ID ||
  305. columnID == Constants.WATCH_VALUE_COLUMN_ID)) {
  306. String expression = (String) value;
  307. if (expression.startsWith("\"") && expression.endsWith("\"") && expression.length() > 1) {
  308. // Create a new StringBuffer object with the desired content:
  309. expression = "new " + type + "(\"" + convertToStringInitializer(expression.substring(1, expression.length() - 1)) + "\")";
  310. original.setValueAt(variable, columnID, expression);
  311. return ;
  312. }
  313. }
  314. original.setValueAt(variable, columnID, value);
  315. }
  316. private static String convertToStringInitializer (String s) {
  317. StringBuffer sb = new StringBuffer ();
  318. int i, k = s.length ();
  319. for (i = 0; i < k; i++)
  320. switch (s.charAt (i)) {
  321. case '\b':
  322. sb.append ("\\b");
  323. break;
  324. case '\f':
  325. sb.append ("\\f");
  326. break;
  327. case '\\':
  328. sb.append ("\\\\");
  329. break;
  330. case '\t':
  331. sb.append ("\\t");
  332. break;
  333. case '\r':
  334. sb.append ("\\r");
  335. break;
  336. case '\n':
  337. sb.append ("\\n");
  338. break;
  339. case '\"':
  340. sb.append ("\\\"");
  341. break;
  342. default:
  343. sb.append (s.charAt (i));
  344. }
  345. return sb.toString();
  346. }
  347. // other methods ...........................................................
  348. private static HashSet getValueType;
  349. private static boolean isGetValueType (String type) {
  350. if (getValueType == null) {
  351. getValueType = new HashSet ();
  352. getValueType.add ("java.lang.Character");
  353. getValueType.add ("java.lang.Integer");
  354. getValueType.add ("java.lang.Float");
  355. getValueType.add ("java.lang.Byte");
  356. getValueType.add ("java.lang.Boolean");
  357. getValueType.add ("java.lang.Double");
  358. getValueType.add ("java.lang.Long");
  359. getValueType.add ("java.lang.Short");
  360. }
  361. return getValueType.contains (type);
  362. }
  363. private static HashSet leafType;
  364. private static boolean isLeafType (String type) {
  365. if (leafType == null) {
  366. leafType = new HashSet ();
  367. leafType.add ("java.lang.String");
  368. leafType.add ("java.lang.Character");
  369. leafType.add ("java.lang.Integer");
  370. leafType.add ("java.lang.Float");
  371. leafType.add ("java.lang.Byte");
  372. leafType.add ("java.lang.Boolean");
  373. leafType.add ("java.lang.Double");
  374. leafType.add ("java.lang.Long");
  375. leafType.add ("java.lang.Short");
  376. }
  377. return leafType.contains (type);
  378. }
  379. private static HashSet toStringValueType;
  380. private static boolean isToStringValueType (String type) {
  381. if (toStringValueType == null) {
  382. toStringValueType = new HashSet ();
  383. toStringValueType.add ("java.lang.StringBuffer");
  384. toStringValueType.add ("java.lang.StringBuilder");
  385. }
  386. return toStringValueType.contains (type);
  387. }
  388. private static boolean isToArrayType(JPDAClassType ct) {
  389. // Instanceof Collection
  390. return isInstanceOf(ct, "java.util.Collection");
  391. }
  392. private static boolean isMapMapType (JPDAClassType ct) {
  393. // Instanceof Map
  394. return isInstanceOf(ct, "java.util.Map");
  395. }
  396. private static boolean isMapEntryType (JPDAClassType ct) {
  397. // Instanceof Map.Entry
  398. return isInstanceOf(ct, "java.util.Map$Entry");
  399. }
  400. private static boolean isInstanceOf(JPDAClassType ct, String className) {
  401. if (ct == null) return false;
  402. try {
  403. java.lang.reflect.Method isInstanceOfMethod = ct.getClass().getMethod("isInstanceOf", String.class);
  404. return (Boolean) isInstanceOfMethod.invoke(ct, className);
  405. } catch (Exception ex) {
  406. Exceptions.printStackTrace(ex);
  407. return false;
  408. }
  409. }
  410. }