Hi,

Thanks for reply Alexander. I try to answer your questions:


  *   How are you using the aspect in your code? Do you compile the whole code 
with the AspectJ compiler (Ajc) or is the aspect in a separate JAR and used via 
LTW?

        [Mike] currently we use ajc and weave it into our product at compile 
time. But I want to have a separate jar so I can use it with other products.

  *   How do you intend to use it for other products? LTW? Binary post-compile 
weaving? Compilation with Ajc? I guess it depends on what you mean by "other 
products" and whether they are in-house or 3rd party.
[Mike] It is inhouse products. And I want to add aspect ( and all its helper 
classes) into a seprate jar and use that when I compile the products.
  *   What do you need the stacktraces for? Please elaborate and explain as 
detailed as possible.
[Mike] When the target class is called I also get the stacktrace elements
Thread.currentThread().getStackTrace()
>From it I can find the class that calls our deprecated method. Startingpoint 
>is target class. There are irrelevant information in stacktrace that is not 
>applicable ( classes that are part of the java API or test frameworks).
We also look up information in gerrit and push data to a db. So there are more 
classes.

  *   Is your intention to find usages of your own deprecated methods or that 
of 3rd party code, maybe even JRE/JDK?
[Mike] Yes it is our own deprecated methods. No 3rd party code or JRE/JDK that 
we why I analyze the stacktrace.
  *   Have you considered using the AspectJ features "declare error" or 
"declare warning" and just get rid of deprecated class/method usage right 
during compilation instead of during runtime, using expensive stacktrace 
analysis?
[Mike] I guess this means that users have to get rid of their deprecated method 
usage at compile time. It is an interesting option.
Do you have an example on how it works. WIll compilation fail?
  *   As for your original question, the answer could be anything from 
implementing an interface as you suggest to using an abstract base aspect. But 
really, this looks like a "declare warning" use case to me.
[Mike] We have had issues when forcing people to change. Some users is afraid 
of change. So it is merly a "soft" issue. Will the new method be as stable as 
old.
  *   Would you mind giving us a full picture with the stacktrace helper class 
and some simple sample code? An [SSCCE](http://sscce.org/) maybe?
[Mike] Sure I will include it here ( see below).

Sample code:

package com.company.aspect;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
/**
 * Helper class for stacktraces
 */
class StackTraceHelper {
    private ListIterator<StackTraceElement> iterator = null;
    private StringBuilder builder = null;
    private final List<String> excludedPackages = new ArrayList<>();
    public StackTraceHelper(List<StackTraceElement> stackTraceElements) {
        this.iterator = stackTraceElements.listIterator();
        stackTraceToString(stackTraceElements);
    }
    /**
     * Find matching stack trace element and set iterator.
     *
     * @param className
     * @return {@link StackTraceElement} matching className
     */
    public StackTraceElement matchClassName(String className) {
        while (iterator.hasNext()) {
            StackTraceElement ste = iterator.next();
            if (className.equals(ste.getClassName())) {
                return ste;
            }
        }
        //TODO: warn that no StackTraceElement was found for Name.
        return null;
    }
    public StackTraceElement next() {
        return iterator.next();
    }
    public boolean hasNext() {
        return iterator.hasNext();
    }
    public boolean hasPrevious() {
        return iterator.hasPrevious();
    }
    public StackTraceElement previous() {
        iterator.previous();
        return iterator.previous();
    }
    @Override
    public String toString() {
        return builder.toString();
    }
    DeprecatedMethodData extractData(String targetClass) {
        DeprecatedMethodData dmd = new DeprecatedMethodData();
        dmd.setTargetClassName(targetClass);
        //This is the called  class so we need to make sure that next class is 
a test class
        //otherwise we are not interested.
        StackTraceElement steTarget = this.matchClassName(targetClass);
        if (steTarget != null) {
            //we have a match of target in stack trace
            while (this.hasNext()) {
                StackTraceElement ste = this.next();
                String clazzName = ste.getClassName();
                String methodName = ste.getMethodName();
                if (this.isTestClass(clazzName) && 
!this.isExternalFramework(clazzName)) {
                //if (this.isTestClass(clazzName)) {//TODO: Fix
                    dmd.setCallingClassName(clazzName);
                    dmd.setCallingMethodName(methodName);
                    dmd.setDeprecatedClassName(steTarget.getClassName());
                    dmd.setDeprecatedMethodName(steTarget.getMethodName());
                    dmd.setAccess(Access.EXTERNAL);
                    break;
                }
                dmd.setAccess(Access.INTERNAL);
            }
        }
        //Add complete stacktrace to find problems with current algorithm.
        dmd.setStackTrace(this.builder.toString());
        return dmd;
    }
    /**
     * Must be called first thing since next operations
     * will affect this.
     */
    private void stackTraceToString(List<StackTraceElement> stackTraceElements) 
{
        final ListIterator<StackTraceElement> iter = 
stackTraceElements.listIterator();
        builder = new StringBuilder();
        while (iter.hasNext()) {
            builder.append(iter.next().toString());
        }
    }
    public boolean isInternal(String clazz) {
        if (clazz
                .matches(
                "^(com.company.manager|com.company.helpers|"
                        + "com.company.actions|com.company.configuration|"
                        + "com.company.demo).*")) {
            //LogerHelper.log("internal class:" + clazz);
            return true;
        }
        return false;
    }
    public boolean isJava(String clazz) {
        if (clazz.startsWith("sun") ||
                clazz.startsWith("java")) {
            //LogerHelper.log("java class:" + clazz);
            return true;
        }
        return false;
    }
    public boolean isTestClass(String clazz) {
        if (isInternal(clazz) || isJava(clazz)) {
            return false;
        }
        return true;
    }
    public boolean isExternalFramework(String clazz) {
        if (clazz.startsWith("org.testng") || 
clazz.startsWith("org.apache.maven.surefire")) {
            return true;
        }
        return false;
    }

    //TODO: Not ready yet.
//    public void excludePackages(List<String> packageNames) {
//        excludedPackages.addAll(packageNames);
//    }
//
//    boolean exclude(String clazz) {
//        for (String exclude : excludedPackages) {
//            if (clazz
//                    .matches(
//                    "^(" + exclude + ").*")) {
//                return true;
//            }
//        }
//        return false;
//    }
//
//    boolean isTestClass2(String clazz) {
//        return exclude(clazz);
//    }
}











________________________________
Från: aspectj-users-boun...@eclipse.org <aspectj-users-boun...@eclipse.org> för 
Mikael Petterson <mikaelpetter...@hotmail.com>
Skickat: den 15 mars 2018 14:35
Till: aspectj-users@eclipse.org
Ämne: [aspectj-users] Add my aspect to different projects

Hi,

I have created an aspect that can be used to track calls to deprecated methods 
in your product. It is currently implemented in "our product" but I want to 
make a library out of it so we can use it for other products.

The aspect currently looks something like:

aspect DeprecatedMethodLogger {


    pointcut includeDeprecated():execution(public  * *.*(..)) && 
@annotation(Deprecated);
    pointcut excludeBeta():execution(public  * *.*(..)) && 
!@annotation(com.google.common.annotations.Beta);
    pointcut deprecatedMethods():  includeDeprecated() && excludeBeta();
    before() :deprecatedMethods()  {
        if (thisJoinPoint.getTarget() != null) {
            String targetClass = thisJoinPoint.getTarget().getClass().getName();
            List<StackTraceElement> stackTraceElements = 
Arrays.asList(Thread.currentThread().getStackTrace());
            StackTraceHelper stackTraceHelper = new 
StackTraceHelper(stackTraceElements);
            DeprecatedMethodData deprecatedMethodData = 
stackTraceHelper.extractData(targetClass);

 //There is also some additional connections to db and other tools here.

}


In stackTraceHelper there are a number of settings that can be done what is 
relevant in the trace when we try to find the calling class.

These settings I want to to publish so they can be set for each product using 
this library.


So question is if I in all products using it need to create another aspect that 
inherits this one and can set the relevant properties.



so my aspect above would have:


aspect DeprecatedMethodLogger implements DeprecatedMethodLoggerApi {


}


DeprecatedMethodLoggerApi contains setting that can be done.


Then in the products I create:


aspect MyDepreactedMethodLogger extends DeprecatedMethodLogger {


}


Or is there a better way? Suggestions welcome.


br,


//mike





_______________________________________________
aspectj-users mailing list
aspectj-users@eclipse.org
To change your delivery options, retrieve your password, or unsubscribe from 
this list, visit
https://dev.eclipse.org/mailman/listinfo/aspectj-users

Reply via email to