2828import java .util .Iterator ;
2929import java .util .List ;
3030import java .util .Map ;
31+ import java .util .concurrent .CompletableFuture ;
3132import java .util .function .Consumer ;
3233import java .util .logging .Level ;
3334import java .util .logging .Logger ;
6061import com .microsoft .java .debug .core .DebugUtility ;
6162import com .microsoft .java .debug .core .IDebugSession ;
6263import com .microsoft .java .debug .core .StackFrameUtility ;
64+ import com .microsoft .java .debug .core .adapter .HotCodeReplaceEvent ;
6365import com .microsoft .java .debug .core .adapter .IDebugAdapterContext ;
6466import com .microsoft .java .debug .core .adapter .IHotCodeReplaceProvider ;
6567import com .microsoft .java .debug .core .protocol .Events ;
66- import com . microsoft . java . debug . core . protocol . Events . DebugEvent ;
68+
6769import com .sun .jdi .ArrayType ;
6870import com .sun .jdi .ClassNotLoadedException ;
6971import com .sun .jdi .IncompatibleThreadStateException ;
7476import com .sun .jdi .VirtualMachine ;
7577import com .sun .jdi .request .StepRequest ;
7678
79+ import io .reactivex .Observable ;
80+ import io .reactivex .subjects .PublishSubject ;
81+
7782/**
7883 * The hot code replace provider listens for changes to class files and notifies
7984 * the running debug session of the changes.
@@ -92,6 +97,8 @@ public class JavaHotCodeReplaceProvider implements IHotCodeReplaceProvider, IRes
9297
9398 private List <Consumer <List <String >>> consumers = new ArrayList <Consumer <List <String >>>();
9499
100+ private PublishSubject <HotCodeReplaceEvent > eventSubject = PublishSubject .<HotCodeReplaceEvent >create ();
101+
95102 /**
96103 * Visitor for resource deltas.
97104 */
@@ -249,45 +256,6 @@ private IResource getSourceFile(IJavaProject project, String qualifiedName, Stri
249256 }
250257 }
251258
252- /**
253- * Hot code replace event type.
254- */
255- enum EventType {
256- ERROR (-1 ),
257-
258- WARNING (-2 ),
259-
260- STARTING (1 ),
261-
262- END (2 );
263-
264- private int value ;
265-
266- private EventType (int value ) {
267- this .value = value ;
268- }
269-
270- public int getValue () {
271- return this .value ;
272- }
273- }
274-
275- class HotCodeReplaceEvent extends DebugEvent {
276-
277- public EventType eventType ;
278-
279- public String message ;
280-
281- /**
282- * Constructor.
283- */
284- public HotCodeReplaceEvent (EventType eventType , String message ) {
285- super ("hotCodeReplace" );
286- this .eventType = eventType ;
287- this .message = message ;
288- }
289- }
290-
291259 @ Override
292260 public void initialize (IDebugAdapterContext context , Map <String , Object > options ) {
293261 if (DebugSettings .getCurrent ().enableHotCodeReplace ) {
@@ -319,6 +287,25 @@ public void onClassRedefined(Consumer<List<String>> consumer) {
319287 this .consumers .add (consumer );
320288 }
321289
290+ @ Override
291+ public CompletableFuture <List <String >> redefineClasses () {
292+ return CompletableFuture .supplyAsync (() -> {
293+ List <String > classNames = new ArrayList ();
294+
295+ // TODO: fill the class name collection by calling doHotCodeReplace
296+ return classNames ;
297+ });
298+ }
299+
300+ @ Override
301+ public Observable <HotCodeReplaceEvent > getEventHub () {
302+ return eventSubject ;
303+ }
304+
305+ private void publishEvent (HotCodeReplaceEvent .EventType type , String message ) {
306+ eventSubject .onNext (new HotCodeReplaceEvent (type , message ));
307+ }
308+
322309 private void doHotCodeReplace (List <IResource > resourcesToReplace , List <String > qualifiedNamesToReplace ) {
323310 if (context == null || currentDebugSession == null ) {
324311 return ;
@@ -340,8 +327,7 @@ private void doHotCodeReplace(List<IResource> resourcesToReplace, List<String> q
340327 return ;
341328 }
342329
343- context .getProtocolServer ()
344- .sendEvent (new HotCodeReplaceEvent (EventType .STARTING , "Start hot code replacement procedure..." ));
330+ publishEvent (HotCodeReplaceEvent .EventType .STARTING , "Start hot code replacement procedure..." );
345331
346332 try {
347333 List <ThreadReference > poppedThreads = new ArrayList <>();
@@ -361,8 +347,7 @@ private void doHotCodeReplace(List<IResource> resourcesToReplace, List<String> q
361347 }
362348
363349 if (containsObsoleteMethods ()) {
364- context .getProtocolServer ()
365- .sendEvent (new HotCodeReplaceEvent (EventType .ERROR , "JVM contains obsolete methods" ));
350+ publishEvent (HotCodeReplaceEvent .EventType .ERROR , "JVM contains obsolete methods" );
366351 }
367352
368353 if (currentDebugSession .getVM ().canPopFrames () && framesPopped ) {
@@ -373,7 +358,7 @@ private void doHotCodeReplace(List<IResource> resourcesToReplace, List<String> q
373358 } catch (DebugException e ) {
374359 logger .log (Level .SEVERE , "Failed to complete hot code replace: " + e .getMessage (), e );
375360 } finally {
376- context . getProtocolServer (). sendEvent ( new HotCodeReplaceEvent ( EventType .END , "Completed hot code replace" ) );
361+ publishEvent ( HotCodeReplaceEvent . EventType .END , "Completed hot code replace" );
377362 }
378363
379364 threadFrameMap .clear ();
@@ -627,7 +612,7 @@ private void redefineTypesJDK(List<IResource> resources, List<String> qualifiedN
627612 currentDebugSession .getVM ().redefineClasses (typesToBytes );
628613 } catch (UnsupportedOperationException | NoClassDefFoundError | VerifyError | ClassFormatError
629614 | ClassCircularityError e ) {
630- context . getProtocolServer (). sendEvent ( new HotCodeReplaceEvent ( EventType .ERROR , e .getMessage () ));
615+ publishEvent ( HotCodeReplaceEvent . EventType .ERROR , e .getMessage ());
631616 throw new DebugException ("Failed to redefine classes: " + e .getMessage ());
632617 }
633618 }
0 commit comments