Skip to content
Commits on Source (213)
/nailgun-server/target/
/nailgun-examples/target/
/nailgun-client/target/
/target/
ng
*.iml
*.pyc
.idea/
\ No newline at end of file
language: java
jdk:
- oraclejdk8
language: python
addons:
apt:
packages:
- oracle-java8-set-default
- mingw-w64
python:
- "2.7"
- "3.5"
- "3.6"
script:
- make ng
- make ng.exe
- scripts/travis_run.sh
# Code of Conduct
Facebook has adopted a Code of Conduct that we expect project participants to adhere to.
Please read the [full text](https://code.fb.com/codeofconduct/)
so that you can understand what actions will and will not be tolerated.
\ No newline at end of file
# Contributing to Nailgun
We encourage the reporting of issues and bugs, along with pull requests to help make Nailgun codebase better. The following are some information and guidelines to help you contribute to Nailgun.
## Tour of the Codebase
This is a high-level overview of how the Nailgun repository is organized.
### `nailgun-server/`
That is where server side code lives, written in Java. It contains both core code under `src/main` and test code under `src/tests`.
### `nailgun-client/`
Client part of Nailgun, both C and Python versions in appropriate folders.
### `nailgun-examples/`
Some simple implementations of a Nail, helpful to understand how to write server-side code. One can also execute one of those nails for debugging or integration testing.
### `scripts/`
Automation scripts, mostly for continuous integration (i.e. Travis CI).
### `tools/`
Third-party dependencies used in tooling, like linter or code formatter.
## Development Workflow
### Building Nailgun
As simple as running `mvn clean package`.
### Running Tests
Unit tests and integration tests are JUnit and they are run by Maven when you say 'mvn package'. To run E2E test, just execute `./scripts/travis_ci.sh`. It will also run `mvn package` first with all unit tests.
### Using the IntelliJ IDE
Just open project from Nailgun's root folder
### Code Style
Code is autoformatted with Maven plugin and Google code style is used. Be ready to have some changed files after building the project with Maven, so you may have to amend the change to git.
Nailgun Copyright © 2004-2012, Martian Software, Inc.
Copyright © 2017-present Facebook, Inc.
Apache License
Version 2.0, January 2004
......
......@@ -5,22 +5,25 @@
# This is where the mingw32 compiler exists in Ubuntu 8.04.
# Your compiler location may vary.
WIN32_CC=/usr/bin/i586-mingw32msvc-gcc
WIN32_CC=/usr/bin/i686-w64-mingw32-gcc
CFLAGS=-Wall -pedantic -O2
SRCDIR=nailgun-client
SRCDIR=nailgun-client/c
TARGETDIR=nailgun-client/target
PREFIX=/usr/local
ng: ${SRCDIR}/ng.c
@echo "Building ng client. To build a Windows binary, type 'make ng.exe'"
${CC} $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o ng ${SRCDIR}/ng.c
@echo "Building ng client. To build a Windows binary, type 'make ng.exe'"
mkdir -p ${TARGETDIR}
${CC} $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o ${TARGETDIR}/ng ${SRCDIR}/ng.c
install: ng
install -d ${PREFIX}/bin
install ng ${PREFIX}/bin
install ${TARGETDIR}/ng ${PREFIX}/bin
ng.exe: ${SRCDIR}/ng.c
${WIN32_CC} -o ng.exe ${SRCDIR}/ng.c -lwsock32 -O3 ${CFLAGS}
mkdir -p ${TARGETDIR}
${WIN32_CC} -o ${TARGETDIR}/ng.exe ${SRCDIR}/ng.c -lwsock32 -O3 ${CFLAGS}
# any idea why the command line is so sensitive to the order of
# the arguments? If CFLAGS is at the beginning, it won't link.
......@@ -30,5 +33,5 @@ clean:
@echo "You must remove this manually. Most users won't have MinGW"
@echo "installed - so I'd rather not delete something you can't rebuild."
@echo ""
rm -f ng
# rm -f ng.exe
rm -f ${TARGETDIR}/ng
# rm -f ${TARGETDIR}/ng.exe
......@@ -22,6 +22,6 @@ you will additionally need to "make ng.exe".
A ruby client is available through the [railgun](https://github.com/timuralp/railgun) project.
For more information, see [the nailgun website](http://martiansoftware.com/nailgun/).
For more information, see [the nailgun website](https://github.com/facebook/nailgun).
......@@ -21,4 +21,4 @@ build_script:
- "mvn package"
test_script:
- "python -m pynailgun.test_ng"
- "python nailgun-client/py/test_ng.py"
nailgun (1.0.0-1) UNRELEASED; urgency=medium
* New upstream release
* debian/patches
- refresh patches
* Add debian/gbp.conf
* debian/control
- Add Build-Depends: libfmt-maven-plugin-java
-- Hideki Yamane <henrich@debian.org> Sat, 20 Oct 2018 07:57:14 +0900
nailgun (0.9.3-3) unstable; urgency=medium
* debian/control
......
......@@ -8,6 +8,7 @@ Build-Depends:
debhelper (>= 10),
default-jdk,
libmaven-shade-plugin-java,
libfmt-maven-plugin-java,
libjna-platform-java,
maven-debian-helper (>= 1.5)
Standards-Version: 4.1.4
......
[DEFAULT]
debian-branch = debian/sid
upstream-tag = nailgun-all-%(version)s
debian-tag = debian/%(version)s
pristine-tar = True
color = auto
[buildpackage]
# Look for a tag matching the upstream version when creating a tarball
upstream-tree = tag
# uncomment this to automatically GPG sign tags:
sign-tags = True
pbuilder = True
......@@ -6,24 +6,24 @@ Author: Hideki Yamane <henrich@debian.org>
---
Origin: vendor
Forwarded: not-needed
Last-Update: 2013-06-11
Last-Update: 2018-10-20
--- a/Makefile
+++ b/Makefile
@@ -15,10 +15,6 @@
@echo "Building ng client. To build a Windows binary, type 'make ng.exe'"
${CC} $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o ng ${SRCDIR}/ng.c
@@ -17,10 +17,6 @@
mkdir -p ${TARGETDIR}
${CC} $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o ${TARGETDIR}/ng ${SRCDIR}/ng.c
-install: ng
- install -d ${PREFIX}/bin
- install ng ${PREFIX}/bin
- install ${TARGETDIR}/ng ${PREFIX}/bin
-
ng.exe: ${SRCDIR}/ng.c
${WIN32_CC} -o ng.exe ${SRCDIR}/ng.c -lwsock32 -O3 ${CFLAGS}
# any idea why the command line is so sensitive to the order of
@@ -30,5 +26,4 @@
mkdir -p ${TARGETDIR}
${WIN32_CC} -o ${TARGETDIR}/ng.exe ${SRCDIR}/ng.c -lwsock32 -O3 ${CFLAGS}
@@ -33,5 +29,4 @@
@echo "You must remove this manually. Most users won't have MinGW"
@echo "installed - so I'd rather not delete something you can't rebuild."
@echo ""
- rm -f ng
# rm -f ng.exe
- rm -f ${TARGETDIR}/ng
# rm -f ${TARGETDIR}/ng.exe
......@@ -8,10 +8,10 @@ Author: Hideki Yamane <henrich@debian.org>
Origin: vendor
Bug-Ubuntu: https://launchpad.net/bugs/793859
Forwarded: no
Last-Update: 2013-06-11
Last-Update: 2018-10-20
--- a/nailgun-client/ng.c
+++ b/nailgun-client/ng.c
--- a/nailgun-client/c/ng.c
+++ b/nailgun-client/c/ng.c
@@ -81,7 +81,7 @@
#define NAILGUN_CLIENT_NAME_EXE "ng.exe"
......
/*
Copyright 2004-2012, Martian Software, Inc.
Copyright 2017-Present Facebook, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
......@@ -13,7 +13,6 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
......@@ -24,6 +23,7 @@
#ifdef WIN32
#include <direct.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <arpa/inet.h>
#include <netdb.h>
......@@ -41,7 +41,7 @@
#include <fcntl.h>
#include <errno.h>
#define NAILGUN_VERSION "0.9.0"
#define NAILGUN_VERSION "1.0.0"
#define BUFSIZE (2048)
......@@ -60,7 +60,7 @@
typedef unsigned int SOCKET;
#endif
#ifdef __APPLE__
#ifndef MSG_NOSIGNAL
#define SEND_FLAGS 0
#else
#define SEND_FLAGS MSG_NOSIGNAL
......
# Copyright 2004-2015, Martian Software, Inc.
# Copyright 2017-Present Facebook, Inc.
from ng import NailgunConnection, NailgunException
#!/usr/bin/env python
#
# Copyright 2004-2015, Martian Software, Inc.
# Copyright 2017-Present Facebook, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import subprocess
import os
import time
import StringIO
import unittest
import tempfile
import shutil
import uuid
import sys
from pynailgun import NailgunException, NailgunConnection
from ng import NailgunException, NailgunConnection
is_py2 = sys.version[0] == "2"
if is_py2:
from StringIO import StringIO
else:
from io import StringIO
if os.name == "posix":
if os.name == 'posix':
def transport_exists(transport_file):
return os.path.exists(transport_file)
if os.name == 'nt':
if os.name == "nt":
import ctypes
from ctypes.wintypes import WIN32_FIND_DATAW as WIN32_FIND_DATA
INVALID_HANDLE_VALUE = -1
FindFirstFile = ctypes.windll.kernel32.FindFirstFileW
FindClose = ctypes.windll.kernel32.FindClose
......@@ -34,31 +57,36 @@ if os.name == 'nt':
class TestNailgunConnection(unittest.TestCase):
def __init__(self, *args, **kwargs):
super(TestNailgunConnection, self).__init__(*args, **kwargs)
self.heartbeat_timeout_ms = 10000
def setUp(self):
self.setUpTransport()
self.startNailgun()
def setUpTransport(self):
self.tmpdir = tempfile.mkdtemp()
if os.name == 'posix':
self.transport_file = os.path.join(self.tmpdir, 'sock')
self.transport_address = 'local:{0}'.format(self.transport_file)
if os.name == "posix":
self.transport_file = os.path.join(self.tmpdir, "sock")
self.transport_address = "local:{0}".format(self.transport_file)
else:
pipe_name = u'nailgun-test-{0}'.format(uuid.uuid4().hex)
self.transport_address = u'local:{0}'.format(pipe_name)
self.transport_file = ur'\\.\pipe\{0}'.format(pipe_name)
pipe_name = u"nailgun-test-{0}".format(uuid.uuid4().hex)
self.transport_address = u"local:{0}".format(pipe_name)
self.transport_file = u"\\\\.\\pipe\{0}".format(pipe_name)
def getClassPath(self):
cp = [
'nailgun-server/target/nailgun-server-0.9.3-SNAPSHOT-uber.jar',
'nailgun-examples/target/nailgun-examples-0.9.3-SNAPSHOT.jar',
]
if os.name == 'nt':
return ';'.join(cp)
return ':'.join(cp)
"nailgun-server/target/nailgun-server-1.0.0-SNAPSHOT-uber.jar",
"nailgun-examples/target/nailgun-examples-1.0.0-SNAPSHOT.jar",
]
if os.name == "nt":
return ";".join(cp)
return ":".join(cp)
def startNailgun(self):
if os.name == 'posix':
if os.name == "posix":
def preexec_fn():
# Close any open file descriptors to further separate buckd from its
# invoking context (e.g. otherwise we'd hang when running things like
......@@ -67,6 +95,7 @@ class TestNailgunConnection(unittest.TestCase):
os.dup2(dev_null_fd, 0)
os.dup2(dev_null_fd, 2)
os.close(dev_null_fd)
creationflags = 0
else:
preexec_fn = None
......@@ -75,30 +104,56 @@ class TestNailgunConnection(unittest.TestCase):
creationflags = DETACHED_PROCESS
stdout = None
if os.name == 'posix':
stdout=subprocess.PIPE
if os.name == "posix":
stdout = subprocess.PIPE
log_config_file = os.path.join(self.tmpdir, "logging.properties")
self.log_file = os.path.join(self.tmpdir, "test_ng.log")
with open(log_config_file, "w") as config_file:
config_file.write("handlers = java.util.logging.FileHandler\n")
config_file.write(".level = ALL\n")
config_file.write("java.util.logging.FileHandler.level = ALL\n")
config_file.write(
"java.util.logging.FileHandler.pattern = " + self.log_file + "\n"
)
config_file.write("java.util.logging.FileHandler.count = 1\n")
config_file.write(
"java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter\n"
)
cmd = ['java', '-Djna.nosys=true', '-classpath', self.getClassPath()]
if os.environ.get('DEBUG_MODE') == '1':
cmd.append('-agentlib:jdwp=transport=dt_socket,address=localhost:8888,server=y,suspend=y')
cmd = cmd + ['com.martiansoftware.nailgun.NGServer', self.transport_address]
cmd = [
"java",
"-Djna.nosys=true",
"-Djava.util.logging.config.file=" + log_config_file,
"-classpath",
self.getClassPath(),
]
debug_mode = os.environ.get("DEBUG_MODE") or ""
if debug_mode != "":
suspend = "n" if debug_mode == "2" else "y"
cmd.append(
"-agentlib:jdwp=transport=dt_socket,address=localhost:8888,server=y,suspend="
+ suspend
)
cmd = cmd + [
"com.facebook.nailgun.NGServer",
self.transport_address,
str(self.heartbeat_timeout_ms),
]
self.ng_server_process = subprocess.Popen(
cmd,
preexec_fn=preexec_fn,
creationflags=creationflags,
stdout=stdout,
cmd, preexec_fn=preexec_fn, creationflags=creationflags, stdout=stdout
)
self.assertIsNone(self.ng_server_process.poll())
if os.name == 'posix':
if os.name == "posix":
# on *nix we have to wait for server to be ready to accept connections
while True:
the_first_line = self.ng_server_process.stdout.readline().strip()
the_first_line = str(self.ng_server_process.stdout.readline().strip())
if "NGServer" in the_first_line and "started" in the_first_line:
break
if the_first_line is None or the_first_line == '':
if the_first_line is None or the_first_line == "":
break
else:
for _ in range(0, 600):
......@@ -110,80 +165,165 @@ class TestNailgunConnection(unittest.TestCase):
self.assertTrue(transport_exists(self.transport_file))
def test_nailgun_stats(self):
output = StringIO.StringIO()
with NailgunConnection(
def tearDown(self):
try:
with NailgunConnection(
self.transport_address,
cwd=os.getcwd(),
stderr=None,
stdin=None,
stdout=output) as c:
exit_code = c.send_command('ng-stats')
stdout=None,
) as c:
c.send_command("ng-stop")
except NailgunException as e:
# stopping server is a best effort
# if something wrong has happened, we will kill it anyways
pass
# Python2 compatible wait with timeout
process_exit_code = None
for _ in range(0, 500):
process_exit_code = self.ng_server_process.poll()
if process_exit_code is not None:
break
time.sleep(0.02) # 1 second total
if process_exit_code is None:
# some test has failed, ng-server was not stopped. killing it
self.ng_server_process.kill()
debug_logs = os.environ.get("DEBUG_LOGS") or ""
if debug_logs != "":
with open(self.log_file, "r") as log_file:
print("NAILGUN SERVER LOG:\n")
print(log_file.read())
shutil.rmtree(self.tmpdir)
class TestNailgunConnectionMain(TestNailgunConnection):
def __init__(self, *args, **kwargs):
super(TestNailgunConnectionMain, self).__init__(*args, **kwargs)
def test_nailgun_stats(self):
output = StringIO()
with NailgunConnection(
self.transport_address, stderr=None, stdin=None, stdout=output
) as c:
exit_code = c.send_command("ng-stats")
self.assertEqual(exit_code, 0)
actual_out = output.getvalue().strip()
expected_out = 'com.martiansoftware.nailgun.builtins.NGServerStats: 1/1'
expected_out = "com.facebook.nailgun.builtins.NGServerStats: 1/1"
self.assertEqual(actual_out, expected_out)
def test_nailgun_exit_code(self):
output = StringIO.StringIO()
output = StringIO()
expected_exit_code = 10
with NailgunConnection(
self.transport_address,
stderr=None,
stdin=None,
stdout=output) as c:
exit_code = c.send_command('com.martiansoftware.nailgun.examples.Exit', [str(expected_exit_code)])
self.transport_address, stderr=None, stdin=None, stdout=output
) as c:
exit_code = c.send_command(
"com.facebook.nailgun.examples.Exit", [str(expected_exit_code)]
)
self.assertEqual(exit_code, expected_exit_code)
def test_nailgun_stdin(self):
lines = [str(i) for i in range(100)]
echo = '\n'.join(lines)
output = StringIO.StringIO()
input = StringIO.StringIO(echo)
echo = "\n".join(lines)
output = StringIO()
input = StringIO(echo)
with NailgunConnection(
self.transport_address,
stderr=None,
stdin=input,
stdout=output) as c:
exit_code = c.send_command('com.martiansoftware.nailgun.examples.Echo')
self.transport_address, stderr=None, stdin=input, stdout=output
) as c:
exit_code = c.send_command("com.facebook.nailgun.examples.Echo")
self.assertEqual(exit_code, 0)
actual_out = output.getvalue().strip()
self.assertEqual(actual_out, echo)
def test_nailgun_default_streams(self):
with NailgunConnection(self.transport_address) as c:
exit_code = c.send_command('ng-stats')
exit_code = c.send_command("ng-stats")
self.assertEqual(exit_code, 0)
def tearDown(self):
try:
def test_nailgun_heartbeats(self):
output = StringIO()
with NailgunConnection(
self.transport_address,
stderr=None,
stdin=None,
stdout=output,
heartbeat_interval_sec=0.1,
) as c:
# just run Heartbeat nail for 5 seconds. During this period there should be
# heartbeats received and printed back
exit_code = c.send_command(
"com.facebook.nailgun.examples.Heartbeat", ["5000"]
)
self.assertTrue(output.getvalue().count("H") > 10)
def test_nailgun_no_heartbeat(self):
output = StringIO()
with NailgunConnection(
self.transport_address,
stderr=None,
stdin=None,
stdout=output,
heartbeat_interval_sec=0,
) as c:
exit_code = c.send_command(
"com.facebook.nailgun.examples.Heartbeat", ["3000"]
)
self.assertTrue(output.getvalue().count("H") == 0)
def test_stress_nailgun_socket_close_without_race_condition(self):
output = StringIO()
for i in range(1000):
with NailgunConnection(
self.transport_address,
cwd=os.getcwd(),
stderr=None,
stdin=None,
stdout=None) as c:
c.send_command('ng-stop')
except NailgunException as e:
# stopping server is a best effort
# if something wrong has happened, we will kill it anyways
pass
stdout=output,
heartbeat_interval_sec=0.001,
) as c:
exit_code = c.send_command(
"com.facebook.nailgun.examples.Heartbeat", ["10"]
)
self.assertEqual(exit_code, 0)
# Python2 compatible wait with timeout
process_exit_code = None
for _ in range(0, 500):
process_exit_code = self.ng_server_process.poll()
if process_exit_code is not None:
break
time.sleep(0.02) # 1 second total
if process_exit_code is None:
# some test has failed, ng-server was not stopped. killing it
self.ng_server_process.kill()
shutil.rmtree(self.tmpdir)
class TestNailgunConnectionSmallHeartbeatTimeout(TestNailgunConnection):
def __init__(self, *args, **kwargs):
super(TestNailgunConnectionSmallHeartbeatTimeout, self).__init__(
*args, **kwargs
)
def setUp(self):
self.heartbeat_timeout_ms = 1000
super(TestNailgunConnectionSmallHeartbeatTimeout, self).setUp()
def test_nailgun_disconnect(self):
"""
We should disconnect before time elapses because of configuration:
Heartbeats are sent every 5 secs
Server expects to look for disconnects if no hearbeat is received in 1 sec
Server runs for 30 sec given we still have heartbeats, so it should output about 6 'H'
We assert that number of 'H' is smaller
"""
output = StringIO()
with NailgunConnection(
self.transport_address,
stderr=None,
stdin=None,
stdout=output,
heartbeat_interval_sec=5,
) as c:
exit_code = c.send_command(
"com.facebook.nailgun.examples.Heartbeat", ["30000"]
)
self.assertTrue(output.getvalue().count("H") < 3)
if __name__ == '__main__':
for i in range(10):
was_successful = unittest.main(exit=False).result.wasSuccessful()
if not was_successful:
sys.exit(1)
if __name__ == "__main__":
was_successful = unittest.main(exit=False).result.wasSuccessful()
if not was_successful:
sys.exit(1)
......@@ -2,32 +2,33 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.martiansoftware</groupId>
<groupId>com.facebook</groupId>
<artifactId>nailgun-examples</artifactId>
<packaging>jar</packaging>
<name>nailgun-examples</name>
<description>
Nailgun is a client, protocol, and server for running Java programs from
the command line without incurring the JVM startup overhead. Programs run
in the server (which is implemented in Java), and are triggered by the
client (written in C), which handles all I/O.
Nailgun is a client, protocol and server for running Java programs
from the command line without incurring the JVM startup overhead.
Programs run in the server (which is implemented in Java), and are
triggered by the client (C and Python clients available), which
handles all I/O.
This project contains the EXAMPLE CODE ONLY.
</description>
<url>http://martiansoftware.com/nailgun</url>
<url>http://github.com/facebook/nailgun</url>
<parent>
<groupId>com.martiansoftware</groupId>
<groupId>com.facebook</groupId>
<artifactId>nailgun-all</artifactId>
<version>0.9.3-SNAPSHOT</version>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.martiansoftware</groupId>
<groupId>com.facebook</groupId>
<artifactId>nailgun-server</artifactId>
<version>${version}</version>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
......
/*
/*
Copyright 2004-2012, Martian Software, Inc.
Copyright 2017-Present Facebook, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
......@@ -13,42 +13,39 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.martiansoftware.nailgun.examples;
package com.facebook.nailgun.examples;
import java.util.Iterator;
import com.facebook.nailgun.NGContext;
import java.util.TreeSet;
import com.martiansoftware.nailgun.NGContext;
/**
* Simply displays command line arguments to System.out.
*
*
* @author <a href="http://www.martiansoftware.com/contact.html">Marty Lamb</a>
*/
public class DumpAll {
public static void nailMain(NGContext context) {
context.out.println();
context.out.println(" context.getCommand(): " + context.getCommand());
context.out.println(" context.getInetAddress(): " + context.getInetAddress());
context.out.println(" context.getPort(): " + context.getPort());
context.out.println("context.getWorkingDirectory(): " + context.getWorkingDirectory());
context.out.println(" context.getFileSeparator(): " + context.getFileSeparator());
context.out.println(" context.getPathSeparator(): " + context.getPathSeparator());
context.out.println("\ncontext.getArgs():");
for (int i = 0; i < context.getArgs().length; ++i) {
context.out.println(" args[" + i + "]=" + context.getArgs()[i]);
}
context.out.println("\ncontext.getEnv():");
TreeSet keys = new TreeSet(context.getEnv().keySet());
for (Iterator i = keys.iterator(); i.hasNext();) {
String key = (String) i.next();
context.out.println(" env[\"" + key + "\"]=" + context.getEnv().getProperty(key));
}
}
public static void nailMain(NGContext context) {
context.out.println();
context.out.println(" context.getCommand(): " + context.getCommand());
context.out.println(" context.getInetAddress(): " + context.getInetAddress());
context.out.println(" context.getPort(): " + context.getPort());
context.out.println("context.getWorkingDirectory(): " + context.getWorkingDirectory());
context.out.println(" context.getFileSeparator(): " + context.getFileSeparator());
context.out.println(" context.getPathSeparator(): " + context.getPathSeparator());
context.out.println("\ncontext.getArgs():");
for (int i = 0; i < context.getArgs().length; ++i) {
context.out.println(" args[" + i + "]=" + context.getArgs()[i]);
}
context.out.println("\ncontext.getEnv():");
TreeSet keys = new TreeSet(context.getEnv().keySet());
for (Object okey : keys) {
String key = (String) okey;
context.out.println(" env[\"" + key + "\"]=" + context.getEnv().getProperty(key));
}
}
}
/*
/*
Copyright 2004-2012, Martian Software, Inc.
Copyright 2017-Present Facebook, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
......@@ -13,24 +13,23 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.martiansoftware.nailgun.examples;
package com.facebook.nailgun.examples;
/**
* Echos everything it reads from System.in to System.out.
*
*
* @author <a href="http://www.martiansoftware.com/contact.html">Marty Lamb</a>
*/
public class Echo {
public static void main(String[] args) throws Exception {
byte[] b = new byte[1024];
int bytesRead = System.in.read(b);
while (bytesRead != -1) {
System.out.write(b, 0, bytesRead);
bytesRead = System.in.read(b);
}
}
public static void main(String[] args) throws Exception {
byte[] b = new byte[1024];
int bytesRead = System.in.read(b);
while (bytesRead != -1) {
System.out.write(b, 0, bytesRead);
bytesRead = System.in.read(b);
}
}
}