mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
16.32.2014 6994148a0cf47d7d9bbb043037442592223f177c
Prevent OOME in small JVMs:

* restrict the number of worker threads in the transformation work queue
* delay creation of input sources until transformation task is executing.
1 files modified
68 ■■■■■ changed files
opendj-config-maven-plugin/src/main/java/org/forgerock/opendj/maven/GenerateConfigMojo.java 68 ●●●●● patch | view | raw | blame | history
opendj-config-maven-plugin/src/main/java/org/forgerock/opendj/maven/GenerateConfigMojo.java
@@ -155,7 +155,7 @@
    private Templates stylesheetMessages;
    private Templates stylesheetManifest;
    private final List<Future<?>> tasks = new LinkedList<Future<?>>();
    private final ExecutorService executor = Executors.newCachedThreadPool();
    private final URIResolver resolver = new URIResolver() {
        @Override
@@ -211,13 +211,10 @@
            project.addCompileSourceRoot(getGeneratedSourcesDirectory());
        } catch (final Exception e) {
            throw new MojoExecutionException("XSLT configuration transformation failed", e);
        } finally {
            executor.shutdown();
        }
        }
    }
    private void createTransformTask(final StreamSource input, final StreamResult output,
    private void createTransformTask(final StreamSourceFactory inputFactory, final StreamResult output,
            final Templates stylesheet, final ExecutorService executor, final String... parameters)
            throws Exception {
        final Transformer transformer = stylesheet.newTransformer();
@@ -228,25 +225,33 @@
        final Future<Void> future = executor.submit(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                transformer.transform(input, output);
                transformer.transform(inputFactory.newStreamSource(), output);
                return null;
            }
        });
        tasks.add(future);
    }
    private void createTransformTask(final StreamSource input, final String outputFileName,
            final Templates stylesheet, final String... parameters) throws Exception {
    private void createTransformTask(final StreamSourceFactory inputFactory,
            final String outputFileName, final Templates stylesheet,
            final ExecutorService executor, final String... parameters) throws Exception {
        final File outputFile = new File(outputFileName);
        outputFile.getParentFile().mkdirs();
        final StreamResult output = new StreamResult(outputFile);
        createTransformTask(input, output, stylesheet, executor, parameters);
        createTransformTask(inputFactory, output, stylesheet, executor, parameters);
    }
    private void executeTransformXMLDefinitions() throws Exception {
        getLog().info("Transforming XML definitions...");
        /*
         * Restrict the size of the thread pool in order to throttle
         * creation of transformers and ZIP input streams and prevent potential
         * OOME.
         */
        final ExecutorService parallelExecutor = Executors.newFixedThreadPool(16);
        /*
         * The manifest is a single file containing the concatenated output of
         * many transformations. Therefore we must ensure that output is
         * serialized by using a single threaded executor.
@@ -256,7 +261,7 @@
        manifestFile.getParentFile().mkdirs();
        final FileOutputStream manifestFileOutputStream = new FileOutputStream(manifestFile);
        final StreamResult manifest = new StreamResult(manifestFileOutputStream);
        try {
        /*
         * Generate Java classes and resources for each XML definition.
         */
@@ -264,33 +269,36 @@
        final String metaDir = javaDir + "meta/";
        final String serverDir = javaDir + "server/";
        final String clientDir = javaDir + "client/";
        final String ldapProfileDir =
                getGeneratedProfilesDirectory("ldap") + "/" + getPackagePath() + "/meta/";
        final String cliProfileDir =
                getGeneratedProfilesDirectory("cli") + "/" + getPackagePath() + "/meta/";
        final String i18nDir = getGeneratedMessagesDirectory() + "/" + getPackagePath() + "/meta/";
            final String i18nDir =
                    getGeneratedMessagesDirectory() + "/" + getPackagePath() + "/meta/";
        for (final Map.Entry<String, StreamSourceFactory> entry : componentDescriptors.entrySet()) {
            for (final Map.Entry<String, StreamSourceFactory> entry : componentDescriptors
                    .entrySet()) {
            final String meta = metaDir + entry.getKey() + "CfgDefn.java";
            createTransformTask(entry.getValue().newStreamSource(), meta, stylesheetMetaJava);
                createTransformTask(entry.getValue(), meta, stylesheetMetaJava, parallelExecutor);
            final String server = serverDir + entry.getKey() + "Cfg.java";
            createTransformTask(entry.getValue().newStreamSource(), server, stylesheetServerJava);
                createTransformTask(entry.getValue(), server, stylesheetServerJava,
                        parallelExecutor);
            final String client = clientDir + entry.getKey() + "CfgClient.java";
            createTransformTask(entry.getValue().newStreamSource(), client, stylesheetClientJava);
                createTransformTask(entry.getValue(), client, stylesheetClientJava,
                        parallelExecutor);
            final String ldap = ldapProfileDir + entry.getKey() + "CfgDefn.properties";
            createTransformTask(entry.getValue().newStreamSource(), ldap, stylesheetProfileLDAP);
                createTransformTask(entry.getValue(), ldap, stylesheetProfileLDAP, parallelExecutor);
            final String cli = cliProfileDir + entry.getKey() + "CfgDefn.properties";
            createTransformTask(entry.getValue().newStreamSource(), cli, stylesheetProfileCLI);
                createTransformTask(entry.getValue(), cli, stylesheetProfileCLI, parallelExecutor);
            final String i18n = i18nDir + entry.getKey() + "CfgDefn.properties";
            createTransformTask(entry.getValue().newStreamSource(), i18n, stylesheetMessages);
                createTransformTask(entry.getValue(), i18n, stylesheetMessages, parallelExecutor);
            createTransformTask(entry.getValue().newStreamSource(), manifest, stylesheetManifest,
                createTransformTask(entry.getValue(), manifest, stylesheetManifest,
                    sequentialExecutor);
        }
@@ -300,25 +308,33 @@
        profileMap.put("server", stylesheetServerPackageInfo);
        profileMap.put("client", stylesheetClientPackageInfo);
        for (final Map.Entry<String, Templates> entry : profileMap.entrySet()) {
            final StreamSource source;
                final StreamSourceFactory sourceFactory = new StreamSourceFactory() {
                    @Override
                    public StreamSource newStreamSource() throws IOException {
            if (isExtension) {
                source = new StreamSource(new File(getXMLPackageDirectory() + "/Package.xml"));
                            return new StreamSource(new File(getXMLPackageDirectory()
                                    + "/Package.xml"));
            } else {
                source =
                        new StreamSource(getClass().getResourceAsStream(
                            return new StreamSource(getClass().getResourceAsStream(
                                "/" + getXMLPackageDirectory() + "/Package.xml"));
            }
                    }
                };
            final String profile = javaDir + "/" + entry.getKey() + "/package-info.java";
            createTransformTask(source, profile, entry.getValue(), "type", entry.getKey());
                createTransformTask(sourceFactory, profile, entry.getValue(), parallelExecutor,
                        "type", entry.getKey());
        }
        // Wait for all transformations to complete and cleanup.
        for (final Future<?> task : tasks) {
            task.get();
        }
        } finally {
            parallelExecutor.shutdown();
        sequentialExecutor.shutdown();
        manifestFileOutputStream.close();
    }
    }
    private void executeValidateXMLDefinitions() {
        // TODO: