head	1.10;
access;
symbols
	bg2_23:1.9
	bg2_22:1.9
	bg2_21:1.9
	bg2_20:1.9
	bg2_16:1.9
	bg2_15:1.9
	bg2_12:1.9
	bg2_07:1.9;
locks; strict;
comment	@# @;


1.10
date	2008.10.16.04.04.18;	author stefant;	state Exp;
branches;
next	1.9;
commitid	2bc948f6bd3f4567;

1.9
date	2008.02.26.19.38.30;	author stefant;	state Exp;
branches;
next	1.8;
commitid	3d5547c46ab14567;

1.8
date	2008.02.25.23.30.40;	author stefant;	state Exp;
branches;
next	1.7;
commitid	5ff447c34f9a4567;

1.7
date	2008.02.25.02.49.21;	author stefant;	state Exp;
branches;
next	1.6;
commitid	699447c22cae4567;

1.6
date	2008.02.21.03.09.50;	author stefant;	state Exp;
branches;
next	1.5;
commitid	65cc47bceb7c4567;

1.5
date	2008.02.21.02.44.00;	author stefant;	state Exp;
branches;
next	1.4;
commitid	5b5247bce56b4567;

1.4
date	2008.02.17.20.47.28;	author stefant;	state Exp;
branches;
next	1.3;
commitid	6be447b89d5a4567;

1.3
date	2008.02.15.21.09.28;	author stefant;	state Exp;
branches;
next	1.2;
commitid	42f547b5ff844567;

1.2
date	2008.01.14.02.52.20;	author stefant;	state Exp;
branches;
next	1.1;
commitid	7ff0478ace634567;

1.1
date	2008.01.13.20.43.53;	author stefant;	state Exp;
branches;
next	;
commitid	4e54478a77ec4567;


desc
@@


1.10
log
@Moved transitive hull loading and consolelayout to libgraph
@
text
@/*
 * Copyright (c) 2007,2008, Stefan Hepp
 *
 * This file is part of JOPtimizer.
 *
 * JOPtimizer is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * JOPtimizer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package joptimizer.config;

import com.jopdesign.libgraph.struct.AppConfig;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * Main configuration container class.
 *
 * @@author Stefan Hepp, e0026640@@student.tuwien.ac.at
 * @@noinspection InconsistentJavaDoc
 */
public class JopConfig implements AppConfig {

    private Properties config;
    private Set rootClasses;
    private String mainClass;
    private ArchConfig archConfig;
    private String[] libraries;
    private String[] ignore;

    public static final String CONF_OUTPUTPATH = "o";

    public static final String CONF_ASSUME_DYNAMIC_LOADING = "assume-dynamic-loading";

    public static final String CONF_ASSUME_REFLECTION = "assume-reflection";

    public static final String CONF_ALLOW_INCOMPLETE_CODE = "allow-incomplete-code";

    public static final String CONF_ALLOW_LOADDEMAND = "allow-loaddemand";

    public static final String CONF_ARCH = "arch";

    public static final String CONF_ARCH_CONFIG = "arch-config";

    public static final String CONF_LIBRARY_PATH = "libraries";

    public static final String CONF_IGNORE_PATH = "skip";

    public static final String CONF_IGNORE_ACTION_ERRORS = "ignore-errors";

    public JopConfig() {
        initialize(null, null);
    }

    public JopConfig(Properties config) throws ConfigurationException {
        initialize(config, null);
        if ( config != null ) {
            setProperties(config);
        }
    }

    public JopConfig(Properties config, String mainClass) throws ConfigurationException {
        initialize(config, mainClass);
        if ( config != null ) {
            setProperties(config);
        }
    }

    private void initialize(Properties config, String mainClass) {
        this.config = new Properties();
        this.mainClass = mainClass;
        this.rootClasses = new HashSet();
        libraries = new String[0];
        ignore = new String[0];
        archConfig = new ArchConfig();
    }

    /**
     * Add all generic options for this configuration to a list.
     *
     * @@param optionList a list where options as ArgOption will be added.
     */
    public static void createOptions(List optionList) {

        optionList.add(new StringOption(null, CONF_OUTPUTPATH,
                "Set default output path for all generated files.", "path"));
        optionList.add(new StringOption(null, CONF_ARCH,
                "Initialize options with default values for an architecture if not set, and load " +
                "internal architecture configfile. Currently supported: jop,jvm", "arch"));
        optionList.add(new StringOption(null, CONF_ARCH_CONFIG,
                "Load an architecture configuration from a config file.", "file"));
        optionList.add(new BoolOption(null, CONF_ASSUME_DYNAMIC_LOADING,
                "Assume that dynamic class loading is used (disables some optimizations)."));
        optionList.add(new BoolOption(null, CONF_ASSUME_REFLECTION,
                "Assume that reflection is used (disables some optimizations)."));
        optionList.add(new BoolOption(null, CONF_ALLOW_INCOMPLETE_CODE,
                "Ignore missing classes. Some features will not work when this option is set."));
        optionList.add( new BoolOption(null, CONF_ALLOW_LOADDEMAND,
                "Allow class loading on demand. Disables automatic transitive hull loading."));
        optionList.add( new StringOption(null, CONF_LIBRARY_PATH,
                "Comma-separated list of packages or classes which are part of libraries and should " +
                "not be loaded.", "pkg"));
        optionList.add( new StringOption(null, CONF_IGNORE_PATH,
                "Comma-separated list of packages or classes which will not be loaded. Ignored if " +
                CONF_ALLOW_INCOMPLETE_CODE + " is not set.", "pkg"));
        optionList.add( new BoolOption(null, CONF_IGNORE_ACTION_ERRORS,
                "Continue with next method, class or action if any action throws an error."));
    }

    public void setProperties(Map config) throws ConfigurationException {
        for (Iterator it = config.entrySet().iterator(); it.hasNext();) {
            Map.Entry entry = (Map.Entry) it.next();
            setOption(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
        }
    }

    public String getMainClassName() {
        return mainClass;
    }

    public void setMainClassName(String mainClass) {
        this.mainClass = mainClass;
    }

    /**
     * Get a set of all rootclass classnames as collection of strings.
     * @@return a set of all rootclass classnames.
     */
    public Set getRootClasses() {
        return rootClasses;
    }

    /**
     * set the rootclass classnames as set of strings.
     * @@param rootClasses all root classnames as strings.
     */
    public void setRootClasses(Set rootClasses) {
        this.rootClasses = rootClasses;
    }

    public ArchConfig getArchConfig() {
        return archConfig;
    }

    public String getArchConfigFileName() {
        return getOption(CONF_ARCH_CONFIG);
    }

    public void setArchConfig(URL config) throws ConfigurationException {
        if ( config != null ) {
            this.archConfig = new ArchConfig(config);
            this.config.put(CONF_ARCH_CONFIG, config.toString());
        } else {
            this.archConfig = new ArchConfig();
            this.config.remove(CONF_ARCH_CONFIG);
        }
    }

    public void initArchitecture(String arch) throws ConfigurationException {
        if ( "jop".equals(arch) ) {
            URL config = getClass().getResource("jop-arch.properties");
            if ( config == null ) {
                throw new ConfigurationException("Could not find resource {jop-arch.properties}.");
            }
            setArchConfig(config);

        } else if ( "jvm".equals(arch) ) {

            URL config = getClass().getResource("jvm-arch.properties");
            if ( config == null ) {
                throw new ConfigurationException("Could not find resource {jwm-arch.properties}.");
            }
            setArchConfig(config);

            if ( !isSet(CONF_LIBRARY_PATH) ) {
                setOption(CONF_LIBRARY_PATH, "java,sun");
            }

        } else {
            throw new ConfigurationException("Unknown architecture {"+arch+"}.");
        }
    }

    public String getMainMethodSignature() {
        return "main([Ljava/lang/String;)V";
    }

    /**
     * Check if the given option is set. This also returns true, if the option
     * has the value of FALSE.
     *
     * @@see #isEnabled(String)
     * @@param option the name of the option.
     * @@return true, if the option has been set.
     */
    public boolean isSet(String option) {
        return config.containsKey(option);
    }

    public boolean isEnabled(String option) {
        return Boolean.valueOf(config.getProperty(option)).booleanValue();
    }

    public boolean isEnabled(String name, String id, String option) {
        String on = getOptionName(id, option);
        if ( isSet(on) ) {
            return isEnabled(on);
        }
        return isEnabled(getOptionName(name, option));
    }

    public void setOption(String option, String value) throws ConfigurationException {
        if ( CONF_ARCH_CONFIG.equals(option) ) {
            try {
                setArchConfig(new URL(value));
            } catch (MalformedURLException e) {
                throw new ConfigurationException("Invalid configuration file url {"+value+"}.", e);
            }
        } else if ( CONF_ARCH.equals(option) ) {
            initArchitecture(value);
        } else {
            if ( value != null ) {
                config.setProperty(option, value);
            } else {
                config.remove(option);
            }
        }

        if ( CONF_IGNORE_PATH.equals(option) ) {

            if ( value != null && !"".equals(value) ) {
                ignore = value.split(",");
            } else {
                ignore = new String[0];
            }

        } else if ( CONF_LIBRARY_PATH.equals(option) ) {

            if ( value != null && !"".equals(value) ) {
                libraries = value.split(",");
            } else {
                libraries = new String[0];
            }

        }
    }

    public String getOption(String option) {
        return config.getProperty(option);
    }

    public String getOption(String option, String defaultvalue) {
        return config.getProperty(option, defaultvalue);
    }

    public String getOptionName(String prefix, String option) {
        return prefix + "." + option;
    }

    public String getActionOption(String name, String id, String option) {
        return getActionOption(name, id, option, null);
    }

    public String getActionOption(String name, String id, String option, String defaultvalue) {
        String value = getOption(getOptionName(id, option), null);
        if ( value != null ) {
            return value;
        }
        return getOption(getOptionName(name, option), defaultvalue);
    }

    /**
     * Get a map of all currently set options. <br>
     * Do not modify this map.
     * 
     * @@return a map with the full option name as key and its value as string.
     */
    public Map getOptions() {
        return config;
    }

    public String getDefaultOutputPath() {
        return getOption(CONF_OUTPUTPATH, ".");
    }

    public boolean doAssumeDynamicLoading() {
        return isEnabled(CONF_ASSUME_DYNAMIC_LOADING);
    }

    public boolean doAssumeReflection() {
        return isEnabled(CONF_ASSUME_REFLECTION);
    }

    public boolean doLoadOnDemand() {
        return isEnabled(CONF_ALLOW_LOADDEMAND);
    }

    public boolean doIgnoreActionErrors() {
        return isEnabled(CONF_IGNORE_ACTION_ERRORS);
    }

    /**
     * Allow for missing classes. Some features will be disabled
     * if this option is set.
     *
     * @@return true if missing classes should be ignored.
     */
    public boolean doAllowIncompleteCode() {
        return isEnabled(CONF_ALLOW_INCOMPLETE_CODE);
    }

    public boolean isNativeClassName(String className) {
        return archConfig.getNativeClassName().equals(className) ||
                "java.lang.Class".equals(className);
    }

    public boolean isLibraryClassName(String className) {
        for (int i = 0; i < libraries.length; i++) {
            if ( className.startsWith(libraries[i]) ) {
                return true;
            }
        }
        return false;
    }

    public boolean doExcludeClassName(String className) {

        for (int i = 0; i < ignore.length; i++) {
            if ( className.startsWith(ignore[i]) ) {
                return true;
            }
        }

        return false;
    }

}
@


1.9
log
@bugfix for missing appconfig
bugfix for invokespecial of non-private methods
@
text
@a66 2
    public static final String CONF_SKIP_NATIVE_CLASS = "skip-nativeclass";

a123 2
        optionList.add( new BoolOption(null, CONF_SKIP_NATIVE_CLASS,
                "Do not load native system classes."));
d342 1
a342 1
    public String doExcludeClassName(String className) {
d344 3
a346 14
        if ( isNativeClassName(className) && isEnabled(CONF_SKIP_NATIVE_CLASS) ) {
            return "Skipping native class {" + className + "}.";
        }

        if ( isLibraryClassName(className) ) {
            return "Skipping library class {" + className + "}";
        }

        if ( doAllowIncompleteCode() ) {

            for (int i = 0; i < ignore.length; i++) {
                if ( className.startsWith(ignore[i]) ) {
                    return "Skipping excluded class {"+ className + "}";
                }
a347 1

d350 1
a350 1
        return null;
@


1.8
log
@fixes for loading incomplete code, fixes for array-class handling
@
text
@d182 3
d190 3
@


1.7
log
@loading arch config from property-file
allow to load configfile from cmdline
@
text
@d211 1
a211 1
        return config.contains(option);
@


1.6
log
@do not touch JVMHelp as this messes things up
@
text
@d23 2
d26 1
a33 1
 * TODO make 'Architecture'-conf-file option, load sys/default classnames, max-code/stack/locals,.. from prop-file
d44 2
d57 2
d61 2
d70 1
a70 3
        this.config = new Properties();
        this.rootClasses = new HashSet();
        setArchConfig(null);
d73 5
a77 3
    public JopConfig(Properties config) {
        this.config = config == null ? new Properties() : config;
        setArchConfig(getArchConfigFileName());
d80 9
a88 2
    public JopConfig(Properties config, String mainClass) {
        this.config = config == null ? new Properties() : config;
d90 4
a93 1
        setArchConfig(getArchConfigFileName());
d102 1
d105 3
d118 3
d130 5
a134 2
    public void setProperties(Properties config) {
        this.config.putAll(config);
d169 1
a169 1
    public void setArchConfig(String config) {
d171 24
a194 1
            this.config.put(CONF_ARCH_CONFIG, config);
a195 1
        this.archConfig = new ArchConfig(config);
d226 34
a259 2
    public void setOption(String option, String value) {
        config.setProperty(option, value);
d331 9
d346 4
d351 7
a357 1
            // TODO check for jopConfig.ignore_path
@


1.5
log
@added exception for graphs with exceptiontables, using ignore-option
added top-down inline option
@
text
@@


1.4
log
@initializing all actions with id, fallback for configuration to default name, new syntax for action-options.
@
text
@d100 1
a100 1
                "Continue if any action throws an error."));
@


1.3
log
@removed BCEL usage from joptimizer, using libgraph only to find and load class references
@
text
@d84 1
a84 1
        optionList.add(new StringOption(CONF_OUTPUTPATH,
d86 1
a86 1
        optionList.add(new StringOption(CONF_ARCH_CONFIG,
d88 1
a88 1
        optionList.add(new BoolOption(CONF_ASSUME_DYNAMIC_LOADING,
d90 1
a90 1
        optionList.add(new BoolOption(CONF_ASSUME_REFLECTION,
d92 1
a92 1
        optionList.add(new BoolOption(CONF_ALLOW_INCOMPLETE_CODE,
d94 1
a94 1
        optionList.add( new BoolOption( CONF_ALLOW_LOADDEMAND,
d96 1
a96 1
        optionList.add( new StringOption( CONF_IGNORE_PATH,
d99 1
a99 1
        optionList.add( new BoolOption(CONF_IGNORE_ACTION_ERRORS,
d101 1
a101 1
        optionList.add( new BoolOption(CONF_SKIP_NATIVE_CLASS,
d152 12
d168 8
d188 16
@


1.2
log
@fixed NPE
@
text
@a21 1
import org.apache.bcel.util.ClassPath;
d23 5
a27 1
import java.util.*;
a39 1
    private ClassPath classPath;
d59 2
a62 1
        this.classPath = new ClassPath(".");
a68 1
        this.classPath = new ClassPath(".");
d72 1
a72 1
    public JopConfig(Properties config, ClassPath classPath, String mainClass) {
a73 1
        this.classPath = classPath;
d101 2
a151 8
    public ClassPath getClassPath() {
        return classPath;
    }

    public void setClassPath(ClassPath classPath) {
        this.classPath = classPath;
    }

d215 1
a215 1
        if (isNativeClassName(className)) {
@


1.1
log
@added joptimizer sources
@
text
@d1 231
a231 229
/*
 * Copyright (c) 2007,2008, Stefan Hepp
 *
 * This file is part of JOPtimizer.
 *
 * JOPtimizer is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * JOPtimizer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package joptimizer.config;

import com.jopdesign.libgraph.struct.AppConfig;
import org.apache.bcel.util.ClassPath;

import java.util.*;

/**
 * Main configuration container class.
 * TODO make 'Architecture'-conf-file option, load sys/default classnames, max-code/stack/locals,.. from prop-file
 *
 * @@author Stefan Hepp, e0026640@@student.tuwien.ac.at
 * @@noinspection InconsistentJavaDoc
 */
public class JopConfig implements AppConfig {

    private Properties config;
    private Set rootClasses;
    private ClassPath classPath;
    private String mainClass;
    private ArchConfig archConfig;

    public static final String CONF_OUTPUTPATH = "o";

    public static final String CONF_ASSUME_DYNAMIC_LOADING = "assume-dynamic-loading";

    public static final String CONF_ASSUME_REFLECTION = "assume-reflection";

    public static final String CONF_ALLOW_INCOMPLETE_CODE = "allow-incomplete-code";

    public static final String CONF_ALLOW_LOADDEMAND = "allow-loaddemand";

    public static final String CONF_ARCH_CONFIG = "arch-config";

    public static final String CONF_IGNORE_PATH = "skip";

    public static final String CONF_IGNORE_ACTION_ERRORS = "ignore-errors";

    public JopConfig() {
        this.config = new Properties();
        this.classPath = new ClassPath(".");
        this.rootClasses = new HashSet();
        setArchConfig(null);
    }

    public JopConfig(Properties config) {
        this.config = config;
        this.classPath = new ClassPath(".");
        setArchConfig(getArchConfigFileName());
    }

    public JopConfig(Properties config, ClassPath classPath, String mainClass) {
        this.config = config;
        this.classPath = classPath;
        this.mainClass = mainClass;
        setArchConfig(getArchConfigFileName());
    }

    /**
     * Add all generic options for this configuration to a list.
     *
     * @@param optionList a list where options as ArgOption will be added.
     */
    public static void createOptions(List optionList) {
        optionList.add(new StringOption(CONF_OUTPUTPATH,
                "Set default output path for all generated files.", "path"));
        optionList.add(new StringOption(CONF_ARCH_CONFIG,
                "Load an architecture configuration from a config file.", "file"));
        optionList.add(new BoolOption(CONF_ASSUME_DYNAMIC_LOADING,
                "Assume that dynamic class loading is used (disables some optimizations)."));
        optionList.add(new BoolOption(CONF_ASSUME_REFLECTION,
                "Assume that reflection is used (disables some optimizations)."));
        optionList.add(new BoolOption(CONF_ALLOW_INCOMPLETE_CODE,
                "Ignore missing classes. Some features will not work when this option is set."));
        optionList.add( new BoolOption( CONF_ALLOW_LOADDEMAND,
                "Allow class loading on demand. Disables automatic transitive hull loading."));
        optionList.add( new StringOption( CONF_IGNORE_PATH,
                "Comma-separated list of packages or classes which will not be loaded. Ignored if " +
                CONF_ALLOW_INCOMPLETE_CODE + " is not set.", "pkg"));
        optionList.add( new BoolOption(CONF_IGNORE_ACTION_ERRORS,
                "Continue if any action throws an error."));
    }

    public void setProperties(Properties config) {
        this.config.putAll(config);
    }

    public String getMainClassName() {
        return mainClass;
    }

    public void setMainClassName(String mainClass) {
        this.mainClass = mainClass;
    }

    /**
     * Get a set of all rootclass classnames as collection of strings.
     * @@return a set of all rootclass classnames.
     */
    public Set getRootClasses() {
        return rootClasses;
    }

    /**
     * set the rootclass classnames as set of strings.
     * @@param rootClasses all root classnames as strings.
     */
    public void setRootClasses(Set rootClasses) {
        this.rootClasses = rootClasses;
    }

    public ArchConfig getArchConfig() {
        return archConfig;
    }

    public String getArchConfigFileName() {
        return getOption(CONF_ARCH_CONFIG);
    }

    public void setArchConfig(String config) {
        this.config.put(CONF_ARCH_CONFIG, config);
        this.archConfig = new ArchConfig(config);
    }

    public String getMainMethodSignature() {
        return "main([Ljava/lang/String;)V";
    }

    public ClassPath getClassPath() {
        return classPath;
    }

    public void setClassPath(ClassPath classPath) {
        this.classPath = classPath;
    }

    public boolean isEnabled(String option) {
        return Boolean.valueOf(config.getProperty(option)).booleanValue();
    }

    public void setOption(String option, String value) {
        config.setProperty(option, value);
    }

    public String getOption(String option) {
        return config.getProperty(option);
    }

    public String getOption(String option, String defaultvalue) {
        return config.getProperty(option, defaultvalue);
    }

    /**
     * Get a map of all currently set options. <br>
     * Do not modify this map.
     * 
     * @@return a map with the full option name as key and its value as string.
     */
    public Map getOptions() {
        return config;
    }

    public String getDefaultOutputPath() {
        return getOption(CONF_OUTPUTPATH, ".");
    }

    public boolean doAssumeDynamicLoading() {
        return isEnabled(CONF_ASSUME_DYNAMIC_LOADING);
    }

    public boolean doAssumeReflection() {
        return isEnabled(CONF_ASSUME_REFLECTION);
    }

    public boolean doLoadOnDemand() {
        return isEnabled(CONF_ALLOW_LOADDEMAND);
    }

    public boolean doIgnoreActionErrors() {
        return isEnabled(CONF_IGNORE_ACTION_ERRORS);
    }

    /**
     * Allow for missing classes. Some features will be disabled
     * if this option is set.
     *
     * @@return true if missing classes should be ignored.
     */
    public boolean doAllowIncompleteCode() {
        return isEnabled(CONF_ALLOW_INCOMPLETE_CODE);
    }

    public boolean isNativeClassName(String className) {
        return archConfig.getNativeClassName().equals(className) ||
                "java.lang.Class".equals(className);
    }

    public String doExcludeClassName(String className) {

        if (isNativeClassName(className)) {
            return "Skipping native class {" + className + "}.";
        }

        if ( doAllowIncompleteCode() ) {
            // TODO check for jopConfig.ignore_path
        }

        return null;
    }

}
@

