mirror of
https://github.com/angryip/ipscan.git
synced 2025-10-26 11:18:17 +00:00
Refactoring: states now has their special enum: ScanningState. No more int constants. StateMachine introduced, but not used much yet.
git-svn-id: https://ipscan.svn.sourceforge.net/svnroot/ipscan/trunk@135 375186e5-ef17-0410-b0b6-91563547dcda
This commit is contained in:
parent
603f7c0357
commit
2c68534ea7
@ -10,7 +10,7 @@
|
||||
<attribute name="org.eclipse.jdt.launching.CLASSPATH_ATTR_LIBRARY_PATH_ENTRY" value="ipscan/ext/rocksaw/lib"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="lib" path="ext/picocontainer/picocontainer-1.0.jar" sourcepath="ext/picocontainer/src"/>
|
||||
<classpathentry kind="lib" path="ext/picocontainer/picocontainer-1.0.jar"/>
|
||||
<classpathentry kind="lib" path="ext/swt/swt-gtk.jar"/>
|
||||
<classpathentry kind="lib" path="ext/swt/swt-mac.jar"/>
|
||||
<classpathentry kind="lib" path="ext/swt/swt-win32.jar"/>
|
||||
|
||||
@ -10,6 +10,7 @@ import net.azib.ipscan.core.ScannerThreadFactory;
|
||||
import net.azib.ipscan.core.ScanningResultList;
|
||||
import net.azib.ipscan.core.net.PingerRegistry;
|
||||
import net.azib.ipscan.core.net.PingerRegistryImpl;
|
||||
import net.azib.ipscan.core.state.StateMachine;
|
||||
import net.azib.ipscan.exporters.CSVExporter;
|
||||
import net.azib.ipscan.exporters.ExporterRegistry;
|
||||
import net.azib.ipscan.exporters.IPListExporter;
|
||||
@ -92,6 +93,7 @@ public class ComponentRegistry {
|
||||
container.registerComponentImplementation(PingerRegistry.class, PingerRegistryImpl.class);
|
||||
container.registerComponentImplementation(ScanningResultList.class);
|
||||
container.registerComponentImplementation(Scanner.class);
|
||||
container.registerComponentImplementation(StateMachine.class);
|
||||
container.registerComponentImplementation(ScannerThreadFactory.class);
|
||||
|
||||
// GUI follows (TODO: move GUI to a separate place)
|
||||
@ -157,7 +159,7 @@ public class ComponentRegistry {
|
||||
|
||||
container.registerComponentImplementation(OptionsDialog.class);
|
||||
container.registerComponentImplementation(SelectFetchersDialog.class);
|
||||
|
||||
|
||||
// various actions / listener
|
||||
container.registerComponentImplementation(StartStopScanningAction.class);
|
||||
container.registerComponentImplementation(ColumnsActions.SortBy.class);
|
||||
|
||||
@ -8,6 +8,8 @@ package net.azib.ipscan.core;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import net.azib.ipscan.config.GlobalConfig;
|
||||
import net.azib.ipscan.core.state.ScanningState;
|
||||
import net.azib.ipscan.core.state.StateMachine;
|
||||
import net.azib.ipscan.feeders.Feeder;
|
||||
|
||||
/**
|
||||
@ -18,18 +20,20 @@ import net.azib.ipscan.feeders.Feeder;
|
||||
public class ScannerThread extends Thread {
|
||||
|
||||
private Scanner scanner;
|
||||
private StateMachine stateMachine;
|
||||
private ScanningResultList scanningResultList;
|
||||
private Feeder feeder;
|
||||
private ScanningStateCallback statusCallback;
|
||||
private ScanningProgressCallback progressCallback;
|
||||
private ScanningResultsCallback resultsCallback;
|
||||
private int state;
|
||||
private int runningThreads;
|
||||
|
||||
private GlobalConfig config;
|
||||
|
||||
public ScannerThread(Feeder feeder, Scanner scanner, ScanningResultList scanningResults, GlobalConfig globalConfig) {
|
||||
public ScannerThread(Feeder feeder, Scanner scanner, StateMachine stateMachine, ScanningProgressCallback progressCallback, ScanningResultList scanningResults, GlobalConfig globalConfig) {
|
||||
super("Scanner Thread");
|
||||
this.config = globalConfig;
|
||||
this.stateMachine = stateMachine;
|
||||
this.progressCallback = progressCallback;
|
||||
|
||||
// this thread is daemon because we want JVM to terminate it
|
||||
// automatically if user closes the program (Main thread, that is)
|
||||
@ -43,9 +47,9 @@ public class ScannerThread extends Thread {
|
||||
}
|
||||
|
||||
public void run() {
|
||||
changeStatus(ScanningStateCallback.STATE_SCANNING);
|
||||
stateMachine.transitionTo(ScanningState.SCANNING);
|
||||
|
||||
while(feeder.hasNext() && state == ScanningStateCallback.STATE_SCANNING) {
|
||||
while(feeder.hasNext() && stateMachine.isState(ScanningState.SCANNING)) {
|
||||
try {
|
||||
|
||||
// make a small delay between thread creation
|
||||
@ -72,7 +76,7 @@ public class ScannerThread extends Thread {
|
||||
int preparationNumber = resultsCallback.prepareForResults(address);
|
||||
|
||||
// notify listeners of the progress we are doing
|
||||
statusCallback.updateProgress(address, runningThreads, feeder.getPercentageComplete());
|
||||
progressCallback.updateProgress(address, runningThreads, feeder.getPercentageComplete());
|
||||
|
||||
// scan each IP in parallel, in a separate thread
|
||||
new IPThread(address, preparationNumber).start();
|
||||
@ -83,14 +87,14 @@ public class ScannerThread extends Thread {
|
||||
}
|
||||
|
||||
// inform that no more addresses left
|
||||
changeStatus(ScanningStateCallback.STATE_STOPPING);
|
||||
stateMachine.transitionTo(ScanningState.STOPPING);
|
||||
|
||||
// now wait for all threads, which are still running
|
||||
try {
|
||||
// TODO: make a better and safer implementation
|
||||
while (runningThreads > 0) {
|
||||
Thread.sleep(200);
|
||||
statusCallback.updateProgress(null, runningThreads, 100);
|
||||
progressCallback.updateProgress(null, runningThreads, 100);
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
@ -100,28 +104,20 @@ public class ScannerThread extends Thread {
|
||||
scanner.cleanup();
|
||||
|
||||
// finally, the scanning is complete
|
||||
changeStatus(ScanningStateCallback.STATE_IDLE);
|
||||
stateMachine.transitionTo(ScanningState.IDLE);
|
||||
}
|
||||
|
||||
private void changeStatus(int status) {
|
||||
this.state = status;
|
||||
statusCallback.scannerStateChanged(status);
|
||||
}
|
||||
|
||||
|
||||
public void forceStop() {
|
||||
changeStatus(ScanningStateCallback.STATE_STOPPING);
|
||||
stateMachine.transitionTo(ScanningState.STOPPING);
|
||||
}
|
||||
|
||||
public void abort() {
|
||||
changeStatus(ScanningStateCallback.STATE_KILLING);
|
||||
}
|
||||
|
||||
public void setResultsCallback(ScanningResultsCallback resultsCallback) {
|
||||
this.resultsCallback = resultsCallback;
|
||||
stateMachine.transitionTo(ScanningState.KILLING);
|
||||
}
|
||||
|
||||
public void setStatusCallback(ScanningStateCallback statusCallback) {
|
||||
this.statusCallback = statusCallback;
|
||||
// TODO: remove me and change to constructor injection
|
||||
public void setResultsCallback(ScanningResultsCallback resultsCallback) {
|
||||
this.resultsCallback = resultsCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -6,10 +6,13 @@
|
||||
package net.azib.ipscan.core;
|
||||
|
||||
import net.azib.ipscan.config.GlobalConfig;
|
||||
import net.azib.ipscan.core.state.StateMachine;
|
||||
import net.azib.ipscan.feeders.Feeder;
|
||||
|
||||
/**
|
||||
* ScannerThreadFactory
|
||||
* ScannerThreadFactory.
|
||||
*
|
||||
* Note: setter injection is used for this class to avoid cyclic dependency conflicts.
|
||||
*
|
||||
* @author anton
|
||||
*/
|
||||
@ -17,16 +20,17 @@ public class ScannerThreadFactory {
|
||||
|
||||
private ScanningResultList scanningResults;
|
||||
private Scanner scanner;
|
||||
private StateMachine stateMachine;
|
||||
private GlobalConfig globalConfig;
|
||||
|
||||
public ScannerThreadFactory(ScanningResultList scanningResults, Scanner scanner, GlobalConfig globalConfig) {
|
||||
|
||||
public ScannerThreadFactory(ScanningResultList scanningResults, Scanner scanner, StateMachine stateMachine, GlobalConfig globalConfig) {
|
||||
this.scanningResults = scanningResults;
|
||||
this.scanner = scanner;
|
||||
this.stateMachine = stateMachine;
|
||||
this.globalConfig = globalConfig;
|
||||
}
|
||||
|
||||
public ScannerThread createScannerThread(Feeder feeder) {
|
||||
return new ScannerThread(feeder, scanner, scanningResults, globalConfig);
|
||||
public ScannerThread createScannerThread(Feeder feeder, ScanningProgressCallback progressCallback) {
|
||||
return new ScannerThread(feeder, scanner, stateMachine, progressCallback, scanningResults, globalConfig);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -7,26 +7,22 @@ package net.azib.ipscan.core;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
import net.azib.ipscan.core.state.ScanningState;
|
||||
|
||||
/**
|
||||
* This callback is called on scanning status updates.
|
||||
* This callback is called on scanning state updates.
|
||||
*
|
||||
* @author anton
|
||||
*/
|
||||
public interface ScanningStateCallback {
|
||||
|
||||
public static final int STATE_IDLE = 0;
|
||||
public static final int STATE_SCANNING = 1;
|
||||
public static final int STATE_STOPPING = 2;
|
||||
public static final int STATE_KILLING = 3;
|
||||
|
||||
public interface ScanningProgressCallback {
|
||||
|
||||
/**
|
||||
* This method is called on scanner status changes,
|
||||
* This method is called on scanner state changes,
|
||||
* eg. when scanning is about to stop.
|
||||
*
|
||||
* @param status integer value of current status, having the
|
||||
* corresponding STATE_XXX constant
|
||||
* @param new state
|
||||
*/
|
||||
public void scannerStateChanged(int status);
|
||||
public void scannerStateChanged(ScanningState state);
|
||||
|
||||
/**
|
||||
* This method is called on scanning progress updates.
|
||||
43
src/net/azib/ipscan/core/state/ScanningState.java
Normal file
43
src/net/azib/ipscan/core/state/ScanningState.java
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* This file is a part of Angry IP Scanner source code,
|
||||
* see http://www.azib.net/ for more information.
|
||||
* Licensed under GPLv2.
|
||||
*/
|
||||
|
||||
package net.azib.ipscan.core.state;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* ScanningState enum - all possible states.
|
||||
*
|
||||
* @author Anton Keks
|
||||
*/
|
||||
public enum ScanningState {
|
||||
|
||||
IDLE,
|
||||
SCANNING,
|
||||
STOPPING,
|
||||
KILLING;
|
||||
|
||||
private Set<StateTransitionListener> listeners = new HashSet<StateTransitionListener>();
|
||||
|
||||
/**
|
||||
* Transitions the state to the next one
|
||||
*/
|
||||
public ScanningState next() {
|
||||
ScanningState[] states = values();
|
||||
return states[ordinal()+1 % states.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies all registered listeners of the transition to this state.
|
||||
*/
|
||||
public void notifyOnEntry() {
|
||||
for (StateTransitionListener listener : listeners) {
|
||||
listener.transitionTo(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
38
src/net/azib/ipscan/core/state/StateMachine.java
Normal file
38
src/net/azib/ipscan/core/state/StateMachine.java
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* This file is a part of Angry IP Scanner source code,
|
||||
* see http://www.azib.net/ for more information.
|
||||
* Licensed under GPLv2.
|
||||
*/
|
||||
|
||||
package net.azib.ipscan.core.state;
|
||||
|
||||
import net.azib.ipscan.core.ScanningProgressCallback;
|
||||
|
||||
/**
|
||||
* StateMachine
|
||||
*
|
||||
* @author Anton Keks
|
||||
*/
|
||||
public class StateMachine {
|
||||
|
||||
private ScanningProgressCallback progressCallback;
|
||||
private ScanningState state;
|
||||
|
||||
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) {
|
||||
return this.state == state;
|
||||
}
|
||||
|
||||
public void setScanningProgressCallback(ScanningProgressCallback progressCallback) {
|
||||
this.progressCallback = progressCallback;
|
||||
}
|
||||
|
||||
}
|
||||
22
src/net/azib/ipscan/core/state/StateTransitionListener.java
Normal file
22
src/net/azib/ipscan/core/state/StateTransitionListener.java
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* This file is a part of Angry IP Scanner source code,
|
||||
* see http://www.azib.net/ for more information.
|
||||
* Licensed under GPLv2.
|
||||
*/
|
||||
|
||||
package net.azib.ipscan.core.state;
|
||||
|
||||
/**
|
||||
* StateTransitionListener
|
||||
*
|
||||
* @author Anton Keks
|
||||
*/
|
||||
public interface StateTransitionListener {
|
||||
|
||||
/**
|
||||
* Notifies on transition to the specified state.
|
||||
* @param state
|
||||
*/
|
||||
public void transitionTo(ScanningState state);
|
||||
|
||||
}
|
||||
@ -10,7 +10,9 @@ import java.net.InetAddress;
|
||||
import net.azib.ipscan.config.Labels;
|
||||
import net.azib.ipscan.core.ScannerThread;
|
||||
import net.azib.ipscan.core.ScannerThreadFactory;
|
||||
import net.azib.ipscan.core.ScanningStateCallback;
|
||||
import net.azib.ipscan.core.ScanningProgressCallback;
|
||||
import net.azib.ipscan.core.state.ScanningState;
|
||||
import net.azib.ipscan.core.state.StateMachine;
|
||||
import net.azib.ipscan.gui.ResultTable;
|
||||
import net.azib.ipscan.gui.ScanningResultsConsumer;
|
||||
import net.azib.ipscan.gui.StatusBar;
|
||||
@ -28,7 +30,7 @@ import org.eclipse.swt.widgets.Display;
|
||||
*
|
||||
* @author anton
|
||||
*/
|
||||
public class StartStopScanningAction implements SelectionListener, ScanningStateCallback {
|
||||
public class StartStopScanningAction implements SelectionListener, ScanningProgressCallback {
|
||||
|
||||
private ScannerThreadFactory scannerThreadFactory;
|
||||
private ScannerThread scannerThread;
|
||||
@ -37,14 +39,14 @@ public class StartStopScanningAction implements SelectionListener, ScanningState
|
||||
private ResultTable resultTable;
|
||||
private FeederGUIRegistry feederRegistry;
|
||||
private Button button;
|
||||
private Image[] buttonImages = new Image[4];
|
||||
private String[] buttonTexts = new String[4];
|
||||
private Image[] buttonImages = new Image[ScanningState.values().length];
|
||||
private String[] buttonTexts = new String[ScanningState.values().length];
|
||||
|
||||
private Display display;
|
||||
|
||||
private int state = ScanningStateCallback.STATE_IDLE;
|
||||
private ScanningState state = ScanningState.IDLE;
|
||||
|
||||
public StartStopScanningAction(ScannerThreadFactory scannerThreadFactory, ResultTable resultTable, StatusBar statusBar, FeederGUIRegistry feederRegistry, Button startStopButton) {
|
||||
public StartStopScanningAction(ScannerThreadFactory scannerThreadFactory, StateMachine stateMachine, ResultTable resultTable, StatusBar statusBar, FeederGUIRegistry feederRegistry, Button startStopButton) {
|
||||
this.scannerThreadFactory = scannerThreadFactory;
|
||||
this.resultTable = resultTable;
|
||||
this.statusBar = statusBar;
|
||||
@ -52,21 +54,23 @@ public class StartStopScanningAction implements SelectionListener, ScanningState
|
||||
this.button = startStopButton;
|
||||
this.display = button.getDisplay();
|
||||
|
||||
stateMachine.setScanningProgressCallback(this);
|
||||
|
||||
// pre-load button images
|
||||
buttonImages[ScanningStateCallback.STATE_IDLE] = new Image(null, Labels.getInstance().getImageAsStream("button.start.img"));
|
||||
buttonImages[ScanningStateCallback.STATE_SCANNING] = new Image(null, Labels.getInstance().getImageAsStream("button.stop.img"));
|
||||
buttonImages[ScanningStateCallback.STATE_STOPPING] = new Image(null, Labels.getInstance().getImageAsStream("button.kill.img"));
|
||||
buttonImages[ScanningStateCallback.STATE_KILLING] = buttonImages[ScanningStateCallback.STATE_STOPPING];
|
||||
buttonImages[ScanningState.IDLE.ordinal()] = new Image(null, Labels.getInstance().getImageAsStream("button.start.img"));
|
||||
buttonImages[ScanningState.SCANNING.ordinal()] = new Image(null, Labels.getInstance().getImageAsStream("button.stop.img"));
|
||||
buttonImages[ScanningState.STOPPING.ordinal()] = new Image(null, Labels.getInstance().getImageAsStream("button.kill.img"));
|
||||
buttonImages[ScanningState.KILLING.ordinal()] = buttonImages[ScanningState.STOPPING.ordinal()];
|
||||
|
||||
// pre-load button texts
|
||||
buttonTexts[ScanningStateCallback.STATE_IDLE] = Labels.getLabel("button.start");
|
||||
buttonTexts[ScanningStateCallback.STATE_SCANNING] = Labels.getLabel("button.stop");
|
||||
buttonTexts[ScanningStateCallback.STATE_STOPPING] = Labels.getLabel("button.kill");
|
||||
buttonTexts[ScanningStateCallback.STATE_KILLING] = Labels.getLabel("button.kill");
|
||||
buttonTexts[ScanningState.IDLE.ordinal()] = Labels.getLabel("button.start");
|
||||
buttonTexts[ScanningState.SCANNING.ordinal()] = Labels.getLabel("button.stop");
|
||||
buttonTexts[ScanningState.STOPPING.ordinal()] = Labels.getLabel("button.kill");
|
||||
buttonTexts[ScanningState.KILLING.ordinal()] = Labels.getLabel("button.kill");
|
||||
|
||||
// set the defaultimage
|
||||
button.setImage(buttonImages[state]);
|
||||
button.setText(buttonTexts[state]);
|
||||
button.setImage(buttonImages[state.ordinal()]);
|
||||
button.setText(buttonTexts[state.ordinal()]);
|
||||
}
|
||||
|
||||
public void widgetDefaultSelected(SelectionEvent e) {
|
||||
@ -75,28 +79,28 @@ public class StartStopScanningAction implements SelectionListener, ScanningState
|
||||
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
switch (state) {
|
||||
case ScanningStateCallback.STATE_IDLE:
|
||||
case IDLE:
|
||||
// start the scan!
|
||||
resultTable.initNewScan(feederRegistry.current().getInfo());
|
||||
ScanningResultsConsumer resultsConsumer = new ScanningResultsConsumer(resultTable);
|
||||
scannerThread = scannerThreadFactory.createScannerThread(feederRegistry.current().getFeeder());
|
||||
scannerThread = scannerThreadFactory.createScannerThread(feederRegistry.current().getFeeder(), this);
|
||||
// TODO: fix this: this is needed here to avoid cylic dependencies...
|
||||
scannerThread.setResultsCallback(resultsConsumer);
|
||||
scannerThread.setStatusCallback(this);
|
||||
scannerThread.start();
|
||||
break;
|
||||
case ScanningStateCallback.STATE_SCANNING:
|
||||
case SCANNING:
|
||||
scannerThread.forceStop();
|
||||
break;
|
||||
case ScanningStateCallback.STATE_STOPPING:
|
||||
case STOPPING:
|
||||
scannerThread.abort();
|
||||
break;
|
||||
case ScanningStateCallback.STATE_KILLING:
|
||||
case KILLING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void scannerStateChanged(int status) {
|
||||
this.state = status;
|
||||
public void scannerStateChanged(ScanningState newState) {
|
||||
this.state = newState;
|
||||
if (display.isDisposed())
|
||||
return;
|
||||
display.asyncExec(new Runnable() {
|
||||
@ -104,22 +108,22 @@ public class StartStopScanningAction implements SelectionListener, ScanningState
|
||||
if (statusBar.isDisposed())
|
||||
return;
|
||||
|
||||
switch (StartStopScanningAction.this.state) {
|
||||
case STATE_IDLE:
|
||||
switch (state) {
|
||||
case IDLE:
|
||||
// reset state text
|
||||
statusBar.setStatusText(null);
|
||||
statusBar.setProgress(0);
|
||||
break;
|
||||
case STATE_STOPPING:
|
||||
case STOPPING:
|
||||
statusBar.setStatusText(Labels.getLabel("state.waitForThreads"));
|
||||
break;
|
||||
case STATE_KILLING:
|
||||
case KILLING:
|
||||
statusBar.setStatusText(Labels.getLabel("state.killingThreads"));
|
||||
break;
|
||||
}
|
||||
// change button image
|
||||
button.setImage(buttonImages[StartStopScanningAction.this.state]);
|
||||
button.setText(buttonTexts[StartStopScanningAction.this.state]);
|
||||
button.setImage(buttonImages[state.ordinal()]);
|
||||
button.setText(buttonTexts[state.ordinal()]);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -140,7 +144,7 @@ public class StartStopScanningAction implements SelectionListener, ScanningState
|
||||
statusBar.setProgress(percentageComplete);
|
||||
|
||||
// change button image
|
||||
button.setImage(buttonImages[StartStopScanningAction.this.state]);
|
||||
button.setImage(buttonImages[state.ordinal()]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user