Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

master merge into 3.x #4768

Merged
merged 10 commits into from
Apr 19, 2021
5 changes: 2 additions & 3 deletions connectors/helidon-connector/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.

This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -34,8 +34,7 @@
<dependency>
<groupId>io.helidon.jersey</groupId>
<artifactId>helidon-jersey-connector</artifactId>
<!-- Use 2.0.3 when available -->
<version>2.0.2</version>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -139,7 +139,6 @@ public EventOutput getCommentsOnlyStream() throws IOException {
}

@Test
@Ignore //2.0.0-M3
public void testReadSseEventAsPlainString() throws Exception {
final Response r = target().path("test/single").request().get(Response.class);
assertThat(r.readEntity(String.class), containsString("single"));
@@ -189,7 +188,6 @@ public void onEvent(InboundEvent inboundEvent) {
}

@Test
@Ignore // 2.0.0-M3
public void testReadFromClosedOutput() throws Exception {
/**
* Need to disable HTTP Keep-Alive to prevent this test from hanging in HttpURLConnection
Original file line number Diff line number Diff line change
@@ -73,7 +73,8 @@ public class HttpUrlConnector implements Connector {
private static final String ALLOW_RESTRICTED_HEADERS_SYSTEM_PROPERTY = "sun.net.http.allowRestrictedHeaders";
// Avoid multi-thread uses of HttpsURLConnection.getDefaultSSLSocketFactory() because it does not implement a
// proper lazy-initialization. See https://github.com/jersey/jersey/issues/3293
private static final SSLSocketFactory DEFAULT_SSL_SOCKET_FACTORY = HttpsURLConnection.getDefaultSSLSocketFactory();
private static final LazyValue<SSLSocketFactory> DEFAULT_SSL_SOCKET_FACTORY =
Values.lazy((Value<SSLSocketFactory>) () -> HttpsURLConnection.getDefaultSSLSocketFactory());
// The list of restricted headers is extracted from sun.net.www.protocol.http.HttpURLConnection
private static final String[] restrictedHeaders = {
"Access-Control-Request-Headers",
@@ -305,7 +306,7 @@ protected void secureConnection(final JerseyClient client, final HttpURLConnecti
suc.setHostnameVerifier(verifier);
}

if (DEFAULT_SSL_SOCKET_FACTORY == suc.getSSLSocketFactory()) {
if (DEFAULT_SSL_SOCKET_FACTORY.get() == suc.getSSLSocketFactory()) {
// indicates that the custom socket factory was not set
suc.setSSLSocketFactory(sslSocketFactory.get());
}
5 changes: 5 additions & 0 deletions core-common/pom.xml
Original file line number Diff line number Diff line change
@@ -216,6 +216,11 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -53,18 +53,20 @@
final class ClientLoggingFilter extends LoggingInterceptor implements ClientRequestFilter, ClientResponseFilter {

/**
* Create a logging filter with custom logger and custom settings of entity
* Create a logging filter using builder instance with custom logger and custom settings of entity
* logging.
*
* @param logger the logger to log messages to.
* @param level level at which the messages will be logged.
* @param verbosity verbosity of the logged messages. See {@link Verbosity}.
* @param maxEntitySize maximum number of entity bytes to be logged (and buffered) - if the entity is larger,
* @param builder loggingFeatureBuilder which contains values for:
* logger the logger to log messages to.
* level level at which the messages will be logged.
* verbosity verbosity of the logged messages. See {@link Verbosity}.
* maxEntitySize maximum number of entity bytes to be logged (and buffered) - if the entity is larger,
* logging filter will print (and buffer in memory) only the specified number of bytes
* and print "...more..." string at the end. Negative values are interpreted as zero.
* separator delimiter for particular log lines. Default is Linux new line delimiter
*/
public ClientLoggingFilter(final Logger logger, final Level level, final Verbosity verbosity, final int maxEntitySize) {
super(logger, level, verbosity, maxEntitySize);
public ClientLoggingFilter(LoggingFeature.LoggingFeatureBuilder builder) {
super(builder);
}

@Override
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -40,6 +40,7 @@
* <li>{@link #LOGGING_FEATURE_LOGGER_LEVEL}</li>
* <li>{@link #LOGGING_FEATURE_VERBOSITY}</li>
* <li>{@link #LOGGING_FEATURE_MAX_ENTITY_SIZE}</li>
* <li>{@link #LOGGING_FEATURE_SEPARATOR}</li>
* </ul>
* <p>
* If any of the configuration value is not set, following default values are applied:
@@ -56,13 +57,15 @@
* <li>{@link #LOGGING_FEATURE_LOGGER_LEVEL_SERVER}</li>
* <li>{@link #LOGGING_FEATURE_VERBOSITY_SERVER}</li>
* <li>{@link #LOGGING_FEATURE_MAX_ENTITY_SIZE_SERVER}</li>
* <li>{@link #LOGGING_FEATURE_SEPARATOR_SERVER}</li>
* </ul>
* Client configurable properties:
* <ul>
* <li>{@link #LOGGING_FEATURE_LOGGER_NAME_CLIENT}</li>
* <li>{@link #LOGGING_FEATURE_LOGGER_LEVEL_CLIENT}</li>
* <li>{@link #LOGGING_FEATURE_VERBOSITY_CLIENT}</li>
* <li>{@link #LOGGING_FEATURE_MAX_ENTITY_SIZE_CLIENT}</li>
* <li>{@link #LOGGING_FEATURE_SEPARATOR_CLIENT}</li>
* </ul>
*
* @author Ondrej Kosatka
@@ -86,11 +89,16 @@ public class LoggingFeature implements Feature {
* Default verbosity for entity logging. See {@link Verbosity}.
*/
public static final Verbosity DEFAULT_VERBOSITY = Verbosity.PAYLOAD_TEXT;
/**
* Default separator for entity logging.
*/
public static final String DEFAULT_SEPARATOR = "\n";

private static final String LOGGER_NAME_POSTFIX = ".logger.name";
private static final String LOGGER_LEVEL_POSTFIX = ".logger.level";
private static final String VERBOSITY_POSTFIX = ".verbosity";
private static final String MAX_ENTITY_POSTFIX = ".entity.maxSize";
private static final String SEPARATOR_POSTFIX = ".separator";
private static final String LOGGING_FEATURE_COMMON_PREFIX = "jersey.config.logging";
/**
* Common logger name property.
@@ -108,6 +116,10 @@ public class LoggingFeature implements Feature {
* Common property for configuring a maximum number of bytes of entity to be logged.
*/
public static final String LOGGING_FEATURE_MAX_ENTITY_SIZE = LOGGING_FEATURE_COMMON_PREFIX + MAX_ENTITY_POSTFIX;
/**
* Common property for configuring logging separator.
*/
public static final String LOGGING_FEATURE_SEPARATOR = LOGGING_FEATURE_COMMON_PREFIX + SEPARATOR_POSTFIX;

private static final String LOGGING_FEATURE_SERVER_PREFIX = "jersey.config.server.logging";
/**
@@ -126,6 +138,10 @@ public class LoggingFeature implements Feature {
* Server property for configuring a maximum number of bytes of entity to be logged.
*/
public static final String LOGGING_FEATURE_MAX_ENTITY_SIZE_SERVER = LOGGING_FEATURE_SERVER_PREFIX + MAX_ENTITY_POSTFIX;
/**
* Server property for configuring separator.
*/
public static final String LOGGING_FEATURE_SEPARATOR_SERVER = LOGGING_FEATURE_SERVER_PREFIX + SEPARATOR_POSTFIX;

private static final String LOGGING_FEATURE_CLIENT_PREFIX = "jersey.config.client.logging";
/**
@@ -144,11 +160,12 @@ public class LoggingFeature implements Feature {
* Client property for configuring a maximum number of bytes of entity to be logged.
*/
public static final String LOGGING_FEATURE_MAX_ENTITY_SIZE_CLIENT = LOGGING_FEATURE_CLIENT_PREFIX + MAX_ENTITY_POSTFIX;
/**
* Client property for logging separator.
*/
public static final String LOGGING_FEATURE_SEPARATOR_CLIENT = LOGGING_FEATURE_CLIENT_PREFIX + SEPARATOR_POSTFIX;

private final Logger filterLogger;
private final Verbosity verbosity;
private final Integer maxEntitySize;
private final Level level;
private final LoggingFeatureBuilder builder;

/**
* Creates the feature with default values.
@@ -199,47 +216,84 @@ public LoggingFeature(Logger logger, Integer maxEntitySize) {
* and print "...more..." string at the end. Negative values are interpreted as zero.
*/
public LoggingFeature(Logger logger, Level level, Verbosity verbosity, Integer maxEntitySize) {
this.filterLogger = logger;
this.level = level;
this.verbosity = verbosity;
this.maxEntitySize = maxEntitySize;

this(LoggingFeature.builder()
.withLogger(logger)
.level(level)
.verbosity(verbosity)
.maxEntitySize(maxEntitySize)
.separator(DEFAULT_SEPARATOR)
);

}

/**
* Constructor based on logging feature builder. All parameters are passed through a builder instance.
*
* @param builder instance of a builder with required logging feature parameters
*/
public LoggingFeature(LoggingFeatureBuilder builder) {
this.builder = builder;
}

@Override
public boolean configure(FeatureContext context) {
boolean enabled = false;
boolean enabled = context.getConfiguration().getRuntimeType() != null;

if (context.getConfiguration().getRuntimeType() == RuntimeType.CLIENT) {
ClientLoggingFilter clientLoggingFilter = (ClientLoggingFilter) createLoggingFilter(context, RuntimeType.CLIENT);
context.register(clientLoggingFilter);
enabled = true;
}
if (context.getConfiguration().getRuntimeType() == RuntimeType.SERVER) {
ServerLoggingFilter serverClientFilter = (ServerLoggingFilter) createLoggingFilter(context, RuntimeType.SERVER);
context.register(serverClientFilter);
enabled = true;
if (enabled) {
context.register(createLoggingFilter(context, context.getConfiguration().getRuntimeType()));
}

return enabled;
}

/**
* builder method to create LoggingFeature with required settings
*
* @return Builder for LoggingFeature
*/
public static LoggingFeatureBuilder builder() {
return new LoggingFeatureBuilder();
}

private LoggingInterceptor createLoggingFilter(FeatureContext context, RuntimeType runtimeType) {
Map properties = context.getConfiguration().getProperties();
String filterLoggerName = CommonProperties.getValue(

final LoggingFeatureBuilder loggingBuilder =
configureBuilderParameters(builder, context, runtimeType);

return (runtimeType == RuntimeType.SERVER)
? new ServerLoggingFilter(loggingBuilder)
: new ClientLoggingFilter(loggingBuilder);
}

private static LoggingFeatureBuilder configureBuilderParameters(LoggingFeatureBuilder builder,
FeatureContext context, RuntimeType runtimeType) {

final Map properties = context.getConfiguration().getProperties();
//get values from properties (if any)
final String filterLoggerName = CommonProperties.getValue(
properties,
runtimeType == RuntimeType.SERVER ? LOGGING_FEATURE_LOGGER_NAME_SERVER : LOGGING_FEATURE_LOGGER_NAME_CLIENT,
CommonProperties.getValue(
properties,
LOGGING_FEATURE_LOGGER_NAME,
DEFAULT_LOGGER_NAME
));
String filterLevel = CommonProperties.getValue(
final String filterLevel = CommonProperties.getValue(
properties,
runtimeType == RuntimeType.SERVER ? LOGGING_FEATURE_LOGGER_LEVEL_SERVER : LOGGING_FEATURE_LOGGER_LEVEL_CLIENT,
CommonProperties.getValue(
context.getConfiguration().getProperties(),
LOGGING_FEATURE_LOGGER_LEVEL,
DEFAULT_LOGGER_LEVEL));
Verbosity filterVerbosity = CommonProperties.getValue(
final String filterSeparator = CommonProperties.getValue(
properties,
runtimeType == RuntimeType.SERVER ? LOGGING_FEATURE_SEPARATOR_SERVER : LOGGING_FEATURE_SEPARATOR_CLIENT,
CommonProperties.getValue(
context.getConfiguration().getProperties(),
LOGGING_FEATURE_SEPARATOR,
DEFAULT_SEPARATOR));
final Verbosity filterVerbosity = CommonProperties.getValue(
properties,
runtimeType == RuntimeType.SERVER ? LOGGING_FEATURE_VERBOSITY_SERVER : LOGGING_FEATURE_VERBOSITY_CLIENT,
CommonProperties.getValue(
@@ -257,19 +311,16 @@ private LoggingInterceptor createLoggingFilter(FeatureContext context, RuntimeTy
DEFAULT_MAX_ENTITY_SIZE
));

Level loggerLevel = Level.parse(filterLevel);

if (runtimeType == RuntimeType.SERVER) {
return new ServerLoggingFilter(filterLogger != null ? filterLogger : Logger.getLogger(filterLoggerName),
level != null ? level : loggerLevel,
verbosity != null ? verbosity : filterVerbosity,
maxEntitySize != null ? maxEntitySize : filterMaxEntitySize);
} else {
return new ClientLoggingFilter(filterLogger != null ? filterLogger : Logger.getLogger(filterLoggerName),
level != null ? level : loggerLevel,
verbosity != null ? verbosity : filterVerbosity,
maxEntitySize != null ? maxEntitySize : filterMaxEntitySize);
}
final Level loggerLevel = Level.parse(filterLevel);

//configure builder vs properties values
builder.filterLogger = builder.filterLogger == null ? Logger.getLogger(filterLoggerName) : builder.filterLogger;
builder.verbosity = builder.verbosity == null ? filterVerbosity : builder.verbosity;
builder.maxEntitySize = builder.maxEntitySize == null ? filterMaxEntitySize : builder.maxEntitySize;
builder.level = builder.level == null ? loggerLevel : builder.level;
builder.separator = builder.separator == null ? filterSeparator : builder.separator;

return builder;
}

/**
@@ -313,4 +364,45 @@ public enum Verbosity {
*/
PAYLOAD_ANY
}
}

/**
* Builder class for logging feature configuration. Accepts parameters for the filter logger, verbosity, max
* entity size, level, and separator.
*/
public static class LoggingFeatureBuilder {

Logger filterLogger;
Verbosity verbosity;
Integer maxEntitySize;
Level level;
String separator;

public LoggingFeatureBuilder() {

}
public LoggingFeatureBuilder withLogger(Logger logger) {
this.filterLogger = logger;
return this;
}
public LoggingFeatureBuilder verbosity(Verbosity verbosity) {
this.verbosity = verbosity;
return this;
}
public LoggingFeatureBuilder maxEntitySize(Integer maxEntitySize) {
this.maxEntitySize = maxEntitySize;
return this;
}
public LoggingFeatureBuilder level(Level level) {
this.level = level;
return this;
}
public LoggingFeatureBuilder separator(String separator) {
this.separator = separator;
return this;
}

public LoggingFeature build() {
return new LoggingFeature(this);
}
}
}
Loading