2.1 --- a/javaclass/classhook.py Sun Feb 13 02:10:43 2005 +0100
2.2 +++ b/javaclass/classhook.py Sun Feb 13 19:10:07 2005 +0100
2.3 @@ -166,7 +166,6 @@
2.4 else:
2.5 archive, archive_path, path = self._get_archive_and_path(dir, name)
2.6
2.7 - #print "Processing name", name, "in", dir, "producing", path, "within archive", archive
2.8
2.9 if self._find_module_at_path(path, archive):
2.10 if archive is not None:
2.11 @@ -204,7 +203,6 @@
2.12
2.13 def _find_module_at_path(self, path, archive):
2.14 if self.hooks.path_isdir(path, archive):
2.15 - #print "Looking in", path, "using archive", archive
2.16
2.17 # Look for classes in the directory.
2.18
2.19 @@ -213,7 +211,6 @@
2.20
2.21 # Otherwise permit importing where directories containing classes exist.
2.22
2.23 - #print "Filenames are", self.hooks.listdir(path, archive)
2.24 for filename in self.hooks.listdir(path, archive):
2.25 pathname = self.hooks.path_join(path, filename)
2.26 result = self._find_module_at_path(pathname, archive)
2.27 @@ -237,30 +234,29 @@
2.28 find_module method produces such a list.
2.29 """
2.30
2.31 - loaded_module_names = []
2.32 - loaded_classes = {}
2.33 - main_module = self._load_module(name, stuff, loaded_module_names, loaded_classes)
2.34 + module = self._not_java_module(name, stuff)
2.35 + if module is not None:
2.36 + return module
2.37 +
2.38 + if not hasattr(self, "loaded_classes"):
2.39 + self.loaded_classes = {}
2.40 + top_level = 1
2.41 + else:
2.42 + top_level = 0
2.43 +
2.44 + main_module = self._load_module(name, stuff)
2.45
2.46 # Initialise the loaded classes.
2.47
2.48 - for module, classes in loaded_classes.items():
2.49 - self._init_classes(module, classes)
2.50 + if top_level:
2.51 + self._init_classes()
2.52 + self.loaded_classes = {}
2.53
2.54 return main_module
2.55
2.56 - def _filter_names(self, module_names, loaded_module_names):
2.57 - for module_name in loaded_module_names:
2.58 - try:
2.59 - i = module_names.index(module_name)
2.60 - del module_names[i]
2.61 - except ValueError:
2.62 - pass
2.63 + def _not_java_module(self, name, stuff):
2.64
2.65 - def _load_module(self, name, stuff, loaded_module_names, loaded_classes):
2.66 - #print "_load_module", name, loaded_module_names
2.67 - loaded_module_names.append(name)
2.68 -
2.69 - # Detect non-Java modules.
2.70 + "Detect non-Java modules."
2.71
2.72 for stuff_item in stuff:
2.73 archive, filename, info = stuff_item
2.74 @@ -268,6 +264,10 @@
2.75 if datatype not in (JAVA_PACKAGE, JAVA_ARCHIVE):
2.76 return ihooks.ModuleLoader.load_module(self, name, stuff_item)
2.77
2.78 + return None
2.79 +
2.80 + def _load_module(self, name, stuff):
2.81 +
2.82 # Set up the module.
2.83 # A union of all locations is placed in the module's path.
2.84
2.85 @@ -292,26 +292,22 @@
2.86
2.87 archive, filename, info = stuff_item
2.88 suffix, mode, datatype = info
2.89 - #print "Loading", archive, filename, info
2.90
2.91 # Get the real filename.
2.92
2.93 filename = self._get_path_in_archive(filename)
2.94 - #print "Real filename", filename
2.95
2.96 # Load the class files.
2.97
2.98 for class_filename in self.hooks.matching(filename, os.extsep + "class", archive):
2.99 - #print "Loading class", class_filename
2.100 s = self.hooks.read(class_filename, archive)
2.101 class_file = classfile.ClassFile(s)
2.102 translator = bytecode.ClassTranslator(class_file)
2.103 - classes[str(class_file.this_class.get_name())] = translator
2.104 external_names += translator.process(global_names)
2.105
2.106 - # Record the classes found under the current module.
2.107 + # Record the classes found under the current module.
2.108
2.109 - loaded_classes[module] = classes
2.110 + self.loaded_classes[str(class_file.this_class.get_name())] = module, translator
2.111
2.112 # Return modules used by external names.
2.113
2.114 @@ -319,57 +315,12 @@
2.115
2.116 # Repeatedly load classes from referenced modules.
2.117
2.118 - self._filter_names(external_module_names, loaded_module_names)
2.119 for module_name in external_module_names:
2.120 - if module_name not in loaded_module_names:
2.121 -
2.122 - # Emulate the __import__ function, loading the requested module
2.123 - # but returning the top-level module.
2.124 -
2.125 - self._import(module_name, global_names, loaded_module_names, loaded_classes)
2.126 + new_module = __import__(module_name, global_names)
2.127 + global_names[module_name.split(".")[0]] = new_module
2.128
2.129 return module
2.130
2.131 - def _import(self, module_name, parent, loaded_module_names, loaded_classes):
2.132 -
2.133 - # Where no Java-based submodules can be found, look for
2.134 - # Python modules instead.
2.135 -
2.136 - new_stuff = self.find_module(module_name)
2.137 - #print "_", new_stuff
2.138 - if not new_stuff:
2.139 - new_module = __import__(module_name, parent)
2.140 - #print "P", new_module
2.141 - parent[module_name.split(".")[0]] = new_module
2.142 - return new_module
2.143 -
2.144 - module_name_parts = module_name.split(".")
2.145 - path = []
2.146 - for module_name_part in module_name_parts:
2.147 - path.append(module_name_part)
2.148 - path_str = ".".join(path)
2.149 - if self.modules_dict().has_key(path_str):
2.150 -
2.151 - # Add submodules to existing modules.
2.152 -
2.153 - new_module = self.modules_dict()[path_str]
2.154 - parent = new_module.__dict__
2.155 - #print "-", path_str
2.156 -
2.157 - else:
2.158 -
2.159 - # Find submodules.
2.160 -
2.161 - new_stuff = self.find_module(path_str)
2.162 - new_module = self._load_module(path_str, new_stuff, loaded_module_names, loaded_classes)
2.163 - #print "J", new_module
2.164 - #print "+", path_str, new_module
2.165 - parent[module_name_part] = new_module
2.166 - parent = new_module.__dict__
2.167 -
2.168 - #print "->", new_module.__dict__.keys()
2.169 - return new_module
2.170 -
2.171 def _get_external_module_names(self, names):
2.172 groups = self._get_names_grouped_by_module(names)
2.173 if groups.has_key(""):
2.174 @@ -391,19 +342,45 @@
2.175 module_name = ".".join(full_name_parts[:-1])
2.176 return module_name, class_name
2.177
2.178 - def _init_classes(self, module, classes):
2.179 - global_names = module.__dict__
2.180 + def _init_classes(self):
2.181 +
2.182 + # Order the classes according to inheritance.
2.183 +
2.184 + init_order = []
2.185 + for class_name, (module, translator) in self.loaded_classes.items():
2.186 + super_class = translator.get_super_class()
2.187 +
2.188 + # Insert the super class before any mention of the current class.
2.189
2.190 - # First, create the classes.
2.191 + if super_class is not None:
2.192 + super_class_name = str(super_class.get_name())
2.193 + if super_class_name not in init_order:
2.194 + if class_name not in init_order:
2.195 + init_order.append(super_class_name)
2.196 + else:
2.197 + index = init_order.index(class_name)
2.198 + init_order.insert(index, super_class_name)
2.199 +
2.200 + if class_name not in init_order:
2.201 + init_order.append(class_name)
2.202 +
2.203 + # Create the classes.
2.204
2.205 real_classes = []
2.206 - for name, translator in classes.items():
2.207 - real_classes.append(translator.get_class(global_names))
2.208 + for class_name in init_order:
2.209 + try:
2.210 + module, translator = self.loaded_classes[class_name]
2.211 + global_names = module.__dict__
2.212 + real_classes.append((module, translator.get_class(global_names)))
2.213 + except KeyError:
2.214 + # NOTE: Should be a non-Java class.
2.215 + pass
2.216
2.217 # Finally, call __clinit__ methods for all relevant classes.
2.218
2.219 - for cls in real_classes:
2.220 + for module, cls in real_classes:
2.221 if hasattr(cls, "__clinit__"):
2.222 + global_names = module.__dict__
2.223 eval(cls.__clinit__.func_code, global_names)
2.224
2.225 ihooks.ModuleImporter(loader=ClassLoader(hooks=ClassHooks())).install()