/projects/netbeans-7.3/debugger.jpda.ant/antsrc/org/netbeans/modules/debugger/jpda/ant/JPDAStart.java
https://gitlab.com/essere.lab.public/qualitas.class-corpus · Java · 990 lines · 767 code · 83 blank · 140 comment · 151 complexity · 18f28afc539f1e5e054beda77553796c MD5 · raw file
- /*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
- *
- * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
- * Other names may be trademarks of their respective owners.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common
- * Development and Distribution License("CDDL") (collectively, the
- * "License"). You may not use this file except in compliance with the
- * License. You can obtain a copy of the License at
- * http://www.netbeans.org/cddl-gplv2.html
- * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
- * specific language governing permissions and limitations under the
- * License. When distributing the software, include this License Header
- * Notice in each file and include the License file at
- * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the GPL Version 2 section of the License file that
- * accompanied this code. If applicable, add the following below the
- * License Header, with the fields enclosed by brackets [] replaced by
- * your own identifying information:
- * "Portions Copyrighted [year] [name of copyright owner]"
- *
- * Contributor(s):
- *
- * The Original Software is NetBeans. The Initial Developer of the Original
- * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
- * Microsystems, Inc. All Rights Reserved.
- *
- * If you wish your version of this file to be governed by only the CDDL
- * or only the GPL Version 2, indicate your decision by adding
- * "[Contributor] elects to include this software in this distribution
- * under the [CDDL or GPL Version 2] license." If you do not indicate a
- * single choice of license, a recipient has the option to distribute
- * your version of this file under either the CDDL, the GPL Version 2 or
- * to extend the choice of license to its licensees as provided above.
- * However, if you add GPL Version 2 code and therefore, elected the GPL
- * Version 2 license, then the option applies only if the new code is
- * made subject to such option by the copyright holder.
- */
- 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.lang.ref.WeakReference;
- import java.net.InetAddress;
- import java.net.UnknownHostException;
- import java.util.Collection;
- import java.util.LinkedList;
- import java.util.Map.Entry;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- import java.util.regex.Pattern;
- 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.ErrorManager;
- import org.openide.filesystems.FileStateInvalidException;
- 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.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 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
- /** 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;
- private final Object [] lock = new Object[2];
- /** The class debugger should stop in, or null. */
- private String stopClassName = null;
- private String listeningCP = null;
- private RequestProcessor rp = new RequestProcessor("JPDAStart", 1);
-
- // properties ..............................................................
- public void setAddressProperty (String propertyName) {
- this.addressProperty = propertyName;
- }
- private String getAddressProperty () {
- return addressProperty;
- }
- public void setTransport (String transport) {
- logger.fine("Set transport: '"+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 addClasspath (Path path) {
- logger.fine("addClasspath("+path+")");
- if (classpath != null)
- throw new BuildException ("Only one classpath subelement is supported");
- classpath = path;
- }
- public void addBootclasspath (Path path) {
- logger.fine("addBootclasspath("+path+")");
- if (bootclasspath != null)
- throw new BuildException ("Only one bootclasspath subelement is supported");
- bootclasspath = path;
- }
- public void addSourcepath (Sourcepath path) {
- logger.fine("addSourcepath("+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(), 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);
- }
- }
- 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) {
- localAddress.setValue("127.0.0.1"); // NOI18N
- }
- 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.fine(" socket listening at " + address+", host = "+host+", port = "+port); // NOI18N
- try {
- InetAddress.getByName(host);
- } catch (UnknownHostException uhex) {
- logger.fine( "unknown host '"+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 (),
- classpath,
- plainSourcepath,
- isSourcePathExclusive
- );
- ClassPath jdkSourcePath = createJDKSourcePath (
- getProject (),
- bootclasspath
- );
- if (logger.isLoggable(Level.FINE)) {
- logger.fine("Create sourcepath:"); // NOI18N
- logger.fine(" classpath : " + classpath); // NOI18N
- logger.fine(" sourcepath : " + plainSourcepath); // NOI18N
- logger.fine(" bootclasspath : " + bootclasspath); // NOI18N
- logger.fine(" >> sourcePath : " + sourcePath); // NOI18N
- logger.fine(" >> jdkSourcePath : " + jdkSourcePath); // NOI18N
- }
- Breakpoint first = null;
- if (stopClassName != null && stopClassName.length() > 0) {
- logger.fine(
- "create method breakpoint, class name = " + // NOI18N
- stopClassName
- );
- first = createBreakpoint (stopClassName);
- }
- debug ("Debugger started"); // NOI18N
- logger.fine("start listening at " + 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");
- File baseDir;
- if (workDir != null) {
- baseDir = new File(workDir);
- } else {
- baseDir = getProject().getBaseDir();
- }
- properties.put ("baseDir", baseDir); // NOI18N
- logger.fine("JPDAStart: properties = "+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() {
- public void run() {
- synchronized (listeningStarted) {
- listeningThreadPtr[0] = Thread.currentThread();
- listeningStarted[0] = true;
- listeningStarted.notifyAll();
- }
- try {
- DebuggerEngine[] engines = JPDADebugger.startListeningAndGetEngines (
- flc,
- args,
- new Object[] { properties }
- );
- 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() {
- public void messageLogged(BuildEvent event) {}
- public void taskStarted(BuildEvent event) { }
- public void taskFinished(BuildEvent event) {}
- public void targetStarted(BuildEvent event) {}
- public void targetFinished(BuildEvent event) {}
- public void buildStarted(BuildEvent event) {}
- 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.fine("buildFinished: listening thread = "+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.fine("buildFinished: killing session "+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() {
- 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 final static void debug (String msg) {
- if (!logger.isLoggable(Level.FINER)) return;
- logger.finer (
- new Date() + " [" + Thread.currentThread().getName() +
- "] - " + msg
- );
- }
- static ClassPath createSourcePath (
- Project project,
- Path classpath,
- Path sourcepath,
- boolean isSourcePathExclusive
- ) {
- if (sourcepath != null && isSourcePathExclusive) {
- return convertToClassPath (project, sourcepath);
- }
- ClassPath cp = convertToSourcePath (project, classpath, true);
- ClassPath sp = convertToClassPath (project, sourcepath);
- ClassPath sourcePath = ClassPathSupport.createProxyClassPath (
- new ClassPath[] {cp, sp}
- );
- return sourcePath;
- }
- 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]);
- File file = FileUtil.normalizeFile
- (project.resolveFile (pathName));
- if (!isValid (file, project)) continue;
- URL url = fileToURL (file, project, reportNonExistingFiles, true);
- if (url == null) continue;
- logger.fine("convertToSourcePath - class: " + url); // NOI18N
- try {
- SourceForBinaryQuery.Result srcRootsResult = SourceForBinaryQuery.findSourceRoots(url);
- FileObject fos[] = srcRootsResult.getRoots();
- int j, jj = fos.length;
- logger.fine(" source roots = "+java.util.Arrays.asList(fos)+"; jj = "+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++) {
- logger.fine("convertToSourcePath - source : " + fos [j]); // NOI18N
- if (FileUtil.isArchiveFile (fos [j]))
- fos [j] = FileUtil.getArchiveRoot (fos [j]);
- try {
- url = fos [j].getURL ();
- } catch (FileStateInvalidException ex) {
- ErrorManager.getDefault ().notify
- (ErrorManager.EXCEPTION, ex);
- continue;
- }
- if (url == null) continue;
- if (!exist.contains (url)) {
- l.add (ClassPathSupport.createResource (url));
- exist.add (url);
- }
- } // for
- } catch (IllegalArgumentException ex) {
- ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, ex);
- logger.fine("Have illegal url! "+ex.getLocalizedMessage()); // NOI18N
- }
- }
- return ClassPathSupport.createClassPath (l);
- }
- private static URL fileToURL (File file, Project project, boolean reportNonExistingFiles, boolean withSlash) {
- try {
- 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.getURL ();
- }
- } catch (FileStateInvalidException e) {
- ErrorManager.getDefault ().notify (ErrorManager.EXCEPTION, e);
- return null;
- }
- }
- 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.fine("new Sourcepath("+p+")");
- }
- public Sourcepath(Project p, String path) {
- super(p, path);
- this.path = path;
- logger.fine("new Sourcepath("+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() {
- public void run() {
- if (first != null) {
- DebuggerManager.getDebuggerManager().removeBreakpoint(first);
- first = null;
- ((JPDADebugger) e.getSource()).removePropertyChangeListener(JPDADebugger.PROP_STATE, pcl);
- }
- }
- });
- }
- }
- return;
- }
- private void dispose() {
- DebuggerManager.getDebuggerManager ().removeDebuggerListener (
- DebuggerManager.PROP_DEBUGGER_ENGINES,
- this
- );
- rp.post (new Runnable () {
- 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();
- }
- }
- }
- }