From 02144e0a976e6e59fe6f7ddeb5228bbd7f2251ca Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Mon, 20 Jun 2016 17:46:21 -0700 Subject: [PATCH 1/2] Making test keystores compatible with Java 8 restrictions --- .../src/test/config/etc/keystore | Bin 1416 -> 3697 bytes jetty-server/src/test/resources/keystore | Bin 1426 -> 3697 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/keystore b/jetty-osgi/test-jetty-osgi/src/test/config/etc/keystore index 08f6cda8a7b0104236c37f3c06b4cda1d8fc58e6..d6592f95ee93575d659f28e1c2ebb81191484986 100644 GIT binary patch literal 3697 zcmd6pX*d+@{>NvrWFIDxY+1`X7+JztLzb~8nyh1tFhllAM#9*skfo5_gREH|Ye<*} zjioF#A|{kAS+bnz>746yuJeEMe|KKoFTTI)zOU?< z#FyiM0S zgr$YM*b&YG_ zBYG^7qphlg*P^t%*8HVu*QIYChB#Y3%{|xDITzOcS5-xyIyE%==@R8Y2F%EN$6tMG zwQ~+5^ZD_b{g(m9_2BQ0{&XXjG03a(Cfv|JEqWr-i^`OAfZB{rft_(B9hc^H$E)_a zjgLn%qTnla5ZwQM;E?px_@7IR$8USXlh(u`>^GMh9l|HpP569{Uh#aQL+p(OHnqe z)(^mk4f`p1`(oj2Np3=Cw1)BGr;+8tJmlLZNPmq-TqKgs#r8Y1q7IwBBO@4BD*1NS zBDbi)W>k;I3;j$!MM*5gnNFBdvoq0<+V!T{qf(LrAI1dGb`iTaVNLu#EV;tO#x)c^@!-Q)A?S< z?%W8;T{x!36yKF7cVg1G!7S0?Q)zgxTU&-sGxU7Z;ZOz?lFbZ?nlsYypI`VqD#}nm zIY7RC&6o@WaXNPA9~tE`Sxpu6s9ERtoptCD=Q7mnt0vjZ!RyA2LInmLiX&I_U;9XH zzBP&BwK2(XK5`zqsk6U+b?dtUY#q^aYRgiXQ9=`KZ&S;NZtvLkutD1^3!-9lM-F=%E00v__Y1q(j|bzhne1L zzpOFaVm?e=8qekKJ61kqX}x%>OvS44k4H{lWrfBLoUB^#dt2=%@HSr`BsB;*&Buol zvO#Z%BPw-=N-4V?Kguu>t*Z1lx8lEXlpan^K8vpU3>PDBVXzrWZYBKPJD1|kbEI!5 zYOu1mv-LS!NV9!cdC52BhSF4#DCG5@5_yY=6TDK*J)1r#Y|3-sE;Bi|2@XYFJJCR}`0OVC88V)?m`{9}V6z+VXX2E-#W-N8I*qRc$Pm4xc zEZWN{!_)u(a5F3t+yILN<>rAwKoE$I-nu~)#>T)T6>Su~!v+Mh&;pYXrvRZPCfJsa z0m^9Wd&3tO?EA0EiT|oF{<|Up6Z?6J87g3g^A8Z#bqN*L!};C}^bWxKVuURMLgj=_ z1Ki~l*kPPYs50{+-@(Xg6;x{w7)u=Z}F2@~|l=!;}?a3JOZ9 zFeQh-rK*DJKjr^cvyniN-_4|v1{?|Gpdkpz42lE-0a2{d=TvW{yQ{>!rTSsB;34Ob zD#A-j0<+zvdn-Jndahyp+$dkSnL__2i|S&`^EJ}owEt73gtB_}ycu&i3&)=UX38&i zj5HU!Zj-nLWoNmu!AGxnEiBRwrZ}^Vufg?Mle6E6pmEARSN%4Nb3TImCLU7%@)F`; z-qOtqSy>%F_amkLSlj?7VJ?*Rcrf7YE2X^c72W-4qGM*bmh?L@9Cgmq?y`uS>}uA8 z&DT7UE8u-Hpdlz}Z0(0<>%0+(qlLxGmEJd8TULo{H1rSYgip}6)Hx`A%^z zT*#!j^NIrTXS`K0J6kuBZ7i?bz4Nw$MbQOK^AktWS6xY4_&GZfS=M1m!9<^ zCya2V*0d6}XLX?6`t=dS9>WLvlcmw!|0?g{r2A>w%UvB*G@di{tkUm=~ z#6P_nJ(+SQFnJ-nJiT*+QN`PA`C(LB8}XX>T}mci&QNr=D26904C9d7mMuH!lNGd{ zJK;E2-`%uKQ6cW-C}GtV--vzEz%#d|_p%z4#D2Ywa8NBmLuN15bU!Wr;gpbroUi&J zlc@JFY7Z^NhVzxYK}>p^hde~d9I6$4D4y`lsma+h+DX)FJeDRCe0*a*4fwyX>G1=r z7DnO=@g|&_$B=F{66zg^RN70xjAFhSo@C$D5q-~EaM3+nSv99@b(HnB0Ld%XtSw_H zGyKA^Nu48vQVN>b0*axU-<&IvD4LISE zPFNoja@A!c0D19a@6GJEy!;+t7iaO{--#xl&ky0}0K>d55-Oca#3fbux;odo6{y>k zq?h|gqxYPY4f&?l80EVPa&0%z zj&=BPpW|+E>#f3hX|cvFgFXGLmIT4HrtTKA66yt|44xsyzhoh7q>pTH3$S@?p)ZyL z_d*^lF#V{Hx%|qxI}AWftkp#MQqmF(0UNL9RdiSNLe<0tvQa!Fb<`J@ zC+m`2ExT6e=JGHM}J=Q8hY6xoY7?8TI;m8h4&CMMH1K-9+E@8n`5 z=y>l@Lt@zcq#D`gDXZ0>134LP-`2RG=>n|~Tb*5XlipYBS)M7#=-CSH^XbhUcP6hjZT$zBKxwpx zoJ0%C9T1(`<_6{W1fcuLq{M#_=>N$iei+{`CPDuXCMgKR1b>l;2Z=}f3R~j>{oT;Q z`sg6EHxBQE_6<^xDz!Vh~l$4d>a2l3qN`XeHU-Eyh zU&7Ph9sLO=LL$voB8Wf$G;G5^$JI-nK#Z;5O^dLx8}zh&^z}&?HY!!NNsiSBLC)iU z4msl&aksF7TTLrIa~C1Cih7cDy3G1bNRnl_}%xr@88H;K8>^i}vh97R(z zFf691ePm#~wOhcL$(!k5#$bR#YUlEA%I`P-U?ZIlzg%tMKD+JA`8O4QZ;y82U|L_A zoELO&jAkx(YEO-nb4+V_HrQ;aKC@d8GYodSrbwOZFbWedevPhswrtLGQ{?N*rin(+ zbUDXIDrI_w>+QEG^dSq%tv>h%17}n;%Q@1Kx$6}eERle)tkEOs_W{e1t@VHDnEGdv wEFzAHc&(-O`dvH6;mJRF{6sVzs8PZB{SN^zS470bpS=8~^|S delta 1225 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 Date: Mon, 20 Jun 2016 17:47:29 -0700 Subject: [PATCH 2/2] Fixes #425 - Removing duplicate Decoder affecting lifecycle + Duplicate Decoder was created and used in OnMessageCallable. Now using DecoderFactory to obtain already instantiated Decoder instead. --- .../jsr356/annotations/JsrCallable.java | 6 +- .../jsr356/annotations/JsrParamIdBinary.java | 11 +- .../jsr356/annotations/JsrParamIdDecoder.java | 5 +- .../jsr356/annotations/JsrParamIdPong.java | 3 +- .../jsr356/annotations/JsrParamIdText.java | 34 ++- .../jsr356/annotations/OnCloseCallable.java | 5 +- .../jsr356/annotations/OnErrorCallable.java | 3 +- .../annotations/OnMessageBinaryCallable.java | 6 +- .../jsr356/annotations/OnMessageCallable.java | 25 +-- .../annotations/OnMessageTextCallable.java | 6 +- .../jsr356/annotations/OnOpenCallable.java | 5 +- .../jsr356/decoders/TimeDecoder.java | 1 + .../jsr356/server/ConfiguratorTest.java | 199 ++++++++++++++---- 13 files changed, 202 insertions(+), 107 deletions(-) diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrCallable.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrCallable.java index 8b727b0f380..f55e066cb85 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrCallable.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrCallable.java @@ -171,5 +171,9 @@ public abstract class JsrCallable extends CallableMethod } } - public abstract void setDecoderClass(Class decoderClass); + /** + * The Type of Class a {@link Decoder} should be created to produce. + * @param decodingType the type of class a Decoder should be created to produce + */ + public abstract void setDecodingType(Class decodingType); } diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdBinary.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdBinary.java index 71976e4b960..3b10457911f 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdBinary.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdBinary.java @@ -23,12 +23,9 @@ import java.nio.ByteBuffer; import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role; -import org.eclipse.jetty.websocket.jsr356.decoders.ByteArrayDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.ByteBufferDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.InputStreamDecoder; /** - * Param handling for static Binary @{@link OnMessage} parameters. + * Param handling for static Binary @{@link javax.websocket.OnMessage} parameters. */ public class JsrParamIdBinary extends JsrParamIdOnMessage implements IJsrParamId { @@ -46,14 +43,14 @@ public class JsrParamIdBinary extends JsrParamIdOnMessage implements IJsrParamId if (param.type.isAssignableFrom(ByteBuffer.class)) { param.bind(Role.MESSAGE_BINARY); - callable.setDecoderClass(ByteBufferDecoder.class); + callable.setDecodingType(ByteBuffer.class); return true; } if (param.type.isAssignableFrom(byte[].class)) { param.bind(Role.MESSAGE_BINARY); - callable.setDecoderClass(ByteArrayDecoder.class); + callable.setDecodingType(byte[].class); return true; } @@ -62,7 +59,7 @@ public class JsrParamIdBinary extends JsrParamIdOnMessage implements IJsrParamId { assertPartialMessageSupportDisabled(param,callable); param.bind(Role.MESSAGE_BINARY_STREAM); - callable.setDecoderClass(InputStreamDecoder.class); + callable.setDecodingType(InputStream.class); return true; } diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdDecoder.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdDecoder.java index c147abc16a4..babab0556c1 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdDecoder.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdDecoder.java @@ -23,7 +23,7 @@ import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role; import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadata; /** - * Param handling for Text or Binary @{@link OnMessage} parameters declared as {@link Decoder}s + * Param handling for Text or Binary @{@link javax.websocket.OnMessage} parameters declared as {@link javax.websocket.Decoder}s */ public class JsrParamIdDecoder extends JsrParamIdOnMessage implements IJsrParamId { @@ -67,7 +67,8 @@ public class JsrParamIdDecoder extends JsrParamIdOnMessage implements IJsrParamI param.bind(Role.MESSAGE_PONG); break; } - callable.setDecoderClass(metadata.getCoderClass()); + + callable.setDecodingType(metadata.getObjectType()); return true; } return false; diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdPong.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdPong.java index 6ca40399f86..f1a5dd62e8c 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdPong.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdPong.java @@ -22,7 +22,6 @@ import javax.websocket.PongMessage; import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role; -import org.eclipse.jetty.websocket.jsr356.decoders.PongMessageDecoder; public class JsrParamIdPong extends JsrParamIdOnMessage implements IJsrParamId { @@ -41,7 +40,7 @@ public class JsrParamIdPong extends JsrParamIdOnMessage implements IJsrParamId { assertPartialMessageSupportDisabled(param,callable); param.bind(Role.MESSAGE_PONG); - callable.setDecoderClass(PongMessageDecoder.class); + callable.setDecodingType(PongMessage.class); return true; } return false; diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdText.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdText.java index 7fe36004831..ea0c04db7cd 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdText.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdText.java @@ -22,19 +22,9 @@ import java.io.Reader; import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role; -import org.eclipse.jetty.websocket.jsr356.decoders.BooleanDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.ByteDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.CharacterDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.DoubleDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.FloatDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.IntegerDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.LongDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.ReaderDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.ShortDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.StringDecoder; /** - * Param handling for static Text @{@link OnMessage} parameters + * Param handling for static Text @{@link javax.websocket.OnMessage} parameters */ public class JsrParamIdText extends JsrParamIdOnMessage implements IJsrParamId { @@ -63,7 +53,7 @@ public class JsrParamIdText extends JsrParamIdOnMessage implements IJsrParamId if (param.type.isAssignableFrom(String.class)) { param.bind(Role.MESSAGE_TEXT); - callable.setDecoderClass(StringDecoder.class); + callable.setDecodingType(String.class); return true; } @@ -72,56 +62,56 @@ public class JsrParamIdText extends JsrParamIdOnMessage implements IJsrParamId { assertPartialMessageSupportDisabled(param,callable); param.bind(Role.MESSAGE_TEXT); - callable.setDecoderClass(BooleanDecoder.class); + callable.setDecodingType(Boolean.class); return true; } if (param.type.isAssignableFrom(Byte.class) || (param.type == Byte.TYPE)) { assertPartialMessageSupportDisabled(param,callable); param.bind(Role.MESSAGE_TEXT); - callable.setDecoderClass(ByteDecoder.class); + callable.setDecodingType(Byte.class); return true; } if (param.type.isAssignableFrom(Character.class) || (param.type == Character.TYPE)) { assertPartialMessageSupportDisabled(param,callable); param.bind(Role.MESSAGE_TEXT); - callable.setDecoderClass(CharacterDecoder.class); + callable.setDecodingType(Character.class); return true; } if (param.type.isAssignableFrom(Double.class) || (param.type == Double.TYPE)) { assertPartialMessageSupportDisabled(param,callable); param.bind(Role.MESSAGE_TEXT); - callable.setDecoderClass(DoubleDecoder.class); + callable.setDecodingType(Double.class); return true; } if (param.type.isAssignableFrom(Float.class) || (param.type == Float.TYPE)) { assertPartialMessageSupportDisabled(param,callable); param.bind(Role.MESSAGE_TEXT); - callable.setDecoderClass(FloatDecoder.class); + callable.setDecodingType(Float.class); return true; } if (param.type.isAssignableFrom(Integer.class) || (param.type == Integer.TYPE)) { assertPartialMessageSupportDisabled(param,callable); param.bind(Role.MESSAGE_TEXT); - callable.setDecoderClass(IntegerDecoder.class); + callable.setDecodingType(Integer.class); return true; } if (param.type.isAssignableFrom(Long.class) || (param.type == Long.TYPE)) { assertPartialMessageSupportDisabled(param,callable); param.bind(Role.MESSAGE_TEXT); - callable.setDecoderClass(LongDecoder.class); + callable.setDecodingType(Long.class); return true; } if (param.type.isAssignableFrom(Short.class) || (param.type == Short.TYPE)) { assertPartialMessageSupportDisabled(param,callable); param.bind(Role.MESSAGE_TEXT); - callable.setDecoderClass(ShortDecoder.class); + callable.setDecodingType(Short.class); return true; } @@ -130,7 +120,7 @@ public class JsrParamIdText extends JsrParamIdOnMessage implements IJsrParamId { assertPartialMessageSupportDisabled(param,callable); param.bind(Role.MESSAGE_TEXT_STREAM); - callable.setDecoderClass(ReaderDecoder.class); + callable.setDecodingType(Reader.class); return true; } @@ -148,7 +138,7 @@ public class JsrParamIdText extends JsrParamIdOnMessage implements IJsrParamId else { param.bind(Role.MESSAGE_TEXT); - callable.setDecoderClass(BooleanDecoder.class); + callable.setDecodingType(Boolean.class); } return true; } diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnCloseCallable.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnCloseCallable.java index 00f8ae0caac..4a0fc7dad46 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnCloseCallable.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnCloseCallable.java @@ -22,14 +22,13 @@ import java.lang.reflect.Method; import javax.websocket.CloseReason; import javax.websocket.CloseReason.CloseCodes; -import javax.websocket.Decoder; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.jsr356.JsrSession; import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role; /** - * Callable for {@link OnClose} annotated methods + * Callable for {@link javax.websocket.OnClose} annotated methods */ public class OnCloseCallable extends JsrCallable { @@ -82,7 +81,7 @@ public class OnCloseCallable extends JsrCallable } @Override - public void setDecoderClass(Class decoderClass) + public void setDecodingType(Class decodingType) { /* ignore, not relevant for onClose */ } diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnErrorCallable.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnErrorCallable.java index b8adf6c20ab..ba54ae6bcf3 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnErrorCallable.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnErrorCallable.java @@ -66,9 +66,8 @@ public class OnErrorCallable extends JsrCallable } @Override - public void setDecoderClass(Class decoderClass) + public void setDecodingType(Class decodingType) { /* ignore, not relevant for onClose */ } - } diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnMessageBinaryCallable.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnMessageBinaryCallable.java index a93386a22b6..764b879d86f 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnMessageBinaryCallable.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnMessageBinaryCallable.java @@ -28,11 +28,11 @@ import org.eclipse.jetty.websocket.jsr356.JsrSession; import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role; /** - * Callable for {@link OnMessage} annotated methods with a whole or partial binary messages. + * Callable for {@link javax.websocket.OnMessage} annotated methods with a whole or partial binary messages. *

- * Not for use with {@link InputStream} based {@link OnMessage} method objects. + * Not for use with {@link java.io.InputStream} based {@link javax.websocket.OnMessage} method objects. * - * @see Binary + * @see javax.websocket.Decoder.Binary */ public class OnMessageBinaryCallable extends OnMessageCallable { diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnMessageCallable.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnMessageCallable.java index 7c1a171534d..c077b07eff9 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnMessageCallable.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnMessageCallable.java @@ -26,7 +26,6 @@ import javax.websocket.Encoder; import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; import org.eclipse.jetty.websocket.common.util.ReflectUtils; import org.eclipse.jetty.websocket.jsr356.EncoderFactory; -import org.eclipse.jetty.websocket.jsr356.InitException; import org.eclipse.jetty.websocket.jsr356.JsrSession; import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role; @@ -34,7 +33,7 @@ public class OnMessageCallable extends JsrCallable { protected final Class returnType; protected Encoder returnEncoder; - protected Class decoderClass; + protected Class decodingType; protected Decoder decoder; protected int idxPartialMessageFlag = -1; protected int idxMessageObject = -1; @@ -50,7 +49,7 @@ public class OnMessageCallable extends JsrCallable { super(copy); this.returnType = copy.returnType; - this.decoderClass = copy.decoderClass; + this.decodingType = copy.decodingType; this.decoder = copy.decoder; this.idxPartialMessageFlag = copy.idxPartialMessageFlag; this.idxMessageObject = copy.idxMessageObject; @@ -93,11 +92,6 @@ public class OnMessageCallable extends JsrCallable return decoder; } - public Class getDecoderClass() - { - return decoderClass; - } - public Param getMessageObjectParam() { if (idxMessageObject < 0) @@ -138,16 +132,9 @@ public class OnMessageCallable extends JsrCallable this.returnEncoder = encoderWrapper.getEncoder(); } - if (decoderClass != null) + if (decodingType != null) { - try - { - this.decoder = decoderClass.newInstance(); - } - catch (InstantiationException | IllegalAccessException e) - { - throw new InitException("Unable to create decoder: " + decoderClass.getName(),e); - } + this.decoder = session.getDecoderFactory().getDecoderFor(decodingType); } } @@ -162,9 +149,9 @@ public class OnMessageCallable extends JsrCallable } @Override - public void setDecoderClass(Class decoderClass) + public void setDecodingType(Class decodingType) { - this.decoderClass = decoderClass; + this.decodingType = decodingType; messageRoleAssigned = true; } diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnMessageTextCallable.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnMessageTextCallable.java index 865d48dc8a5..fd87263c8e1 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnMessageTextCallable.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnMessageTextCallable.java @@ -27,11 +27,11 @@ import org.eclipse.jetty.websocket.jsr356.JsrSession; import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role; /** - * Callable for {@link OnMessage} annotated methods with a whole or partial text messages. + * Callable for {@link javax.websocket.OnMessage} annotated methods with a whole or partial text messages. *

- * Not for use with {@link Reader} based {@link OnMessage} method objects. + * Not for use with {@link java.io.Reader} based {@link javax.websocket.OnMessage} method objects. * - * @see Text + * @see javax.websocket.Decoder.Text */ public class OnMessageTextCallable extends OnMessageCallable { diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnOpenCallable.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnOpenCallable.java index fe464374aaa..dfabd48370f 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnOpenCallable.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/OnOpenCallable.java @@ -20,14 +20,13 @@ package org.eclipse.jetty.websocket.jsr356.annotations; import java.lang.reflect.Method; -import javax.websocket.Decoder; import javax.websocket.EndpointConfig; import org.eclipse.jetty.websocket.jsr356.JsrSession; import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role; /** - * Callable for {@link OnOpen} annotated methods + * Callable for {@link javax.websocket.OnOpen} annotated methods */ public class OnOpenCallable extends JsrCallable { @@ -62,7 +61,7 @@ public class OnOpenCallable extends JsrCallable } @Override - public void setDecoderClass(Class decoderClass) + public void setDecodingType(Class decodingType) { /* ignore, not relevant for onClose */ } diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/TimeDecoder.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/TimeDecoder.java index 4cd3a684de0..6db1ddead77 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/TimeDecoder.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/TimeDecoder.java @@ -52,6 +52,7 @@ public class TimeDecoder implements Decoder.Text @Override public void init(EndpointConfig config) { + System.out.println("#### INIT ####"); } @Override diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java index 1123495af1a..65b5269a377 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java @@ -18,19 +18,28 @@ package org.eclipse.jetty.websocket.jsr356.server; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; import java.io.PrintWriter; import java.io.StringWriter; import java.net.InetSocketAddress; import java.net.URI; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.Collections; +import java.util.Date; import java.util.List; import java.util.Map; +import java.util.TimeZone; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import javax.websocket.DecodeException; +import javax.websocket.Decoder; +import javax.websocket.EndpointConfig; import javax.websocket.Extension; import javax.websocket.HandshakeResponse; import javax.websocket.OnMessage; @@ -98,8 +107,8 @@ public class ConfiguratorTest @Override public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { - super.modifyHandshake(sec,request,response); - sec.getUserProperties().put("request-headers",request.getHeaders()); + super.modifyHandshake(sec, request, response); + sec.getUserProperties().put("request-headers", request.getHeaders()); } } @@ -113,7 +122,7 @@ public class ConfiguratorTest response.append("Request Header [").append(headerKey).append("]: "); @SuppressWarnings("unchecked") - Map> headers = (Map>)session.getUserProperties().get("request-headers"); + Map> headers = (Map>) session.getUserProperties().get("request-headers"); if (headers == null) { response.append(""); @@ -127,7 +136,7 @@ public class ConfiguratorTest } else { - response.append(QuoteUtil.join(values,",")); + response.append(QuoteUtil.join(values, ",")); } } @@ -142,15 +151,15 @@ public class ConfiguratorTest @Override public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { - super.modifyHandshake(sec,request,response); + super.modifyHandshake(sec, request, response); } @Override public String getNegotiatedSubprotocol(List supported, List requested) { - String seen = QuoteUtil.join(requested,","); - seenProtocols.compareAndSet(null,seen); - return super.getNegotiatedSubprotocol(supported,requested); + String seen = QuoteUtil.join(requested, ","); + seenProtocols.compareAndSet(null, seen); + return super.getNegotiatedSubprotocol(supported, requested); } } @@ -175,15 +184,24 @@ public class ConfiguratorTest { int upgradeNum = upgradeCount.addAndGet(1); LOG.debug("Upgrade Num: {}", upgradeNum); - sec.getUserProperties().put("upgradeNum",Integer.toString(upgradeNum)); - switch(upgradeNum) { - case 1: sec.getUserProperties().put("apple", "fruit from tree"); break; - case 2: sec.getUserProperties().put("blueberry", "fruit from bush"); break; - case 3: sec.getUserProperties().put("strawberry", "fruit from annual"); break; - default: sec.getUserProperties().put("fruit"+upgradeNum, "placeholder"); break; + sec.getUserProperties().put("upgradeNum", Integer.toString(upgradeNum)); + switch (upgradeNum) + { + case 1: + sec.getUserProperties().put("apple", "fruit from tree"); + break; + case 2: + sec.getUserProperties().put("blueberry", "fruit from bush"); + break; + case 3: + sec.getUserProperties().put("strawberry", "fruit from annual"); + break; + default: + sec.getUserProperties().put("fruit" + upgradeNum, "placeholder"); + break; } - super.modifyHandshake(sec,request,response); + super.modifyHandshake(sec, request, response); } } @@ -193,7 +211,7 @@ public class ConfiguratorTest @OnMessage public String onMessage(Session session, String msg) { - String value = (String)session.getUserProperties().get(msg); + String value = (String) session.getUserProperties().get(msg); StringBuilder response = new StringBuilder(); response.append("Requested User Property: [").append(msg).append("] = "); if (value == null) @@ -213,13 +231,13 @@ public class ConfiguratorTest @Override public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { - InetSocketAddress local = (InetSocketAddress)sec.getUserProperties().get(JsrCreator.PROP_LOCAL_ADDRESS); - InetSocketAddress remote = (InetSocketAddress)sec.getUserProperties().get(JsrCreator.PROP_REMOTE_ADDRESS); + InetSocketAddress local = (InetSocketAddress) sec.getUserProperties().get(JsrCreator.PROP_LOCAL_ADDRESS); + InetSocketAddress remote = (InetSocketAddress) sec.getUserProperties().get(JsrCreator.PROP_REMOTE_ADDRESS); sec.getUserProperties().put("found.local", local); sec.getUserProperties().put("found.remote", remote); - super.modifyHandshake(sec,request,response); + super.modifyHandshake(sec, request, response); } } @@ -230,22 +248,100 @@ public class ConfiguratorTest public String onMessage(Session session, String msg) { StringBuilder response = new StringBuilder(); - appendPropValue(session,response,"javax.websocket.endpoint.localAddress"); - appendPropValue(session,response,"javax.websocket.endpoint.remoteAddress"); - appendPropValue(session,response,"found.local"); - appendPropValue(session,response,"found.remote"); + appendPropValue(session, response, "javax.websocket.endpoint.localAddress"); + appendPropValue(session, response, "javax.websocket.endpoint.remoteAddress"); + appendPropValue(session, response, "found.local"); + appendPropValue(session, response, "found.remote"); return response.toString(); } private void appendPropValue(Session session, StringBuilder response, String key) { - InetSocketAddress value = (InetSocketAddress)session.getUserProperties().get(key); + InetSocketAddress value = (InetSocketAddress) session.getUserProperties().get(key); response.append("[").append(key).append("] = "); response.append(toSafeAddr(value)); response.append(System.lineSeparator()); } } + + public static class SelectedProtocolConfigurator extends ServerEndpointConfig.Configurator + { + @Override + public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) + { + List selectedProtocol = response.getHeaders().get("Sec-WebSocket-Protocol"); + String protocol = "<>"; + if (selectedProtocol != null || !selectedProtocol.isEmpty()) + protocol = selectedProtocol.get(0); + config.getUserProperties().put("selected-subprotocol", protocol); + } + } + + public static class GmtTimeDecoder implements Decoder.Text + { + private TimeZone TZ; + + @Override + public Calendar decode(String s) throws DecodeException + { + if (TZ == null) + throw new DecodeException(s, ".init() not called"); + try + { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + dateFormat.setTimeZone(TZ); + Date time = dateFormat.parse(s); + Calendar cal = Calendar.getInstance(); + cal.setTimeZone(TZ); + cal.setTime(time); + return cal; + } + catch (ParseException e) + { + throw new DecodeException(s, "Unable to decode Time", e); + } + } + + @Override + public void init(EndpointConfig config) + { + TZ = TimeZone.getTimeZone("GMT+0"); + } + + @Override + public void destroy() + { + } + + @Override + public boolean willDecode(String s) + { + return true; + } + } + + @ServerEndpoint(value = "/timedecoder", + subprotocols = { "time", "gmt" }, + configurator = SelectedProtocolConfigurator.class, + decoders = {GmtTimeDecoder.class}) + public static class TimeDecoderSocket + { + private TimeZone TZ = TimeZone.getTimeZone("GMT+0"); + + @OnMessage + public String onMessage(Calendar cal) + { + return String.format("cal=%s", newDateFormat().format(cal.getTime())); + } + + private SimpleDateFormat newDateFormat() + { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss Z"); + dateFormat.setTimeZone(TZ); + return dateFormat; + } + } private static Server server; private static URI baseServerUri; @@ -269,6 +365,7 @@ public class ConfiguratorTest container.addEndpoint(ProtocolsSocket.class); container.addEndpoint(UniqueUserPropsSocket.class); container.addEndpoint(AddressSocket.class); + container.addEndpoint(TimeDecoderSocket.class); server.start(); String host = connector.getHost(); @@ -277,9 +374,9 @@ public class ConfiguratorTest host = "localhost"; } int port = connector.getLocalPort(); - baseServerUri = new URI(String.format("ws://%s:%d/",host,port)); + baseServerUri = new URI(String.format("ws://%s:%d/", host, port)); if (LOG.isDebugEnabled()) - LOG.debug("Server started on {}",baseServerUri); + LOG.debug("Server started on {}", baseServerUri); } public static String toSafeAddr(InetSocketAddress addr) @@ -288,7 +385,7 @@ public class ConfiguratorTest { return ""; } - return String.format("%s:%d",addr.getAddress().getHostAddress(),addr.getPort()); + return String.format("%s:%d", addr.getAddress().getHostAddress(), addr.getPort()); } @AfterClass @@ -308,7 +405,7 @@ public class ConfiguratorTest client.connect(); client.sendStandardRequest(); HttpResponse response = client.readResponseHeader(); - Assert.assertThat("response.extensions",response.getExtensionsHeader(),is("identity")); + Assert.assertThat("response.extensions", response.getExtensionsHeader(), is("identity")); } } @@ -323,7 +420,7 @@ public class ConfiguratorTest client.connect(); client.sendStandardRequest(); HttpResponse response = client.readResponseHeader(); - Assert.assertThat("response.extensions",response.getExtensionsHeader(),nullValue()); + Assert.assertThat("response.extensions", response.getExtensionsHeader(), nullValue()); } } @@ -340,7 +437,7 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("X-Dummy")); - EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); + EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); WebSocketFrame frame = frames.poll(); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Request Header [X-Dummy]: \"Bogus\"")); } @@ -359,7 +456,7 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("apple")); - EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); + EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); WebSocketFrame frame = frames.poll(); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [apple] = \"fruit from tree\"")); } @@ -373,7 +470,7 @@ public class ConfiguratorTest client.write(new TextFrame().setPayload("apple")); client.write(new TextFrame().setPayload("blueberry")); - EventQueue frames = client.readFrames(2,1,TimeUnit.SECONDS); + EventQueue frames = client.readFrames(2, 1, TimeUnit.SECONDS); WebSocketFrame frame = frames.poll(); // should have no value Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [apple] = ")); @@ -399,7 +496,7 @@ public class ConfiguratorTest InetSocketAddress expectedRemote = client.getRemoteSocketAddress(); client.write(new TextFrame().setPayload("addr")); - EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); + EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); WebSocketFrame frame = frames.poll(); StringWriter expected = new StringWriter(); @@ -407,8 +504,8 @@ public class ConfiguratorTest // local <-> remote are opposite on server (duh) out.printf("[javax.websocket.endpoint.localAddress] = %s%n", toSafeAddr(expectedRemote)); out.printf("[javax.websocket.endpoint.remoteAddress] = %s%n", toSafeAddr(expectedLocal)); - out.printf("[found.local] = %s%n",toSafeAddr(expectedRemote)); - out.printf("[found.remote] = %s%n",toSafeAddr(expectedLocal)); + out.printf("[found.local] = %s%n", toSafeAddr(expectedRemote)); + out.printf("[found.remote] = %s%n", toSafeAddr(expectedLocal)); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is(expected.toString())); } @@ -431,7 +528,7 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("getProtocols")); - EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); + EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); WebSocketFrame frame = frames.poll(); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\"]")); } @@ -454,7 +551,7 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("getProtocols")); - EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); + EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); WebSocketFrame frame = frames.poll(); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]")); } @@ -477,7 +574,7 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("getProtocols")); - EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); + EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); WebSocketFrame frame = frames.poll(); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]")); } @@ -500,9 +597,31 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("getProtocols")); - EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); + EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); WebSocketFrame frame = frames.poll(); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]")); } } + + /** + * Test of Sec-WebSocket-Protocol, using non-spec case header + */ + @Test + public void testDecoderWithProtocol() throws Exception + { + URI uri = baseServerUri.resolve("/timedecoder"); + + try (BlockheadClient client = new BlockheadClient(uri)) + { + client.addHeader("Sec-Websocket-Protocol: gmt\r\n"); + client.connect(); + client.sendStandardRequest(); + client.expectUpgradeResponse(); + + client.write(new TextFrame().setPayload("2016-06-20T14:27:44")); + EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); + WebSocketFrame frame = frames.poll(); + Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("cal=2016.06.20 AD at 14:27:44 +0000")); + } + } }