Hotjava Protocol and Content Handler
ÇöÀç ´ëºÎºÐÀÇ ÀÚ¹Ù ÇÁ·Î±×·¥Àº ÀÚ¹Ù ¾ÖÇø´°ú ¾îÇø®ÄÉÀ̼ÇÀÌ ÁÖ·ù¸¦ ÀÌ·ç°í ÀÖ´Ù. ±×·¯³ª ÇÖÀÚ¹Ù ºê¶ó¿ìÀúÀÇ µ¿ÀûÀÎ ÇÁ·ÎÅäÄÝ, µ¥ÀÌÅÍ Å¸ÀÔÀÇ È®ÀåÀ» À§ÇØ »ç¿ëµÇ´Â ÇÁ·ÎÅäÄÝ Çڵ鷯, ÄÁÅÙÆ® Çڵ鷯 ¶ÇÇÑ Â÷¼¼´ë ÀÚ¹Ù¸¦ ÀÌ¿ëÇÑ ¾îÇø®ÄÉÀÌ¼Ç È®Àå ±â¼ú·Î Â÷Èķδ ¸¹Àº ¿¹Á¦µéÀÌ ½ñ¾ÆÁ® ³ª¿Ã °ÍÀÌ´Ù. ÇÁ·ÎÅäÄÝ Çڵ鷯³ª ÄÁÅÙÆ® Çڵ鷯 ±¸ÇöÀ» À§ÇÑ Ç÷§ÆûÀ¸·Î´Â ÇÖÀÚ¹Ù ºê¶ó¿ìÀú¸¸À» »ç¿ëÇÒ ¼ö ÀÖ´Ù´Â Á¡À» À¯ÀÇÇÏÀÚ. º» ³í¹®¿¡¼´Â À̸¦ °¡´ÉÇÏ°Ô ÇÏ´Â ÇÖÀÚ¹ÙÀÇ ÄÁÅÙÆ® Çڵ鷯¿Í ÇÁ·ÎÅäÄÝ Çڵ鷯ÀÇ °³³ä, ÇÁ·Î±×·¡¹Ö ¹æ¹ýµîÀ» ¿¹Á¦¸¦ ÅëÇØ ±â¼úÇÑ´Ù.
(±×¸² 1) ÇÖÀÚ¹ÙÀÇ ÇÁ·ÎÅäÄÝ, µ¥ÀÌŸ ó¸® È®Àå ±â¼ú
ÀϹÝÀûÀÎ À¥ ÇÁ·ÎÅäÄÝ(http, ftp, telnet, news, mailto ...)°ú ÄÁÅÙÆ® (html, text, gif, jpg ...)ÀÇ Ã³¸®´Â À¥ ºê¶ó¿ìÀúÀÇ °íÁ¤ÈµÈ Çù»ó °úÁ¤À» ÅëÇØ ÀÌ·ç¾îÁø´Ù. ¹Ý¸é, ÇÖÀÚ¹Ù ºê¶ó¿ìÀú´Â (±×¸² 2)¿Í °°Àº µ¿ÀûÀÎ Çù»ó°úÁ¤ÀÌ ÀÌ·ç¾îÁö¹Ç·Î, »õ·Î¿î ÇÁ·ÎÅäÄÝ, µ¥ÀÌŸ¸¦ È®ÀåÇÒ ¼ö ÀÖ´Â °¡´É¼ºÀÌ »ý±â°Ô µÈ´Ù.
(±×¸² 2) ÇÖÀÚ¹ÙÀÇ µ¥ÀÌŸ, ÇÁ·ÎÅäÄÝ Ã³¸®
<protocol>://<host>/<file>
ÇÁ·ÎÅäÄÝ Ã³¸® ·çƾÀ» ã°Ô µÇ¸ç, »õ·Î¿î ÇÁ·ÎÅäÄÝÀÎ °æ¿ì, ÇØ´çÇÏ´Â
ÇÁ·ÎÅäÄÝ Çڵ鷯 ·çƾÀ» ã¾Æ 󸮸¦ ÇϰԵȴÙ.
ÀÌ·¯ÇÑ ¹æ½ÄÀº ±âÁ¸ ÇÁ·ÎÅäÄÝÀÇ À¥ ±â´É È®Àå¸é »Ó¸¸ ¾Æ´Ï¶ó
»ç¿ëÀÚ°¡ »õ·Ó°Ô Á¤ÀÇÇÑ ÇÁ·ÎÅäÄÝ¿¡ ÀÌ·ç±â±îÁö Æø³Ð°Ô Àû¿ë°¡´ÉÇÏ´Ù.
¿¹¸¦ µé¸é ´ÙÀ½°ú °°Àº Àû¿ëÀÌ °¡´ÉÇÑ´Ù.
±âÁ¸ À¥ ºê¶ó¿ìÀú¿¡¼´Â http, ftp, telent¿Í °°Àº ÇÁ·ÎÅäÄݵéÀ» Áö¿øÇϰí ÀÖ´Ù. º» ³í¹®¿¡¼´Â finger ÇÁ·ÎÅäÄÝÀ» À§ÇÑ Äڵ带 ÇÁ·ÎÅäÄÝ Çڵ鷯·Î ÀÛ¼ºÇÏ¿© ÇÖÀÚ¹Ù¿¡¼ È®Àå »ç¿ëÀÌ °¡´ÉÇϵµ·Ï ÀνºÅç½ÃÄѺ¸ÀÚ. ÀÎÅÍ³Ý µµ¸ÞÀÎ etri.re.krÀ» °®´Â ȯ°æ¿¡¼ finger ¼ºñ½º¸¦ À§ÇÑ ÇÁ·ÎÅäÄÝ Çڵ鷯¸¦ ÀνºÅçÇÏ¿© ó¸®ÇϰíÀÚ ÇÑ´Ù¸é ´ÙÀ½°ú °°Àº ÀνºÅç °úÁ¤°ú ÇÁ·Î±×·¡¹Ö °úÁ¤ÀÌ ¿ä±¸µÈ´Ù. ÀÎÅÍ³Ý µµ¸ÞÀÎÀ» µû¶ó ÇÁ·ÎÅäÄÝ Çڵ鷯¸¦ ÀÛ¼ºÇÏ´Â ÀÌÀ¯´Â ³×ÀÌ¹Ö Ãæµ¹À» ¹æÁöÇϱâ À§ÇؼÀÌ´Ù.
classes - kr - re - etri- protocol - finger
´ë°³ µð·ºÅ丮ÀÇ ½ÃÀÛÀº classes·Î Çϸç, ³ª¸ÓÁö 4°¡Áö µð·ºÅ丮 À̸§Àº
kr.re.etri.protocol ÆÐŰÁö¸¦ »ý¼ºÇϱâ À§ÇÑ À̸§µéÀÌ´Ù. ¸¶Áö¸· finger µð·ºÅ丮´Â
ÇÁ·ÎÅäÄÝ Çڵ鷯ÀÇ À̸§°ú °°¾Æ¾ß ÇÑ´Ù.
classes - kr - re - etri- protocol - finger - Handler.java
|- FingerURLConnection.java
finger ÇÁ·ÎÅäÄÝ Çڵ鷯¸¦ À§ÇÑ ÀÚ¹Ù ¼Ò½º ÆÄÀÏÀÎ Handler.java¿Í
FingerURLConnection.java¸¦ finger µð·ºÅ丮 ¾Æ·¡¿¡ ÀÛ¼ºÇÑ´Ù.
ÆÐŰÁö·Î package kr.re.etri.protocol.finger°¡ ¼±¾ðµÇ¾î¾ß Çϸç,
Handler.java ÇÁ·Î±×·¥Àº java.net ÆÐŰÁöÀÇ
URLStreamHandler Ŭ·¡½ºÀÇ ÇÏÀ§Å¬·¡½º·Î Á¤ÀÇÇØ¾ß Çϸç,
FingerURLConnection.java ÇÁ·Î±×·¥Àº URLConnectionÀÇ ÇÏÀ§Å¬·¡½º·Î
Á¤ÀÇÇØ¾ß ÇÔÀ» À¯ÀÇÇÑ´Ù.
URLStreamHandler Ŭ·¡½º´Â JDK 1.0.2 java.net ÆÐŰÁö¿¡ ´ÙÀ½°ú °°Àº °èÃþ ±¸Á¶·Î Æ÷ÇԵǾî ÀÖÀ¸¸ç Á¤ÀÇµÈ ¸Þ¼Òµå´Â ´ÙÀ½°ú °°´Ù.
java.lang.Object | +----java.net.URLStreamHandler
Handler.java ÄÚµå´Â (ÄÚµå 1)°ú °°´Ù. openConnection() ¸Þ¼Òµå´Â ¿À¹ö¶óÀ̵åµÇ¾î ÁÖ¾îÁø urlÀ» °¡Áö°í FingerURLConnection(url) Ŭ·¡½º¸¦ È£ÃâÇϰԲû µÇ¾îÀÖ´Ù. fingerÀÇ URL ½ºÅ´ Á¤ÀǸ¦ À§ÇØ parseURL()°ú toExternalForm()À» ¿À¹ö¶óÀ̵å ÇÏ¿´´Ù.
//ÄÚµå 1 : Handler.java
package kr.re.etri.protocol.finger;
import java.net.*;
import java.io.*;
import java.util.StringTokenizer;
public class Handler extends java.net.URLStreamHandler {
static void debug(String s) {
System.err.println(s);
}
public Handler () {
System.out.println("Made a FingerURLStreamHandler");
}
protected URLConnection openConnection(URL url) throws IOException {
return new FingerURLConnection(url);
}
protected void parseURL(URL u, String spec, int start, int limit) {
String protocol = u.getProtocol();
String host = new String();
int port = u.getPort();
if(port <=0)
port = 79; // default port for finger
String file = new String();
String ref = null;
StringTokenizer st = null;
if ((start <= limit )) {
while(spec.charAt(start) == '/' || spec.charAt(start) == ':')
start++;
}
st = new StringTokenizer(spec.substring(start), ",", false);
while(st.hasMoreTokens()) {
String elem = st.nextToken();
String newHost, newUser;
int i;
if(elem == null)
continue;
i = elem.indexOf('@');
if(i < 0) {
try {
newHost = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
newHost = "localhost";
}
}
else
newHost = new String(elem.substring(i + 1));
newUser = new String(elem.substring(0, i));
if(host.length() != 0) {
file += ",";
host += ",";
}
file += newUser;
host += newHost;
}
setURL(u, protocol, host, port, file, ref);
}
/**
* reverse parse the URL - put back to "original" form
*/
protected String toExternalForm(URL u) {
StringTokenizer st1 = new StringTokenizer(u.getFile(), ",", false);
StringTokenizer st2 = new StringTokenizer(u.getHost(), ",", false);
String body = new String();
while(st1.hasMoreTokens() && st2.hasMoreTokens())
body += st1.nextToken() + "@" + st2.nextToken() + ",";
return new String(u.getProtocol() + "://" + body);
}
}
¶ÇÇÑ °°Àº µð·ºÅ丮¿¡ FingerURLConnection.java ¼Ò½º ÆÄÀϵµ (ÄÚµå 2)¿Í °°ÀÌ
ÀÛ¼ºÇÑ´Ù.
//ÄÚµå 2 : FingerURLConnection.java
package kr.re.etri.protocol.finger;
import java.net.*;
import java.io.*;
import java.util.StringTokenizer;
import java.util.Date;
public class FingerURLConnection extends java.net.URLConnection {
private void debug(String s) {
System.err.println(s);
}
private Socket server = null;
public FingerURLConnection (URL url) {
super(url);
System.out.println("Made a FingerURLConnection");
}
public Object getContent() throws IOException {
debug("In FingerURLConnection.getContent()");
StringBuffer sb = new StringBuffer();
sb.append("<TITLE>Finger output</TITLE>\n<HTML>");
StringTokenizer st1 = new StringTokenizer(url.getFile(), ",", false);
StringTokenizer st2 = new StringTokenizer(url.getHost(), ",", false);
while (st1.hasMoreTokens() && st2.hasMoreTokens()) {
sb.append("<P><HR>" + getSingleData(st1.nextToken(), st2.nextToken()));
}
sb.append("<P><P><HR>" + ((new Date()).toString()) + "\n</HTML>");
return sb.toString();
}
public void connect() throws IOException {
debug("fingerURLconn::connect");
}
private String getSingleData(String user, String host) {
try {
server = new Socket(host, 79);
System.out.println("Made socket to " + host + " on port " + 79);
} catch (UnknownHostException uk) {
debug("Unknown host in getSingleData: " + host);
return "<PRE>Unknown host " + host + "</PRE>";
} catch (SocketException ee) {
debug("SocketException in getSingleData: " + host);
return "<PRE>No finger server running on " + host + "</PRE>";
} catch (IOException eee) {
debug("IOException in getSingleData, making socket: "
+ eee.getMessage());
eee.printStackTrace();
return "<PRE>IOError connecting to " + host + "</PRE>";
}
debug("write to socket");
PrintStream ps = null;
DataInputStream dis = null;
try {
ps = new PrintStream(server.getOutputStream());
dis = new DataInputStream(server.getInputStream());
} catch (IOException e) {
debug("input/output error making streams: " + e.getMessage());
e.printStackTrace();
return "<PRE>ERROR OCCURRED</PRE>";
}
ps.println(user);
String li = null;
StringBuffer sb = new StringBuffer();
sb.append("<PRE>Finger data for " + user + "@" + host + ":</PRE><BR>\n");
try {
while((li = dis.readLine()) != null) {
debug("Server output:>> " + li);
sb.append(li + "\n<P>");
}
} catch (IOException e) {
debug("input/output error in readLine: " + e.getMessage());
e.printStackTrace();
return "<PRE>ERROR OCCURRED</PRE>";
}
return sb.toString();
}
public InputStream getInputStream() throws IOException {
debug("In FingerURLConn::getInputStream");
if(!connected)
connect();
return new StringBufferInputStream((String)getContent());
}
public String getContentType() {
debug("getting FingerURLConn::ContentType()");
return "text/html";
}
public OutputStream getOutputStream() throws IOException {
if(!connected)
connect();
return null;
}
}
setenv CLASSPATH .:/home/developer/classes
µµ½º ½©(Windows 95/NT)ÀÎ °æ¿ì,
set CLASSPATH=.;C:\developer\classes
cd kr/re/etri/protocol/finger
javac Handler.java
javac RunURLConnection.java
µµ½º ½©(Windows 95/NT)ÀÎ °æ¿ì
cd kr\re\etri\protocol\finger
javac Handler.java
javac RunURLConnection.java
$HOME/.hotjava/properties
µµ½º ½©(Windows 95/NT)ÀÎ °æ¿ì,
\.hotjava\properties
ÇÖÀÚ¹Ù ÇÁ¶óÆÛƼ ÆÄÀÏ¿¡ »õ·Î¿î ÆÐŰÁöÀÎ kr.re.etri.protocol.finger¸¦ Æ÷ÇÔÇϵµ·Ï ¼¼ÆÃÇÑ´Ù.
java.protocol.handler.pkgs=kr.re.etri.protocol
finger://mkshin@pec.etri.re.kr
ÇÖÀÚ¹ÙÀÇ °á°ú ȸéÀº (±×¸² 3)°ú °°´Ù.
(±×¸² 3) finger ÇÁ·ÎÅäÄÝ Çڵ鷯 °á°ú ȸé
classes - kr - re - etri - content - text
´ë°³ µð·ºÅ丮´Â classes·Î ½ÃÀÛÇϸç, ³ª¸ÓÁö 4°¡Áö µð·ºÅ丮 À̸§Àº
kr.re.etri.content ÆÐŰÁö¸¦ »ý¼ºÇϱâ À§ÇÑ À̸§µéÀÌ´Ù.
¸¶Áö¸· text µð·ºÅ丮´Â µ¥ÀÌÅÍÀÇ MIME ŸÀÔ°ú °°Àº À̸§À» °¡Á®¾ß ÇÑ´Ù.
classes - kr - re - etri - content - text - plain.java
text µð·ºÅ丮 ¾Æ·¡¿¡ text/plain ŸÀÔÀÇ ¹®¼¸¦ ó¸®Çϱâ À§ÇÑ
ÀÚ¹Ù ¼Ò½º ÆÄÀÏÀÎ plain.java¸¦ ÀÛ¼ºÇÑ´Ù.
ÆÐŰÁö·Î package
kr.re.etri.content.text°¡ ¼±¾ðµÇ¾î¾ß Çϸç,
java.net ÆÐŰÁöÀÇ ContentHandler Ŭ·¡½ºÀÇ ÇÏÀ§Å¬·¡½º
·Î Á¤ÀÇÇØ¾ß ÇÔÀ» À¯ÀÇÇÑ´Ù.
ContentHandler Ŭ·¡½º´Â JDK1.0.2 java.net ÆÐŰÁö¿¡ ´ÙÀ½°ú °°Àº °èÃþ ±¸Á¶·Î Æ÷ÇԵǾî ÀÖÀ¸¸ç Á¤ÀÇµÈ ¸Þ¼Òµå´Â ´ÙÀ½°ú °°´Ù.
java.lang.Object | +----java.net.ContentHandler
// ÄÚµå 3 plain.java
package kr.re.etri.content.text;
import java.net.ContentHandler;
import java.io.InputStream;
import java.net.URLConnection;
import java.io.IOException;
public class plain extends ContentHandler {
public Object getContent(URLConnection uc) {
try {
InputStream is = uc.getInputStream();
StringBuffer sb = new StringBuffer();
int c;
sb.append("[Content of " + uc.getURL() + "]\n\n");
sb.append("[This opening message brought to you by your
plain/text\n");
sb.append("content handler. To remove this content handler,
delete the\n");
sb.append("kr.re.etri.content.text directory from your class path
and\n");
sb.append("the java.content.handler.pkgs property from your
HotJava\n");
sb.append("properties file.]\n");
sb.append("-------------------------------------\n\n");
while ((c = is.read()) >= 0) {
sb.append((char)c);
}
is.close();
return sb.toString();
} catch (IOException e) {
return "Problem reading document: " + uc.getURL();
}
}
}
setenv CLASSPATH .:/home/developer/classes
µµ½º ½©(Windows 95/NT)ÀÎ °æ¿ì,
set CLASSPATH=.;C:\developer\classes
javac plain.java
$HOME/.hotjava/properties
µµ½º ½©(Windows 95/NT)ÀÎ °æ¿ì,
\.hotjava\properties
ÇÖÀÚ¹Ù ÇÁ¶óÆÛƼ ÆÄÀÏ¿¡ »õ·Î¿î ÄÁÅÙÆ® ÆÐŰÁöÀÎ kr.re.etri.content.text¸¦ Æ÷ÇÔÇϵµ·Ï ¼¼ÆÃÇÑ´Ù.
java.content.handler.pkgs=kr.re.etri.content
This document has two lines. This is the first line.
This is the second (and last) line.
ÇÖÀÚ¹Ù ºê¶ó¿ìÀú ³»¿¡´Â ´Ü¼øÈ÷ À§ÀÇ µÎÁÙ¸¸ÀÌ Ãâ·ÂµÇ´Â °ÍÀÌ ¾Æ´Ï°í
(ÄÚµå 3)ÀÇ getContent() ¸Þ¼Òµå¿¡¼ Á¤ÀÇµÈ Ãâ·ÂÆû´ë·Î
(±×¸² 4)¿Í °°Àº °á°ú°¡ Ãâ·ÂµÈ´Ù.
(±×¸² 4) text/plain ÄÁÅÙÆ® Çڵ鷯 °á°ú ȸé