In this lab, you will be working for the first time with networking and with threads. Both of these can get very difficult, but for your first experience with them, you'll be looking just at some basic techniques. In fact, because of the test on Friday, this lab is meant to be easier than average.
You will need the files from the directory /classes/f07/cs225/files_for_lab_9. You can begin by creating an Eclipse project and adding the files from that directory to your project.
This lab will be due next Wednesday, November 7. And don't forget that last weeks's lab is due on October 31.
You will be working only in the file Images.java. The work that you do will depend on the file ThreadedImageCrawler.java, but you will not modify that file. The other two files are not really part of the project, but they contain some code that you might want to look at. ThreadedCrawl.java is a simple main program that tests ThreadImageCrawler. The other file, GetURL.java can download files from the Web.
The Images class includes a main program that opens a blank window. You will want to add images to that window. The class contains two methods for adding a BufferedImage to the display in the window. Recall that a BufferedImage is just an image stored in the computer's memory.
Now, Java has an easy method (ImageIO.read(stream)) for reading a BufferedImage from an InputStream. And it is fairly easy to obtain an InputStream for reading data from an Internet Web address. You can combine these to download an image from a given Web address. In fact, the sample program GetURL already does this. In that sample program, the image is saved to a file. You can use the same techniques as GetURL to get a BufferedImage from the Web, but once you have the image you should add it to the window instead of saving it to a file.
Write a method in the Images class that will try to read a BufferedImage from a specified URL. The URL should be passed as a parameter. If the image is read successfully, then it should be added to the window by calling one of the two addImage() methods. Place the image at a random point in the window. It would be nice to draw the image at a smaller size if it is too big.
Test your method by calling it in the constructor of the class. For the parameter, use a known image URL such as new URL("http://math.hws.edu/eck/InnocentEye.gif"). You can remove this test once you know your download method is working.
Next, you will create a Thread that runs in a loop where it gets an image from the Web, adds that image to the image, and repeats this over and over as long as the window is open.
As a source of image URLs, your program should use an object of type ThreadedImageCrawler. An object of type ThreadedImageCrawler is designed to "crawl" the web and look for URLs of images. Behind the scenes, it uses multiple threads to do the crawling, but you don't have to worry about that. It keeps a queue of the image URLs that it finds and it has a method that you can call to get the next image from the queue. To use a ThreadedImageCrawler, you just have to create the object and give it a starting URL where it can begin its search. The methods that you need are:
To implement web-crawling in your program, you should add a variable of type ThreadedImageCrawler to the Images class. In the Images constructor, you can create the ThreadedImageCrawler object and give it a starting URL. Use, for example, new URL("http://math.hws.edu/").
Next, you want to create the image-downloading thread. Write a subclass of the Thread class, with a run() method that repeatedly gets a URL from the ThreadedImageCrawler and tries to download and display it (using the method that you wrote in the first part of the lab). Add a delay of, say 4000 milliseconds between images using the Thread.sleep() method.
In the Images constructor, you can create an object belonging to the thread class that you have written and call its start() method to get it running. If your program is working (and if you use a good start URL), a new image will be added to the window every few seconds.
If you want to improve your project, here are some ideas. The URLConnection class has a method getContentLength() that, like getContentType(), can be called after calling getInputStream(). It returns the number of bytes of data that the server will send over the input stream, if that number is known. The number of bytes is not always known in advance; if it is not known, then the return value of getContentLength() is -1. You might want to check this value before downloading the image, in order to avoid downloading very large images (say, larger than a megabyte). You might also want to avoid very small images (say, smaller than a kilobyte), since they are unlikely to contain interesting images.
As another idea, instead of using the method getNextImageURL() to retrieve images from the ThreadedImageCrawler, use getNextImageURLIfAvailable(). Using the latter method will prevent your thread from blocking indefinitely. Furthermore, if you fail to find an image in several attempts, it's likely that the crawler has permanently run out of images. In that case, you might want to put up a message to the user or end the program.
You could put up a dialog box when the program starts where the user can enter the start URL. For this, you could use the JOptionPane.showInputDialogBox() method.
If you wanted to be very ambitious, you could replace the simple thread that downloads images with a thread pool that has several threads that do image downloading. These thread could put the images that they download into a short queue of type ArrayBlockingQueue<BufferedImage>, and another thread could remove images from that queue and add them to the display. The purpose would be the buffering, which would make it likely that an image is always available when the image-drawing thread wants to draw one. Without this buffering, the image-drawing also does the downloading, and this can take an indefinite amount of time that can make the timing of the image displays less regular.