1.1 --- a/javaclass/classhook.py Sun Feb 13 02:10:43 2005 +0100
1.2 +++ b/javaclass/classhook.py Sun Feb 13 19:10:07 2005 +0100
1.3 @@ -166,7 +166,6 @@
1.4 else:
1.5 archive, archive_path, path = self._get_archive_and_path(dir, name)
1.6
1.7 - #print "Processing name", name, "in", dir, "producing", path, "within archive", archive
1.8
1.9 if self._find_module_at_path(path, archive):
1.10 if archive is not None:
1.11 @@ -204,7 +203,6 @@
1.12
1.13 def _find_module_at_path(self, path, archive):
1.14 if self.hooks.path_isdir(path, archive):
1.15 - #print "Looking in", path, "using archive", archive
1.16
1.17 # Look for classes in the directory.
1.18
1.19 @@ -213,7 +211,6 @@
1.20
1.21 # Otherwise permit importing where directories containing classes exist.
1.22
1.23 - #print "Filenames are", self.hooks.listdir(path, archive)
1.24 for filename in self.hooks.listdir(path, archive):
1.25 pathname = self.hooks.path_join(path, filename)
1.26 result = self._find_module_at_path(pathname, archive)
1.27 @@ -237,30 +234,29 @@
1.28 find_module method produces such a list.
1.29 """
1.30
1.31 - loaded_module_names = []
1.32 - loaded_classes = {}
1.33 - main_module = self._load_module(name, stuff, loaded_module_names, loaded_classes)
1.34 + module = self._not_java_module(name, stuff)
1.35 + if module is not None:
1.36 + return module
1.37 +
1.38 + if not hasattr(self, "loaded_classes"):
1.39 + self.loaded_classes = {}
1.40 + top_level = 1
1.41 + else:
1.42 + top_level = 0
1.43 +
1.44 + main_module = self._load_module(name, stuff)
1.45
1.46 # Initialise the loaded classes.
1.47
1.48 - for module, classes in loaded_classes.items():
1.49 - self._init_classes(module, classes)
1.50 + if top_level:
1.51 + self._init_classes()
1.52 + self.loaded_classes = {}
1.53
1.54 return main_module
1.55
1.56 - def _filter_names(self, module_names, loaded_module_names):
1.57 - for module_name in loaded_module_names:
1.58 - try:
1.59 - i = module_names.index(module_name)
1.60 - del module_names[i]
1.61 - except ValueError:
1.62 - pass
1.63 + def _not_java_module(self, name, stuff):
1.64
1.65 - def _load_module(self, name, stuff, loaded_module_names, loaded_classes):
1.66 - #print "_load_module", name, loaded_module_names
1.67 - loaded_module_names.append(name)
1.68 -
1.69 - # Detect non-Java modules.
1.70 + "Detect non-Java modules."
1.71
1.72 for stuff_item in stuff:
1.73 archive, filename, info = stuff_item
1.74 @@ -268,6 +264,10 @@
1.75 if datatype not in (JAVA_PACKAGE, JAVA_ARCHIVE):
1.76 return ihooks.ModuleLoader.load_module(self, name, stuff_item)
1.77
1.78 + return None
1.79 +
1.80 + def _load_module(self, name, stuff):
1.81 +
1.82 # Set up the module.
1.83 # A union of all locations is placed in the module's path.
1.84
1.85 @@ -292,26 +292,22 @@
1.86
1.87 archive, filename, info = stuff_item
1.88 suffix, mode, datatype = info
1.89 - #print "Loading", archive, filename, info
1.90
1.91 # Get the real filename.
1.92
1.93 filename = self._get_path_in_archive(filename)
1.94 - #print "Real filename", filename
1.95
1.96 # Load the class files.
1.97
1.98 for class_filename in self.hooks.matching(filename, os.extsep + "class", archive):
1.99 - #print "Loading class", class_filename
1.100 s = self.hooks.read(class_filename, archive)
1.101 class_file = classfile.ClassFile(s)
1.102 translator = bytecode.ClassTranslator(class_file)
1.103 - classes[str(class_file.this_class.get_name())] = translator
1.104 external_names += translator.process(global_names)
1.105
1.106 - # Record the classes found under the current module.
1.107 + # Record the classes found under the current module.
1.108
1.109 - loaded_classes[module] = classes
1.110 + self.loaded_classes[str(class_file.this_class.get_name())] = module, translator
1.111
1.112 # Return modules used by external names.
1.113
1.114 @@ -319,57 +315,12 @@
1.115
1.116 # Repeatedly load classes from referenced modules.
1.117
1.118 - self._filter_names(external_module_names, loaded_module_names)
1.119 for module_name in external_module_names:
1.120 - if module_name not in loaded_module_names:
1.121 -
1.122 - # Emulate the __import__ function, loading the requested module
1.123 - # but returning the top-level module.
1.124 -
1.125 - self._import(module_name, global_names, loaded_module_names, loaded_classes)
1.126 + new_module = __import__(module_name, global_names)
1.127 + global_names[module_name.split(".")[0]] = new_module
1.128
1.129 return module
1.130
1.131 - def _import(self, module_name, parent, loaded_module_names, loaded_classes):
1.132 -
1.133 - # Where no Java-based submodules can be found, look for
1.134 - # Python modules instead.
1.135 -
1.136 - new_stuff = self.find_module(module_name)
1.137 - #print "_", new_stuff
1.138 - if not new_stuff:
1.139 - new_module = __import__(module_name, parent)
1.140 - #print "P", new_module
1.141 - parent[module_name.split(".")[0]] = new_module
1.142 - return new_module
1.143 -
1.144 - module_name_parts = module_name.split(".")
1.145 - path = []
1.146 - for module_name_part in module_name_parts:
1.147 - path.append(module_name_part)
1.148 - path_str = ".".join(path)
1.149 - if self.modules_dict().has_key(path_str):
1.150 -
1.151 - # Add submodules to existing modules.
1.152 -
1.153 - new_module = self.modules_dict()[path_str]
1.154 - parent = new_module.__dict__
1.155 - #print "-", path_str
1.156 -
1.157 - else:
1.158 -
1.159 - # Find submodules.
1.160 -
1.161 - new_stuff = self.find_module(path_str)
1.162 - new_module = self._load_module(path_str, new_stuff, loaded_module_names, loaded_classes)
1.163 - #print "J", new_module
1.164 - #print "+", path_str, new_module
1.165 - parent[module_name_part] = new_module
1.166 - parent = new_module.__dict__
1.167 -
1.168 - #print "->", new_module.__dict__.keys()
1.169 - return new_module
1.170 -
1.171 def _get_external_module_names(self, names):
1.172 groups = self._get_names_grouped_by_module(names)
1.173 if groups.has_key(""):
1.174 @@ -391,19 +342,45 @@
1.175 module_name = ".".join(full_name_parts[:-1])
1.176 return module_name, class_name
1.177
1.178 - def _init_classes(self, module, classes):
1.179 - global_names = module.__dict__
1.180 + def _init_classes(self):
1.181 +
1.182 + # Order the classes according to inheritance.
1.183 +
1.184 + init_order = []
1.185 + for class_name, (module, translator) in self.loaded_classes.items():
1.186 + super_class = translator.get_super_class()
1.187 +
1.188 + # Insert the super class before any mention of the current class.
1.189
1.190 - # First, create the classes.
1.191 + if super_class is not None:
1.192 + super_class_name = str(super_class.get_name())
1.193 + if super_class_name not in init_order:
1.194 + if class_name not in init_order:
1.195 + init_order.append(super_class_name)
1.196 + else:
1.197 + index = init_order.index(class_name)
1.198 + init_order.insert(index, super_class_name)
1.199 +
1.200 + if class_name not in init_order:
1.201 + init_order.append(class_name)
1.202 +
1.203 + # Create the classes.
1.204
1.205 real_classes = []
1.206 - for name, translator in classes.items():
1.207 - real_classes.append(translator.get_class(global_names))
1.208 + for class_name in init_order:
1.209 + try:
1.210 + module, translator = self.loaded_classes[class_name]
1.211 + global_names = module.__dict__
1.212 + real_classes.append((module, translator.get_class(global_names)))
1.213 + except KeyError:
1.214 + # NOTE: Should be a non-Java class.
1.215 + pass
1.216
1.217 # Finally, call __clinit__ methods for all relevant classes.
1.218
1.219 - for cls in real_classes:
1.220 + for module, cls in real_classes:
1.221 if hasattr(cls, "__clinit__"):
1.222 + global_names = module.__dict__
1.223 eval(cls.__clinit__.func_code, global_names)
1.224
1.225 ihooks.ModuleImporter(loader=ClassLoader(hooks=ClassHooks())).install()