File: modjy_publish.py

package info (click to toggle)
jython 2.5.3-16%2Bdeb9u1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 43,772 kB
  • ctags: 106,434
  • sloc: python: 351,322; java: 216,349; xml: 1,584; sh: 330; perl: 114; ansic: 102; makefile: 45
file content (143 lines) | stat: -rw-r--r-- 6,547 bytes parent folder | download | duplicates (7)
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
139
140
141
142
143
###
#
# 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 self.app_directory is not None and 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:
                for name_val in query_string.split('&'):
                    if name_val.find('=') != -1:
                        name, value = name_val.split('=', 1)
                    else:
                        name, value = name_val, ''
                    if name == self.params['callable_query_name']:
                        callable_name = value
            else:
                callable_name = ''
        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']:
            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)) )