[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