/*
 * Copyright 2000-2003 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.jdi;

import com.sun.jdi.*;

import java.util.List;
import java.util.Map;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Collections;
import java.lang.ref.SoftReference;

/**
 * Represents methods with method bodies.
 * That is, non-native non-abstract methods.
 * Private to MethodImpl.
 */
public class ConcreteMethodImpl extends MethodImpl {

    /*
     * A subset of the line number info that is softly cached
     */
    static private class SoftLocationXRefs {
        final String stratumID;   // The stratum of this information
        final Map<Integer, List<Location>> lineMapper;     // Maps line number to location(s)
        final List<Location> lineLocations; // List of locations ordered by code index

        /*
         * Note: these do not necessarily correspond to
         * the line numbers of the first and last elements
         * in the lineLocations list. Use these only for bounds
         * checking and with lineMapper.
         */
        final int lowestLine;
        final int highestLine;

        SoftLocationXRefs(String stratumID, Map<Integer, List<Location>> lineMapper, List<Location> lineLocations,
                     int lowestLine, int highestLine) {
            this.stratumID = stratumID;
            this.lineMapper = Collections.unmodifiableMap(lineMapper);
            this.lineLocations =
                Collections.unmodifiableList(lineLocations);
            this.lowestLine = lowestLine;
            this.highestLine = highestLine;
        }
    }

    private Location location = null;
    private SoftReference<SoftLocationXRefs> softBaseLocationXRefsRef;
    private SoftReference<SoftLocationXRefs> softOtherLocationXRefsRef;
    private SoftReference<List<LocalVariable>> variablesRef = null;
    private boolean absentVariableInformation = false;
    private long firstIndex = -1;
    private long lastIndex = -1;
    private SoftReference<byte[]> bytecodesRef = null;
    private int argSlotCount = -1;

    ConcreteMethodImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,
                       long ref,
                       String name, String signature,
                       String genericSignature, int modifiers) {

        // The generic signature is set when this is created
        super(vm, declaringType, ref, name, signature,
              genericSignature, modifiers);
    }

    public Location location() {
        if (location == null) {
            getBaseLocations();
        }
        return location;
    }

    List<Location> sourceNameFilter(List<Location> list,
                          SDE.Stratum stratum,
                          String sourceName)
                            throws AbsentInformationException {
        if (sourceName == null) {
            return list;
        } else {
            /* needs sourceName filteration */
            List<Location> locs = new ArrayList<Location>();
            for (Location loc : list) {
                if (((LocationImpl)loc).sourceName(stratum).equals(sourceName)) {
                    locs.add(loc);
                }
            }
            return locs;
        }
    }

    List<Location> allLineLocations(SDE.Stratum stratum,
                          String sourceName)
                            throws AbsentInformationException {
        List<Location> lineLocations = getLocations(stratum).lineLocations;

        if (lineLocations.size() == 0) {
            throw new AbsentInformationException();
        }

        return Collections.unmodifiableList(
          sourceNameFilter(lineLocations, stratum, sourceName));
    }

    List<Location> locationsOfLine(SDE.Stratum stratum,
                         String sourceName,
                         int lineNumber)
                            throws AbsentInformationException {
        SoftLocationXRefs info = getLocations(stratum);

        if (info.lineLocations.size() == 0) {
            throw new AbsentInformationException();
        }

        /*
         * Find the locations which match the line number
         * passed in.
         */
        List<Location> list = info.lineMapper.get(new Integer(lineNumber));

        if (list == null) {
            list = new ArrayList<Location>(0);
        }
        return Collections.unmodifiableList(
          sourceNameFilter(list, stratum, sourceName));
    }


    public Location locationOfCodeIndex(long codeIndex) {
        if (firstIndex == -1) {
            getBaseLocations();
        }

        /*
         * Check for invalid code index.
         */
        if (codeIndex < firstIndex || codeIndex > lastIndex) {
            return null;
        }

        return new LocationImpl(virtualMachine(), this, codeIndex);
    }


    LineInfo codeIndexToLineInfo(SDE.Stratum stratum,
                                 long codeIndex) {
        if (firstIndex == -1) {
            getBaseLocations();
        }

        /*
         * Check for invalid code index.
         */
        if (codeIndex < firstIndex || codeIndex > lastIndex) {
            throw new InternalError(
                    "Location with invalid code index");
        }

        List<Location> lineLocations = getLocations(stratum).lineLocations;

        /*
         * Check for absent line numbers.
         */
        if (lineLocations.size() == 0) {
            return super.codeIndexToLineInfo(stratum, codeIndex);
        }

        Iterator iter = lineLocations.iterator();
        /*
         * Treat code before the beginning of the first line table
         * entry as part of the first line.  javac will generate
         * code like this for some local classes. This "prolog"
         * code contains assignments from locals in the enclosing
         * scope to synthetic fields in the local class.  Same for
         * other language prolog code.
         */
        LocationImpl bestMatch = (LocationImpl)iter.next();
        while (iter.hasNext()) {
            LocationImpl current = (LocationImpl)iter.next();
            if (current.codeIndex() > codeIndex) {
                break;
            }
            bestMatch = current;
        }
        return bestMatch.getLineInfo(stratum);
    }


    public List<LocalVariable> variables() throws AbsentInformationException {
        return getVariables();
    }

    public List<LocalVariable> variablesByName(String name) throws AbsentInformationException {
        List<LocalVariable> variables = getVariables();

        List<LocalVariable> retList = new ArrayList<LocalVariable>(2);
        Iterator iter = variables.iterator();
        while(iter.hasNext()) {
            LocalVariable variable = (LocalVariable)iter.next();
            if (variable.name().equals(name)) {
                retList.add(variable);
            }
        }
        return retList;
    }

    public List<LocalVariable> arguments() throws AbsentInformationException {
        List<LocalVariable> variables = getVariables();

        List<LocalVariable> retList = new ArrayList<LocalVariable>(variables.size());
        Iterator iter = variables.iterator();
        while(iter.hasNext()) {
            LocalVariable variable = (LocalVariable)iter.next();
            if (variable.isArgument()) {
                retList.add(variable);
            }
        }
        return retList;
    }

    public byte[] bytecodes() {
        byte[] bytecodes = (bytecodesRef == null) ? null :
                                     (byte[])bytecodesRef.get();
        if (bytecodes == null) {
            try {
                bytecodes = JDWP.Method.Bytecodes.
                                 process(vm, declaringType, ref).bytes;
            } catch (JDWPException exc) {
                throw exc.toJDIException();
            }
            bytecodesRef = new SoftReference<byte[]>(bytecodes);
        }
        /*
         * Arrays are always modifiable, so it is a little unsafe
         * to return the cached bytecodes directly; instead, we
         * make a clone at the cost of using more memory.
         */
        return (byte[])bytecodes.clone();
    }

    int argSlotCount() throws AbsentInformationException {
        if (argSlotCount == -1) {
            getVariables();
        }
        return argSlotCount;
    }

    private SoftLocationXRefs getLocations(SDE.Stratum stratum) {
        if (stratum.isJava()) {
            return getBaseLocations();
        }
        String stratumID = stratum.id();
        SoftLocationXRefs info =
            (softOtherLocationXRefsRef == null) ? null :
               (SoftLocationXRefs)softOtherLocationXRefsRef.get();
        if (info != null && info.stratumID.equals(stratumID)) {
            return info;
        }

        List<Location> lineLocations = new ArrayList<Location>();
        Map<Integer, List<Location>> lineMapper = new HashMap<Integer, List<Location>>();
        int lowestLine = -1;
        int highestLine = -1;
        SDE.LineStratum lastLineStratum = null;
        SDE.Stratum baseStratum =
            declaringType.stratum(SDE.BASE_STRATUM_NAME);
        Iterator it = getBaseLocations().lineLocations.iterator();
        while(it.hasNext()) {
            LocationImpl loc = (LocationImpl)it.next();
            int baseLineNumber = loc.lineNumber(baseStratum);
            SDE.LineStratum lineStratum =
                  stratum.lineStratum(declaringType,
                                      baseLineNumber);

            if (lineStratum == null) {
                // location not mapped in this stratum
                continue;
            }

            int lineNumber = lineStratum.lineNumber();

            // remove unmapped and dup lines
            if ((lineNumber != -1) &&
                          (!lineStratum.equals(lastLineStratum))) {
                lastLineStratum = lineStratum;

                // Remember the largest/smallest line number
                if (lineNumber > highestLine) {
                    highestLine = lineNumber;
                }
                if ((lineNumber < lowestLine) || (lowestLine == -1)) {
                    lowestLine = lineNumber;
                }

                loc.addStratumLineInfo(
                  new StratumLineInfo(stratumID,
                                      lineNumber,
                                      lineStratum.sourceName(),
                                      lineStratum.sourcePath()));

                // Add to the location list
                lineLocations.add(loc);

                // Add to the line -> locations map
                Integer key = new Integer(lineNumber);
                List<Location> mappedLocs = lineMapper.get(key);
                if (mappedLocs == null) {
                    mappedLocs = new ArrayList<Location>(1);
                    lineMapper.put(key, mappedLocs);
                }
                mappedLocs.add(loc);
            }
        }

        info = new SoftLocationXRefs(stratumID,
                                lineMapper, lineLocations,
                                lowestLine, highestLine);
        softOtherLocationXRefsRef = new SoftReference<SoftLocationXRefs>(info);
        return info;
    }

    private SoftLocationXRefs getBaseLocations() {
        SoftLocationXRefs info = (softBaseLocationXRefsRef == null) ? null :
                                     (SoftLocationXRefs)softBaseLocationXRefsRef.get();
        if (info != null) {
            return info;
        }

        JDWP.Method.LineTable lntab = null;
        try {
            lntab = JDWP.Method.LineTable.process(vm, declaringType, ref);
        } catch (JDWPException exc) {
            /*
             * Note: the absent info error shouldn't happen here
             * because the first and last index are always available.
             */
            throw exc.toJDIException();
        }

        int count  = lntab.lines.length;

        List<Location> lineLocations = new ArrayList<Location>(count);
        Map<Integer, List<Location>>lineMapper = new HashMap<Integer, List<Location>>();
        int lowestLine = -1;
        int highestLine = -1;
        for (int i = 0; i < count; i++) {
            long bci = lntab.lines[i].lineCodeIndex;
            int lineNumber = lntab.lines[i].lineNumber;

            /*
             * Some compilers will point multiple consecutive
             * lines at the same location. We need to choose
             * one of them so that we can consistently map back
             * and forth between line and location. So we choose
             * to record only the last line entry at a particular
             * location.
             */
            if ((i + 1 == count) || (bci != lntab.lines[i+1].lineCodeIndex)) {
                // Remember the largest/smallest line number
                if (lineNumber > highestLine) {
                    highestLine = lineNumber;
                }
                if ((lineNumber < lowestLine) || (lowestLine == -1)) {
                    lowestLine = lineNumber;
                }
                LocationImpl loc =
                    new LocationImpl(virtualMachine(), this, bci);
                loc.addBaseLineInfo(
                    new BaseLineInfo(lineNumber, declaringType));

                // Add to the location list
                lineLocations.add(loc);

                // Add to the line -> locations map
                Integer key = new Integer(lineNumber);
                List<Location> mappedLocs = lineMapper.get(key);
                if (mappedLocs == null) {
                    mappedLocs = new ArrayList<Location>(1);
                    lineMapper.put(key, mappedLocs);
                }
                mappedLocs.add(loc);
            }
        }

        /*
         * firstIndex, lastIndex, and startLocation need to be
         * retrieved only once since they are strongly referenced.
         */
        if (location == null) {
            firstIndex = lntab.start;
            lastIndex = lntab.end;
            /*
             * The startLocation is the first one in the
             * location list if we have one;
             * otherwise, we construct a location for a
             * method start with no line info
             */
            if (count > 0) {
                location = lineLocations.get(0);
            } else {
                location = new LocationImpl(virtualMachine(), this,
                                            firstIndex);
            }
        }

        info = new SoftLocationXRefs(SDE.BASE_STRATUM_NAME,
                                lineMapper, lineLocations,
                                lowestLine, highestLine);
        softBaseLocationXRefsRef = new SoftReference<SoftLocationXRefs>(info);
        return info;
    }

    private List<LocalVariable> getVariables1_4() throws AbsentInformationException {
        JDWP.Method.VariableTable vartab = null;
        try {
            vartab = JDWP.Method.VariableTable.
                                     process(vm, declaringType, ref);
        } catch (JDWPException exc) {
            if (exc.errorCode() == JDWP.Error.ABSENT_INFORMATION) {
                absentVariableInformation = true;
                throw new AbsentInformationException();
            } else {
                throw exc.toJDIException();
            }
        }

        // Get the number of slots used by argument variables
        argSlotCount = vartab.argCnt;
        int count = vartab.slots.length;
        List<LocalVariable> variables = new ArrayList<LocalVariable>(count);
        for (int i=0; i<count; i++) {
            JDWP.Method.VariableTable.SlotInfo si = vartab.slots[i];

            /*
             * Skip "this*" entries because they are never real
             * variables from the JLS perspective.
             */
            if (!si.name.startsWith("this$") && !si.name.equals("this")) {
                Location scopeStart = new LocationImpl(virtualMachine(),
                                                       this, si.codeIndex);
                Location scopeEnd =
                    new LocationImpl(virtualMachine(), this,
                                     si.codeIndex + si.length - 1);
                LocalVariable variable =
                    new LocalVariableImpl(virtualMachine(), this,
                                          si.slot, scopeStart, scopeEnd,
                                          si.name, si.signature, null);
                // Add to the variable list
                variables.add(variable);
            }
        }
        return variables;
    }

    private List<LocalVariable> getVariables1() throws AbsentInformationException {

        if (!vm.canGet1_5LanguageFeatures()) {
            return getVariables1_4();
        }

        JDWP.Method.VariableTableWithGeneric vartab = null;
        try {
            vartab = JDWP.Method.VariableTableWithGeneric.
                                     process(vm, declaringType, ref);
        } catch (JDWPException exc) {
            if (exc.errorCode() == JDWP.Error.ABSENT_INFORMATION) {
                absentVariableInformation = true;
                throw new AbsentInformationException();
            } else {
                throw exc.toJDIException();
            }
        }

        // Get the number of slots used by argument variables
        argSlotCount = vartab.argCnt;
        int count = vartab.slots.length;
        List<LocalVariable> variables = new ArrayList<LocalVariable>(count);
        for (int i=0; i<count; i++) {
            JDWP.Method.VariableTableWithGeneric.SlotInfo si = vartab.slots[i];

            /*
             * Skip "this*" entries because they are never real
             * variables from the JLS perspective.
             */
            if (!si.name.startsWith("this$") && !si.name.equals("this")) {
                Location scopeStart = new LocationImpl(virtualMachine(),
                                                       this, si.codeIndex);
                Location scopeEnd =
                    new LocationImpl(virtualMachine(), this,
                                     si.codeIndex + si.length - 1);
                LocalVariable variable =
                    new LocalVariableImpl(virtualMachine(), this,
                                          si.slot, scopeStart, scopeEnd,
                                          si.name, si.signature,
                                          si.genericSignature);
                // Add to the variable list
                variables.add(variable);
            }
        }
        return variables;
    }

    private List<LocalVariable> getVariables() throws AbsentInformationException {
        if (absentVariableInformation) {
            throw new AbsentInformationException();
        }

        List<LocalVariable> variables = (variablesRef == null) ? null :
                                        variablesRef.get();
        if (variables != null) {
            return variables;
        }
        variables = getVariables1();
        variables = Collections.unmodifiableList(variables);
        variablesRef = new SoftReference<List<LocalVariable>>(variables);
        return variables;
    }
}
