1 #!/usr/bin/env python 2 3 """ 4 Webware adapter. 5 6 Copyright (C) 2004, 2005, 2006 Paul Boddie <paul@boddie.org.uk> 7 8 This library is free software; you can redistribute it and/or 9 modify it under the terms of the GNU Lesser General Public 10 License as published by the Free Software Foundation; either 11 version 2.1 of the License, or (at your option) any later version. 12 13 This library is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 Lesser General Public License for more details. 17 18 You should have received a copy of the GNU Lesser General Public 19 License along with this library; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 21 """ 22 23 import WebStack.Webware 24 from WebStack.Generic import EndOfResponse 25 26 # For Webware releases later than 0.8.1, employ special URLParsers in contexts 27 # for each application in the application server; such parsers create servlets 28 # instead of having servlet factories do that work. 29 30 try: 31 from WebKit.URLParser import URLParser 32 33 except ImportError: 34 35 # NOTE: Using Webware 0.8.1 or earlier. Assume that this really is the case. 36 37 pass 38 39 else: 40 class WebStackURLParser(URLParser): 41 42 """ 43 A custom URL parser which provides access to application-specific resources. 44 Override the 'parse' method for more precise control of servlet 45 instantiation. 46 """ 47 48 def __init__(self, resource, authenticator=None, handle_errors=1): 49 50 """ 51 Initialise the parser object with the given root application-specific 52 'resource' and optional 'authenticator'. The optional 'handle_errors' 53 parameter (if true) causes handlers to deal with uncaught exceptions 54 cleanly. 55 """ 56 57 self.webstack_resource = resource 58 self.webstack_authenticator = authenticator 59 self.handle_errors = handle_errors 60 61 def parse(self, trans, requestPath): 62 63 """ 64 For the given Webware transaction, 'trans', override the usual servlet 65 factory mechanism and return a servlet which will provide access to the 66 application-specific resources. 67 The 'trans' object - a Webware transaction - is not given to the servlet 68 since such information is available when the 'respond' method is invoked 69 on the servlet. 70 The provided 'requestPath' object is not used, since this information 71 should be available elsewhere. 72 """ 73 74 return WebStackServlet(self.webstack_resource, self.webstack_authenticator, 75 self.handle_errors) 76 77 # Convenience function. 78 79 def deploy(resource, authenticator=None, address=None, handle_errors=1): 80 return WebStackURLParser(resource, authenticator=authenticator, handle_errors=handle_errors) 81 82 # For Webware 0.8.1 and earlier, employ servlet factories and servlets. 83 84 from WebKit.ServletFactory import ServletFactory 85 from WebKit.Servlet import Servlet 86 87 class WebStackServletFactory(ServletFactory): 88 89 """ 90 A servlet factory object producing servlets which provide access to 91 application-specific resources. 92 """ 93 94 def __init__(self, application, resource, file_extensions, authenticator=None, handle_errors=1): 95 96 """ 97 Initialise the servlet factory with the Webware 'application' and the 98 WebStack root application-specific 'resource'. The 'file_extensions' 99 specified indicate for which files this factory is invoked. An optional 100 'authenticator' is used to control access to the resource. The optional 101 'handle_errors' parameter (if true) causes handlers to deal with 102 uncaught exceptions cleanly. 103 """ 104 105 ServletFactory.__init__(self, application) 106 self.webstack_resource = resource 107 self.file_extensions = file_extensions 108 self.webstack_authenticator = authenticator 109 self.handle_errors = handle_errors 110 111 def uniqueness(self): 112 113 """ 114 Return "file" uniqueness - probably the most appropriate response. 115 """ 116 117 return "file" 118 119 def extensions(self): 120 121 """ 122 Return the file extensions supported by this factory. 123 """ 124 125 return self.file_extensions 126 127 def servletForTransaction(self, trans): 128 129 """ 130 Return a servlet which will provide access to the application-specific 131 resources. The 'trans' object - a Webware transaction - is not given to 132 the servlet since such information is available when the 'respond' 133 method is invoked on the servlet. 134 """ 135 136 return WebStackServlet(self.webstack_resource, self.webstack_authenticator, 137 self.handle_errors) 138 139 # Servlets are common to both solutions. 140 141 class WebStackServlet(Servlet): 142 143 "A servlet which dispatches transactions to application-specific resources." 144 145 def __init__(self, resource, authenticator, handle_errors): 146 147 """ 148 Initialise the servlet with an application-specific 'resource' and 149 'authenticator'. Where 'handle_errors' is true, uncaught exceptions are 150 dealt with by the handler. 151 """ 152 153 Servlet.__init__(self) 154 self.webstack_resource = resource 155 self.webstack_authenticator = authenticator 156 self.handle_errors = handle_errors 157 158 def respond(self, trans): 159 160 """ 161 Respond to the incoming transaction, 'trans', by dispatching to the 162 application-specific resource. 163 """ 164 165 new_trans = WebStack.Webware.Transaction(trans) 166 167 try: 168 if self.webstack_authenticator is None or self.webstack_authenticator.authenticate(new_trans): 169 try: 170 self.webstack_resource.respond(new_trans) 171 except EndOfResponse: 172 pass 173 except: 174 if self.handle_errors: 175 new_trans.set_response_code(500) # Internal error 176 else: 177 raise 178 else: 179 new_trans.set_response_code(401) # Unauthorized 180 new_trans.set_header_value("WWW-Authenticate", '%s realm="%s"' % ( 181 self.webstack_authenticator.get_auth_type(), self.webstack_authenticator.get_realm())) 182 183 finally: 184 new_trans.commit() 185 186 # vim: tabstop=4 expandtab shiftwidth=4