src/Java.st
branchjk_new_structure
changeset 752 ff7bc6428c9c
child 754 a3d9edeb7d73
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Java.st	Fri Apr 08 12:02:36 2011 +0000
@@ -0,0 +1,1411 @@
+"
+ 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:#Java
+	instanceVariableNames:''
+	classVariableNames:'Classes UnresolvedClassRefs Release ClassPath SourceDirectories
+		JavaHome InternedStrings Java_lang_String Java_lang_Class
+		PrettyPrintStyle LastArgumentString Threads ExcludedClassPath
+		FailedToLoadClasses SourceCache SourceArchiveCache'
+	poolDictionaries:''
+	category:'Languages-Java-Support'
+!
+
+!Java 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.
+"
+
+
+!
+
+documentation
+"Java class is main entry point or - you might say -
+facade to the Java world inside Smalltalk. It also 
+serves as configuration entity - e.g. controlling 
+classpath, source paths, etc. Java class is responsible
+for correct initialization and glueing other classes.
+"
+! !
+
+!Java class methodsFor:'accessing'!
+
+classForName:aString
+    "return a javaClass - either existing or loaded"
+
+    |cls loader classURL|
+
+    cls := self at:aString.
+    cls isNil ifTrue:[
+        FailedToLoadClasses notNil ifTrue:[
+            (FailedToLoadClasses includes:aString) ifTrue:[
+"/                ('JAVA [info]: class loading already failed: ' , aString) infoPrintCR.
+                ^ nil
+            ]
+        ].
+
+        ('JAVA [info]: late class loading: ' , aString) infoPrintCR.
+        loader := JavaClassReader classLoaderQuerySignal query.
+        loader isNil ifTrue:[
+            "/ load using default (ST/X) loader
+            cls := JavaClassReader loadClass:aString.
+        ] ifFalse:[
+            "/ load using a Java class loader
+"/            classURL := Java as_URL:('file:' , aString , '.class').
+"/            loader loadClass:classURL.
+            loader perform:#'loadClass(Ljava/lang/String;)Ljava/lang/Class;'
+                with:(Java as_String:aString).
+
+            cls := self at:aString.
+        ].
+        cls isNil ifTrue:[
+            FailedToLoadClasses isNil ifTrue:[
+                FailedToLoadClasses := Set new.
+            ].
+            FailedToLoadClasses add:aString
+        ]
+    ].
+    ^ cls
+
+    "Created: / 18.3.1997 / 16:45:57 / cg"
+    "Modified: / 27.4.1998 / 15:00:52 / cg"
+!
+
+classNamed:aString
+    ^ self at:aString
+!
+
+intern:aJavaString
+    |stString internedString|
+
+    stString := self as_ST_String:aJavaString.
+    internedString := InternedStrings at:stString ifAbsent:nil.
+    internedString isNil ifTrue:[
+        InternedStrings at:stString put:aJavaString.
+        internedString := aJavaString
+    ].
+    ^ internedString
+!
+
+java_lang_Class
+    Java_lang_Class isNil ifTrue:[
+        Java_lang_Class := self at:'java.lang.Class'
+    ].
+    ^ Java_lang_Class
+
+    "Created: 26.3.1997 / 13:42:59 / cg"
+    "Modified: 26.3.1997 / 13:46:24 / cg"
+!
+
+java_lang_String
+    Java_lang_String isNil ifTrue:[
+        Java_lang_String := self at:'java.lang.String'
+    ].
+    ^ Java_lang_String
+
+    "Created: 26.3.1997 / 13:43:17 / cg"
+    "Modified: 26.3.1997 / 13:50:21 / cg"
+!
+
+prettyPrintStyle
+    ^ PrettyPrintStyle
+
+    "Created: 1.8.1997 / 10:37:57 / cg"
+!
+
+release
+
+    ^Release
+
+    "Created: / 22-11-2010 / 12:38:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+release: aJavaRelease
+
+    Release := aJavaRelease.
+
+    "
+        Java release: JavaRelease openJDK6. 
+        Java release: JavaRelease sunJDK6. 
+        
+    "
+
+    "Created: / 22-11-2010 / 12:38:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 30-11-2010 / 11:54:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+systemPropertyAt:key put:something
+    JavaVM systemProperties at:key put:something
+
+    "Created: / 9.1.1999 / 14:49:35 / cg"
+!
+
+threads
+    Threads isNil ifTrue:[
+        Threads := WeakIdentityDictionary new.
+    ].
+    ^ Threads
+
+    "Created: 26.8.1997 / 19:53:57 / cg"
+    "Modified: 26.8.1997 / 19:55:27 / cg"
+! !
+
+!Java class methodsFor:'accessing paths'!
+
+addToClassPath:aPath
+
+    | path |
+    path := aPath asFilename.
+
+    (aPath asString includes: $*) ifTrue:[
+        self addToClassPathFilesMatching: path baseName
+             in: path directoryName.
+    ] ifFalse:[
+        (ClassPath includes:aPath asString) ifFalse:[
+            ClassPath add:aPath asString.
+            FailedToLoadClasses := nil
+        ]
+    ]
+
+    "Created: / 01-08-1997 / 21:10:07 / cg"
+    "Modified: / 17-09-1998 / 20:43:55 / cg"
+    "Modified: / 20-12-2010 / 17:37:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+addToClassPathFilesMatching: pattern in: path
+
+    | dir |
+    dir := path asFilename.
+    dir directoryContents do:
+        [:fname|
+        (fname matches: pattern) ifTrue:
+            [| p |
+            p := (dir / fname) pathName.
+            (ClassPath includes:p) ifFalse:
+                [ClassPath add:p.
+                FailedToLoadClasses := nil]]].
+
+    "Created: / 20-12-2010 / 17:26:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+addToSourcePath:aPath
+    SourceDirectories ifNil:[SourceDirectories := OrderedCollection new].
+    (SourceDirectories includes:aPath) ifFalse:[
+        SourceDirectories add:aPath
+    ]
+
+    "Created: / 02-08-1997 / 14:12:31 / cg"
+    "Modified: / 06-02-2011 / 22:51:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+classPath
+    ^ ClassPath
+
+    "Created: 7.2.1997 / 19:23:45 / cg"
+    "Modified: 7.2.1997 / 19:23:55 / cg"
+!
+
+classPath:aCollectionOfPaths
+    ClassPath := aCollectionOfPaths asOrderedCollection.
+    FailedToLoadClasses := nil
+
+    "Created: / 7.2.1997 / 19:23:45 / cg"
+    "Modified: / 17.9.1998 / 20:44:09 / cg"
+!
+
+effectiveClassPath
+
+    | CLASSPATH |
+    CLASSPATH := ((OperatingSystem getEnvironment: 'CLASSPATH') ? '') 
+        tokensBasedOn: OperatingSystem pathSeparator.
+
+    ^
+        "for testing only"
+        Release classPath,
+        (Array 
+            with: ((Smalltalk packageDirectoryForPackageId:'stx:libjava') / 'java' / 'libjava-projects' / 'Conversion' / 'bin' ) pathName
+            with: ((Smalltalk packageDirectoryForPackageId:'stx:libjava') / 'java' / 'libjava-support' / 'bin' ) pathName
+        ),
+
+        (ClassPath ? #()),
+            CLASSPATH
+
+    "
+        Java effectiveClassPath
+    "
+
+    "Created: / 22-11-2010 / 13:03:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 17-01-2011 / 09:44:16 / kursjan <kursjan@fit.cvut.cz>"
+    "Modified: / 17-03-2011 / 13:33:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+effectiveSourceDirectories
+
+    ^Release sourcePath ,
+        (SourceDirectories ? #())
+
+    "
+        Java effectiveSourceDirectories 
+    "
+
+    "Created: / 30-11-2010 / 11:53:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+excludedClassPath
+    ^ ExcludedClassPath
+
+    "Modified: / 7.2.1997 / 19:23:55 / cg"
+    "Created: / 27.1.1998 / 21:57:13 / cg"
+!
+
+isExcludedFromClassPath:fileName
+    |nm|
+
+    nm := fileName asFilename pathName.
+    ExcludedClassPath do:[:excludedPath |
+        (nm startsWith:excludedPath) ifTrue:[^ true].
+    ].
+    ^ false
+
+    "Created: / 27.1.1998 / 22:00:40 / cg"
+!
+
+javaHome
+    ^ JavaHome ifNil:[Release javaHome]
+
+    "Created: / 06-08-1997 / 00:53:19 / cg"
+    "Modified: / 22-11-2010 / 12:39:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+javaHome:aPath
+
+    <resource: #obsolete>
+
+    self obsoleteMethodWarning: 'javaHome is now controlled by java release'.
+
+    JavaHome := aPath
+
+    "Created: / 06-08-1997 / 00:53:23 / cg"
+    "Modified: / 22-11-2010 / 12:40:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+newJavaHome:newJavaHome
+    self javaHome:newJavaHome.
+
+!
+
+removeFromClassPath:aPath
+    (ClassPath includes:aPath) ifTrue:[
+        ClassPath remove:aPath
+    ]
+
+    "Modified: 7.2.1997 / 19:23:55 / cg"
+    "Created: 1.8.1997 / 21:10:21 / cg"
+!
+
+removeFromSourcePath:aPath
+    (SourceDirectories includes:aPath) ifTrue:[
+        SourceDirectories remove:aPath
+    ]
+
+    "Modified: 7.2.1997 / 19:23:55 / cg"
+    "Created: 2.8.1997 / 14:13:01 / cg"
+!
+
+sourceDirectories
+    ^ SourceDirectories
+!
+
+sourceDirectories:aCollectionOfPaths
+    SourceDirectories := aCollectionOfPaths asOrderedCollection
+
+    "
+     Java
+        sourceDirectories:#(
+                            '/phys/ibm3/java/src'
+                           )
+    "
+
+
+!
+
+sourcePath
+    ^ SourceDirectories
+
+    "Created: / 16.1.1998 / 13:26:55 / cg"
+! !
+
+!Java class methodsFor:'change & update'!
+
+update: what with: param from: sender
+
+    what == #restarted ifTrue:[
+        self reinitialize.
+    ]
+
+    "Created: / 14-12-2010 / 21:00:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!Java class methodsFor:'class initialization'!
+
+initAllClasses
+    |system|
+
+    FailedToLoadClasses := nil.
+    self initAllStaticFields.
+
+    system := self classForName:'java.lang.System'.
+    system isInitialized ifFalse:[
+        self initSystemClass.
+    ].
+
+    self allClassesDo:[:cls |
+       cls isInitialized ifFalse:[
+           cls classInit
+       ]
+    ]
+
+     "
+      Java initAllClasses
+     "
+
+    "Modified: / 27.11.1998 / 00:33:05 / cg"
+!
+
+initAllStaticFields
+     self allClassesDo:[:cls |
+        cls initializeStaticFields
+     ]
+
+!
+
+initSystemClass
+    |system|
+
+    system := Java at:'java.lang.System'.
+    system isNil ifTrue:[
+"/        JavaVM initializeVM.
+"/        system := Java at:'java.lang.System'.
+"/        system isNil ifTrue:[
+        self warn:'JavaVM: no ''' , 'java.lang.System' allBold , ''' class.'.
+"/            self error:'no ''java.lang.System'' class'.
+            ^ self
+"/        ].
+    ].
+
+    system classInit.
+    (system implements:#'initializeSystemClass()V') ifTrue:[
+        system perform: "invokeStatic:" #'initializeSystemClass()V'.
+    ].
+
+    "
+     Java initSystemClass
+
+     (Java at:'java.lang.System') 
+        perform:#'getProperty(Ljava/lang/String;)Ljava/lang/String;'
+        with:(Java as_String:'java.home')
+    "
+
+    "Modified: / 10.11.1998 / 12:39:58 / cg"
+!
+
+initialize
+    JavaNativeMethod flushAllCachedNativeMethods.
+
+    InternedStrings := Dictionary new.
+    FailedToLoadClasses := nil.
+
+    ClassPath := OrderedCollection new. 
+    ExcludedClassPath := OrderedCollection new.
+
+    SourceCache := CacheDictionary new: 32.
+    SourceArchiveCache := CacheDictionary new: 32.
+
+    self initializeRelease. "lazy initialization of Release"
+
+    self initializePrettyPrintStyle.
+
+    ObjectMemory addDependent: self.
+
+    "
+     Java flushAllJavaResources.   
+     Java initialize.
+     JavaVM initializeVM
+     Java classPath inspect
+    "
+
+    "Modified: / 06-11-2001 / 09:24:12 / cg"
+    "Created: / 03-10-2010 / 15:54:02 / Jan Kurs <kurs.jan@post.cz>"
+    "Modified: / 15-10-2010 / 17:37:20 / Jan Kurs <kurs.jan@post.cz>"
+    "Modified: / 10-02-2011 / 23:08:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+initializeForNewClassPath:directoriesToSearch
+    |jClasses jHome jSources|
+
+    jClasses := OrderedCollection new.
+
+    directoriesToSearch do:[:aPath | 
+        |dir libDir toAdd|
+
+        dir := aPath asFilename.
+        (jHome isNil and:[dir exists]) ifTrue:[
+            ((dir hasSuffix:'jar')
+            or:[dir hasSuffix:'zip']) ifTrue:[
+                toAdd := dir pathName.
+            ] ifFalse:[
+
+                "/ there must be either a classes directory,
+                "/ or a classes.zip file ...
+                (libDir := dir construct:'lib') exists ifTrue:[
+                    ((libDir construct:'classes') exists 
+                    and:[(libDir construct:'classes') isDirectory]) ifTrue:[
+                        jHome := aPath.
+                        toAdd := (libDir constructString:'classes').
+                    ] ifFalse:[
+                        (libDir construct:'classes.zip') exists ifTrue:[
+                            jHome := aPath.
+                            toAdd := (libDir constructString:'classes.zip').
+                        ] ifFalse:[
+                            (libDir construct:'rt.jar') exists ifTrue:[
+                                jHome := aPath.
+                                toAdd := (libDir constructString:'rt.jar').
+                            ].
+                            (libDir construct:'rt.zip') exists ifTrue:[
+                                jHome := aPath.
+                                toAdd := (libDir constructString:'rt.zip').
+                            ] 
+                        ]
+                    ]
+                ] ifFalse:[
+                    ((dir construct:'classes') exists 
+                    and:[(dir construct:'classes') isDirectory]) ifTrue:[
+                        jHome := aPath.
+                        toAdd := (dir constructString:'classes').
+                    ] ifFalse:[
+                        (dir construct:'classes.zip') exists ifTrue:[
+                            jHome := aPath.
+                            toAdd := (dir constructString:'classes.zip').
+                        ] ifFalse:[
+                            (dir construct:'rt.zip') exists ifTrue:[
+                                jHome := aPath.
+                                toAdd := (dir constructString:'rt.zip').
+                            ] 
+                        ]
+                    ]
+                ].
+            ].
+        ].
+        toAdd notNil ifTrue:[
+            Transcript showCR:'Adding to classPath: ' , toAdd.
+            jClasses add:toAdd.
+        ].
+    ].
+
+    self javaHome:jHome.
+    self classPath:(jClasses collect:[:f | f asFilename name]).
+    jHome isNil ifTrue:[
+        Transcript showCR:'no java home directory found'.
+    ] ifFalse:[
+        jHome := jHome asFilename.
+        Transcript showCR:'Found javaHome in: ' , jHome pathName.
+
+        (jSources := jHome construct:'source') exists ifFalse:[
+            (jSources := jHome construct:'src') exists ifFalse:[
+                (jSources := jHome construct:'sources') exists ifFalse:[
+                    (jSources := jHome construct:'src.zip') exists ifFalse:[
+                        jSources := nil.
+                    ]
+                ]
+            ]
+        ].
+
+        jSources isNil ifTrue:[
+            Transcript showCR:'no java source directory found'.
+        ] ifFalse:[
+            Transcript showCR:'Found javaSources in: ' , jSources pathName.
+            self sourceDirectories:(Array with:jSources pathName).
+        ].
+    ].
+
+    "
+     self initializeForNewClassPath:(Java classPath)
+     self initializeForNewClassPath:(Array with:'/home/java/jdk113')
+    "
+
+    "Modified: / 03-10-2010 / 15:49:02 / Jan Kurs <kurs.jan@post.cz>"
+    "Modified: / 19-10-2010 / 10:49:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+initializePrettyPrintStyle
+    PrettyPrintStyle := IdentityDictionary new.
+    PrettyPrintStyle  at:#accessAttribute put:(#color -> (Color red:0 green:0 blue:25)).
+    PrettyPrintStyle  at:#className       put:(Array with:(#color -> Color black) with:#bold).
+    PrettyPrintStyle  at:#methodName      put:(Array with:(#color -> Color black) with:#bold).
+    PrettyPrintStyle  at:#code            put:(#color -> Color black).
+
+
+     "
+      Java initializePrettyPrintStyle
+     "
+
+    "Created: 1.8.1997 / 11:08:43 / cg"
+    "Modified: 1.8.1997 / 11:09:58 / cg"
+!
+
+initializeRelease
+
+    Release ifNil:[Release := JavaRelease any].
+
+    "
+        Release := nil. 
+        self initializeRelease.
+        Release
+    "
+
+    "Created: / 22-11-2010 / 13:41:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+reinitAllClasses
+     self markAllClassesUninitialized.
+     self initAllClasses
+
+     "
+      Java reinitAllClasses
+     "
+
+    "Modified: / 4.1.1998 / 00:34:29 / cg"
+!
+
+reinitialize
+    "/ all JavaThreads are lost on a restart (for now)
+
+    FailedToLoadClasses := nil.
+    Threads := nil.
+
+    "Kludge"
+    JavaMethod reinitialize.
+    JavaMethodWithException reinitialize.    
+    JavaMethodWithHandler reinitialize.
+    JavaNativeMethod reinitialize.
+    JavaNativeMethod flushAllCachedNativeMethods.
+
+
+    "
+     Java reinitialize
+    "
+
+    "Created: / 26-08-1997 / 20:07:00 / cg"
+    "Modified: / 27-04-1998 / 14:57:23 / cg"
+    "Modified: / 14-12-2010 / 21:30:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+startupJavaSystem
+    |javaEventThread haveEventThread haveScreenUpdater|
+
+    FailedToLoadClasses := nil.
+
+    "/
+    "/ check if already running
+    "/
+
+    haveEventThread := true.
+    javaEventThread := JavaVM javaEventThread.
+    (javaEventThread isNil or:[javaEventThread isDead]) ifTrue:[
+        haveEventThread := false
+    ].
+
+    haveScreenUpdater := false.
+    haveEventThread ifTrue:[
+        self threads do:[:aJavaThread |
+            aJavaThread name = 'JAVA-Screen Updater' ifTrue:[
+                aJavaThread isDead ifFalse:[
+                    "/ already running
+                    haveScreenUpdater := true
+                ]
+            ]
+        ].
+    ].
+
+    (haveEventThread and:[haveScreenUpdater]) ifTrue:[
+        ^ self
+    ].
+
+    JavaClass orderOfClassInits isNil ifTrue:[
+        "/ the very first start ...
+        'JAVA [info]: (re)initializing JAVA environment completely ...' infoPrintCR.
+
+        JavaVM initializeVM.
+    ] ifFalse:[
+        JavaVM initializeVMIfNoEventThreadRunning
+    ].    
+    'JAVA [info]: done JAVA initialization.' infoPrintCR.
+
+    "
+     Java startupJavaSystem
+    "
+
+    "Modified: / 24.12.1999 / 01:37:49 / cg"
+!
+
+terminateAllThreads
+    |myself threadsToKill|
+
+    Threads isNil ifTrue:[
+        ^ self
+    ].
+
+    myself := Processor activeProcess.
+
+    threadsToKill := IdentitySet new.
+    Threads do:[:aJavaThread |
+        aJavaThread ~~ myself ifTrue:[
+            (aJavaThread isNil or:[aJavaThread == 0]) ifFalse:[
+                (aJavaThread isMemberOf:JavaProcess) ifTrue:[
+                    aJavaThread isDead ifFalse:[
+                        threadsToKill add:aJavaThread
+                    ]
+                ]
+            ]
+        ]
+    ].
+    threadsToKill do:[:aThread |
+aThread == JavaVM javaScreenUpdaterThread ifTrue:[self halt].
+aThread == JavaVM javaEventQueueThread ifTrue:[self halt].
+        aThread terminate
+    ].
+    Threads := nil.
+
+    "
+     Java terminateAllThreads
+    "
+
+    "Created: / 26.8.1997 / 19:57:40 / cg"
+    "Modified: / 24.12.1999 / 02:34:53 / cg"
+! !
+
+!Java class methodsFor:'enumerating'!
+
+allClasses
+    ^ Classes ? #()
+
+    "
+    |if|
+
+    if := Java at:'java.awt.GraphicsEnvironment'.
+    Java allClasses select:[:aClass |
+                                aClass hasInterface:if
+                            ]
+    "
+
+    "Modified: / 28.1.1998 / 01:42:04 / cg"
+!
+
+allClassesDo:aBlock
+    Classes notNil ifTrue:[
+        Classes do:aBlock
+    ]
+! !
+
+!Java class methodsFor:'object conversions'!
+
+as_Float:aNumber
+    "convert an ST-float into a Java Float"
+
+    |i|
+
+    i := (Java at:'java.lang.Float') new.
+    i perform:#'<init>(F)V' with:(aNumber asShortFloat).
+    ^ i
+
+    "
+     Java as_Float:1
+     Java as_Float:3.14159
+    "
+
+    "Created: 7.8.1997 / 21:21:13 / cg"
+    "Modified: 7.8.1997 / 21:22:05 / cg"
+!
+
+as_Hashtable:aDictionary
+    "given a smalltalk dictionary, create and return
+     a Java hashTable for it"
+
+    |hashTable|
+
+    hashTable := (self classForName:'java.util.Hashtable') new.
+    aDictionary keysAndValuesDo:[:k :v |
+        |sk sv jk jv|
+
+        (sk := k) isSymbol ifTrue:[
+            sk := sk asString
+        ].
+        (sv := v) isSymbol ifTrue:[
+            sv := sv asString
+        ].
+        jk := self as_Object:sk.
+        jv := self as_Object:sv.
+
+        hashTable 
+            perform:#'put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;'    
+            with:jk
+            with:jv.
+    ].
+    ^ hashTable
+
+    "
+     Java as_Hashtable:(Dictionary new
+                           at:'hello' put:'Hallo';
+                           at:'world' put:'Welt';       
+                           yourself)
+    "
+
+    "Modified: / 14.1.1998 / 17:02:13 / cg"
+!
+
+as_Integer:anInteger
+    "convert an ST-integer into a Java Integer"
+
+    |i|
+
+    i := (Java at:'java.lang.Integer') new.
+    i perform:#'<init>(I)V' with:anInteger.
+    ^ i
+
+    "
+     Java as_Integer:1
+    "
+
+    "Modified: 7.8.1997 / 21:19:37 / cg"
+    "Created: 7.8.1997 / 21:21:13 / cg"
+!
+
+as_Object:anObject
+    "convert an ST-Object into a Java Object"
+
+    anObject isString ifTrue:[
+        ^ self as_String:anObject
+    ].
+    anObject isInteger ifTrue:[
+        ^ self as_Integer:anObject
+    ].
+
+    self halt.
+
+    "
+     Java as_Object:'hello world'
+    "
+
+    "Created: 7.8.1997 / 21:15:38 / cg"
+    "Modified: 7.8.1997 / 21:20:07 / cg"
+!
+
+as_ST_String: aJavaString 
+    "hard-coding internas of java.lang.String here is bad ..."
+    
+    | str  count  offs  start  stop |
+
+    aJavaString isNil ifTrue: [ ^ nil ].
+    
+    "/ count := aJavaString instVarNamed:'count'.
+    
+    count := aJavaString instVarAt: 3.
+    
+    "/ str := aJavaString instVarNamed:'value'
+    
+    str := aJavaString instVarAt: 1.
+    str size == count 
+        ifTrue: 
+            [ "cos I don't see any reason to do this"
+            "/ ^ str asOneByteString.
+            ^ str asOneByteString. ].
+    
+    "/ offs := (aJavaString instVarNamed:'offset').
+    
+    offs := aJavaString instVarAt: 2.
+    
+    "/ start := offs + 1.
+    
+    start := offs + 1.
+    
+    "/ stop := start + (aJavaString instVarNamed:'count') - 1.
+    
+    stop := start + count - 1.
+    
+    "/ ^ ((aJavaString instVarNamed:'value') copyFrom:start to:stop) asString
+    
+    ^ (str copyFrom: start to: stop) asOneByteString
+
+    "Created: / 08-08-1997 / 12:02:55 / cg"
+    "Modified: / 04-01-1999 / 23:55:08 / cg"
+    "Modified: / 22-03-2011 / 17:21:19 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
+as_String:aString
+    "convert an ST-String into a Java String"
+
+    "hard-coding internas of java.lang.String here is bad ..."
+
+    |s|
+
+    s := Java_lang_String basicNew.
+    s instVarNamed:'value'  put: aString.
+    s instVarNamed:'offset' put: 0.
+    s instVarNamed:'count'  put: aString size.
+    s instVarNamed:'hash'   put: 0.
+    ^ s
+
+    "
+     Java as_String:'hello world'
+    "
+
+    "Created: / 07-08-1997 / 21:15:49 / cg"
+    "Modified: / 03-02-2011 / 23:33:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+as_URL:aString
+    "convert an ST-String into a Java String"
+
+    "hard-coding internas of java.lang.String here is bad ..."
+
+    |u s|
+
+    s := aString.
+
+    "/ kludge for volume
+    OperatingSystem isMSDOSlike ifTrue:[
+        ((s size > 1) and:[(s at:2) == $:]) ifTrue:[
+            s := 'file:' , (s copy at:2 put:$|)
+        ]
+    ].
+    u := (self at:'java.net.URL') newCleared.
+    u perform:#'<init>(Ljava/lang/String;)V' with:(self as_String:s).
+    ^ u
+
+    "
+     Java as_URL:'http://www.altavista.com'
+     Java as_URL:'file:/foo/bar'
+    "
+
+    "Created: / 7.8.1997 / 21:15:49 / cg"
+    "Modified: / 25.9.1999 / 22:22:21 / cg"
+! !
+
+!Java class methodsFor:'queries'!
+
+smalltalkClassFor:typeRef
+self halt.
+"/    (typeString startsWith:'[[') ifTrue:[
+"/        ^ Array
+"/    ].
+"/    (typeString startsWith:'[F') ifTrue:[
+"/        ^ FloatArray
+"/    ].
+    self halt.
+
+    "Modified: 7.4.1997 / 13:33:46 / cg"
+!
+
+smalltalkDerefType:typeString
+    (typeString startsWith:'[') ifTrue:[
+        ^ typeString copyFrom:2
+    ].
+    self halt.
+
+    "Modified: 7.4.1997 / 13:13:24 / cg"
+! !
+
+!Java class methodsFor:'registering java classes'!
+
+at:aJavaName
+    "search & return for a class by name;
+     if there is no such class, return nil.
+     The argument, aJavaName may be either an internal name
+     (sep'd by slashes) or an external name (sep'd by periods).
+     The 'java/lang' standard packages prefix may be ommitted."
+
+    |sym nm cls|
+
+    Classes isNil ifTrue:[^ nil].
+
+    sym := aJavaName asSymbolIfInterned.
+    sym notNil ifTrue:[
+        cls := Classes at:sym ifAbsent:nil.
+        cls notNil ifTrue:[^ cls].
+    ].
+
+    nm := aJavaName.
+    (nm includes:$.) ifTrue:[
+        nm := (nm asString copyReplaceAll:$. with:$/).
+        sym := nm asSymbolIfInterned.
+        sym notNil ifTrue:[
+            cls := Classes at:sym ifAbsent:nil.
+            cls notNil ifTrue:[^ cls].
+        ].
+    ].
+        
+    (nm includes:$/) ifFalse:[
+        "/
+        "/ try java.lang.Foo
+        "/
+        nm := 'java/lang/' , nm.
+        sym := nm asSymbolIfInterned.
+        sym notNil ifTrue:[
+            cls := Classes at:sym ifAbsent:nil.
+            cls notNil ifTrue:[^ cls].
+        ].
+    ].
+
+    ^ nil
+
+    "
+     Java at:'java/lang/String' 
+     Java at:'java.lang.String'
+     Java at:'String'          
+     Java at:'System'            
+     Java at:'Foo'               
+    "
+
+    "Modified: / 18.7.1998 / 22:55:16 / cg"
+!
+
+at:aJavaName put:aJavaClass
+    |nameSymbol oldClass|
+
+    Classes isNil ifTrue:[
+        Classes := IdentityDictionary new.
+    ].
+
+    nameSymbol := aJavaName asSymbol.
+    (Classes includesKey:nameSymbol) ifTrue:[
+        oldClass := Classes at:nameSymbol.
+        oldClass == aJavaClass ifTrue:[
+            ^ self
+        ].
+        ('JAVA: class ' , aJavaName , ' is already loaded') infoPrintCR.
+        self updateClassRefsFrom:oldClass to:aJavaClass.
+    ].
+
+    Classes at:nameSymbol put:aJavaClass.
+    nameSymbol == #'java/lang/String' ifTrue:[
+        Java_lang_String := aJavaClass
+    ].
+
+"/    UnresolvedClassRefs notNil ifTrue:[
+"/        UnresolvedClassRefs do:[:toResolve |
+"/        ]
+"/    ].
+
+    self changed:#classes
+
+    "Created: 17.4.1996 / 23:29:31 / cg"
+    "Modified: 7.8.1997 / 19:15:58 / cg"
+!
+
+flushAllJavaResources
+    self flushClasses.
+
+    SourceCache := CacheDictionary new: 32.
+    SourceArchiveCache := CacheDictionary new: 32.
+
+    ObjectMemory allObjectsDo:[:someObject |
+        someObject isBehavior ifTrue:[
+            someObject isJavaClass ifTrue:[
+                someObject setConstantPool:nil.
+                someObject setInterfaces:nil.
+                someObject setMethodDictionary:(MethodDictionary new).
+                'JAVA [info]: flushing ' print. someObject fullName printCR.
+            ]
+        ].
+"/        (someObject isKindOf:JavaMethod) ifTrue:[
+"/            someObject setJavaClass:nil.
+"/            someObject setExceptionTable:nil.
+"/        ].
+        (someObject isMemberOf:JavaUnresolvedClassConstant) ifTrue:[
+            someObject constantPool:nil
+        ].
+    ].
+    JavaClass flushClassesInitOrder.
+
+    self flushClasses
+
+    "
+     Java flushAllJavaResources
+    "
+
+    "Modified: / 06-11-2001 / 09:49:37 / cg"
+    "Modified: / 10-02-2011 / 23:08:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+flushClasses
+    Classes := UnresolvedClassRefs := nil.
+    Smalltalk keys copy do:[:aKey | 
+        (aKey startsWith:'JAVA::') ifTrue:[ Smalltalk removeKey:aKey ]
+    ].
+    Smalltalk removeKey:#'JAVA'.
+
+    Java_lang_String := Java_lang_Class := nil.
+    JavaVM releaseAllJavaResources.
+    JavaUnresolvedConstant flushPatchLists.
+    Debugger == DebugView ifTrue:[Debugger newDebugger].
+    ObjectMemory flushCaches.
+
+    "
+     Java flushClasses
+    "
+
+    "Modified: / 6.11.2001 / 09:47:49 / cg"
+!
+
+markAllClassesUninitialized
+    self allClassesDo:[:aJavaClass |
+        aJavaClass markUninitialized
+    ].
+
+    "
+     Java markAllClassesUninitialized
+    "
+!
+
+rememberUnresolved:anUnresolvedClassRef
+    ('JAVA: remember unresolved class: ' , anUnresolvedClassRef fullName) infoPrintCR.
+
+    UnresolvedClassRefs isNil ifTrue:[
+        UnresolvedClassRefs := Dictionary new.
+    ].
+    UnresolvedClassRefs 
+        at:anUnresolvedClassRef fullName
+        put:anUnresolvedClassRef
+
+    "Created: / 18.4.1996 / 00:05:31 / cg"
+    "Modified: / 19.10.1998 / 20:57:44 / cg"
+!
+
+removeClass:aJavaClass
+    "/ remove it from myself
+
+    |javaName sym nm cls p ns|
+
+    javaName := aJavaClass fullName.
+
+    sym := javaName asSymbolIfInterned.
+    sym notNil ifTrue:[
+        cls := Classes at:sym ifAbsent:nil.
+    ].
+    cls isNil ifTrue:[
+        nm := javaName.
+        (nm includes:$.) ifTrue:[
+            "/
+            "/ try pckg/.../name
+            "/
+            nm := (nm asString copyReplaceAll:$. with:$/).
+            sym := nm asSymbolIfInterned.
+            sym notNil ifTrue:[
+                cls := Classes at:sym ifAbsent:nil.
+            ].
+        ].
+    ].
+    (cls notNil and:[cls == aJavaClass]) ifTrue:[
+        Classes removeKey:sym.
+        self updateClassRefsFrom:aJavaClass to:nil.
+    ].
+    Smalltalk removeKey:('JAVA::' , javaName) asSymbol.
+    Smalltalk removeKey:javaName asSymbol.
+    Smalltalk removeKey:((javaName , '') copy replaceAll:$/ with:$.) asSymbol.
+
+    "/ remove myself from the JAVA::-::-:: namespace
+    "/ (which exists for convenient smalltalk access only)
+
+    p := aJavaClass nameSpacePath.
+    p knownAsSymbol ifTrue:[
+        ns := Smalltalk at:p asSymbol.
+        (ns notNil and:[ns isNameSpace]) ifTrue:[
+            Smalltalk removeKey:(p , '::' , aJavaClass lastName) asSymbol
+        ]
+    ].
+
+    "Modified: / 19.10.1998 / 20:58:49 / cg"
+!
+
+unresolvedClassRefFor:aClassName
+    UnresolvedClassRefs isNil ifTrue:[^ nil].
+    ^ UnresolvedClassRefs at:aClassName ifAbsent:nil.
+
+    "Modified: / 19.10.1998 / 20:56:46 / cg"
+!
+
+updateClassRefsFrom:oldClass to:newClass
+    "update all references to oldClass to now refer to newClass.
+     sent, when a class is reloaded"
+
+    newClass notNil ifTrue:[
+        "/
+        "/ kludge: the new class might have been resolved with the oldClass ...
+        "/
+        newClass constantPool 
+            updateClassRefsFrom:oldClass to:newClass.
+    ].
+
+    self allClassesDo:[:aJavaClass |
+        aJavaClass updateClassRefsFrom:oldClass to:newClass
+    ].
+
+    "Created: 26.3.1997 / 13:49:20 / cg"
+    "Modified: 12.8.1997 / 03:04:44 / cg"
+! !
+
+!Java class methodsFor:'source management'!
+
+classSource:filename package:package in:dirOrZipFile 
+    |fn zar f |
+
+    fn := dirOrZipFile asFilename.
+    fn isDirectory 
+        ifTrue:
+            [ package notNil 
+                ifTrue:[ (f:= fn / package / filename) exists ifTrue:[ ^ f contents asString ]. ].
+            (f := fn / filename) exists ifTrue:[ ^ f contents asString ]. ]
+        ifFalse:
+            [ (dirOrZipFile last == $p and: [fn hasSuffix:'zip'])
+                ifTrue:
+                    [ zar := SourceArchiveCache 
+                                at: dirOrZipFile 
+                                ifAbsentPut:[ZipArchive oldFileNamed:fn pathName].
+                    zar notNil 
+                        ifTrue:
+                            [   package notNil 
+                                ifTrue:[ 
+                                    OperatingSystem fileSeparator ~~ $/ ifTrue: [ 
+                                        f := (package copyReplaceAll: OperatingSystem fileSeparator with: $/) , '/' , filename
+                                    ] ifFalse:[
+                                        f := package , '/' , filename.
+                                    ]]                                
+                                ifFalse:[ f := filename].
+                            (zar findMember: f) ifNotNil:
+                                [          
+                                    "Kludge because of broken ZipArchive"
+                                    |  cache |
+                                    cache := Filename homeDirectory / '.smalltalk' / 'javax' / Release name / 'src'.
+                                    cache exists ifFalse:[cache recursiveMakeDirectory].
+                                    (cache / f) exists ifTrue:[^(cache / f) contents asString].
+                                    OperatingSystem 
+                                        executeCommand:('unzip "%1" "%2"' bindWith: fn asAbsoluteFilename asString 
+                                                            with: f asString)
+                                        inDirectory: cache asString.
+                                    (f := cache / f) exists ifTrue:[^f contents asString]
+                                ]
+                            ]]].            
+
+    ^ nil
+
+    "
+        Java classSource: 'Object.java' package:'java/lang' in:'/home/jv/Projects/JavaX/java-6-openjdk/src'
+        Java classSource: 'Object.java' package:'java/lang' in:'/usr/lib/jvm/java-6-openjdk/src.zip'
+
+    "
+
+    "Modified: / 29-03-1998 / 21:46:40 / cg"
+    "Created: / 30-11-2010 / 12:32:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 01-04-2011 / 22:31:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+classSourceOf:aClass
+    |package dirName binary sourceFileName sourceFile loader codeBaseURL protocol codeBaseURLIdx src|
+
+    aClass isNil ifTrue:[
+        ^ nil
+    ].
+    "/ look at the cache"
+    SourceCache at: aClass ifPresent: [:src|^src].
+
+    "/ first, look in the directory, where the binary
+    "/ was loaded from.
+
+    binary := aClass binaryFile.
+    binary notNil ifTrue:[
+        binary := binary asFilename.
+        aClass sourceFile notNil ifTrue:[
+            sourceFileName := binary directory constructString:(aClass sourceFile).
+            sourceFileName asFilename exists ifFalse:[
+                sourceFileName := nil.
+            ]
+        ].
+        sourceFileName isNil ifTrue:[
+            sourceFileName := binary withSuffix:'java'.
+        ].
+        sourceFile := sourceFileName asFilename.
+    ] ifFalse:[
+        "/ maybe it was loaded by a java classLoader ...
+        (loader := aClass classLoader) notNil ifTrue:[
+            codeBaseURLIdx := loader class instVarOffsetOf:'codeBaseURL'.
+            codeBaseURLIdx notNil ifTrue:[
+                (codeBaseURL := loader instVarAt:codeBaseURLIdx) notNil ifTrue:[
+                    (protocol := codeBaseURL instVarNamed:'protocol') notNil ifTrue:[
+                        (Java as_ST_String:protocol) = 'file' ifTrue:[
+                            dirName := Java as_ST_String:(codeBaseURL instVarNamed:'file').
+                            dirName := dirName asFilename.
+                            dirName exists ifTrue:[
+                                aClass sourceFile notNil ifTrue:[
+                                    sourceFile := sourceFileName := dirName construct:aClass sourceFile.
+                                ]
+                            ]
+                        ]
+                    ]
+                ]
+            ]
+        ]
+    ].
+    sourceFile notNil ifTrue:[
+        sourceFile exists ifFalse:[
+            binary notNil ifTrue:[
+                sourceFileName := binary withSuffix:'jav'.
+                sourceFile := sourceFileName asFilename.
+                sourceFile exists ifFalse:[
+                    sourceFileName := binary withSuffix:'JAV'.
+                    sourceFile := sourceFileName asFilename.
+                    sourceFile exists ifFalse:[
+                        sourceFileName := binary withSuffix:'JAVA'.
+                        sourceFile := sourceFileName asFilename.
+                    ].
+                ].
+            ]
+        ].
+    ].
+
+    "/ special case: there were multiple classes in a single
+    "/ source file.
+
+    (binary notNil and:[aClass sourceFile notNil]) ifTrue:[
+        binary withoutSuffix baseName ~= aClass sourceFile asFilename withoutSuffix baseName ifTrue:[
+            'JAVA: trouble extracting fileName: ' infoPrint.
+            binary withoutSuffix baseName print. ' vs. ' infoPrint.
+            aClass sourceFile asFilename withoutSuffix baseName infoPrintCR.
+        ].
+    ].
+
+    "/ if that fails, look in standard places
+
+    (sourceFile isNil or:[sourceFile exists not]) ifTrue:[
+        sourceFile := aClass sourceFile.
+        package := aClass javaPackageAsDirname.
+        self effectiveSourceDirectories do:[:dir|
+            src := self classSource: sourceFile package: package in: dir.
+            src ifNotNil:[^src]
+        ]
+
+
+    ].
+    sourceFile isFilename ifFalse:[^nil].
+    ^ (sourceFile contentsOfEntireFile).
+
+    "
+        Java classSourceOf: JAVA::java::lang::Object
+    "
+
+    "Modified: / 27-01-1999 / 20:40:30 / cg"
+    "Modified: / 10-02-2011 / 23:10:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!Java class methodsFor:'starting apps'!
+
+javaProcessForMainOf:aJavaClass
+    "ask for a commandLine, create a java process to invoke
+     its main and return it. The process is not scheduled for
+     execution."
+
+    ^ self javaProcessForMainOf:aJavaClass argumentString:nil
+
+    "Modified: / 30.12.1998 / 20:24:25 / cg"
+!
+
+javaProcessForMainOf:aJavaClass argumentString:argStringIn
+    "create a java process, ready to invoke the classes main
+     method. Returns the process - ready to run but not yet resumed"
+
+    |p argStringArray argString stdInReplacement alreadyAskedForStdin|
+
+    argString := argStringIn.
+    argString isNil ifTrue:[
+        argString := Dialog 
+                    request:'argument string:' 
+                    initialAnswer:LastArgumentString ? ''
+                    onCancel:nil.
+        argString isNil ifTrue:[^ nil].
+
+        LastArgumentString := argString.
+    ].
+
+    JavaVM initializeVMIfNoEventThreadRunning.
+    (Java at:'java.lang.System') instVarNamed:'security' put:nil.
+
+    argString isEmpty ifTrue:[
+        argStringArray := #()
+    ] ifFalse:[
+        argStringArray := argString asCollectionOfWords collect:[:s | Java as_String:s] as:Array.
+    ].
+
+    p := JavaProcess 
+            for:[
+                    "/ if the program reads from stdin, let user provide a file
+                    "/ for it.
+                    JavaVM stdinReplacementFileQuerySignal handle:[:ex |
+                        |fn|
+
+                        alreadyAskedForStdin == true ifFalse:[
+                            fn := Dialog 
+                                    requestFileName:'Program reads from Stdin - give inputFile or cancel for EOF'
+                                    default:nil
+                                    fromDirectory:(FileSelectionBox lastFileSelectionDirectory).
+                            fn notNil ifTrue:[
+                                stdInReplacement := fn asFilename readStream.
+                            ].
+                            alreadyAskedForStdin := true.
+                        ].
+                        ex proceedWith:stdInReplacement
+                    ] do:[
+                        aJavaClass 
+                            performStatic:#'main([Ljava/lang/String;)V'
+                            with:argStringArray.
+                    ]
+                ]
+            priority:(Processor activePriority - 1).
+
+    p name:(aJavaClass fullName , '::main()').
+    p restartable:true.
+    ^ p
+
+    "Created: / 15.8.1997 / 04:41:20 / cg"
+    "Modified: / 24.12.1999 / 01:50:21 / cg"
+! !
+
+!Java class methodsFor:'documentation'!
+
+version
+    ^ '$Id$'
+!
+
+version_SVN
+    ^ '$Id$'
+! !
+
+Java initialize!