/**
* TcpLinePrinter Class
*
* Printer driver implementation to communicate to network printer using Socket API.
* See: http://lprng.sourceforge.net/LPRng-Reference-Multipart/socketapi.htm
*
* @author Wahyu Yoga Pratama (wyogap@thatcoolguy.com)
*
* @created Jan 29, 2010
* @version $$
*
* HISTORY:
* - 2010/01/29 Created.
*
*/
package tcg.print;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
public class TcpLinePrinter implements ILinePrinter
{
//private static byte[] END_OF_TRANSMISSION = { 0x4 };
//private static byte[] UNICODE_MAKER = { (byte)0xff, (byte)0xfe };
private static final int DEF_SOCK_TIMEOUT_MILLIS = 500;
private String hostname_ = "";
private int port_ = 0;
private int timeoutMillis_ = DEF_SOCK_TIMEOUT_MILLIS;
/**
* Check if we can connect to the desired printer.
*
* @return true if we can connect, false otherwise
*/
public TcpLinePrinter(String hostname, int port)
{
if (hostname != null) hostname_ = hostname;
port_ = port;
}
public boolean ping()
{
//open connection to the print server
Socket sock = new Socket();
try
{
sock.bind(null);
sock.connect(new InetSocketAddress(hostname_, port_), timeoutMillis_);
}
catch (IOException ioe)
{
return false;
}
//open dummy input stream and output stream
try
{
sock.getOutputStream();
sock.getInputStream();
}
catch (IOException ioe)
{
return false;
}
//close the connection
try
{
sock.close();
}
catch(IOException ioe)
{
//ignore
}
//successful
return true;
}
/**
* Print a printable object
*
* @param printable - the printable object
* @return true if we can print successfully, false otherwise
* @throws RuntimeException if there is an error
*/
public boolean print(IPrintable printable) throws RuntimeException
{
//validation
if (printable == null) return true;
//open connection to the print server
Socket sock = new Socket();
try
{
sock.bind(null);
sock.connect(new InetSocketAddress(hostname_, port_), timeoutMillis_);
}
catch (IOException ioe)
{
throw new RuntimeException("print: can not connect to remote print server " +
hostname_ + ":" + port_ + ". Error: " + ioe.toString());
}
//get the bytes to send to print server
byte[] data = printable.getBytes();
//since java string is unicode, we must send unicode marker first before sending the raw data
//byte[] control = { (byte)0xFE, (byte)0xFF }; //or should it be 0xFFFE?
//since we use UTF-8 for our charset conversion, we do not need unicode marker
byte[] control = {};
//send the data
try
{
OutputStream os = sock.getOutputStream();
os.write(control);
os.write(data);
os.flush();
}
catch (IOException ioe)
{
throw new RuntimeException("print: can not write to remote print server. Error: "
+ ioe.toString());
}
//get the acknowledge. not really necessary since we close the connection right away.
//TODO: must find out how to interpret the data from printer
//try
//{
// InputStream is = sock.getInputStream();
//}
//catch (IOException ioe)
//{
// throw new RuntimeException("print: can not get acknowledgement from remote print server " +
// hostname_ + ":" + port_ + ". error: " + ioe.toString());
//}
//close the connection
try
{
sock.close();
}
catch(IOException ioe)
{
//ignore
}
return true;
}
/**
* Print a printable object.
*
* This is a hack function allowing us to call print() without worrying to catch
* the possible runtime exception, thus simplifying the code. This should only be used
* when we do not care what the possible failure reason is.
*
* @param printable - the printable object
* @return true if we can print successfully, false otherwise
*/
public boolean _print(IPrintable printable)
{
try
{
return print(printable);
}
catch (RuntimeException re)
{
//ignore
return false;
}
}
}