247 lines · 7.1 KB · Java
RawDownload
/* * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.example.debug.gui; import java.io.*;import java.util.*; import com.sun.jdi.*;import com.sun.jdi.request.*; import javax.swing.*; /** * Represents and manages one source file. * Caches source lines.  Holds other source file info. */public class SourceModel extends AbstractListModel {     private File path;     boolean isActuallySource = true;     private List<ReferenceType> classes = new ArrayList<ReferenceType>();     private Environment env;     // Cached line-by-line access.     //### Unify this with source model used in source view?    //### What is our cache-management policy for these?    //### Even with weak refs, we won't discard any part of the    //### source if the SourceModel object is reachable.    /**     * List of Line.     */    private List<Line> sourceLines = null;     public static class Line {        public String text;        public boolean hasBreakpoint = false;        public ReferenceType refType = null;        Line(String text) {            this.text = text;        }        public boolean isExecutable() {            return refType != null;        }        public boolean hasBreakpoint() {            return hasBreakpoint;        }    };     // 132 characters long, all printable characters.    public static final Line prototypeCellValue = new Line(                                        "abcdefghijklmnopqrstuvwxyz" +                                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +                                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +                                        "1234567890~!@#$%^&*()_+{}|" +                                        ":<>?`-=[];',.XXXXXXXXXXXX/\\\"");     SourceModel(Environment env, File path) {        this.env = env;        this.path = path;    }     public SourceModel(String message) {        this.path = null;        setMessage(message);    }     private void setMessage(String message) {        isActuallySource = false;        sourceLines = new ArrayList<Line>();        sourceLines.add(new Line(message));    }     // **** Implement ListModel  *****     @Override    public Object getElementAt(int index) {        if (sourceLines == null) {            initialize();        }        return sourceLines.get(index);    }     @Override    public int getSize() {        if (sourceLines == null) {            initialize();        }        return sourceLines.size();    }     // ***** Other functionality *****     public File fileName() {        return path;    }     public BufferedReader sourceReader() throws IOException {        return new BufferedReader(new FileReader(path));    }     public Line line(int lineNo) {        if (sourceLines == null) {            initialize();        }        int index = lineNo - 1; // list is 0-indexed        if (index >= sourceLines.size() || index < 0) {            return null;        } else {            return sourceLines.get(index);        }    }     public String sourceLine(int lineNo) {        Line line = line(lineNo);        if (line == null) {            return null;        } else {            return line.text;        }    }     void addClass(ReferenceType refType) {        // Logically is Set        if (classes.indexOf(refType) == -1) {            classes.add(refType);            if (sourceLines != null) {                markClassLines(refType);            }        }    }     /**     * @return List of currently known {@link com.sun.jdi.ReferenceType}     * in this source file.     */    public List<ReferenceType> referenceTypes() {        return Collections.unmodifiableList(classes);    }     private void initialize() {        try {            rawInit();        } catch (IOException exc) {            setMessage("[Error reading source code]");        }    }     public void showBreakpoint(int ln, boolean hasBreakpoint) {        line(ln).hasBreakpoint = hasBreakpoint;        fireContentsChanged(this, ln, ln);    }     public void showExecutable(int ln, ReferenceType refType) {        line(ln).refType = refType;        fireContentsChanged(this, ln, ln);    }     /**     * Mark executable lines and breakpoints, but only     * when sourceLines is set.     */    private void markClassLines(ReferenceType refType) {        for (Method meth : refType.methods()) {            try {                for (Location loc : meth.allLineLocations()) {                    showExecutable(loc.lineNumber(), refType);                }            } catch (AbsentInformationException exc) {                // do nothing            }        }        for (BreakpointRequest bp :                 env.getExecutionManager().eventRequestManager().breakpointRequests()) {            if (bp.location() != null) {                Location loc = bp.location();                if (loc.declaringType().equals(refType)) {                    showBreakpoint(loc.lineNumber(),true);                }            }        }    }     private void rawInit() throws IOException {        sourceLines = new ArrayList<Line>();        BufferedReader reader = sourceReader();        try {            String line = reader.readLine();            while (line != null) {                sourceLines.add(new Line(expandTabs(line)));                line = reader.readLine();            }        } finally {            reader.close();        }        for (ReferenceType refType : classes) {            markClassLines(refType);        }    }     private String expandTabs(String s) {        int col = 0;        int len = s.length();        StringBuffer sb = new StringBuffer(132);        for (int i = 0; i < len; i++) {            char c = s.charAt(i);            sb.append(c);            if (c == '\t') {                int pad = (8 - (col % 8));                for (int j = 0; j < pad; j++) {                    sb.append(' ');                }                col += pad;            } else {                col++;            }        }        return sb.toString();    } }