<commit_before>/*
 *  Copyright 2008 <NAME> <<EMAIL>>
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.ringojs.tools;

import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.WrapFactory;
import org.ringojs.engine.RingoWrapFactory;
import org.ringojs.util.StringUtils;
import org.ringojs.repository.*;
import org.mozilla.javascript.ClassShutter;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Logger;

/**
 * This class describes the configuration for a RingoJS application or shell session.
 * @author hannes
 */
public class RingoConfiguration {

    private Repository home;
    private List<Repository> repositories;
    private Resource mainResource;
    private String[] arguments;
    private int optimizationLevel = 0;
    private boolean strictVars = true;
    private boolean debug = false;
    private boolean verbose = false;
    private int languageVersion = 180;
    private boolean parentProtoProperties = false;
    private Class<Scriptable>[] hostClasses = null;
    private ClassShutter classShutter = null;
    private WrapFactory wrapFactory = null;
    private List<String> bootstrapScripts;
    private boolean sealed = false;
    private boolean policyEnabled = false;
    private boolean reloading = true;
    private String charset = "UTF-8";

    /**
     * Create a new Ringo configuration and sets up its module search path.
     *
     * @param ringoHome the ringo installation directory
     * @param userModules the module search path as list of paths
     * @param systemModules system module path to append to module path, or null
     * @throws FileNotFoundException if a moudule path item does not exist
     */
    public RingoConfiguration(Repository ringoHome, List<String> userModules,
                              String systemModules) throws IOException {
        repositories = new ArrayList<Repository>();
        home = ringoHome;
        home.setAbsolute(true);

        String optLevel = System.getProperty("rhino.optlevel");
        if (optLevel != null) {
            optimizationLevel = Integer.parseInt(optLevel);
        }
        String langVersion = System.getProperty("rhino.langversion");
        if (langVersion != null) {
            languageVersion = Integer.parseInt(langVersion);
        }
        String parentProto = System.getProperty("rhino.parentproto");
        if (parentProto != null) {
            parentProtoProperties = Integer.parseInt(parentProto) != 0;
        }

        if (userModules != null) {
            for (String pathElem : userModules) {
                String path = pathElem.trim();
                addModuleRepository(resolveRootRepository(path));
            }
        }

        // append system modules path relative to ringo home
        // TODO this probably shouldn't be on require.paths
        if (systemModules != null) {
            addModuleRepository(resolveRootRepository(systemModules));
        }

        // now that repositories are set up try to set default log4j configuration file
        if (System.getProperty("log4j.configuration") == null) {
            Resource log4jConfig = getResource("config/log4j.properties");
            try {
                System.setProperty("log4j.configuration", log4jConfig.getUrl().toString());
            } catch (MalformedURLException x) {
                System.setProperty("log4j.configuration", "file:" + log4jConfig.getPath());
            }
        }
        getLogger().fine("Parsed repository list: " + repositories);
    }

    public void addModuleRepository(Repository repository) throws IOException {
        if (repository != null && repository.exists()) {
            repository.setRoot();
            repositories.add(repository);
        } else {
            throw new FileNotFoundException(repository.getPath());
        }
    }

    /**
     * Resolve a module repository path.
     * @param path the path
     * @return a repository
     * @throws FileNotFoundException if the path couldn't be resolved
     */
    public Repository resolveRootRepository(String path) throws IOException {
        File file = new File(path);
        if (!file.isAbsolute()) {
            // Try to resolve as installation repository child first
            Repository repository = home.getChildRepository(path);
            if (repository != null && repository.exists()) {
                repository.setRoot();
                return repository;
            }
            // Try to resolve path as classpath resource
            URL url = RingoConfiguration.class.getResource("/" + path);
            if (url != null) {
                String protocol = url.getProtocol();
                if (("jar".equals(protocol) || "zip".equals(protocol))) {
                    Repository jar = toZipRepository(url);
                    if (jar != null) {
                        repository = jar.getChildRepository(path);
                        if (repository.exists()) {
                            repository.setRoot();
                            return repository;
                        }
                    }
                }
            }
            // then try to resolve against current directory
            file = file.getAbsoluteFile();
        }
        if (!file.exists()) {
            throw new FileNotFoundException("File '" + file + "' does not exist.");
        }
        if (file.isFile() && StringUtils.isZipOrJarFile(path)) {
            return new ZipRepository(file);
        } else {
            return new FileRepository(file);
        }
    }

    /**
     * Set the main script for this configuration. If the scriptName argument is not null,
     * we check whether the script is already contained in the ringo module path.
     *
     * If not, the script's parent repository is prepended to the module path. If scriptName is
     * null, we prepend the current working directory to the module path.<commit_msg>Only try to resolve system modules against ringo home and ringo.jar.<commit_after>/*
 *  Copyright 2008 <NAME> <<EMAIL>>
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.ringojs.tools;

import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.WrapFactory;
import org.ringojs.engine.RingoWrapFactory;
import org.ringojs.util.StringUtils;
import org.ringojs.repository.*;
import org.mozilla.javascript.ClassShutter;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Logger;

/**
 * This class describes the configuration for a RingoJS application or shell session.
 * @author hannes
 */
public class RingoConfiguration {

    private Repository home;
    private List<Repository> repositories;
    private Resource mainResource;
    private String[] arguments;
    private int optimizationLevel = 0;
    private boolean strictVars = true;
    private boolean debug = false;
    private boolean verbose = false;
    private int languageVersion = 180;
    private boolean parentProtoProperties = false;
    private Class<Scriptable>[] hostClasses = null;
    private ClassShutter classShutter = null;
    private WrapFactory wrapFactory = null;
    private List<String> bootstrapScripts;
    private boolean sealed = false;
    private boolean policyEnabled = false;
    private boolean reloading = true;
    private String charset = "UTF-8";

    /**
     * Create a new Ringo configuration and sets up its module search path.
     *
     * @param ringoHome the ringo installation directory
     * @param userModules the module search path as list of paths
     * @param systemModules system module path to append to module path, or null
     * @throws FileNotFoundException if a moudule path item does not exist
     */
    public RingoConfiguration(Repository ringoHome, List<String> userModules,
                              String systemModules) throws IOException {
        repositories = new ArrayList<Repository>();
        home = ringoHome;
        home.setAbsolute(true);

        String optLevel = System.getProperty("rhino.optlevel");
        if (optLevel != null) {
            optimizationLevel = Integer.parseInt(optLevel);
        }
        String langVersion = System.getProperty("rhino.langversion");
        if (langVersion != null) {
            languageVersion = Integer.parseInt(langVersion);
        }
        String parentProto = System.getProperty("rhino.parentproto");
        if (parentProto != null) {
            parentProtoProperties = Integer.parseInt(parentProto) != 0;
        }

        if (userModules != null) {
            for (String pathElem : userModules) {
                String path = pathElem.trim();
                addModuleRepository(resolveRepository(path, false));
            }
        }

        // append system modules path relative to ringo home
        if (systemModules != null) {
            addModuleRepository(resolveRepository(systemModules, true));
        }

        // now that repositories are set up try to set default log4j configuration file
        if (System.getProperty("log4j.configuration") == null) {
            Resource log4jConfig = getResource("config/log4j.properties");
            try {
                System.setProperty("log4j.configuration", log4jConfig.getUrl().toString());
            } catch (MalformedURLException x) {
                System.setProperty("log4j.configuration", "file:" + log4jConfig.getPath());
            }
        }
        getLogger().fine("Parsed repository list: " + repositories);
    }

    public void addModuleRepository(Repository repository) throws IOException {
        if (repository != null && repository.exists()) {
            repository.setRoot();
            repositories.add(repository);
        } else {
            throw new FileNotFoundException(repository.getPath());
        }
    }

    /**
     * Resolve a module repository path.
     * @param path the path
     * @param system whether repository should be resolved as system repository
     * @return a repository
     * @throws FileNotFoundException if the path couldn't be resolved
     */
    public Repository resolveRepository(String path, boolean system)
            throws IOException {
        File file = new File(path);
        if (!file.isAbsolute()) {
            // If this is a system repo resolve in ringo home and ringo.jar
            if (system) {
                Repository repo = resolveSystemRepository(path);
                if (repo != null) return repo;
            }
            // then try to resolve against current directory
            file = file.getAbsoluteFile();
        }
        if (!file.exists()) {
            throw new FileNotFoundException("File '" + file + "' does not exist.");
        }
        if (file.isFile() && StringUtils.isZipOrJarFile(path)) {
            return new ZipRepository(file);
        } else {
            return new FileRepository(file);
        }
    }

    private Repository resolveSystemRepository(String path)
            throws IOException {
        // Try to resolve as installation repository child first
        Repository repository = home.getChildRepository(path);
        if (repository != null && repository.exists()) {
            repository.setRoot();
            return repository;
        }
        // Try to resolve path as classpath resource
        URL url = RingoConfiguration.class.getResource("/" + path);
        if (url != null) {
            String protocol = url.getProtocol();
            if (("jar".equals(protocol) || "zip".equals(protocol))) {
                Repository jar = toZipRepository(url);
                if (jar != null) {
                    repository = jar.getChildRepository(path);
                    if (repository.exists()) {
                        repository.setRoot();
                        return repository;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Set the main script for this configuration. If the scriptName argument is not null,
     * we check whether the script is already contained in the ringo module path.
     *
     * If not, the script's parent repository is prepended to the module path. If scriptName is
     * null, we prepend the current working directory to the module path.
{'fraction_non_alphanumeric': 0.08617827499097798, 'fraction_numerical': 0.0031757488271382172, 'mean_word_length': 2.417016029593095, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4033800', 'n_tokens_mistral': 3409, 'n_tokens_neox': 3336, 'n_words': 1120}