1.1 --- a/dew4nb/src/org/netbeans/modules/dew4nb/services/debugger/ActiveSessions.java Tue Feb 11 13:50:52 2014 +0100
1.2 +++ b/dew4nb/src/org/netbeans/modules/dew4nb/services/debugger/ActiveSessions.java Tue Feb 11 18:05:20 2014 +0100
1.3 @@ -107,48 +107,48 @@
1.4 @NonNull final WorkspaceResolver.Context context,
1.5 @NonNull final EndPoint.Env env) {
1.6 Parameters.notNull("context", context); //NOI18N
1.7 - Parameters.notNull("env", env); //NOI18N
1.8 - final int id = sequencer.incrementAndGet();
1.9 - Session session;
1.10 + Parameters.notNull("env", env); //NOI18N
1.11 + Session session = null;
1.12 + final DebugInterceptor di = DebugInterceptor.getInstance();
1.13 try {
1.14 - for (session = findSession(); session == null; session = findSession()) {
1.15 - LOG.info("Wating for debugger...."); //NOI18N
1.16 + for (session = findSession(); session == null && di.isDebuggerStarting(); session = findSession()) {
1.17 + LOG.info("Wating for debugger session...."); //NOI18N
1.18 Thread.sleep(1000);
1.19 }
1.20 } catch (InterruptedException ie) {
1.21 - return -1;
1.22 + //Pass
1.23 }
1.24 - if (session != null) {
1.25 - if (active.putIfAbsent(id, new Data(id, context, env, session)) != null) {
1.26 - throw new IllegalStateException("Trying to reuse active session"); //NOI18N
1.27 - }
1.28 - final JPDADebugger jpda = session.lookupFirst(null, JPDADebugger.class);
1.29 - if (!(jpda instanceof JPDADebuggerImpl)) {
1.30 - throw new IllegalStateException("Wrong debugger service."); //NOI18N
1.31 - }
1.32 - try {
1.33 - jpda.waitRunning();
1.34 - //Hack:
1.35 - //Now comes the fun, JPDADebuggerImpl is full of races
1.36 - //so after wait we need to busy wait. Inverted spin-park :-)
1.37 - while (jpda.getState() < 2) {
1.38 - Thread.sleep(500);
1.39 - }
1.40 - } catch (DebuggerStartException | InterruptedException ex) {
1.41 - LOG.log(Level.WARNING, "Debugger start Exception: {0}", ex);
1.42 - return -1;
1.43 - }
1.44 - final int state = jpda.getState();
1.45 - if (state == JPDADebugger.STATE_RUNNING || state == JPDADebugger.STATE_STOPPED) {
1.46 - return id;
1.47 - } else {
1.48 - LOG.log(Level.WARNING, "Wrong debugger state: {0}", state);
1.49 - return -1;
1.50 - }
1.51 - } else {
1.52 + if (session == null) {
1.53 LOG.warning("No debugger session");
1.54 return -1;
1.55 }
1.56 + final int id = sequencer.incrementAndGet();
1.57 + if (active.putIfAbsent(id, new Data(id, context, env, session)) != null) {
1.58 + throw new IllegalStateException("Trying to reuse active session"); //NOI18N
1.59 + }
1.60 + final JPDADebugger jpda = session.lookupFirst(null, JPDADebugger.class);
1.61 + if (!(jpda instanceof JPDADebuggerImpl)) {
1.62 + throw new IllegalStateException("Wrong debugger service."); //NOI18N
1.63 + }
1.64 + try {
1.65 + jpda.waitRunning();
1.66 + //Hack:
1.67 + //Now comes the fun, JPDADebuggerImpl is full of races
1.68 + //so after wait we need to busy wait. Inverted spin-park :-)
1.69 + while (jpda.getState() < 2) {
1.70 + Thread.sleep(500);
1.71 + }
1.72 + } catch (DebuggerStartException | InterruptedException ex) {
1.73 + LOG.log(Level.WARNING, "Debugger start Exception: {0}", ex);
1.74 + return -1;
1.75 + }
1.76 + final int state = jpda.getState();
1.77 + if (state == JPDADebugger.STATE_RUNNING || state == JPDADebugger.STATE_STOPPED) {
1.78 + return id;
1.79 + } else {
1.80 + LOG.log(Level.WARNING, "Wrong debugger state: {0}", state);
1.81 + return -1;
1.82 + }
1.83 }
1.84
1.85 @CheckForNull
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/dew4nb/src/org/netbeans/modules/dew4nb/services/debugger/DebugInterceptor.java Tue Feb 11 18:05:20 2014 +0100
2.3 @@ -0,0 +1,110 @@
2.4 +/*
2.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2.6 + *
2.7 + * Copyright 2014 Oracle and/or its affiliates. All rights reserved.
2.8 + *
2.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
2.10 + * Other names may be trademarks of their respective owners.
2.11 + *
2.12 + * The contents of this file are subject to the terms of either the GNU
2.13 + * General Public License Version 2 only ("GPL") or the Common
2.14 + * Development and Distribution License("CDDL") (collectively, the
2.15 + * "License"). You may not use this file except in compliance with the
2.16 + * License. You can obtain a copy of the License at
2.17 + * http://www.netbeans.org/cddl-gplv2.html
2.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
2.19 + * specific language governing permissions and limitations under the
2.20 + * License. When distributing the software, include this License Header
2.21 + * Notice in each file and include the License file at
2.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
2.23 + * particular file as subject to the "Classpath" exception as provided
2.24 + * by Oracle in the GPL Version 2 section of the License file that
2.25 + * accompanied this code. If applicable, add the following below the
2.26 + * License Header, with the fields enclosed by brackets [] replaced by
2.27 + * your own identifying information:
2.28 + * "Portions Copyrighted [year] [name of copyright owner]"
2.29 + *
2.30 + * If you wish your version of this file to be governed by only the CDDL
2.31 + * or only the GPL Version 2, indicate your decision by adding
2.32 + * "[Contributor] elects to include this software in this distribution
2.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
2.34 + * single choice of license, a recipient has the option to distribute
2.35 + * your version of this file under either the CDDL, the GPL Version 2 or
2.36 + * to extend the choice of license to its licensees as provided above.
2.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
2.38 + * Version 2 license, then the option applies only if the new code is
2.39 + * made subject to such option by the copyright holder.
2.40 + *
2.41 + * Contributor(s):
2.42 + *
2.43 + * Portions Copyrighted 2014 Sun Microsystems, Inc.
2.44 + */
2.45 +
2.46 +package org.netbeans.modules.dew4nb.services.debugger;
2.47 +
2.48 +import java.util.logging.Logger;
2.49 +import org.netbeans.api.annotations.common.NonNull;
2.50 +import org.netbeans.api.debugger.DebuggerManager;
2.51 +import org.netbeans.api.debugger.Session;
2.52 +import org.netbeans.modules.dew4nb.endpoint.EndPoint;
2.53 +import org.netbeans.modules.dew4nb.services.project.ProjectAction;
2.54 +import org.netbeans.modules.dew4nb.services.project.ProjectActionInterceptor;
2.55 +import org.netbeans.spi.project.ActionProvider;
2.56 +import org.openide.util.Lookup;
2.57 +import org.openide.util.lookup.ServiceProvider;
2.58 +
2.59 +/**
2.60 + *
2.61 + * @author Tomas Zezula
2.62 + */
2.63 +@ServiceProvider(service = ProjectActionInterceptor.class)
2.64 +public final class DebugInterceptor implements ProjectActionInterceptor {
2.65 +
2.66 + private static final Logger LOG = Logger.getLogger(DebugInterceptor.class.getName());
2.67 +
2.68 + private volatile boolean debuggerStarting;
2.69 +
2.70 + @Override
2.71 + public void started(
2.72 + @NonNull final EndPoint.Env env,
2.73 + @NonNull final ProjectAction request) {
2.74 + LOG.fine("started"); //NOI18N
2.75 + if (ActionProvider.COMMAND_DEBUG.equals(request.getAction())) {
2.76 + LOG.fine("debug"); //NOI18N
2.77 + debuggerStarting = true;
2.78 + killAllExistingSessions();
2.79 + }
2.80 + }
2.81 +
2.82 + @Override
2.83 + public void finished(
2.84 + @NonNull final EndPoint.Env env,
2.85 + @NonNull final ProjectAction request,
2.86 + final boolean result) {
2.87 + LOG.fine("finished"); //NOI18N
2.88 + if (ActionProvider.COMMAND_DEBUG.equals(request.getAction())) {
2.89 + LOG.fine("debug"); //NOI18N
2.90 + debuggerStarting = false;
2.91 + }
2.92 + }
2.93 +
2.94 + boolean isDebuggerStarting() {
2.95 + return debuggerStarting;
2.96 + }
2.97 +
2.98 + private void killAllExistingSessions() {
2.99 + for (Session s : DebuggerManager.getDebuggerManager().getSessions()) {
2.100 + s.kill();
2.101 + }
2.102 + }
2.103 +
2.104 + @NonNull
2.105 + static DebugInterceptor getInstance() {
2.106 + for (ProjectActionInterceptor i : Lookup.getDefault().lookupAll(ProjectActionInterceptor.class)) {
2.107 + if (i.getClass() == DebugInterceptor.class) {
2.108 + return DebugInterceptor.class.cast(i);
2.109 + }
2.110 + }
2.111 + throw new IllegalStateException("Not registered in Lookup"); //NOI18N
2.112 + }
2.113 +}
3.1 --- a/dew4nb/src/org/netbeans/modules/dew4nb/services/project/IORedirectProvider.java Tue Feb 11 13:50:52 2014 +0100
3.2 +++ b/dew4nb/src/org/netbeans/modules/dew4nb/services/project/IORedirectProvider.java Tue Feb 11 18:05:20 2014 +0100
3.3 @@ -60,6 +60,7 @@
3.4 import org.netbeans.api.annotations.common.NullAllowed;
3.5 import org.netbeans.modules.dew4nb.endpoint.EndPoint;
3.6 import org.netbeans.modules.dew4nb.endpoint.Status;
3.7 +import org.openide.util.Pair;
3.8 import org.openide.util.Parameters;
3.9 import org.openide.util.lookup.ServiceProvider;
3.10 import org.openide.windows.IOProvider;
3.11 @@ -74,11 +75,8 @@
3.12 @ServiceProvider(service = IOProvider.class, position = 0)
3.13 public class IORedirectProvider extends IOProvider {
3.14
3.15 - static final String PROP_STATE = "state"; //NOI18N
3.16 - static final String PROP_TYPE = "type"; //NOI18N
3.17 -
3.18 private static final Pattern EMPTY_STR = Pattern.compile("^\\s*$"); //NOI18N
3.19 - private static final ThreadLocal<EndPoint.Env> currentEnv = new ThreadLocal<>();
3.20 + private static final ThreadLocal<Pair<EndPoint.Env,String>> currentEnv = new ThreadLocal<>();
3.21 private static final Object threadsLock = new Object();
3.22 //@GuardedBy("threadsLock")
3.23 private static final Map<RedirectIO,Collection<Reference<Thread>>> activeThreads =
3.24 @@ -87,9 +85,17 @@
3.25 public IORedirectProvider() {}
3.26
3.27
3.28 - static void bindEnv(@NonNull final EndPoint.Env env) {
3.29 + static void bindEnv(
3.30 + @NonNull final EndPoint.Env env,
3.31 + @NonNull final ProjectAction request) {
3.32 Parameters.notNull("env", env); //NOI18N
3.33 - currentEnv.set(env);
3.34 + Parameters.notNull("request", request); //NOI18N
3.35 + if (ProjectMessageType.invokeAction != request.getType()) {
3.36 + throw new IllegalArgumentException(String.valueOf(request.getType()));
3.37 + }
3.38 + currentEnv.set(Pair.<EndPoint.Env,String>of(
3.39 + env,
3.40 + request.getState()));
3.41 }
3.42
3.43 static void unbindEnv() {
3.44 @@ -182,6 +188,7 @@
3.45
3.46 private final AtomicBoolean closed;
3.47 private volatile EndPoint.Env env;
3.48 + private volatile String state;
3.49
3.50 RedirectIO() {
3.51 this.closed = new AtomicBoolean();
3.52 @@ -259,7 +266,7 @@
3.53 @NonNull final String data,
3.54 final boolean err) {
3.55 env.sendObject(createResponse(
3.56 - env,
3.57 + state,
3.58 null,
3.59 err?
3.60 null :
3.61 @@ -273,7 +280,7 @@
3.62 void closeImpl() {
3.63 if (!closed.getAndSet(true)) {
3.64 env.sendObject(createResponse(
3.65 - env,
3.66 + state,
3.67 BuildResult.success,
3.68 null,
3.69 null,
3.70 @@ -284,7 +291,7 @@
3.71 void openUrlImpl(@NonNull final URL url) {
3.72 Parameters.notNull("url", url); //NOI18N
3.73 env.sendObject(createResponse(
3.74 - env,
3.75 + state,
3.76 null,
3.77 null,
3.78 null,
3.79 @@ -295,10 +302,12 @@
3.80 synchronized (threadsLock) {
3.81 activeThreads.remove(this);
3.82 }
3.83 - env = currentEnv.get();
3.84 - if (env == null) {
3.85 + final Pair<EndPoint.Env,String> p = currentEnv.get();
3.86 + if (p == null) {
3.87 throw new IllegalStateException();
3.88 }
3.89 + env = p.first();
3.90 + state = p.second();
3.91 closed.set(false);
3.92 }
3.93
3.94 @@ -426,18 +435,14 @@
3.95
3.96 @NonNull
3.97 private static InvokeProjectActionResult createResponse(
3.98 - @NonNull final EndPoint.Env env,
3.99 + @NonNull final String state,
3.100 @NullAllowed final BuildResult result,
3.101 @NullAllowed final String stdOut,
3.102 @NullAllowed final String stdErr,
3.103 @NullAllowed final Collection<? extends URL> urls) {
3.104 - Parameters.notNull("env", env); //NOI18N
3.105 - final ProjectMessageType type = env.getProperty(PROP_TYPE, ProjectMessageType.class);
3.106 - Parameters.notNull("type", type); //NOI18N
3.107 - final String state = env.getProperty(PROP_STATE, String.class);
3.108 Parameters.notNull("state", state); //NOI18N
3.109 final InvokeProjectActionResult res = new InvokeProjectActionResult();
3.110 - res.setType(type);
3.111 + res.setType(ProjectMessageType.invokeAction);
3.112 res.setState(state);
3.113 res.setStatus(Status.done);
3.114 res.setResult(result);
4.1 --- a/dew4nb/src/org/netbeans/modules/dew4nb/services/project/InvokeProjectActionHandler.java Tue Feb 11 13:50:52 2014 +0100
4.2 +++ b/dew4nb/src/org/netbeans/modules/dew4nb/services/project/InvokeProjectActionHandler.java Tue Feb 11 18:05:20 2014 +0100
4.3 @@ -43,6 +43,7 @@
4.4 package org.netbeans.modules.dew4nb.services.project;
4.5
4.6 import javax.swing.SwingUtilities;
4.7 +import org.netbeans.api.annotations.common.NonNull;
4.8 import org.netbeans.api.project.FileOwnerQuery;
4.9 import org.netbeans.api.project.Project;
4.10 import org.netbeans.modules.dew4nb.endpoint.AsyncRequestHandler;
4.11 @@ -50,9 +51,11 @@
4.12 import org.netbeans.modules.dew4nb.endpoint.RequestHandler;
4.13 import org.netbeans.modules.dew4nb.endpoint.Status;
4.14 import org.netbeans.modules.dew4nb.spi.WorkspaceResolver;
4.15 +import org.netbeans.spi.project.ActionProgress;
4.16 import org.netbeans.spi.project.ActionProvider;
4.17 import org.openide.filesystems.FileObject;
4.18 import org.openide.util.Lookup;
4.19 +import org.openide.util.Parameters;
4.20 import org.openide.util.lookup.Lookups;
4.21 import org.openide.util.lookup.ServiceProvider;
4.22
4.23 @@ -97,22 +100,51 @@
4.24 SwingUtilities.invokeLater(new Runnable() {
4.25 @Override
4.26 public void run() {
4.27 - env.setProperty(IORedirectProvider.PROP_TYPE, request.getType());
4.28 - env.setProperty(IORedirectProvider.PROP_STATE, request.getState());
4.29 - IORedirectProvider.bindEnv(env);
4.30 - try {
4.31 - ap.invokeAction(
4.32 - request.getAction(),
4.33 - Lookups.fixed(file, prj));
4.34 - } finally {
4.35 - IORedirectProvider.unbindEnv();
4.36 - }
4.37 + ap.invokeAction(
4.38 + request.getAction(),
4.39 + Lookups.fixed(
4.40 + file,
4.41 + prj,
4.42 + new Progress(env, request)));
4.43 }
4.44 });
4.45 }
4.46 }
4.47 }
4.48 return res;
4.49 - }
4.50 + }
4.51 +
4.52 + private static final class Progress extends ActionProgress {
4.53 +
4.54 + private static final Lookup.Result<ProjectActionInterceptor> impls =
4.55 + Lookup.getDefault().lookupResult(ProjectActionInterceptor.class);
4.56 + private final EndPoint.Env env;
4.57 + private final ProjectAction request;
4.58 +
4.59 + Progress(
4.60 + @NonNull final EndPoint.Env env,
4.61 + @NonNull final ProjectAction request) {
4.62 + Parameters.notNull("env", env); //NOI18N
4.63 + Parameters.notNull("request", request); //NOI18N
4.64 + this.env = env;
4.65 + this.request = request;
4.66 + IORedirectProvider.bindEnv(this.env, this.request);
4.67 + for (ProjectActionInterceptor interceptor : impls.allInstances()) {
4.68 + interceptor.started(this.env, this.request);
4.69 + }
4.70 + }
4.71 +
4.72 + @Override
4.73 + protected void started() {
4.74 + }
4.75 +
4.76 + @Override
4.77 + public void finished(boolean success) {
4.78 + IORedirectProvider.unbindEnv();
4.79 + for (ProjectActionInterceptor interceptor : impls.allInstances()) {
4.80 + interceptor.finished(this.env, this.request, success);
4.81 + }
4.82 + }
4.83 + }
4.84
4.85 }
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/dew4nb/src/org/netbeans/modules/dew4nb/services/project/ProjectActionInterceptor.java Tue Feb 11 18:05:20 2014 +0100
5.3 @@ -0,0 +1,55 @@
5.4 +/*
5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5.6 + *
5.7 + * Copyright 2014 Oracle and/or its affiliates. All rights reserved.
5.8 + *
5.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
5.10 + * Other names may be trademarks of their respective owners.
5.11 + *
5.12 + * The contents of this file are subject to the terms of either the GNU
5.13 + * General Public License Version 2 only ("GPL") or the Common
5.14 + * Development and Distribution License("CDDL") (collectively, the
5.15 + * "License"). You may not use this file except in compliance with the
5.16 + * License. You can obtain a copy of the License at
5.17 + * http://www.netbeans.org/cddl-gplv2.html
5.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
5.19 + * specific language governing permissions and limitations under the
5.20 + * License. When distributing the software, include this License Header
5.21 + * Notice in each file and include the License file at
5.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
5.23 + * particular file as subject to the "Classpath" exception as provided
5.24 + * by Oracle in the GPL Version 2 section of the License file that
5.25 + * accompanied this code. If applicable, add the following below the
5.26 + * License Header, with the fields enclosed by brackets [] replaced by
5.27 + * your own identifying information:
5.28 + * "Portions Copyrighted [year] [name of copyright owner]"
5.29 + *
5.30 + * If you wish your version of this file to be governed by only the CDDL
5.31 + * or only the GPL Version 2, indicate your decision by adding
5.32 + * "[Contributor] elects to include this software in this distribution
5.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
5.34 + * single choice of license, a recipient has the option to distribute
5.35 + * your version of this file under either the CDDL, the GPL Version 2 or
5.36 + * to extend the choice of license to its licensees as provided above.
5.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
5.38 + * Version 2 license, then the option applies only if the new code is
5.39 + * made subject to such option by the copyright holder.
5.40 + *
5.41 + * Contributor(s):
5.42 + *
5.43 + * Portions Copyrighted 2014 Sun Microsystems, Inc.
5.44 + */
5.45 +
5.46 +package org.netbeans.modules.dew4nb.services.project;
5.47 +
5.48 +import org.netbeans.api.annotations.common.NonNull;
5.49 +import org.netbeans.modules.dew4nb.endpoint.EndPoint;
5.50 +
5.51 +/**
5.52 + *
5.53 + * @author Tomas Zezula
5.54 + */
5.55 +public interface ProjectActionInterceptor {
5.56 + void started(@NonNull EndPoint.Env env, @NonNull final ProjectAction request);
5.57 + void finished(@NonNull EndPoint.Env env, @NonNull final ProjectAction request, boolean result);
5.58 +}