@@ -58,55 +58,118 @@ struct JavaToSwift: ParsableCommand {
58
58
)
59
59
var input : String
60
60
61
+ /// Describes what kind of generation action is being performed by
62
+ /// Java2Swift.
63
+ enum GenerationMode {
64
+ /// Generate a configuration file given a Jar file.
65
+ case configuration( jarFile: String )
66
+
67
+ /// Generate Swift wrappers for Java classes based on the given
68
+ /// configuration.
69
+ case classWrappers( Configuration )
70
+ }
71
+
61
72
mutating func run( ) throws {
62
- var vmOptions : [ String ] = [ ]
63
- let classpath = classPathWithJarFile
64
- if !classpath. isEmpty {
65
- vmOptions. append ( " -cp " )
66
- vmOptions. append ( contentsOf: classpath)
73
+ // Determine the mode in which we'll execute.
74
+ let generationMode : GenerationMode
75
+ if jarFile {
76
+ generationMode = . configuration( jarFile: input)
77
+ } else {
78
+ let config = try JavaTranslator . readConfiguration ( from: URL ( filePath: input) )
79
+ generationMode = . classWrappers( config)
80
+ }
81
+
82
+ // Load all of the dependent configurations and associate them with Swift
83
+ // modules.
84
+ let dependentConfigs = try dependsOn. map { dependentConfig in
85
+ guard let equalLoc = dependentConfig. firstIndex ( of: " = " ) else {
86
+ throw JavaToSwiftError . badConfigOption ( dependentConfig)
87
+ }
88
+
89
+ let afterEqual = dependentConfig. index ( after: equalLoc)
90
+ let swiftModuleName = String ( dependentConfig [ ..< equalLoc] )
91
+ let configFileName = String ( dependentConfig [ afterEqual... ] )
92
+
93
+ let config = try JavaTranslator . readConfiguration ( from: URL ( filePath: configFileName) )
94
+
95
+ return ( swiftModuleName, config)
67
96
}
68
97
69
- let jvm = try JavaVirtualMachine . shared ( vmOptions: vmOptions)
70
- try run ( environment: jvm. environment ( ) )
98
+ // Form a class path from all of our input sources:
99
+ // * Command-line option --classpath
100
+ var classPathPieces : [ String ] = classpath
101
+ switch generationMode {
102
+ case . configuration( jarFile: let jarFile) :
103
+ // * Jar file (in `-jar-file` mode)
104
+ classPathPieces. append ( jarFile)
105
+ case . classWrappers( let config) :
106
+ // * Class path specified in the configuration file (if any)
107
+ config. classPath. map { classPathPieces. append ( $0) }
108
+ }
109
+
110
+ // * Classes paths from all dependent configuration files
111
+ for (_, config) in dependentConfigs {
112
+ config. classPath. map { classPathPieces. append ( $0) }
113
+ }
114
+
115
+ // Bring up the Java VM.
116
+ let jvm = try JavaVirtualMachine . shared ( classPath: classPathPieces)
117
+
118
+ // Run the generation step.
119
+ let classPath = classPathPieces. joined ( separator: " : " )
120
+ switch generationMode {
121
+ case . configuration( jarFile: let jarFile) :
122
+ try emitConfiguration (
123
+ forJarFile: jarFile,
124
+ classPath: classPath,
125
+ environment: jvm. environment ( )
126
+ )
127
+
128
+ case . classWrappers( let config) :
129
+ try generateWrappers (
130
+ config: config,
131
+ classPath: classPath,
132
+ dependentConfigs: dependentConfigs,
133
+ environment: jvm. environment ( )
134
+ )
135
+ }
71
136
}
72
137
73
- mutating func run( environment: JNIEnvironment ) throws {
138
+ /// Generate wrapper
139
+ mutating func generateWrappers(
140
+ config: Configuration ,
141
+ classPath: String ,
142
+ dependentConfigs: [ ( String , Configuration ) ] ,
143
+ environment: JNIEnvironment
144
+ ) throws {
74
145
let translator = JavaTranslator (
75
146
swiftModuleName: moduleName,
76
147
environment: environment
77
148
)
78
149
79
- // Load all of the configurations this depends on.
80
- for config in dependsOn {
81
- guard let equalLoc = config. firstIndex ( of: " = " ) else {
82
- throw JavaToSwiftError . badConfigOption ( config)
83
- }
84
-
85
- let afterEqual = config. index ( after: equalLoc)
86
- let swiftModuleName = String ( config [ ..< equalLoc] )
87
- let configFileName = String ( config [ afterEqual... ] )
88
-
89
- try translator. loadDependentConfiguration (
90
- forSwiftModule: swiftModuleName,
91
- from: URL ( filePath: configFileName)
150
+ // Note all of the dependent configurations.
151
+ for (swiftModuleName, dependentConfig) in dependentConfigs {
152
+ translator. addConfiguration (
153
+ dependentConfig,
154
+ forSwiftModule: swiftModuleName
92
155
)
93
156
}
94
157
95
- // Jar file mode: read a Jar file and output a configuration.
96
- if jarFile {
97
- return try emitConfiguration ( forJarFile: input, environment: environment)
98
- }
99
-
100
- // Load the configuration file.
101
- let config = try translator. readConfiguration ( from: URL ( filePath: input) )
158
+ // Add the configuration for this module.
159
+ translator. addConfiguration ( config, forSwiftModule: moduleName)
102
160
103
161
// Load all of the requested classes.
162
+ #if false
104
163
let classLoader = URLClassLoader (
105
- try classPathWithJarFile . map {
106
- try URL ( " file:// \( $0 ) " , environment: environment)
107
- } ,
164
+ [
165
+ try URL ( " file:// \( classPath ) " , environment: environment)
166
+ ] ,
108
167
environment: environment
109
168
)
169
+ #else
170
+ let classLoader = try JavaClass < ClassLoader > ( in: environment)
171
+ . getSystemClassLoader ( ) !
172
+ #endif
110
173
var javaClasses : [ JavaClass < JavaObject > ] = [ ]
111
174
for (javaClassName, swiftName) in config. classes {
112
175
guard let javaClass = try classLoader. loadClass ( javaClassName) else {
@@ -146,15 +209,6 @@ struct JavaToSwift: ParsableCommand {
146
209
}
147
210
}
148
211
149
- /// Return the class path augmented with the Jar file, if there is one.
150
- var classPathWithJarFile : [ String ] {
151
- if jarFile {
152
- return [ input] + classpath
153
- }
154
-
155
- return classpath
156
- }
157
-
158
212
func writeContents( _ contents: String , to filename: String , description: String ) throws {
159
213
if outputDirectory == " - " {
160
214
print ( " // \( filename) - \( description) " )
@@ -171,10 +225,13 @@ struct JavaToSwift: ParsableCommand {
171
225
print ( " done. " )
172
226
}
173
227
174
- func emitConfiguration( forJarFile jarFileName: String , environment: JNIEnvironment ) throws {
175
- var configuration = Configuration (
176
- classPath: classPathWithJarFile. joined ( separator: " : " )
177
- )
228
+ func emitConfiguration(
229
+ forJarFile jarFileName: String ,
230
+ classPath: String ,
231
+ environment: JNIEnvironment
232
+ ) throws {
233
+ var configuration = Configuration ( classPath: classPath)
234
+
178
235
let jarFile = try JarFile ( jarFileName, false , environment: environment)
179
236
for entry in jarFile. entries ( ) ! {
180
237
// We only look at class files in the Jar file.
@@ -205,9 +262,7 @@ struct JavaToSwift: ParsableCommand {
205
262
// Write the file.
206
263
try writeContents (
207
264
contents,
208
- to: URL ( filePath: outputDirectory)
209
- . appending ( path: " Java2Swift.config " )
210
- . path ( percentEncoded: false ) ,
265
+ to: " Java2Swift.config " ,
211
266
description: " Java2Swift configuration file "
212
267
)
213
268
}
@@ -238,3 +293,14 @@ extension String {
238
293
return self
239
294
}
240
295
}
296
+
297
+ @JavaClass ( " java.lang.ClassLoader " )
298
+ public struct ClassLoader {
299
+ @JavaMethod
300
+ public func loadClass( _ arg0: String ) throws -> JavaClass < JavaObject > ?
301
+ }
302
+
303
+ extension JavaClass< ClassLoader> {
304
+ @JavaStaticMethod
305
+ public func getSystemClassLoader( ) -> ClassLoader ?
306
+ }
0 commit comments