class ad extends ActiveCacheInterface {
// maximal 10 positions in document,
static int MAXPOS = 10;
// 10 possible choices for rotation
banner for each position
static int MAXOPT = 10;
// the main function of the applet
public static int FromCache(String User_HTTP_Request,
String Client_IP_Address,
String Client_Name,
int Cache_File,
int New_File)
{
boolean inCache;
// ads.obj is the
specification file, which specifies the
// positions in
documents and ratation banners, check
// whether the ads.obj
object is in ActiveCache
inCache = is_in_cache("ads.obj");
// if the object
is not in cache, we need to get it
// from the server
and save it in an object in ActiveCache
if (!inCache) {
int result;
result = getAdsObj();
if (result == -1) return -1;
}
// the positions
in the document
String position[] = new String[MAXPOS];
// the rotation
banners for all the positions
String htmls[][] = new String[MAXPOS][MAXOPT];
// the probability
of each roataion banner
double freqs[][] = new double[MAXPOS][MAXOPT];
// the seed for
each position
long seeds[] = new long[MAXPOS];
// initialize these
variables
init(htmls, position, freqs, seeds);
// read the content
of the ads.obj into the variables
// including the
positions, rotation banners, probabilities
if (readAdsObj(position, htmls, freqs) ==
-1)
return -1;
// read the seeds
into the variable seeds
readSeed(seeds);
// now we scan the
document and insert rotation banners
// in their positions
String line, posStr;
while (true) {
// read
a line from the cached document
line = readLine(Cache_File);
// if
there is nothing left from the document, exit
if (line.equals(""))
break;
// check
whether this line contains start pattern of position
// which
is the form: <!-- Begin Rotate Banner position i -->
posStr = checkBeginBanner(line);
if (posStr.equals("")) {
// no pattern in this line, just copy this line to new document
byte tmp[] = new
byte[line.length()];
line.getBytes(0,
line.length(), tmp, 0);
write(New_File, tmp,
tmp.length);
} else {
// rotate banner section begins, posStr is the position string
int pos, choice;
// check whether this position string is specified by ads.obj
pos = findPosition(position,
posStr);
// if not specified, ignore this pattern
if (pos == -1) continue;
// we make a choice as which banner to insert for this position
choice = makeChoice(freqs[pos],
seeds[pos]);
// change the seed for this position, so next time it is different
changeSeed(seeds,
pos);
// write the rotation banner corresponding to the choice into new document
byte tmp[] = new
byte[htmls[pos][choice].length()];
htmls[pos][choice].getBytes(0,
htmls[pos][choice].length(), tmp, 0);
write(New_File, tmp,
tmp.length);
// sacan the cached document until we found the end pattern
while (true) {
line
= readLine(Cache_File);
if (line.equals(""))
break;
if (checkEndBanner(line))
break;
}
}
}
// some seeds may
have changed, we write the updated seeds into seed object
writeSeed(seeds);
// let the proxy
give the new document to client
return 1;
}
// send HTTP request to server to get
the ads.obj object
// parse the respone from server and
save the content of
// response into an object in ActiveCache
private static int getAdsObj()
{
StringBuffer reqStr = new StringBuffer();
String curDoc, docName;
int pos;
int fd, newfd;
boolean result;
// construct the
url of ads.obj, which is the url
// of the document
appended by .ads.obj
// get the url of
the current document
curDoc = curdocurl();
pos = curDoc.indexOf("http://");
if (pos == -1) return -1;
pos = curDoc.indexOf('/', pos+8);
if (pos == -1) return -1;
docName = curDoc.substring(pos);
// construct the
HTTP request, GET html_doc.ads.obj HTTP/1.0
reqStr.append("GET ").append(docName)
.append(".ads.obj").append("
HTTP/1.0\n\n");
// send request
to server getting the object
fd = send_request_to_server(new String(reqStr));
if (fd == -1) return -1;
// see whether the
GET request succeeded
result = ParseResult(fd);
if (!result) return -1;
// filter the header part of the response
filterHeader(fd);
// create an object
in ActiveCache for the ads.obj
newfd = create("ads.obj", 00700);
if (newfd == -1) return -1;
int num;
byte buf[];
buf = new byte[1024];
// save the content
of the response into ads.obj
while ((num = read(fd, buf, 1024)) > 0) {
write(newfd, buf, num);
}
close(newfd);
return 0;
}
// check whether the status of the response
is 200
// the response should begin with HTTP/1.x
200 OK
private static boolean ParseResult(int fd)
{
String line, result;
int pos;
line = readLine(fd);
pos = line.indexOf(' ');
if (pos == -1) return false;
result = line.substring(pos+1, pos+4);
if (result.equals("200"))
return true;
else
return false;
}
// filter the header of the HTTP response
private static int filterHeader(int fd)
{
String line;
while (true) {
line = readLine(fd);
if (line.equals("\r\n")) return
1;
if (line.equals("\n")) return
1;
if (line.equals("")) return -1;
}
}
// initialize the values of the variables
private static void init(String htmls[][],
String position[],
double freqs[][],
long seeds[])
{
int i, j;
for (i=0; i<MAXPOS; i++) {
for (j=0; j<MAXOPT; j++) {
htmls[i][j] = new
String("");
}
}
for (i=0; i<MAXPOS; i++) {
position[i] = new String("");
}
for (i=0; i<MAXPOS; i++) {
for (j=0; j<MAXOPT; j++) {
freqs[i][j] = 0.0;
}
}
for (i=0; i<MAXPOS; i++) {
seeds[i] = 0;
}
}
// read the ads.obj object, which contains
the
// positions, rotation banners, probabilities
// general format of the object is:
// position 1
// probability_1
roataion_banner_1
// probability_2
rotation_banner_2
// ... ...
// probability_n
rotation_banner_n
// position_2
// ... ...
// position_n
private static int readAdsObj(String position[],
String htmls[][],
double freqs[][])
{
int fd;
// open the object
from the ActiveCache
fd = open("ads.obj", 0);
if (fd == -1) return -1;
int i, j;
String line, doubleStr, htmlStr;
i = -1; j = 0;
while (true) {
// read
one line from the object
line = readLine(fd);
// if
nothing left to read, exit
if (line.equals("")) break;
if (line.startsWith("Position
")) {
// if this line specifies one position, record the position
i++; j=0;
position[i] = new
String(line.substring(0, line.length()-1));
} else {
// the file should begin with Position line
if (i < 0) {
close(fd);
return
-1;
}
int pos;
// this line should specify a pair of probability
// and rotation_banner separated by spaces
// read till a space, this should be a probabilities
for (pos=0; (pos<line.length())
&& (line.charAt(pos)!=' ')
&& (line.charAt(pos)!='\t'); pos++);
// if the line has no space, illegal format, ignore it
if (pos >= line.length())
continue;
// get the value of the probability, save it in freqs[i][j]
doubleStr = line.substring(0,
pos);
freqs[i][j] = Double.valueOf(doubleStr).doubleValue();
// read until a non-space character, where the rotation banner starts
for (; (pos<line.length())
&& ((line.charAt(pos)==' ')
|| (line.charAt(pos)=='\t')); pos++);
// illegal format, ignore it
if (pos >= line.length())
continue;
// record the rotation banner in htmls[i][j]
htmls[i][j] = line.substring(pos);
j++;
}
}
close(fd);
return 0;
}
// read the seed object from ActiveCache,
if it is the
// first invocation of applet, the
seed object does not
// exist yet, we use zeros for seed
in this case
private static void readSeed(long seeds[])
{
boolean inCache;
int fd;
String line;
inCache = is_in_cache("seed");
// the seed object
not in ActiveCache yet, ignore
// it, we just use
zeros as seeds
if (!inCache) return;
else {
int i;
// open
the seed object for reading
// each
line of the seed object is just a value
fd = open("seed", 0);
if (fd == -1) return;
for (i=0; i<MAXPOS; i++) {
int start;
// read one line, if no line left, exit
line = readLine(fd);
if (line.equals(""))
break;
start = 0;
// read the value in this line, into seeds[i]
while (Character.isDigit(line.charAt(start)))
start
++;
seeds[i] = Long.valueOf(line.substring(0,
start)).longValue();
}
}
}
// check whether this line contains
a start pattern
// which is like <!--Begin Rotate
Banner position i -->
// if true, return the position string,
otherwise return
// empty string
private static String checkBeginBanner(String line)
{
int pos1, pos2, pos3;
pos1 = line.indexOf("<!--");
pos2 = line.indexOf("Begin Rotate Banner");
pos3 = line.indexOf("-->");
if ((pos1==-1) || (pos2==-1) || (pos3==-1))
return new String("");
if ((pos1<pos2) && (pos2<pos3))
{
int start, end;
start = pos2+19; end = pos3;
while (!Character.isLetterOrDigit(line.charAt(start)))
start ++;
while (!Character.isLetterOrDigit(line.charAt(end)))
end --;
return line.substring(start,
end+1);
} else {
return new String("");
}
}
// check whether this line contains
an end pattern,
// which is like: <!-- End Rotate
Banner position i -->
private static boolean checkEndBanner(String line)
{
int pos1, pos2, pos3;
pos1 = line.indexOf("<!--");
int pos1, pos2, pos3;
pos1 = line.indexOf("<!--");
pos2 = line.indexOf("End Rotate Banner");
pos3 = line.indexOf("-->");
if ((pos1==-1) || (pos2==-1) || (pos3==-1))
return false;
if ((pos1<pos2) && (pos2<pos3))
{
return true;
} else {
return false;
}
}
// check whether a position specified
in the document has been
// specified in the ads.obj object.
The specified positions
// of ads.obj are in position[], PosStr
is a position found
// in the html document
private static int findPosition(String position[], String PosStr)
{
int i;
for (i=0; i<MAXPOS; i++) {
if (position[i] == null) continue;
if (PosStr.equals(position[i]))
return i;
}
return -1;
}
// make a choice based on the probabilities
and seed for one position
// freqs[] is the probabilities of
rotation banners of one position
// seed is the seed for this position
private static int makeChoice(double freqs[], long seed)
{
int i;
double randNum, total;
Random rand = new Random(seed);
// generate a random
number
randNum = rand.nextDouble();
total = 0;
// see the number
fall into which rotation banner
// and make a choice
for (i=0; i<MAXOPT; i++) {
total += freqs[i];
if (total > randNum) {
return i;
}
}
return 0;
}
// the seed for the position is changed
private static void changeSeed(long seeds[], int pos)
{
seeds[pos] += 10000;
}
// write the seeds into seed object,
if this is the
// first invocation of applet, we need
to create the seed
// object now
private static void writeSeed(long seeds[])
{
boolean inCache;
int i, fd;
byte buf[];
inCache = is_in_cache("seed");
if (inCache) {
fd = open("seed", 2);
} else {
fd = create("seed", 00700);
}
if (fd == -1) {
return;
}
for (i=0; i<MAXPOS; i++) {
buf = Convert(Long.toString(seeds[i]));
write(fd, buf, buf.length);
}
close(fd);
}
// convert a String into a byte array
private static byte[] Convert(String str)
{
int i;
byte buf[] = new byte[str.length()+1];
for (i=0; i<str.length(); i++) {
buf[i] = (byte)(str.charAt(i));
}
buf[i] = 10;
return buf;
}
// read one line from the file, fd is
the file descriptor
private static String readLine(int fd)
{
StringBuffer strbuf = new StringBuffer(0);
byte buf[] = new byte[1];
while (read(fd, buf, 1)==1) {
strbuf.append((char)buf[0]);
if (buf[0] == '\n') break;
}
return new String(strbuf);
}
}