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.netbeans.insane.model;
043:
044: import java.io.*;
045: import java.util.*;
046: import javax.xml.parsers.SAXParser;
047: import javax.xml.parsers.SAXParserFactory;
048: import org.xml.sax.*;
049: import org.xml.sax.helpers.DefaultHandler;
050:
051: /**
052: * An implementation of the heap model that parses SimpleXmlVisitor output
053: * and keeps all the data in memory.
054: *
055: * @author Nenik
056: */
057: class XmlHeapModel implements org.netbeans.insane.model.HeapModel {
058:
059: public static HeapModel parse(File file) throws Exception {
060: HeapModel model = new XmlHeapModel(new InputSource(
061: new FileInputStream(file)));
062: return model;
063: }
064:
065: private Map<Integer, Item> items = new HashMap<Integer, Item>();
066: private Map<String, Item> roots = new HashMap<String, Item>();
067:
068: // HeapModel interface implementation
069: public Iterator<Item> getAllItems() {
070: return Collections.unmodifiableCollection(items.values())
071: .iterator();
072: }
073:
074: public Collection<Item> getObjectsOfType(String type) {
075: Collection<Item> filter = new ArrayList<Item>();
076: for (Iterator<Item> it = getAllItems(); it.hasNext();) {
077: Item act = it.next();
078: if (type.equals(act.getType()))
079: filter.add(act);
080: }
081: return filter;
082: }
083:
084: public Collection<String> getRoots() {
085: return Collections.unmodifiableSet(roots.keySet());
086: }
087:
088: public Item getObjectAt(String staticRefName) {
089: return roots.get(staticRefName);
090: }
091:
092: public Item getItem(int id) {
093: Item itm = items.get(new java.lang.Integer(id));
094: if (itm == null)
095: throw new IllegalArgumentException("Bad ID");
096: return itm;
097: }
098:
099: static class MemItem implements Item {
100: // a list of Items, Strings and one null
101: private Object[] refs = new Object[] { null };
102: private int id;
103: private int size;
104: private String type;
105: private String value;
106:
107: MemItem(int id, String type, int size, String value) {
108: this .id = id;
109: this .type = type.intern();
110: this .size = size;
111: this .value = value;
112: }
113:
114: // Item interface implementation
115: public String getType() {
116: return type;
117: }
118:
119: public int getSize() {
120: return size;
121: }
122:
123: public String getValue() {
124: return value;
125: }
126:
127: public Enumeration<Object> incomming() {
128: return new RefEnum(true, refs);
129: }
130:
131: public Enumeration<Item> outgoing() {
132: return new RefEnum(false, refs);
133: }
134:
135: public int getId() {
136: return id;
137: }
138:
139: // debug helper
140: public String toString() {
141: if (value == null) {
142: return type + "@" + Integer.toHexString(id);
143: } else {
144: return type + "@" + Integer.toHexString(id) + ": \""
145: + value + '"';
146: }
147: }
148:
149: // parsing impl
150: void addIncomming(Object incomming) {
151: Object[] nr = new Object[refs.length + 1];
152: nr[0] = incomming;
153: System.arraycopy(refs, 0, nr, 1, refs.length);
154: refs = nr;
155: }
156:
157: void addOutgoing(Object outgoing) {
158: Object[] nr = new Object[refs.length + 1];
159: nr[refs.length] = outgoing;
160: System.arraycopy(refs, 0, nr, 0, refs.length);
161: refs = nr;
162: }
163: }
164:
165: //parser implementation
166:
167: private XmlHeapModel(InputSource is) throws Exception {
168: Handler h = new Handler();
169: SAXParserFactory fact = SAXParserFactory.newInstance();
170: SAXParser parser = fact.newSAXParser();
171: parser.getXMLReader().setContentHandler(h);
172: parser.getXMLReader().parse(is);
173: }
174:
175: Item createItem(int id, String type, int size, String val) {
176: Item item = new MemItem(id, type, size, val);
177: items.put(new Integer(id), item);
178: return item;
179: }
180:
181: void addReference(int from, int to) {
182: MemItem f = (MemItem) getItem(from);
183: MemItem t = (MemItem) getItem(to);
184: f.addOutgoing(t);
185: t.addIncomming(f);
186: }
187:
188: void addReference(String stat, int to) {
189: MemItem t = (MemItem) getItem(to);
190: t.addIncomming(stat);
191: }
192:
193: private class Handler extends DefaultHandler {
194: private int depth = 0;
195:
196: public void startElement(String namespaceURI, String localName,
197: String qName, Attributes atts) throws SAXException {
198: if (depth == 0) {
199: if (!"insane".equals(qName))
200: throw new SAXException("format");
201: } else if (depth != 1) {
202: throw new SAXException("format");
203: } else {
204: if ("object".equals(qName)) {
205: String id = atts.getValue("id");
206: String type = atts.getValue("type");
207: String size = atts.getValue("size");
208: String val = atts.getValue("value");
209: createItem(getIdFromString(id), type, Integer
210: .parseInt(size), val);
211: } else if ("ref".equals(qName)) {
212: String from = atts.getValue("from");
213: String name = atts.getValue("name");
214: String to = atts.getValue("to");
215: // if (! "java.lang.ref.Reference.referent".equals(name)) {
216: if (from != null) {
217: addReference(getIdFromString(from),
218: getIdFromString(to));
219: } else {
220: addReference(name, getIdFromString(to));
221: }
222: // }
223: } else {
224: throw new SAXException("format");
225: }
226: }
227: depth++;
228: }
229:
230: public void endElement(String namespaceURI, String localName,
231: String qName) throws SAXException {
232: depth--;
233: }
234: }
235:
236: int getIdFromString(String s) {
237: return Integer.parseInt(s, 16);
238: }
239:
240: // An enumeration over object array, enumeration either pre-null items
241: // or post-null items
242: private static class RefEnum implements Enumeration {
243: int ptr;
244: Object[] items;
245:
246: RefEnum(boolean first, Object[] data) {
247: items = data;
248: if (!first)
249: while (data[ptr++] != null)
250: ;
251: }
252:
253: public boolean hasMoreElements() {
254: return ptr < items.length && items[ptr] != null;
255: }
256:
257: public Object nextElement() {
258: if (hasMoreElements())
259: return items[ptr++];
260: throw new NoSuchElementException();
261: }
262: }
263:
264: }
|