/**
* EchoServer.java
* Copyright � 1998-2011 Research In Motion Limited
*
* 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.
*
* Note: For the sake of simplicity, this sample application may not leverage
* resource bundles and resource strings. However, it is STRONGLY recommended
* that application developers make use of the localization features available
* within the BlackBerry development platform to ensure a seamless application
* experience across a variety of languages and geographies. For more information
* on localizing your application, please refer to the BlackBerry Java Development
* Environment Development Guide associated with this release.
*/
package com.rim.samples.server.communicationapidemo;
import static java.net.HttpURLConnection.HTTP_OK;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
/**
* A class to echo the body of an HTTP request back as the HTTP response. The URL
* to access the HTTPServer is "http://[YOUR_IP]:8105/JSON".
*/
public final class EchoServer
{
public final static int RESPONSE_DELAY = 1;
public static int reqCounter = 1;
private static DateFormat df = new SimpleDateFormat("HH:mm:ss MM/dd/yy");
private static int port = 8105; // Server port
/**
* Entry point
*/
public static void main(String[] args) throws IOException
{
final InetSocketAddress addr;
final HttpServer server;
String address = InetAddress.getLocalHost().getHostAddress();
addr = new InetSocketAddress(address, port);
server = HttpServer.create(addr, 10);
server.createContext("/ATOM", new GenericHandler("public_timeline.atom"));
server.createContext("/RSS", new GenericHandler("public_timeline.rss"));
server.createContext("/SOAP", new GenericHandler("simple_soap.xml"));
server.createContext("/JSON", new GenericHandler("public_timeline.json"));
server.createContext("/XML", new GenericHandler("public_timeline.xml"));
server.createContext("/TEXT", new TEXTHandler());
server.createContext("/TEXT2", new TEXTHandler());
server.start();
System.out.println("Server started on IP: " + address + ":" + port + " at " + df.format(new Date()));
String serverUri = "http://" + address + ":" + port;
String statusInfo = String.format("\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", "Listening for requests:", serverUri + "/ATOM", serverUri
+ "/RSS", serverUri + "/SOAP", serverUri + "/JSON", serverUri + "/XML", serverUri + "/TEXT", serverUri + "/TEXT2");
System.out.println(statusInfo);
System.out.println("Responses will be sent with a delay of " + RESPONSE_DELAY + " sec");
}
/**
* Reads a file and returns its contents in a byte array
*
* @param file File to read
* @return byte array of file contents
* @throws IOException
*/
public static byte[] getBytesFromFile(File file) throws IOException
{
InputStream is = new FileInputStream(file);
System.out.println("\tReading file:" + file.getName());
// Get the size of the file
long length = file.length();
//Before converting length to an int type, check to ensure that file is
// not larger than Integer.MAX_VALUE.
if(length > Integer.MAX_VALUE)
{
System.out.println("\tFile is too large to process");
return null;
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int) length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while((offset < bytes.length) && ((numRead = is.read(bytes, offset, bytes.length - offset)) >= 0))
{
offset += numRead;
}
// Ensure all the bytes have been read in
if(offset < bytes.length)
{
throw new IOException("\tCould not completely read file " + file.getName());
}
is.close();
return bytes;
}
}
class GenericHandler implements HttpHandler
{
private String path = "com\\rim\\samples\\server\\communicationapidemo\\";
private String _fileName;
private DateFormat df = new SimpleDateFormat("HH:mm:ss MM/dd/yy");
public GenericHandler(String fileName)
{
_fileName = fileName;
}
public void handle(HttpExchange t) throws IOException
{
final OutputStream os;
String response;
System.out.println("\n>> incoming request [id: " + EchoServer.reqCounter++ + ", time: " + df.format(new Date()) + "]");
byte[] fileArray = EchoServer.getBytesFromFile(new File(path + _fileName));
response = "";
if(fileArray != null)
{
for(int i = 0; i < fileArray.length; ++i)
{
response += (char) fileArray[i];
}
}
try
{
System.out.print("\tWaiting " + EchoServer.RESPONSE_DELAY + " sec ...");
Thread.sleep(EchoServer.RESPONSE_DELAY * 1000);
System.out.println("DONE");
}
catch(InterruptedException e)
{
e.printStackTrace();
}
t.sendResponseHeaders(HTTP_OK, response.length());
os = t.getResponseBody();
os.write(response.getBytes());
os.close();
t.close();
System.out.println("<< response [length = " + response.length() + ", time: " + df.format(new Date()) + "]");
System.out.flush();
}
}
class TEXTHandler implements HttpHandler
{
private DateFormat df = new SimpleDateFormat("HH:mm:ss MM/dd/yy");
public void handle(HttpExchange t) throws IOException
{
final InputStream is;
final OutputStream os;
StringBuilder buf;
int b;
final String request, response;
System.out.println("\n>> incoming request [id: " + EchoServer.reqCounter++ + ", time: " + df.format(new Date()) + "]");
buf = new StringBuilder();
is = t.getRequestBody();
while((b = is.read()) != -1)
{
buf.append((char) b);
}
is.close();
response = buf.toString();
/*
* Now send the response. We could have instead done this
* dynamically, using 0 as the response size (forcing chunked encoding)
* and writing the bytes of the response directly to the OutputStream,
* but building the String first allows us to know the exact length so
* we can send a response with a known size.
*/
try
{
System.out.print("\tWaiting " + EchoServer.RESPONSE_DELAY + " sec ...");
Thread.sleep(EchoServer.RESPONSE_DELAY * 1000);
System.out.println("DONE");
}
catch(InterruptedException e)
{
e.printStackTrace();
}
t.sendResponseHeaders(HTTP_OK, response.length());
os = t.getResponseBody();
os.write(response.getBytes());
os.close();
t.close();
System.out.println("<< response [length = " + response.length() + ", time: " + df.format(new Date()) + "]");
System.out.flush();
}
}