mirror of
https://github.com/angryip/ipscan.git
synced 2025-10-26 11:18:17 +00:00
StateMachine is now in charge of state transitions
git-svn-id: https://ipscan.svn.sourceforge.net/svnroot/ipscan/trunk@137 375186e5-ef17-0410-b0b6-91563547dcda
This commit is contained in:
parent
662e111d04
commit
43df609c1b
@ -38,6 +38,7 @@ public class ScannerThread extends Thread {
|
||||
// this thread is daemon because we want JVM to terminate it
|
||||
// automatically if user closes the program (Main thread, that is)
|
||||
setDaemon(true);
|
||||
|
||||
this.feeder = feeder;
|
||||
this.scanner = scanner;
|
||||
this.scanningResultList = scanningResults;
|
||||
@ -47,11 +48,8 @@ public class ScannerThread extends Thread {
|
||||
}
|
||||
|
||||
public void run() {
|
||||
stateMachine.transitionTo(ScanningState.SCANNING);
|
||||
|
||||
while(feeder.hasNext() && stateMachine.isState(ScanningState.SCANNING)) {
|
||||
while(feeder.hasNext() && stateMachine.inState(ScanningState.SCANNING)) {
|
||||
try {
|
||||
|
||||
// make a small delay between thread creation
|
||||
Thread.sleep(config.threadDelay);
|
||||
|
||||
@ -81,13 +79,13 @@ public class ScannerThread extends Thread {
|
||||
// scan each IP in parallel, in a separate thread
|
||||
new IPThread(address, preparationNumber).start();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// inform that no more addresses left
|
||||
stateMachine.transitionTo(ScanningState.STOPPING);
|
||||
stateMachine.stop();
|
||||
|
||||
// now wait for all threads, which are still running
|
||||
try {
|
||||
@ -104,17 +102,9 @@ public class ScannerThread extends Thread {
|
||||
scanner.cleanup();
|
||||
|
||||
// finally, the scanning is complete
|
||||
stateMachine.transitionTo(ScanningState.IDLE);
|
||||
stateMachine.complete();
|
||||
}
|
||||
|
||||
public void forceStop() {
|
||||
stateMachine.transitionTo(ScanningState.STOPPING);
|
||||
}
|
||||
|
||||
public void abort() {
|
||||
stateMachine.transitionTo(ScanningState.KILLING);
|
||||
}
|
||||
|
||||
|
||||
// TODO: remove me and change to constructor injection
|
||||
public void setResultsCallback(ScanningResultsCallback resultsCallback) {
|
||||
this.resultsCallback = resultsCallback;
|
||||
|
||||
@ -7,23 +7,13 @@ package net.azib.ipscan.core;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
import net.azib.ipscan.core.state.ScanningState;
|
||||
|
||||
/**
|
||||
* This callback is called on scanning state updates.
|
||||
*
|
||||
* @author anton
|
||||
*/
|
||||
public interface ScanningProgressCallback {
|
||||
|
||||
/**
|
||||
* This method is called on scanner state changes,
|
||||
* eg. when scanning is about to stop.
|
||||
*
|
||||
* @param new state
|
||||
*/
|
||||
public void scannerStateChanged(ScanningState state);
|
||||
|
||||
|
||||
/**
|
||||
* This method is called on scanning progress updates.
|
||||
* There are no guarantees that this method is called on every
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
|
||||
package net.azib.ipscan.core.state;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ScanningState enum - all possible states.
|
||||
@ -21,7 +21,7 @@ public enum ScanningState {
|
||||
STOPPING,
|
||||
KILLING;
|
||||
|
||||
private Set<StateTransitionListener> listeners = new HashSet<StateTransitionListener>();
|
||||
private List<StateTransitionListener> listeners = new ArrayList<StateTransitionListener>();
|
||||
|
||||
/**
|
||||
* Transitions the state to the next one
|
||||
@ -31,6 +31,10 @@ public enum ScanningState {
|
||||
return states[ordinal()+1 % states.length];
|
||||
}
|
||||
|
||||
public void addTransitionListener(StateTransitionListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies all registered listeners of the transition to this state.
|
||||
*/
|
||||
|
||||
@ -6,7 +6,10 @@
|
||||
|
||||
package net.azib.ipscan.core.state;
|
||||
|
||||
import net.azib.ipscan.core.ScanningProgressCallback;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.azib.ipscan.config.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* StateMachine
|
||||
@ -15,19 +18,15 @@ import net.azib.ipscan.core.ScanningProgressCallback;
|
||||
*/
|
||||
public class StateMachine {
|
||||
|
||||
private ScanningProgressCallback progressCallback;
|
||||
private static final Logger LOG = LoggerFactory.getLogger();
|
||||
|
||||
private ScanningState state = ScanningState.IDLE;
|
||||
|
||||
public void transitionTo(ScanningState newState) {
|
||||
this.state = newState;
|
||||
progressCallback.scannerStateChanged(newState);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state
|
||||
* @return true if current state is as specified
|
||||
*/
|
||||
public boolean isState(ScanningState state) {
|
||||
public boolean inState(ScanningState state) {
|
||||
return this.state == state;
|
||||
}
|
||||
|
||||
@ -38,8 +37,48 @@ public class StateMachine {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setScanningProgressCallback(ScanningProgressCallback progressCallback) {
|
||||
this.progressCallback = progressCallback;
|
||||
/**
|
||||
* Transitions to the specified state, notifying all listeners.
|
||||
* @param newState
|
||||
*/
|
||||
public void transitionTo(ScanningState newState) {
|
||||
state = newState;
|
||||
state.notifyOnEntry();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transitions to the next state in the sequence.
|
||||
* Called when user presses the scan button.
|
||||
*/
|
||||
public void transitionToNext() {
|
||||
// killing state cannot be transitioned from by pressing a button
|
||||
if (state != ScanningState.KILLING) {
|
||||
transitionTo(state.next());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transitions to the stopping state
|
||||
*/
|
||||
public void stop() {
|
||||
if (state == ScanningState.SCANNING) {
|
||||
transitionTo(ScanningState.STOPPING);
|
||||
}
|
||||
else {
|
||||
LOG.warning("Attempt to stop from " + state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transitions back to the idle state
|
||||
*/
|
||||
public void complete() {
|
||||
if (state == ScanningState.STOPPING || state == ScanningState.KILLING) {
|
||||
transitionTo(ScanningState.IDLE);
|
||||
}
|
||||
else {
|
||||
LOG.warning("Attempt to complete from " + state);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import net.azib.ipscan.core.ScannerThreadFactory;
|
||||
import net.azib.ipscan.core.ScanningProgressCallback;
|
||||
import net.azib.ipscan.core.state.ScanningState;
|
||||
import net.azib.ipscan.core.state.StateMachine;
|
||||
import net.azib.ipscan.core.state.StateTransitionListener;
|
||||
import net.azib.ipscan.gui.ResultTable;
|
||||
import net.azib.ipscan.gui.ScanningResultsConsumer;
|
||||
import net.azib.ipscan.gui.StatusBar;
|
||||
@ -30,7 +31,7 @@ import org.eclipse.swt.widgets.Display;
|
||||
*
|
||||
* @author anton
|
||||
*/
|
||||
public class StartStopScanningAction implements SelectionListener, ScanningProgressCallback {
|
||||
public class StartStopScanningAction implements SelectionListener, ScanningProgressCallback, StateTransitionListener {
|
||||
|
||||
private ScannerThreadFactory scannerThreadFactory;
|
||||
private ScannerThread scannerThread;
|
||||
@ -53,10 +54,7 @@ public class StartStopScanningAction implements SelectionListener, ScanningProgr
|
||||
this.feederRegistry = feederRegistry;
|
||||
this.button = startStopButton;
|
||||
this.display = button.getDisplay();
|
||||
|
||||
this.stateMachine = stateMachine;
|
||||
// TODO: remove this, use state transition notifications
|
||||
this.stateMachine.setScanningProgressCallback(this);
|
||||
|
||||
// pre-load button images
|
||||
buttonImages[ScanningState.IDLE.ordinal()] = new Image(null, Labels.getInstance().getImageAsStream("button.start.img"));
|
||||
@ -69,6 +67,11 @@ public class StartStopScanningAction implements SelectionListener, ScanningProgr
|
||||
buttonTexts[ScanningState.SCANNING.ordinal()] = Labels.getLabel("button.stop");
|
||||
buttonTexts[ScanningState.STOPPING.ordinal()] = Labels.getLabel("button.kill");
|
||||
buttonTexts[ScanningState.KILLING.ordinal()] = Labels.getLabel("button.kill");
|
||||
|
||||
// add listeners to all state changes
|
||||
for (ScanningState state : ScanningState.values()) {
|
||||
state.addTransitionListener(this);
|
||||
}
|
||||
|
||||
// set the defaultimage
|
||||
ScanningState state = stateMachine.getState();
|
||||
@ -81,31 +84,13 @@ public class StartStopScanningAction implements SelectionListener, ScanningProgr
|
||||
}
|
||||
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
switch (stateMachine.getState()) {
|
||||
case IDLE:
|
||||
// start the scan!
|
||||
resultTable.initNewScan(feederRegistry.current().getInfo());
|
||||
ScanningResultsConsumer resultsConsumer = new ScanningResultsConsumer(resultTable);
|
||||
scannerThread = scannerThreadFactory.createScannerThread(feederRegistry.current().getFeeder(), this);
|
||||
// TODO: fix this: this is needed here to avoid cylic dependencies...
|
||||
scannerThread.setResultsCallback(resultsConsumer);
|
||||
scannerThread.start();
|
||||
break;
|
||||
case SCANNING:
|
||||
scannerThread.forceStop();
|
||||
break;
|
||||
case STOPPING:
|
||||
scannerThread.abort();
|
||||
break;
|
||||
case KILLING:
|
||||
break;
|
||||
}
|
||||
stateMachine.transitionToNext();
|
||||
}
|
||||
|
||||
public void scannerStateChanged(final ScanningState state) {
|
||||
public void transitionTo(final ScanningState state) {
|
||||
if (display.isDisposed())
|
||||
return;
|
||||
display.asyncExec(new Runnable() {
|
||||
display.syncExec(new Runnable() {
|
||||
public void run() {
|
||||
if (statusBar.isDisposed())
|
||||
return;
|
||||
@ -116,6 +101,15 @@ public class StartStopScanningAction implements SelectionListener, ScanningProgr
|
||||
statusBar.setStatusText(null);
|
||||
statusBar.setProgress(0);
|
||||
break;
|
||||
case SCANNING:
|
||||
// start the scan!
|
||||
resultTable.initNewScan(feederRegistry.current().getInfo());
|
||||
ScanningResultsConsumer resultsConsumer = new ScanningResultsConsumer(resultTable);
|
||||
scannerThread = scannerThreadFactory.createScannerThread(feederRegistry.current().getFeeder(), StartStopScanningAction.this);
|
||||
// TODO: fix this: this is needed here to avoid cylic dependencies...
|
||||
scannerThread.setResultsCallback(resultsConsumer);
|
||||
scannerThread.start();
|
||||
break;
|
||||
case STOPPING:
|
||||
statusBar.setStatusText(Labels.getLabel("state.waitForThreads"));
|
||||
break;
|
||||
@ -150,5 +144,5 @@ public class StartStopScanningAction implements SelectionListener, ScanningProgr
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user