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

/*
 * This source code is provided to illustrate the usage of a given feature
 * or technique and has been deliberately simplified. Additional steps
 * required for a production-quality application, such as security checks,
 * input validation and proper error handling, might not be present in
 * this sample code.
 */


package com.sun.tools.example.debug.tty;

import com.sun.jdi.*;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.ExceptionRequest;
import com.sun.jdi.request.ClassPrepareRequest;
import com.sun.jdi.event.ClassPrepareEvent;
import java.util.ArrayList;

abstract class EventRequestSpec {

    final ReferenceTypeSpec refSpec;

    int suspendPolicy = EventRequest.SUSPEND_ALL;

    EventRequest resolved = null;
    ClassPrepareRequest prepareRequest = null;

    EventRequestSpec(ReferenceTypeSpec refSpec) {
        this.refSpec = refSpec;
    }

    /**
     * The 'refType' is known to match, return the EventRequest.
     */
    abstract EventRequest resolveEventRequest(ReferenceType refType)
                                           throws Exception;

    /**
     * @return If this EventRequestSpec matches the 'refType'
     * return the cooresponding EventRequest.  Otherwise
     * return null.
     */
    synchronized EventRequest resolve(ClassPrepareEvent event) throws Exception {
        if ((resolved == null) &&
            (prepareRequest != null) &&
            prepareRequest.equals(event.request())) {

            resolved = resolveEventRequest(event.referenceType());
            prepareRequest.disable();
            Env.vm().eventRequestManager().deleteEventRequest(prepareRequest);
            prepareRequest = null;

            if (refSpec instanceof PatternReferenceTypeSpec) {
                PatternReferenceTypeSpec prs = (PatternReferenceTypeSpec)refSpec;
                if (! prs.isUnique()){
                    /*
                     * Class pattern event requests are never
                     * considered "resolved", since future class loads
                     * might also match.
                     * Create and enable a new ClassPrepareRequest to
                     * keep trying to resolve.
                     */
                    resolved = null;
                    prepareRequest = refSpec.createPrepareRequest();
                    prepareRequest.enable();
                }
            }
        }
        return resolved;
    }

    synchronized void remove() {
        if (isResolved()) {
            Env.vm().eventRequestManager().deleteEventRequest(resolved());
        }
        if (refSpec instanceof PatternReferenceTypeSpec) {
            PatternReferenceTypeSpec prs = (PatternReferenceTypeSpec)refSpec;
            if (! prs.isUnique()){
                /*
                 * This is a class pattern.  Track down and delete
                 * all EventRequests matching this spec.
                 * Note: Class patterns apply only to ExceptionRequests,
                 * so that is all we need to examine.
                 */
                ArrayList<ExceptionRequest> deleteList = new ArrayList<ExceptionRequest>();
                for (ExceptionRequest er :
                         Env.vm().eventRequestManager().exceptionRequests()) {
                    if (prs.matches(er.exception())) {
                        deleteList.add (er);
                    }
                }
                Env.vm().eventRequestManager().deleteEventRequests(deleteList);
            }
        }
    }

    private EventRequest resolveAgainstPreparedClasses() throws Exception {
        for (ReferenceType refType : Env.vm().allClasses()) {
            if (refType.isPrepared() && refSpec.matches(refType)) {
                resolved = resolveEventRequest(refType);
            }
        }
        return resolved;
    }

    synchronized EventRequest resolveEagerly() throws Exception {
        try {
            if (resolved == null) {
                /*
                 * Not resolved.  Schedule a prepare request so we
                 * can resolve later.
                 */
                prepareRequest = refSpec.createPrepareRequest();
                prepareRequest.enable();

                // Try to resolve in case the class is already loaded.
                resolveAgainstPreparedClasses();
                if (resolved != null) {
                    prepareRequest.disable();
                    Env.vm().eventRequestManager().deleteEventRequest(prepareRequest);
                    prepareRequest = null;
                }
            }
            if (refSpec instanceof PatternReferenceTypeSpec) {
                PatternReferenceTypeSpec prs = (PatternReferenceTypeSpec)refSpec;
                if (! prs.isUnique()){
                    /*
                     * Class pattern event requests are never
                     * considered "resolved", since future class loads
                     * might also match.  Create a new
                     * ClassPrepareRequest if necessary and keep
                     * trying to resolve.
                     */
                    resolved = null;
                    if (prepareRequest == null) {
                        prepareRequest = refSpec.createPrepareRequest();
                        prepareRequest.enable();
                    }
                }
            }
        } catch (VMNotConnectedException e) {
            // Do nothing. Another resolve will be attempted when the
            // VM is started.
        }
        return resolved;
    }

    /**
     * @return the eventRequest this spec has been resolved to,
     * null if so far unresolved.
     */
    EventRequest resolved() {
        return resolved;
    }

    /**
     * @return true if this spec has been resolved.
     */
    boolean isResolved() {
        return resolved != null;
    }

    protected boolean isJavaIdentifier(String s) {
        if (s.length() == 0) {
            return false;
        }

        int cp = s.codePointAt(0);
        if (! Character.isJavaIdentifierStart(cp)) {
            return false;
        }

        for (int i = Character.charCount(cp); i < s.length(); i += Character.charCount(cp)) {
            cp = s.codePointAt(i);
            if (! Character.isJavaIdentifierPart(cp)) {
                return false;
            }
        }

        return true;
    }

    String errorMessageFor(Exception e) {
        if (e instanceof IllegalArgumentException) {
            return (MessageOutput.format("Invalid command syntax"));
        } else if (e instanceof RuntimeException) {
            // A runtime exception that we were not expecting
            throw (RuntimeException)e;
        } else {
            return (MessageOutput.format("Internal error; unable to set",
                                         this.refSpec.toString()));
        }
    }
}
