Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Issue #7573 - fix support in websocket for class path param types #7579

Merged
merged 1 commit into from
Feb 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@
import org.eclipse.jetty.websocket.javax.common.messages.DecodedTextMessageSink;
import org.eclipse.jetty.websocket.javax.common.messages.DecodedTextStreamMessageSink;

import static java.nio.charset.StandardCharsets.UTF_8;

public abstract class JavaxWebSocketFrameHandlerFactory
{
private static final MethodHandle FILTER_RETURN_TYPE_METHOD;
Expand Down Expand Up @@ -536,49 +534,47 @@ public static MethodHandle bindTemplateVariables(MethodHandle target, String[] n
{
retHandle = MethodHandles.insertArguments(retHandle, IDX, strValue);
}
else if (Integer.TYPE.isAssignableFrom(type))
else if (Integer.class.isAssignableFrom(type) || Integer.TYPE.isAssignableFrom(type))
{
int intValue = Integer.parseInt(strValue);
Integer intValue = Integer.parseInt(strValue);
retHandle = MethodHandles.insertArguments(retHandle, IDX, intValue);
}
else if (Long.TYPE.isAssignableFrom(type))
else if (Long.class.isAssignableFrom(type) || Long.TYPE.isAssignableFrom(type))
{
long longValue = Long.parseLong(strValue);
Long longValue = Long.parseLong(strValue);
retHandle = MethodHandles.insertArguments(retHandle, IDX, longValue);
}
else if (Short.TYPE.isAssignableFrom(type))
else if (Short.class.isAssignableFrom(type) || Short.TYPE.isAssignableFrom(type))
{
short shortValue = Short.parseShort(strValue);
Short shortValue = Short.parseShort(strValue);
retHandle = MethodHandles.insertArguments(retHandle, IDX, shortValue);
}
else if (Float.TYPE.isAssignableFrom(type))
else if (Float.class.isAssignableFrom(type) || Float.TYPE.isAssignableFrom(type))
{
float floatValue = Float.parseFloat(strValue);
Float floatValue = Float.parseFloat(strValue);
retHandle = MethodHandles.insertArguments(retHandle, IDX, floatValue);
}
else if (Double.TYPE.isAssignableFrom(type))
else if (Double.class.isAssignableFrom(type) || Double.TYPE.isAssignableFrom(type))
{
double doubleValue = Double.parseDouble(strValue);
Double doubleValue = Double.parseDouble(strValue);
retHandle = MethodHandles.insertArguments(retHandle, IDX, doubleValue);
}
else if (Boolean.TYPE.isAssignableFrom(type))
else if (Boolean.class.isAssignableFrom(type) || Boolean.TYPE.isAssignableFrom(type))
{
boolean boolValue = Boolean.parseBoolean(strValue);
Boolean boolValue = Boolean.parseBoolean(strValue);
retHandle = MethodHandles.insertArguments(retHandle, IDX, boolValue);
}
else if (Character.TYPE.isAssignableFrom(type))
else if (Character.class.isAssignableFrom(type) || Character.TYPE.isAssignableFrom(type))
{
if (strValue.length() != 1)
throw new IllegalArgumentException("Invalid Size");
char charValue = strValue.charAt(0);
Character charValue = strValue.charAt(0);
retHandle = MethodHandles.insertArguments(retHandle, IDX, charValue);
}
else if (Byte.TYPE.isAssignableFrom(type))
else if (Byte.class.isAssignableFrom(type) || Byte.TYPE.isAssignableFrom(type))
{
byte[] buf = strValue.getBytes(UTF_8);
if (buf.length != 1)
throw new IllegalArgumentException("Invalid Size");
retHandle = MethodHandles.insertArguments(retHandle, IDX, buf[0]);
Byte b = Byte.parseByte(strValue);
retHandle = MethodHandles.insertArguments(retHandle, IDX, b);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,21 @@ public InvokerUtils.Arg getParamArg(Method method, Class<?> paramType, int idx)
public static void validateType(Class<?> type)
{
if (!String.class.isAssignableFrom(type) &&
!Integer.class.isAssignableFrom(type) &&
!Integer.TYPE.isAssignableFrom(type) &&
!Long.class.isAssignableFrom(type) &&
!Long.TYPE.isAssignableFrom(type) &&
!Short.class.isAssignableFrom(type) &&
!Short.TYPE.isAssignableFrom(type) &&
!Float.class.isAssignableFrom(type) &&
!Float.TYPE.isAssignableFrom(type) &&
!Double.class.isAssignableFrom(type) &&
!Double.TYPE.isAssignableFrom(type) &&
!Boolean.class.isAssignableFrom(type) &&
!Boolean.TYPE.isAssignableFrom(type) &&
!Character.class.isAssignableFrom(type) &&
!Character.TYPE.isAssignableFrom(type) &&
!Byte.class.isAssignableFrom(type) &&
!Byte.TYPE.isAssignableFrom(type))
throw new InvalidSignatureException("Unsupported PathParam Type: " + type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import java.net.URI;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import javax.websocket.ContainerProvider;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
Expand All @@ -27,12 +28,35 @@
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer;
import org.eclipse.jetty.websocket.javax.server.internal.JavaxWebSocketServerContainer;
import org.eclipse.jetty.websocket.javax.tests.pathparam.BooleanClassSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.BooleanTypeSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.ByteClassSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.ByteTypeSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.CharacterClassSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.CharacterTypeSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.DoubleClassSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.DoubleTypeSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.FloatClassSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.FloatTypeSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.IntegerClassSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.IntegerTypeSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.LongClassSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.LongTypeSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.ShortClassSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.ShortTypeSocket;
import org.eclipse.jetty.websocket.javax.tests.pathparam.StringClassSocket;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class PathParamTest
{
Expand Down Expand Up @@ -81,6 +105,48 @@ public void onMessage(String message, @PathParam("name") String name)
}
}

public static Stream<Arguments> pathParamEndpoints()
{
return Stream.of(
Arguments.of(BooleanClassSocket.class, "false"),
Arguments.of(BooleanTypeSocket.class, "true"),
Arguments.of(ByteClassSocket.class, "32"),
Arguments.of(ByteTypeSocket.class, "51"),
Arguments.of(CharacterClassSocket.class, "q"),
Arguments.of(CharacterTypeSocket.class, "&"),
Arguments.of(DoubleClassSocket.class, Double.toString(Double.MAX_VALUE)),
Arguments.of(DoubleTypeSocket.class, Double.toString(Double.MIN_VALUE)),
Arguments.of(FloatClassSocket.class, "0.00235"),
Arguments.of(FloatTypeSocket.class, "123.456"),
Arguments.of(IntegerClassSocket.class, Integer.toString(Integer.MIN_VALUE)),
Arguments.of(IntegerTypeSocket.class, Integer.toString(Integer.MAX_VALUE)),
Arguments.of(LongClassSocket.class, Long.toString(Long.MAX_VALUE)),
Arguments.of(LongTypeSocket.class, Long.toString(Long.MIN_VALUE)),
Arguments.of(ShortClassSocket.class, Short.toString(Short.MAX_VALUE)),
Arguments.of(ShortTypeSocket.class, Short.toString(Short.MIN_VALUE)),
Arguments.of(StringClassSocket.class, "this_is_a_String_ID")
);
}

@ParameterizedTest
@MethodSource("pathParamEndpoints")
public void testPathParamSignatures(Class<?> endpointClass, String id) throws Exception
{
JavaxWebSocketServerContainer serverContainer = JavaxWebSocketServerContainer.getContainer(_context.getServletContext());
assertNotNull(serverContainer);
serverContainer.addEndpoint(endpointClass);

WebSocketContainer container = ContainerProvider.getWebSocketContainer();
EventSocket clientEndpoint = new EventSocket();

URI serverUri = URI.create("ws://localhost:" + _connector.getLocalPort() + "/context/pathParam/id/" + id);
container.connectToServer(clientEndpoint, serverUri);

assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS));
String resp = clientEndpoint.textMessages.poll(1, TimeUnit.SECONDS);
assertThat(resp, is("id: " + id));
}

@Test
public void testBasicPathParamSocket() throws Exception
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// ========================================================================
// Copyright (c) 1995-2022 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.tests.pathparam;

import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/pathParam/id/{id}")
public class BooleanClassSocket
{
@OnOpen
public void onOpen(Session session, @PathParam("id") Boolean id) throws Exception
{
session.getBasicRemote().sendText("id: " + id);
session.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// ========================================================================
// Copyright (c) 1995-2022 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.tests.pathparam;

import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/pathParam/id/{id}")
public class BooleanTypeSocket
{
@OnOpen
public void onOpen(Session session, @PathParam("id") boolean id) throws Exception
{
session.getBasicRemote().sendText("id: " + id);
session.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// ========================================================================
// Copyright (c) 1995-2022 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.tests.pathparam;

import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/pathParam/id/{id}")
public class ByteClassSocket
{
@OnOpen
public void onOpen(Session session, @PathParam("id") Byte id) throws Exception
{
session.getBasicRemote().sendText("id: " + id);
session.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// ========================================================================
// Copyright (c) 1995-2022 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.tests.pathparam;

import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/pathParam/id/{id}")
public class ByteTypeSocket
{
@OnOpen
public void onOpen(Session session, @PathParam("id") byte id) throws Exception
{
session.getBasicRemote().sendText("id: " + id);
session.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// ========================================================================
// Copyright (c) 1995-2022 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.tests.pathparam;

import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/pathParam/id/{id}")
public class CharacterClassSocket
{
@OnOpen
public void onOpen(Session session, @PathParam("id") Character id) throws Exception
{
session.getBasicRemote().sendText("id: " + id);
session.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// ========================================================================
// Copyright (c) 1995-2022 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.tests.pathparam;

import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/pathParam/id/{id}")
public class CharacterTypeSocket
{
@OnOpen
public void onOpen(Session session, @PathParam("id") char id) throws Exception
{
session.getBasicRemote().sendText("id: " + id);
session.close();
}
}
Loading