Let me start out by saying that when grading we will never care about any output that your server writes to stderr using System.err.println or the global logger in the java.util.logging package. In particular, you won't need to worry about cleaning up after yourself, your submitted project can print as much stderr debug information as you like, so be verbose!
Also know that when grading I will ignore all html tags and whitespace/punctuation, so your output does not need to attain perfection in formatting. However, the content should be *perfect* (spelling, number formatting, etc) because what is left will all be graded automatically.
There are a lot of classes to work through on this project, here is some advice on how to approach all the work you have to do.
The basic server is really the best place to get started, in my opinion. Write a server that just listens for connections (just like in project 1). The connections will be initiated by a browser on the same machine, so if you have a server running on port 5555, you can 'talk' to it with an address like
Initially you can use the Socket.getInputStream with an InputStreamReader/BufferedReader to just print out all the information sent to you by the browser. Once you see what's going on, you can use the HttpRequest.parseRequest method to read all this information into a handy package and build a StandardHttpRequestEvent out of it to pass on to another handler.
The best place to start is with a FileHandler that only implements the HttpRequestProcessor interface and implements no commands. You'll get the most satisfaction out of this step :) Implement the process method to open the target of the HttpRequestEvent with a FileInputStream and attach it to the event with attachStream. (You should also set the "Content-Type" field to match what you are requesting, such as "text/plain", "image/gif", "text/html" etc. Voila, you should have a completely functioning file server.
You'll have to work out the usage of the Event send() methods at the end, I believe the code I gave always does the right thing(tm) on its own. Just be sure you send the response back to the client once the event is processed.
I gave you a little random.html file in the download bundle containing one image link. If your file server is working and you request random.html, the browser should immediately request the contained graphic as well. If the page loads with an image of a turtle, you're ready to move on.
You've already been given most of the shell of HttpCommandProcessor, use a TreeMap (sorting comes in handly later, you could also use a hashmap) to implement the registerCommand and associated methods. Read the online documentation for parseArgs and other methods to figure out what needs to be done. Once you have this implemented, register the HttpCommandEcho provided with
HttpCommandProcessor cp = new HttpCommandProcessor("foobar"); cp.registerCommand("echo", new HttpCommandEcho());and start up your server with this one command processor. You should get a response to:
If it doesn't work off the bat, add copious debug statements to figure out where things are going wrong. Once you can process one command, you should be able to write a couple of simple commands which only need the HttpCommandProcessor class to run:
Go back and fix your filehandler so it extends HttpCommandProcessor. This should require no change to the code, so long as you have implemented getStatus and getName correctly already.
Just a little more complicated than the previous commands, the info command will make you use the methods for reading the HttpRequest through the HttpRequestEvent interface methods using maps and iterators and such. Otherwise it is no different than the others.
Next in line will be the RemoteManager, which extends HttpRequestDispatcher so you should start here. This should be straight forward to implement, as it is no different than the dispatcher from p1. You should definately work on the 'status' command with the getStatus() method of this class (as always, see javadocs) to get some useful feedback through the browser about the configuration of the dispatcher. Attach a couple of named Dummy command processors to test the status command.
With the dispatcher status command working, the next logical commands to support are "kill" and "move", which both rely on getStatus() to report success or failure of the associated dispatcher.
We've given you the factory interface and an implementation, it should be clear how to create and use your own factories. The next command should be "start" with a limitted factory that only knows about handlers you've created so far (and possibly some additional dummy ones if you like).
That done, HttpRemoteManager is just an HttpRequestDispatcher with the "start" command registered.
This will require some studying of the java API documentation for URL , URLConnection, and HttpURLConnection, because you will have to open a connection to a remote server to get a file back. You could implement this ahead of the Dispatcher/etc. if you wanted to. The implementation isn't long- 20 to 30 lines, you'll just have to do some research to figure out how to use URLConnection. Before you ask for some hand holding, it is really essential that you learn to use other peoples code based on documentation alone. I've already pointed you at the right classes, you just need to find the methods you need.
You'll see the 'get' command is represented by a nested class in my documentation here The command, unlike the others, is not standalone and can only be instantiated by an HttpRemoteFileHandler object. This also means that the command has direct access to all the fields and methods in the RemoteFileHandler. Some of the other commands could have also been implemented this way (such as the log command).
The requirements for HttpRemoteFileHandler and HttpProxyHandler are somewhat artificial to get you to use the 'proxy pattern', so don't bother me about other ways of implementing the same functionality :) This is the way it's gotta be.
It is fairly straight forward to implement this in terms of HttpRemoteFileHandler. You can start by hardcoding a target. Then use a DummyHttpRequestEvent to modify file requests(those not prefixed with "/?") to be RemoteFileServer formatted requests that the RemoteFileServer will processes.
If you didn't initially, implement HttpCommandProxySetTarget to change the target dynamically.
You can implement this anywhere you like, for the most part it is straight forward if you've done filehandler and commands successfully. You'll see in the javadocs that for each command the HttpFileLogger has a method call to support that command, so the commands themselves (other than possibly 'get')are relatively simple.