[BUILD] Use SuppressFrobidden annotation instead of class level excludes

Forbidden APIs 1.8 allows excludes based on annotations which can now be on methods etc. for more find grained control.

Closes #10560
This commit is contained in:
Simon Willnauer 2015-04-13 10:03:50 +02:00
parent df118214c4
commit d738b3d1e2
14 changed files with 94 additions and 58 deletions

28
pom.xml
View File

@ -1423,33 +1423,6 @@
<failOnUnsupportedJava>false</failOnUnsupportedJava>
<excludes>
<exclude>jsr166e/**</exclude>
<!-- start excludes for valid system-out -->
<exclude>org/elasticsearch/common/logging/log4j/ConsoleAppender*</exclude>
<exclude>org/elasticsearch/common/http/client/HttpDownloadHelper*</exclude>
<exclude>org/elasticsearch/common/cli/Terminal*</exclude>
<exclude>org/elasticsearch/plugins/PluginManager$SysOut.class</exclude>
<exclude>org/elasticsearch/common/http/client/HttpDownloadHelper.class</exclude>
<exclude>org/elasticsearch/bootstrap/Bootstrap.class</exclude>
<exclude>org/elasticsearch/Version.class</exclude>
<exclude>org/elasticsearch/common/lucene/search/Queries$QueryWrapperFilterFactory.class</exclude>
<!-- end excludes for valid system-out -->
<!-- start excludes for Math.abs -->
<exclude>org/elasticsearch/common/util/MathUtils.class</exclude>
<exclude>org/elasticsearch/common/math/UnboxedMathUtils.class</exclude>
<exclude>org/elasticsearch/cluster/routing/OperationRouting.class</exclude>
<!-- end excludes for Math.abs -->
<!-- start exclude for FilteredQuery -->
<exclude>org/elasticsearch/common/lucene/search/XFilteredQuery.class</exclude>
<!-- end exclude for FilteredQuery -->
<!-- start exclude for Channels utility class -->
<exclude>org/elasticsearch/common/io/Channels.class</exclude>
<!-- end exclude for Channels -->
<!-- start exclude for Lucene utility class -->
<exclude>org/elasticsearch/common/lucene/Lucene$LenientParser.class</exclude>
<!-- end exclude for Lucene -->
<!-- start exclude for Future utility class -->
<exclude>org/elasticsearch/common/util/concurrent/FutureUtils.class</exclude>
<!-- end exclude for Future utility class -->
</excludes>
<bundledSignatures>
<!-- This will automatically choose the right signatures based on 'targetVersion': -->
@ -1462,6 +1435,7 @@
<signaturesFile>dev-tools/forbidden/all-signatures.txt</signaturesFile>
</signaturesFiles>
<signatures>${forbidden.signatures}</signatures>
<suppressAnnotations><annotation>**.SuppressForbidden</annotation></suppressAnnotations>
</configuration>
<phase>compile</phase>
<goals>

View File

@ -21,6 +21,7 @@ package org.elasticsearch;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
@ -580,6 +581,7 @@ public class Version {
return sb.toString();
}
@SuppressForbidden(reason = "System.out.*")
public static void main(String[] args) {
System.out.println("Version: " + Version.CURRENT + ", Build: " + Build.CURRENT.hashShort() + "/" + Build.CURRENT.timestamp() + ", JVM: " + JvmInfo.jvmInfo().version());
}

View File

@ -22,6 +22,7 @@ package org.elasticsearch.bootstrap;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.Version;
import org.elasticsearch.common.PidFile;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.inject.CreationException;
import org.elasticsearch.common.inject.spi.Message;
@ -90,6 +91,7 @@ public class Bootstrap {
}
}
@SuppressForbidden(reason = "Exception#printStackTrace()")
private static void setupLogging(Tuple<Settings, Environment> tuple) {
try {
tuple.v1().getClassLoader().loadClass("org.apache.log4j.Logger");
@ -99,7 +101,7 @@ public class Bootstrap {
} catch (NoClassDefFoundError e) {
// no log4j
} catch (Exception e) {
System.err.println("Failed to configure logging...");
sysError("Failed to configure logging...", false);
e.printStackTrace();
}
}
@ -154,8 +156,7 @@ public class Bootstrap {
PidFile.create(Paths.get(pidFile), true);
} catch (Exception e) {
String errorMessage = buildErrorMessage("pid", e);
System.err.println(errorMessage);
System.err.flush();
sysError(errorMessage, true);
System.exit(3);
}
}
@ -171,8 +172,7 @@ public class Bootstrap {
setupLogging(tuple);
} catch (Exception e) {
String errorMessage = buildErrorMessage("Setup", e);
System.err.println(errorMessage);
System.err.flush();
sysError(errorMessage, true);
System.exit(3);
}
@ -191,7 +191,7 @@ public class Bootstrap {
try {
if (!foreground) {
Loggers.disableConsoleLogging();
System.out.close();
closeSystOut();
}
// fail if using broken version
@ -203,7 +203,7 @@ public class Bootstrap {
bootstrap.start();
if (!foreground) {
System.err.close();
closeSysError();
}
keepAliveLatch = new CountDownLatch(1);
@ -234,8 +234,7 @@ public class Bootstrap {
}
String errorMessage = buildErrorMessage(stage, e);
if (foreground) {
System.err.println(errorMessage);
System.err.flush();
sysError(errorMessage, true);
Loggers.disableConsoleLogging();
}
logger.error("Exception", e);
@ -244,6 +243,24 @@ public class Bootstrap {
}
}
@SuppressForbidden(reason = "System#out")
private static void closeSystOut() {
System.out.close();
}
@SuppressForbidden(reason = "System#err")
private static void closeSysError() {
System.err.close();
}
@SuppressForbidden(reason = "System#err")
private static void sysError(String line, boolean flush) {
System.err.println(line);
if (flush) {
System.err.flush();
}
}
private static String buildErrorMessage(String stage, Throwable e) {
StringBuilder errorMessage = new StringBuilder("{").append(Version.CURRENT).append("}: ");
errorMessage.append(stage).append(" Failed ...\n");

View File

@ -28,6 +28,7 @@ import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.routing.allocation.decider.AwarenessAllocationDecider;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.math.MathUtils;
@ -247,6 +248,7 @@ public class OperationRouting extends AbstractComponent {
return indexShard;
}
@SuppressForbidden(reason = "Math#abs is trappy")
private int shardId(ClusterState clusterState, String index, String type, String id, @Nullable String routing) {
final IndexMetaData indexMetaData = indexMetaData(clusterState, index);
final Version createdVersion = indexMetaData.getCreationVersion();

View File

@ -0,0 +1,33 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.elasticsearch.common;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
/**
* Annotation to suppress forbidden-apis errors inside a whole class, a method, or a field.
*/
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
public @interface SuppressForbidden {
String reason();
}

View File

@ -20,6 +20,7 @@
package org.elasticsearch.common.cli;
import org.apache.commons.cli.CommandLine;
import org.elasticsearch.common.SuppressForbidden;
import java.io.*;
import java.util.Locale;
@ -27,6 +28,7 @@ import java.util.Locale;
/**
*
*/
@SuppressForbidden(reason = "System#out")
public abstract class Terminal {
public static final String DEBUG_SYSTEM_PROPERTY = "es.cli.debug";
@ -163,6 +165,7 @@ public abstract class Terminal {
}
}
@SuppressForbidden(reason = "System#out")
private static class SystemTerminal extends Terminal {
private final PrintWriter printWriter = new PrintWriter(System.out);

View File

@ -23,6 +23,7 @@ import org.apache.lucene.util.IOUtils;
import org.elasticsearch.ElasticsearchTimeoutException;
import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.unit.TimeValue;
import java.io.*;
@ -134,6 +135,7 @@ public class HttpDownloadHelper {
/**
* verbose progress system prints to some output stream
*/
@SuppressForbidden(reason = "System#out")
public static class VerboseProgress implements DownloadProgress {
private int dots = 0;
// CheckStyle:VisibilityModifier OFF - bc

View File

@ -19,6 +19,7 @@
package org.elasticsearch.common.io;
import org.elasticsearch.common.SuppressForbidden;
import org.jboss.netty.buffer.ChannelBuffer;
import java.io.EOFException;
@ -28,6 +29,7 @@ import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.WritableByteChannel;
@SuppressForbidden(reason = "Channel#read")
public final class Channels {
private Channels() {

View File

@ -22,6 +22,7 @@ package org.elasticsearch.common.logging.log4j;
import org.apache.log4j.Layout;
import org.apache.log4j.WriterAppender;
import org.apache.log4j.helpers.LogLog;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.logging.Loggers;
import java.io.IOException;
@ -138,6 +139,7 @@ public class ConsoleAppender extends WriterAppender {
* Prepares the appender for use.
*/
@Override
@SuppressForbidden(reason = "System#out")
public void activateOptions() {
if (follow) {
if (target.equals(SYSTEM_ERR)) {
@ -172,6 +174,7 @@ public class ConsoleAppender extends WriterAppender {
* An implementation of OutputStream that redirects to the
* current System.err.
*/
@SuppressForbidden(reason = "System#err")
private static class SystemErrStream extends OutputStream {
public SystemErrStream() {
}
@ -194,6 +197,7 @@ public class ConsoleAppender extends WriterAppender {
}
@Override
public void write(final byte[] b, final int off, final int len)
throws IOException {
if (!Loggers.consoleLoggingEnabled()) {
@ -215,6 +219,7 @@ public class ConsoleAppender extends WriterAppender {
* An implementation of OutputStream that redirects to the
* current System.out.
*/
@SuppressForbidden(reason = "System#err")
private static class SystemOutStream extends OutputStream {
public SystemOutStream() {
}

View File

@ -54,6 +54,7 @@ import org.elasticsearch.ElasticsearchIllegalStateException;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.logging.ESLogger;
@ -659,6 +660,7 @@ public class Lucene {
return LenientParser.parse(toParse, defaultValue);
}
@SuppressForbidden(reason = "Version#parseLeniently() used in a central place")
private static final class LenientParser {
public static Version parse(String toParse, Version defaultValue) {
if (Strings.hasLength(toParse)) {

View File

@ -21,6 +21,7 @@ package org.elasticsearch.common.lucene.search;
import org.apache.lucene.search.*;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.index.search.child.CustomQueryWrappingFilter;
@ -148,22 +149,12 @@ public class Queries {
* If a filter has an anti per segment execution / caching nature then @{@link CustomQueryWrappingFilter} is returned
* otherwise the standard {@link org.apache.lucene.search.QueryWrapperFilter} is returned.
*/
@SuppressForbidden(reason = "QueryWrapperFilter cachability")
public static Filter wrap(Query query, QueryParseContext context) {
return FACTORY.wrap(query, context);
}
private static final QueryWrapperFilterFactory FACTORY = new QueryWrapperFilterFactory();
// NOTE: This is a separate class since we added QueryWrapperFilter as a forbidden API
// that way we can exclude only the inner class without excluding the entire Queries class
// and potentially miss a forbidden API usage!
private static final class QueryWrapperFilterFactory {
public Filter wrap(Query query, QueryParseContext context) {
if (context.requireCustomQueryWrappingFilter() || CustomQueryWrappingFilter.shouldUseCustomQueryWrappingFilter(query)) {
return new CustomQueryWrappingFilter(query);
} else {
return new QueryWrapperFilter(query);
}
if (context.requireCustomQueryWrappingFilter() || CustomQueryWrappingFilter.shouldUseCustomQueryWrappingFilter(query)) {
return new CustomQueryWrappingFilter(query);
} else {
return new QueryWrapperFilter(query);
}
}
}

View File

@ -19,6 +19,8 @@
package org.elasticsearch.common.math;
import org.elasticsearch.common.SuppressForbidden;
import java.util.concurrent.ThreadLocalRandom;
/**
@ -456,18 +458,22 @@ public class UnboxedMathUtils {
return ThreadLocalRandom.current().nextLong(l);
}
@SuppressForbidden(reason = "Math#abs is trappy")
public static int abs(Integer a) {
return Math.abs(a);
}
@SuppressForbidden(reason = "Math#abs is trappy")
public static long abs(Long a) {
return Math.abs(a);
}
@SuppressForbidden(reason = "Math#abs is trappy")
public static float abs(Float a) {
return Math.abs(a);
}
@SuppressForbidden(reason = "Math#abs is trappy")
public static double abs(Double a) {
return Math.abs(a);
}

View File

@ -19,7 +19,7 @@
package org.elasticsearch.common.util.concurrent;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.common.SuppressForbidden;
import java.util.concurrent.Future;
@ -27,6 +27,7 @@ import java.util.concurrent.Future;
*/
public class FutureUtils {
@SuppressForbidden(reason = "Future#cancel()")
public static boolean cancel(Future<?> toCancel) {
if (toCancel != null) {
return toCancel.cancel(false); // this method is a forbidden API since it interrupts threads

View File

@ -21,26 +21,22 @@ package org.elasticsearch.plugins;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import org.apache.lucene.util.IOUtils;
import org.elasticsearch.*;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.http.client.HttpDownloadHelper;
import org.elasticsearch.common.io.FileSystemUtils;
import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.env.Environment;
import org.elasticsearch.index.Index;
import org.elasticsearch.node.internal.InternalSettingsPreparer;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.MalformedURLException;
@ -48,7 +44,6 @@ import java.net.URL;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.util.*;
@ -582,6 +577,7 @@ public class PluginManager {
if (outputMode != OutputMode.SILENT) SysOut.println(line);
}
@SuppressForbidden(reason = "System#out")
static class SysOut {
public static void newline() {