File: modjy_publish.py

package info (click to toggle)
jython 2.5.1-2
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 41,624 kB
  • ctags: 101,579
  • sloc: python: 351,444; java: 204,338; xml: 1,316; sh: 330; ansic: 126; perl: 114; makefile: 94
file content (138 lines) | stat: -rw-r--r-- 5,693 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
###
#
# Copyright Alan Kennedy. 
# 
# You may contact the copyright holder at this uri:
# 
# http://www.xhaus.com/contact/modjy
# 
# The licence under which this code is released is the Apache License v2.0.
# 
# The terms and conditions of this license are listed in a file contained
# in the distribution that also contained this file, under the name
# LICENSE.txt.
# 
# You may also read a copy of the license at the following web address.
# 
# http://modjy.xhaus.com/LICENSE.txt
#
###

import sys
import synchronize

from java.io import File

from modjy_exceptions import *

class modjy_publisher:

	def init_publisher(self):
		self.cache = None
		if self.params['app_directory']:
			self.app_directory = self.expand_relative_path(self.params['app_directory'])
		else:
			self.app_directory = self.servlet_context.getRealPath('/')
		self.params['app_directory'] = self.app_directory
		if not self.app_directory in sys.path:
			sys.path.append(self.app_directory)

	def map_uri(self, req, environ):
		source_uri = '%s%s%s' % (self.app_directory, File.separator, self.params['app_filename'])
		callable_name = self.params['app_callable_name']
		if self.params['callable_query_name']:
			query_string = req.getQueryString()
			if query_string and '=' in query_string:
				for name_val in query_string.split('&'):
					name, value = name_val.split('=')
					if name == self.params['callable_query_name']:
						callable_name = value
		return source_uri, callable_name

	def get_app_object(self, req, environ):
		environ["SCRIPT_NAME"] = "%s%s" % (req.getContextPath(), req.getServletPath())
		path_info = req.getPathInfo() or ""
		environ["PATH_INFO"] = path_info
		environ["PATH_TRANSLATED"] = File(self.app_directory, path_info).getPath()

		if self.params['app_import_name'] is not None:
			return self.get_app_object_importable(self.params['app_import_name'])
		else:
			if self.cache is None:
				self.cache = {}
			return self.get_app_object_old_style(req, environ)

	get_app_object = synchronize.make_synchronized(get_app_object)

	def get_app_object_importable(self, importable_name):
		self.log.debug("Attempting to import application callable '%s'\n" % (importable_name, ))
		# Under the importable mechanism, the cache contains a single object
		if self.cache is None:
			application, instantiable, method_name = self.load_importable(importable_name.strip())
			if instantiable and self.params['cache_callables']:
				application = application()
			self.cache = application, instantiable, method_name
		application, instantiable, method_name = self.cache
		self.log.debug("Application is " + str(application))
		if instantiable and not self.params['cache_callables']:
			application = application()
			self.log.debug("Instantiated application is " + str(application))
		if method_name is not None:
			if not hasattr(application, method_name):
				self.log.fatal("Attribute error application callable '%s' as no method '%s'" % (application, method_name))
				self.raise_exc(ApplicationNotFound, "Attribute error application callable '%s' as no method '%s'" % (application, method_name))
			application = getattr(application, method_name)
			self.log.debug("Application method is " + str(application))
		return application

	def load_importable(self, name):
		try:
			instantiable = False ; method_name = None
			importable_name = name
			if name.find('()') != -1:
				instantiable = True
				importable_name, method_name = name.split('()')
				if method_name.startswith('.'):
					method_name = method_name[1:]
				if not method_name:
					method_name = None
			module_path, from_name = importable_name.rsplit('.', 1)
			imported = __import__(module_path, globals(), locals(), [from_name])
			imported = getattr(imported, from_name)
			return imported, instantiable, method_name
		except (ImportError, AttributeError), aix:
			self.log.fatal("Import error import application callable '%s': %s\n" % (name, str(aix)))
			self.raise_exc(ApplicationNotFound, "Failed to import app callable '%s': %s" % (name, str(aix)))

	def get_app_object_old_style(self, req, environ):
		source_uri, callable_name = self.map_uri(req, environ)
		source_filename = source_uri
		if not self.params['cache_callables']:
			self.log.debug("Caching of callables disabled")
			return self.load_object(source_filename, callable_name)
		if not self.cache.has_key( (source_filename, callable_name) ):
			self.log.debug("Callable object not in cache: %s#%s" % (source_filename, callable_name) )
			return self.load_object(source_filename, callable_name)
		app_callable, last_mod = self.cache.get( (source_filename, callable_name) )
		self.log.debug("Callable object was in cache: %s#%s" % (source_filename, callable_name) )
		if self.params['reload_on_mod']:
			f = File(source_filename)
			if f.lastModified() > last_mod:
				self.log.info("Source file '%s' has been modified: reloading" % source_filename)
				return self.load_object(source_filename, callable_name)
		return app_callable

	def load_object(self, path, callable_name):
		try:
			app_ns = {} ; execfile(path, app_ns)
			app_callable = app_ns[callable_name]
			f = File(path)
			self.cache[ (path, callable_name) ] = (app_callable, f.lastModified())
			return app_callable
		except IOError, ioe:
			self.raise_exc(ApplicationNotFound, "Application filename not found: %s" % path)
		except KeyError, k:
			self.raise_exc(NoCallable, "No callable named '%s' in %s" % (callable_name, path))
		except Exception, x:
			self.raise_exc(NoCallable, "Error loading jython callable '%s': %s" % (callable_name, str(x)) )