Skip to content

Commit

Permalink
Issue #6106 - Decorate javax.websocket Encoder & Decoders.
Browse files Browse the repository at this point in the history
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
  • Loading branch information
lachlan-roberts committed Apr 6, 2021
1 parent ac5eb54 commit a1e5227
Show file tree
Hide file tree
Showing 18 changed files with 127 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public JavaxWebSocketFrameHandlerMetadata getMetadata(Class<?> endpointClass, En
if (endpointClass.getAnnotation(ClientEndpoint.class) == null)
return null;

JavaxWebSocketFrameHandlerMetadata metadata = new JavaxWebSocketFrameHandlerMetadata(endpointConfig);
JavaxWebSocketFrameHandlerMetadata metadata = new JavaxWebSocketFrameHandlerMetadata(endpointConfig, components);
return discoverJavaxFrameHandlerMetadata(endpointClass, metadata);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ public DecoratedObjectFactory getObjectFactory()
return components.getObjectFactory();
}

public WebSocketComponents getWebSocketComponents()
{
return components;
}

public long getDefaultAsyncSendTimeout()
{
return defaultCustomizer.getWriteTimeout().toMillis();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.core.exception.InvalidSignatureException;
import org.eclipse.jetty.websocket.core.exception.InvalidWebSocketException;
import org.eclipse.jetty.websocket.core.internal.messages.MessageSink;
Expand Down Expand Up @@ -102,10 +103,12 @@ static InvokerUtils.Arg[] getArgsFor(Class<?> objectType)

protected final JavaxWebSocketContainer container;
protected final InvokerUtils.ParamIdentifier paramIdentifier;
protected final WebSocketComponents components;

public JavaxWebSocketFrameHandlerFactory(JavaxWebSocketContainer container, InvokerUtils.ParamIdentifier paramIdentifier)
{
this.container = container;
this.components = container.getWebSocketComponents();
this.paramIdentifier = paramIdentifier == null ? InvokerUtils.PARAM_IDENTITY : paramIdentifier;
}

Expand Down Expand Up @@ -248,7 +251,7 @@ private MethodHandle toMethodHandle(MethodHandles.Lookup lookup, Method method)

protected JavaxWebSocketFrameHandlerMetadata createEndpointMetadata(EndpointConfig endpointConfig)
{
JavaxWebSocketFrameHandlerMetadata metadata = new JavaxWebSocketFrameHandlerMetadata(endpointConfig);
JavaxWebSocketFrameHandlerMetadata metadata = new JavaxWebSocketFrameHandlerMetadata(endpointConfig, container.getWebSocketComponents());
MethodHandles.Lookup lookup = getServerMethodHandleLookup();

Method openMethod = ReflectUtils.findMethod(Endpoint.class, "onOpen", Session.class, EndpointConfig.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import javax.websocket.EndpointConfig;

import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.core.exception.InvalidWebSocketException;
import org.eclipse.jetty.websocket.javax.common.decoders.AvailableDecoders;
import org.eclipse.jetty.websocket.javax.common.encoders.AvailableEncoders;
Expand Down Expand Up @@ -64,10 +65,10 @@ public class JavaxWebSocketFrameHandlerMetadata
*/
private UriTemplatePathSpec uriTemplatePathSpec;

public JavaxWebSocketFrameHandlerMetadata(EndpointConfig endpointConfig)
public JavaxWebSocketFrameHandlerMetadata(EndpointConfig endpointConfig, WebSocketComponents components)
{
this.availableDecoders = new AvailableDecoders(endpointConfig);
this.availableEncoders = new AvailableEncoders(endpointConfig);
this.availableDecoders = new AvailableDecoders(endpointConfig, components);
this.availableEncoders = new AvailableEncoders(endpointConfig, components);
}

public AvailableDecoders getAvailableDecoders()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ public JavaxWebSocketSession(JavaxWebSocketContainer container,
this.coreSession = coreSession;
this.frameHandler = frameHandler;
this.sessionId = UUID.randomUUID().toString();
this.availableDecoders = new AvailableDecoders(endpointConfig);
this.availableEncoders = new AvailableEncoders(endpointConfig);
this.availableDecoders = new AvailableDecoders(endpointConfig, coreSession.getWebSocketComponents());
this.availableEncoders = new AvailableEncoders(endpointConfig, coreSession.getWebSocketComponents());

if (endpointConfig instanceof PathParamProvider)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;

import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.core.exception.InvalidSignatureException;
import org.eclipse.jetty.websocket.core.exception.InvalidWebSocketException;
import org.eclipse.jetty.websocket.core.internal.util.ReflectUtils;
Expand All @@ -33,9 +34,12 @@ public class AvailableDecoders implements Iterable<RegisteredDecoder>
{
private final List<RegisteredDecoder> registeredDecoders = new ArrayList<>();
private final EndpointConfig config;
private final WebSocketComponents components;

public AvailableDecoders(EndpointConfig config)
public AvailableDecoders(EndpointConfig config, WebSocketComponents components)
{
this.components = Objects.requireNonNull(components);

// Register the Config Based Decoders.
this.config = Objects.requireNonNull(config);
registerAll(config.getDecoders());
Expand Down Expand Up @@ -72,7 +76,7 @@ public AvailableDecoders(EndpointConfig config)

private void registerPrimitive(Class<? extends Decoder> decoderClass, Class<? extends Decoder> interfaceType, Class<?> type)
{
registeredDecoders.add(new RegisteredDecoder(decoderClass, interfaceType, type, config, true));
registeredDecoders.add(new RegisteredDecoder(decoderClass, interfaceType, type, config, components, true));
}

private void register(Class<? extends Decoder> decoder)
Expand Down Expand Up @@ -151,7 +155,7 @@ private void add(Class<? extends Decoder> decoder, Class<? extends Decoder> inte
return;
}

registeredDecoders.add(new RegisteredDecoder(decoder, interfaceClass, objectType, config));
registeredDecoders.add(new RegisteredDecoder(decoder, interfaceClass, objectType, config, components));
}

public RegisteredDecoder getFirstRegisteredDecoder(Class<?> type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;

import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.javax.common.InitException;

public class RegisteredDecoder
{
private final WebSocketComponents components;

// The user supplied Decoder class
public final Class<? extends Decoder> decoder;
// The javax.websocket.Decoder.* type (eg: Decoder.Binary, Decoder.BinaryStream, Decoder.Text, Decoder.TextStream)
Expand All @@ -31,18 +34,19 @@ public class RegisteredDecoder

private Decoder instance;

public RegisteredDecoder(Class<? extends Decoder> decoder, Class<? extends Decoder> interfaceType, Class<?> objectType, EndpointConfig endpointConfig)
public RegisteredDecoder(Class<? extends Decoder> decoder, Class<? extends Decoder> interfaceType, Class<?> objectType, EndpointConfig endpointConfig, WebSocketComponents components)
{
this(decoder, interfaceType, objectType, endpointConfig, false);
this(decoder, interfaceType, objectType, endpointConfig, components, false);
}

public RegisteredDecoder(Class<? extends Decoder> decoder, Class<? extends Decoder> interfaceType, Class<?> objectType, EndpointConfig endpointConfig, boolean primitive)
public RegisteredDecoder(Class<? extends Decoder> decoder, Class<? extends Decoder> interfaceType, Class<?> objectType, EndpointConfig endpointConfig, WebSocketComponents components, boolean primitive)
{
this.decoder = decoder;
this.interfaceType = interfaceType;
this.objectType = objectType;
this.primitive = primitive;
this.config = endpointConfig;
this.components = components;
}

public boolean implementsInterface(Class<? extends Decoder> type)
Expand All @@ -61,7 +65,7 @@ public <T extends Decoder> T getInstance()
{
try
{
instance = decoder.getConstructor().newInstance();
instance = components.getObjectFactory().createInstance(decoder);
instance.init(config);
return (T)instance;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,69 +24,24 @@
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;

import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.core.exception.InvalidSignatureException;
import org.eclipse.jetty.websocket.core.exception.InvalidWebSocketException;
import org.eclipse.jetty.websocket.core.internal.util.ReflectUtils;
import org.eclipse.jetty.websocket.javax.common.InitException;

public class AvailableEncoders implements Predicate<Class<?>>
{
public static class RegisteredEncoder
{
public final Class<? extends Encoder> encoder;
public final Class<? extends Encoder> interfaceType;
public final Class<?> objectType;
public final boolean primitive;
public Encoder instance;

public RegisteredEncoder(Class<? extends Encoder> encoder, Class<? extends Encoder> interfaceType, Class<?> objectType)
{
this(encoder, interfaceType, objectType, false);
}

public RegisteredEncoder(Class<? extends Encoder> encoder, Class<? extends Encoder> interfaceType, Class<?> objectType, boolean primitive)
{
this.encoder = encoder;
this.interfaceType = interfaceType;
this.objectType = objectType;
this.primitive = primitive;
}

public boolean implementsInterface(Class<? extends Encoder> type)
{
return interfaceType.isAssignableFrom(type);
}

public boolean isType(Class<?> type)
{
return objectType.isAssignableFrom(type);
}

@Override
public String toString()
{
StringBuilder str = new StringBuilder();
str.append(AvailableEncoders.RegisteredEncoder.class.getSimpleName());
str.append('[').append(encoder.getName());
str.append(',').append(interfaceType.getName());
str.append(',').append(objectType.getName());
if (primitive)
{
str.append(",PRIMITIVE");
}
str.append(']');
return str.toString();
}
}

private final EndpointConfig config;
private LinkedList<RegisteredEncoder> registeredEncoders;
private final WebSocketComponents components;
private final LinkedList<RegisteredEncoder> registeredEncoders;

public AvailableEncoders(EndpointConfig config)
public AvailableEncoders(EndpointConfig config, WebSocketComponents components)
{
Objects.requireNonNull(config);
this.config = config;
registeredEncoders = new LinkedList<>();
this.config = Objects.requireNonNull(config);
this.components = Objects.requireNonNull(components);
this.registeredEncoders = new LinkedList<>();

// TEXT based [via Class reference]
registerPrimitive(BooleanEncoder.class, Encoder.Text.class, Boolean.class);
Expand Down Expand Up @@ -267,7 +222,7 @@ public Encoder getInstanceFor(Class<?> type)
return registeredEncoder.instance;
}

registeredEncoder.instance = registeredEncoder.encoder.getConstructor().newInstance();
registeredEncoder.instance = components.getObjectFactory().createInstance(registeredEncoder.encoder);
registeredEncoder.instance.init(this.config);
return registeredEncoder.instance;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//
// ========================================================================
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.websocket.javax.common.encoders;

import javax.websocket.Encoder;

public class RegisteredEncoder
{
public final Class<? extends Encoder> encoder;
public final Class<? extends Encoder> interfaceType;
public final Class<?> objectType;
public final boolean primitive;
public Encoder instance;

public RegisteredEncoder(Class<? extends Encoder> encoder, Class<? extends Encoder> interfaceType, Class<?> objectType)
{
this(encoder, interfaceType, objectType, false);
}

public RegisteredEncoder(Class<? extends Encoder> encoder, Class<? extends Encoder> interfaceType, Class<?> objectType, boolean primitive)
{
this.encoder = encoder;
this.interfaceType = interfaceType;
this.objectType = objectType;
this.primitive = primitive;
}

public boolean implementsInterface(Class<? extends Encoder> type)
{
return interfaceType.isAssignableFrom(type);
}

public boolean isType(Class<?> type)
{
return objectType.isAssignableFrom(type);
}

@Override
public String toString()
{
StringBuilder str = new StringBuilder();
str.append(RegisteredEncoder.class.getSimpleName());
str.append('[').append(encoder.getName());
str.append(',').append(interfaceType.getName());
str.append(',').append(objectType.getName());
if (primitive)
{
str.append(",PRIMITIVE");
}
str.append(']');
return str.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import javax.websocket.EndpointConfig;

import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.javax.common.decoders.AvailableDecoders;
import org.eclipse.jetty.websocket.javax.common.encoders.AvailableEncoders;
import org.junit.jupiter.api.AfterAll;
Expand Down Expand Up @@ -46,12 +47,13 @@ public static void stopContainer() throws Exception
protected Map<String, String> uriParams;
protected EndpointConfig endpointConfig;
protected CoreSession coreSession = new CoreSession.Empty();
private WebSocketComponents components = new WebSocketComponents();

public AbstractJavaxWebSocketFrameHandlerTest()
{
endpointConfig = ClientEndpointConfig.Builder.create().build();
encoders = new AvailableEncoders(endpointConfig);
decoders = new AvailableDecoders(endpointConfig);
encoders = new AvailableEncoders(endpointConfig, components);
decoders = new AvailableDecoders(endpointConfig, components);
uriParams = new HashMap<>();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public JavaxWebSocketFrameHandlerMetadata getMetadata(Class<?> endpointClass, En
return null;
}

JavaxWebSocketFrameHandlerMetadata metadata = new JavaxWebSocketFrameHandlerMetadata(endpointConfig);
JavaxWebSocketFrameHandlerMetadata metadata = new JavaxWebSocketFrameHandlerMetadata(endpointConfig, components);
return discoverJavaxFrameHandlerMetadata(endpointClass, metadata);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@
import javax.websocket.ClientEndpointConfig;
import javax.websocket.Decoder;

import org.eclipse.jetty.websocket.core.WebSocketComponents;
import org.eclipse.jetty.websocket.javax.common.AbstractSessionTest;
import org.eclipse.jetty.websocket.javax.common.JavaxWebSocketFrameHandlerFactory;
import org.eclipse.jetty.websocket.javax.common.decoders.RegisteredDecoder;

public abstract class AbstractMessageSinkTest extends AbstractSessionTest
{
private final WebSocketComponents _components = new WebSocketComponents();

public List<RegisteredDecoder> toRegisteredDecoderList(Class<? extends Decoder> clazz, Class<?> objectType)
{
Class<? extends Decoder> interfaceType;
Expand All @@ -40,7 +43,7 @@ else if (Decoder.BinaryStream.class.isAssignableFrom(clazz))
else
throw new IllegalStateException();

return List.of(new RegisteredDecoder(clazz, interfaceType, objectType, ClientEndpointConfig.Builder.create().build()));
return List.of(new RegisteredDecoder(clazz, interfaceType, objectType, ClientEndpointConfig.Builder.create().build(), _components));
}

public <T> MethodHandle getAcceptHandle(Consumer<T> copy, Class<T> type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,6 @@ public Map<String, Object> getUserProperties()
// [JSR] Step 6: create endpoint class
Class<?> endpointClass = config.getEndpointClass();
Object endpoint = config.getConfigurator().getEndpointInstance(endpointClass);
// Do not decorate here (let the Connection and Session start first)
// This will allow CDI to see Session for injection into Endpoint classes.
return new ConfiguredEndpoint(endpoint, config);
}
catch (InstantiationException e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public JavaxWebSocketFrameHandlerMetadata getMetadata(Class<?> endpointClass, En
return super.getMetadata(endpointClass, endpointConfig);

UriTemplatePathSpec templatePathSpec = new UriTemplatePathSpec(anno.value());
JavaxWebSocketFrameHandlerMetadata metadata = new JavaxWebSocketFrameHandlerMetadata(endpointConfig);
JavaxWebSocketFrameHandlerMetadata metadata = new JavaxWebSocketFrameHandlerMetadata(endpointConfig, components);
metadata.setUriTemplatePathSpec(templatePathSpec);
return discoverJavaxFrameHandlerMetadata(endpointClass, metadata);
}
Expand Down
Loading

0 comments on commit a1e5227

Please sign in to comment.