0

私はaspectJを使用してパラメーターの名前にアクセスしようとしていますが、実際の名前の代わりに常にarg0を取得します。AspectJ JoinPointの質問で-gパラメーターを使用してJavaデバッグオプションをアクティブ化する必要があることがわかりましたが、それは私には機能しません...

これは私のJavaコードです:

private Set<Collection<String>> s;
private Collection<String> c;

public HashCodeProperty() {
    s = new HashSet<Collection<String>>();
    c = new ArrayList<String>();
}

/**
 * method that satisfy property
 */
public void satisfy() {
    c.add("this is ok");
    s.add(c);
    System.out.println("Collection is in Set: " + s.contains(c));
}

/**
 * method that violate the property
 */
public void violate() {
    c.add("this is ok");
    s.add(c);
    c.add("don't do this");
    System.out.println("Collection is in Set: " +s.contains(c));
}

これは私のAspectJコードです:

pointcut addElementsToHashCodeSet() : call (* Set.add(..));

declare warning: addElementsToHashCodeSet(): "pointcut: addElementsToHashCode()";

after(): addElementsToHashCodeSet() { 
    monitorHashCode.addElementsToHashCode((MethodSignature)thisJoinPoint.getSignature());



public void addElementsToHashCode(MethodSignature methodSignature) { 
    System.out.println("\naddElementsToHashCode.");

    // We need to access to real PARAMETER NAME
    // Then we will concatenate with method and full class name
    String firstParameterName = methodSignature.getParameterNames()[0];
    // Add firstParameterName to an array that will contain all 
    // the name of the collections inserted into the HasSet 
    System.out.println("\nfirstParameterName: "+firstParameterName);
}

現在の出力:

firstParameterName:arg0

出力として必要なもの:

firstParameterName:c

私にはこの2つのオプションがあります:

Javaコンパイラオプション

AspectJコンパイラオプション

他に何をアクティブ化する必要がありますか?

どうもありがとうございます !

4

2 に答える 2

1

次のポイントカットを使用して、変数の名前(識別子)を知るためのより良い方法を見つけました。

before(Collection c): addElementsToHashCodeSet() && args(c)

このようにして、変数cへの直接参照を取得できます。

eclipseでデバッグシンボルをアクティブにする必要はありませんでした。

必要なソリューションは、次のコードで実現できます。

インストルメンテーション:

package fr.imag.ufrima.tat.tp6.aspects;

import java.util.Collection;
import java.util.Set;

import fr.imag.ufrima.tat.tp6.aspects.monitor.MonitorHashCode;

/**
 * Techniques Avancées de Test
 * 
 * @author Rodmar CONDE
 *
 * Instrumentator for validation of HashSet classes.
 * 
 * Secures the usage of HashSet that include Collections in preventing 
 * more elements to be added to the collections once they are added. 
 * 
 * Monitor code is provided in a separate class: MonitorHashCode.
 */
public aspect InstrumentationHashCode {

    private MonitorHashCode monitorHashCode;

    public InstrumentationHashCode() {
        monitorHashCode = new MonitorHashCode();
    }

    pointcut addElementsToHashCodeSet() : call (* Set.add(..));

    declare warning: addElementsToHashCodeSet(): "pointcut: addElementsToHashCode()";

    before(Collection c): addElementsToHashCodeSet() && args(c) { 
        monitorHashCode.addElementsToHashCode(c);                   
    }

    pointcut addElementsToCollection() : call (* Collection.add(..));

    declare warning: addElementsToCollection(): "pointcut: addElementsToCollection()";

    after(String s): addElementsToCollection() && args(s) {
        monitorHashCode.addElementsToCollection(thisJoinPoint.getTarget());     
    }

}

モニター:

package fr.imag.ufrima.tat.tp6.aspects.monitor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 
 * @author Rodmar CONDE
 * 
 * Monitor used to prevent adding elements to a collection that has already been added to a HashMap
 *
 */
public class MonitorHashCode {
    /**
     *  Stores the system identity hashcode of the collections that are added to the monitored HashCode 
     */
    private List<Integer> collectionsAddedToHashSet;

    public MonitorHashCode() {
        System.out.println("Monitor created.");
        collectionsAddedToHashSet = new ArrayList<Integer>();
    }

    /**
     * Adds the system identity hashcode of the passed collection to the list
     * 
     * @param c Collection to be added to the list
     */
    public void addElementsToHashCode(Collection c) { 
        System.out.println("\naddElementsToHashCode.");

        collectionsAddedToHashSet.add(System.identityHashCode(c));
        System.out.println("\nCollection has been added to HashMap.");
    }

    /**
     * 
     * Before adding the element, search if the collection exists already
     * in the list, if so print an error.
     *
     * @param pointCutTarget
     */
    public void addElementsToCollection(Object pointCutTarget) { 
        System.out.println("\naddElementsToCollection.");

        int systemIdentityHashCode = System.identityHashCode(pointCutTarget);
        boolean isContained = collectionsAddedToHashSet.contains(systemIdentityHashCode);
        System.out.println(String.format("currentCollection: %s systemIdentityHashCode: %d - isContained: %s", pointCutTarget, systemIdentityHashCode, isContained));
        if (isContained) {
            System.out.println("Error: you have already added this collection into a hashmap, you can not add more elements into it!");
        }
    }

}
于 2013-03-26T10:28:17.660 に答える
0

私が読んだ方法では、Set.add(..)メソッドの最初のパラメーターの(内部)名前を求めています。これはJava-APIの一部であるため、定義する名前になることはありません。必要なのは、そのパラメーターに渡される値の名前です。

値は、 JoinPoint.getArgs()メソッドを介してObject []として使用できるはずですが、名前を取得する方法がすぐにはわかりません。ただし、リフレクションを介して可能である必要があります。

于 2013-03-25T10:52:43.470 に答える