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