[args4j] Port to JSR-269

Michal Srb msrb at fedoraproject.org
Tue May 6 06:43:07 UTC 2014


commit b35ea2f6625a26979b297ad6585abe83de401c83
Author: Michal Srb <msrb at redhat.com>
Date:   Tue May 6 08:16:59 2014 +0200

    Port to JSR-269

 0001-Port-to-JSR-269.patch |  438 ++++++++++++++++++++++++++++++++++++++++++++
 args4j.spec                |    9 +-
 2 files changed, 446 insertions(+), 1 deletions(-)
---
diff --git a/0001-Port-to-JSR-269.patch b/0001-Port-to-JSR-269.patch
new file mode 100644
index 0000000..ad017eb
--- /dev/null
+++ b/0001-Port-to-JSR-269.patch
@@ -0,0 +1,438 @@
+From 6636088282b21b3d8b7d0d1c5f3251005f5cd02d Mon Sep 17 00:00:00 2001
+From: Michal Srb <msrb at redhat.com>
+Date: Tue, 6 May 2014 07:51:51 +0200
+Subject: [PATCH] Port to JSR-269
+
+---
+ .../args4j/apt/AnnotationProcessorFactoryImpl.java | 154 ------------------
+ .../args4j/apt/AnnotationProcessorImpl.java        | 176 +++++++++++++++++++++
+ args4j-tools/src/org/kohsuke/args4j/apt/Main.java  |  17 +-
+ .../src/org/kohsuke/args4j/apt/TxtWriter.java      |   4 +-
+ .../src/org/kohsuke/args4j/apt/XmlWriter.java      |   4 +-
+ 5 files changed, 189 insertions(+), 166 deletions(-)
+ delete mode 100644 args4j-tools/src/org/kohsuke/args4j/apt/AnnotationProcessorFactoryImpl.java
+ create mode 100644 args4j-tools/src/org/kohsuke/args4j/apt/AnnotationProcessorImpl.java
+
+diff --git a/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationProcessorFactoryImpl.java b/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationProcessorFactoryImpl.java
+deleted file mode 100644
+index d7148f8..0000000
+--- a/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationProcessorFactoryImpl.java
++++ /dev/null
+@@ -1,154 +0,0 @@
+-package org.kohsuke.args4j.apt;
+-
+-import com.sun.mirror.apt.AnnotationProcessor;
+-import com.sun.mirror.apt.AnnotationProcessorEnvironment;
+-import com.sun.mirror.apt.AnnotationProcessorFactory;
+-import com.sun.mirror.declaration.AnnotationTypeDeclaration;
+-import com.sun.mirror.declaration.ClassDeclaration;
+-import com.sun.mirror.declaration.Declaration;
+-import com.sun.mirror.declaration.FieldDeclaration;
+-import com.sun.mirror.declaration.MethodDeclaration;
+-import com.sun.mirror.declaration.TypeDeclaration;
+-import com.sun.mirror.declaration.MemberDeclaration;
+-import com.sun.mirror.type.ClassType;
+-import com.sun.mirror.util.SimpleDeclarationVisitor;
+-import org.kohsuke.args4j.Argument;
+-import org.kohsuke.args4j.Option;
+-
+-import java.io.File;
+-import java.io.FileWriter;
+-import java.io.IOException;
+-import java.io.FileInputStream;
+-import java.util.Arrays;
+-import java.util.Collection;
+-import java.util.Collections;
+-import java.util.HashSet;
+-import java.util.Set;
+-import java.util.Properties;
+-
+-/**
+- * {@link AnnotationProcessorFactory} to be invoked by APT.
+- *
+- * This class receives options from the Main method through system properties (ouch!).
+- *
+- * @author Kohsuke Kawaguchi
+- */
+-public class AnnotationProcessorFactoryImpl implements AnnotationProcessorFactory {
+-
+-    private File outDir;
+-    private String format;
+-    private Properties resource = null;
+-
+-    public AnnotationProcessorFactoryImpl() {
+-        outDir = new File(System.getProperty("args4j.outdir"));
+-        format = System.getProperty("args4j.format");
+-
+-        String res = System.getProperty("args4j.resource");
+-        if(res!=null && res.length()>0) {
+-            try {
+-                resource = new Properties();
+-                resource.load(new FileInputStream(res));
+-            } catch (IOException e) {
+-                throw new Error(e);
+-            }
+-        }
+-    }
+-
+-    public Collection<String> supportedOptions() {
+-        return Collections.emptyList();
+-    }
+-
+-    public Collection<String> supportedAnnotationTypes() {
+-        return Arrays.asList(Option.class.getName(),Argument.class.getName());
+-    }
+-
+-    public AnnotationProcessor getProcessorFor(final Set<AnnotationTypeDeclaration> annotationTypeDeclarations, final AnnotationProcessorEnvironment env) {
+-        return new AnnotationProcessor() {
+-            public void process() {
+-                Collection<Declaration> params = env.getDeclarationsAnnotatedWith((AnnotationTypeDeclaration)env.getTypeDeclaration(Option.class.getName()));
+-
+-                final Set<TypeDeclaration> optionBeans = new HashSet<TypeDeclaration>();
+-                for (Declaration d : params) {
+-                    d.accept(new SimpleDeclarationVisitor() {
+-                        public void visitFieldDeclaration(FieldDeclaration f) {
+-                            TypeDeclaration dt = f.getDeclaringType();
+-                            optionBeans.add(dt);
+-                        }
+-
+-                        public void visitMethodDeclaration(MethodDeclaration m) {
+-                            optionBeans.add(m.getDeclaringType());
+-                        }
+-                    });
+-                }
+-
+-                for (TypeDeclaration t : optionBeans) {
+-                    // make sure that they are on classes
+-                    if(t instanceof ClassDeclaration) {
+-                        ClassDeclaration cd = (ClassDeclaration)t;
+-                        try {
+-                            AnnotationVisitor writer = createAnnotationVisitor(cd);
+-                            env.getMessager().printNotice("Processing "+cd.getQualifiedName());
+-                            scan(cd, writer);
+-                        } catch (IOException e) {
+-                            env.getMessager().printError(e.getMessage());
+-                        }
+-                    } else {
+-                        env.getMessager().printError(t.getPosition(),
+-                            "args4j annotations need to be placed on a class");
+-                    }
+-                }
+-            }
+-        };
+-    }
+-
+-    private AnnotationVisitor createAnnotationVisitor(ClassDeclaration cd) throws IOException {
+-        FileWriter out = new FileWriter(new File(outDir,cd.getQualifiedName()+"."+format.toLowerCase()));
+-        AnnotationVisitor writer;
+-        if(format.equals("XML"))
+-            writer = new XmlWriter(out,cd);
+-        else if (format.equals("TXT"))
+-            writer = new TxtWriter(out, cd);
+-        else
+-            writer = new HtmlWriter(out);
+-        return new AnnotationVisitorReorderer(writer);
+-    }
+-
+-    private void scan(ClassDeclaration decl, AnnotationVisitor visitor) {
+-        while(decl!=null) {
+-            for( FieldDeclaration f : decl.getFields() )
+-                scan(f, visitor);
+-
+-            for (MethodDeclaration m : decl.getMethods())
+-                scan(m, visitor);
+-
+-            ClassType sc = decl.getSuperclass();
+-            if(sc==null)    break;
+-
+-            decl = sc.getDeclaration();
+-        }
+-
+-        visitor.done();
+-    }
+-
+-    private void scan(MemberDeclaration f, AnnotationVisitor visitor) {
+-        Option o = f.getAnnotation(Option.class);
+-        if(o==null) return;
+-
+-        String usage = getUsage(o);
+-        if(isOptionHidden(usage))    return;
+-
+-        visitor.onOption(new OptionWithUsage(o, usage));
+-    }
+-
+-    private boolean isOptionHidden(String usage) {
+-        return usage==null || usage.length()==0;
+-    }
+-
+-    private String getUsage(Option o) {
+-        if(resource==null)
+-            return o.usage();
+-        else
+-            return resource.getProperty(o.usage());
+-    }
+-
+-}
+diff --git a/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationProcessorImpl.java b/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationProcessorImpl.java
+new file mode 100644
+index 0000000..14fd3c0
+--- /dev/null
++++ b/args4j-tools/src/org/kohsuke/args4j/apt/AnnotationProcessorImpl.java
+@@ -0,0 +1,176 @@
++package org.kohsuke.args4j.apt;
++
++import java.io.File;
++import java.io.FileInputStream;
++import java.io.FileWriter;
++import java.io.IOException;
++import java.util.Arrays;
++import java.util.HashSet;
++import java.util.Properties;
++import java.util.Set;
++
++import javax.annotation.processing.AbstractProcessor;
++import javax.annotation.processing.Processor;
++import javax.annotation.processing.RoundEnvironment;
++import javax.lang.model.SourceVersion;
++import javax.lang.model.element.Element;
++import javax.lang.model.element.ExecutableElement;
++import javax.lang.model.element.TypeElement;
++import javax.lang.model.element.VariableElement;
++import javax.lang.model.util.SimpleElementVisitor8;
++import javax.lang.model.util.Types;
++import javax.tools.Diagnostic.Kind;
++
++import org.kohsuke.args4j.Argument;
++import org.kohsuke.args4j.Option;
++
++/**
++ * Annotation {@link Processor} to be invoked by javac.
++ * 
++ * This class receives options from the Main method through system properties
++ * (ouch!).
++ * 
++ * @author Kohsuke Kawaguchi
++ */
++
++public class AnnotationProcessorImpl extends AbstractProcessor {
++
++    private File outDir;
++    private String format;
++    private Properties resource = null;
++
++    public AnnotationProcessorImpl() {
++        outDir = new File(System.getProperty("args4j.outdir"));
++        format = System.getProperty("args4j.format");
++
++        String res = System.getProperty("args4j.resource");
++        if (res != null && res.length() > 0) {
++            try {
++                resource = new Properties();
++                resource.load(new FileInputStream(res));
++            } catch (IOException e) {
++                throw new Error(e);
++            }
++        }
++    }
++
++    @Override
++    public Set<String> getSupportedAnnotationTypes() {
++        return new HashSet<String>(Arrays.asList(Option.class.getName(),
++                Argument.class.getName()));
++    }
++
++    @Override
++    public SourceVersion getSupportedSourceVersion() {
++
++        // inspiration taken from metainf-services project
++        try {
++            return SourceVersion.valueOf("RELEASE_8");
++        } catch (IllegalArgumentException x) {
++        }
++        try {
++            return SourceVersion.valueOf("RELEASE_7");
++        } catch (IllegalArgumentException x) {
++        }
++
++        return SourceVersion.RELEASE_6;
++    }
++
++    private AnnotationVisitor createAnnotationVisitor(TypeElement te)
++            throws IOException {
++        FileWriter out = new FileWriter(new File(outDir, te.getQualifiedName()
++                + "." + format.toLowerCase()));
++        AnnotationVisitor writer;
++        if (format.equals("XML"))
++            writer = new XmlWriter(out, te);
++        else if (format.equals("TXT"))
++            writer = new TxtWriter(out, te);
++        else
++            writer = new HtmlWriter(out);
++        return new AnnotationVisitorReorderer(writer);
++    }
++
++    private void scan(TypeElement decl, AnnotationVisitor visitor) {
++
++        Types typeUtils = processingEnv.getTypeUtils();
++
++        while (decl != null) {
++            for (Element f : decl.getEnclosedElements()) {
++                scan(f, visitor);
++            }
++            decl = (TypeElement) typeUtils.asElement(decl.getSuperclass());
++        }
++
++        visitor.done();
++    }
++
++    private void scan(Element f, AnnotationVisitor visitor) {
++        Option o = f.getAnnotation(Option.class);
++        if (o == null)
++            return;
++
++        String usage = getUsage(o);
++        if (isOptionHidden(usage))
++            return;
++
++        visitor.onOption(new OptionWithUsage(o, usage));
++    }
++
++    private boolean isOptionHidden(String usage) {
++        return usage == null || usage.length() == 0;
++    }
++
++    private String getUsage(Option o) {
++        if (resource == null)
++            return o.usage();
++        else
++            return resource.getProperty(o.usage());
++    }
++
++    @Override
++    public boolean process(Set<? extends TypeElement> annotations,
++            RoundEnvironment roundEnv) {
++
++        Set<? extends Element> params = roundEnv
++                .getElementsAnnotatedWith(Option.class);
++
++        final Set<TypeElement> optionBeans = new HashSet<TypeElement>();
++
++        for (Element d : params) {
++
++            d.accept(new SimpleElementVisitor8<Void, Void>() {
++                @Override
++                public Void visitVariable(VariableElement e, Void p) {
++                    TypeElement dt = (TypeElement) e.getEnclosingElement();
++                    optionBeans.add(dt);
++                    return null;
++                }
++
++                public Void visitExecutable(ExecutableElement m, Void p) {
++                    optionBeans.add((TypeElement) m.getEnclosingElement());
++                    return null;
++                }
++            }, null);
++        }
++
++        for (TypeElement t : optionBeans) {
++            // make sure that they are on classes
++            if (t.getKind().isClass()) {
++                try {
++                    AnnotationVisitor writer = createAnnotationVisitor(t);
++                    processingEnv.getMessager().printMessage(Kind.NOTE,
++                            "Processing " + t.getQualifiedName());
++                    scan(t, writer);
++                } catch (IOException e) {
++                    processingEnv.getMessager().printMessage(Kind.ERROR,
++                            e.getMessage());
++                }
++            } else {
++                processingEnv.getMessager().printMessage(Kind.ERROR,
++                        "args4j annotations need to be placed on a class", t);
++            }
++        }
++
++        return true;
++    }
++}
+diff --git a/args4j-tools/src/org/kohsuke/args4j/apt/Main.java b/args4j-tools/src/org/kohsuke/args4j/apt/Main.java
+index 92d0205..91bd47a 100644
+--- a/args4j-tools/src/org/kohsuke/args4j/apt/Main.java
++++ b/args4j-tools/src/org/kohsuke/args4j/apt/Main.java
+@@ -13,6 +13,9 @@ import java.net.URLClassLoader;
+ import java.util.ArrayList;
+ import java.util.List;
+ 
++import javax.tools.JavaCompiler;
++import javax.tools.ToolProvider;
++
+ /**
+  * Entry point that invokes APT.
+  *
+@@ -62,15 +65,13 @@ public class Main {
+         if(resourceName==null)  resourceName = "";  // can't have null in properties
+         System.setProperty("args4j.resource",resourceName);
+ 
+-        aptArgs.add(0,"-nocompile");
++        aptArgs.add(0, "-proc:only");
++        aptArgs.add(1, "-processor");
++        aptArgs.add(2, AnnotationProcessorImpl.class.getName());
++
++        JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
+ 
+-        // locate tools.jar
+-        ClassLoader cl = loadToolsJar();
+-        Class<?> apt = cl.loadClass("com.sun.tools.apt.Main");
+-        Method main = getProcessMethod(apt);
+-        return (Integer)main.invoke(null,new Object[]{
+-            cl.loadClass("org.kohsuke.args4j.apt.AnnotationProcessorFactoryImpl").newInstance(),
+-            aptArgs.toArray(new String[0])});
++        return javac.run(System.in, System.out, System.err, aptArgs.toArray(new String[0]));
+     }
+ 
+     private void printUsage(CmdLineParser parser) {
+diff --git a/args4j-tools/src/org/kohsuke/args4j/apt/TxtWriter.java b/args4j-tools/src/org/kohsuke/args4j/apt/TxtWriter.java
+index fc73b5c..ca98d8b 100644
+--- a/args4j-tools/src/org/kohsuke/args4j/apt/TxtWriter.java
++++ b/args4j-tools/src/org/kohsuke/args4j/apt/TxtWriter.java
+@@ -1,6 +1,6 @@
+ package org.kohsuke.args4j.apt;
+ 
+-import com.sun.mirror.declaration.ClassDeclaration;
++import javax.lang.model.element.TypeElement;
+ import org.kohsuke.args4j.Option;
+ 
+ import java.io.PrintWriter;
+@@ -14,7 +14,7 @@ import java.io.Writer;
+ class TxtWriter implements AnnotationVisitor {
+     private final PrintWriter out;
+ 
+-    public TxtWriter(Writer out, ClassDeclaration d) {
++    public TxtWriter(Writer out, TypeElement d) {
+         this.out = new PrintWriter(out);
+         this.out.println("Usage: " + d.getQualifiedName());
+     }
+diff --git a/args4j-tools/src/org/kohsuke/args4j/apt/XmlWriter.java b/args4j-tools/src/org/kohsuke/args4j/apt/XmlWriter.java
+index 1fcc5e5..0b20f31 100644
+--- a/args4j-tools/src/org/kohsuke/args4j/apt/XmlWriter.java
++++ b/args4j-tools/src/org/kohsuke/args4j/apt/XmlWriter.java
+@@ -1,6 +1,6 @@
+ package org.kohsuke.args4j.apt;
+ 
+-import com.sun.mirror.declaration.ClassDeclaration;
++import javax.lang.model.element.TypeElement;
+ 
+ import java.io.PrintWriter;
+ import java.io.Writer;
+@@ -13,7 +13,7 @@ import java.io.Writer;
+ class XmlWriter implements AnnotationVisitor {
+     private final PrintWriter out;
+ 
+-    public XmlWriter(Writer out, ClassDeclaration d) {
++    public XmlWriter(Writer out, TypeElement d) {
+         this.out = new PrintWriter(out);
+         this.out.println("<usage class=\'"+d.getQualifiedName()+"\'>");
+     }
+-- 
+1.9.0
+
diff --git a/args4j.spec b/args4j.spec
index 9adf376..5b8c76b 100644
--- a/args4j.spec
+++ b/args4j.spec
@@ -1,11 +1,13 @@
 Name:           args4j
 Version:        2.0.26
-Release:        3%{?dist}
+Release:        4%{?dist}
 Summary:        Java command line arguments parser
 License:        MIT
 URL:            http://args4j.kohsuke.org/
 Source0:        https://github.com/kohsuke/%{name}/archive/%{name}-site-%{version}.tar.gz
 
+Patch0:         0001-Port-to-JSR-269.patch
+
 BuildArch:      noarch
 
 BuildRequires:  maven-local
@@ -38,6 +40,8 @@ This package contains the API documentation for %{name}.
 %prep
 %setup -q -n %{name}-%{name}-site-%{version}
 
+%patch0 -p1
+
 # removing classpath addition
 sed -i 's/<addClasspath>true/<addClasspath>false/g' %{name}-tools/pom.xml
 
@@ -74,6 +78,9 @@ find -name '*.jar' -exec rm -f '{}' \;
 %doc %{name}/LICENSE.txt
 
 %changelog
+* Tue May 06 2014 Michal Srb <msrb at redhat.com> - 2.0.26-4
+- Port to JSR-269
+
 * Tue Mar 04 2014 Stanislav Ochotnicky <sochotnicky at redhat.com> - 2.0.26-3
 - Use Requires: java-headless rebuild (#1067528)
 


More information about the scm-commits mailing list