290 likes | 301 Views
OLFS Extensions. Writing a Custom DispatchHandler. Extending the OLFS. Extension ‘modules’ written in Java Jar files added to a directory within Tomcat and called out in the olfs.xml file. The new modules have complete access to the request information Both HTTP GET and POST requests
E N D
OLFS Extensions Writing a Custom DispatchHandler
Extending the OLFS • Extension ‘modules’ written in Java • Jar files added to a directory within Tomcat and called out in the olfs.xml file. • The new modules have complete access to the request information • Both HTTP GET and POST requests • There is some significant processing done before the handler is called: • Conditional GET Requests (Handler is called on to provide last modified dates) • Authorization & Authentication
The OLFS uses an ordered list of Dispatch Handlers to handle requests. • Each handler on the list is asked if it can handle the incoming request. • The first handler on the list that claims the request gets to handle it. • List order is important, as some handlers (for example THREDDS) may claim to handle requests that could (should) be handled by a different handler. • Handlers are free to do anything they need to handle a request: Contact a remote system/process, read files, spawn threads, et cetera. OLFS Dispatch Handlers
DispatchHandler Interface Dispatch Handlers must implement the DispatchHandler interface: public interface DispatchHandler { public void init(DispatchServlet servlet, Element config) throws Exception; public boolean requestCanBeHandled(HttpServletRequest request) throws Exception; public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; public long getLastModified(HttpServletRequest req); public void destroy(); }
Dispatch Handler Interface:init() method Declaration: public void init(DispatchServlet servlet, Element config) throws Exception; Parameters: servlet: This will be the DispatchServlet that creates the instance of DispatchHandler that is being initialized. DispatchServlet is a child of HttpServlet. config: A JDOM Element object containing the XML Element that announced which implementation of DispatchHandler to use. It may (or may not) contain additional confguration information. Exceptions: Throws an Exception when the bad things happen.
Dispatch Handler Interface:requestCanBeHandled() method Declaration: public boolean requestCanBeHandled(HttpServletRequest request) throws Exception; Parameters: request: The request to be handled. Return: True if the DispatchHandler can service the request, false otherwise. Exceptions: Throws an Exception when the bad things happen.
Dispatch Handler Interface:handleRequest() method public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; Parameters: request: The request to be handled. response: The response object thru which the response information will placed/written. Exceptions: Throws an Exception when the bad things happen.
Dispatch Handler Interface:getLastModified() method Declaration: public long getLastModified(HttpServletRequest request); Parameters: request: The request for which we need to get a last modified date. Return: The last modified date of the URI referenced in the request. If the date cannot be determined then return -1. Exceptions: May not throw an Exception.
Dispatch Handler Interface:destroy() method Declaration: public void destroy(); Parameters: None Return: None. Exceptions: May not throw an Exception.
requestCanBeHandled() method: public boolean requestCanBeHandled(HttpServletRequest request) throws Exception{ String sName = ReqInfo.getFullSourceName(request); return sName.startsWith("/helloWorld"); } This simple test will cause our example DispatchHandler to claim all requests that begin with “/helloWorld”
handleRequest() method: public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception{ response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_OK); String msg = "<html><body><br><br><br><br>"; msg += "<center><h1>HELLO WORLD!</h1></center>"; msg += "</body></html>"; response.getWriter().print(msg); } Provides a simple “Hello World” response.
getLastModified() method: public long getLastModified(HttpServletRequest request) { return -1; } Returning a negative one will cause the page to always reload.
Installing your Handler • Edit the olfs.xml file in $CATALINA_HOME/content/opendap • Add your new DispatchHandler implementation to the list of handlers by inserting XML element: <Handler className="bom.tutorial.ExampleDispatchHandler" />Immediately after the BESManager handler. • Restart Tomcat.
Testing your Handler • Point your browser at: http://localhost:8080/opendap/helloWorld
Experiment • Edit the olfs.xml file in $CATALINA_HOME/content/opendap • Move the element that defines your handler to the end of the handler list and restart Tomcat. • Try other permutations of the Handler list (be sure to restart Tomcat after each change). This will probably break Hyrax :)
FileService:init() method public void init(DispatchServlet s, Element config) throws Exception { if(initialized) return; String dir; Element dv = config.getChild("TopDir"); if(dv!=null){ dir = dv.getTextTrim(); if(dir!=null) { File f = new File(dir); if (f.exists() && f.isDirectory()) fileRoot = dir; else fileRoot = s.getServletContext().getRealPath("docs"); } } while(fileRoot.endsWith("/")) fileRoot = fileRoot.substring(0,fileRoot.length()-1); log.info("fileRoot: " + fileRoot); initialized = true; }
FileService:init() method public void init(DispatchServlet s, Element config) throws Exception { if(initialized) return; String dir; Element dv = config.getChild("TopDir"); if(dv!=null){ dir = dv.getTextTrim(); if(dir!=null) { File f = new File(dir); if (f.exists() && f.isDirectory()) fileRoot = dir; else fileRoot = s.getServletContext().getRealPath("docs"); } } while(fileRoot.endsWith("/")) fileRoot = fileRoot.substring(0,fileRoot.length()-1); log.info("fileRoot: " + fileRoot); initialized = true; }
FileService: requestCanBeHandled() and handleRequest() methods public boolean requestCanBeHandled(HttpServletRequest request) throws Exception{ return fileService(request,null,false); } public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception{ fileService(request,response,true); } Both of these methods call on the fileService() method to perform both the handling evaluation and the response evaluation.
FileService: fileService() method private boolean fileService(HttpServletRequest request, HttpServletResponse response, boolean sendResponse) throws Exception{ String path = getPath(request); boolean isFileRequest = false; if(path!=null){ isFileRequest = true; if(sendResponse){ File file = new File(path); if(file.exists()){ if(file.isDirectory()) sendDirPage(file,request, response); else if(file.isFile()) sendFile(file,response); else sendFileNotFound(response); } else { sendFileNotFound(response); } } } return isFileRequest; }
FileService: getPath() method private String getPath(HttpServletRequest req){ String sName = ReqInfo.getFullSourceName(req); String path = null; if(sName.startsWith(urlPrefix)){ path = sName.substring(urlPrefix.length(),sName.length()); if( ! path.startsWith("/")) path = "/" + path; path = fileRoot + path; } return path; }
FileService: getLastModifed() method public long getLastModified(HttpServletRequest req){ String path = getPath(req); if(path!=null){ File file = new File(path); if(file.exists()) return file.lastModified(); } return -1; } • Utilizes the getPath() method. Ignores a bad return (that will be handled later with a 404 page). • Interacts directly with the file system to ascertain the last modified date of the file/directory.
Installing your Handler • Edit the olfs.xml file in $CATALINA_HOME/content/opendap • Add your new DispatchHandler implementation to the list of handlers by inserting XML element: <Handler className="bom.tutorial.FileService> <TopDir>/path/of/dir/to/access</TopDir> </Handler>Immediately after the BESManager handler. • Restart Tomcat.
FileDispatchHandler:A Hyrax DispatchHandler. • Hyrax will serve files that it does not recognize as data. • It is also possible to configure Hyrax to allow users to directly download the source data files.
FileDispatchHandler:init() method public void init(DispatchServlet servlet,Element config) throwsException { if(initialized) return; Element dv = config.getChild("AllowDirectDataSourceAccess"); if(dv!=null){ allowDirectDataSourceAccess = true; } log.info("Intialized. Direct Data Source Access: ” + (allowDirectDataSourceAccess?"Enabled":"Disabled") ); initialized = true; }
FileDispatchHandler:requestCanBeHandled() and handleRequest() methods public boolean requestCanBeHandled(HttpServletRequest request) throws Exception { return fileDispatch(request, null, false); } public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { if(!fileDispatch(request, response, true)) log.debug("FileDispatch request failed inexplicably!"); } public boolean fileDispatch(HttpServletRequest request, HttpServletResponse response, boolean sendResponse) throws Exception;
FileDispatchHandler:fileDispatch() method public boolean fileDispatch(HttpServletRequest request, HttpServletResponse response, boolean sendResponse) throws Exception { DataSourceInfo dsi = new BESDataSource(ReqInfo.getFullSourceName(request)); boolean isFileResponse = false; if (dsi.sourceExists()) { if (!dsi.isCollection()) { isFileResponse = true; if (sendResponse) { if (!dsi.isDataset() || allowDirectDataSourceAccess) { sendFile(request, response); } else { sendDirectAccessDenied(request, response); } } } } return isFileResponse; }
Summary • DispatchHandler implementations are free to conduct business using any available tools • Sockets • JDBC • File Systems • Etc. • Care should be taken in ordering them in the olfs.xml configuration file. Improper ordering can create unintended results, including disabling of desired functionality.