I am writing a web service using Jersey and Grizzly. I want to run it using SSL. I have created server.jks and client.jks just like described here.
Running the web service:
public static HttpServer startServer() {
final ResourceConfig rc = new ResourceConfig().packages("com.mypackage");
SSLContextConfigurator sslContextConfigurator = new SSLContextConfigurator();
sslContextConfigurator.setKeyStoreFile("server.jks");
sslContextConfigurator.setKeyStorePass("changeit");
SSLEngineConfigurator sslEngineConfigurator = new SSLEngineConfigurator(sslContextConfigurator);
return GrizzlyHttpServerFactory.createHttpServer(URI.create(getURI().toString()), rc, true,
sslEngineConfigurator);
}
private static URI getURI() {
URI uri;
// Running on localhost
uri = UriBuilder.fromUri("https://" + "localhost/" + ConstApp.APP_PATH).port(ConstApp.PORT)
.build();
return uri;
}
So running the web service on localhost port 443 with the server.jks.
Now I want to check and test the web service.
Java HTTPClient class:
String https_url = "https://localhost:443/myapp";
URL url;
try {
url = new URL(https_url);
HttpsURLConnection sslCon = (HttpsURLConnection) url.openConnection();
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream stream = new FileInputStream("client.jks");
keyStore.load(stream, "changeit".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory sslSocketFactory = ctx.getSocketFactory();
sslCon.setSSLSocketFactory(sslSocketFactory);
sslCon.setRequestMethod("GET");
// add request header
sslCon.setRequestProperty("User-Agent", "Mozilla/5.0");
int responseCode = sslCon.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(sslCon.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// print result
System.out.println(response.toString());
} catch (Exception e) {
e.printStackTrace();
}
Running the HTTPClient result in an exception:
javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 1
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:196)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1513)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
at httpClient.HTTPClient.testIt(HTTPClient.java:158)
at httpClient.HTTPClient.main(HTTPClient.java:36)
Can anyone please help me out here and tell me what am I doing wrong?
Related
A client developed in Java using JDK 1.6. I am consuming API in the java code. Whenever I hit this API from soapui or from JDK 1.7 it is working perfectly fine but when I tried to hit this API using JDK 1.6, it is returning the error.
com.sun.xml.internal.ws.client.ClientTransportException: HTTP transport error: java.net.SocketException: Connection reset
I have tried by developing client using WSDL and using HTTPSURLConnection, with both mechanism, I am getting the same error. It seems there is nothing wrong with the code. I am unable to find out the way for the resolution.
Wireshark Result:
When I ran the jar from JDK 1.7, I can see the result in Wireshark, the protocol is TSLv1 but when I tried to run the jar from 1.6, the protocol has been changed to SSLv2.
Is it possible to change protocol in the code or on the system where we are calling jar?
Here is my code:
public String myFun(String sender) throws IOException,
NoSuchAlgorithmException, KeyManagementException{
SSLContext sslContext = SSLContext.getInstance("SSL");
TrustManager[] trustManager = getTrustManager();
sslContext.init(null, trustManager, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
try{
String inquiryRequest = inquiryRequest = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:v5=\"http://xxxxxxx\">\n"
+"<soapenv:Header>\n"
+"</soapenv:Header>\n"
+"<soapenv:Body>\n"
+"<v5:single.smsReq>\n"
+"<sender>"+sender+"</sender>\n"
+"</v5:single.smsReq>\n"
+"</soapenv:Body>\n"
+"</soapenv:Envelope>";
URL url =new URL ("https://xxxx:xx/xx");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("content-type","application/xml");
conn.setRequestProperty("Authorization","Basic xxx");
conn.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(inquiryRequest);
wr.flush();
wr.close();
BufferedReader in = new BufferedReader( new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
conn.disconnect();
return response.toString();
}catch(Exception e){
return null;
}
}
private TrustManager[] getTrustManager() {
TrustManager[] certs = new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String t) {
}
public void checkServerTrusted(X509Certificate[] certs, String t) {
}
}
};
return certs;
}
In SSLContext you can setup your own SSlContext TSLv1 or SSLv2 then call sslContext.init with trusted certificates. And, add it to your HttpsURLConnection as the DefaultSSLSocketFactory.
System.setProperty ("jsse.enableSNIExtension", "false");
SSLContext sslContext = SSLContext.getInstance("SSL");
TrustManager[] trustManager = getTrustManager();
sslContext.init(null, trustManager, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HostnameVerifier hostNameVerifier = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hostNameVerifier);
I am creating an application where I want to POST xml data directly (without key value pair) to API. The API needs certification authentication which is done here in code. Now I want to POST the data to same URL.
Here is what I want to do :
My current code is :
#Override
public String demoAPI(String xmlData) {
StringBuilder sb = new StringBuilder();
String output="";
try {
KeyStore clientStore = KeyStore.getInstance("PKCS12");
clientStore.load(new FileInputStream(new File("path-to-pfx-file")),
"password".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientStore, "password".toCharArray());
KeyManager[] kms = kmf.getKeyManagers();
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("path-to-jks-file"), "password".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
TrustManager[] tms = tmf.getTrustManagers();
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kms, tms, new SecureRandom());
SSLContext.setDefault(sslContext);
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
URL url = new URL("URL");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setConnectTimeout(100000);
con.setSSLSocketFactory(sslContext.getSocketFactory());
con.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
System.out.println(sb.toString());
output = sb.toString();
} catch (Exception e) {
e.printStackTrace();
output = e.getMessage();
}
return output;
}
Whereas , for same url , I want to POST xmlData from method.
How can I do that ? What should I change in the code after
con.setRequestMethod("POST"); ?
You have a url and you have some XML to post this url via HTTP. And your post request is a SOAP request, you can send this soap message in the body of this request. So nothing special or different than many developers' do. Post your soap data via http by using java.net or Apache or others. Here are the code samples to do this:
HttpsURLConnection con = null;
try{
URL url = new URL("URL");
con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("content-type", "application/x-www-form-urlencoded");
con.setRequestProperty("Content-Language", "application/soap+xml; charset=utf-8"); // request properties, set your needs
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write(xmlData.getBytes("utf-8"));
os.close();
}catch(Exception e){
e.printStackTrace();
}finally{
con.disconnect();
}
Another option would be to use Apache library. And the code:
HttpPost httpPost = new HttpPost("URL");
StringEntity strEntity = new StringEntity(xmlData, "text/xml", "UTF-8");
strEntity.setContentType("text/xml");
httpPost.setHeader("Content-Type","application/soap+xml;charset=UTF-8");
httpPost.setEntity(strEntity);
HttpClient httpclient = new DefaultHttpClient();
BasicHttpResponse httpResponse = (BasicHttpResponse) httpclient.execute(httpPost);
I want to add TLS 1.2 to the below code, Tried by creating socket but no luck. Can someone help on it ? Can we add it after creating a client ?
private static int executeSOAPRequest(String req, String targetURL)
throws Exception {
PostMethod post = new PostMethod(targetURL);
post.setRequestBody(req);
post.setRequestHeader("Content-type",
"text/xml; characterset=ISO-8859-1");
post.setRequestHeader("SOAPAction", "\"\"");
// prepare HTTP Client
HttpClient client = new HttpClient();
client.getParams().setParameter("SOAPAction", "\"\"");
// Post the request
int respCode = client.executeMethod(post);
System.out.println(post.getResponseBodyAsString());
// If response is not success
if (respCode != 200)
throw new Exception("Executing SOAP request has failed.");
// Convert the response into NOM XML
int resp = 0;
Document doc = nomDocPool.lendDocument();
try {
resp = doc.parseString(post.getResponseBodyAsString());
nomDocPool.returnDocument(doc);
} catch (XMLException e) {
nomDocPool.returnDocument(doc);
//logger.error("Exception while generating SAML : "
//+ e);
throw e;
}
System.out.println("resp: "+resp);
return resp;
}
HttpClient already handles TLS for you. This is documented:
http://hc.apache.org/httpclient-3.x/sslguide.html
HttpClient provides full support for HTTP over Secure Sockets Layer (SSL) or IETF Transport Layer Security (TLS) protocols by leveraging the Java Secure Socket Extension (JSSE). JSSE has been integrated into the Java 2 platform as of version 1.4 and works with HttpClient out of the box.
All you have to do is make sure your targetURL is using https:// instead of http://, then HttpClient handles the rest for you.
Forget HttpClient. Use javax.net.ssl.HttpsURLConnection.
String myResponse = null;
URL url = new URL(targetURL);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestProperty("Content-Type", "text/xml; characterset=ISO-8859-1");
con.setRequestProperty("SOAPAction", "\"\"");
con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(true);
con.setSSLSocketFactory(My_Lovely_CertificateHelper.getSslSocketFactory());
con.connect();
OutputStream os = con.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "ISO-8859-1");
osw.write(req);
osw.flush();
osw.close();
InputStream is = null;
if (con.getResponseCode() < HttpsURLConnection.HTTP_BAD_REQUEST) {
is = con.getInputStream();
} else {
is = con.getErrorStream();
}
InputStreamReader isr = new InputStreamReader(is, "ISO-8859-1");
int read = -1;
char[] buff = new char[1024];
StringBuilder sb = new StringBuilder();
while ((read = isr.read(buff)) != -1) {
sb.append(buff, 0, read);
}
myResponse = sb.toString();
return myResponse;
getSslSocketFactory()
public static SSLSocketFactory getSslSocketFactory() throws Exception {
SSLContext sc = SSLContext.getInstance("TLSv1.2");
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
String trustStorePath = getcertPath(); //"user.dir" + "\ohHappyDays.jks";
String password = "finallyFoundLoveIn2021";
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(trustStorePath), password.toCharArray());
kmf.init(ks, password.toCharArray());
sc.init(kmf.getKeyManagers(), (TrustManager[]) null, (SecureRandom) null);
return sc.getSocketFactory();
}
I'm building a server that has to call two webservices. Webservices have the same CA certificate (PKCS12).
the first one receives request by GET, the other one by SOAP call.
follow a part of code that creates connection for GET request
InputStream inputStream = null;
// is https protocol?
if (url.getProtocol().toLowerCase().equals("https")) {
trustAllHosts();
// create connection
HttpsURLConnection httpsUrlConnection = null;
if(proxy != null){
httpsUrlConnection = (HttpsURLConnection) url.openConnection(proxy);
} else {
httpsUrlConnection = (HttpsURLConnection) url.openConnection();
}
// set the check to: do not verify
httpsUrlConnection.setHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
setHeaders(httpsUrlConnection, headers);
//set del certificato
log.debug("set certificate for get...");
File cerp12 = new File(Utils.getWebAppLocalPath(),"WEB-INF"+String.valueOf(File.separatorChar)+PropConfig.getProperty("cer.p12"));
((HttpsURLConnection) httpsUrlConnection).setSSLSocketFactory(security(cerp12,PropConfig.getProperty("cer.pwd")));
httpsUrlConnection.connect();
inputStream = httpsUrlConnection.getInputStream();
} else {
HttpURLConnection httpUrlConnection = null;
if(proxy != null){
httpUrlConnection = (HttpURLConnection) url.openConnection(proxy);
} else {
httpUrlConnection = (HttpURLConnection) url.openConnection();
}
setHeaders(httpUrlConnection, headers);
inputStream = httpUrlConnection.getInputStream();
}
in = new BufferedReader(new InputStreamReader(inputStream));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result.append(inputLine);
}
and this part is for SOAP request
InputStream inputStream = null;
// is https protocol?
if (url.getProtocol().toLowerCase().equals("https")) {
trustAllHosts();
// create connection
HttpsURLConnection httpsUrlConnection = null;
if(proxy != null){
httpsUrlConnection = (HttpsURLConnection) url.openConnection(proxy);
} else {
httpsUrlConnection = (HttpsURLConnection) url.openConnection();
}
// set the check to: do not verify
httpsUrlConnection.setHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
setHeaders(httpsUrlConnection, headers);
//set del certificato
log.debug("set certificate for get...");
File cerp12 = new File(Utils.getWebAppLocalPath(),"WEB-INF"+String.valueOf(File.separatorChar)+PropConfig.getProperty("cer.p12"));
((HttpsURLConnection) httpsUrlConnection).setSSLSocketFactory(security(cerp12,PropConfig.getProperty("cer.pwd")));
httpsUrlConnection.connect();
inputStream = httpsUrlConnection.getInputStream();
} else {
HttpURLConnection httpUrlConnection = null;
if(proxy != null){
httpUrlConnection = (HttpURLConnection) url.openConnection(proxy);
} else {
httpUrlConnection = (HttpURLConnection) url.openConnection();
}
setHeaders(httpUrlConnection, headers);
inputStream = httpUrlConnection.getInputStream();
}
in = new BufferedReader(new InputStreamReader(inputStream));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result.append(inputLine);
}
the code is almost the same
with GET request I have no problem, but with SOAP request httpsUrlConnection.connect(); throws
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Here is howto create ssl context for HTTPS connection.
SSLSocketFactory socketFactory = createSSLContext().getSocketFactory();
HttpsURLConnection connection = (HttpsURLConnection) (url).openConnection();
connection.setSSLSocketFactory(socketFactory);
And method to create SSL context. Note, it load root server certificate from .pem file (x509 format) and client certificate from .p12 (pkcs12 format). If server don't required client certificate, pass null for key managers. If server sertificate issued by authority, which already in $JRE_HOME/lib/security/cacerts, pass null as trust managers.
And one more note: in .pem file you should store root certificate in PKIX path of server certificate. For example, github.com That site has PKIX path CN = github.com -> CN = DigiCert High Assurance EV CA-1 -> CN = DigiCert High Assurance EV Root CA -> CN = GTE CyberTrust Global Root. So you store GTE CyberTrust Global Root
private final SSLContext createSSLContext()
throws NoSuchAlgorithmException, KeyStoreException,
CertificateException, IOException,
UnrecoverableKeyException, KeyManagementException {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(Config.getString(Config.KEYSTORE_PATH)));
} catch (Exception ex) {
throw new IOException("not found keystore file: " Config.getString(Config.KEYSTORE_PATH), ex);
}
try{
keyStore.load(fis, Config.getString(Config.KEYSTORE_PASSWORD).toCharArray());
}finally {
IOUtils.closeQuietly(fis);
}
CertificateFactory cf = CertificateFactory.getInstance("X.509");
FileInputStream in = new FileInputStream(Config.getString(Config.HTTPS_SERVER_CERT));
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(null);
try {
X509Certificate cacert = (X509Certificate) cf.generateCertificate(in);
trustStore.setCertificateEntry("alias", cacert);
} finally {
IOUtils.closeQuietly(in);
}
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(trustStore);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keyStore, Config.getString(Config.KEYSTORE_PASSWORD).toCharArray());
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
return sslContext;
}
I'm trying to retrieve tweets from the Twitter streaming API using Twitter4J. The project connects to a remote server using an SSLSocket to retrieve some data and, after this, the Twitter4J is called. The problem is that if I establish this connection the Twitter4J arise this exception:
[Wed Feb 20 11:32:02 CET
2013]sun.security.validator.ValidatorException: PKIX path building
failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
This doesn't happen if I don't make the connection and I clean the keystore defined with the next lines:
System.clearProperty("javax.net.ssl.trustStore");
System.clearProperty("javax.net.ssl.trustStorePassword");
The code to connect is this one:
private String publishFetcher() throws UnknownHostException, IOException {
// Set trustStore.
System.setProperty("javax.net.ssl.trustStore", properties.getProperty("trustedStore"));
System.setProperty("javax.net.ssl.trustStorePassword", properties.getProperty("trustedStorePassword"));
String host = properties.getProperty("host");
int hostPort = Integer.parseInt(properties.getProperty("host_port"));
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket(host, hostPort);
// Get input and output streams from socket connection.
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter output = new PrintWriter(socket.getOutputStream());
// Request connection token to controller
String connectionToken = getConnectionToken(input, output);
// Publish fetcher
final int rmiPort = Integer.parseInt(properties.getProperty("rmi_port"));
TwitterFetcher fetcher = new TwitterFetcher(connector);
Fetcher stub = (Fetcher) UnicastRemoteObject.exportObject(fetcher, 0);
Registry registry = LocateRegistry.createRegistry(rmiPort);
registry.rebind(connectionToken, stub);
// Send RMI port
output.write(String.valueOf(rmiPort) + "\n");
output.flush();
input.close();
output.close();
// Clean trusteStore properties.
System.clearProperty("javax.net.ssl.trustStore");
System.clearProperty("javax.net.ssl.trustStorePassword");
return connectionToken;
}
I think that the problem is related with SSLSocketFactory because I tested somethings in a different project. For example, this code works like a charm:
SSLSocketFactory deffactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
System.setProperty("javax.net.ssl.trustStore", "sttv_keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "Smart.Table");
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
factory = deffactory;
// Twitter4J code...
But this code doesn't work:
System.setProperty("javax.net.ssl.trustStore", "sttv_keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "Smart.Table");
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
// Twitter4J code...
I can't do the same in my real project because breaks... almost everything ^^
What could be the problem? and the solution?
The problem with the code is that I was replacing the trust store instead of creating a new one for my app. The code that solves the problems is the next one:
private SSLSocket getSSLSocket() throws TrackerSSLConnectionException {
try {
// Load properties.
String keystore = properties.getProperty("keystore");
String passphrase = properties.getProperty("keystorePassphrase");
String host = properties.getProperty("host");
int hostPort = Integer.parseInt(properties.getProperty("host_port"));
// Create keystore.
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream(keystore), passphrase.toCharArray());
// Get factory for the given keystore.
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory factory = ctx.getSocketFactory();
return (SSLSocket) factory.createSocket(host, hostPort);
} catch (Exception e) {
throw new TrackerSSLConnectionException(e.getMessage(), e.getCause());
}
}
private String publishFetcher() throws TrackerSSLConnectionException, IOException {
// Get socket connection.
SSLSocket socket = getSSLSocket();
// Get input and output streams from socket.
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter output = new PrintWriter(socket.getOutputStream());
// Request connection token to controller.
String connectionToken = getConnectionToken(input, output);
// Publish fetcher.
final int rmiPort = Integer.parseInt(properties.getProperty("rmi_port"));
TwitterFetcher fetcher = new TwitterFetcher(connector);
Fetcher stub = (Fetcher) UnicastRemoteObject.exportObject(fetcher, 0);
Registry registry = LocateRegistry.createRegistry(rmiPort);
registry.rebind(connectionToken, stub);
// Send RMI port.
output.write(String.valueOf(rmiPort) + "\n");
output.flush();
input.close();
output.close();
return connectionToken;
}