edu.ksu.cis.indus.tools.slicer.criteria.specification.SliceCriterionSpec.java Source code

Java tutorial

Introduction

Here is the source code for edu.ksu.cis.indus.tools.slicer.criteria.specification.SliceCriterionSpec.java

Source

/*******************************************************************************
 * Indus, a program analysis and transformation toolkit for Java.
 * Copyright (c) 2001, 2007 Venkatesh Prasad Ranganath
 * 
 * All rights reserved.  This program and the accompanying materials are made 
 * available under the terms of the Eclipse Public License v1.0 which accompanies 
 * the distribution containing this program, and is available at 
 * http://www.opensource.org/licenses/eclipse-1.0.php.
 * 
 * For questions about the license, copyright, and software, contact 
 *    Venkatesh Prasad Ranganath at venkateshprasad.ranganath@gmail.com
 *                                 
 * This software was developed by Venkatesh Prasad Ranganath in SAnToS Laboratory 
 * at Kansas State University.
 *******************************************************************************/

package edu.ksu.cis.indus.tools.slicer.criteria.specification;

import edu.ksu.cis.indus.common.soot.Util;
import edu.ksu.cis.indus.slicer.CriteriaSpecHelper;
import edu.ksu.cis.indus.slicer.ISliceCriterion;
import edu.ksu.cis.indus.slicer.SliceCriteriaFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.MissingResourceException;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import soot.Body;
import soot.Scene;
import soot.SootClass;
import soot.SootMethod;
import soot.Type;
import soot.Value;
import soot.ValueBox;
import soot.jimple.Stmt;

/**
 * This class is the criterion specification. <i>This is intended for internal use only.  Clients should not depend on or use
 * this class.</i>
 *
 * @author <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a>
 * @author $Author: rvprasad $
 * @version $Revision: 1.8 $ $Date: 2007/02/10 19:06:02 $
 */
public final class SliceCriterionSpec implements Cloneable {
    /** 
     * The logger used by instances of this class to log messages.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(SliceCriterionSpec.class);

    /** 
     * The singleton slice criteria factory.
     */
    private static final SliceCriteriaFactory CRITERIA_FACTORY = SliceCriteriaFactory.getFactory();

    /** 
     * The sequence of names of parameter types of the method immediately enclosing the criterion.
     *
     * @invariant parameterTypeNames.oclIsKindOf(Sequence(String))
     */
    private List<String> parameterTypeNames;

    /** 
     * The name of the class immediately enclosing the criterion.
     */
    private String className;

    /** 
     * The name of the method immediately enclosing the criterion.
     */
    private String methodName;

    /** 
     * The name of the return type of the method  immediately enclosing the criterion.
     */
    private String returnTypeName;

    /** 
     * This indicates if all expressions in the statement should be considered as slice criterion.
     */
    private boolean considerEntireStmt;

    /** 
     * This indicates if the execution of the statement should be considered as slice criterion.
     */
    private boolean considerExecution;

    /** 
     * The index of the use or def value box, in the statement, that is the slice criterion.
     */
    private int exprIndex = -1; // Initialization is required due to a limitation of JiBX (known problem 3 on JiBX site)

    /** 
     * The index of the statement, in the method body, in which the slice criterion occurs.
     */
    private int stmtIndex = -1; // Initialization is required due to a limitation of JiBX (known problem 3 on JiBX site)

    /**
     * Creates an instance of this class.
     */
    private SliceCriterionSpec() {
        parameterTypeNames = createParameterTypeNamesContainer();
    }

    /**
     * Retrieves the criteria represented by this spec relative to the given scene.
     *
     * @param scene relative to which the criteria will be generated.
     *
     * @return the collection of slice criterion.
     *
     * @throws MissingResourceException when the any of the types used in the criterion specification cannot be found.
     * @throws IllegalStateException when the method in the spec does not have a body or the specified statment/expr does not
     *          exists.
     */
    public Collection<ISliceCriterion> getCriteria(final Scene scene) {
        trim();

        final SootClass _sc = scene.getSootClass(className);

        if (_sc == null) {
            final String _msg = className + " is not available in the System.";
            LOGGER.error(_msg);
            throw new MissingResourceException("Given class not available in the System.", className, null);
        }

        final List<Type> _parameterTypes = new ArrayList<Type>();

        for (final Iterator<String> _i = parameterTypeNames.iterator(); _i.hasNext();) {
            final String _name = _i.next();
            _parameterTypes.add(Util.getTypeFor(_name, scene));
        }

        final SootMethod _sm = _sc.getMethod(methodName, _parameterTypes, Util.getTypeFor(returnTypeName, scene));
        _sc.setApplicationClass();

        final Body _body = _sm.retrieveActiveBody();

        if (_body == null) {
            final String _msg = returnTypeName + " " + methodName + "(" + parameterTypeNames
                    + ") does not have a body.";
            LOGGER.error(_msg);
            throw new IllegalStateException(_msg);
        }

        final List<Stmt> _stmts = Collections.list(Collections.<Stmt>enumeration(_body.getUnits()));

        if (_stmts.size() < stmtIndex + 1) {
            final String _msg = returnTypeName + " " + methodName + "(" + parameterTypeNames + ") has only "
                    + _stmts.size() + " statements. [" + stmtIndex + "]";
            LOGGER.error(_msg);
            throw new IllegalStateException(_msg);
        }

        final Collection<ISliceCriterion> _result;

        if (stmtIndex == -1) {
            _result = CRITERIA_FACTORY.getCriteria(_sm);
        } else {
            final Stmt _stmt = _stmts.get(stmtIndex);

            if (exprIndex == -1) {
                _result = CRITERIA_FACTORY.getCriteria(_sm, _stmt, considerEntireStmt, considerExecution);
            } else {
                _result = CRITERIA_FACTORY.getCriteria(_sm, _stmt,
                        (ValueBox) _stmt.getUseAndDefBoxes().get(exprIndex), considerExecution);
            }
        }

        return _result;
    }

    /**
     * Extracts the names of the given type.
     *
     * @param parameterTypes is the collection of types whose names should be extracted.
     *
     * @return the names of the type.
     *
     * @pre paramterTypes != null
     * @post result != null
     */
    public static List<String> getNamesOfTypes(final List<Type> parameterTypes) {
        final List<String> _result = new ArrayList<String>();

        for (final Iterator<Type> _i = parameterTypes.iterator(); _i.hasNext();) {
            _result.add(_i.next().toString().replace(']', ' ').trim());
        }
        return _result;
    }

    /**
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        trim();
        return new ToStringBuilder(this).append("className", this.className)
                .append("returnTypeName", this.returnTypeName).append("methodName", this.methodName)
                .append("parameterTypeNames", this.parameterTypeNames).append("stmtIndex", this.stmtIndex)
                .append("exprIndex", this.exprIndex).append("considerExecution", this.considerExecution)
                .append("considerEntireStmt", this.considerEntireStmt).toString();
    }

    /**
     * Retrieves the specification for the given criterion relative to <code>scene</code>.
     *
     * @param criterion for which the specification should be generated.
     *
     * @return the specification.
     *
     * @throws IllegalStateException when an error occurs while creating the criterion.
     *
     * @pre criterion != null and scene != null
     * @post result != null
     */
    static Collection<SliceCriterionSpec> getCriterionSpec(final ISliceCriterion criterion) {
        final SootMethod _method = criterion.getOccurringMethod();
        final SootClass _declaringClass = _method.getDeclaringClass();
        final String _prefix = _declaringClass.getPackageName();
        final String _shortJavaStyleName = _declaringClass.getShortJavaStyleName();
        final String _className;

        if (_prefix.length() != 0) {
            _className = _prefix + "." + _shortJavaStyleName;
        } else {
            _className = _shortJavaStyleName;
        }

        final String _methodName = _method.getName();
        final Collection<SliceCriterionSpec> _result;
        if (!_method.isAbstract() && !_method.isNative()) {
            final Body _body = _method.retrieveActiveBody();

            if (_body == null) {
                final String _msg = _method.getSignature() + " does not have a body.";
                LOGGER.error(_msg);
                throw new IllegalStateException(_msg);
            }

            final List<Stmt> _stmts = Collections.list(Collections.<Stmt>enumeration(_body.getUnits()));
            final Stmt _occurringStmt = CriteriaSpecHelper.getOccurringStmt(criterion);
            final int _stmtIndex = _stmts.indexOf(_occurringStmt);
            final boolean _considerExecution = CriteriaSpecHelper.isConsiderExecution(criterion);

            final SliceCriterionSpec _spec = new SliceCriterionSpec();
            _spec.className = _className;
            _spec.methodName = _methodName;
            _spec.parameterTypeNames = getNamesOfTypes(_method.getParameterTypes());
            _spec.returnTypeName = _method.getReturnType().toString();
            _spec.stmtIndex = _stmtIndex;
            _spec.exprIndex = -1;
            _spec.considerExecution = _considerExecution;
            _spec.considerEntireStmt = false;

            _result = new ArrayList<SliceCriterionSpec>();
            final ValueBox _occurringExprBox = CriteriaSpecHelper.getOccurringExpr(criterion);

            if (_occurringExprBox != null) {
                final Value _expr = _occurringExprBox.getValue();
                final int _size = _expr.getUseBoxes().size();

                if (_size == 0) {
                    _spec.exprIndex = _occurringStmt.getUseAndDefBoxes().indexOf(_occurringExprBox);
                    _result.add(_spec);
                } else {
                    for (int _i = _size - 1; _i >= 0; _i--) {
                        try {
                            final SliceCriterionSpec _temp = (SliceCriterionSpec) _spec.clone();
                            _temp.exprIndex = _i;
                            _result.add(_temp);
                        } catch (final CloneNotSupportedException _e) {
                            final String _msg = "Low level Error while creating criterion specification.";
                            LOGGER.error(_msg);
                            throw new IllegalStateException(_msg);
                        }
                    }
                }
            } else {
                _result.add(_spec);
            }
        } else {
            _result = Collections.emptySet();
        }

        return _result;
    }

    /**
     * Creates a container for names of paramter types. This is used mainly during deserialization.
     *
     * @return the container.
     *
     * @post result != null
     */
    private static List<String> createParameterTypeNamesContainer() {
        return new ArrayList<String>();
    }

    /**
     * Trims the string data in the specification.
     */
    private void trim() {
        if (className != null) {
            className = className.trim();
        }

        if (methodName != null) {
            methodName = methodName.trim();
        }

        if (returnTypeName != null) {
            returnTypeName = returnTypeName.trim();
        }

        for (final ListIterator<String> _i = parameterTypeNames.listIterator(); _i.hasNext();) {
            final String _str = _i.next();

            if (_str != null) {
                _i.remove();
                _i.add(_str.trim());
            }
        }
    }
}

// End of File