diff options
author | Matt Windsor <mattwindsor@btinternet.com> | 2011-03-18 14:01:42 +0000 |
---|---|---|
committer | Matt Windsor <mattwindsor@btinternet.com> | 2011-03-18 14:01:42 +0000 |
commit | dfde3f3d62ee5de17d09195513711fd006cbf270 (patch) | |
tree | 0fb70b0f75927a03daa8ad8ddc218f6e657e6d66 | |
parent | b6831f847f93622a64f1b776bc3cf62befddab98 (diff) |
Remove duplicate files; begin rewriting server to use Apache HttpCore by using HttpCore Response resources; exception-based error handling introduced for get requests.
-rw-r--r-- | src/uk/org/ury/library/LibraryItem.java | 27 | ||||
-rw-r--r-- | src/uk/org/ury/library/LibraryItemProperty.java | 43 | ||||
-rw-r--r-- | src/uk/org/ury/library/LibraryTableModel.java | 184 | ||||
-rw-r--r-- | src/uk/org/ury/server/Server.java | 272 | ||||
-rw-r--r-- | src/uk/org/ury/server/exceptions/BadRequestException.java | 48 | ||||
-rw-r--r-- | src/uk/org/ury/server/exceptions/HandleFailureException.java | 2 | ||||
-rw-r--r-- | src/uk/org/ury/server/exceptions/HandlerNotFoundException.java | 51 | ||||
-rw-r--r-- | src/uk/org/ury/server/exceptions/HandlerSetupFailureException.java | 55 | ||||
-rw-r--r-- | src/uk/org/ury/server/exceptions/HandlingException.java | 48 | ||||
-rw-r--r-- | src/uk/org/ury/server/exceptions/NotAHandlerException.java | 34 | ||||
-rw-r--r-- | src/uk/org/ury/show/ShowItem.java | 25 | ||||
-rw-r--r-- | src/uk/org/ury/show/ShowItemProperty.java | 26 |
12 files changed, 435 insertions, 380 deletions
diff --git a/src/uk/org/ury/library/LibraryItem.java b/src/uk/org/ury/library/LibraryItem.java deleted file mode 100644 index 6156bab..0000000 --- a/src/uk/org/ury/library/LibraryItem.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * - */ -package uk.org.ury.library; - - -import java.util.Map; - -import uk.org.ury.database.DatabaseItem; -import uk.org.ury.library.LibraryItemProperty; - - -/** - * An item in the URY library. - * - * @author Matt Windsor - */ - -public class LibraryItem extends DatabaseItem<LibraryItemProperty, - String> -{ - public - LibraryItem (Map<LibraryItemProperty, String> properties) - { - super (properties); - } -}
\ No newline at end of file diff --git a/src/uk/org/ury/library/LibraryItemProperty.java b/src/uk/org/ury/library/LibraryItemProperty.java deleted file mode 100644 index 154e405..0000000 --- a/src/uk/org/ury/library/LibraryItemProperty.java +++ /dev/null @@ -1,43 +0,0 @@ -package uk.org.ury.library; - -/** - * The parameters that are stored in the LibraryItem. - * - * @author Matt Windsor - */ - -public enum LibraryItemProperty - { - // Constant SQL identifier - TITLE ("title"), - ALBUM ("album"), - ARTIST ("artist"), - LABEL ("label"), - STATUS ("status"), - MEDIUM ("medium"), - FORMAT ("format"), - DATE_RELEASED ("datereleased"), - DATE_ADDED ("dateadded"), - DATE_EDITED ("dateedited"), - SHELF_LETTER ("shelfletter"), - SHELF_NUMBER ("shelfnumber"), - CD_ID ("cdid"), - ADD_MEMBER_ID ("memberid_add"), - EDIT_MEMBER_ID ("memberid_lastedit"), - ADD_FORENAME ("fnameadd"), - ADD_SURNAME ("snameadd"), - EDIT_FORENAME ("fnameedit"), - EDIT_SURNAME ("snameedit"), - IS_DIGITISED ("digitised"), - IS_CLEAN ("clean"); - - - public final String sql; - - - private - LibraryItemProperty (String sql) - { - this.sql = sql; - } - };
\ No newline at end of file diff --git a/src/uk/org/ury/library/LibraryTableModel.java b/src/uk/org/ury/library/LibraryTableModel.java deleted file mode 100644 index f380274..0000000 --- a/src/uk/org/ury/library/LibraryTableModel.java +++ /dev/null @@ -1,184 +0,0 @@ -/** - * - */ -package uk.org.ury.library; - -import java.util.List; - -import javax.swing.table.AbstractTableModel; - -import uk.org.ury.database.exceptions.MissingPropertyException; -import uk.org.ury.library.LibraryItemProperty; - - -/** - * A table model for the library viewer. - * - * @author Matt Windsor - */ - -public class LibraryTableModel extends AbstractTableModel -{ - - /** - * - */ - - private static final long serialVersionUID = -1744980619128903509L; - - private List<LibraryItem> data; - - - /** - * Construct a new table model. - * - * @param data The list of data on which the model will be based. - */ - - public - LibraryTableModel (List<LibraryItem> data) - { - this.data = data; - } - - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#getColumnCount() - */ - - @Override - public int - getColumnCount () - { - return 6; - } - - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#getRowCount() - */ - - @Override - public int - getRowCount () - { - return data.size (); - } - - - /** - * @param c The column whose class should be investigated. - * - * @return the column class of column c. - */ - - @Override - public Class<?> - getColumnClass (int c) - { - return getValueAt (0, c).getClass (); - } - - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#getValueAt(int, int) - */ - - @Override - public Object getValueAt (int rowIndex, int columnIndex) - { - LibraryItem li = data.get (rowIndex); - - try - { - switch (columnIndex) - { - case 0: // Title - return li.get (LibraryItemProperty.TITLE); - - case 1: // Artist - return li.get (LibraryItemProperty.ARTIST); - - case 2: // Album - return li.get (LibraryItemProperty.ALBUM); - - case 3: // Medium - - // TODO: Make this less kludge-y - - String mediumString = li.get (LibraryItemProperty.MEDIUM); - - if (mediumString.equals ("c")) - return "Compact Disc"; - else if (mediumString.equals ("7")) - return "7\" Vinyl"; - else if (mediumString.equals ("2")) - return "12\" Vinyl"; - else - return "Unrecognised"; - - case 4: // Clean? - - // Return true if marked true, false if marked false or unknown etc. - - String cleanString = li.get (LibraryItemProperty.IS_CLEAN); - - // TODO: Nicer way of showing this - - if (cleanString.equals ("y")) - return "Yes"; - else if (cleanString.equals ("n")) - return "No"; - else - return "???"; - - case 5: // isDigitised - - // Return true if marked true, false if marked false or unknown etc. - - String digitisedString = li.get (LibraryItemProperty.IS_DIGITISED); - - if (digitisedString.equals ("t")) - return true; - else - return false; - - default: - return ""; - } - } - catch (MissingPropertyException e) - { - return "Unknown"; - } - } - - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#getColumnName(int, int) - */ - - @Override - public String - getColumnName (int index) - { - switch (index) - { - case 0: - return "Title"; - case 1: - return "Artist"; - case 2: - return "Album"; - case 3: - return "Medium"; - case 4: - return "Clean?"; - case 5: - return "On system?"; - - default: - return "ERROR"; - } - } -} diff --git a/src/uk/org/ury/server/Server.java b/src/uk/org/ury/server/Server.java index 8a25916..6ac192c 100644 --- a/src/uk/org/ury/server/Server.java +++ b/src/uk/org/ury/server/Server.java @@ -20,12 +20,29 @@ import java.util.List; import java.util.HashMap; import java.util.Map; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.HttpVersion; +import org.apache.http.ParseException; +import org.apache.http.entity.BasicHttpEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.message.BasicHttpResponse; +import org.apache.http.protocol.HTTP; +import org.apache.http.util.EntityUtils; + import uk.org.ury.config.ConfigReader; import uk.org.ury.database.DatabaseDriver; import uk.org.ury.database.UserClass; import uk.org.ury.database.exceptions.ConnectionFailureException; import uk.org.ury.database.exceptions.MissingCredentialsException; +import uk.org.ury.server.exceptions.BadRequestException; import uk.org.ury.server.exceptions.HandleFailureException; +import uk.org.ury.server.exceptions.HandlerNotFoundException; +import uk.org.ury.server.exceptions.HandlerSetupFailureException; +import uk.org.ury.server.exceptions.HandlingException; +import uk.org.ury.server.exceptions.NotAHandlerException; /** * The unified URY server, accepting requests over HTTP. @@ -168,29 +185,104 @@ public class Server public void processBuffer (List<String> buffer, PrintWriter out) - { + { String requestStart = buffer.get (0); System.out.println (requestStart); + HttpResponse response; + if (requestStart.startsWith ("GET")) { System.out.println ("That was a GET..."); - handleGet (buffer, out); + try + { + response = handleGet (buffer); + } + catch (HandlerNotFoundException e) + { + // TODO: log + response = serveError (HttpStatus.SC_NOT_FOUND, + e.getMessage ()); + } + catch (BadRequestException e) + { + // TODO: log + response = serveError (HttpStatus.SC_BAD_REQUEST, + e.getMessage ()); + } + catch (HandlingException e) + { + response = serveError (HttpStatus.SC_INTERNAL_SERVER_ERROR, + e.getMessage ()); + } } else { System.out.println ("Uh-oh! I don't know what to do!"); - - out.println (HTTP_VERSION + " 501 Not Implemented"); - out.println ("Connection: close"); - out.print ("\r\n"); + response = serveError (HttpStatus.SC_NOT_IMPLEMENTED, + "Feature not implemented yet."); + } + + + // Now send the response. + + for (Header h : response.getAllHeaders ()) + { + out.println (h); + } + + try + { + out.print (EntityUtils.toString (response.getEntity ())); + } + catch (ParseException e) + { + // TODO Auto-generated catch block + e.printStackTrace (); + } + catch (IOException e) + { + // TODO Auto-generated catch block + e.printStackTrace (); } } - public void - handleGet (List<String> buffer, PrintWriter out) + + /** + * Handle a HTTP GET request. + * + * @param buffer The HTTP request as a list of strings. + * + * @return The HTTP response. + * + * @throws HandlerNotFoundException if the client requested + * a request handler that could not be found on the + * class path. + * + * @throws HandlerSetupFailureException if the handler was + * found but could not be set up (eg does not + * implement appropriate interface or cannot be + * instantiated). + * + * @throws HandleFailureException if an appropriate handler + * was contacted, but it failed to process the + * request. + * + * @throws BadRequestException if the request was malformed + * or invalid. + * + * @throws NotAHandlerException if the class requested to + * handle the request is not a handler. + */ + + public HttpResponse + handleGet (List<String> buffer) + throws HandlerNotFoundException, HandlerSetupFailureException, + HandleFailureException, BadRequestException, NotAHandlerException { + HttpResponse response = null; + String[] getsplit = buffer.get (0).split (" "); String path = getsplit[1]; @@ -200,11 +292,22 @@ public class Server // Someone's trying to get the index page! // Humour them. - out.println (HTTP_VERSION + " 200 OK"); - out.println ("Connection: close"); - out.print ("\r\n"); + response = new BasicHttpResponse (HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, + "OK"); - out.println (DOCTYPE + INDEX_HTML); + StringEntity entity = null; + + try + { + entity = new StringEntity (DOCTYPE + INDEX_HTML); + } + catch (UnsupportedEncodingException e) + { + throw new HandlerSetupFailureException ("(Index page)", e); + } + + response.setEntity (entity); } else { @@ -216,16 +319,15 @@ public class Server { pathURL = new URL ("http://localhost" + path); } - catch (MalformedURLException e1) + catch (MalformedURLException e) { - serveError (400, "Malformed URL.", out); + throw new BadRequestException (e); } - - + String className = "uk.org.ury" + pathURL.getPath ().replace ('/', '.'); System.out.println (className); Class<?> newClass = null; - + try { @@ -233,112 +335,134 @@ public class Server } catch (ClassNotFoundException e) { - serveError (404, "Class " + className + " not found.", out); - return; + throw new HandlerNotFoundException (className, e); } - if (RequestHandler.class.isAssignableFrom (newClass)) + + // Check for error (response set) here. + + if (response == null + && RequestHandler.class.isAssignableFrom (newClass)) { String queryString = pathURL.getQuery (); Map<String, String> parameters; + try { parameters = parseQueryString (queryString); } catch (UnsupportedEncodingException e) { - serveError (500, "URL decode failure for class " - + className - + " (" + e.getMessage () + ").", out); - return; + throw new HandlerSetupFailureException (className, e); } - List<String> response; - + List<String> content; + try { RequestHandler srh = ((RequestHandler) newClass.newInstance ()); - response = srh.handleGetRequest (parameters, this); + content = srh.handleGetRequest (parameters, this); } catch (InstantiationException e) { - serveError (500, "Instantiation exception for class " - + className - + " (" + e.getMessage () + ").", out); - return; + throw new HandlerSetupFailureException (className, e); } catch (IllegalAccessException e) { - serveError (500, "Illegal access exception for class " - + className - + " (" + e.getMessage () + ").", out); - return; - } - catch (HandleFailureException e) - { - serveError (500, "Failed to handle request for class " - + className - + " (" + e.getMessage () + ").", out); - return; + throw new HandlerSetupFailureException (className, e); } - // If we made it this far, the response is A-OK. - out.println (HTTP_VERSION + " 200 OK"); - out.println ("Content-Type: text/plain"); - out.print ("\r\n"); + // Everything seems OK, so make the response. - out.println ("START"); + response = new BasicHttpResponse (HttpVersion.HTTP_1_1, + HttpStatus.SC_OK, + "OK"); + + String entityString = ""; + + entityString += "START" + "\r\n"; - for (String line : response) - out.println (line); + for (String line : content) + entityString += line + "\r\n"; - out.println ("END"); - - out.flush (); + entityString += "END"; + + + StringEntity entity = null; + + try + { + entity = new StringEntity (entityString); + } + catch (UnsupportedEncodingException e) + { + throw new HandlerSetupFailureException (className, e); + } + + entity.setContentType (HTTP.PLAIN_TEXT_TYPE); + response.setEntity (entity); } else - { - serveError (404, "Class " + className + " does not handle requests.", out); - return; - } + throw new NotAHandlerException (className); } + + return response; } /** - * Serve a HTTP plain-text error. + * Serve a HTTP plain-text error as a HTTP response. * * @param code HTTP status code to use. * @param reason The reason to display to the client. - * @param out The output stream. + * + * @return the HTTP response for the error. */ - private void - serveError (int code, String reason, PrintWriter out) - { - String errorStatus = ""; + private HttpResponse + serveError (int code, String reason) + { + // Get the reason string to put in the error response. + // TODO: standards? + + String statusReason = ""; switch (code) { - case 400: - errorStatus = "400 Bad Request"; + case HttpStatus.SC_BAD_REQUEST: + statusReason = "Bad Request"; break; - case 404: - errorStatus = "404 Not Found"; + case HttpStatus.SC_NOT_FOUND: + statusReason = "Not Found"; break; default: - errorStatus = "500 Internal Server Error"; + case HttpStatus.SC_INTERNAL_SERVER_ERROR: + statusReason = "Internal Server Error"; break; } - out.println (HTTP_VERSION + " " + errorStatus); - out.println ("Content-Type: text/plain"); - out.println ("Connection: close"); - out.print ("\r\n"); - - out.println ("ERROR: " + reason); - out.flush (); + HttpResponse response = new BasicHttpResponse (HttpVersion.HTTP_1_1, + code, statusReason); + StringEntity entity = null; + + try + { + entity = new StringEntity ("ERROR: " + reason); + } + catch (UnsupportedEncodingException e) + { + // TODO Auto-generated catch block + e.printStackTrace (); + } + + if (entity != null) + { + entity.setContentType (HTTP.PLAIN_TEXT_TYPE); + response.setEntity (entity); + } + + return response; } diff --git a/src/uk/org/ury/server/exceptions/BadRequestException.java b/src/uk/org/ury/server/exceptions/BadRequestException.java new file mode 100644 index 0000000..61aa951 --- /dev/null +++ b/src/uk/org/ury/server/exceptions/BadRequestException.java @@ -0,0 +1,48 @@ +/** + * + */ +package uk.org.ury.server.exceptions; + +/** + * Exception thrown when the server meets a malformed request, or + * part of one. + * + * @author Matt Windsor + */ + +public class BadRequestException extends HandlingException +{ + + /** + * TODO: Change this! ---v + */ + + private static final long serialVersionUID = -397479334359858162L; + + + /** + * Construct a new BadRequestException with a default reason. + */ + + public + BadRequestException () + { + super ("Bad request."); + } + + + /** + * Construct a new HandlerNotFoundException with a chained + * exception. + * + * @param cause The exception that this new exception is to + * wrap. + */ + + public + BadRequestException (Throwable cause) + { + super ("Bad request. (" + + cause.getMessage () + ")", cause); + } +} diff --git a/src/uk/org/ury/server/exceptions/HandleFailureException.java b/src/uk/org/ury/server/exceptions/HandleFailureException.java index 063cc52..ddcfdea 100644 --- a/src/uk/org/ury/server/exceptions/HandleFailureException.java +++ b/src/uk/org/ury/server/exceptions/HandleFailureException.java @@ -10,7 +10,7 @@ package uk.org.ury.server.exceptions; * @author Matt Windsor */ -public class HandleFailureException extends Exception +public class HandleFailureException extends HandlingException { /** diff --git a/src/uk/org/ury/server/exceptions/HandlerNotFoundException.java b/src/uk/org/ury/server/exceptions/HandlerNotFoundException.java new file mode 100644 index 0000000..7b614f6 --- /dev/null +++ b/src/uk/org/ury/server/exceptions/HandlerNotFoundException.java @@ -0,0 +1,51 @@ +/** + * + */ +package uk.org.ury.server.exceptions; + +/** + * Exception thrown when the server request handler requested + * by the client is not * found in the class space. + * + * @author Matt Windsor + */ + +public class HandlerNotFoundException extends HandlingException +{ + + /** + * TODO: Change this! ---v + */ + + private static final long serialVersionUID = -397479334359858162L; + + + /** + * Construct a new HandlerNotFoundException with a + * default reason. + */ + + public + HandlerNotFoundException () + { + super ("Handler not found."); + } + + + /** + * Construct a new HandlerNotFoundException with a class name and + * chained exception. + * + * @param className The name of the missing handler class. + * + * @param cause The exception that this new exception is to + * wrap. + */ + + public + HandlerNotFoundException (String className, Throwable cause) + { + super ("Handler " + className + " not found. (" + + cause.getMessage () + ")", cause); + } +} diff --git a/src/uk/org/ury/server/exceptions/HandlerSetupFailureException.java b/src/uk/org/ury/server/exceptions/HandlerSetupFailureException.java new file mode 100644 index 0000000..d301eac --- /dev/null +++ b/src/uk/org/ury/server/exceptions/HandlerSetupFailureException.java @@ -0,0 +1,55 @@ +/** + * + */ +package uk.org.ury.server.exceptions; + +/** + * Exception thrown when the server request handler requested + * by the client cannot be set up to process the request. + * + * @author Matt Windsor + */ + +public class HandlerSetupFailureException extends HandlingException +{ + + /** + * TODO: Change this! ---v + */ + + private static final long serialVersionUID = -397479334359858162L; + + + /** + * Construct a new HandlerNotFoundException with a + * default reason. + */ + + public + HandlerSetupFailureException () + { + super ("Handler setup failed."); + } + + + /** + * Construct a new HandlerSetupFailureException with a class name + * and chained exception. + * + * Use this to hide exception specifics from higher abstraction + * layers. + * + * @param className The name of the failed handler class. + * + * @param cause The exception that this new exception is to + * wrap. + */ + + public + HandlerSetupFailureException (String className, + Throwable cause) + { + super ("Setup for handler " + className + " failed (reason: " + + cause.getMessage () + ").", cause); + } +} diff --git a/src/uk/org/ury/server/exceptions/HandlingException.java b/src/uk/org/ury/server/exceptions/HandlingException.java new file mode 100644 index 0000000..2ce681b --- /dev/null +++ b/src/uk/org/ury/server/exceptions/HandlingException.java @@ -0,0 +1,48 @@ +/** + * + */ +package uk.org.ury.server.exceptions; + +/** + * Generic exception thrown when the server cannot handle a request. + * + * @author Matt Windsor + */ + +public class HandlingException extends Exception +{ + /** + * TODO: Change this! ---v + */ + + private static final long serialVersionUID = -397479334359858162L; + + + /** + * Construct a HandlingException with a reason. + * + * @param string The reason to present. + */ + + public + HandlingException (String string) + { + super (string); + } + + + /** + * Construct a HandlingException with a reason and a cause to + * chain. + * + * @param string The reason to present. + * + * @param cause The thrown cause that this exception should wrap. + */ + + public + HandlingException (String string, Throwable cause) + { + super (string, cause); + } +} diff --git a/src/uk/org/ury/server/exceptions/NotAHandlerException.java b/src/uk/org/ury/server/exceptions/NotAHandlerException.java new file mode 100644 index 0000000..9a67d62 --- /dev/null +++ b/src/uk/org/ury/server/exceptions/NotAHandlerException.java @@ -0,0 +1,34 @@ +/** + * + */ +package uk.org.ury.server.exceptions; + +/** + * Exception thrown if the class requested as a handler by the client + * is, in fact, not a handler (it does not implement RequestHandler). + * + * @author Matt Windsor + */ + +public class NotAHandlerException extends HandlingException +{ + /** + * + */ + private static final long serialVersionUID = -7268289187311868036L; + + /** + * Construct a NotAHandlerException with the name of the class that + * is not a handler. + * + * @param className The name of the offending class. + */ + + public + NotAHandlerException (String className) + { + super ("Class " + className + " is not a request handler."); + // TODO Auto-generated constructor stub + } + +} diff --git a/src/uk/org/ury/show/ShowItem.java b/src/uk/org/ury/show/ShowItem.java deleted file mode 100644 index be65c80..0000000 --- a/src/uk/org/ury/show/ShowItem.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * - */ -package uk.org.ury.show; - - -import java.util.Map; - -import uk.org.ury.database.DatabaseItem; - - -/** - * An item in the show database. - * - * @author Matt Windsor - */ - -public class ShowItem extends DatabaseItem<ShowItemProperty, String> -{ - public - ShowItem (Map<ShowItemProperty, String> properties) - { - super (properties); - } -} diff --git a/src/uk/org/ury/show/ShowItemProperty.java b/src/uk/org/ury/show/ShowItemProperty.java deleted file mode 100644 index a722a21..0000000 --- a/src/uk/org/ury/show/ShowItemProperty.java +++ /dev/null @@ -1,26 +0,0 @@ -package uk.org.ury.show; - - -/** - * Enumeration of the parameters that are stored in a ShowItem. - * - * @author Matt Windsor - */ - -public enum ShowItemProperty - { - // Constant SQL identifier - NAME1 ("name1"), - NAME2 ("name2"), - POSITION ("positionid"); - - - public final String sql; - - - private - ShowItemProperty (String sql) - { - this.sql = sql; - } - };
\ No newline at end of file |