/*
 * Copyright (c) 1998, 2013, 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.jdi;

import com.sun.jdi.*;
import com.sun.jdi.request.BreakpointRequest;
import java.util.*;
import java.lang.ref.WeakReference;

public class ThreadReferenceImpl extends ObjectReferenceImpl
             implements ThreadReference, VMListener {
    static final int SUSPEND_STATUS_SUSPENDED = 0x1;
    static final int SUSPEND_STATUS_BREAK = 0x2;

    private int suspendedZombieCount = 0;

    /*
     * Some objects can only be created while a thread is suspended and are valid
     * only while the thread remains suspended.  Examples are StackFrameImpl
     * and MonitorInfoImpl.  When the thread resumes, these objects have to be
     * marked as invalid so that their methods can throw
     * InvalidStackFrameException if they are called.  To do this, such objects
     * register themselves as listeners of the associated thread.  When the
     * thread is resumed, its listeners are notified and mark themselves
     * invalid.
     * Also, note that ThreadReferenceImpl itself caches some info that
     * is valid only as long as the thread is suspended.  When the thread
     * is resumed, that cache must be purged.
     * Lastly, note that ThreadReferenceImpl and its super, ObjectReferenceImpl
     * cache some info that is only valid as long as the entire VM is suspended.
     * If _any_ thread is resumed, this cache must be purged.  To handle this,
     * both ThreadReferenceImpl and ObjectReferenceImpl register themselves as
     * VMListeners so that they get notified when all threads are suspended and
     * when any thread is resumed.
     */

    // This is cached for the life of the thread
    private ThreadGroupReference threadGroup;

    // This is cached only while this one thread is suspended.  Each time
    // the thread is resumed, we abandon the current cache object and
    // create a new initialized one.
    private static class LocalCache {
        JDWP.ThreadReference.Status status = null;
        List<StackFrame> frames = null;
        int framesStart = -1;
        int framesLength = 0;
        int frameCount = -1;
        List<ObjectReference> ownedMonitors = null;
        List<MonitorInfo> ownedMonitorsInfo = null;
        ObjectReference contendedMonitor = null;
        boolean triedCurrentContended = false;
    }

    /*
     * The localCache instance var is set by resetLocalCache to an initialized
     * object as shown above.  This occurs when the ThreadReference
     * object is created, and when the mirrored thread is resumed.
     * The fields are then filled in by the relevant methods as they
     * are called.  A problem can occur if resetLocalCache is called
     * (ie, a resume() is executed) at certain points in the execution
     * of some of these methods - see 6751643.  To avoid this, each
     * method that wants to use this cache must make a local copy of
     * this variable and use that.  This means that each invocation of
     * these methods will use a copy of the cache object that was in
     * effect at the point that the copy was made; if a racy resume
     * occurs, it won't affect the method's local copy.  This means that
     * the values returned by these calls may not match the state of
     * the debuggee at the time the caller gets the values.  EG,
     * frameCount() is called and comes up with 5 frames.  But before
     * it returns this, a resume of the debuggee thread is executed in a
     * different debugger thread.  The thread is resumed and running at
     * the time that the value 5 is returned.  Or even worse, the thread
     * could be suspended again and have a different number of frames, eg, 24,
     * but this call will still return 5.
     */
    private LocalCache localCache;

    private void resetLocalCache() {
        localCache = new LocalCache();
    }

    // This is cached only while all threads in the VM are suspended
    // Yes, someone could change the name of a thread while it is suspended.
    private static class Cache extends ObjectReferenceImpl.Cache {
        String name = null;
    }
    protected ObjectReferenceImpl.Cache newCache() {
        return new Cache();
    }

    // Listeners - synchronized on vm.state()
    private List<WeakReference<ThreadListener>> listeners = new ArrayList<WeakReference<ThreadListener>>();


    ThreadReferenceImpl(VirtualMachine aVm, long aRef) {
        super(aVm,aRef);
        resetLocalCache();
        vm.state().addListener(this);
    }

    protected String description() {
        return "ThreadReference " + uniqueID();
    }

    /*
     * VMListener implementation
     */
    public boolean vmNotSuspended(VMAction action) {
        if (action.resumingThread() == null) {
            // all threads are being resumed
            synchronized (vm.state()) {
                processThreadAction(new ThreadAction(this,
                                            ThreadAction.THREAD_RESUMABLE));
            }

        }

        /*
         * Othewise, only one thread is being resumed:
         *   if it is us,
         *      we have already done our processThreadAction to notify our
         *      listeners when we processed the resume.
         *   if it is not us,
         *      we don't want to notify our listeners
         *       because we are not being resumed.
         */
        return super.vmNotSuspended(action);
    }

    /**
     * Note that we only cache the name string while the entire VM is suspended
     * because the name can change via Thread.setName arbitrarily while this
     * thread is running.
     */
    public String name() {
        String name = null;
        try {
            Cache local = (Cache)getCache();

            if (local != null) {
                name = local.name;
            }
            if (name == null) {
                name = JDWP.ThreadReference.Name.process(vm, this)
                                                             .threadName;
                if (local != null) {
                    local.name = name;
                }
            }
        } catch (JDWPException exc) {
            throw exc.toJDIException();
        }
        return name;
    }

    /*
     * Sends a command to the back end which is defined to do an
     * implicit vm-wide resume.
     */
    PacketStream sendResumingCommand(CommandSender sender) {
        synchronized (vm.state()) {
            processThreadAction(new ThreadAction(this,
                                        ThreadAction.THREAD_RESUMABLE));
            return sender.send();
        }
    }

    public void suspend() {
        try {
            JDWP.ThreadReference.Suspend.process(vm, this);
        } catch (JDWPException exc) {
            throw exc.toJDIException();
        }
        // Don't consider the thread suspended yet. On reply, notifySuspend()
        // will be called.
    }

    public void resume() {
        /*
         * If it's a zombie, we can just update internal state without
         * going to back end.
         */
        if (suspendedZombieCount > 0) {
            suspendedZombieCount--;
            return;
        }

        PacketStream stream;
        synchronized (vm.state()) {
            processThreadAction(new ThreadAction(this,
                                      ThreadAction.THREAD_RESUMABLE));
            stream = JDWP.ThreadReference.Resume.enqueueCommand(vm, this);
        }
        try {
            JDWP.ThreadReference.Resume.waitForReply(vm, stream);
        } catch (JDWPException exc) {
            throw exc.toJDIException();
        }
    }

    public int suspendCount() {
        /*
         * If it's a zombie, we maintain the count in the front end.
         */
        if (suspendedZombieCount > 0) {
            return suspendedZombieCount;
        }

        try {
            return JDWP.ThreadReference.SuspendCount.process(vm, this).suspendCount;
        } catch (JDWPException exc) {
            throw exc.toJDIException();
        }
    }

    public void stop(ObjectReference throwable) throws InvalidTypeException {
        validateMirror(throwable);
        // Verify that the given object is a Throwable instance
        List<ReferenceType> list = vm.classesByName("java.lang.Throwable");
        ClassTypeImpl throwableClass = (ClassTypeImpl)list.get(0);
        if ((throwable == null) ||
            !throwableClass.isAssignableFrom(throwable)) {
             throw new InvalidTypeException("Not an instance of Throwable");
        }

        try {
            JDWP.ThreadReference.Stop.process(vm, this,
                                         (ObjectReferenceImpl)throwable);
        } catch (JDWPException exc) {
            throw exc.toJDIException();
        }
    }

    public void interrupt() {
        try {
            JDWP.ThreadReference.Interrupt.process(vm, this);
        } catch (JDWPException exc) {
            throw exc.toJDIException();
        }
    }

    private JDWP.ThreadReference.Status jdwpStatus() {
        LocalCache snapshot = localCache;
        JDWP.ThreadReference.Status myStatus = snapshot.status;
        try {
             if (myStatus == null) {
                 myStatus = JDWP.ThreadReference.Status.process(vm, this);
                if ((myStatus.suspendStatus & SUSPEND_STATUS_SUSPENDED) != 0) {
                    // thread is suspended, we can cache the status.
                    snapshot.status = myStatus;
                }
            }
         } catch (JDWPException exc) {
            throw exc.toJDIException();
        }
        return myStatus;
    }

    public int status() {
        return jdwpStatus().threadStatus;
    }

    public boolean isSuspended() {
        return ((suspendedZombieCount > 0) ||
                ((jdwpStatus().suspendStatus & SUSPEND_STATUS_SUSPENDED) != 0));
    }

    public boolean isAtBreakpoint() {
        /*
         * TO DO: This fails to take filters into account.
         */
        try {
            StackFrame frame = frame(0);
            Location location = frame.location();
            List<BreakpointRequest> requests = vm.eventRequestManager().breakpointRequests();
            Iterator<BreakpointRequest> iter = requests.iterator();
            while (iter.hasNext()) {
                BreakpointRequest request = iter.next();
                if (location.equals(request.location())) {
                    return true;
                }
            }
            return false;
        } catch (IndexOutOfBoundsException iobe) {
            return false;  // no frames on stack => not at breakpoint
        } catch (IncompatibleThreadStateException itse) {
            // Per the javadoc, not suspended => return false
            return false;
        }
    }

    public ThreadGroupReference threadGroup() {
        /*
         * Thread group can't change, so it's cached once and for all.
         */
        if (threadGroup == null) {
            try {
                threadGroup = JDWP.ThreadReference.ThreadGroup.
                    process(vm, this).group;
            } catch (JDWPException exc) {
                throw exc.toJDIException();
            }
        }
        return threadGroup;
    }

    public int frameCount() throws IncompatibleThreadStateException  {
        LocalCache snapshot = localCache;
        try {
            if (snapshot.frameCount == -1) {
                snapshot.frameCount = JDWP.ThreadReference.FrameCount
                                          .process(vm, this).frameCount;
            }
        } catch (JDWPException exc) {
            switch (exc.errorCode()) {
            case JDWP.Error.THREAD_NOT_SUSPENDED:
            case JDWP.Error.INVALID_THREAD:   /* zombie */
                throw new IncompatibleThreadStateException();
            default:
                throw exc.toJDIException();
            }
        }
        return snapshot.frameCount;
    }

    public List<StackFrame> frames() throws IncompatibleThreadStateException  {
        return privateFrames(0, -1);
    }

    public StackFrame frame(int index) throws IncompatibleThreadStateException  {
        List<StackFrame> list = privateFrames(index, 1);
        return list.get(0);
    }

    /**
     * Is the requested subrange within what has been retrieved?
     * local is known to be non-null.  Should only be called from
     * a sync method.
     */
    private boolean isSubrange(LocalCache snapshot,
                               int start, int length) {
        if (start < snapshot.framesStart) {
            return false;
        }
        if (length == -1) {
            return (snapshot.framesLength == -1);
        }
        if (snapshot.framesLength == -1) {
            if ((start + length) > (snapshot.framesStart +
                                    snapshot.frames.size())) {
                throw new IndexOutOfBoundsException();
            }
            return true;
        }
        return ((start + length) <= (snapshot.framesStart + snapshot.framesLength));
    }

    public List<StackFrame> frames(int start, int length)
                              throws IncompatibleThreadStateException  {
        if (length < 0) {
            throw new IndexOutOfBoundsException(
                "length must be greater than or equal to zero");
        }
        return privateFrames(start, length);
    }

    /**
     * Private version of frames() allows "-1" to specify all
     * remaining frames.
     */
    synchronized private List<StackFrame> privateFrames(int start, int length)
                              throws IncompatibleThreadStateException  {

        // Lock must be held while creating stack frames so if that two threads
        // do this at the same time, one won't clobber the subset created by the other.
        LocalCache snapshot = localCache;
        try {
            if (snapshot.frames == null || !isSubrange(snapshot, start, length)) {
                JDWP.ThreadReference.Frames.Frame[] jdwpFrames
                    = JDWP.ThreadReference.Frames.
                    process(vm, this, start, length).frames;
                int count = jdwpFrames.length;
                snapshot.frames = new ArrayList<StackFrame>(count);

                for (int i = 0; i<count; i++) {
                    if (jdwpFrames[i].location == null) {
                        throw new InternalException("Invalid frame location");
                    }
                    StackFrame frame = new StackFrameImpl(vm, this,
                                                          jdwpFrames[i].frameID,
                                                          jdwpFrames[i].location);
                    // Add to the frame list
                    snapshot.frames.add(frame);
                }
                snapshot.framesStart = start;
                snapshot.framesLength = length;
                return Collections.unmodifiableList(snapshot.frames);
            } else {
                int fromIndex = start - snapshot.framesStart;
                int toIndex;
                if (length == -1) {
                    toIndex = snapshot.frames.size() - fromIndex;
                } else {
                    toIndex = fromIndex + length;
                }
                return Collections.unmodifiableList(snapshot.frames.subList(fromIndex, toIndex));
            }
        } catch (JDWPException exc) {
            switch (exc.errorCode()) {
            case JDWP.Error.THREAD_NOT_SUSPENDED:
            case JDWP.Error.INVALID_THREAD:   /* zombie */
                throw new IncompatibleThreadStateException();
            default:
                throw exc.toJDIException();
            }
        }
    }

    public List<ObjectReference> ownedMonitors()  throws IncompatibleThreadStateException  {
        LocalCache snapshot = localCache;
        try {
            if (snapshot.ownedMonitors == null) {
                snapshot.ownedMonitors = Arrays.asList(
                                 (ObjectReference[])JDWP.ThreadReference.OwnedMonitors.
                                         process(vm, this).owned);
                if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
                    vm.printTrace(description() +
                                  " temporarily caching owned monitors"+
                                  " (count = " + snapshot.ownedMonitors.size() + ")");
                }
            }
        } catch (JDWPException exc) {
            switch (exc.errorCode()) {
            case JDWP.Error.THREAD_NOT_SUSPENDED:
            case JDWP.Error.INVALID_THREAD:   /* zombie */
                throw new IncompatibleThreadStateException();
            default:
                throw exc.toJDIException();
            }
        }
        return snapshot.ownedMonitors;
    }

    public ObjectReference currentContendedMonitor()
                              throws IncompatibleThreadStateException  {
        LocalCache snapshot = localCache;
        try {
            if (snapshot.contendedMonitor == null &&
                !snapshot.triedCurrentContended) {
                snapshot.contendedMonitor = JDWP.ThreadReference.CurrentContendedMonitor.
                    process(vm, this).monitor;
                snapshot.triedCurrentContended = true;
                if ((snapshot.contendedMonitor != null) &&
                    ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0)) {
                    vm.printTrace(description() +
                                  " temporarily caching contended monitor"+
                                  " (id = " + snapshot.contendedMonitor.uniqueID() + ")");
                }
            }
        } catch (JDWPException exc) {
            switch (exc.errorCode()) {
            case JDWP.Error.THREAD_NOT_SUSPENDED:
            case JDWP.Error.INVALID_THREAD:   /* zombie */
                throw new IncompatibleThreadStateException();
            default:
                throw exc.toJDIException();
            }
        }
        return snapshot.contendedMonitor;
    }

    public List<MonitorInfo> ownedMonitorsAndFrames()  throws IncompatibleThreadStateException  {
        LocalCache snapshot = localCache;
        try {
            if (snapshot.ownedMonitorsInfo == null) {
                JDWP.ThreadReference.OwnedMonitorsStackDepthInfo.monitor[] minfo;
                minfo = JDWP.ThreadReference.OwnedMonitorsStackDepthInfo.process(vm, this).owned;

                snapshot.ownedMonitorsInfo = new ArrayList<MonitorInfo>(minfo.length);

                for (int i=0; i < minfo.length; i++) {
                    JDWP.ThreadReference.OwnedMonitorsStackDepthInfo.monitor mi =
                                                                         minfo[i];
                    MonitorInfo mon = new MonitorInfoImpl(vm, minfo[i].monitor, this, minfo[i].stack_depth);
                    snapshot.ownedMonitorsInfo.add(mon);
                }

                if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
                    vm.printTrace(description() +
                                  " temporarily caching owned monitors"+
                                  " (count = " + snapshot.ownedMonitorsInfo.size() + ")");
                    }
                }

        } catch (JDWPException exc) {
            switch (exc.errorCode()) {
            case JDWP.Error.THREAD_NOT_SUSPENDED:
            case JDWP.Error.INVALID_THREAD:   /* zombie */
                throw new IncompatibleThreadStateException();
            default:
                throw exc.toJDIException();
            }
        }
        return snapshot.ownedMonitorsInfo;
    }

    public void popFrames(StackFrame frame) throws IncompatibleThreadStateException {
        // Note that interface-wise this functionality belongs
        // here in ThreadReference, but implementation-wise it
        // belongs in StackFrame, so we just forward it.
        if (!frame.thread().equals(this)) {
            throw new IllegalArgumentException("frame does not belong to this thread");
        }
        if (!vm.canPopFrames()) {
            throw new UnsupportedOperationException(
                "target does not support popping frames");
        }
        ((StackFrameImpl)frame).pop();
    }

    public void forceEarlyReturn(Value  returnValue) throws InvalidTypeException,
                                                            ClassNotLoadedException,
                                             IncompatibleThreadStateException {
        if (!vm.canForceEarlyReturn()) {
            throw new UnsupportedOperationException(
                "target does not support the forcing of a method to return early");
        }

        validateMirrorOrNull(returnValue);

        StackFrameImpl sf;
        try {
           sf = (StackFrameImpl)frame(0);
        } catch (IndexOutOfBoundsException exc) {
           throw new InvalidStackFrameException("No more frames on the stack");
        }
        sf.validateStackFrame();
        MethodImpl meth = (MethodImpl)sf.location().method();
        ValueImpl convertedValue  = ValueImpl.prepareForAssignment(returnValue,
                                                                   meth.getReturnValueContainer());

        try {
            JDWP.ThreadReference.ForceEarlyReturn.process(vm, this, convertedValue);
        } catch (JDWPException exc) {
            switch (exc.errorCode()) {
            case JDWP.Error.OPAQUE_FRAME:
                throw new NativeMethodException();
            case JDWP.Error.THREAD_NOT_SUSPENDED:
                throw new IncompatibleThreadStateException(
                         "Thread not suspended");
            case JDWP.Error.THREAD_NOT_ALIVE:
                throw new IncompatibleThreadStateException(
                                     "Thread has not started or has finished");
            case JDWP.Error.NO_MORE_FRAMES:
                throw new InvalidStackFrameException(
                         "No more frames on the stack");
            default:
                throw exc.toJDIException();
            }
        }
    }

    public String toString() {
        return "instance of " + referenceType().name() +
               "(name='" + name() + "', " + "id=" + uniqueID() + ")";
    }

    byte typeValueKey() {
        return JDWP.Tag.THREAD;
    }

    void addListener(ThreadListener listener) {
        synchronized (vm.state()) {
            listeners.add(new WeakReference<ThreadListener>(listener));
        }
    }

    void removeListener(ThreadListener listener) {
        synchronized (vm.state()) {
            Iterator<WeakReference<ThreadListener>> iter = listeners.iterator();
            while (iter.hasNext()) {
                WeakReference<ThreadListener> ref = iter.next();
                if (listener.equals(ref.get())) {
                    iter.remove();
                    break;
                }
            }
        }
    }

    /**
     * Propagate the the thread state change information
     * to registered listeners.
     * Must be entered while synchronized on vm.state()
     */
    private void processThreadAction(ThreadAction action) {
        synchronized (vm.state()) {
            Iterator<WeakReference<ThreadListener>> iter = listeners.iterator();
            while (iter.hasNext()) {
                WeakReference<ThreadListener> ref = iter.next();
                ThreadListener listener = ref.get();
                if (listener != null) {
                    switch (action.id()) {
                        case ThreadAction.THREAD_RESUMABLE:
                            if (!listener.threadResumable(action)) {
                                iter.remove();
                            }
                            break;
                    }
                } else {
                    // Listener is unreachable; clean up
                    iter.remove();
                }
            }

            // Discard our local cache
            resetLocalCache();
        }
    }
}
