/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.debugger.jpda.ant;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.beans.PropertyChangeEvent;

import com.sun.jdi.Bootstrap;
import com.sun.jdi.connect.ListeningConnector;
import com.sun.jdi.connect.Transport;
import com.sun.jdi.connect.Connector;
import java.beans.PropertyChangeListener;
import java.io.FileFilter;
import java.io.IOException;

import java.lang.ref.WeakReference;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.Path;
import org.netbeans.api.debugger.Breakpoint;
import org.netbeans.api.debugger.jpda.DebuggerStartException;

import org.openide.util.RequestProcessor;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;

import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.queries.SourceForBinaryQuery;
import org.netbeans.api.debugger.DebuggerManager;
import org.netbeans.api.debugger.jpda.JPDADebugger;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
import org.netbeans.api.debugger.DebuggerEngine;
import org.netbeans.api.debugger.DebuggerManagerAdapter;
import org.netbeans.api.debugger.Session;
import org.netbeans.api.debugger.jpda.ExceptionBreakpoint;
import org.netbeans.api.debugger.jpda.JPDAClassType;
import org.netbeans.api.debugger.jpda.JPDAThread;
import org.netbeans.api.debugger.jpda.MethodBreakpoint;
import org.netbeans.api.debugger.jpda.ObjectVariable;
import org.netbeans.api.debugger.jpda.Variable;
import org.netbeans.api.debugger.jpda.event.JPDABreakpointEvent;
import org.netbeans.api.debugger.jpda.event.JPDABreakpointListener;
import org.netbeans.api.java.platform.JavaPlatform;
import org.netbeans.api.java.source.BuildArtifactMapper;
import org.netbeans.api.java.source.BuildArtifactMapper.ArtifactsUpdated;
import org.netbeans.api.project.ProjectManager;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;


/**
 * Ant task to start the NetBeans JPDA debugger in listening mode.
 *
 * @author Jesse Glick, David Konecny
 */
public class JPDAStart extends Task implements Runnable {

    private static final Logger logger = Logger.getLogger("org.netbeans.modules.debugger.jpda.ant"); // NOI18N

    private static final String URL_EMBEDDING = String.format("!%c",File.separatorChar);   //NOI18N
    private static final String SOCKET_TRANSPORT = "dt_socket"; // NOI18N
    private static final String SHMEM_TRANSPORT = "dt_shmem"; // NOI18N
    private static final String SOCKET_CONNECTOR = "com.sun.jdi.SocketListen"; // NOI18N
    private static final String SHMEM_CONNECTOR = "com.sun.jdi.SharedMemoryListen"; // NOI18N
    private static final String MODULE_INFO_CLZ = "module-info.class";  //NOI18N
    private static final Set<? extends String> MODULE_FILES;
    static {
        final Set<String> exts = new HashSet<String>();
        exts.add("jar");    //NOI18N
        exts.add("jmod");   //NOI18N
        MODULE_FILES = Collections.unmodifiableSet(exts);
    }

    /** Name of the property to which the JPDA address will be set.
     * Target VM should use this address and connect to it
     */
    private String                  addressProperty;
    /** Default transport is socket*/
    private String                  transport = SOCKET_TRANSPORT;
    /** Preferred connector name. May be null. */
    private String                  connector;
    /** Name which will represent this debugging session in debugger UI.
     * If known in advance it should be name of the app which will be debugged.
     */
    private String                  name;
    /** Explicit sourcepath of the debugged process. */
    private Sourcepath              sourcepath = null;
    private Path                    plainSourcepath = null;
    private boolean                 isSourcePathExclusive;
    /** Explicit classpath of the debugged process. */
    private Path                    classpath = null;
    /** Explicit bootclasspath of the debugged process. */
    private Path                    bootclasspath = null;
    /** Explicit modulepath of the debugged process. */
    private Path                    modulepath = null;
    private final Object []         lock = new Object[2];
    /** The class debugger should stop in, or null. */
    private String                  stopClassName = null;
    private String                  listeningCP = null;
    private boolean                 useLoopBackAddress = true;
    private RequestProcessor        rp = new RequestProcessor("JPDAStart", 5);

    
    // properties ..............................................................

    public void setAddressProperty (String propertyName) {
        this.addressProperty = propertyName;
    }

    private String getAddressProperty () {
        return addressProperty;
    }

    public void setTransport (String transport) {
        logger.log(Level.FINE, "Set transport: ''{0}''", transport);
        this.transport = transport;
    }

    private String getTransport () {
        return transport;
    }
    
    public void setConnector(String connector) {
        this.connector = connector;
    }

    public String getConnector() {
        return connector;
    }

    public void setName (String name) {
        this.name = name;
    }

    private String getName () {
        return name;
    }

    public void setStopClassName (String stopClassName) {
        this.stopClassName = stopClassName;
    }

    private String getStopClassName () {
        return stopClassName;
    }

    public void setListeningcp(String listeningCP) {
        this.listeningCP = listeningCP;
    }
    
    public void setUseLoopBackAddress(String useLoopBackAddress) { // useLoopBackAddress
        this.useLoopBackAddress = Boolean.parseBoolean(useLoopBackAddress);
        logger.log(Level.FINE, "setUseLoopBackAddress = ''{0}'' => {1}", new Object[] { useLoopBackAddress, this.useLoopBackAddress });
    }

    public void addClasspath (Path path) {
        logger.log(Level.FINE, "addClasspath({0})", path);
        if (classpath != null)
            throw new BuildException ("Only one classpath subelement is supported");
        classpath = path;
    }

    public void addBootclasspath (Path path) {
        logger.log(Level.FINE, "addBootclasspath({0})", path);
        if (bootclasspath != null)
            throw new BuildException ("Only one bootclasspath subelement is supported");
        bootclasspath = path;
    }

    public void addModulepath (Path path) {
        logger.log(Level.FINE, "addModlepath({0})", path);
        if (modulepath != null)
            throw new BuildException ("Only one modulepath subelement is supported");
        modulepath = path;
    }

    public void addSourcepath (Sourcepath path) {
        logger.log(Level.FINE, "addSourcepath({0})", path);
        if (sourcepath != null)
            throw new BuildException ("Only one sourcepath subelement is supported");
        sourcepath = path;
    }

    static void verifyPaths(Project project, Path path) {
        if (path == null) return ;
        String[] paths = path.list();
        for (int i = 0; i < paths.length; i++) {
            String pathName = project.replaceProperties(paths[i]);
            File file = FileUtil.normalizeFile
                (project.resolveFile (pathName));
            if (!file.exists()) {
                project.log("Non-existing path \""+pathName+"\" provided.", Project.MSG_WARN);
                //throw new BuildException("Non-existing path \""+paths[i]+"\" provided.");
            }
        }
    }

    /** Searching for a connector in given collection.
     * @param name - name of the connector
     * @param connectors
     * @return the connector or null
     */
    private static ListeningConnector findConnector(String name, final Collection<ListeningConnector> connectors) {
        assert name != null;
        for (ListeningConnector c : connectors) {
            if (name.equals(c.name())) {
                return c;
            }
        }
        return null;
    }
    
    // main methods ............................................................

    @Override
    public void execute () throws BuildException {
        verifyPaths(getProject(), classpath);
        verifyPaths(getProject(), modulepath);
        //verifyPaths(getProject(), bootclasspath); Do not check the paths on bootclasspath (see issue #70930).
        if (sourcepath != null) {
            isSourcePathExclusive = sourcepath.isExclusive();
            plainSourcepath = sourcepath.getPlainPath();
        }
        verifyPaths(getProject(), plainSourcepath);
        try {
            logger.fine("JPDAStart.execute()"); // NOI18N
            debug ("Execute started"); // NOI18N
            if (name == null)
                throw new BuildException ("name attribute must specify name of this debugging session", getLocation ());
            if (addressProperty == null)
                throw new BuildException ("addressproperty attribute must specify name of property to which address will be set", getLocation ());
            if (transport == null)
                transport = SOCKET_TRANSPORT;
            debug ("Entering synch lock"); // NOI18N
            lock[0] = lock[1] = null;
            synchronized (lock) {
                debug ("Entered synch lock"); // NOI18N
                rp.post (this);
                try {
                    debug ("Entering wait"); // NOI18N
                    lock.wait ();
                    debug ("Wait finished"); // NOI18N
                    if (lock [1] != null) {
                        if (lock[1] instanceof DebuggerStartException) {
                            //getProject().log(((DebuggerStartException) lock[1]).getLocalizedMessage(), Project.MSG_ERR);
                            throw new BuildException(((DebuggerStartException) lock[1]).getLocalizedMessage());
                        } else if (lock[1] instanceof ThreadDeath) {
                            throw (ThreadDeath) lock[1];
                        } else {
                            throw new BuildException ((Throwable) lock [1]);
                        }
                    }
                } catch (InterruptedException e) {
                    throw new BuildException (e);
                }
            }
        } catch (Throwable t) {
            t.printStackTrace ();
            throw new BuildException (t);
        }
    }

    @Override
    public void run () {
        logger.fine("JPDAStart.run()"); // NOI18N
        debug ("Entering synch lock"); // NOI18N
        synchronized (lock) {
            debug("Entered synch lock"); // NOI18N
            try {
                ListeningConnector lc = null;
                final Set<ListeningConnector> connectors = new HashSet<ListeningConnector>();
                // search for connectors registered by NetBeans modules
                // In JavaFX listening connectors are registered as Connector.class.
                final Lookup.Result<Connector> r = Lookup.getDefault().lookupResult(Connector.class);
                for(Connector c: r.allInstances()) {
                    if (c instanceof ListeningConnector) connectors.add((ListeningConnector) c);
                }
                // use JDI default as well
                connectors.addAll(Bootstrap.virtualMachineManager().listeningConnectors());

                // if name of the connector has been specified, try to use it
                if (connector != null) {
                    logger.log(Level.FINE, "Looking for connector {0}", connector);
                    lc = findConnector(connector, connectors);
                }
                if (lc == null) {
                    // if dt_socket then use default socket as specified by JDI
                    if (transport.equals(SOCKET_TRANSPORT)) {
                        logger.log(Level.FINE, "Looking for default connector {0}", SOCKET_CONNECTOR);
                        lc = findConnector(SOCKET_CONNECTOR, connectors);
                    // if dt_shmem then use the default socket as specified by JDI
                    } else if (transport.equals(SHMEM_TRANSPORT)) {
                        logger.log(Level.FINE, "Looking for default connector {0}", SHMEM_CONNECTOR);
                        lc = findConnector(SHMEM_CONNECTOR, connectors);
                    }
                }
                // fallback to the original, i.e. find first connector whose transport
                // name matches given transport
                if (lc == null) {
                    logger.log(Level.FINE, "Fall back, looking for a connector with transport {0}", transport);
                    for (ListeningConnector c: connectors) {
                        Transport t = c.transport ();
                        if (t != null && t.name ().equals (transport)) {
                            lc = c;
                            break;
                        }
                    }
                }
                if (lc == null) {
                    throw new BuildException
                        ("No transports named " + transport + " found!");
                }
                logger.log(Level.FINE, "Listening using connector {0}, transport {1}", new Object[] {lc.name(), lc.transport().name()});

                final Map args = lc.defaultArguments ();
                Connector.StringArgument localAddress = (Connector.StringArgument) args.get("localAddress"); // NOI18N
                if (localAddress != null) {
                    String host = null;
                    if (!useLoopBackAddress) {
                        try {
                            host = InetAddress.getLocalHost().getCanonicalHostName();
                        } catch (UnknownHostException uhex) {}
                    }
                    if (host == null) {
                        host = "127.0.0.1"; // NOI18N
                    }
                    localAddress.setValue(host);
                }
                logger.log(Level.FINE, "Assigned host = ''{0}''", localAddress);
                String address = null;
                try {
                    address = lc.startListening (args);
                } catch (java.io.IOException ioex) {
                    boolean passed = false;
                    // workaround for issue 148490
                    if (SHMEM_TRANSPORT.equals(transport)) {
                        Connector.StringArgument argName = (Connector.StringArgument) args.get("name"); // NOI18N
                        for (int x = 0; x < 5; x++) {
                            String tryAddress = "javadebug" + Math.round(Math.random() * 10000); // NOI18N
                            try {
                                argName.setValue (tryAddress);
                                address = lc.startListening (args);
                                passed = true;
                                break;
                            } catch (Exception e) {
                                // ignore
                            }
                        } // for
                    }
                    if (!passed) {
                        getProject().log("Listening failed with arguments: "+args);
                        throw ioex;
                    }
                } catch (com.sun.jdi.connect.IllegalConnectorArgumentsException iaex) {
                    getProject().log("Listening failed with arguments: "+args);
                    throw iaex;
                }
                /* A fix to bug http://developer.java.sun.com/developer/bugParade/bugs/4932074.html has been integrated into JDK 1.5
                // Uncomment if the fix is not complete in all cases
                // This code parses the address string "HOST:PORT" to extract PORT and then point debugee to localhost:PORT
                // This is NOT a clean solution to the problem but it SHOULD work in 99% cases
                if (SOCKET_TRANSPORT.equals(transport)) {
                    int port = -1;
                    try {
                        port = Integer.parseInt (address.substring (address.indexOf (':') + 1));
                        Connector.IntegerArgument portArg = (Connector.IntegerArgument) args.get("port"); // NOI18N
                        portArg.setValue (port);
                        address = "localhost:" + port; // NOI18N
                    } catch (Exception e) {
                        // this address format is not known, use default
                    }
                }*/
                if (SOCKET_TRANSPORT.equals(transport)) {
                    try {
                        int port = Integer.parseInt (address.substring (address.indexOf (':') + 1));
                        Connector.IntegerArgument portArg = (Connector.IntegerArgument) args.get("port"); // NOI18N
                        portArg.setValue (port);
                        // Since some users have badly configured host addresses,
                        // perform a check for the address and use "localhost"
                        // if the address can not be resolved: (see http://www.netbeans.org/issues/show_bug.cgi?id=154974)
                        String host = address.substring(0, address.indexOf (':'));
                        logger.log(Level.FINE, "  socket listening at {0}, host = {1}, port = {2}",  // NOI18N
                                   new Object[]{address, host, port});
                        try {
                            InetAddress.getByName(host);
                        } catch (UnknownHostException uhex) {
                            logger.log(  Level.FINE, "unknown host ''{0}''", host);
                            address = "localhost:" + port; // NOI18N
                        } catch (SecurityException  se) {}
                    } catch (Exception e) {
                        // ignore
                    }
                }
                if (SHMEM_TRANSPORT.equals(transport)) {
                    try {
                        Connector.StringArgument name = (Connector.StringArgument) args.get("name"); // NOI18N
                        name.setValue (address);
                    } catch (Exception e) {
                        // ignore
                    }
                }
                getProject ().setNewProperty (getAddressProperty (), address);

                debug ("Creating source path"); // NOI18N
                ClassPath sourcePath = createSourcePath (
                    getProject (),
                    modulepath,
                    classpath,
                    plainSourcepath,
                    isSourcePathExclusive
                );
                ClassPath jdkSourcePath = createJDKSourcePath (
                    getProject (),
                    bootclasspath
                );
                if (logger.isLoggable(Level.FINE)) {
                    logger.fine("Create sourcepath:"); // NOI18N
                    logger.log(Level.FINE, "    modulepath : {0}", modulepath); // NOI18N
                    logger.log(Level.FINE, "    classpath : {0}", classpath); // NOI18N
                    logger.log(Level.FINE, "    sourcepath : {0}", plainSourcepath); // NOI18N
                    logger.log(Level.FINE, "    bootclasspath : {0}", bootclasspath); // NOI18N
                    logger.log(Level.FINE, "    >> sourcePath : {0}", sourcePath); // NOI18N
                    logger.log(Level.FINE, "    >> jdkSourcePath : {0}", jdkSourcePath); // NOI18N
                }

                Breakpoint first = null;

                if (stopClassName != null && stopClassName.length() > 0) {
                    logger.log(Level.FINE, "create method breakpoint, class name = {0}", stopClassName);    // NOI18N
                    first = createBreakpoint (stopClassName);
                }

                debug ("Debugger started"); // NOI18N
                logger.log(Level.FINE, "start listening at {0}", address); // NOI18N

                final Map properties = new HashMap ();
                // uncomment to implement smart stepping with step-outs
                // rather than step-ins (for J2ME)
                // props.put("SS_ACTION_STEPOUT", Boolean.TRUE);
                properties.put ("sourcepath", sourcePath); // NOI18N
                properties.put ("name", getName ()); // NOI18N
                properties.put ("jdksources", jdkSourcePath); // NOI18N
                properties.put ("listeningCP", listeningCP); // NOI18N
                String workDir = getProject().getProperty("work.dir");
                final File baseDir;
                if (workDir != null) {
                    baseDir = new File(workDir);
                } else {
                    baseDir = getProject().getBaseDir();
                }
                properties.put ("baseDir", baseDir); // NOI18N

                logger.log(Level.FINE, "JPDAStart: properties = {0}", properties);

                final ListeningConnector flc = lc;
                final WeakReference<Session> startedSessionRef[] = new WeakReference[] { new WeakReference<Session>(null) };

                Map<URL, ArtifactsUpdated> listeners = new HashMap<URL, ArtifactsUpdated>();
                List<Breakpoint> artificialBreakpoints = new LinkedList<Breakpoint>();
                if (listeningCP != null) {
                    ExceptionBreakpoint b = createCompilationErrorBreakpoint();
                    DebuggerManager.getDebuggerManager ().addBreakpoint (b);
                    artificialBreakpoints.add(b);
                }

                DebuggerManager.getDebuggerManager().addDebuggerListener(
                        DebuggerManager.PROP_DEBUGGER_ENGINES,
                        new Listener(first, artificialBreakpoints, listeners, startedSessionRef, rp));

                // Let it start asynchronously so that the script can go on and start the debuggee
                final Thread[] listeningThreadPtr = new Thread[] { null };
                final boolean[] listeningStarted = new boolean[] { false };
                rp.post(new Runnable() {
                    @Override
                    public void run() {
                        synchronized (listeningStarted) {
                            listeningThreadPtr[0] = Thread.currentThread();
                            listeningStarted[0] = true;
                            listeningStarted.notifyAll();
                        }
                        Object[] services = null;
                        try {
                            FileObject prjRoot = FileUtil.toFileObject(FileUtil.normalizeFile(baseDir));
                            if (prjRoot != null) {
                                org.netbeans.api.project.Project prj = ProjectManager.getDefault().findProject(prjRoot);
                                if (prj != null) {
                                    services = new Object[] { properties, prj };
                                }
                            }
                        } catch (IOException ioex) {}
                        if (services == null) {
                            services = new Object[] { properties };
                        }
                        try {
                            DebuggerEngine[] engines = JPDADebugger.startListeningAndGetEngines (
                                flc,
                                args,
                                services
                            );
                            startedSessionRef[0] = new WeakReference(engines[0].lookupFirst(null, Session.class));
                        } catch (DebuggerStartException dsex) {
                            // Was not able to start up
                        } finally {
                            synchronized (listeningStarted) {
                                listeningThreadPtr[0] = null;
                                listeningStarted.notifyAll();
                            }
                        }
                    }
                });

                logger.log(Level.FINE, "adding a BuildListener to project {0} in {1}", new Object[] {getProject().getName(), getProject().getBaseDir()});
                getProject().addBuildListener(new BuildListener() {

                    @Override public void messageLogged(BuildEvent event) {}
                    @Override public void taskStarted(BuildEvent event) { }
                    @Override public void taskFinished(BuildEvent event) {}
                    @Override public void targetStarted(BuildEvent event) {}
                    @Override public void targetFinished(BuildEvent event) {}
                    @Override public void buildStarted(BuildEvent event) {}
                    @Override public void buildFinished(BuildEvent event) {
                        // First wait until listening actually starts:
                        logger.fine("buildFinished: waiting for listening start...");
                        synchronized (listeningStarted) {
                            if (!listeningStarted[0]) {
                                try {
                                    listeningStarted.wait();
                                } catch (InterruptedException ex) {}
                            }
                        }
                        logger.fine("buildFinished: stopping listening...");
                        // Then stop it:
                        try {
                            flc.stopListening(args);
                        } catch (java.io.IOException ioex) {
                        } catch (com.sun.jdi.connect.IllegalConnectorArgumentsException iaex) {
                        }
                        logger.fine("buildFinished: interrupting listening thread...");
                        // If the listening is still running, interrupt it:
                        for (int i = 0; i < 10; i++) {
                            synchronized (listeningStarted) {
                                logger.log(Level.FINE, "buildFinished: listening thread = {0}", listeningThreadPtr[0]);
                                if (listeningThreadPtr[0] != null) {
                                    listeningThreadPtr[0].interrupt();
                                    try {
                                        listeningStarted.wait(500);
                                    } catch (InterruptedException ex) {}
                                } else {
                                    break;
                                }
                            }
                        }
                        // Finally, kill the started session:
                        Session s = startedSessionRef[0].get();
                        logger.log(Level.FINE, "buildFinished: killing session {0}", s);
                        if (s != null) {
                            s.kill();
                        }
                    }

                });
            } catch (java.io.IOException ioex) {
                lock[1] = ioex;
            } catch (com.sun.jdi.connect.IllegalConnectorArgumentsException icaex) {
                lock[1] = icaex;
            } catch (ThreadDeath td) {
                // Session was canceled - see issue #148483
                lock[1] = td;
            } finally {
                debug ("Notifying"); // NOI18N
                lock.notify ();
            }
        }
    } // run ()


    // support methods .........................................................

    private MethodBreakpoint createBreakpoint (String stopClassName) {
        MethodBreakpoint breakpoint = MethodBreakpoint.create (
            stopClassName,
            "*"
        );
        breakpoint.setHidden (true);
        DebuggerManager.getDebuggerManager ().addBreakpoint (breakpoint);
        return breakpoint;
    }

    private ExceptionBreakpoint createCompilationErrorBreakpoint() {
        ExceptionBreakpoint b = ExceptionBreakpoint.create("java.lang.RuntimeException", ExceptionBreakpoint.TYPE_EXCEPTION_UNCATCHED);
        b.setHidden (true);
        b.addJPDABreakpointListener(new JPDABreakpointListener() {
            @Override
            public void breakpointReached(JPDABreakpointEvent event) {
                boolean suspend = false;
                try {
                    if (event.getVariable() instanceof ObjectVariable) {
                        ObjectVariable ov = (ObjectVariable) event.getVariable();
                        JPDAClassType ct = ov.getClassType();
                        if (ct != null) {
                            suspend = "java.lang.RuntimeException".equals(ct.getName());
                            if (suspend) {
                                java.lang.reflect.Method invokeMethodMethod = ov.getClass().getMethod("invokeMethod", JPDAThread.class, String.class, String.class, Variable[].class);
                                invokeMethodMethod.setAccessible(true);
                                Variable message = (Variable) invokeMethodMethod.invoke(ov, event.getThread(), "getMessage", "()Ljava/lang/String;", new Variable[0]);
                                if (message != null) {
                                    suspend = message.getValue().startsWith("\"Uncompilable source code");
                                }
                                //suspend = suspend && ov.invokeMethod("getMessage", "()Ljava/lang/String;", new Variable[0]).getValue().startsWith("\"Uncompilable source code");
                            }
                        }
                    }
                } catch (IllegalAccessException iaex) {
                    logger.log(Level.FINE, null, iaex);
                } catch (java.lang.reflect.InvocationTargetException itex) {
                    logger.log(Level.FINE, null, itex);
                } catch (NoSuchMethodException ex) {
                    logger.log(Level.FINE, null, ex);
                //} catch (InvalidExpressionException ex) {
                //    logger.log(Level.FINE, null, ex);
                }

                if (!suspend) {
                    event.resume();
                }
            }
        });
        b.setPrintText(NbBundle.getBundle("org/netbeans/modules/debugger/jpda/ant/Bundle").getString("MSG_StoppedOnCompileError"));
        return b;
    }

    private static void debug (String msg) {
        if (!logger.isLoggable(Level.FINER)) return;
        logger.log(Level.FINER, "{0} [{1}] - {2}",
                   new Object[]{ new Date(), Thread.currentThread().getName(), msg });
    }

    static ClassPath createSourcePath (
        Project project,
        Path modulepath,
        Path classpath,
        Path sourcepath,
        boolean isSourcePathExclusive
    ) {
        if (sourcepath != null && isSourcePathExclusive) {
            return convertToClassPath (project, sourcepath);
        }
        ClassPath cp = convertToSourcePath (project, classpath, true);
        ClassPath modulesSources = convertToSourcePath(project, modules(project, modulepath), true);
        ClassPath sp = convertToClassPath (project, sourcepath);

        ClassPath sourcePath = ClassPathSupport.createProxyClassPath (
            new ClassPath[] {cp, modulesSources, sp}
        );
        return sourcePath;
    }

    private static Path modules(
            Project project,
            Path modulepath) {
        if (modulepath == null) {
            return null;
        }
        final Path modules = new Path(project);
        for (String pathElement : modulepath.list()) {
            final String pathName = project.replaceProperties(pathElement);
            if (pathName.lastIndexOf(URL_EMBEDDING) >=0) {
                modules.append(new Path(project, pathElement));
                continue;
            }
            final File file = FileUtil.normalizeFile(project.resolveFile (pathName));
            if (file.isDirectory() && !new File(file,MODULE_INFO_CLZ).exists()) {
                //Folder of modules add them
                for (File module : file.listFiles(new FileFilter() {
                    @Override
                    public boolean accept(File pathname) {
                        return pathname.isDirectory() ||
                            MODULE_FILES.contains(getExt(pathname));
                    }
                   })) {
                    modules.append(new Path(project, String.format("%s%s%s",   //NOI18N
                           pathElement,
                           File.separatorChar,
                           module.getName())));
               }
            } else {
                modules.append(new Path(project, pathElement));
            }

        }
        return modules;
    }

    private static String getExt(final File file) {
        final String name = file.getName();
        final int dot = name.indexOf('.');  //NOI18N
        return dot <= 0 ?
                "" :
                name.substring(dot+1).toLowerCase();
    }

    static ClassPath createJDKSourcePath (
        Project project,
        Path bootclasspath
    ) {
        if (bootclasspath == null) {
            // if current platform is default one, bootclasspath is set to null
            JavaPlatform jp = JavaPlatform.getDefault();
            if (jp != null) {
                return jp.getSourceFolders ();
            } else {
                return ClassPathSupport.createClassPath(java.util.Collections.EMPTY_LIST);
            }
        } else {
            return convertToSourcePath (project, bootclasspath, false);
        }
    }

    private static ClassPath convertToClassPath (Project project, Path path) {
        String[] paths = path == null ? new String [0] : path.list ();
        List l = new ArrayList ();
        int i, k = paths.length;
        for (i = 0; i < k; i++) {
            String pathName = project.replaceProperties(paths[i]);
            File f = FileUtil.normalizeFile (project.resolveFile (pathName));
            if (!isValid (f, project)) continue;
            URL url = fileToURL (f, project, true, false);
            if (url == null) continue;
            l.add (url);
        }
        URL[] urls = (URL[]) l.toArray (new URL [l.size ()]);
        return ClassPathSupport.createClassPath (urls);
    }

    /**
     * This method uses SourceForBinaryQuery to find sources for each
     * path item and returns them as ClassPath instance. All path items for which
     * the sources were not found are omitted.
     *
     */
    private static ClassPath convertToSourcePath (Project project, Path path, boolean reportNonExistingFiles) {
        String[] paths = path == null ? new String [0] : path.list ();
        List l = new ArrayList ();
        Set exist = new HashSet ();
        int i, k = paths.length;
        for (i = 0; i < k; i++) {
            String pathName = project.replaceProperties(paths[i]);
            final String pathInArchive;
            final int index = pathName.lastIndexOf(URL_EMBEDDING);
            if (index >= 0) {
                pathInArchive = pathName.substring(index+URL_EMBEDDING.length()).replace(File.separatorChar, '/');  //NOI18N
                pathName = pathName.substring(0, index);
            } else {
                pathInArchive = ""; //NOI18N
            }
            File file = FileUtil.normalizeFile
                (project.resolveFile (pathName));
            if (!isValid (file, project)) continue;
            URL url = fileToURL (file, project, reportNonExistingFiles, true);
            if (url == null) continue;
            if (!pathInArchive.isEmpty()) {
                url = appendPathInArchive(url, pathInArchive, project);
            }
            logger.log(Level.FINE, "convertToSourcePath - class: {0}", url); // NOI18N
            try {
                SourceForBinaryQuery.Result srcRootsResult = SourceForBinaryQuery.findSourceRoots(url);
                FileObject fos[] = srcRootsResult.getRoots();
                int j, jj = fos.length;
                logger.log(Level.FINE, "  source roots = {0}; jj = {1}", new Object[]{java.util.Arrays.asList(fos), jj});
                /* ?? (#60640)
                if (jj == 0) { // no sourcepath defined
                    // Take all registered source roots
                    Set allSourceRoots = GlobalPathRegistry.getDefault().getSourceRoots();
                    fos = (FileObject[]) allSourceRoots.toArray(new FileObject[0]);
                    jj = fos.length;
                }
                 */
                for (j = 0; j < jj; j++) {
                    FileObject fo = fos[j];
                    logger.log(Level.FINE, "convertToSourcePath - source : {0}", fo); // NOI18N
                    if (FileUtil.isArchiveFile (fo)) {
                        fo = FileUtil.getArchiveRoot (fo);
                        if (fo == null) { // can occur if we fail to find the actual archive
                            fo = fos[j];
                        }
                    }
                    url = fo.toURL ();
                    if (url == null) continue;
                    if (!exist.contains (url)) {
                        l.add (ClassPathSupport.createResource (url));
                        exist.add (url);
                    }
                } // for
            } catch (IllegalArgumentException ex) {
                Exceptions.printStackTrace(ex);
                logger.log(Level.FINE, "Have illegal url! {0}", ex.getLocalizedMessage()); // NOI18N
            }
        }
        return ClassPathSupport.createClassPath (l);
    }

    private static URL appendPathInArchive(URL rootURL, String pathInArchive, Project prj) {
        String embeddedURL = rootURL.toExternalForm() + pathInArchive;
        if (embeddedURL.charAt(embeddedURL.length()-1) != '/') {    //NOI18N
            embeddedURL = embeddedURL + '/';    //NOI18N
        }
        try {
            return new URL(embeddedURL);
        } catch (MalformedURLException e) {
            prj.log("Invalid embedded URL: \""+embeddedURL+"\".", Project.MSG_WARN);   //NOI18N
            return rootURL;
        }
    }


    private static URL fileToURL (File file, Project project, boolean reportNonExistingFiles, boolean withSlash) {
        FileObject fileObject = FileUtil.toFileObject (file);
        if (fileObject == null) {
            if (reportNonExistingFiles) {
                String path = file.getAbsolutePath();
                project.log("Have no file for "+path, Project.MSG_WARN);
            }
            return null;
        }
        if (FileUtil.isArchiveFile (fileObject)) {
            fileObject = FileUtil.getArchiveRoot (fileObject);
            if (fileObject == null) {
                project.log("Bad archive "+file.getAbsolutePath(), Project.MSG_WARN);
                /*
                ErrorManager.getDefault().notify(ErrorManager.getDefault().annotate(
                        new NullPointerException("Bad archive "+file.toString()),
                        NbBundle.getMessage(JPDAStart.class, "MSG_WrongArchive", file.getAbsolutePath())));
                 */
                return null;
            }
        }
        if (withSlash) {
            return FileUtil.urlForArchiveOrDir(file);
        } else {
            return fileObject.toURL ();
        }
    }

    private static boolean isValid (File f, Project project) {
        if (f.getPath ().indexOf ("${") != -1 && !f.exists ()) { // NOI18N
            project.log (
                "Classpath item " + f + " will be ignored.",  // NOI18N
                Project.MSG_VERBOSE
            );
            return false;
        }
        return true;
    }


    // innerclasses ............................................................

    public static class Sourcepath extends Path {

        private boolean isExclusive;
        private String path = null;
        private Path plainPath;

        public Sourcepath(Project p) {
            super(p);
            logger.log(Level.FINE, "new Sourcepath({0})", p);
        }

        public Sourcepath(Project p, String path) {
            super(p, path);
            this.path = path;
            logger.log(Level.FINE, "new Sourcepath({0}, {1})", new Object[]{p, path});
        }

        public void setExclusive(String exclusive) {
            isExclusive = "true".equalsIgnoreCase(exclusive);
        }

        boolean isExclusive() {
            return isExclusive;
        }

        public Path getPlainPath() {
            if (plainPath == null) {
                if (getRefid() != null) {
                    Path pp;
                    if (path != null) {
                        pp = new Path(getProject(), path);
                    } else {
                        pp = new Path(getProject());
                    }
                    pp.setLocation(getLocation());
                    pp.setDescription(getDescription());
                    pp.setRefid(getRefid());
                    //pp.setChecked(isChecked());
                    //pp.union = union == null ? union : (Union) union.clone();
                    plainPath = pp;
                } else {
                    plainPath = this;
                }
            }
            return plainPath;
        }

    }

    private static class Listener extends DebuggerManagerAdapter {

        private final PropertyChangeListener pcl = WeakListeners.propertyChange(this, null);

        private Set<DebuggerEngine> engines = new HashSet<DebuggerEngine>();

        private Breakpoint first;
        private final List<Breakpoint> artificalBreakpoints;
        private final Map<URL, ArtifactsUpdated> listeners;
        private final WeakReference<Session> startedSessionRef[];
        private boolean enginesCheckDone = false;
        private final RequestProcessor rp;

        private Listener(Breakpoint first,
                         List<Breakpoint> artificalBreakpoints,
                         Map<URL, ArtifactsUpdated> listeners,
                         WeakReference<Session> startedSessionRef[],
                         RequestProcessor rp) {
            this.first = first;
            this.artificalBreakpoints = artificalBreakpoints;
            this.listeners = listeners;
            this.startedSessionRef = startedSessionRef;
            this.rp = rp;
        }

        @Override
        public void propertyChange (final PropertyChangeEvent e) {
            if (JPDADebugger.PROP_STATE.equals(e.getPropertyName ())) {
                int state = ((Integer) e.getNewValue ()).intValue ();
                if (state == JPDADebugger.STATE_STOPPED || state == JPDADebugger.STATE_DISCONNECTED) {
                    rp.post(new Runnable() {
                        @Override
                        public void run() {
                            if (first != null) {
                                DebuggerManager.getDebuggerManager().removeBreakpoint(first);
                                first = null;
                                ((JPDADebugger) e.getSource()).removePropertyChangeListener(JPDADebugger.PROP_STATE, pcl);
                            }
                        }
                    });
                }
            }
        }

        private void dispose() {
            DebuggerManager.getDebuggerManager ().removeDebuggerListener (
                DebuggerManager.PROP_DEBUGGER_ENGINES,
                this
            );
            rp.post (new Runnable () {
                @Override
                public void run () {
                    if (artificalBreakpoints != null) {
                        for (Breakpoint b : artificalBreakpoints) {
                            DebuggerManager.getDebuggerManager().removeBreakpoint(b);
                        }
                    }
                    if (first != null) {
                        DebuggerManager.getDebuggerManager().removeBreakpoint(first);
                    }
                    if (listeners != null) {
                        for (Entry<URL, ArtifactsUpdated> e : listeners.entrySet()) {
                            BuildArtifactMapper.removeArtifactsUpdatedListener(e.getKey(), e.getValue());
                        }
                    }
                }
            });
        }

        @Override
        public void engineAdded (DebuggerEngine engine) {
            // Consider only engines from the started session.
            Session session;
            synchronized (startedSessionRef) {
                session = startedSessionRef[0].get();
            }
            if (session != null) {
                // perform check
                boolean hasEngine = false;
                for (String l : session.getSupportedLanguages()) {
                    if (engine.equals(session.getEngineForLanguage(l))) {
                        hasEngine = true;
                        break;
                    }
                }
                if (!hasEngine) {
                    return;
                }
            }
            JPDADebugger debugger = engine.lookupFirst(null, JPDADebugger.class);
            if (debugger == null) return;
            debugger.addPropertyChangeListener (
                JPDADebugger.PROP_STATE,
                pcl
            );
            engines.add(engine);
        }

        @Override
        public void engineRemoved (DebuggerEngine engine) {
            Session session;
            synchronized (startedSessionRef) {
                session = startedSessionRef[0].get();
            }
            if (session != null && !enginesCheckDone) {
                // check each registered engine if it belong to the session
                enginesCheckDone = true;
                List<DebuggerEngine> list = new ArrayList<DebuggerEngine>(engines);
                for (DebuggerEngine eng : list) {
                    boolean hasEngine = false;
                    for (String l : session.getSupportedLanguages()) {
                        if (engine.equals(session.getEngineForLanguage(l))) {
                            hasEngine = true;
                            break;
                        }
                    }
                    if (!hasEngine) {
                        engines.remove(eng);
                    }
                }
            }
            JPDADebugger debugger = engine.lookupFirst(null, JPDADebugger.class);
            if (debugger == null) return;
            if (engines.remove(engine)) {
                debugger.removePropertyChangeListener (
                    JPDADebugger.PROP_STATE,
                    pcl
                );
            }
            if (engines.isEmpty()) {
                dispose();
            }
        }
    }

}
