View | Details | Raw Unified | Return to bug 59804
Collapse All | Expand All

(-)src/testcases/org/apache/poi/TestDeprecatedFeatures.java (+125 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
package org.apache.poi;
19
20
import java.lang.reflect.AnnotatedElement;
21
import java.lang.reflect.Constructor;
22
import java.lang.reflect.Field;
23
import java.lang.reflect.Method;
24
import java.lang.reflect.Member;
25
import java.lang.Deprecated;
26
import java.lang.annotation.Annotation;
27
28
//import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
29
30
import org.apache.poi.util.Removal;
31
32
/**
33
 * Find classes, methods, and field in the POI project that have been deprecated and marked for removal
34
 * Looks for {@literal @}{@link java.lang.Deprecated} and {@literal @}{@link org.apache.poi.util.Removal}.
35
 *
36
 * Unfortunately, a feature that has been {@literal @}deprecated in the JavaDocs cannot be accessed by
37
 * reflection because JavaDocs are not compiled into the final classes.
38
 * Some features may be JavaDoc-deprecated and marked for {@literal @}Removal, but not {@literal @}Deprecated.
39
 *
40
 *
41
 * This class could be used to fail a build if a deprecated feature lingers well after its intended removal
42
 * date.
43
 * 
44
 * It may not be possible to remove a deprecated feature if other features that depend on it were not also
45
 * marked for removal. For example, if deprecation and removal annotations were added to an interface but
46
 * not to all implementing classes, we may have to wait another 2 releases to deprecate the forgotten 
47
 * features before removing the feature.
48
 *
49
 * For this reason, this unit test should be run in for-info-only mode, and a separate job that is not part
50
 * of the main JDK6-8 builds would be responsible for notifying when features marked for removal are past due.
51
 *
52
 * Based on http://www.vogella.com/tutorials/JavaAnnotations/article.html
53
 */
54
public class TestDeprecatedFeatures {
55
56
    private static String checkDeprecated(final String message, final AnnotatedElement e) {
57
        final Annotation deprecated = e.getAnnotation(Deprecated.class);
58
        final Removal removal = (Removal) e.getAnnotation(Removal.class);
59
60
        if (deprecated == null && removal == null) {
61
            return null;
62
        }
63
64
        // compare the current version from build.xml (given by 
65
        final String currentVersion = System.getProperty("version.id"); //set by build script (build.xml, build.gradle)
66
        if (currentVersion != null && removal != null) {
67
            final String removalVersion = removal.version();
68
            if (removalVersion != null) {
69
                // Compare the version numbers with some version-aware string parser
70
                // org.apache.maven.artifact.versioning.ComparableVersion is ASL 2.0-licensed
71
                // org.apache.maven.artifact.versioning.DefaultArtifactVersion
72
                //assertThat(new DefaultArtifactVersion(currentVersion),
73
                //        greaterThan(new DefaultArtifactVersion(removalVersion)));
74
            }
75
        }
76
        final String fullName = e.toString();
77
        final String preamble = message + " [" + fullName + "] ";
78
79
        if (deprecated != null && removal != null) {
80
            return preamble + "is deprecated and scheduled for removal in POI " + removal.version();
81
        }
82
        else if (deprecated != null) {
83
            return preamble + "is deprecated but no scheduled removal version is specified";
84
        }
85
        else if (removal != null) {
86
            return preamble + "is scheduled for removal in POI " + removal.version();
87
        }
88
        return null;
89
    }
90
    private static void check(final String message, final AnnotatedElement e) {
91
        String s = checkDeprecated(message, e);
92
        if (s != null) {
93
            System.out.println(s);
94
        }
95
    }
96
97
    public static void main(final String[] args) {
98
        Annotation deprecated, removal;
99
100
        for (final Class klass : ClassFinder.find("org.apache.poi")) {
101
            // check if the class is deprecated
102
            check("Class", klass);
103
            // inner classes and enums will be checked later by the ClassFinder.
104
105
            // check if the class contains any deprecated contructors
106
            for (final Constructor constructor : klass.getDeclaredConstructors()) {
107
                check("Constructor", constructor);
108
            }
109
            
110
            // check if the class contains any deprecated methods
111
            for (final Method method : klass.getDeclaredMethods()) {
112
                check("Method", method);
113
            }
114
115
            // check if the class contains any deprecated fields
116
            // https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html
117
            for (final Field field : klass.getDeclaredFields()) {
118
                check("Field", field);
119
            }
120
121
        }
122
    }
123
124
}
125
native
(-)src/testcases/org/apache/poi/ClassFinder.java (+54 lines)
Line 0 Link Here
1
2
package org.apache.poi;
3
// NON-FREE!
4
// Copied from http://stackoverflow.com/questions/15519626/how-to-get-all-classes-names-in-a-package
5
6
import java.io.File;
7
import java.net.URL;
8
import java.util.List;
9
import java.util.ArrayList;
10
11
public class ClassFinder {
12
13
    private static final char PKG_SEPARATOR = '.';
14
15
    private static final char DIR_SEPARATOR = '/';
16
17
    private static final String CLASS_FILE_SUFFIX = ".class";
18
19
    private static final String BAD_PACKAGE_ERROR = "Unable to get resources from path '%s'. Are you sure the package '%s' exists?";
20
21
    public static List<Class<?>> find(String scannedPackage) {
22
        String scannedPath = scannedPackage.replace(PKG_SEPARATOR, DIR_SEPARATOR);
23
        URL scannedUrl = Thread.currentThread().getContextClassLoader().getResource(scannedPath);
24
        if (scannedUrl == null) {
25
            throw new IllegalArgumentException(String.format(BAD_PACKAGE_ERROR, scannedPath, scannedPackage));
26
        }
27
        File scannedDir = new File(scannedUrl.getFile());
28
        List<Class<?>> classes = new ArrayList<Class<?>>();
29
        for (File file : scannedDir.listFiles()) {
30
            classes.addAll(find(file, scannedPackage));
31
        }
32
        return classes;
33
    }
34
35
    private static List<Class<?>> find(File file, String scannedPackage) {
36
        List<Class<?>> classes = new ArrayList<Class<?>>();
37
        String resource = scannedPackage + PKG_SEPARATOR + file.getName();
38
        if (file.isDirectory()) {
39
            for (File child : file.listFiles()) {
40
                classes.addAll(find(child, resource));
41
            }
42
        } else if (resource.endsWith(CLASS_FILE_SUFFIX)) {
43
            int endIndex = resource.length() - CLASS_FILE_SUFFIX.length();
44
            String className = resource.substring(0, endIndex);
45
            try {
46
                classes.add(Class.forName(className));
47
            } catch (ClassNotFoundException ignore) {
48
            }
49
        }
50
        return classes;
51
    }
52
53
}
54
native
(-)src/java/org/apache/poi/util/Removal.java (+2 lines)
Lines 58-61 Link Here
58
     * Example: "3.15"
58
     * Example: "3.15"
59
     */
59
     */
60
    String version() default "";
60
    String version() default "";
61
    // TODO: Verify that the version syntax is valid by parsing with a version-aware parser like
62
    // org.apache.maven.artifact.versioning.DefaultArtifactVersion
61
}
63
}
(-)src/testcases/org/apache/poi/TestTestDeprecatedFeatures.java (+76 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
package org.apache.poi;
19
20
import java.lang.Deprecated;
21
22
23
import org.apache.poi.util.Removal;
24
25
/**
26
 * A test class to verify that TestDeprecatedFeatures can find all the known deprecation types
27
 * with different visibility.
28
 */
29
@Deprecated
30
@Removal(version="3.14")
31
public class TestTestDeprecatedFeatures {
32
    @Deprecated
33
    @Removal(version="3.14")
34
    private static final int CLASS_CONST = 5;
35
36
    @Deprecated
37
    @Removal(version="3.14")
38
    protected int FIELD = 5;
39
40
    @Deprecated
41
    @Removal(version="3.14")
42
    public TestTestDeprecatedFeatures() {
43
    }
44
45
    @Deprecated
46
    @Removal(version="3.14")
47
    public class SomeDeprecatedInner {
48
        @Deprecated
49
        @Removal(version="3.14")
50
        private SomeDeprecatedInner() {
51
        }
52
    }
53
54
    // enums are a special case of class and will be recognized as a class with reflection
55
    @Deprecated
56
    @Removal(version="3.14")
57
    /*package*/ enum SomeDeprecatedEnum {
58
        MERCURY,
59
        VENUS,
60
        EARTH,
61
        MARS,
62
        JUPITER,
63
        SATURN,
64
        URANUS,
65
        NEPTUNE,
66
        @Deprecated
67
        @Removal(version="3.14")
68
        PLUTO
69
    }
70
71
    @Deprecated
72
    @Removal(version="3.14")
73
    public void someDeprecatedMethod() {
74
    }
75
} 
76
native

Return to bug 59804