view j2se/src/share/classes/com/sun/tools/example/debug/gui/SourceModel.java @ 1:193df1943809 trunk

[svn] Load openjdk/jdk7/b13 into jdk/trunk.
author xiomara
date Fri, 25 May 2007 00:49:14 +0000
parents a4ed3fb96592
children
line wrap: on
line source

/*
 * Copyright 1998-1999 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.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 com.sun.tools.example.debug.bdi.*;

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  *****

    public Object getElementAt(int index) {
        if (sourceLines == null) {
            initialize();
        }
        return sourceLines.get(index);
    }

    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) {
        List methods = refType.methods();
        for (Iterator mit = methods.iterator(); mit.hasNext();) {
            Method meth = (Method)mit.next();
            try {
                List lines = meth.allLineLocations();
                for (Iterator lit = lines.iterator(); lit.hasNext();) {
                    Location loc = (Location)lit.next();
                    showExecutable(loc.lineNumber(), refType);
                }       
            } catch (AbsentInformationException exc) {
                // do nothing
            }
        }             
        List bps = env.getExecutionManager().eventRequestManager().breakpointRequests();
        for (Iterator it = bps.iterator(); it.hasNext();) {
            BreakpointRequest bp = (BreakpointRequest)it.next();
            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 (Iterator it = classes.iterator(); it.hasNext();) {
            markClassLines((ClassType)it.next());
        }
    }

    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();
    }

}