OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 132 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
93 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.utils;
15
 
16
import static org.openconcerto.utils.DesktopEnvironment.cmdSubstitution;
180 ilm 17
 
93 ilm 18
import org.openconcerto.utils.cc.ITransformer;
19
 
20
import java.io.BufferedReader;
21
import java.io.File;
22
import java.io.IOException;
23
import java.io.InputStreamReader;
132 ilm 24
import java.math.BigDecimal;
93 ilm 25
import java.net.InetAddress;
26
import java.net.SocketException;
180 ilm 27
import java.nio.file.Files;
28
import java.nio.file.Paths;
93 ilm 29
import java.util.ArrayList;
30
import java.util.List;
31
import java.util.logging.Level;
132 ilm 32
import java.util.regex.Matcher;
33
import java.util.regex.Pattern;
93 ilm 34
 
35
/**
36
 * To abstract differences between platform for non java tasks.
37
 *
38
 * @author Sylvain
39
 * @see DesktopEnvironment
40
 */
41
public abstract class Platform {
42
 
43
    private static final int PING_TIMEOUT = 250;
44
 
45
    public static final Platform getInstance() {
46
        final OSFamily os = OSFamily.getInstance();
47
        if (os == OSFamily.Windows) {
48
            return CYGWIN;
180 ilm 49
        } else if (os == OSFamily.FreeBSD) {
93 ilm 50
            return FREEBSD;
180 ilm 51
        } else if (os == OSFamily.Mac) {
52
            return MACOS;
93 ilm 53
        } else {
54
            return LINUX;
55
        }
56
    }
57
 
58
    public abstract boolean supportsPID();
59
 
60
    public abstract boolean isRunning(final int pid) throws IOException;
61
 
62
    public abstract String getPath(final File f);
63
 
64
    public final String getPID() throws IOException {
180 ilm 65
        // TODO remove reflection and getPreJava9PID() once on java 11
66
        try {
67
            final Class<?> phClass = Class.forName("java.lang.ProcessHandle");
68
            final Object ph = phClass.getMethod("current").invoke(null);
69
            return ((Number) phClass.getMethod("pid").invoke(ph)).toString();
70
        } catch (ClassNotFoundException e) {
71
            // fall back
72
        } catch (Exception e) {
73
            throw new IOException("Couldn't get PID", e);
74
        }
75
        return getPreJava9PID();
76
    }
77
 
78
    protected String getPreJava9PID() throws IOException {
93 ilm 79
        final Process p = this.eval("echo -n $PPID");
180 ilm 80
        try (final BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
93 ilm 81
            return reader.readLine();
82
        }
83
    }
84
 
85
    public final String tail(final File f, final int n) throws IOException {
86
        final Process p = Runtime.getRuntime().exec(new String[] { "tail", "-n" + n, this.getPath(f) });
87
        return cmdSubstitution(p);
88
    }
89
 
90
    protected abstract String getBash();
91
 
92
    /**
93
     * Create a symbolic link from f2 to f1. NOTE: the path from f2 to f1 is made relative (eg
94
     * lastLog -> ./allLogs/tuesdayLog).
95
     *
96
     * @param f1 the destination of the link, eg "/dir/allLogs/tuesdayLog".
97
     * @param f2 the name of the link, eg "/dir/lastLog".
98
     * @throws IOException if an error occurs.
99
     */
100
    public final void ln_s(File f1, File f2) throws IOException {
101
        FileUtils.ln(f1, f2);
102
    }
103
 
104
    public boolean isSymLink(File f) throws IOException {
105
        return exitStatus(Runtime.getRuntime().exec(new String[] { "test", "-L", f.getAbsolutePath() })) == 0;
106
    }
107
 
108
    // see cygwin
109
    public File getNativeSymlinkFile(File dir) {
110
        return dir;
111
    }
112
 
113
    public abstract String readLink(File f) throws IOException;
114
 
115
    public final boolean exists(File f) throws IOException {
116
        return exitStatus(Runtime.getRuntime().exec(new String[] { "test", "-e", f.getAbsolutePath() })) == 0;
117
    }
118
 
119
    public final void append(File f1, File f2) throws IOException {
120
        final String c = "cat '" + f1.getAbsolutePath() + "' >> '" + f2.getAbsolutePath() + "'";
180 ilm 121
        this.waitForSuccess(this.eval(c), "append");
93 ilm 122
    }
123
 
124
    public Process cp_l(File src, File dest) throws IOException {
125
        return Runtime.getRuntime().exec(new String[] { "cp", "-prl", src.getAbsolutePath(), dest.getAbsolutePath() });
126
    }
127
 
128
    public final boolean ping(InetAddress host) throws IOException {
129
        return this.ping(host, PING_TIMEOUT);
130
    }
131
 
132
    /**
133
     * Test whether that address is reachable.
134
     *
135
     * @param host the host to reach.
136
     * @param timeout the time, in milliseconds, before the call aborts.
137
     * @return <code>true</code> if the address is reachable.
138
     * @throws IOException if a network error occurs.
139
     */
140
    public abstract boolean ping(InetAddress host, final int timeout) throws IOException;
141
 
142
    public final PingBuilder createPingBuilder() {
143
        return new PingBuilder(this);
144
    }
145
 
132 ilm 146
    protected abstract PingResult ping(InetAddress host, final PingBuilder pingBuilder, final int routingTableIndex) throws IOException;
93 ilm 147
 
132 ilm 148
    protected abstract BigDecimal parsePingAverageRT(String statsLine);
149
 
150
    protected final PingResult ping(final String command, final int totalCount, int requiredCount) throws IOException {
93 ilm 151
        if (requiredCount <= 0)
152
            requiredCount = totalCount;
180 ilm 153
        // Keep errors out of cmdSubstitution() (e.g. "ping: sendto: Message too long" when
154
        // setDontFragment(true))
155
        final Process proc = evalPB(command).redirectErrorStream(false).start();
156
        final String output = cmdSubstitution(proc);
157
        try {
158
            this.waitForSuccess(proc, "ping");
159
            final List<String> countAndLastLine = StringUtils.splitIntoLines(output);
160
            if (countAndLastLine.size() != 2)
161
                throw new IllegalStateException("Not 2 lines in " + countAndLastLine);
162
            final int replied = Integer.parseInt(countAndLastLine.get(0));
163
            assert replied <= totalCount;
164
            final BigDecimal averageRTT = replied == 0 ? null : parsePingAverageRT(countAndLastLine.get(1).trim());
165
            return new PingResult(totalCount, replied, requiredCount, averageRTT);
166
        } catch (Exception e) {
167
            throw new IllegalStateException("Couldn't use output :<<<\n" + output + "\n<<<", e);
168
        }
93 ilm 169
    }
170
 
171
    /**
172
     * Eval the passed string with bash.
173
     *
174
     * @param s a bash script.
175
     * @return the created process.
176
     * @throws IOException If an I/O error occurs.
177
     */
178
    public final Process eval(String s) throws IOException {
180 ilm 179
        return evalPB(s).start();
93 ilm 180
    }
181
 
180 ilm 182
    public final ProcessBuilder evalPB(String s) throws IOException {
183
        return new ProcessBuilder(this.getBash(), "-c", s);
184
    }
185
 
93 ilm 186
    public final int exitStatus(Process p) {
180 ilm 187
        return this.exitStatus(p, null);
188
    }
189
 
190
    public final int exitStatus(Process p, final String name) {
93 ilm 191
        try {
192
            return p.waitFor();
193
        } catch (InterruptedException e) {
180 ilm 194
            throw new RTInterruptedException("Interrupted while waiting for" + (name == null ? "" : " '" + name + "'") + " process", e);
93 ilm 195
        }
196
    }
197
 
180 ilm 198
    public final void waitForSuccess(final Process p, final String name) {
199
        final int exitStatus = exitStatus(p, name);
200
        if (exitStatus != 0)
201
            throw new IllegalStateException(name + " unsuccessful : " + exitStatus);
202
    }
203
 
93 ilm 204
    public abstract boolean isAdmin() throws IOException;
205
 
206
    private static abstract class UnixPlatform extends Platform {
207
 
208
        @Override
209
        public boolean supportsPID() {
210
            return true;
211
        }
212
 
180 ilm 213
        @Override
214
        public final String getPreJava9PID() throws IOException {
215
            final String symlink = getSelfProcessSymlink();
216
            if (symlink == null)
217
                return super.getPreJava9PID();
218
 
219
            // readSymbolicLink() seems to faster than getCanonicalFile() or toRealPath().
220
            // Another way is using reflection for
221
            // ManagementFactory.getRuntimeMXBean().jvm.getProcessId()
222
            return Files.readSymbolicLink(Paths.get(symlink)).getFileName().toString();
223
        }
224
 
225
        protected abstract String getSelfProcessSymlink();
226
 
93 ilm 227
        public final boolean isRunning(final int pid) throws IOException {
228
            // --pid only works on Linux, -p also on Nexenta
229
            final Process p = Runtime.getRuntime().exec(new String[] { "ps", "-p", String.valueOf(pid) });
230
            return this.exitStatus(p) == 0;
231
        }
232
 
233
        public String getPath(final File f) {
234
            return f.getPath();
235
        }
236
 
237
        @Override
238
        protected String getBash() {
239
            return "bash";
240
        }
241
 
242
        @Override
243
        public String readLink(File f) throws IOException {
244
            // --no-newline long form not supported on FreeBSD
245
            final Process p = Runtime.getRuntime().exec(new String[] { "readlink", "-n", f.getAbsolutePath() });
246
            return cmdSubstitution(p);
247
        }
248
 
249
        @Override
250
        public boolean ping(InetAddress host, final int timeout) throws IOException {
251
            try {
252
                return host.isReachable(timeout);
253
            } catch (SocketException e) {
254
                // On FreeBSD at least, if the destination is blocked by the firewall :
255
                // java.net.SocketException: Operation not permitted
256
                // at java.net.Inet4AddressImpl.isReachable0(Native Method)
257
                // at java.net.Inet4AddressImpl.isReachable(Inet4AddressImpl.java:70)
258
                Log.get().log(Level.FINER, "Swallow exception", e);
259
                return false;
260
            }
261
        }
262
 
132 ilm 263
        // Linux : rtt min/avg/max/mdev = 12.552/13.399/14.247/0.855 ms
264
        // FreeBSD : round-trip min/avg/max/stddev = 0.301/0.371/0.442/0.071 ms
265
        private static final Pattern PING_STATS_PATTERN = Pattern
266
                .compile("^\\p{Blank}*(?:rtt|round-trip)\\p{Blank}+min/avg/max/(?:mdev|stddev)\\p{Blank}+=\\p{Blank}+([0-9\\.]+)/([0-9\\.]+)/([0-9\\.]+)/([0-9\\.]+)\\p{Blank}+ms$");
267
 
93 ilm 268
        @Override
132 ilm 269
        protected BigDecimal parsePingAverageRT(String statsLine) {
270
            final Matcher m = PING_STATS_PATTERN.matcher(statsLine);
271
            if (!m.matches())
180 ilm 272
                throw new IllegalArgumentException("Not matching " + PING_STATS_PATTERN + " :\n" + statsLine);
132 ilm 273
            return new BigDecimal(m.group(2));
274
        }
275
 
276
        @Override
93 ilm 277
        public boolean isAdmin() throws IOException {
278
            // root is uid 0
279
            return cmdSubstitution(this.eval("id -u")).trim().equals("0");
280
        }
281
    }
282
 
283
    private static final Platform LINUX = new UnixPlatform() {
180 ilm 284
 
93 ilm 285
        @Override
180 ilm 286
        protected String getSelfProcessSymlink() {
287
            return "/proc/self";
288
        }
289
 
290
        @Override
132 ilm 291
        public PingResult ping(final InetAddress host, final PingBuilder pingBuilder, final int routingTableIndex) throws IOException {
93 ilm 292
            if (routingTableIndex > 0)
293
                throw new UnsupportedOperationException("On Linux, choosing a different routing table requires changing the system policy");
294
            final List<String> command = new ArrayList<String>(16);
295
            command.add("ping");
296
            final int totalCount = pingBuilder.getTotalCount();
297
            command.add("-c");
298
            command.add(String.valueOf(totalCount));
299
 
300
            if (pingBuilder.getWaitTime() > 0) {
301
                command.add("-W");
302
                final int timeInSeconds = pingBuilder.getWaitTime() / 1000;
303
                command.add(String.valueOf(Math.max(timeInSeconds, 1)));
304
            }
305
 
306
            command.add("-M");
307
            command.add(pingBuilder.isDontFragment() ? "do" : "dont");
308
 
309
            if (pingBuilder.getLength() > 0) {
310
                command.add("-s");
311
                command.add(String.valueOf(pingBuilder.getLength()));
312
            }
313
            if (pingBuilder.getTTL() > 0) {
314
                command.add("-t");
315
                command.add(String.valueOf(pingBuilder.getTTL()));
316
            }
132 ilm 317
            if (pingBuilder.getSourceAddress() != null) {
318
                command.add("-I");
319
                command.add(pingBuilder.getSourceAddress());
320
            }
93 ilm 321
 
322
            command.add(host.getHostAddress());
323
 
132 ilm 324
            return ping("out=$(" + CollectionUtils.join(command, " ") + ") ; grep -c ttl= <<< \"$out\" ; tail -n1 <<< \"$out\"", totalCount, pingBuilder.getRequiredReplies());
93 ilm 325
        }
326
    };
327
 
328
    private static final Platform FREEBSD = new UnixPlatform() {
180 ilm 329
 
93 ilm 330
        @Override
180 ilm 331
        protected String getSelfProcessSymlink() {
332
            return "/proc/curproc";
333
        }
334
 
335
        @Override
132 ilm 336
        public PingResult ping(final InetAddress host, final PingBuilder pingBuilder, final int routingTableIndex) throws IOException {
93 ilm 337
            final List<String> command = new ArrayList<String>(16);
338
            command.add("setfib");
339
            command.add(String.valueOf(routingTableIndex));
340
            command.add("ping");
341
            final int totalCount = pingBuilder.getTotalCount();
342
            command.add("-c");
343
            command.add(String.valueOf(totalCount));
344
 
345
            if (pingBuilder.getWaitTime() > 0) {
346
                command.add("-W");
347
                command.add(String.valueOf(pingBuilder.getWaitTime()));
348
            }
349
 
350
            if (pingBuilder.isDontFragment()) {
351
                command.add("-D");
352
            }
353
            if (pingBuilder.getLength() > 0) {
354
                command.add("-s");
355
                command.add(String.valueOf(pingBuilder.getLength()));
356
            }
357
            if (pingBuilder.getTTL() > 0) {
358
                command.add("-m");
359
                command.add(String.valueOf(pingBuilder.getTTL()));
360
            }
132 ilm 361
            if (pingBuilder.getSourceAddress() != null) {
362
                command.add("-S");
363
                command.add(pingBuilder.getSourceAddress());
364
            }
93 ilm 365
 
366
            command.add(host.getHostAddress());
367
 
132 ilm 368
            return ping("out=$(" + CollectionUtils.join(command, " ") + ") ; grep -c ttl= <<< \"$out\" ; tail -n1 <<< \"$out\"", totalCount, pingBuilder.getRequiredReplies());
93 ilm 369
        }
370
    };
371
 
180 ilm 372
    private static final Platform MACOS = new UnixPlatform() {
373
        @Override
374
        protected String getSelfProcessSymlink() {
375
            return null;
376
        }
377
 
378
        @Override
379
        protected PingResult ping(InetAddress host, PingBuilder pingBuilder, int routingTableIndex) throws IOException {
380
            return FREEBSD.ping(host, pingBuilder, routingTableIndex);
381
        }
382
    };
383
 
132 ilm 384
    private static final class CygwinPlatform extends Platform {
93 ilm 385
 
386
        @Override
387
        public boolean supportsPID() {
388
            return false;
389
        }
390
 
391
        @Override
392
        public boolean isRunning(int pid) throws IOException {
393
            // PID TTY STIME COMMAND
394
            // 864 ? 09:27:57 \??\C:\WINDOWS\system32\winlogon.exe
395
            // so if we count lines, we should get 2
396
            final Process p = this.eval("export PATH=$PATH:/usr/bin ; test $(ps -sW -p " + pid + " | wc -l) -eq 2 ");
397
            return this.exitStatus(p) == 0;
398
        }
399
 
400
        @Override
401
        protected String getBash() {
402
            // We used to specify the full path here, but this needed to be configurable (e.g.
403
            // cygwin 32 or 64 bit), plus all other programs are required to be on the PATH
404
            return "bash.exe";
405
        }
406
 
407
        @Override
408
        public String readLink(File f) throws IOException {
409
            // windows format to be able to use File
410
            final Process p = Runtime.getRuntime().exec(new String[] { "readshortcut.exe", "-w", f.getAbsolutePath() });
411
            return cmdSubstitution(p).trim();
412
        }
413
 
414
        @Override
415
        public String getPath(File f) {
416
            return toCygwinPath(f);
417
        }
418
 
419
        @Override
420
        public boolean ping(InetAddress host, final int timeout) throws IOException {
421
            // windows implem of isReachable() is buggy
422
            // see http://bordet.blogspot.com/2006/07/icmp-and-inetaddressisreachable.html
180 ilm 423
            final int exit = this.exitStatus(Runtime.getRuntime().exec("ping -n 1 -w " + timeout + " " + host.getHostAddress()), "ping");
424
            return exit == 0;
93 ilm 425
        }
426
 
427
        @Override
132 ilm 428
        public PingResult ping(final InetAddress host, final PingBuilder pingBuilder, final int routingTableIndex) throws IOException {
93 ilm 429
            if (routingTableIndex > 0)
430
                throw new UnsupportedOperationException("Only one routing table on Windows");
431
            final List<String> command = new ArrayList<String>(16);
432
            command.add("ping");
433
            final int totalCount = pingBuilder.getTotalCount();
434
            command.add("-n");
435
            command.add(String.valueOf(totalCount));
436
 
437
            if (pingBuilder.getWaitTime() > 0) {
438
                command.add("-w");
439
                command.add(String.valueOf(pingBuilder.getWaitTime()));
440
            }
441
 
442
            if (pingBuilder.isDontFragment()) {
443
                command.add("-f");
444
            }
445
            if (pingBuilder.getLength() > 0) {
446
                command.add("-l");
447
                command.add(String.valueOf(pingBuilder.getLength()));
448
            }
449
            if (pingBuilder.getTTL() > 0) {
450
                command.add("-i");
451
                command.add(String.valueOf(pingBuilder.getTTL()));
452
            }
132 ilm 453
            if (pingBuilder.getSourceAddress() != null) {
454
                command.add("-S");
455
                command.add(pingBuilder.getSourceAddress());
456
            }
93 ilm 457
 
458
            command.add(host.getHostAddress());
459
 
132 ilm 460
            // can't use local variable : never could work out newlines problem
461
            // see https://cygwin.com/ml/cygwin-announce/2011-02/msg00027.html
462
            return ping("tmpF=$(mktemp) && " + CollectionUtils.join(command, " ") + " > $tmpF ; grep -c \"TTL=\" < $tmpF ; tail -n1 $tmpF; rm \"$tmpF\"", totalCount, pingBuilder.getRequiredReplies());
93 ilm 463
        }
464
 
132 ilm 465
        // Minimum = 35ms, Maximum = 36ms, Moyenne = 35ms
466
        private static final Pattern PING_STATS_PATTERN = Pattern.compile("^\\p{Blank}*\\p{Alpha}+ = ([0-9\\.]+)ms, \\p{Alpha}+ = ([0-9\\.]+)ms, \\p{Alpha}+ = ([0-9\\.]+)ms$");
467
 
93 ilm 468
        @Override
132 ilm 469
        protected BigDecimal parsePingAverageRT(String statsLine) {
470
            final Matcher m = PING_STATS_PATTERN.matcher(statsLine);
471
            if (!m.matches())
472
                throw new IllegalArgumentException("Not matching " + PING_STATS_PATTERN + " : " + statsLine);
473
            return new BigDecimal(m.group(3));
474
        }
475
 
476
        @Override
93 ilm 477
        public boolean isAdmin() throws IOException {
132 ilm 478
            // SID administrators S-1-5-32-544 or S-1-5-114
479
            return this.exitStatus(this.eval("id -G | egrep '\\b(544|114)\\b'")) == 0;
93 ilm 480
        }
481
 
482
        @Override
483
        public boolean isSymLink(File f) throws IOException {
484
            // links created with "ln" can loose their "test -L" status over a copy (eg between two
485
            // Eclipse workspaces), so check with filename
486
            return getNativeSymlinkFile(f).exists() || super.isSymLink(f);
487
        }
488
 
489
        // when cygwin does "ln -s f link" it actually creates "link.lnk"
490
        @Override
491
        public File getNativeSymlinkFile(File dir) {
492
            return FileUtils.addSuffix(dir, ".lnk");
493
        }
494
    };
495
 
132 ilm 496
    private static final Platform CYGWIN = new CygwinPlatform();
497
 
93 ilm 498
    public static String toCygwinPath(File dir) {
499
        final List<File> ancestors = getAncestors(dir);
500
 
501
        final String root = ancestors.get(0).getPath();
502
        final List<File> rest = ancestors.subList(1, ancestors.size());
503
        return "/cygdrive/" + root.charAt(0) + "/" + CollectionUtils.join(rest, "/", new ITransformer<File, String>() {
504
            @Override
505
            public String transformChecked(File f) {
506
                return f.getName();
507
            }
508
        });
509
    }
510
 
511
    public static List<File> getAncestors(File f) {
512
        final File abs = f.getAbsoluteFile();
513
        File current = abs;
514
        final List<File> res = new ArrayList<File>();
515
 
516
        while (current != null) {
517
            res.add(0, current);
518
            current = current.getParentFile();
519
        }
520
        return res;
521
    }
522
 
132 ilm 523
    public static final class PingResult {
524
 
525
        private final int wantedCount, repliesCount, requiredReplies;
526
        private final BigDecimal averageRTT;
527
 
528
        private PingResult(final int wantedCount, final int repliesCount, final int requiredReplies, final BigDecimal averageRTT) {
529
            this.wantedCount = wantedCount;
530
            this.repliesCount = repliesCount;
531
            this.requiredReplies = requiredReplies;
532
            this.averageRTT = averageRTT;
533
        }
534
 
535
        public final int getRepliesCount() {
536
            return this.repliesCount;
537
        }
538
 
539
        public final int getRequiredReplies() {
540
            return this.requiredReplies;
541
        }
542
 
543
        public final boolean hasRequiredReplies() {
544
            return this.hasEnoughReplies(this.getRequiredReplies());
545
        }
546
 
547
        public final boolean hasEnoughReplies(final int min) {
548
            return this.getRepliesCount() >= min;
549
        }
550
 
551
        public final BigDecimal getAverageRTT() {
552
            return this.averageRTT;
553
        }
554
 
555
        @Override
556
        public String toString() {
557
            return this.getClass().getSimpleName() + " " + this.getRepliesCount() + "/" + this.wantedCount + " reply(ies), average RTT : " + this.getAverageRTT() + " ms";
558
        }
559
    }
560
 
93 ilm 561
    public static final class PingBuilder {
562
 
563
        private final Platform platform;
564
 
565
        // in milliseconds
566
        private int waitTime = 4000;
567
        private boolean dontFragment = false;
568
        private int length = -1;
132 ilm 569
        private String srcAddr = null;
93 ilm 570
        private int ttl = -1;
571
        private int totalCount = 4;
572
        private int requiredReplies = -1;
573
 
574
        PingBuilder(final Platform p) {
575
            this.platform = p;
576
        }
577
 
578
        public final PingBuilder setWaitTime(final int waitTime) {
579
            this.waitTime = waitTime;
580
            return this;
581
        }
582
 
583
        public final int getWaitTime() {
584
            return this.waitTime;
585
        }
586
 
587
        public final boolean isDontFragment() {
588
            return this.dontFragment;
589
        }
590
 
591
        public final PingBuilder setDontFragment(boolean dontFragment) {
592
            this.dontFragment = dontFragment;
593
            return this;
594
        }
595
 
596
        public final int getLength() {
597
            return this.length;
598
        }
599
 
600
        public final PingBuilder setLength(int length) {
601
            this.length = length;
602
            return this;
603
        }
604
 
132 ilm 605
        public String getSourceAddress() {
606
            return this.srcAddr;
607
        }
608
 
609
        public PingBuilder setSourceAddress(String srcAddr) {
610
            this.srcAddr = srcAddr;
611
            return this;
612
        }
613
 
93 ilm 614
        public final int getTTL() {
615
            return this.ttl;
616
        }
617
 
618
        public final PingBuilder setTTL(int ttl) {
619
            this.ttl = ttl;
620
            return this;
621
        }
622
 
623
        public final int getTotalCount() {
624
            return this.totalCount;
625
        }
626
 
627
        public final PingBuilder setTotalCount(int totalCount) {
628
            if (totalCount <= 0)
629
                throw new IllegalArgumentException("Negative count : " + totalCount);
630
            this.totalCount = totalCount;
631
            return this;
632
        }
633
 
634
        public final int getRequiredReplies() {
635
            return this.requiredReplies;
636
        }
637
 
638
        public final PingBuilder setRequiredReplies(int requiredReplies) {
639
            this.requiredReplies = requiredReplies;
640
            return this;
641
        }
642
 
132 ilm 643
        public final boolean isAlive(final InetAddress host) throws IOException {
644
            return this.isAlive(host, 0);
93 ilm 645
        }
646
 
132 ilm 647
        public final boolean isAlive(final InetAddress host, final int routingTableIndex) throws IOException {
648
            return execute(host, routingTableIndex).hasRequiredReplies();
649
        }
650
 
651
        public PingResult execute(final InetAddress host) throws IOException {
652
            return execute(host, 0);
653
        }
654
 
655
        public PingResult execute(final InetAddress host, final int routingTableIndex) throws IOException {
93 ilm 656
            return this.platform.ping(host, this, routingTableIndex);
657
        }
658
    }
132 ilm 659
 
660
    public static final class Ping {
661
        public static void main(String[] args) throws IOException {
662
            final int totalCount = Integer.parseInt(System.getProperty("count", "4"));
663
            final String srcAddr = System.getProperty("srcAddr");
664
            System.out.println(Platform.getInstance().createPingBuilder().setTotalCount(totalCount).setSourceAddress(srcAddr).execute(InetAddress.getByName(args[0])));
665
        }
666
    }
93 ilm 667
}