001    package EVolve;
002    
003    /* EVolve - an Extensible Software Visualization Framework
004     * Copyright (C) 2001-2002 Qin Wang
005     *
006     * This library is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Library General Public
008     * License as published by the Free Software Foundation; either
009     * version 2 of the License, or (at your option) any later version.
010     *
011     * This library is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Library General Public License for more details.
015     *
016     * You should have received a copy of the GNU Library General Public
017     * License along with this library; if not, write to the
018     * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
019     * Boston, MA 02111-1307, USA.
020     */
021    
022    /*
023     * EVolve is distributed at http://www.sable.mcgill.ca/EVolve/
024     */
025    
026    import java.io.IOException;
027    import java.io.RandomAccessFile;
028    import java.util.TreeMap;
029    import javax.swing.JFileChooser;
030    import EVolve.data.DataSource;
031    import EVolve.data.ElementDefinition;
032    import EVolve.data.Entity;
033    import EVolve.data.EntityBuilder;
034    import EVolve.data.Event;
035    import EVolve.data.EventBuilder;
036    import EVolve.data.FieldDefinition;
037    import EVolve.data.NumericStringComparator;
038    import EVolve.exceptions.CancelLoadDataException;
039    import EVolve.exceptions.DataProcessingException;
040    import EVolve.exceptions.EVolveException;
041    
042    public class DemoSource implements DataSource {
043        private final String dsourceName = "DemoSource";
044        private String fn = null; // data file name
045    
046        private RandomAccessFile file;
047    
048        private EntityBuilder classBuilder;
049    
050        private EntityBuilder threadBuilder;
051    
052        private EntityBuilder methodBuilder;
053        private FieldDefinition methodDefiningClass;
054    
055        private EntityBuilder locationBuilder;
056    
057        private EntityBuilder sizeBuilder;
058    
059        private EventBuilder allocationBuilder;
060        private FieldDefinition allocationObjectCount;
061        private FieldDefinition allocationObjectSize;
062        private FieldDefinition allocationBytecode;
063        private FieldDefinition allocationObjectType;
064        private FieldDefinition allocationThread;
065        private FieldDefinition allocationMethod;
066        private FieldDefinition allocationLocation;
067        private FieldDefinition allocationSize;
068        private FieldDefinition allocationFieldSum;
069        private FieldDefinition allocationFieldCounter;
070    
071        private EventBuilder invocationBuilder;
072        private FieldDefinition invocationNumber;
073        private FieldDefinition invocationBytecode;
074        private FieldDefinition invocationThread;
075        private FieldDefinition invocationMethod;
076        private FieldDefinition invocationLocation;
077        private FieldDefinition invocationFieldCounter;
078    
079    
080        private ElementDefinition[] definition;
081        private int definitionCounter;
082    
083        private TreeMap classMap;
084        private TreeMap threadMap;
085        private TreeMap methodMap;
086        private TreeMap locationMap;
087        private TreeMap sizeMap;
088    
089        private long counter[];
090    
091        public void init() throws EVolveException {
092            String lastName = fn;
093    
094            fn = Scene.getDataFileName();
095            if (fn == null) {
096                JFileChooser fc = new JFileChooser(Scene.getUIManager().getLastDataDir());
097                if (fc.showOpenDialog(Scene.getFrame()) == JFileChooser.APPROVE_OPTION) {
098                    try {
099                        file = new RandomAccessFile(fc.getSelectedFile(), "r");
100                        fn = fc.getSelectedFile().getName();
101                        Scene.setDataFilename(fc.getSelectedFile().getPath());
102                        Scene.getUIManager().setLastDataDir(fc.getSelectedFile().getPath());
103                        Scene.setDataFilename(null);
104                    } catch (IOException e) {
105                        throw new DataProcessingException("IO exception occurred when access data file.");
106                    }
107                } else {
108                    fn = lastName;
109                    throw new CancelLoadDataException();
110                }
111            } else {
112                try {
113                    file = new RandomAccessFile(fn, "r");
114                } catch (IOException e) {
115                    throw new DataProcessingException("File loading failed.");
116                }
117            }
118    
119        }
120    
121        public void startBuildDefinition() throws DataProcessingException {
122            String[] propertySum = {"time","sum"};
123            String[] propertyCount = {"time","count"};
124            String[] propertyAmount = {"amount"};
125            String[] propertyCoordinate = {"time","coordinate"};
126            String[] propertyThread = {"reference","thread"};
127    
128            definition = new ElementDefinition[7];
129    
130            classBuilder = new EntityBuilder("Class", "Class");
131            definition[0] = classBuilder.buildDefinition();
132    
133            threadBuilder = new EntityBuilder("Thread", "Thread");
134            definition[1] = threadBuilder.buildDefinition();
135    
136            methodBuilder = new EntityBuilder("Method", "Method");
137            methodDefiningClass = methodBuilder.buildReferenceDefinition("Defining Class", classBuilder, null, "Defining class of the method");
138            definition[2] = methodBuilder.buildDefinition();
139    
140            locationBuilder = new EntityBuilder("Location", "Location in Method");
141            definition[3] = locationBuilder.buildDefinition();
142    
143            sizeBuilder = new EntityBuilder("Size", "Object Size");
144            sizeBuilder.addComparator(new NumericStringComparator());
145            definition[4] = sizeBuilder.buildDefinition();
146    
147            allocationBuilder = new EventBuilder("Object Allocation", "Object allocation event");
148            allocationFieldSum = allocationBuilder.buildValueDefinition("Memory Allocated", propertySum, "Size of memory allocated");
149            allocationFieldCounter = allocationBuilder.buildValueDefinition("Allocations", propertyCount, "Number of objects allocated");
150            allocationObjectCount = allocationBuilder.buildValueDefinition("Object Count", propertyAmount, "Number of objects allocated");
151            allocationObjectSize = allocationBuilder.buildValueDefinition("Memory Allocated", propertyAmount, "Size of memory allocated");
152            allocationBytecode = allocationBuilder.buildValueDefinition("Bytecode", propertyCoordinate, "Bytecode sequence");
153            allocationObjectType = allocationBuilder.buildReferenceDefinition("Object Type", classBuilder, null, "Type of the object");
154            allocationThread = allocationBuilder.buildReferenceDefinition("Thread", threadBuilder, propertyThread, "Thread in which the object is allocated");
155            allocationMethod = allocationBuilder.buildReferenceDefinition("Allocating Methods", methodBuilder, null, "Method that creates the object");
156            allocationLocation = allocationBuilder.buildReferenceDefinition("Allocating Locations", locationBuilder, null, "Location where the object is created");
157            allocationSize = allocationBuilder.buildReferenceDefinition("Allocation Size", sizeBuilder, null, "Allocation Size");
158            definition[5] = allocationBuilder.buildDefinition();
159    
160            invocationBuilder = new EventBuilder("Method Invocation", "Method invocation event");
161            invocationFieldCounter = invocationBuilder.buildValueDefinition("Invocations", propertyCount, "Total number of invocations");
162            invocationNumber = invocationBuilder.buildValueDefinition("Number of Invocations", propertyAmount, "Total number of invocations");
163            invocationBytecode = invocationBuilder.buildValueDefinition("Bytecode", propertyCoordinate, "Bytecode sequence");
164            invocationThread = invocationBuilder.buildReferenceDefinition("Thread", threadBuilder, propertyThread, "Thread in which the method is invoked");
165            invocationMethod = invocationBuilder.buildReferenceDefinition("Method", methodBuilder, null, "Method that is invoked");
166            invocationLocation = invocationBuilder.buildReferenceDefinition("Invoking Locations", locationBuilder, null, "Location where the method is invoked");
167            definition[6] = invocationBuilder.buildDefinition();
168    
169            definitionCounter = -1;
170            counter = new long[definition.length];
171            for (int i=0; i<counter.length; i++)
172                counter[i] = 0;
173        }
174    
175        public ElementDefinition getNextDefinition() throws DataProcessingException {
176            definitionCounter++;
177            if (definitionCounter < definition.length) {
178                return definition[definitionCounter];
179            } else {
180                return null;
181            }
182        }
183    
184        private String getSub(String line, int part) {
185            int start = line.indexOf(' ') + 1;
186            int i = 1;
187            while (i < part) {
188                start = line.indexOf(' ', start) + 1;
189                i++;
190            }
191            int end = line.indexOf(' ', start);
192            if (end == -1) {
193                return line.substring(start);
194            } else {
195                return line.substring(start, end);
196            }
197        }
198    
199        public void startBuildEntity() throws DataProcessingException {
200            try {
201                file.seek(0);
202    
203                classMap = new TreeMap();
204                threadMap = new TreeMap();
205                methodMap = new TreeMap();
206                locationMap = new TreeMap();
207                sizeMap = new TreeMap();
208            } catch (IOException e) {
209                throw new DataProcessingException("File processing failed.");
210            }
211        }
212    
213        public Entity getNextEntity() throws DataProcessingException {
214            try {
215                Entity returnVal = null;
216                String line = file.readLine();
217    
218                while ((returnVal == null) && (line != null) && (line.length()>0)) {
219                    line = line.trim();
220                    char ch = line.charAt(0);
221    
222                    if (ch == 'C') {
223                        classBuilder.newEntity(getSub(line, 1));
224                        returnVal = classBuilder.buildEntity();
225                        classMap.put(getSub(line, 2), returnVal);
226                    } else if (ch == 'T') {
227                        threadBuilder.newEntity(getSub(line, 1));
228                        returnVal = threadBuilder.buildEntity();
229                        threadMap.put(getSub(line, 2), returnVal);
230                    } else if (ch == 'M') {
231                        methodBuilder.newEntity(getSub(line, 1));
232                        methodBuilder.addReferenceField(methodDefiningClass, (Entity)(classMap.get(getSub(line, 3))));
233                        returnVal = methodBuilder.buildEntity();
234                        methodMap.put(getSub(line, 2), returnVal);
235                    } else if (ch == 'L') {
236                        locationBuilder.newEntity(getSub(line, 1));
237                        returnVal = locationBuilder.buildEntity();
238                        locationMap.put(getSub(line, 2), returnVal);
239                    } else if (ch == 'O') {
240                        String size = getSub(line, 6);
241                        if (!sizeMap.containsKey(size)) {
242                            sizeBuilder.newEntity(size);
243                            returnVal = sizeBuilder.buildEntity();
244                            sizeMap.put(size, returnVal);
245                        }
246                        counter[5]++;
247                    } else if (ch == '+') {
248                        counter[6]+=2;
249                    }
250    
251                    if (returnVal == null) {
252                        line = file.readLine();
253                    }
254                }
255    
256                return returnVal;
257            } catch (IOException e) {
258                throw new DataProcessingException("File processing failed.");
259            }
260        }
261    
262        public void startBuildEvent() throws DataProcessingException {
263            try {
264                file.seek(0);
265            } catch (IOException e) {
266                throw new DataProcessingException("File processing failed.");
267            }
268        }
269    
270        public Event getNextEvent() throws DataProcessingException {
271            try {
272                Event returnVal = null;
273                String line = file.readLine();
274    
275                while ((returnVal == null) && (line != null)) {
276                    line = line.trim();
277                    char ch = line.charAt(0);
278    
279                    if (ch == 'O') {
280                        allocationBuilder.newEvent();
281                        String size = getSub(line, 6);
282                        allocationBuilder.addValueField(allocationObjectCount, 1);
283                        allocationBuilder.addValueField(allocationObjectSize, Integer.parseInt(getSub(line, 6)));
284                        allocationBuilder.addValueField(allocationFieldCounter, 1);
285                        allocationBuilder.addValueField(allocationFieldSum, Integer.parseInt(getSub(line, 6)));
286                        allocationBuilder.addValueField(allocationBytecode, Integer.parseInt(getSub(line, 1)));
287                        allocationBuilder.addReferenceField(allocationObjectType, (Entity)(classMap.get(getSub(line, 5))));
288                        allocationBuilder.addReferenceField(allocationThread, (Entity)(threadMap.get(getSub(line, 2))));
289                        allocationBuilder.addReferenceField(allocationMethod, (Entity)(methodMap.get(getSub(line, 3))));
290                        allocationBuilder.addReferenceField(allocationLocation, (Entity)(locationMap.get(getSub(line, 4))));
291                        allocationBuilder.addReferenceField(allocationSize, (Entity)(sizeMap.get(size)));
292                        returnVal = allocationBuilder.buildEvent();
293                    } else if (ch == '+') {
294                        invocationBuilder.newEvent();
295                        invocationBuilder.addValueField(invocationNumber, 1);
296                        invocationBuilder.addValueField(invocationFieldCounter, 1);
297                        invocationBuilder.addValueField(invocationBytecode, Integer.parseInt(getSub(line, 1)));
298                        invocationBuilder.addReferenceField(invocationThread, (Entity)(threadMap.get(getSub(line, 2))));
299                        invocationBuilder.addReferenceField(invocationMethod, (Entity)(methodMap.get(getSub(line, 3))));
300                        invocationBuilder.addReferenceField(invocationLocation, (Entity)(locationMap.get(getSub(line, 4))));
301                        returnVal = invocationBuilder.buildEvent();
302                    } else if (ch == '-') {
303                        invocationBuilder.newEvent(true);
304                        invocationBuilder.addValueField(invocationNumber, 1);
305                        invocationBuilder.addValueField(invocationBytecode, Integer.parseInt(getSub(line, 1)));
306                        invocationBuilder.addReferenceField(invocationThread, (Entity)(threadMap.get(getSub(line, 2))));
307                        invocationBuilder.addReferenceField(invocationMethod, (Entity)(methodMap.get(getSub(line, 3))));
308                        invocationBuilder.addReferenceField(invocationLocation, (Entity)(locationMap.get(getSub(line, 4))));
309                        returnVal = invocationBuilder.buildEvent();
310                    }
311    
312                    if (returnVal == null) {
313                        line = file.readLine();
314                    }
315                }
316    
317                return returnVal;
318            } catch (IOException e) {
319                throw new DataProcessingException("File processing failed.");
320            }
321        }
322    
323        public String getName() {
324            return dsourceName;
325        }
326    
327        public String getFileName() {
328            return fn;
329        }
330    
331        public long getTotalNumberOfEvents() {
332            long total = 0;
333    
334            for (int i=0; i<definition.length; i++)
335                total = total + counter[i];
336    
337            return total;
338        }
339    
340        public long getNumberOfEvents(String definitionName) {
341            long number = 0;
342    
343            for (int i=0; i<definition.length; i++) {
344                if (definition[i].getName().equals(definitionName)) {
345                    number = counter[i];
346                    if (definitionName.equals("Method Invocation")) number = number/2;
347                    break;
348                }
349            }
350    
351            return number;
352        }
353    }