javaclass

Change of javaclass/classhook.py

168:1f3fa26a27e2
javaclass/classhook.py
     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()