--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/JavaClassReader.st Fri Apr 08 12:02:36 2011 +0000
@@ -0,0 +1,2536 @@
+"
+ COPYRIGHT (c) 1997 by eXept Software AG
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+"{ Package: 'stx:libjava' }"
+
+Object subclass:#JavaClassReader
+ instanceVariableNames:'inStream msb constants majorVsn minorVsn constNeeds2Slots
+ constSlot'
+ classVariableNames:'Verbose AnnotationsVerbose Silent AbsolutelySilent
+ LazyClassLoading InvalidClassFormatSignal ClassLoaderQuerySignal
+ JavaArchiveCache'
+ poolDictionaries:''
+ category:'Languages-Java-Support'
+!
+
+!JavaClassReader class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 1997 by eXept Software AG
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+
+
+! !
+
+!JavaClassReader class methodsFor:'initialization'!
+
+initialize
+ InvalidClassFormatSignal := Signal new mayProceed: true.
+ InvalidClassFormatSignal notifierString: 'class load failure'.
+ InvalidClassFormatSignal nameClass: self message: #invalidClassFormatSignal.
+ Verbose := false.
+ Silent := true.
+ AbsolutelySilent := false.
+
+ "/LazyClassLoading := false.
+
+ LazyClassLoading := true.
+ ClassLoaderQuerySignal := QuerySignal new.
+ JavaArchiveCache := CacheDictionary new: 32.
+ AnnotationsVerbose := false.
+ "
+ JavaClassReader initialize"
+
+ "Modified: / 27-01-1998 / 17:54:23 / cg"
+ "Modified: / 17-12-2010 / 17:37:45 / Marcel Hlopko <hlopik@gmail.com>"
+ "Modified: / 10-02-2011 / 23:16:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 16-03-2011 / 12:13:41 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+! !
+
+!JavaClassReader class methodsFor:'Signal constants'!
+
+classLoaderQuerySignal
+ ^ ClassLoaderQuerySignal
+
+ "Created: 14.8.1997 / 19:56:03 / cg"
+!
+
+invalidClassFormatSignal
+ ^ InvalidClassFormatSignal
+
+ "Created: 3.8.1997 / 18:17:21 / cg"
+! !
+
+!JavaClassReader class methodsFor:'constants'!
+
+fileMajorVersions
+ ^ #(
+ 45 "Java 1.2"
+ 49 "Java 6"
+ )
+
+ "Created: / 19-10-2010 / 21:40:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+fileMinorVersions
+ ^ #(
+ 3 "Java 1.2"
+ 0 "Java 6"
+ )
+
+ "Created: / 19-10-2010 / 21:41:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+magic_LSB
+ ^ 16rBEBAFECA
+
+ "Modified: / 7.5.1998 / 13:14:27 / cg"
+ "Created: / 7.5.1998 / 13:15:05 / cg"
+!
+
+magic_MSB
+ ^ 16rCAFEBABE
+
+ "Modified: / 7.5.1998 / 13:14:27 / cg"
+! !
+
+!JavaClassReader class methodsFor:'debugging'!
+
+annotationsVerbose:aBoolean
+ AnnotationsVerbose := aBoolean
+
+ "
+ Java flushClasses.
+ JavaClassReader verbose:true
+ JavaClassReader verbose:false"
+
+ "Created: / 25-02-2011 / 12:25:23 / Marcel Hlopko <hlopik@gmail.com>"
+!
+
+verbose:aBoolean
+ Verbose := aBoolean
+
+ "
+ Java flushClasses.
+ JavaClassReader verbose:true
+ JavaClassReader verbose:false
+ "
+! !
+
+!JavaClassReader class methodsFor:'file reading'!
+
+loadClass:aClassName
+ "reads a class, installs and returns it.
+ The classes string constants are resolved & <clinit> is called,
+ if it implements it."
+
+ |rslt loader|
+
+ loader := ClassLoaderQuerySignal query.
+ loader isNil ifTrue:[
+ ^ self loadSystemClass:aClassName
+ ].
+
+ ^ loader loadClass:aClassName
+
+ "
+ JavaClassReader loadClass:'awt/Component'
+ JavaClassReader loadClass:'awt/Button'
+ JavaClassReader loadClass:'browser/AddButton'
+
+ JavaClassReader loadClass:'java/lang/Object'
+ JavaClassReader loadClass:'java/lang/AbstractMethodError'
+ JavaClassReader loadClass:'java/lang/Thread'
+ "
+
+ "Created: / 15.4.1996 / 14:58:53 / cg"
+ "Modified: / 20.10.1998 / 17:24:54 / cg"
+!
+
+loadClassLazy: aClassName ignoring: classesBeingLoaded
+ "private helper:
+ reads a class, installs and returns it.
+ The class is searched along the ClassPath.
+
+ This is a partial load (to load other classes):
+ - The classes stringConstants are not fixed to be JavaStrings
+ (i.e they are still ST-Strings).
+ - The class is NOT initialized."
+
+ | rslt clsName cls loadedClass |
+
+ clsName := aClassName.
+ (clsName endsWith: ';')
+ ifTrue:
+ [ (clsName startsWith: '[L')
+ ifTrue: [ clsName := clsName copyFrom: 3 to: clsName size - 1. ]
+ ifFalse:
+ [ ('oops - loading of ' , clsName , ' attempted') printNL.
+ self halt: 'should not happen'.
+ ^ nil. ] ].
+ (clsName endsWith: '[]')
+ ifTrue:
+ [ ('oops - loading of ' , clsName , ' attempted') printNL.
+ self halt: 'should not happen'.
+ ^ nil ].
+ (clsName includes: $.)
+ ifTrue: [ clsName := clsName asString copyReplaceAll: $. with: $/ ].
+ (classesBeingLoaded notNil and: [ classesBeingLoaded includes: clsName ])
+ ifTrue:
+ [ ('oops - recursive load of ' , clsName , ' attempted') printNL.
+ self halt: 'should not happen'.
+ ^ JavaUnresolvedClassConstant fullName: clsName ].
+ (cls := Java at: clsName) notNil
+ ifTrue:
+ [ ('oops - ' , clsName , ' is already loaded') printNL.
+
+ "/self halt:clsName , ' is already loaded - should not happen'.
+
+ ^ cls ].
+ classesBeingLoaded isNil
+ ifTrue: [ loadedClass := Set with: clsName ]
+ ifFalse:
+ [ loadedClass := Set withAll: classesBeingLoaded.
+ loadedClass add: clsName. ].
+ Java effectiveClassPath do:
+ [:path |
+ | nm p zar entry zipFile read |
+
+ Verbose == true
+ ifTrue: [ Transcript showCR: 'trying ' , path asFilename pathName , ' ...'. ].
+ p := path.
+ p asFilename isDirectory
+ ifTrue:
+ [ (p endsWith: Filename separator)
+ ifFalse: [ p := p , (Filename separator asString) ].
+ (Array
+ with: clsName
+ with: clsName asLowercase
+ with: clsName asUppercase) do:
+ [:tryName |
+ nm := p , tryName , '.class'.
+ Verbose == true ifTrue: [ Transcript showCR: 'trying ' , nm , ' ...'. ].
+ nm asFilename exists
+ ifTrue:
+ [ (Java isExcludedFromClassPath: nm)
+ ifFalse:
+ [ rslt := self loadFileLazy: nm ignoring: loadedClass.
+ rslt notNil ifTrue: [ ^ rslt ]. ] ]. ] ]
+ ifFalse:
+ [ Verbose == true
+ ifTrue:
+ [ Transcript
+ showCR: 'trying ' , (p asFilename withSuffix: 'jar') pathName , ' ...'.
+ Transcript
+ showCR: 'and ' , (p asFilename withSuffix: 'zip') pathName , ' ...'. ].
+ ((zipFile := p asFilename withSuffix: 'jar') exists
+ or: [ (zipFile := p asFilename withSuffix: 'zip') exists ])
+ ifTrue:
+ [
+ zar := JavaArchiveCache at: zipFile
+ ifAbsentPut: [ ZipArchive oldFileNamed: zipFile ].
+ read :=
+ [ nm := clsName , '.class'.
+ entry := zar extract: nm.
+ entry notNil
+ ifTrue:
+ [ (Java isExcludedFromClassPath: nm)
+ ifFalse:
+ [ rslt := self loadStreamLazy: (entry readStream) ignoring: loadedClass.
+ rslt notNil ifTrue: [ ^ rslt ]. ] ] ].
+ JavaClassReader invalidClassFormatSignal handle:
+ [ "Kludge, sometimes zar gets corrupted"
+
+ zar := JavaArchiveCache at: zipFile put: (ZipArchive oldFileNamed: zipFile).
+ read value ]
+ do: [ read value ]. ] ] ].
+ ('JAVA [info]: no file found for: ' , clsName) infoPrintCR.
+ ^ nil
+
+ "Modified: / 14-08-1997 / 11:38:42 / stefan"
+ "Modified: / 17-09-1998 / 20:51:25 / cg"
+ "Modified: / 18-03-2011 / 16:06:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 21-03-2011 / 12:42:12 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
+loadClassesIn: directory
+ "load all classes (.class files, strictly speaking) found in given directory
+ or .jar file. The argument is string containing the name of the directory.
+ Returns a set of loaded classes.
+ "
+
+ | dir dirString className loadedClasses |
+ dir := directory asFilename.
+ loadedClasses := Set new.
+ Java addToClassPath: dir pathName.
+ dir recursiveDirectoryContentsAsFilenamesDo:
+ [:filename |
+ (filename isRegularFile and: [ filename suffix = #class ])
+ ifTrue:
+ [ dirString := dir asAbsoluteFilename pathName.
+ className := filename withoutSuffix pathName.
+ className := className subString: dirString size + 2 to: className size.
+ loadedClasses add: (self loadClass: className).
+ "horrible and ugly and I'm gonna fix it very very soon""
+ className
+ indexOfSubCollection: 'annotation'
+ startingAt: 1
+ ifAbsent: [ self loadClass: className ]
+
+ caseSensitive: false.
+ " ]. ].
+ ^loadedClasses
+
+ "Created: / 15-03-2011 / 15:39:49 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+ "Modified: / 16-03-2011 / 18:01:04 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+ "Modified: / 01-04-2011 / 15:44:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+loadFile:aFilename
+ "reads a class from aFilename, installs and returns it.
+ The classes strings are fixed and its class-init function is called."
+
+ self loadFileLazy:aFilename ignoring:(Set new).
+ self postLoadActions
+!
+
+loadFileLazy:aFilename ignoring:classesBeingLoaded
+ "reads a class from aFilename, installs and returns it.
+ Strings are fixed and classrefs are fixed,
+ but NO no class-init functions are called."
+
+ |aClass pool|
+
+ aClass := self readFile:aFilename ignoring:classesBeingLoaded.
+ aClass notNil ifTrue:[
+ aClass isJavaClass ifTrue:[
+ "/ a java class
+ Java at:(aClass fullName asSymbol) put:aClass.
+
+ classesBeingLoaded remove:aClass fullName ifAbsent:nil.
+
+ JavaUnresolvedConstant resolveFor:aClass.
+ ] ifFalse:[
+ "/ a smalltalk class
+ "/ self halt.
+aClass inspect.
+ ]
+ ].
+ ^ aClass
+
+ "
+ JavaClassReader loadFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+
+ '/phys/ibm3/java/lib/java/lang' asFilename
+ directoryContents do:[:nm |
+ (nm endsWith:'.class') ifTrue:[
+ ('/phys/ibm3/java/lib/java/lang/' , nm) printNL.
+ JavaClassReader loadFile:'/phys/ibm3/java/lib/java/lang/' , nm
+ ]
+ ].
+
+ '/phys/ibm3/java/lib/java/io' asFilename
+ directoryContents do:[:nm |
+ (nm endsWith:'.class') ifTrue:[
+ ('/phys/ibm3/java/lib/java/io/' , nm) printNL.
+ JavaClassReader loadFile:'/phys/ibm3/java/lib/java/io/' , nm
+ ]
+ ].
+
+ '/phys/ibm3/java/lib/java/net' asFilename
+ directoryContents do:[:nm |
+ (nm endsWith:'.class') ifTrue:[
+ ('/phys/ibm3/java/lib/java/net/' , nm) printNL.
+ JavaClassReader loadFile:'/phys/ibm3/java/lib/java/net/' , nm
+ ]
+ ].
+
+ '/phys/ibm3/java/lib/java/util' asFilename
+ directoryContents do:[:nm |
+ (nm endsWith:'.class') ifTrue:[
+ ('/phys/ibm3/java/lib/java/util/' , nm) printNL.
+ JavaClassReader loadFile:'/phys/ibm3/java/lib/java/util/' , nm
+ ]
+ ].
+
+ '/phys/ibm3/java/lib/java/awt' asFilename
+ directoryContents do:[:nm |
+ (nm endsWith:'.class') ifTrue:[
+ ('/phys/ibm3/java/lib/java/awt/' , nm) printNL.
+ JavaClassReader loadFile:'/phys/ibm3/java/lib/java/awt/' , nm
+ ]
+ ].
+
+ '/phys/ibm3/java/lib/java/applet' asFilename
+ directoryContents do:[:nm |
+ (nm endsWith:'.class') ifTrue:[
+ ('/phys/ibm3/java/lib/java/applet/' , nm) printNL.
+ JavaClassReader loadFile:'/phys/ibm3/java/lib/java/applet/' , nm
+ ]
+ ].
+
+ JavaClassReader loadFile:'/phys/ibm3/java/lib/java/lang/AbstractMethodError.class'
+ JavaClassReader loadFile:'/phys/ibm3/java/lib/java/lang/Thread.class'
+ "
+
+ "Created: / 15.4.1996 / 14:58:53 / cg"
+ "Modified: / 12.5.1998 / 22:06:52 / cg"
+!
+
+loadStreamLazy:aStream ignoring:classesBeingLoaded
+ "reads a class from aStream, installs and returns it.
+ Strings are fixed and classrefs are fixed,
+ but NO no class-init functions are called."
+
+ |javaClass pool|
+
+ javaClass := self readStream:aStream ignoring:classesBeingLoaded.
+ javaClass notNil ifTrue:[
+ Java at:(javaClass fullName asSymbol) put:javaClass.
+
+ classesBeingLoaded remove:javaClass fullName ifAbsent:nil.
+
+ JavaUnresolvedConstant resolveFor:javaClass.
+ ].
+ ^ javaClass
+
+ "Created: / 30.3.1998 / 17:59:02 / cg"
+!
+
+loadSystemClass:aClassName
+ "reads a class, installs and returns it.
+ The classes string constants are resolved & <clinit> is called,
+ if it implements it.
+ This only loads local classes (i.e. any Java classReader is not used)"
+
+ |rslt|
+
+ rslt := self loadClassLazy:aClassName ignoring:(Set new).
+ rslt notNil ifTrue:[self postLoadActions].
+
+ ^ rslt
+
+ "
+ JavaClassReader loadSystemClass:'awt/Component'
+ JavaClassReader loadSystemClass:'awt/Button'
+ JavaClassReader loadSystemClass:'browser/AddButton'
+
+ JavaClassReader loadSystemClass:'java/lang/Object'
+ JavaClassReader loadSystemClass:'java/lang/AbstractMethodError'
+ JavaClassReader loadSystemClass:'java/lang/Thread'
+ "
+
+ "Modified: / 3.1.1998 / 22:36:13 / cg"
+ "Created: / 20.10.1998 / 17:24:40 / cg"
+!
+
+postLoadActions
+ "Resolve all classes' string constants.
+ Perform all class initialization functions (of those which are not
+ yet initialized)."
+
+ ^ self postLoadActions:true
+
+ "Modified: 15.8.1997 / 01:02:17 / cg"
+!
+
+postLoadActions:loadUnresolved
+ "Resolve all classes' string constants.
+ Perform all class initialization functions
+ (of those which are not yet initialized)."
+
+ |classes prevUnresolved newUnresolved loader|
+
+ "/ need at least java.lang.String, for valid constants
+ Java java_lang_String isNil ifTrue:[
+ self loadClassLazy:'java.lang.String' ignoring:(Set new).
+ ].
+
+ LazyClassLoading ifFalse:[
+ loader := ClassLoaderQuerySignal query.
+
+ prevUnresolved := nil.
+ newUnresolved := JavaUnresolvedConstant unresolvedClassNames asArray.
+ loadUnresolved ifTrue:[
+ [prevUnresolved ~= newUnresolved] whileTrue:[
+ newUnresolved do:[:nextUnresolved |
+ |classURL|
+
+ (Java at:nextUnresolved) isNil ifTrue:[ "/ could have been loaded in the meantime
+ Silent ifFalse:[
+ 'loading unresolved: ' print. nextUnresolved printCR.
+ ].
+ loader isNil ifTrue:[
+ self
+ loadClassLazy:nextUnresolved
+ ignoring:(Set new).
+ ] ifFalse:[
+ "/
+ "/ the aquired loader is a javaClassLoader
+ "/ which expects an URL as arg.
+ "/
+ "/ classURL := Java as_URL:('file:' , nextUnresolved asString , '.class').
+ "/ loader loadClass:classURL
+ loader
+ perform:#'loadClass(Ljava/lang/String;)Ljava/lang/Class;'
+ with:(Java as_String:(nextUnresolved asString)).
+ ]
+ ]
+ ].
+ prevUnresolved := newUnresolved.
+ newUnresolved := JavaUnresolvedConstant unresolvedClassNames asArray.
+ ].
+ ].
+false ifTrue:[
+ newUnresolved size == 0 ifTrue:[
+ "/ nothing unresolved
+
+ (classes := Java allClasses) notNil ifTrue:[
+ "/ init all new classes
+ "/ fetch again - there could be new ones ...
+
+ classes := Java allClasses.
+ classes do:[:aJavaClass |
+ aJavaClass isInitialized ifFalse:[
+ Silent ifFalse:[
+ 'performing class initialization of ' print. aJavaClass fullName printCR.
+ ].
+ aJavaClass classInit
+ ]
+ ]
+ ]
+ ].
+].
+ ]
+
+ "Created: / 15.8.1997 / 01:01:44 / cg"
+ "Modified: / 21.10.1998 / 01:18:35 / cg"
+!
+
+readFile:aFilename ignoring:classesBeingLoaded
+ "reads a class from aFilename and returns it.
+ The JavaClass is NOT installed as global and unresolved
+ refs are NOT patched."
+
+ |inStream javaClass|
+
+ "Silent"false ifFalse:[
+ 'reading ' print. aFilename print. ' ...' printCR.
+ ].
+ ObjectMemory compressingGarbageCollect.
+
+ [
+ inStream := aFilename asFilename readStream.
+ ] on:StreamError do:[:ex|
+ ('JAVA [info]: no file: ' , aFilename asString) printCR.
+ self halt.
+ ^ nil
+ ].
+
+ javaClass := self new readStream:inStream ignoring:classesBeingLoaded.
+ (javaClass notNil and:[javaClass isJavaClass]) ifTrue:[
+ javaClass setBinaryFilePath:(inStream pathName).
+ ].
+ inStream close.
+
+ ObjectMemory compressingGarbageCollect.
+ AbsolutelySilent ifFalse:[
+ ' ... loaded ' print. javaClass displayString printNL.
+ ].
+
+
+ ^ javaClass
+
+ "Created: / 15.4.1996 / 14:58:53 / cg"
+ "Modified: / 9.5.1998 / 01:44:24 / cg"
+!
+
+readStream:aStream
+ "reads a class from aStream and returns it.
+ The JavaClass is installed as global.
+ If new classes are required to be loaded, a new standard loader
+ is created."
+
+ ^ self readStream:aStream loader:nil
+
+ "Modified: 14.8.1997 / 19:51:50 / cg"
+!
+
+readStream:aStream ignoring:classesBeingLoaded
+ "reads a class from aStream and returns it.
+ The JavaClass is not installed as global"
+
+ |javaClass|
+
+ javaClass := self new readStream:aStream ignoring:classesBeingLoaded.
+
+ AbsolutelySilent ifFalse:[
+ ' ... loaded ' print. javaClass displayString printNL.
+ ].
+
+ ^ javaClass
+
+ "Modified: / 30.3.1998 / 18:14:40 / cg"
+!
+
+readStream:aStream loader:aClassLoader
+ "reads a class from aStream and returns it.
+ The JavaClass is installed as global.
+ If new classes are required to be loaded, aClassLoader is
+ asked to do it. If aClassLoader is nil, a new standard loader
+ is created."
+
+ ^ self
+ readStream:aStream
+ loader:aClassLoader
+ loadUnresolved:true
+
+ "Modified: 15.8.1997 / 01:00:35 / cg"
+!
+
+readStream:aStream loader:aClassLoader loadUnresolved:loadUnresolved
+ "reads a class from aStream and returns it.
+ The JavaClass is installed as global.
+ If new classes are required to be loaded, aClassLoader is
+ asked to do it. If aClassLoader is nil, a new standard loader
+ is created."
+
+ |javaClass|
+
+ ClassLoaderQuerySignal answer:aClassLoader
+ do:[
+ javaClass := self readStream:aStream ignoring:(Set new).
+ javaClass notNil ifTrue:[
+ self postLoadActions:loadUnresolved.
+ Java at:(javaClass fullName asSymbol) put:javaClass.
+ JavaUnresolvedConstant resolveFor:javaClass.
+ ].
+ ].
+ ^ javaClass
+
+ "Created: / 15.8.1997 / 00:59:24 / cg"
+ "Modified: / 23.1.1998 / 17:14:09 / cg"
+!
+
+resolveClass:aJavaClass
+ "Resolve a particular classes' constants.
+ Perform all class initialization functions
+ (of those which are not yet initialized)."
+
+ |loader classToLoad|
+
+ LazyClassLoading ifFalse:[
+ loader := (aJavaClass classLoader). "/ ? (ClassLoaderQuerySignal raise).
+
+ [
+ classToLoad := nil.
+ aJavaClass constantPool do:[:item |
+ |itemClass |
+
+ itemClass := item class.
+ itemClass == JavaUnresolvedClassConstant ifTrue:[
+ classToLoad := item className.
+"/ ] ifFalse:[
+"/ itemClass == JavaUnresolvedMethodrefConstant ifTrue:[
+"/self halt.
+"/ ] ifFalse:[
+"/ itemClass == JavaUnresolvedInterfaceMethodrefConstant ifTrue:[
+"/self halt.
+"/ ]
+"/ ]
+ ].
+ ].
+
+ classToLoad notNil ifTrue:[
+ loader isNil ifTrue:[
+ self
+ loadClassLazy:classToLoad
+ ignoring:(Set new).
+ ] ifFalse:[
+ "/
+ "/ the aquired loader is a javaClassLoader
+ "/ which expects an URL as arg.
+ "/
+ "/ classURL := Java as_URL:('file:' , nextUnresolved asString , '.class').
+ "/ loader loadClass:classURL
+ loader
+ perform:#'loadClass(Ljava/lang/String;)Ljava/lang/Class;'
+ with:(Java as_String:(classToLoad asString)).
+ ]
+ ].
+ classToLoad notNil.
+ ] whileTrue.
+
+ aJavaClass isInitialized ifFalse:[
+ Silent ifFalse:[
+ 'performing class initialization of ' print. aJavaClass fullName printCR.
+ ].
+ aJavaClass classInit
+ ].
+ ]
+
+ "Created: / 20.10.1998 / 17:53:22 / cg"
+ "Modified: / 20.10.1998 / 17:59:09 / cg"
+! !
+
+!JavaClassReader methodsFor:'file reading'!
+
+readClassFileIgnoring:classesbeingLoaded
+ "reads a class from inStream and returns it.
+ The JavaClass is not installed as global and its constants
+ (especially strings) may not be fully resolved."
+
+ |magic access_flags this_class this_class_index super_class super_class_index realSuperClass this_class_ref existingSuperClass fields interfaces staticFields nStatic jSuperClass loader superClassName thisClassName existing_class thisMetaClass|
+
+ "/
+ "/ read magic, determine byte order
+ "/
+ msb := true.
+ magic := inStream nextUnsignedLongMSB:true.
+ magic = (self class magic_MSB) ifFalse:[
+ magic = (self class magic_LSB) ifFalse:[
+ InvalidClassFormatSignal raiseErrorString:'not a java class file'.
+ ^ nil
+ ].
+ msb := false.
+ Verbose ifTrue:[
+ Transcript showCR:'file is lsb'
+ ].
+ ] ifTrue:[
+ Verbose ifTrue:[
+ Transcript showCR:'file is msb'
+ ].
+ ].
+
+ "/
+ "/ get version
+ "/
+
+ minorVsn := inStream nextUnsignedShortMSB:msb.
+ majorVsn := inStream nextUnsignedShortMSB:msb.
+ ((self class fileMajorVersions includes:majorVsn) not
+ or:[(self class fileMinorVersions includes:minorVsn) not])
+ ifTrue:[
+ Transcript
+ show:'warning this file has version ';
+ show:majorVsn;
+ show:'.';
+ showCR:minorVsn.
+ ].
+ Verbose ifTrue:[
+ Transcript
+ show:'version = ';
+ show:(majorVsn printString);
+ show:'.';
+ showCR:(minorVsn printString).
+ ].
+
+ "/
+ "/ get constant pool
+ "/
+
+ self readConstantPool.
+
+ "/
+ "/ access flags
+ "/
+
+ access_flags := inStream nextUnsignedShortMSB:msb.
+ this_class_index := inStream nextUnsignedShortMSB:msb.
+ super_class_index := inStream nextUnsignedShortMSB:msb.
+ super_class_index == 0 ifTrue:[
+ super_class := nil
+ ] ifFalse:[
+ super_class := constants at:super_class_index.
+ superClassName := super_class fullName.
+
+ "/ special for ST-classes
+
+ (superClassName startsWith:'smalltalk.') ifTrue:[
+ "/ a Smalltalk class
+ superClassName := superClassName copyFrom:11.
+ existingSuperClass := Smalltalk at:superClassName asSymbol.
+ existingSuperClass notNil ifTrue:[
+ super_class := existingSuperClass
+ ] ifFalse:[
+ "/ self halt - must load superclass ...
+ ]
+ ] ifFalse:[
+ "/ a JAVA class
+ existingSuperClass := Java classNamed:superClassName.
+ existingSuperClass notNil ifTrue:[
+ super_class := existingSuperClass
+ ] ifFalse:[
+ (super_class isMemberOf:JavaUnresolvedClassConstant) ifTrue:[
+ Silent ifFalse:[
+ 'load superClass: ' print.
+ superClassName printCR.
+ ].
+ loader := ClassLoaderQuerySignal query.
+ loader isNil ifTrue:[
+ existingSuperClass := self class loadClassLazy:superClassName
+ ignoring:classesbeingLoaded.
+ ] ifFalse:[
+ jSuperClass := loader
+ perform:#'loadClass(Ljava/lang/String;)Ljava/lang/Class;'
+ with:(Java as_String:superClassName).
+ existingSuperClass := JavaVM reflection classForJavaClassObject:jSuperClass.
+ ].
+ existingSuperClass isNil ifTrue:[
+ ('JAVA: cannot find superclass: ' , superClassName) infoPrintCR.
+
+ "/ self halt:('cannot find superclass: ' , superClassName).
+
+ ^ nil.
+ ].
+ super_class := existingSuperClass
+ ] ifFalse:[
+ self halt:'oops - superclass ?'
+ ]
+ ].
+ ].
+ ].
+
+ "/
+ "/ get interfaces
+ "/
+
+ interfaces := self readInterfaces.
+
+ "/
+ "/ get fields
+ "/
+
+ fields := self readFieldInfofields.
+
+ "/
+ "/ create the fields as instVars
+ "/ static fields are created as class-InstVars
+ "/
+
+ staticFields := fields select:[:f | f isStatic].
+ nStatic := staticFields size.
+ this_class_ref := constants at:this_class_index.
+ thisClassName := this_class_ref fullName.
+
+ "/ care for smalltalk classes ...
+
+ (thisClassName startsWith:'smalltalk.') ifTrue:[
+ thisClassName := thisClassName copyFrom:11.
+ existing_class := Smalltalk at:thisClassName asSymbol.
+ existing_class notNil ifTrue:[
+ self halt:('overloading existing class: ' , thisClassName).
+ thisClassName := (thisClassName , '_new') asSymbol.
+ ].
+ thisMetaClass := Metaclass new.
+ thisMetaClass setSuperclass:super_class class.
+ thisMetaClass instSize:(super_class class instSize + nStatic).
+ this_class := thisMetaClass new.
+ this_class setSuperclass:super_class.
+ this_class setName:thisClassName asSymbol.
+ ] ifFalse:[
+ "/ a java class
+ this_class := JavaClass fullName:thisClassName numStatic:nStatic.
+ nStatic ~~ 0 ifTrue:[
+ fields := fields select:[:f | f isStatic not].
+ JavaClass setInstanceVariableStringFromFields:staticFields
+ in:this_class class.
+ this_class setStaticFields:staticFields.
+ this_class initializeStaticFields.
+ ].
+ this_class setAccessFlags:access_flags.
+ this_class setSuperclass:super_class.
+ this_class setConstantPool:constants.
+ this_class setFields:fields.
+ this_class setInterfaces:interfaces.
+ constants owner:this_class.
+ ].
+
+ "/
+ "/ get methods
+ "/
+
+ self readMethodsFor:this_class.
+ self readAttributesFor:this_class.
+ ^ this_class
+
+ "
+ JavaClassReader loadFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ JavaClassReader loadFile:'/phys/ibm3/hotjava/classes/browser/Alignable.class'
+ JavaClassReader loadFile:'foo.cls'
+
+ JavaClassReader verbose:true.
+ JavaClassReader loadFile:'/phys/ibm3/hotjava/classes/java/lang/ArithmeticException.class'
+ JavaClassReader loadFile:'/phys/ibm3/java/lib/java/lang/ArithmeticException.class'"
+
+ "Created: / 15-04-1996 / 15:02:47 / cg"
+ "Modified: / 12-11-1998 / 21:14:45 / cg"
+ "Modified: / 15-10-2010 / 17:37:38 / Jan Kurs <kurs.jan@post.cz>"
+ "Modified: / 19-10-2010 / 21:43:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 28-01-2011 / 15:09:48 / Marcel Hlopko <hlopik@gmail.com>"
+!
+
+readStream:aStream ignoring:classesBeingLoaded
+ "reads a class from aStream and returns it.
+ The JavaClass is not installed as global"
+
+ inStream := aStream.
+ inStream binary.
+
+ ^ self readClassFileIgnoring:classesBeingLoaded
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ "
+
+ "Created: 15.4.1996 / 15:00:55 / cg"
+ "Modified: 15.4.1996 / 15:06:18 / cg"
+! !
+
+!JavaClassReader methodsFor:'file reading - attributes'!
+
+readAnnotationDefaultAttributeFor:something
+ "/ ('JAVA [info]: unhandled attribute: AnnotationDefault') infoPrintCR.
+
+ |len startPos endPos annotationDefault|
+
+ self assert:something isJavaMethod
+ description:'AnnotationDefault may only occure for methods!!'.
+ len := inStream nextUnsignedLongMSB:msb.
+ startPos := inStream position.
+ annotationDefault := (something ensureHasAnnotations)
+ default:(JavaAnnotationDefault new
+ value:(self readAnnotationValueFor:something));
+ default.
+ endPos := inStream position.
+ inStream position:startPos.
+ annotationDefault bytes:(inStream next:len).
+ self assert:inStream position = endPos
+ description:'self readAnnotationValueFor: something is reading what it shouldn'.
+
+ "Modified: / 28-02-2011 / 17:08:28 / Marcel Hlopko <hlopik@gmail.com>"
+ "Modified: / 03-03-2011 / 23:06:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+readAnnotationFor:something
+ | typeIndex type result attrsCount |
+
+ typeIndex := inStream nextUnsignedShortMSB:msb.
+ type := something constantPool at:typeIndex.
+ attrsCount := inStream nextUnsignedShortMSB:msb.
+ result := JavaAnnotation for:something.
+ result name:type.
+ attrsCount timesRepeat:
+ [ | nameIndex name valueIndex attr |
+
+ nameIndex := inStream nextUnsignedShortMSB:msb.
+ name := something constantPool at:nameIndex.
+ attr := self readAnnotationValueFor:something.
+ attr name:name.
+ result values at:attr name put:attr.
+ AnnotationsVerbose
+ ifTrue:[ ('JAVA [INFO]: Reading annotation attribute: ' , name) infoPrintCR. ]. ].
+ ^ result.
+
+ "Created: / 17-12-2010 / 16:21:28 / Marcel Hlopko <hlopik@gmail.com>"
+ "Modified: / 25-02-2011 / 12:25:36 / Marcel Hlopko <hlopik@gmail.com>"
+!
+
+readAnnotationValueFor:something
+ | tag result |
+
+ tag := (inStream nextByte) asCharacter.
+ tag = $e
+ ifTrue:
+ [ result := JavaAnnotationEnumValue for:something.
+ result nameIndex:(inStream nextUnsignedShortMSB:msb).
+ result valueIndex:(inStream nextUnsignedShortMSB:msb).
+ AnnotationsVerbose
+ ifTrue:
+ [ ('JAVA [INFO]: Reading annotation enum value: ' , result name printString, ' -> '
+ , result value printString) infoPrintCR ].
+ ^ result ].
+ tag = $c
+ ifTrue:
+ [ result := JavaAnnotationClassValue for:something.
+ result classIndex:(inStream nextUnsignedShortMSB:msb).
+ AnnotationsVerbose
+ ifTrue:
+ [ ('JAVA [INFO]: Reading annotation class value: ' , result name printString, ' -> '
+ , result value printString) infoPrintCR ].
+ ^ result ].
+ tag = $@
+ ifTrue:
+ [ result := JavaAnnotationNestedAnnotationValue for:something.
+ result classIndex:(inStream nextUnsignedShortMSB:msb).
+ AnnotationsVerbose
+ ifTrue:
+ [ ('JAVA [INFO]: Reading annotation nested annotation value: ' , result name printString
+ , ' -> ' , result value printString)
+ infoPrintCR ].
+ ^ result ].
+ tag = $[
+ ifTrue:
+ [ result := JavaAnnotationArrayValue for:something.
+ result count:(inStream nextUnsignedShortMSB:msb).
+ AnnotationsVerbose
+ ifTrue:[ ('JAVA [INFO]: Reading annotation array value') infoPrintCR ].
+ 1 to:result count
+ do:[:index | result values at:index put:(self readAnnotationValueFor:something) ].
+ AnnotationsVerbose
+ ifTrue:
+ [ ('JAVA [INFO]: Finished reading annotation array value: '
+ , result value printString) infoPrintCR ].
+ ^ result ].
+ result := JavaAnnotationPrimitiveValue for:something.
+ result valueIndex:(inStream nextUnsignedShortMSB:msb).
+ AnnotationsVerbose
+ ifTrue:
+ [ ('JAVA [INFO]: Finished reading annotation primitive value: '
+ , result name printString , ' -> ' , result value printString) infoPrintCR ].
+ ^ result.
+
+ "Created: / 17-12-2010 / 16:44:14 / Marcel Hlopko <hlopik@gmail.com>"
+ "Modified: / 28-02-2011 / 16:12:09 / Marcel Hlopko <hlopik@gmail.com>"
+!
+
+readAttribute:attributeName for:something
+ "/ implemented JAVA attributes
+
+ (attributeName = 'ConstantValue')
+ ifTrue:
+ [ self readConstantValueAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'Code')
+ ifTrue:
+ [ self readCodeAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'Exceptions')
+ ifTrue:
+ [ self readExceptionsAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'InnerClasses')
+ ifTrue:
+ [ self readInnerClassesAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'EnclosingMethod')
+ ifTrue:
+ [ self readEnclosingMethodAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'LineNumberTable')
+ ifTrue:
+ [ self readLineNumberTableAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'LocalVariableTable')
+ ifTrue:
+ [ self readLocalVariableTableAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'LocalVariableTypeTable')
+ ifTrue:
+ [ self readLocalVariableTypeTableAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'SourceFile')
+ ifTrue:
+ [ self readSourceFileAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'SourceDebugExtension')
+ ifTrue:
+ [ self readSourceDebugExtensionAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'Synthetic')
+ ifTrue:
+ [ self readSyntheticAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'Signature')
+ ifTrue:
+ [ self readSignatureAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'Deprecated')
+ ifTrue:
+ [ self readDeprecatedAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'RuntimeVisibleAnnotations')
+ ifTrue:
+ [ self readRuntimeAnnotationsAttributeFor:something visible:true.
+ ^ self. ].
+ (attributeName = 'RuntimeInvisibleAnnotations')
+ ifTrue:
+ [ self readRuntimeAnnotationsAttributeFor:something visible:false.
+ ^ self. ].
+ (attributeName = 'RuntimeVisibleParameterAnnotations')
+ ifTrue:
+ [ self readRuntimeParameterAnnotationsAttributeFor:something visible:true.
+ ^ self. ].
+ (attributeName = 'RuntimeInvisibleParameterAnnotations')
+ ifTrue:
+ [ self readRuntimeParameterAnnotationsAttributeFor:something visible:false.
+ ^ self. ].
+ (attributeName = 'AnnotationDefault')
+ ifTrue:
+ [ self readAnnotationDefaultAttributeFor:something.
+ ^ self. ].
+
+ "/ ignored JAVA attributes
+
+ (attributeName = 'FastJavac1.0')
+ ifTrue:
+ [ "/ ('JAVA [info]: unhandled attribute: ' , attributeName) infoPrintCR.
+ self skipAttribute:attributeName.
+ ^ self. ].
+ (attributeName = 'AbsoluteSourcePath')
+ ifTrue:
+ [ ('JAVA [info]: unhandled attribute: ' , attributeName) infoPrintCR.
+ self skipAttribute:attributeName.
+ ^ self. ].
+ (attributeName startsWith:((Character value:13) asString , 'WARNING:'))
+ ifTrue:
+ [ "/ ('JAVA [info]: unhandled attribute: ' , attributeName) infoPrintCR.
+ self skipAttribute:attributeName.
+ ^ self. ].
+ (attributeName = 'StackMapTable')
+ ifTrue:
+ [ "/ ('JAVA [info]: unhandled attribute: ' , attributeName) infoPrintCR.
+ self readStackMapTableAttributeFor:something.
+ ^ self. ].
+
+ "/ implemented ST attributes
+
+ (attributeName = 'STLiterals')
+ ifTrue:
+ [ self readSTLiteralsAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'ClassRevision')
+ ifTrue:
+ [ self readSTClassRevisionAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'ClassPackage')
+ ifTrue:
+ [ self readSTClassPackageAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'ClassCategory')
+ ifTrue:
+ [ self readSTClassCategoryAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'ClassVarNames')
+ ifTrue:
+ [ self readSTClassVarNamesAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'ClassInstVarNames')
+ ifTrue:
+ [ self readSTClassInstVarNamesAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'InstVarNames')
+ ifTrue:
+ [ self readSTInstVarNamesAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'STCode')
+ ifTrue:
+ [ self readSTCodeAttributeFor:something.
+ ^ self. ].
+ (attributeName = 'MethodCategory')
+ ifTrue:
+ [ self readSTMethodCategoryAttributeFor:something.
+ ^ self. ].
+
+ "/ unknown attributes
+
+ ('JAVA [warning]: unrecognized attribute: ' , attributeName) infoPrintCR.
+ self skipAttribute:attributeName.
+
+ "Modified: / 03-12-1998 / 13:13:42 / cg"
+ "Modified: / 25-02-2011 / 18:09:21 / Marcel Hlopko <hlopik@gmail.com>"
+!
+
+readAttributeFor:something
+ |attribute_name_index attribute_name attribute_length attribute_info|
+
+ Verbose ifTrue:[Transcript show:'attrib at pos: '; showCR:inStream position].
+
+ attribute_name_index := inStream nextUnsignedShortMSB:msb.
+ attribute_name_index == 0 ifTrue:[
+ self halt.
+ "/self skipAttribute:'unnamed'.
+ ^ self.
+ ].
+
+ "/
+ "/ UNDOC feature ?
+ "/
+ attribute_name_index > constants size ifTrue:[
+ attribute_name_index == 16rb700 ifTrue:[
+ self halt.
+ ]
+ ].
+
+ attribute_name := constants at:attribute_name_index.
+
+ Verbose ifTrue:[Transcript show:'attrib name: '; showCR:attribute_name].
+
+ self readAttribute:attribute_name for:something.
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ "
+
+ "Created: / 15-04-1996 / 15:40:17 / cg"
+ "Modified: / 09-04-1998 / 18:13:34 / cg"
+ "Modified: / 19-10-2010 / 21:43:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+readAttributesFor:something
+ |attributes_count|
+
+ attributes_count := inStream nextUnsignedShortMSB:msb.
+
+ 1 to:attributes_count do:[:i |
+ self readAttributeFor:something.
+ ].
+
+ "Modified: 15.4.1996 / 15:33:28 / cg"
+ "Created: 15.4.1996 / 15:40:17 / cg"
+!
+
+readDeprecatedAttributeFor:aJavaMethodWithHandler
+
+ self skipAttribute:'Deprecated'.
+ ^self
+
+ "Created: / 18-10-2010 / 22:26:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+readEnclosingMethodAttributeFor:something
+"/ ('JAVA [info]: unhandled attribute: EnclosingMethod') infoPrintCR.
+ self skipAttribute:'EnclosingMethod'.
+!
+
+readInnerClassesAttributeFor:something
+"/ ('JAVA [info]: unhandled attribute: InnerClasses') infoPrintCR.
+ self skipAttribute:'InnerClasses'.
+!
+
+readLocalVariableTypeTableAttributeFor:something
+"/ ('JAVA [info]: unhandled attribute: LocalVariableTypeTable') infoPrintCR.
+ self skipAttribute:'LocalVariableTypeTable'.
+!
+
+readRuntimeAnnotationsAttributeFor: something visible: visible
+ | length annotationsCount annotations rawAnnotations startPos endPos |
+
+ self assert: inStream isPositionable
+ message: '.class file stream must be positionable'.
+ length := inStream nextUnsignedLongMSB: msb.
+ startPos := inStream position.
+ annotationsCount := inStream nextUnsignedShortMSB: msb.
+ annotationsCount = 0 ifTrue: [ ^ nil ].
+ annotations := visible ifTrue: [something ensureHasAnnotations ensureRuntimeVisible] ifFalse: [something ensureHasAnnotations ensureRuntimeInvisible].
+ annotationsCount timesRepeat:
+ [ | currentAnnotation |
+
+ currentAnnotation := self readAnnotationFor: something.
+ annotations at: currentAnnotation name put: currentAnnotation. ].
+ "Cut raw annotations as required by getRawAnnotations()"
+ endPos := inStream position.
+ inStream position: startPos.
+ rawAnnotations := inStream next: length.
+ inStream position ~= endPos
+ ifTrue: [ self halt: 'annotations are probably reading what they shouldnt' ].
+ annotations rawAnnotations: rawAnnotations.
+
+ "Modified: / 07-01-2011 / 22:00:07 / Jan Kurs <kurs.jan@post.cz>"
+ "Modified: / 25-02-2011 / 18:45:58 / Marcel Hlopko <hlopik@gmail.com>"
+ "Modified: / 03-03-2011 / 23:01:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 16-03-2011 / 16:57:03 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
+readRuntimeParameterAnnotationsAttributeFor: javaMethod visible: visible
+ | length paramsCount annotationsCount rawAnnotations startPos endPos |
+
+ self assert: inStream isPositionable
+ message: '.class file stream must be positionable'.
+ length := inStream nextUnsignedLongMSB: msb.
+ startPos := inStream position.
+ paramsCount := inStream nextByte.
+ paramsCount = 0 ifTrue: [ ^ nil ].
+ 1 to: paramsCount
+ do:
+ [:paramIndex |
+ annotationsCount := inStream nextUnsignedShortMSB: msb.
+ annotationsCount > 0
+ ifTrue:
+ [ | annotations |
+ annotations := visible
+ ifTrue:
+ [ javaMethod ensureHasAnnotations ensureVisibleParameterAnnotationsAt: paramIndex ]
+ ifFalse:
+ [javaMethod ensureHasAnnotations ensureInvisibleParameterAnnotationsAt: paramIndex ].
+ annotationsCount timesRepeat:
+ [ | annotation |
+
+ annotation := self readAnnotationFor: javaMethod.
+ annotations at: (annotation name) put: annotation. ] ]].
+ endPos := inStream position.
+ rawAnnotations := inStream position: startPos.
+ rawAnnotations := inStream next: length.
+ inStream position ~= endPos
+ ifTrue: [ self halt: 'annotations are probably reading what they shouldnt' ].
+ javaMethod annotations rawAnnotations: rawAnnotations.
+
+ "Modified: / 28-02-2011 / 17:05:47 / Marcel Hlopko <hlopik@gmail.com>"
+ "Modified: / 16-03-2011 / 17:26:42 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
+readSignatureAttributeFor:something
+"/ ('JAVA [info]: unhandled attribute: Signature') infoPrintCR.
+ self skipAttribute:'Signature'.
+!
+
+readSourceDebugExtensionAttributeFor:something
+"/ ('JAVA [info]: unhandled attribute: SourceDebugExtension') infoPrintCR.
+ self skipAttribute:'SourceDebugExtension'.
+!
+
+readSourceFileAttributeFor:aClass
+ |attribute_length sourceFile_index sourceFile|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ sourceFile_index := inStream nextUnsignedShortMSB:msb.
+ sourceFile := constants at:sourceFile_index.
+
+ aClass isJavaClass ifTrue:[
+ aClass setSourceFile:sourceFile.
+ ] ifFalse:[
+ aClass setClassFilename:sourceFile
+ ].
+
+ Verbose ifTrue:[Transcript show:'sourceFile: '; showCR:sourceFile].
+ ^ true
+
+ "
+ JavaClassReader loadFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ JavaClassReader loadFile:'/phys/ibm3/hotjava/classes/browser/Alignable.class'
+ JavaClassReader loadFile:'foo.cls'
+ "
+
+ "Created: / 15.4.1996 / 15:40:17 / cg"
+ "Modified: / 12.5.1998 / 22:01:07 / cg"
+!
+
+readStackMapTableAttributeFor:something
+"/ ('JAVA [info]: unhandled attribute: StackMapTable') infoPrintCR.
+ self skipAttribute:'StackMapTable'.
+
+ "Created: / 09-02-2011 / 01:19:20 / Marcel Hlopko <hlopik@gmail.com>"
+!
+
+readSyntheticAttributeFor:something
+"/ ('JAVA [info]: unhandled attribute: Synthetic') infoPrintCR.
+ self skipAttribute:'Synthetic'.
+!
+
+skipAttribute:attributeName
+ "dont know about this attribute - skip it here"
+
+ |attribute_length attribute_info|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+ attribute_info := ByteArray new:(attribute_length).
+ inStream nextBytes:attribute_length into:attribute_info startingAt:1.
+
+ Verbose ifTrue:[Transcript show:'skipped '; show:attributeName; showCR:'-attribute'].
+
+ "Created: / 9.4.1998 / 18:12:46 / cg"
+ "Modified: / 9.4.1998 / 18:13:20 / cg"
+! !
+
+!JavaClassReader methodsFor:'file reading - attributes-ST'!
+
+readSTClassCategoryAttributeFor:aClass
+ |attribute_length categoryString_index categoryString|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ categoryString_index := inStream nextUnsignedShortMSB:msb.
+ categoryString := constants at:categoryString_index.
+
+ aClass category:categoryString.
+
+ Verbose ifTrue:[Transcript show:'categoryString: '; showCR:categoryString].
+ ^ true
+
+ "
+ JavaClassReader loadFile:'foo.cls'
+ "
+
+ "Created: / 9.5.1998 / 02:33:13 / cg"
+ "Modified: / 9.5.1998 / 02:36:55 / cg"
+!
+
+readSTClassInstVarNamesAttributeFor:aClass
+ |attribute_length nameString_index nameString|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ nameString_index := inStream nextUnsignedShortMSB:msb.
+ nameString := constants at:nameString_index.
+
+ aClass class instanceVariableString:nameString.
+
+ Verbose ifTrue:[Transcript show:'nameString: '; showCR:nameString].
+ ^ true
+
+ "
+ JavaClassReader loadFile:'foo.cls'
+ "
+
+ "Modified: / 12.5.1998 / 22:18:03 / cg"
+ "Created: / 12.5.1998 / 22:18:24 / cg"
+!
+
+readSTClassPackageAttributeFor:aClass
+ |attribute_length packageString_index packageString|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ packageString_index := inStream nextUnsignedShortMSB:msb.
+ packageString := constants at:packageString_index.
+
+ aClass package:packageString asSymbol.
+
+ Verbose ifTrue:[Transcript show:'packageString: '; showCR:packageString].
+ ^ true
+
+ "
+ JavaClassReader loadFile:'foo.cls'
+ "
+
+ "Modified: / 9.5.1998 / 02:32:38 / cg"
+ "Created: / 9.5.1998 / 02:33:44 / cg"
+!
+
+readSTClassRevisionAttributeFor:aClass
+ |attribute_length revisionString_index revisionString|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ revisionString_index := inStream nextUnsignedShortMSB:msb.
+ revisionString := constants at:revisionString_index.
+
+ aClass setBinaryRevision:revisionString.
+
+ Verbose ifTrue:[Transcript show:'revisionString: '; showCR:revisionString].
+ ^ true
+
+ "
+ JavaClassReader loadFile:'foo.cls'
+ "
+
+ "Created: / 9.5.1998 / 02:33:13 / cg"
+ "Modified: / 9.5.1998 / 02:35:01 / cg"
+!
+
+readSTClassVarNamesAttributeFor:aClass
+ |attribute_length nameString_index nameString|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ nameString_index := inStream nextUnsignedShortMSB:msb.
+ nameString := constants at:nameString_index.
+
+ aClass classVariableString:nameString.
+
+ Verbose ifTrue:[Transcript show:'nameString: '; showCR:nameString].
+ ^ true
+
+ "
+ JavaClassReader loadFile:'foo.cls'
+ "
+
+ "Created: / 9.5.1998 / 02:33:13 / cg"
+ "Modified: / 12.5.1998 / 22:18:03 / cg"
+!
+
+readSTInstVarNamesAttributeFor:aClass
+ |attribute_length nameString_index nameString|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ nameString_index := inStream nextUnsignedShortMSB:msb.
+ nameString := constants at:nameString_index.
+
+ aClass setInstanceVariableString:nameString.
+
+ Verbose ifTrue:[Transcript show:'nameString: '; showCR:nameString].
+ ^ true
+
+ "
+ JavaClassReader loadFile:'foo.cls'
+ "
+
+ "Created: / 12.5.1998 / 22:18:14 / cg"
+ "Modified: / 12.5.1998 / 22:21:10 / cg"
+! !
+
+!JavaClassReader methodsFor:'file reading - constants'!
+
+readConstant
+ |tag constReader const|
+
+
+ constNeeds2Slots := false.
+
+ "/
+ "/ get tag
+ "/
+ tag := inStream nextByte.
+ Verbose ifTrue:[Transcript show:'tag = '; showCR:tag].
+
+ tag >= 250 ifTrue:[
+ constReader := #(
+ "/ ST types
+ readConstant_ST_Large "/ 249
+ readConstant_ST_Special "/ 250
+ readConstant_ST_Character "/ 251
+ readConstant_ST_ByteArray "/ 252
+ readConstant_ST_Array "/ 253
+ readConstant_ST_Symbol "/ 254
+ readConstant_ST_Reserved "/ 255
+ ) at:tag-249+1.
+ ] ifFalse:[
+ constReader := #(
+ "/ JAVA types
+ readConstant_Utf8 "/ 1 - now called Utf8
+ readConstant_Unicode "/ 2
+ readConstant_Integer "/ 3
+ readConstant_Float "/ 4
+ readConstant_Long "/ 5
+ readConstant_Double "/ 6
+ readConstant_Class "/ 7
+ readConstant_String "/ 8
+ readConstant_Fieldref "/ 9
+ readConstant_Methodref "/ 10
+ readConstant_InterfaceMethodref "/ 11
+ readConstant_NameAndType "/ 12
+ ) at:tag ifAbsent:[#readConstant_Undef].
+ ].
+ ^ self perform:constReader.
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ "
+
+ "Created: / 15.4.1996 / 15:46:32 / cg"
+ "Modified: / 9.5.1998 / 01:26:05 / cg"
+!
+
+readConstantPool
+ |constantPoolCount const i|
+
+ "/
+ "/ get constant pool
+ "/
+ constantPoolCount := inStream nextUnsignedShortMSB:msb.
+ Verbose ifTrue:[Transcript show:'constantPoolCount = '; showCR:constantPoolCount].
+
+ constants := JavaConstantPool "Array" new:constantPoolCount-1.
+
+ constSlot := 1.
+ [constSlot < constantPoolCount] whileTrue:[
+ Verbose ifTrue:[Transcript show:'const: '; showCR:constSlot].
+ const := self readConstant.
+ constants at:constSlot put:const.
+
+ "/ long & double consts take 2 slots
+ "/ (only first is used)
+ constNeeds2Slots ifTrue:[
+ constSlot := constSlot + 2.
+ ] ifFalse:[
+ constSlot := constSlot + 1.
+ ]
+ ].
+
+ constSlot := -1.
+
+ "/ preresolve what can be (especially, strings are resolved here)
+
+ 1 to:constantPoolCount-1 do:[:i |
+ |const value|
+
+ const := constants at:i.
+ const notNil ifTrue:[ "/ kludge for 2-slot constants (which only take 1 slot in ST/X)
+ (const isKindOf:JavaUnresolvedConstant) ifTrue:[
+ value := const preResolve.
+ value ~~ const ifTrue:[
+ constants at:i put:value.
+ ]
+ ]
+ ]
+ ].
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/Alignable.class'
+ "
+
+ "Created: / 15.4.1996 / 15:14:11 / cg"
+ "Modified: / 7.5.1998 / 11:44:06 / cg"
+!
+
+readConstant_Asciz
+ |len string|
+
+ len := inStream nextUnsignedShortMSB:msb.
+ string := String new:len.
+ inStream nextBytes:len into:string startingAt:1.
+
+ Verbose ifTrue:[Transcript show:'asciz; string= '; showCR:string].
+
+ ^ string
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/Alignable.class'
+ "
+
+ "Created: 15.4.1996 / 15:15:35 / cg"
+ "Modified: 15.4.1996 / 16:33:45 / cg"
+!
+
+readConstant_Class
+ |name_index name|
+
+ name_index := inStream nextUnsignedShortMSB:msb.
+
+ Verbose ifTrue:[Transcript show:'class; index= '; showCR:name_index].
+
+ name := constants at:name_index.
+ name notNil ifTrue:[
+ Verbose ifTrue:[Transcript showCR:'name in constant_class already resolved'].
+ "/ self halt
+ ].
+
+ ^ JavaUnresolvedClassConstant
+ pool:constants
+ poolIndex:constSlot
+ nameIndex:name_index
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ "
+
+ "Created: / 15.4.1996 / 15:21:13 / cg"
+ "Modified: / 8.5.1998 / 21:53:16 / cg"
+!
+
+readConstant_Double
+ |high low aFloat bytes|
+
+"/ new code - to be tested
+"/ bytes := ByteArray new:8.
+"/
+"/ inStream nextBytes:8 into:bytes startingAt:1.
+"/ msb ~~ UninterpretedBytes isBigEndian ifTrue:[
+"/ bytes reverse
+"/ ].
+"/ aFloat := bytes doubleAt:1.
+
+"/ old code
+
+ high := inStream nextUnsignedLongMSB:msb.
+ low := inStream nextUnsignedLongMSB:msb.
+
+ aFloat := Float new.
+ UninterpretedBytes isBigEndian ifTrue:[
+ aFloat basicAt:1 put:((high bitShift:-24) bitAnd:16rFF).
+ aFloat basicAt:2 put:((high bitShift:-16) bitAnd:16rFF).
+ aFloat basicAt:3 put:((high bitShift:-8) bitAnd:16rFF).
+ aFloat basicAt:4 put:(high bitAnd:16rFF).
+ aFloat basicAt:5 put:((low bitShift:-24) bitAnd:16rFF).
+ aFloat basicAt:6 put:((low bitShift:-16) bitAnd:16rFF).
+ aFloat basicAt:7 put:((low bitShift:-8) bitAnd:16rFF).
+ aFloat basicAt:8 put:(low bitAnd:16rFF).
+ ] ifFalse:[
+ aFloat basicAt:1 put:(low bitAnd:16rFF).
+ aFloat basicAt:2 put:((low bitShift:-8) bitAnd:16rFF).
+ aFloat basicAt:3 put:((low bitShift:-16) bitAnd:16rFF).
+ aFloat basicAt:4 put:((low bitShift:-24) bitAnd:16rFF).
+ aFloat basicAt:5 put:(high bitAnd:16rFF).
+ aFloat basicAt:6 put:((high bitShift:-8) bitAnd:16rFF).
+ aFloat basicAt:7 put:((high bitShift:-16) bitAnd:16rFF).
+ aFloat basicAt:8 put:((high bitShift:-24) bitAnd:16rFF).
+ ].
+
+ constNeeds2Slots := true.
+
+ Verbose ifTrue:[Transcript show:'double; value= '; showCR:aFloat].
+ ^ aFloat
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/Alignable.class'
+ "
+
+ "Created: / 15.4.1996 / 16:34:42 / cg"
+ "Modified: / 8.5.1998 / 22:06:07 / cg"
+!
+
+readConstant_Fieldref
+ |class_index name_and_type_index|
+
+ class_index := inStream nextUnsignedShortMSB:msb.
+ name_and_type_index := inStream nextUnsignedShortMSB:msb.
+
+ Verbose ifTrue:[Transcript show:'fieldref; classindex= '; showCR:class_index].
+ Verbose ifTrue:[Transcript show:'fieldref; name&typeindex= '; showCR:name_and_type_index].
+
+ ^ JavaUnresolvedFieldrefConstant
+ pool:constants
+ poolIndex:constSlot
+ classIndex:class_index
+ nameandTypeIndex:name_and_type_index
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ "
+
+ "Created: 15.4.1996 / 15:22:18 / cg"
+ "Modified: 15.4.1996 / 16:07:01 / cg"
+!
+
+readConstant_Float
+ |b1 b2 b3 b4 aFloat bytes|
+
+"/ new code - to be tested ...
+"/
+"/ bytes := ByteArray new:4.
+"/ inStream nextBytes:4 into:bytes startingAt:1.
+"/ msb ~~ UninterpretedBytes isBigEndian ifTrue:[
+"/ bytes reverse
+"/ ].
+"/ aFloat := bytes floatAt:1.
+"/ Verbose ifTrue:[Transcript show:'float; value= '; showCR:aFloat].
+"/ ^ aFloat.
+
+"/ old code
+
+ aFloat := ShortFloat basicNew.
+
+ b1 := inStream nextByte.
+ b2 := inStream nextByte.
+ b3 := inStream nextByte.
+ b4 := inStream nextByte.
+
+ UninterpretedBytes isBigEndian ifTrue:[
+ aFloat basicAt:1 put:b1.
+ aFloat basicAt:2 put:b2.
+ aFloat basicAt:3 put:b3.
+ aFloat basicAt:4 put:b4.
+ ] ifFalse:[
+ aFloat basicAt:4 put:b1.
+ aFloat basicAt:3 put:b2.
+ aFloat basicAt:2 put:b3.
+ aFloat basicAt:1 put:b4.
+ ].
+ Verbose ifTrue:[Transcript show:'float; value= '; showCR:aFloat].
+ ^ aFloat
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/Alignable.class'
+ "
+
+ "Created: / 15.4.1996 / 16:34:42 / cg"
+ "Modified: / 10.11.1998 / 22:04:59 / cg"
+!
+
+readConstant_Integer
+ |value|
+
+ value := inStream nextLongMSB:msb.
+
+ Verbose ifTrue:[Transcript show:'integer; value= '; showCR:value].
+
+ ^ value
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/Alignable.class'
+ "
+
+ "Modified: 15.4.1996 / 15:42:16 / cg"
+ "Created: 15.4.1996 / 16:34:42 / cg"
+!
+
+readConstant_InterfaceMethodref
+ |class_index name_and_type_index|
+
+ class_index := inStream nextUnsignedShortMSB:msb.
+ name_and_type_index := inStream nextUnsignedShortMSB:msb.
+
+ Verbose ifTrue:[Transcript show:'methodref; classindex= '; showCR:class_index].
+ Verbose ifTrue:[Transcript show:'methodref; name&typeindex= '; showCR:name_and_type_index].
+
+ ^ JavaUnresolvedInterfaceMethodrefConstant
+ pool:constants
+ poolIndex:constSlot
+ classIndex:class_index
+ nameandTypeIndex:name_and_type_index
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ "
+
+ "Created: 15.4.1996 / 15:22:37 / cg"
+ "Modified: 15.4.1996 / 16:07:19 / cg"
+!
+
+readConstant_Long
+ |high low value|
+
+ high := inStream nextUnsignedLongMSB:msb.
+ low := inStream nextUnsignedLongMSB:msb.
+
+ value := (high bitShift:32) bitOr:low.
+ (high bitTest:16r80000000) ifTrue:[
+ value := value - 16r10000000000000000.
+ ].
+ constNeeds2Slots := true.
+
+ Verbose ifTrue:[Transcript show:'long; value= '; showCR:value].
+ ^ value
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/Alignable.class'
+ "
+
+ "Modified: 15.4.1996 / 15:42:16 / cg"
+ "Created: 15.4.1996 / 16:34:42 / cg"
+!
+
+readConstant_Methodref
+ |class_index name_and_type_index|
+
+ class_index := inStream nextUnsignedShortMSB:msb.
+ name_and_type_index := inStream nextUnsignedShortMSB:msb.
+
+ Verbose ifTrue:[Transcript show:'methodref; classindex= '; showCR:class_index].
+ Verbose ifTrue:[Transcript show:'methodref; name&typeindex= '; showCR:name_and_type_index].
+
+ ^ JavaUnresolvedMethodrefConstant
+ pool:constants
+ poolIndex:constSlot
+ classIndex:class_index
+ nameandTypeIndex:name_and_type_index
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ "
+
+ "Created: 15.4.1996 / 15:22:37 / cg"
+ "Modified: 15.4.1996 / 16:07:19 / cg"
+!
+
+readConstant_NameAndType
+ |name_index signature_index|
+
+ name_index := inStream nextUnsignedShortMSB:msb.
+ signature_index := inStream nextUnsignedShortMSB:msb.
+
+ Verbose ifTrue:[Transcript show:'methodref; nameindex= '; showCR:name_index].
+ Verbose ifTrue:[Transcript show:'methodref; signatureindex= '; showCR:signature_index].
+
+ ^ JavaUnresolvedNameandTypeConstant
+ pool:constants
+ poolIndex:constSlot
+ nameIndex:name_index
+ signatureIndex:signature_index
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ "
+
+ "Created: 15.4.1996 / 15:23:43 / cg"
+ "Modified: 15.4.1996 / 16:17:16 / cg"
+!
+
+readConstant_String
+ |tag string_index chars jString|
+
+ string_index := inStream nextUnsignedShortMSB:msb.
+
+ Verbose ifTrue:[Transcript show:'string; index= '; showCR:string_index].
+
+ "/ resolve here if possible
+ string_index < constSlot ifTrue:[
+ Java java_lang_String notNil ifTrue:[
+ chars := (constants at:string_index).
+ chars isString ifFalse:[
+ self halt:'should not happen'
+ ].
+ jString := Java as_String:chars.
+ ^ jString.
+ ]
+ ].
+
+ ^ JavaUnresolvedStringConstant
+ pool:constants
+ poolIndex:constSlot
+ stringIndex:string_index
+
+ "
+ Verbose := true.
+ JavaClassReader readFile:'/phys/ibm3/java/lib/java/lang/System.class'
+ "
+
+ "Created: / 15.4.1996 / 15:20:33 / cg"
+ "Modified: / 7.5.1998 / 11:42:45 / cg"
+!
+
+readConstant_Unicode
+ |len string ascii|
+
+ len := inStream nextUnsignedShortMSB:msb.
+ string := TwoByteString new:len.
+ 1 to:len do:[:idx |
+ ascii := inStream nextUnsignedShortMSB:msb.
+ string at:idx put:(Character value:ascii).
+ ].
+
+ Verbose ifTrue:[Transcript show:'asciz; unicodeString= '; showCR:string].
+
+ ^ string
+!
+
+readConstant_Utf8
+ |len bytes string|
+
+ len := inStream nextUnsignedShortMSB:msb.
+ bytes := ByteArray new:len.
+ inStream nextBytes:len into:bytes startingAt:1.
+ string := CharacterArray fromJavaUTF8Bytes:bytes.
+
+ Verbose ifTrue:[Transcript show:'asciz; string= '; showCR:string].
+
+ ^ string
+
+ "Modified: / 19-10-2010 / 12:38:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!JavaClassReader methodsFor:'file reading - constants-ST'!
+
+readConstant_ST_Array
+ |aSize arr|
+
+ aSize := inStream nextUnsignedShortMSB:msb.
+ arr := Array new:aSize.
+
+ 1 to:aSize do:[:i |
+ |element_index element|
+
+ element_index := inStream nextUnsignedShortMSB:msb.
+ arr at:i put:element_index.
+ ].
+ Verbose ifTrue:[Transcript show:'array; size= '; showCR:aSize].
+
+ ^ JavaUnresolvedSTArrayConstant
+ pool:constants
+ poolIndex:constSlot
+ array:arr
+
+ "Created: / 7.5.1998 / 11:47:01 / cg"
+ "Modified: / 9.5.1998 / 00:25:34 / cg"
+!
+
+readConstant_ST_ByteArray
+ |aSize arr|
+
+ aSize := inStream nextUnsignedShortMSB:msb.
+ arr := ByteArray new:aSize.
+
+ 1 to:aSize do:[:i |
+ |element_index|
+
+ arr at:i put:(inStream nextByte).
+ ].
+ Verbose ifTrue:[Transcript show:'byteArray; size= '; showCR:aSize].
+
+ ^ arr
+
+ "Created: / 7.5.1998 / 11:47:12 / cg"
+!
+
+readConstant_ST_Character
+ |ascii|
+
+ ascii := inStream nextUnsignedShortMSB:msb.
+
+ Verbose ifTrue:[Transcript show:'char; ascii= '; showCR:ascii].
+ ^ Character value:ascii
+
+ "Created: / 7.5.1998 / 11:48:12 / cg"
+!
+
+readConstant_ST_Special
+ |type|
+
+ type := inStream nextUnsignedShortMSB:msb.
+ ^ #(
+ nil
+ true
+ false
+ ) at:(type + 1)
+
+ "Created: / 8.5.1998 / 23:06:56 / cg"
+ "Modified: / 9.5.1998 / 00:40:14 / cg"
+!
+
+readConstant_ST_String
+ |tag string_index chars|
+
+ string_index := inStream nextUnsignedShortMSB:msb.
+
+ Verbose ifTrue:[Transcript show:'string; index= '; showCR:string_index].
+
+ "/ resolve here if possible
+ string_index < constSlot ifTrue:[
+ chars := (constants at:string_index).
+ ^ chars
+ ].
+
+ ^ JavaUnresolvedSTStringConstant
+ pool:constants
+ poolIndex:constSlot
+ stringIndex:string_index
+
+ "Modified: / 7.5.1998 / 11:48:28 / cg"
+ "Created: / 7.5.1998 / 11:49:55 / cg"
+!
+
+readConstant_ST_Symbol
+ |tag string_index chars|
+
+ string_index := inStream nextUnsignedShortMSB:msb.
+
+ Verbose ifTrue:[Transcript show:'symbol; index= '; showCR:string_index].
+
+ "/ resolve here if possible
+ string_index < constSlot ifTrue:[
+ chars := (constants at:string_index).
+ chars isString ifFalse:[
+ self halt:'should not happen'
+ ].
+ ^ chars asSymbol
+ ].
+
+ ^ JavaUnresolvedSTSymbolConstant
+ pool:constants
+ poolIndex:constSlot
+ stringIndex:string_index
+
+ "Modified: / 7.5.1998 / 11:48:28 / cg"
+! !
+
+!JavaClassReader methodsFor:'file reading - fields'!
+
+readConstantValueAttributeFor:aField
+ |attribute_length constantvalue_index constantValue|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ constantvalue_index := inStream nextUnsignedShortMSB:msb.
+ constantValue := constants at:constantvalue_index.
+
+ aField constantValue:constantValue.
+
+ Verbose ifTrue:[Transcript show:'constantValue: '; showCR:constantValue].
+ ^ true
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/Alignable.class'
+ "
+
+ "Modified: 15.4.1996 / 15:33:28 / cg"
+ "Created: 15.4.1996 / 15:40:17 / cg"
+!
+
+readFieldInfofield
+ | access_flags name_index signature_index attributes_count field |
+
+ access_flags := inStream nextUnsignedShortMSB: msb.
+ name_index := inStream nextUnsignedShortMSB: msb.
+ signature_index := inStream nextUnsignedShortMSB: msb.
+ field := JavaField new.
+ field setAccessFlags: access_flags.
+ field setName: (constants at: name_index) asSymbol.
+ field setSignature: (constants at: signature_index) asSymbol.
+ field constantPool: constants.
+ attributes_count := inStream nextUnsignedShortMSB: msb.
+ Verbose
+ ifTrue:
+ [ Transcript
+ show: ' field name: ';
+ show: (constants at: name_index);
+ show: ' access: ';
+ show: access_flags;
+ show: ' attrib_cnt: ';
+ showCR: attributes_count ].
+ 1 to: attributes_count do: [:i | self readAttributeFor: field. ].
+ ^ field.
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'"
+
+ "Created: / 15-04-1996 / 15:38:43 / cg"
+ "Modified: / 15-10-1998 / 10:38:01 / cg"
+ "Modified: / 17-12-2010 / 18:44:30 / Marcel Hlopko <hlopik@gmail.com>"
+ "Modified: / 01-04-2011 / 11:38:36 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
+readFieldInfofields
+ |nFields fields|
+
+ "/
+ "/ get fieldInfos
+ "/
+ nFields := inStream nextUnsignedShortMSB:msb.
+ Verbose ifTrue:[Transcript show:'fieldsCount = '; showCR:nFields].
+
+ fields := Array new:nFields.
+
+ 1 to:nFields do:[:i |
+ Verbose ifTrue:[Transcript show:'field: '; showCR:i].
+ fields at:i put:(self readFieldInfofield)
+ ].
+ ^ fields
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ "
+
+ "Created: 15.4.1996 / 15:34:41 / cg"
+ "Modified: 15.4.1996 / 15:35:28 / cg"
+! !
+
+!JavaClassReader methodsFor:'file reading - interfaces'!
+
+readInterfaces
+ |interfacesCount interface_index interface interfaces|
+
+ "/
+ "/ get interfaces
+ "/
+ interfacesCount := inStream nextUnsignedShortMSB:msb.
+ Verbose ifTrue:[Transcript show:'interfacesCount = '; showCR:interfacesCount].
+
+ interfaces := Array new:interfacesCount.
+
+ 1 to:interfacesCount do:[:i |
+ Verbose ifTrue:[Transcript show:'interface: '; showCR:i].
+ interface_index := inStream nextUnsignedShortMSB:msb.
+ interface := constants at:interface_index.
+
+ interfaces at:i put:interface.
+ ].
+ ^ interfaces
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ "
+
+ "Created: 15.4.1996 / 15:31:59 / cg"
+ "Modified: 15.4.1996 / 15:33:28 / cg"
+! !
+
+!JavaClassReader methodsFor:'file reading - methods'!
+
+readCodeAttributeFor:aJavaMethod
+ |attribute_length max_stack max_locals code_length code
+ exception_table_length exception_table unknown1 unknown2|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ Verbose ifTrue:[Transcript show:'code_attribute_length: 0x'; showCR:(attribute_length printStringRadix:16)].
+
+ ((minorVsn > 2) or:[majorVsn > 45]) ifTrue:[
+ "/ should be:
+ max_stack := inStream nextUnsignedShortMSB:msb.
+ max_locals := inStream nextUnsignedShortMSB:msb.
+ code_length := inStream nextUnsignedLongMSB:msb.
+
+"/ unknown1 := inStream nextByte.
+"/ max_stack := inStream nextByte.
+"/ max_locals := inStream nextUnsignedShortMSB:msb.
+"/ unknown2 := inStream nextUnsignedShortMSB:msb.
+"/ code_length := inStream nextUnsignedShortMSB:msb.
+"/ Verbose ifTrue:[Transcript show:'?1: '; showCR:unknown1].
+"/ Verbose ifTrue:[Transcript show:'?2: '; showCR:unknown2].
+ ] ifFalse:[
+ max_stack := inStream nextByte.
+ max_locals := inStream nextByte.
+ code_length := inStream nextUnsignedShortMSB:msb.
+ ].
+
+ Verbose ifTrue:[
+ Transcript show:'code_length: '; showCR:(code_length printStringRadix:16).
+ Transcript show:'code at pos: '; showCR:inStream position
+ ].
+
+ code_length ~~ 0 ifTrue:[
+ code := ByteArray new:code_length.
+ inStream nextBytes:code_length into:code startingAt:1.
+ ].
+ Verbose ifTrue:[Transcript show:'method code: '; showCR:code.].
+
+ exception_table_length := inStream nextUnsignedShortMSB:msb.
+ Verbose ifTrue:[Transcript show:'exception_table_length: '; showCR:(exception_table_length printStringRadix:16)].
+ exception_table_length ~~ 0 ifTrue:[
+ Verbose ifTrue:[Transcript show:'exceptionTable length:'; showCR:exception_table_length.].
+
+ exception_table := Array new:exception_table_length.
+ 1 to:exception_table_length do:[:i |
+ |start_pc end_pc handler_pc catch_type|
+
+ start_pc := inStream nextUnsignedShortMSB:msb.
+ end_pc := inStream nextUnsignedShortMSB:msb.
+ handler_pc := inStream nextUnsignedShortMSB:msb.
+ catch_type := inStream nextUnsignedShortMSB:msb.
+ catch_type ~= 0 ifTrue:[
+ catch_type := constants at:catch_type.
+ ].
+ exception_table at:i put:(JavaExceptionTableEntry
+ startPC:start_pc
+ endPC:end_pc
+ handlerPC:handler_pc
+ catchType:catch_type).
+ ].
+ aJavaMethod setExceptionHandlerTable:exception_table.
+ ].
+
+ aJavaMethod
+ setCode:code
+ maxStack:max_stack
+ maxLocals:max_locals
+ u1:unknown1
+ u2:unknown2.
+
+ self readAttributesFor:aJavaMethod.
+ ^ true
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/Alignable.class'
+ "
+
+ "Created: / 15-04-1996 / 15:40:17 / cg"
+ "Modified: / 16-05-1998 / 01:39:42 / cg"
+ "Modified: / 17-12-2010 / 00:24:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+readExceptionsAttributeFor:aJavaMethod
+ |attribute_length exception_table_length exception_table|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ exception_table_length := inStream nextUnsignedShortMSB:msb.
+ exception_table_length ~~ 0 ifTrue:[
+ exception_table := Array new:exception_table_length.
+ 1 to:exception_table_length do:[:i |
+ |idx ex|
+
+ idx := inStream nextUnsignedShortMSB:msb.
+ ex := constants at:idx.
+ exception_table at:i put:ex.
+ ].
+ ].
+
+ Verbose ifTrue:[Transcript showCR:'method has an exceptionTable'].
+
+ aJavaMethod setExceptionTable:exception_table.
+ ^ true
+
+ "Modified: 15.4.1996 / 15:33:28 / cg"
+ "Created: 15.4.1996 / 15:40:17 / cg"
+!
+
+readLineNumberTableAttributeFor:aJavaMethod
+ |attribute_length line_number_table_length line_number_table|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ line_number_table_length := inStream nextUnsignedShortMSB:msb.
+ line_number_table_length ~~ 0 ifTrue:[
+ line_number_table := Array new:line_number_table_length.
+ 1 to:line_number_table_length do:[:i |
+ |start_pc line_number|
+
+ start_pc := inStream nextUnsignedShortMSB:msb.
+ line_number := inStream nextUnsignedShortMSB:msb.
+ line_number_table at:i put:(start_pc -> line_number).
+ ].
+ Verbose ifTrue:[Transcript showCR:'method has a lineNumberTable'].
+
+ aJavaMethod setLineNumberTable:line_number_table.
+ ].
+
+ ^ true
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/java/lang/Boolean.class'
+ "
+
+ "Created: / 15.4.1996 / 15:40:17 / cg"
+ "Modified: / 7.4.1998 / 19:08:42 / cg"
+!
+
+readLocalVariableTableAttributeFor:aJavaMethod
+ |attribute_length local_variable_table_length local_variable_table|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ local_variable_table_length := inStream nextUnsignedShortMSB:msb.
+ local_variable_table_length ~~ 0 ifTrue:[
+ local_variable_table := JavaLocalVariableTable new:local_variable_table_length.
+ 1 to:local_variable_table_length do:[:i |
+ |start_pc length name_index sig_index slot name signature|
+
+ start_pc := inStream nextUnsignedShortMSB:msb.
+ length := inStream nextUnsignedShortMSB:msb.
+ name_index := inStream nextUnsignedShortMSB:msb.
+ name := constants at:name_index.
+ sig_index := inStream nextUnsignedShortMSB:msb.
+ signature := constants at:sig_index.
+ slot := inStream nextUnsignedShortMSB:msb.
+
+ local_variable_table at:i put:(JavaLocalVariableTableEntry new
+ startPC:start_pc
+ length:length
+ name:name
+ signature:signature
+ slot:slot)
+ ].
+ ].
+
+ Verbose ifTrue:[Transcript showCR:'method has a localvariableTable'].
+
+ aJavaMethod setLocalVariableTable:local_variable_table.
+ ^ true
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/java/lang/Boolean.class'
+ "
+
+ "Modified: 15.4.1996 / 15:33:28 / cg"
+ "Created: 15.4.1996 / 15:40:17 / cg"
+!
+
+readMethodFor:aClass
+ |m access_flags name_index name signature_index signature
+ tooManyArgs|
+
+ "/
+ "/ get a method
+ "/
+ access_flags := inStream nextUnsignedShortMSB:msb.
+ name_index := inStream nextUnsignedShortMSB:msb.
+ signature_index := inStream nextUnsignedShortMSB:msb.
+
+ name := constants at:name_index.
+ signature := constants at:signature_index.
+
+ Verbose ifTrue:[
+ Transcript show:'method name:'; showCR:name.
+ Transcript show:'signature:'; showCR:signature.
+ ].
+
+ aClass isJavaClass ifTrue:[
+ (access_flags bitAnd:JavaMethod A_NATIVE) ~~ 0 ifTrue:[
+ m := JavaNativeMethod new.
+ ] ifFalse:[
+ m := JavaMethodWithHandler new.
+ ].
+ m setAccessFlags:access_flags.
+ tooManyArgs := false.
+ ArgumentError handle:[:ex |
+ 'JAVA: ***** java method has too many arguments - will fail to execute' infoPrintCR.
+ tooManyArgs := true.
+ ex proceed.
+ ] do:[
+ m setName:name signature:signature.
+ ].
+ m setJavaClass:aClass.
+
+ self readAttributesFor:m.
+
+ tooManyArgs ifTrue:[
+ m code:nil.
+ m byteCode:nil.
+ ].
+ (m exceptionHandlerTable isNil) ifTrue:[
+ m isNative ifFalse:[
+ m getExceptionTable isNil ifTrue:[
+ m := JavaMethod fromMethod:m
+ ] ifFalse:[
+ m := JavaMethodWithException fromMethod:m
+ ]
+ ]
+ ] ifFalse:[
+ m setAccessFlags:(m accessFlags bitOr:JavaMethod A_HASHANDLER)
+ ].
+ aClass addMethod:m name:name signature:signature.
+ ] ifFalse:[
+ m := Method new.
+ self readAttributesFor:m.
+ (access_flags bitTest:JavaMethod A_STATIC) ifTrue:[
+ aClass class primAddSelector:name asSymbol withMethod:m.
+ ] ifFalse:[
+ aClass primAddSelector:name asSymbol withMethod:m.
+ ]
+ ].
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ "
+
+ "Created: / 15-04-1996 / 16:48:49 / cg"
+ "Modified: / 25-09-1999 / 23:16:25 / cg"
+ "Modified: / 04-02-2011 / 23:07:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+readMethodsFor:aJavaClass
+ |methodsCount method|
+
+ "/
+ "/ get methods
+ "/
+ methodsCount := inStream nextUnsignedShortMSB:msb.
+ Verbose ifTrue:[Transcript show:'methodsCount = '; showCR:methodsCount].
+
+ 1 to:methodsCount do:[:i |
+ Verbose ifTrue:[Transcript show:'method: '; showCR:i].
+ method := self readMethodFor:aJavaClass
+ ].
+
+ "
+ JavaClassReader readFile:'/phys/ibm3/hotjava/classes/browser/AddButton.class'
+ "
+
+ "Created: / 15.4.1996 / 16:46:30 / cg"
+ "Modified: / 8.5.1998 / 21:20:59 / cg"
+! !
+
+!JavaClassReader methodsFor:'file reading - methods-ST'!
+
+readSTCodeAttributeFor:aSmalltalkMethod
+ |attribute_length max_stack max_locals code_length code
+ exception_table_length unknown1 unknown2|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ Verbose ifTrue:[Transcript show:'attribute_length: 0x'; showCR:(attribute_length printStringRadix:16)].
+
+ max_stack := inStream nextUnsignedShortMSB:msb.
+ max_locals := inStream nextUnsignedShortMSB:msb.
+
+ code_length := inStream nextUnsignedLongMSB:msb.
+ Verbose ifTrue:[Transcript show:'code_length: '; showCR:(code_length printStringRadix:16)].
+ Verbose ifTrue:[Transcript show:'code at pos: '; showCR:inStream position].
+
+ code_length ~~ 0 ifTrue:[
+ code := ByteArray new:code_length.
+ inStream nextBytes:code_length into:code startingAt:1.
+ ].
+ Verbose ifTrue:[Transcript show:'method code: '; showCR:code.].
+
+ exception_table_length := inStream nextUnsignedShortMSB:msb.
+ Verbose ifTrue:[Transcript show:'exception_table_length: '; showCR:(exception_table_length printStringRadix:16)].
+ exception_table_length ~~ 0 ifTrue:[
+ self error:'unexpected exceptionTable length'.
+ "/ skip it.
+ 1 to:exception_table_length do:[:i |
+ "start_pc :=" inStream nextUnsignedShortMSB:msb.
+ "end_pc :=" inStream nextUnsignedShortMSB:msb.
+ "handler_pc :=" inStream nextUnsignedShortMSB:msb.
+ "catch_type :=" inStream nextUnsignedShortMSB:msb.
+ ].
+ ].
+
+ aSmalltalkMethod byteCode:code.
+ aSmalltalkMethod stackSize:max_stack .
+ aSmalltalkMethod numberOfVars:max_locals.
+
+ self readAttributesFor:aSmalltalkMethod.
+ ^ true
+
+ "Modified: / 16.5.1998 / 01:39:30 / cg"
+!
+
+readSTLiteralsAttributeFor:aSmalltalkMethod
+ |attribute_length literal_table_length literal_table litIndex literal|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ literal_table_length := inStream nextUnsignedShortMSB:msb.
+ literal_table_length ~~ 0 ifTrue:[
+ literal_table := Array new:literal_table_length.
+ 1 to:literal_table_length do:[:i |
+ litIndex := inStream nextUnsignedShortMSB:msb.
+ literal := (constants at:litIndex).
+ literal_table at:i put:literal.
+ ].
+ ].
+ Verbose ifTrue:[Transcript show:'literals: '; showCR:literal_table storeString.].
+
+ "Created: / 7.5.1998 / 11:52:28 / cg"
+ "Modified: / 16.5.1998 / 01:52:27 / cg"
+!
+
+readSTMethodCategoryAttributeFor:aSmalltalkMethod
+ |attribute_length name_index name|
+
+ attribute_length := inStream nextUnsignedLongMSB:msb.
+
+ name_index := inStream nextUnsignedShortMSB:msb.
+ name := (constants at:name_index).
+
+ aSmalltalkMethod category:name.
+
+ "Modified: / 8.5.1998 / 20:39:59 / cg"
+ "Created: / 16.5.1998 / 01:04:19 / cg"
+! !
+
+!JavaClassReader class methodsFor:'documentation'!
+
+version
+ ^ '$Id$'
+!
+
+version_CVS
+ ^ '§Header: /home/jv/Projects/SmalltalkX/repositories/cvs/stx/libjava/JavaClassReader.st,v 1.92 2009/10/09 14:21:53 cg Exp §'
+!
+
+version_SVN
+ ^ '$Id$'
+! !
+
+JavaClassReader initialize!