ASF Bugzilla – Attachment 34767 Details for
Bug 59804
Add annotation for indicating when deprecated features may be removed
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Find @Deprecated and @Removal annotations with reflection
bug59804.patch (text/plain), 11.72 KB, created by
Javen O'Neal
on 2017-02-20 10:57:49 UTC
(
hide
)
Description:
Find @Deprecated and @Removal annotations with reflection
Filename:
MIME Type:
Creator:
Javen O'Neal
Created:
2017-02-20 10:57:49 UTC
Size:
11.72 KB
patch
obsolete
>Index: src/testcases/org/apache/poi/TestDeprecatedFeatures.java >=================================================================== >--- src/testcases/org/apache/poi/TestDeprecatedFeatures.java (revision 0) >+++ src/testcases/org/apache/poi/TestDeprecatedFeatures.java (working copy) >@@ -0,0 +1,124 @@ >+/* ==================================================================== >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at >+ >+ http://www.apache.org/licenses/LICENSE-2.0 >+ >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. >+==================================================================== */ >+ >+package org.apache.poi; >+ >+import java.lang.reflect.AnnotatedElement; >+import java.lang.reflect.Constructor; >+import java.lang.reflect.Field; >+import java.lang.reflect.Method; >+import java.lang.reflect.Member; >+import java.lang.Deprecated; >+import java.lang.annotation.Annotation; >+ >+//import org.apache.maven.artifact.versioning.DefaultArtifactVersion; >+ >+import org.apache.poi.util.Removal; >+ >+/** >+ * Find classes, methods, and field in the POI project that have been deprecated and marked for removal >+ * Looks for {@literal @}{@link java.lang.Deprecated} and {@literal @}{@link org.apache.poi.util.Removal}. >+ * >+ * Unfortunately, a feature that has been {@literal @}deprecated in the JavaDocs cannot be accessed by >+ * reflection because JavaDocs are not compiled into the final classes. >+ * Some features may be JavaDoc-deprecated and marked for {@literal @}Removal, but not {@literal @}Deprecated. >+ * >+ * >+ * This class could be used to fail a build if a deprecated feature lingers well after its intended removal >+ * date. >+ * >+ * It may not be possible to remove a deprecated feature if other features that depend on it were not also >+ * marked for removal. For example, if deprecation and removal annotations were added to an interface but >+ * not to all implementing classes, we may have to wait another 2 releases to deprecate the forgotten >+ * features before removing the feature. >+ * >+ * For this reason, this unit test should be run in for-info-only mode, and a separate job that is not part >+ * of the main JDK6-8 builds would be responsible for notifying when features marked for removal are past due. >+ * >+ * Based on http://www.vogella.com/tutorials/JavaAnnotations/article.html >+ */ >+public class TestDeprecatedFeatures { >+ >+ private static String checkDeprecated(final String message, final AnnotatedElement e) { >+ final Annotation deprecated = e.getAnnotation(Deprecated.class); >+ final Removal removal = (Removal) e.getAnnotation(Removal.class); >+ >+ if (deprecated == null && removal == null) { >+ return null; >+ } >+ >+ // compare the current version from build.xml (given by >+ final String currentVersion = System.getProperty("version.id"); //set by build script (build.xml, build.gradle) >+ if (currentVersion != null && removal != null) { >+ final String removalVersion = removal.version(); >+ if (removalVersion != null) { >+ // Compare the version numbers with some version-aware string parser >+ // org.apache.maven.artifact.versioning.ComparableVersion is ASL 2.0-licensed >+ // org.apache.maven.artifact.versioning.DefaultArtifactVersion >+ //assertThat(new DefaultArtifactVersion(currentVersion), >+ // greaterThan(new DefaultArtifactVersion(removalVersion))); >+ } >+ } >+ final String fullName = e.toString(); >+ final String preamble = message + " [" + fullName + "] "; >+ >+ if (deprecated != null && removal != null) { >+ return preamble + "is deprecated and scheduled for removal in POI " + removal.version(); >+ } >+ else if (deprecated != null) { >+ return preamble + "is deprecated but no scheduled removal version is specified"; >+ } >+ else if (removal != null) { >+ return preamble + "is scheduled for removal in POI " + removal.version(); >+ } >+ return null; >+ } >+ private static void check(final String message, final AnnotatedElement e) { >+ String s = checkDeprecated(message, e); >+ if (s != null) { >+ System.out.println(s); >+ } >+ } >+ >+ public static void main(final String[] args) { >+ Annotation deprecated, removal; >+ >+ for (final Class klass : ClassFinder.find("org.apache.poi")) { >+ // check if the class is deprecated >+ check("Class", klass); >+ // inner classes and enums will be checked later by the ClassFinder. >+ >+ // check if the class contains any deprecated contructors >+ for (final Constructor constructor : klass.getDeclaredConstructors()) { >+ check("Constructor", constructor); >+ } >+ >+ // check if the class contains any deprecated methods >+ for (final Method method : klass.getDeclaredMethods()) { >+ check("Method", method); >+ } >+ >+ // check if the class contains any deprecated fields >+ // https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html >+ for (final Field field : klass.getDeclaredFields()) { >+ check("Field", field); >+ } >+ >+ } >+ } >+ >+} > >Property changes on: src/testcases/org/apache/poi/TestDeprecatedFeatures.java >___________________________________________________________________ >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Index: src/testcases/org/apache/poi/ClassFinder.java >=================================================================== >--- src/testcases/org/apache/poi/ClassFinder.java (revision 0) >+++ src/testcases/org/apache/poi/ClassFinder.java (working copy) >@@ -0,0 +1,53 @@ >+ >+package org.apache.poi; >+// NON-FREE! >+// Copied from http://stackoverflow.com/questions/15519626/how-to-get-all-classes-names-in-a-package >+ >+import java.io.File; >+import java.net.URL; >+import java.util.List; >+import java.util.ArrayList; >+ >+public class ClassFinder { >+ >+ private static final char PKG_SEPARATOR = '.'; >+ >+ private static final char DIR_SEPARATOR = '/'; >+ >+ private static final String CLASS_FILE_SUFFIX = ".class"; >+ >+ private static final String BAD_PACKAGE_ERROR = "Unable to get resources from path '%s'. Are you sure the package '%s' exists?"; >+ >+ public static List<Class<?>> find(String scannedPackage) { >+ String scannedPath = scannedPackage.replace(PKG_SEPARATOR, DIR_SEPARATOR); >+ URL scannedUrl = Thread.currentThread().getContextClassLoader().getResource(scannedPath); >+ if (scannedUrl == null) { >+ throw new IllegalArgumentException(String.format(BAD_PACKAGE_ERROR, scannedPath, scannedPackage)); >+ } >+ File scannedDir = new File(scannedUrl.getFile()); >+ List<Class<?>> classes = new ArrayList<Class<?>>(); >+ for (File file : scannedDir.listFiles()) { >+ classes.addAll(find(file, scannedPackage)); >+ } >+ return classes; >+ } >+ >+ private static List<Class<?>> find(File file, String scannedPackage) { >+ List<Class<?>> classes = new ArrayList<Class<?>>(); >+ String resource = scannedPackage + PKG_SEPARATOR + file.getName(); >+ if (file.isDirectory()) { >+ for (File child : file.listFiles()) { >+ classes.addAll(find(child, resource)); >+ } >+ } else if (resource.endsWith(CLASS_FILE_SUFFIX)) { >+ int endIndex = resource.length() - CLASS_FILE_SUFFIX.length(); >+ String className = resource.substring(0, endIndex); >+ try { >+ classes.add(Class.forName(className)); >+ } catch (ClassNotFoundException ignore) { >+ } >+ } >+ return classes; >+ } >+ >+} > >Property changes on: src/testcases/org/apache/poi/ClassFinder.java >___________________________________________________________________ >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property >Index: src/java/org/apache/poi/util/Removal.java >=================================================================== >--- src/java/org/apache/poi/util/Removal.java (revision 1783736) >+++ src/java/org/apache/poi/util/Removal.java (working copy) >@@ -58,4 +58,6 @@ > * Example: "3.15" > */ > String version() default ""; >+ // TODO: Verify that the version syntax is valid by parsing with a version-aware parser like >+ // org.apache.maven.artifact.versioning.DefaultArtifactVersion > } >Index: src/testcases/org/apache/poi/TestTestDeprecatedFeatures.java >=================================================================== >--- src/testcases/org/apache/poi/TestTestDeprecatedFeatures.java (revision 0) >+++ src/testcases/org/apache/poi/TestTestDeprecatedFeatures.java (working copy) >@@ -0,0 +1,75 @@ >+/* ==================================================================== >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at >+ >+ http://www.apache.org/licenses/LICENSE-2.0 >+ >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. >+==================================================================== */ >+ >+package org.apache.poi; >+ >+import java.lang.Deprecated; >+ >+ >+import org.apache.poi.util.Removal; >+ >+/** >+ * A test class to verify that TestDeprecatedFeatures can find all the known deprecation types >+ * with different visibility. >+ */ >+@Deprecated >+@Removal(version="3.14") >+public class TestTestDeprecatedFeatures { >+ @Deprecated >+ @Removal(version="3.14") >+ private static final int CLASS_CONST = 5; >+ >+ @Deprecated >+ @Removal(version="3.14") >+ protected int FIELD = 5; >+ >+ @Deprecated >+ @Removal(version="3.14") >+ public TestTestDeprecatedFeatures() { >+ } >+ >+ @Deprecated >+ @Removal(version="3.14") >+ public class SomeDeprecatedInner { >+ @Deprecated >+ @Removal(version="3.14") >+ private SomeDeprecatedInner() { >+ } >+ } >+ >+ // enums are a special case of class and will be recognized as a class with reflection >+ @Deprecated >+ @Removal(version="3.14") >+ /*package*/ enum SomeDeprecatedEnum { >+ MERCURY, >+ VENUS, >+ EARTH, >+ MARS, >+ JUPITER, >+ SATURN, >+ URANUS, >+ NEPTUNE, >+ @Deprecated >+ @Removal(version="3.14") >+ PLUTO >+ } >+ >+ @Deprecated >+ @Removal(version="3.14") >+ public void someDeprecatedMethod() { >+ } >+} > >Property changes on: src/testcases/org/apache/poi/TestTestDeprecatedFeatures.java >___________________________________________________________________ >Added: svn:eol-style >## -0,0 +1 ## >+native >\ No newline at end of property
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 59804
: 34767