private emitModuleFile()

in packages/jsii-pacmak/lib/targets/java.ts [3126:3270]


  private emitModuleFile(mod: spec.Assembly) {
    const moduleName = mod.name;
    const moduleClass = this.makeModuleClass(moduleName);

    const { filePath: moduleResFile, name: moduleResName } =
      this.toJavaResourcePath(mod, `${mod.name}.${MODULE_CLASS_NAME}`);
    this.code.openFile(moduleResFile);
    for (const fqn of Object.keys(this.assembly.types ?? {})) {
      this.code.line(`${fqn}=${this.toNativeFqn(fqn, { binaryName: true })}`);
    }
    this.code.closeFile(moduleResFile);

    const moduleFile = this.toJavaFilePath(mod, {
      assembly: mod.name,
      fqn: `${mod.name}.${MODULE_CLASS_NAME}`,
      kind: spec.TypeKind.Class,
      name: MODULE_CLASS_NAME,
    });

    this.code.openFile(moduleFile);
    this.code.line(`package ${this.toNativeName(mod).packageName};`);
    this.code.line();
    if (Object.keys(mod.dependencies ?? {}).length > 0) {
      this.code.line('import static java.util.Arrays.asList;');
      this.code.line();
    }
    this.code.line('import java.io.BufferedReader;');
    this.code.line('import java.io.InputStream;');
    this.code.line('import java.io.InputStreamReader;');
    this.code.line('import java.io.IOException;');
    this.code.line('import java.io.Reader;');
    this.code.line('import java.io.UncheckedIOException;');
    this.code.line();
    this.code.line('import java.nio.charset.StandardCharsets;');
    this.code.line();
    this.code.line('import java.util.HashMap;');
    if (Object.keys(mod.dependencies ?? {}).length > 0) {
      this.code.line('import java.util.List;');
    }
    this.code.line('import java.util.Map;');
    this.code.line();
    this.code.line('import software.amazon.jsii.JsiiModule;');
    this.code.line();

    this.code.line(ANN_INTERNAL);
    this.code.openBlock(
      `public final class ${MODULE_CLASS_NAME} extends JsiiModule`,
    );
    this.code.line(
      'private static final Map<String, String> MODULE_TYPES = load();',
    );
    this.code.line();

    this.code.openBlock('private static Map<String, String> load()');
    this.code.line('final Map<String, String> result = new HashMap<>();');
    this.code.line(
      `final ClassLoader cl = ${MODULE_CLASS_NAME}.class.getClassLoader();`,
    );
    this.code.line(
      `try (final InputStream is = cl.getResourceAsStream("${moduleResName}");`,
    );
    this.code.line(
      '     final Reader rd = new InputStreamReader(is, StandardCharsets.UTF_8);',
    );
    this.code.openBlock(
      '     final BufferedReader br = new BufferedReader(rd))',
    );
    this.code.line('br.lines()');
    this.code.line('  .filter(line -> !line.trim().isEmpty())');
    this.code.openBlock('  .forEach(line -> ');
    this.code.line('final String[] parts = line.split("=", 2);');
    this.code.line('final String fqn = parts[0];');
    this.code.line('final String className = parts[1];');
    this.code.line('result.put(fqn, className);');
    this.code.unindent('});'); // Proxy for closeBlock
    this.code.closeBlock();
    this.code.openBlock('catch (final IOException exception)');
    this.code.line('throw new UncheckedIOException(exception);');
    this.code.closeBlock();
    this.code.line('return result;');
    this.code.closeBlock();
    this.code.line();

    this.code.line(
      'private final Map<String, Class<?>> cache = new HashMap<>();',
    );
    this.code.line();

    // ctor
    this.code.openBlock(`public ${MODULE_CLASS_NAME}()`);
    this.code.line(
      `super("${moduleName}", "${
        mod.version
      }", ${MODULE_CLASS_NAME}.class, "${this.getAssemblyFileName()}");`,
    );
    this.code.closeBlock(); // ctor

    // dependencies
    if (mod.dependencies && Object.keys(mod.dependencies).length > 0) {
      const deps = [];
      for (const dep of Object.keys(mod.dependencies)) {
        deps.push(`${this.makeModuleClass(dep)}.class`);
      }

      this.code.line();
      this.code.line('@Override');
      this.code.openBlock(
        'public List<Class<? extends JsiiModule>> getDependencies()',
      );
      this.code.line(`return asList(${deps.join(', ')});`);
      this.code.closeBlock();
    }

    this.code.line();
    this.code.line('@Override');
    this.code.openBlock(
      'protected Class<?> resolveClass(final String fqn) throws ClassNotFoundException',
    );
    this.code.openBlock('if (!MODULE_TYPES.containsKey(fqn))');
    this.code.line(
      'throw new ClassNotFoundException("Unknown JSII type: " + fqn);',
    );
    this.code.closeBlock();
    this.code.line('String className = MODULE_TYPES.get(fqn);');
    this.code.openBlock('if (!this.cache.containsKey(className))');
    this.code.line('this.cache.put(className, this.findClass(className));');
    this.code.closeBlock();
    this.code.line('return this.cache.get(className);');
    this.code.closeBlock();
    this.code.line();
    this.code.openBlock('private Class<?> findClass(final String binaryName)');
    this.code.openBlock('try');
    this.code.line('return Class.forName(binaryName);');
    this.code.closeBlock();
    this.code.openBlock('catch (final ClassNotFoundException exception)');
    this.code.line('throw new RuntimeException(exception);');
    this.code.closeBlock();
    this.code.closeBlock();

    this.code.closeBlock();

    this.code.closeFile(moduleFile);

    return moduleClass;
  }