Angry IP Scanner (ipscan) is a cross-platform network scanner written in Java.
GUI uses SWT (Eclipse) for native widgets per platform. Licensed GPLv2.
- Entry point:
net.azib.ipscan.Main(src/net/azib/ipscan/Main.java) - Package root:
net.azib.ipscanundersrc/ - Tests mirror the source tree under
test/
Gradle 9.5 wrapper (./gradlew). Java 21 source/target. CI uses Java 25 (Liberica).
Source layout is non-standard — no src/main/java convention:
- Main sources:
src/(configured assourceSets.main.java.srcDirs) - Test sources:
test/(configured assourceSets.test.java.srcDir) - Resources:
config/,src/,resources/all merged into main resources
./gradlew current # build jar for current OS/arch
./gradlew test # run tests
./gradlew info # list all build targets
./gradlew clean # clean build dirPlatform-specific targets: linux64, any (platform-neutral), win64, macX86, macArm64, mac, linux, win-installer.
Output goes to build/libs/. Run with java -jar <jar-file>.
sudo apt install openjdk-21-jdk rpm fakeroot
- 4 space indents
JUnit 4 + Mockito 2.x. Test classes use @Test, @Before annotations.
./gradlew test # all tests
./gradlew test --tests "net.azib.ipscan.core.net.*" # single package
./gradlew test --tests "*PingFetcherTest" # single classMac caveat: GUI-touching tests are excluded on macOS (Cocoa thread restrictions). Only net.azib.ipscan.core.net.* runs. CI uses xvfb-run -a on Linux for headless SWT tests.
Pinger tests require network access — they ping 127.0.0.1 for alive tests and 192.168.99.253 for dead tests.
Test DI pattern: Tests that need components use new ComponentRegistry().init(false) — the false skips GUI registration, giving a headless injector.
Custom lightweight DI in net.azib.ipscan.di.Injector — constructor-based, picks the constructor with the most parameters. No annotations needed. Wiring is in:
ComponentRegistry— fetchers, exporters, pingersConfigModule— config singletonsGUIRegistry— SWT widgets and GUI components
ComponentRegistry.init(boolean withGUI) is the bootstrap. false = headless (used in tests).
Platform.java has boolean constants (MAC_OS, LINUX, WINDOWS, CRIPPLED_WINDOWS).
Platform-specific fetchers: WinMACFetcher, LinuxMACFetcher, UnixMACFetcher — selected at DI time via reflection in ComponentRegistry.
Windows-specific pingers (WindowsPinger, WinIpHlp) use JNA for native calls.
| Package | Purpose |
|---|---|
config/ |
Config, Labels (i18n), Platform detection, ComponentRegistry (DI wiring) |
core/ |
Scanner engine, scanning state machine, results |
core/net/ |
Pingers (ICMP, TCP, UDP, ARP, Windows-specific) |
di/ |
Custom DI container |
exporters/ |
Result export formats (CSV, TXT, XML, SQL, IPList) |
feeders/ |
IP range input sources (range, random, file, rescan) |
fetchers/ |
Data fetchers (ping, hostname, ports, MAC, web detect, etc.) |
gui/ |
SWT GUI: MainWindow, dialogs, menus, feeder/fetcher panels |
util/ |
Utilities |
Plugins implement net.azib.ipscan.core.Plugin. Loaded from:
-Dipscan.plugins=com.example.MyPluginsystem property- JARs next to the app binary with
IPScan-Pluginmanifest attribute - JARs in
$HOME/.ipscan/
Plugin JARs can bundle their own messages.properties for i18n.
Labels in resources/messages.properties (English fallback) + messages_<lang>.properties per locale.
Access via Labels.getLabel("key"). Supported languages listed in Labels.LANGUAGES.
When adding UI strings, add the key to messages.properties first.
Version is derived from git describe --tags. CI creates draft GitHub releases on tag push.
JARs are minified with ProGuard after packaging. Config in ext/swt.pro and ext/jna.pro. The minified jar replaces the original.
- Linux:
.deb(viafakeroot dpkg-deb) and.rpm(viarpmbuild), only on Ubuntu - Windows:
.exelauncher (concatenated fromext/win-launcher/launcher.exe+ jar), NSIS installer - Mac:
.appbundle withjlink-ed JRE, optional Apple notarization viaAPPLE_USER/APPLE_PASSWORDenv vars
resources/mac-vendors.txt is generated from IEEE OUI data. Update with:
./update-mac-vendors.shRequires gnu-sed on macOS (brew install gnu-sed).
User preferences stored via java.util.prefs.Preferences under node ipscan. Not in project files.
gradle.propertiesadds--add-opens java.base/java.net=ALL-UNNAMED(required for JNA/reflection)- SWT dependency is excluded transitively (
all*.exclude module: 'org.eclipse.swt') — platform-specific SWT is selected via Gradle configurations - Platform configurations (
linux64,win64,macX86,macArm64,jna) control which native libs get bundled