1 #!/usr/bin/env python 2 3 """ 4 Webware adapter. 5 6 Copyright (C) 2004, 2005 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 # For Webware 0.8.1 and earlier, employ servlet factories and servlets. 78 79 from WebKit.ServletFactory import ServletFactory 80 from WebKit.Servlet import Servlet 81 82 class WebStackServletFactory(ServletFactory): 83 84 """ 85 A servlet factory object producing servlets which provide access to 86 application-specific resources. 87 """ 88 89 def __init__(self, application, resource, file_extensions, authenticator=None, handle_errors=1): 90 91 """ 92 Initialise the servlet factory with the Webware 'application' and the 93 WebStack root application-specific 'resource'. The 'file_extensions' 94 specified indicate for which files this factory is invoked. An optional 95 'authenticator' is used to control access to the resource. The optional 96 'handle_errors' parameter (if true) causes handlers to deal with 97 uncaught exceptions cleanly. 98 """ 99 100 ServletFactory.__init__(self, application) 101 self.webstack_resource = resource 102 self.file_extensions = file_extensions 103 self.webstack_authenticator = authenticator 104 self.handle_errors = handle_errors 105 106 def uniqueness(self): 107 108 """ 109 Return "file" uniqueness - probably the most appropriate response. 110 """ 111 112 return "file" 113 114 def extensions(self): 115 116 """ 117 Return the file extensions supported by this factory. 118 """ 119 120 return self.file_extensions 121 122 def servletForTransaction(self, trans): 123 124 """ 125 Return a servlet which will provide access to the application-specific 126 resources. The 'trans' object - a Webware transaction - is not given to 127 the servlet since such information is available when the 'respond' 128 method is invoked on the servlet. 129 """ 130 131 return WebStackServlet(self.webstack_resource, self.webstack_authenticator, 132 self.handle_errors) 133 134 # Servlets are common to both solutions. 135 136 class WebStackServlet(Servlet): 137 138 "A servlet which dispatches transactions to application-specific resources." 139 140 def __init__(self, resource, authenticator, handle_errors): 141 142 """ 143 Initialise the servlet with an application-specific 'resource' and 144 'authenticator'. Where 'handle_errors' is true, uncaught exceptions are 145 dealt with by the handler. 146 """ 147 148 Servlet.__init__(self) 149 self.webstack_resource = resource 150 self.webstack_authenticator = authenticator 151 self.handle_errors = handle_errors 152 153 def respond(self, trans): 154 155 """ 156 Respond to the incoming transaction, 'trans', by dispatching to the 157 application-specific resource. 158 """ 159 160 new_trans = WebStack.Webware.Transaction(trans) 161 162 try: 163 if self.webstack_authenticator is None or self.webstack_authenticator.authenticate(new_trans): 164 try: 165 self.webstack_resource.respond(new_trans) 166 except EndOfResponse: 167 pass 168 except: 169 if self.handle_errors: 170 new_trans.set_response_code(500) # Internal error 171 else: 172 raise 173 else: 174 new_trans.set_response_code(401) # Unauthorized 175 new_trans.set_header_value("WWW-Authenticate", '%s realm="%s"' % ( 176 self.webstack_authenticator.get_auth_type(), self.webstack_authenticator.get_realm())) 177 178 finally: 179 new_trans.commit() 180 181 # vim: tabstop=4 expandtab shiftwidth=4