summaryrefslogtreecommitdiffstats
path: root/lib/jython/Lib/jreload.py
blob: 80029ec4264f06acf580a05e8c46d2cc9e20b118 (plain)
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
# java classes reload support (experimental)
# Copyright 2000 Samuele Pedroni

# ?? could have problem with import pkg.jclass.inner (this should not be used in any case)
# ?? using import * with a load-set together with reloading can be confusing
#    cannot be fixed => anyway import * is not for production code

__version__ = "0.3"

import sys
from org.python.core import imp,PyJavaPackage,PyJavaClass
from _jython import is_lazy as _is_lazy

import jxxload_help


class _LoaderFactory(jxxload_help.JavaLoaderFactory):
    def __init__(self,path):
        vfs = jxxload_help.PathVFS()
        for fname in path:
            vfs.addVFS(fname)
        self.vfs = vfs

    def makeLoader(self):
        return jxxload_help.PathVFSJavaLoader(self.vfs,imp.getSyspathJavaLoader())

class _Unload:

    def __init__(self,ls):
        self.ls = ls
        self.ls_name = ls._name
        self.loader = ls._mgr.loader

    def do_unload(self,pkg):
        for n in pkg.__dict__.keys():
            e = pkg.__dict__[n]
            if isinstance(e,PyJavaClass):
                if _is_lazy(e): continue
                if e.classLoader is self.loader:
                    del pkg.__dict__[n]
                    if pkg.__name__:
                        n = self.ls_name + '.' + pkg.__name__ + '.' +n
                    else:
                        n = self.ls_name + '.' + n
                    if sys.modules.has_key(n): del sys.modules[n]

            elif isinstance(e,PyJavaPackage):
                self.do_unload(e)

    def __call__(self):
        if self.loader:
            if self.ls._mgr.checkLoader() is self.loader:
                self.do_unload(self.ls._top)
                self.ls._mgr.resetLoader()
            loader = self.loader
            jxxload_help.DiscardHelp.discard(loader,loader.interfaces)
            self.loader = None

class LoadSet:
# ?? for the moment from import * and dir do not work for LoadSet, but work for
# contained pkgs
# need java impl as PyObject

    def __init__(self,name,path):
        mgr = jxxload_help.PackageManager(path,_LoaderFactory(path))
        self._name = name
        self._mgr = mgr
        self._top = mgr.topLevelPackage

    def __getattr__(self,name):
        try:
            return getattr(self._top,name)
        except:
            if name == 'unload': return _Unload(self)
            raise
            

    def __repr__(self):
        return "<java load-set %s>" % self._name

def unloadf(ls):
    if not isinstance(ls,LoadSet): raise TypeError,"unloadf(): arg is not a load-set"
    return _Unload(ls)

def makeLoadSet(name,path):
    if sys.modules.has_key(name): return sys.modules[name]
    sys.modules[name] = ls = LoadSet(name,path)
    return ls

_reload = reload

def _do_reload(ls_name,mgr,pkg):
    pkg_name = pkg.__name__
    for n in pkg.__dict__.keys():
        e = pkg.__dict__[n]
        if isinstance(e,PyJavaClass):
            if _is_lazy(e): continue
            del pkg.__dict__[n]
            try :
                c = mgr.findClass(pkg_name,n);
                if c:
                    pkg.__dict__[n] = c
                    if pkg_name:
                        n = ls_name + '.' + pkg_name + '.' + n
                    else:
                        n = ls_name + '.' + n
                    if sys.modules.has_key(n): sys.modules[n] = c
            except:
                pass
        elif isinstance(e,PyJavaPackage):
            _do_reload(ls_name,mgr,e)

def reload(ls):
    if isinstance(ls,LoadSet):
        ls._mgr.resetLoader()
        _do_reload(ls._name,ls._mgr,ls._top)
        return ls
    else:
        return _reload(ls)