summaryrefslogtreecommitdiffhomepage
path: root/src/java/javax/websocket
diff options
context:
space:
mode:
authorMax Romanov <max.romanov@nginx.com>2019-09-05 15:27:32 +0300
committerMax Romanov <max.romanov@nginx.com>2019-09-05 15:27:32 +0300
commit2b8cab1e2478547398ad9c2fe68e025c180cac54 (patch)
treed317fcf9ee52f0f8967116f531784ae533b0ae5a /src/java/javax/websocket
parent3e23afb0d205e503f6cc7d852e34d07da9a5b7f7 (diff)
downloadunit-2b8cab1e2478547398ad9c2fe68e025c180cac54.tar.gz
unit-2b8cab1e2478547398ad9c2fe68e025c180cac54.tar.bz2
Java: introducing websocket support.
Diffstat (limited to 'src/java/javax/websocket')
-rw-r--r--src/java/javax/websocket/ClientEndpoint.java34
-rw-r--r--src/java/javax/websocket/ClientEndpointConfig.java138
-rw-r--r--src/java/javax/websocket/CloseReason.java122
-rw-r--r--src/java/javax/websocket/ContainerProvider.java63
-rw-r--r--src/java/javax/websocket/DecodeException.java56
-rw-r--r--src/java/javax/websocket/Decoder.java53
-rw-r--r--src/java/javax/websocket/DefaultClientEndpointConfig.java80
-rw-r--r--src/java/javax/websocket/DeploymentException.java30
-rw-r--r--src/java/javax/websocket/EncodeException.java38
-rw-r--r--src/java/javax/websocket/Encoder.java51
-rw-r--r--src/java/javax/websocket/Endpoint.java49
-rw-r--r--src/java/javax/websocket/EndpointConfig.java29
-rw-r--r--src/java/javax/websocket/Extension.java29
-rw-r--r--src/java/javax/websocket/HandshakeResponse.java30
-rw-r--r--src/java/javax/websocket/MessageHandler.java42
-rw-r--r--src/java/javax/websocket/OnClose.java27
-rw-r--r--src/java/javax/websocket/OnError.java27
-rw-r--r--src/java/javax/websocket/OnMessage.java28
-rw-r--r--src/java/javax/websocket/OnOpen.java27
-rw-r--r--src/java/javax/websocket/PongMessage.java32
-rw-r--r--src/java/javax/websocket/RemoteEndpoint.java229
-rw-r--r--src/java/javax/websocket/SendHandler.java22
-rw-r--r--src/java/javax/websocket/SendResult.java39
-rw-r--r--src/java/javax/websocket/Session.java193
-rw-r--r--src/java/javax/websocket/SessionException.java35
-rw-r--r--src/java/javax/websocket/WebSocketContainer.java131
-rw-r--r--src/java/javax/websocket/server/DefaultServerEndpointConfig.java95
-rw-r--r--src/java/javax/websocket/server/HandshakeRequest.java53
-rw-r--r--src/java/javax/websocket/server/PathParam.java33
-rw-r--r--src/java/javax/websocket/server/ServerApplicationConfig.java51
-rw-r--r--src/java/javax/websocket/server/ServerContainer.java30
-rw-r--r--src/java/javax/websocket/server/ServerEndpoint.java46
-rw-r--r--src/java/javax/websocket/server/ServerEndpointConfig.java218
33 files changed, 2160 insertions, 0 deletions
diff --git a/src/java/javax/websocket/ClientEndpoint.java b/src/java/javax/websocket/ClientEndpoint.java
new file mode 100644
index 00000000..ee984171
--- /dev/null
+++ b/src/java/javax/websocket/ClientEndpoint.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.websocket.ClientEndpointConfig.Configurator;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface ClientEndpoint {
+ String[] subprotocols() default {};
+ Class<? extends Decoder>[] decoders() default {};
+ Class<? extends Encoder>[] encoders() default {};
+ public Class<? extends Configurator> configurator()
+ default Configurator.class;
+}
diff --git a/src/java/javax/websocket/ClientEndpointConfig.java b/src/java/javax/websocket/ClientEndpointConfig.java
new file mode 100644
index 00000000..13b6cba5
--- /dev/null
+++ b/src/java/javax/websocket/ClientEndpointConfig.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public interface ClientEndpointConfig extends EndpointConfig {
+
+ List<String> getPreferredSubprotocols();
+
+ List<Extension> getExtensions();
+
+ public Configurator getConfigurator();
+
+ public final class Builder {
+
+ private static final Configurator DEFAULT_CONFIGURATOR =
+ new Configurator() {};
+
+
+ public static Builder create() {
+ return new Builder();
+ }
+
+
+ private Builder() {
+ // Hide default constructor
+ }
+
+ private Configurator configurator = DEFAULT_CONFIGURATOR;
+ private List<String> preferredSubprotocols = Collections.emptyList();
+ private List<Extension> extensions = Collections.emptyList();
+ private List<Class<? extends Encoder>> encoders =
+ Collections.emptyList();
+ private List<Class<? extends Decoder>> decoders =
+ Collections.emptyList();
+
+
+ public ClientEndpointConfig build() {
+ return new DefaultClientEndpointConfig(preferredSubprotocols,
+ extensions, encoders, decoders, configurator);
+ }
+
+
+ public Builder configurator(Configurator configurator) {
+ if (configurator == null) {
+ this.configurator = DEFAULT_CONFIGURATOR;
+ } else {
+ this.configurator = configurator;
+ }
+ return this;
+ }
+
+
+ public Builder preferredSubprotocols(
+ List<String> preferredSubprotocols) {
+ if (preferredSubprotocols == null ||
+ preferredSubprotocols.size() == 0) {
+ this.preferredSubprotocols = Collections.emptyList();
+ } else {
+ this.preferredSubprotocols =
+ Collections.unmodifiableList(preferredSubprotocols);
+ }
+ return this;
+ }
+
+
+ public Builder extensions(
+ List<Extension> extensions) {
+ if (extensions == null || extensions.size() == 0) {
+ this.extensions = Collections.emptyList();
+ } else {
+ this.extensions = Collections.unmodifiableList(extensions);
+ }
+ return this;
+ }
+
+
+ public Builder encoders(List<Class<? extends Encoder>> encoders) {
+ if (encoders == null || encoders.size() == 0) {
+ this.encoders = Collections.emptyList();
+ } else {
+ this.encoders = Collections.unmodifiableList(encoders);
+ }
+ return this;
+ }
+
+
+ public Builder decoders(List<Class<? extends Decoder>> decoders) {
+ if (decoders == null || decoders.size() == 0) {
+ this.decoders = Collections.emptyList();
+ } else {
+ this.decoders = Collections.unmodifiableList(decoders);
+ }
+ return this;
+ }
+ }
+
+
+ public class Configurator {
+
+ /**
+ * Provides the client with a mechanism to inspect and/or modify the headers
+ * that are sent to the server to start the WebSocket handshake.
+ *
+ * @param headers The HTTP headers
+ */
+ public void beforeRequest(Map<String, List<String>> headers) {
+ // NO-OP
+ }
+
+ /**
+ * Provides the client with a mechanism to inspect the handshake response
+ * that is returned from the server.
+ *
+ * @param handshakeResponse The response
+ */
+ public void afterResponse(HandshakeResponse handshakeResponse) {
+ // NO-OP
+ }
+ }
+}
diff --git a/src/java/javax/websocket/CloseReason.java b/src/java/javax/websocket/CloseReason.java
new file mode 100644
index 00000000..ef88d135
--- /dev/null
+++ b/src/java/javax/websocket/CloseReason.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+public class CloseReason {
+
+ private final CloseCode closeCode;
+ private final String reasonPhrase;
+
+ public CloseReason(CloseReason.CloseCode closeCode, String reasonPhrase) {
+ this.closeCode = closeCode;
+ this.reasonPhrase = reasonPhrase;
+ }
+
+ public CloseCode getCloseCode() {
+ return closeCode;
+ }
+
+ public String getReasonPhrase() {
+ return reasonPhrase;
+ }
+
+ @Override
+ public String toString() {
+ return "CloseReason: code [" + closeCode.getCode() +
+ "], reason [" + reasonPhrase + "]";
+ }
+
+ public interface CloseCode {
+ int getCode();
+ }
+
+ public enum CloseCodes implements CloseReason.CloseCode {
+
+ NORMAL_CLOSURE(1000),
+ GOING_AWAY(1001),
+ PROTOCOL_ERROR(1002),
+ CANNOT_ACCEPT(1003),
+ RESERVED(1004),
+ NO_STATUS_CODE(1005),
+ CLOSED_ABNORMALLY(1006),
+ NOT_CONSISTENT(1007),
+ VIOLATED_POLICY(1008),
+ TOO_BIG(1009),
+ NO_EXTENSION(1010),
+ UNEXPECTED_CONDITION(1011),
+ SERVICE_RESTART(1012),
+ TRY_AGAIN_LATER(1013),
+ TLS_HANDSHAKE_FAILURE(1015);
+
+ private int code;
+
+ CloseCodes(int code) {
+ this.code = code;
+ }
+
+ public static CloseCode getCloseCode(final int code) {
+ if (code > 2999 && code < 5000) {
+ return new CloseCode() {
+ @Override
+ public int getCode() {
+ return code;
+ }
+ };
+ }
+ switch (code) {
+ case 1000:
+ return CloseCodes.NORMAL_CLOSURE;
+ case 1001:
+ return CloseCodes.GOING_AWAY;
+ case 1002:
+ return CloseCodes.PROTOCOL_ERROR;
+ case 1003:
+ return CloseCodes.CANNOT_ACCEPT;
+ case 1004:
+ return CloseCodes.RESERVED;
+ case 1005:
+ return CloseCodes.NO_STATUS_CODE;
+ case 1006:
+ return CloseCodes.CLOSED_ABNORMALLY;
+ case 1007:
+ return CloseCodes.NOT_CONSISTENT;
+ case 1008:
+ return CloseCodes.VIOLATED_POLICY;
+ case 1009:
+ return CloseCodes.TOO_BIG;
+ case 1010:
+ return CloseCodes.NO_EXTENSION;
+ case 1011:
+ return CloseCodes.UNEXPECTED_CONDITION;
+ case 1012:
+ return CloseCodes.SERVICE_RESTART;
+ case 1013:
+ return CloseCodes.TRY_AGAIN_LATER;
+ case 1015:
+ return CloseCodes.TLS_HANDSHAKE_FAILURE;
+ default:
+ throw new IllegalArgumentException(
+ "Invalid close code: [" + code + "]");
+ }
+ }
+
+ @Override
+ public int getCode() {
+ return code;
+ }
+ }
+}
diff --git a/src/java/javax/websocket/ContainerProvider.java b/src/java/javax/websocket/ContainerProvider.java
new file mode 100644
index 00000000..1727ca93
--- /dev/null
+++ b/src/java/javax/websocket/ContainerProvider.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+/**
+ * Use the {@link ServiceLoader} mechanism to provide instances of the WebSocket
+ * client container.
+ */
+public abstract class ContainerProvider {
+
+ private static final String DEFAULT_PROVIDER_CLASS_NAME =
+ "nginx.unit.websocket.WsWebSocketContainer";
+
+ /**
+ * Create a new container used to create outgoing WebSocket connections.
+ *
+ * @return A newly created container.
+ */
+ public static WebSocketContainer getWebSocketContainer() {
+ WebSocketContainer result = null;
+
+ ServiceLoader<ContainerProvider> serviceLoader =
+ ServiceLoader.load(ContainerProvider.class);
+ Iterator<ContainerProvider> iter = serviceLoader.iterator();
+ while (result == null && iter.hasNext()) {
+ result = iter.next().getContainer();
+ }
+
+ // Fall-back. Also used by unit tests
+ if (result == null) {
+ try {
+ @SuppressWarnings("unchecked")
+ Class<WebSocketContainer> clazz =
+ (Class<WebSocketContainer>) Class.forName(
+ DEFAULT_PROVIDER_CLASS_NAME);
+ result = clazz.getConstructor().newInstance();
+ } catch (ReflectiveOperationException | IllegalArgumentException |
+ SecurityException e) {
+ // No options left. Just return null.
+ }
+ }
+ return result;
+ }
+
+ protected abstract WebSocketContainer getContainer();
+}
diff --git a/src/java/javax/websocket/DecodeException.java b/src/java/javax/websocket/DecodeException.java
new file mode 100644
index 00000000..771cfa58
--- /dev/null
+++ b/src/java/javax/websocket/DecodeException.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.nio.ByteBuffer;
+
+public class DecodeException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ private ByteBuffer bb;
+ private String encodedString;
+
+ public DecodeException(ByteBuffer bb, String message, Throwable cause) {
+ super(message, cause);
+ this.bb = bb;
+ }
+
+ public DecodeException(String encodedString, String message,
+ Throwable cause) {
+ super(message, cause);
+ this.encodedString = encodedString;
+ }
+
+ public DecodeException(ByteBuffer bb, String message) {
+ super(message);
+ this.bb = bb;
+ }
+
+ public DecodeException(String encodedString, String message) {
+ super(message);
+ this.encodedString = encodedString;
+ }
+
+ public ByteBuffer getBytes() {
+ return bb;
+ }
+
+ public String getText() {
+ return encodedString;
+ }
+}
diff --git a/src/java/javax/websocket/Decoder.java b/src/java/javax/websocket/Decoder.java
new file mode 100644
index 00000000..fad262e3
--- /dev/null
+++ b/src/java/javax/websocket/Decoder.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.ByteBuffer;
+
+public interface Decoder {
+
+ abstract void init(EndpointConfig endpointConfig);
+
+ abstract void destroy();
+
+ interface Binary<T> extends Decoder {
+
+ T decode(ByteBuffer bytes) throws DecodeException;
+
+ boolean willDecode(ByteBuffer bytes);
+ }
+
+ interface BinaryStream<T> extends Decoder {
+
+ T decode(InputStream is) throws DecodeException, IOException;
+ }
+
+ interface Text<T> extends Decoder {
+
+ T decode(String s) throws DecodeException;
+
+ boolean willDecode(String s);
+ }
+
+ interface TextStream<T> extends Decoder {
+
+ T decode(Reader reader) throws DecodeException, IOException;
+ }
+}
diff --git a/src/java/javax/websocket/DefaultClientEndpointConfig.java b/src/java/javax/websocket/DefaultClientEndpointConfig.java
new file mode 100644
index 00000000..ce28cb26
--- /dev/null
+++ b/src/java/javax/websocket/DefaultClientEndpointConfig.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+final class DefaultClientEndpointConfig implements ClientEndpointConfig {
+
+ private final List<String> preferredSubprotocols;
+ private final List<Extension> extensions;
+ private final List<Class<? extends Encoder>> encoders;
+ private final List<Class<? extends Decoder>> decoders;
+ private final Map<String,Object> userProperties = new ConcurrentHashMap<>();
+ private final Configurator configurator;
+
+
+ DefaultClientEndpointConfig(List<String> preferredSubprotocols,
+ List<Extension> extensions,
+ List<Class<? extends Encoder>> encoders,
+ List<Class<? extends Decoder>> decoders,
+ Configurator configurator) {
+ this.preferredSubprotocols = preferredSubprotocols;
+ this.extensions = extensions;
+ this.decoders = decoders;
+ this.encoders = encoders;
+ this.configurator = configurator;
+ }
+
+
+ @Override
+ public List<String> getPreferredSubprotocols() {
+ return preferredSubprotocols;
+ }
+
+
+ @Override
+ public List<Extension> getExtensions() {
+ return extensions;
+ }
+
+
+ @Override
+ public List<Class<? extends Encoder>> getEncoders() {
+ return encoders;
+ }
+
+
+ @Override
+ public List<Class<? extends Decoder>> getDecoders() {
+ return decoders;
+ }
+
+
+ @Override
+ public final Map<String, Object> getUserProperties() {
+ return userProperties;
+ }
+
+
+ @Override
+ public Configurator getConfigurator() {
+ return configurator;
+ }
+}
diff --git a/src/java/javax/websocket/DeploymentException.java b/src/java/javax/websocket/DeploymentException.java
new file mode 100644
index 00000000..1678fd09
--- /dev/null
+++ b/src/java/javax/websocket/DeploymentException.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+public class DeploymentException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public DeploymentException(String message) {
+ super(message);
+ }
+
+ public DeploymentException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/java/javax/websocket/EncodeException.java b/src/java/javax/websocket/EncodeException.java
new file mode 100644
index 00000000..fdb536ac
--- /dev/null
+++ b/src/java/javax/websocket/EncodeException.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+public class EncodeException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ private Object object;
+
+ public EncodeException(Object object, String message) {
+ super(message);
+ this.object = object;
+ }
+
+ public EncodeException(Object object, String message, Throwable cause) {
+ super(message, cause);
+ this.object = object;
+ }
+
+ public Object getObject() {
+ return this.object;
+ }
+}
diff --git a/src/java/javax/websocket/Encoder.java b/src/java/javax/websocket/Encoder.java
new file mode 100644
index 00000000..42a107f0
--- /dev/null
+++ b/src/java/javax/websocket/Encoder.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+
+public interface Encoder {
+
+ abstract void init(EndpointConfig endpointConfig);
+
+ abstract void destroy();
+
+ interface Text<T> extends Encoder {
+
+ String encode(T object) throws EncodeException;
+ }
+
+ interface TextStream<T> extends Encoder {
+
+ void encode(T object, Writer writer)
+ throws EncodeException, IOException;
+ }
+
+ interface Binary<T> extends Encoder {
+
+ ByteBuffer encode(T object) throws EncodeException;
+ }
+
+ interface BinaryStream<T> extends Encoder {
+
+ void encode(T object, OutputStream os)
+ throws EncodeException, IOException;
+ }
+}
diff --git a/src/java/javax/websocket/Endpoint.java b/src/java/javax/websocket/Endpoint.java
new file mode 100644
index 00000000..9dfdbcce
--- /dev/null
+++ b/src/java/javax/websocket/Endpoint.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+public abstract class Endpoint {
+
+ /**
+ * Event that is triggered when a new session starts.
+ *
+ * @param session The new session.
+ * @param config The configuration with which the Endpoint was
+ * configured.
+ */
+ public abstract void onOpen(Session session, EndpointConfig config);
+
+ /**
+ * Event that is triggered when a session has closed.
+ *
+ * @param session The session
+ * @param closeReason Why the session was closed
+ */
+ public void onClose(Session session, CloseReason closeReason) {
+ // NO-OP by default
+ }
+
+ /**
+ * Event that is triggered when a protocol error occurs.
+ *
+ * @param session The session.
+ * @param throwable The exception.
+ */
+ public void onError(Session session, Throwable throwable) {
+ // NO-OP by default
+ }
+}
diff --git a/src/java/javax/websocket/EndpointConfig.java b/src/java/javax/websocket/EndpointConfig.java
new file mode 100644
index 00000000..0b6c9681
--- /dev/null
+++ b/src/java/javax/websocket/EndpointConfig.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.util.List;
+import java.util.Map;
+
+public interface EndpointConfig {
+
+ List<Class<? extends Encoder>> getEncoders();
+
+ List<Class<? extends Decoder>> getDecoders();
+
+ Map<String,Object> getUserProperties();
+}
diff --git a/src/java/javax/websocket/Extension.java b/src/java/javax/websocket/Extension.java
new file mode 100644
index 00000000..b95b27b8
--- /dev/null
+++ b/src/java/javax/websocket/Extension.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.util.List;
+
+public interface Extension {
+ String getName();
+ List<Parameter> getParameters();
+
+ interface Parameter {
+ String getName();
+ String getValue();
+ }
+}
diff --git a/src/java/javax/websocket/HandshakeResponse.java b/src/java/javax/websocket/HandshakeResponse.java
new file mode 100644
index 00000000..807192e8
--- /dev/null
+++ b/src/java/javax/websocket/HandshakeResponse.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.util.List;
+import java.util.Map;
+
+public interface HandshakeResponse {
+
+ /**
+ * Name of the WebSocket accept HTTP header.
+ */
+ public static final String SEC_WEBSOCKET_ACCEPT = "Sec-WebSocket-Accept";
+
+ Map<String,List<String>> getHeaders();
+}
diff --git a/src/java/javax/websocket/MessageHandler.java b/src/java/javax/websocket/MessageHandler.java
new file mode 100644
index 00000000..2c30d997
--- /dev/null
+++ b/src/java/javax/websocket/MessageHandler.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+public interface MessageHandler {
+
+ interface Partial<T> extends MessageHandler {
+
+ /**
+ * Called when part of a message is available to be processed.
+ *
+ * @param messagePart The message part
+ * @param last <code>true</code> if this is the last part of
+ * this message, else <code>false</code>
+ */
+ void onMessage(T messagePart, boolean last);
+ }
+
+ interface Whole<T> extends MessageHandler {
+
+ /**
+ * Called when a whole message is available to be processed.
+ *
+ * @param message The message
+ */
+ void onMessage(T message);
+ }
+}
diff --git a/src/java/javax/websocket/OnClose.java b/src/java/javax/websocket/OnClose.java
new file mode 100644
index 00000000..6ee61d36
--- /dev/null
+++ b/src/java/javax/websocket/OnClose.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface OnClose {
+}
diff --git a/src/java/javax/websocket/OnError.java b/src/java/javax/websocket/OnError.java
new file mode 100644
index 00000000..ce431484
--- /dev/null
+++ b/src/java/javax/websocket/OnError.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface OnError {
+}
diff --git a/src/java/javax/websocket/OnMessage.java b/src/java/javax/websocket/OnMessage.java
new file mode 100644
index 00000000..564fa994
--- /dev/null
+++ b/src/java/javax/websocket/OnMessage.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface OnMessage {
+ long maxMessageSize() default -1;
+}
diff --git a/src/java/javax/websocket/OnOpen.java b/src/java/javax/websocket/OnOpen.java
new file mode 100644
index 00000000..9f0ea6e3
--- /dev/null
+++ b/src/java/javax/websocket/OnOpen.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface OnOpen {
+}
diff --git a/src/java/javax/websocket/PongMessage.java b/src/java/javax/websocket/PongMessage.java
new file mode 100644
index 00000000..7e9e3b6a
--- /dev/null
+++ b/src/java/javax/websocket/PongMessage.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Represents a WebSocket Pong message and used by message handlers to enable
+ * applications to process the response to any Pings they send.
+ */
+public interface PongMessage {
+ /**
+ * Get the payload of the Pong message.
+ *
+ * @return The payload of the Pong message.
+ */
+ ByteBuffer getApplicationData();
+}
diff --git a/src/java/javax/websocket/RemoteEndpoint.java b/src/java/javax/websocket/RemoteEndpoint.java
new file mode 100644
index 00000000..19c7a100
--- /dev/null
+++ b/src/java/javax/websocket/RemoteEndpoint.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+import java.util.concurrent.Future;
+
+
+public interface RemoteEndpoint {
+
+ interface Async extends RemoteEndpoint {
+
+ /**
+ * Obtain the timeout (in milliseconds) for sending a message
+ * asynchronously. The default value is determined by
+ * {@link WebSocketContainer#getDefaultAsyncSendTimeout()}.
+ * @return The current send timeout in milliseconds. A non-positive
+ * value means an infinite timeout.
+ */
+ long getSendTimeout();
+
+ /**
+ * Set the timeout (in milliseconds) for sending a message
+ * asynchronously. The default value is determined by
+ * {@link WebSocketContainer#getDefaultAsyncSendTimeout()}.
+ * @param timeout The new timeout for sending messages asynchronously
+ * in milliseconds. A non-positive value means an
+ * infinite timeout.
+ */
+ void setSendTimeout(long timeout);
+
+ /**
+ * Send the message asynchronously, using the SendHandler to signal to the
+ * client when the message has been sent.
+ * @param text The text message to send
+ * @param completion Used to signal to the client when the message has
+ * been sent
+ */
+ void sendText(String text, SendHandler completion);
+
+ /**
+ * Send the message asynchronously, using the Future to signal to the
+ * client when the message has been sent.
+ * @param text The text message to send
+ * @return A Future that signals when the message has been sent.
+ */
+ Future<Void> sendText(String text);
+
+ /**
+ * Send the message asynchronously, using the Future to signal to the client
+ * when the message has been sent.
+ * @param data The text message to send
+ * @return A Future that signals when the message has been sent.
+ * @throws IllegalArgumentException if {@code data} is {@code null}.
+ */
+ Future<Void> sendBinary(ByteBuffer data);
+
+ /**
+ * Send the message asynchronously, using the SendHandler to signal to the
+ * client when the message has been sent.
+ * @param data The text message to send
+ * @param completion Used to signal to the client when the message has
+ * been sent
+ * @throws IllegalArgumentException if {@code data} or {@code completion}
+ * is {@code null}.
+ */
+ void sendBinary(ByteBuffer data, SendHandler completion);
+
+ /**
+ * Encodes object as a message and sends it asynchronously, using the
+ * Future to signal to the client when the message has been sent.
+ * @param obj The object to be sent.
+ * @return A Future that signals when the message has been sent.
+ * @throws IllegalArgumentException if {@code obj} is {@code null}.
+ */
+ Future<Void> sendObject(Object obj);
+
+ /**
+ * Encodes object as a message and sends it asynchronously, using the
+ * SendHandler to signal to the client when the message has been sent.
+ * @param obj The object to be sent.
+ * @param completion Used to signal to the client when the message has
+ * been sent
+ * @throws IllegalArgumentException if {@code obj} or
+ * {@code completion} is {@code null}.
+ */
+ void sendObject(Object obj, SendHandler completion);
+
+ }
+
+ interface Basic extends RemoteEndpoint {
+
+ /**
+ * Send the message, blocking until the message is sent.
+ * @param text The text message to send.
+ * @throws IllegalArgumentException if {@code text} is {@code null}.
+ * @throws IOException if an I/O error occurs during the sending of the
+ * message.
+ */
+ void sendText(String text) throws IOException;
+
+ /**
+ * Send the message, blocking until the message is sent.
+ * @param data The binary message to send
+ * @throws IllegalArgumentException if {@code data} is {@code null}.
+ * @throws IOException if an I/O error occurs during the sending of the
+ * message.
+ */
+ void sendBinary(ByteBuffer data) throws IOException;
+
+ /**
+ * Sends part of a text message to the remote endpoint. Once the first part
+ * of a message has been sent, no other text or binary messages may be sent
+ * until all remaining parts of this message have been sent.
+ *
+ * @param fragment The partial message to send
+ * @param isLast <code>true</code> if this is the last part of the
+ * message, otherwise <code>false</code>
+ * @throws IllegalArgumentException if {@code fragment} is {@code null}.
+ * @throws IOException if an I/O error occurs during the sending of the
+ * message.
+ */
+ void sendText(String fragment, boolean isLast) throws IOException;
+
+ /**
+ * Sends part of a binary message to the remote endpoint. Once the first
+ * part of a message has been sent, no other text or binary messages may be
+ * sent until all remaining parts of this message have been sent.
+ *
+ * @param partialByte The partial message to send
+ * @param isLast <code>true</code> if this is the last part of the
+ * message, otherwise <code>false</code>
+ * @throws IllegalArgumentException if {@code partialByte} is
+ * {@code null}.
+ * @throws IOException if an I/O error occurs during the sending of the
+ * message.
+ */
+ void sendBinary(ByteBuffer partialByte, boolean isLast) throws IOException;
+
+ OutputStream getSendStream() throws IOException;
+
+ Writer getSendWriter() throws IOException;
+
+ /**
+ * Encodes object as a message and sends it to the remote endpoint.
+ * @param data The object to be sent.
+ * @throws EncodeException if there was a problem encoding the
+ * {@code data} object as a websocket message.
+ * @throws IllegalArgumentException if {@code data} is {@code null}.
+ * @throws IOException if an I/O error occurs during the sending of the
+ * message.
+ */
+ void sendObject(Object data) throws IOException, EncodeException;
+
+ }
+ /**
+ * Enable or disable the batching of outgoing messages for this endpoint. If
+ * batching is disabled when it was previously enabled then this method will
+ * block until any currently batched messages have been written.
+ *
+ * @param batchingAllowed New setting
+ * @throws IOException If changing the value resulted in a call to
+ * {@link #flushBatch()} and that call threw an
+ * {@link IOException}.
+ */
+ void setBatchingAllowed(boolean batchingAllowed) throws IOException;
+
+ /**
+ * Obtains the current batching status of the endpoint.
+ *
+ * @return <code>true</code> if batching is enabled, otherwise
+ * <code>false</code>.
+ */
+ boolean getBatchingAllowed();
+
+ /**
+ * Flush any currently batched messages to the remote endpoint. This method
+ * will block until the flush completes.
+ *
+ * @throws IOException If an I/O error occurs while flushing
+ */
+ void flushBatch() throws IOException;
+
+ /**
+ * Send a ping message blocking until the message has been sent. Note that
+ * if a message is in the process of being sent asynchronously, this method
+ * will block until that message and this ping has been sent.
+ *
+ * @param applicationData The payload for the ping message
+ *
+ * @throws IOException If an I/O error occurs while sending the ping
+ * @throws IllegalArgumentException if the applicationData is too large for
+ * a control message (max 125 bytes)
+ */
+ void sendPing(ByteBuffer applicationData)
+ throws IOException, IllegalArgumentException;
+
+ /**
+ * Send a pong message blocking until the message has been sent. Note that
+ * if a message is in the process of being sent asynchronously, this method
+ * will block until that message and this pong has been sent.
+ *
+ * @param applicationData The payload for the pong message
+ *
+ * @throws IOException If an I/O error occurs while sending the pong
+ * @throws IllegalArgumentException if the applicationData is too large for
+ * a control message (max 125 bytes)
+ */
+ void sendPong(ByteBuffer applicationData)
+ throws IOException, IllegalArgumentException;
+}
+
diff --git a/src/java/javax/websocket/SendHandler.java b/src/java/javax/websocket/SendHandler.java
new file mode 100644
index 00000000..65b9a19a
--- /dev/null
+++ b/src/java/javax/websocket/SendHandler.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+public interface SendHandler {
+
+ void onResult(SendResult result);
+}
diff --git a/src/java/javax/websocket/SendResult.java b/src/java/javax/websocket/SendResult.java
new file mode 100644
index 00000000..a3797d5b
--- /dev/null
+++ b/src/java/javax/websocket/SendResult.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+public final class SendResult {
+ private final Throwable exception;
+ private final boolean ok;
+
+ public SendResult(Throwable exception) {
+ this.exception = exception;
+ this.ok = (exception == null);
+ }
+
+ public SendResult() {
+ this (null);
+ }
+
+ public Throwable getException() {
+ return exception;
+ }
+
+ public boolean isOK() {
+ return ok;
+ }
+}
diff --git a/src/java/javax/websocket/Session.java b/src/java/javax/websocket/Session.java
new file mode 100644
index 00000000..eea15e5b
--- /dev/null
+++ b/src/java/javax/websocket/Session.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.URI;
+import java.security.Principal;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public interface Session extends Closeable {
+
+ /**
+ * Get the container that created this session.
+ * @return the container that created this session.
+ */
+ WebSocketContainer getContainer();
+
+ /**
+ * Registers a {@link MessageHandler} for incoming messages. Only one
+ * {@link MessageHandler} may be registered for each message type (text,
+ * binary, pong). The message type will be derived at runtime from the
+ * provided {@link MessageHandler} instance. It is not always possible to do
+ * this so it is better to use
+ * {@link #addMessageHandler(Class, javax.websocket.MessageHandler.Partial)}
+ * or
+ * {@link #addMessageHandler(Class, javax.websocket.MessageHandler.Whole)}.
+ *
+ * @param handler The message handler for a incoming message
+ *
+ * @throws IllegalStateException If a message handler has already been
+ * registered for the associated message type
+ */
+ void addMessageHandler(MessageHandler handler) throws IllegalStateException;
+
+ Set<MessageHandler> getMessageHandlers();
+
+ void removeMessageHandler(MessageHandler listener);
+
+ String getProtocolVersion();
+
+ String getNegotiatedSubprotocol();
+
+ List<Extension> getNegotiatedExtensions();
+
+ boolean isSecure();
+
+ boolean isOpen();
+
+ /**
+ * Get the idle timeout for this session.
+ * @return The current idle timeout for this session in milliseconds. Zero
+ * or negative values indicate an infinite timeout.
+ */
+ long getMaxIdleTimeout();
+
+ /**
+ * Set the idle timeout for this session.
+ * @param timeout The new idle timeout for this session in milliseconds.
+ * Zero or negative values indicate an infinite timeout.
+ */
+ void setMaxIdleTimeout(long timeout);
+
+ /**
+ * Set the current maximum buffer size for binary messages.
+ * @param max The new maximum buffer size in bytes
+ */
+ void setMaxBinaryMessageBufferSize(int max);
+
+ /**
+ * Get the current maximum buffer size for binary messages.
+ * @return The current maximum buffer size in bytes
+ */
+ int getMaxBinaryMessageBufferSize();
+
+ /**
+ * Set the maximum buffer size for text messages.
+ * @param max The new maximum buffer size in characters.
+ */
+ void setMaxTextMessageBufferSize(int max);
+
+ /**
+ * Get the maximum buffer size for text messages.
+ * @return The maximum buffer size in characters.
+ */
+ int getMaxTextMessageBufferSize();
+
+ RemoteEndpoint.Async getAsyncRemote();
+
+ RemoteEndpoint.Basic getBasicRemote();
+
+ /**
+ * Provides a unique identifier for the session. This identifier should not
+ * be relied upon to be generated from a secure random source.
+ * @return A unique identifier for the session.
+ */
+ String getId();
+
+ /**
+ * Close the connection to the remote end point using the code
+ * {@link javax.websocket.CloseReason.CloseCodes#NORMAL_CLOSURE} and an
+ * empty reason phrase.
+ *
+ * @throws IOException if an I/O error occurs while the WebSocket session is
+ * being closed.
+ */
+ @Override
+ void close() throws IOException;
+
+
+ /**
+ * Close the connection to the remote end point using the specified code
+ * and reason phrase.
+ * @param closeReason The reason the WebSocket session is being closed.
+ *
+ * @throws IOException if an I/O error occurs while the WebSocket session is
+ * being closed.
+ */
+ void close(CloseReason closeReason) throws IOException;
+
+ URI getRequestURI();
+
+ Map<String, List<String>> getRequestParameterMap();
+
+ String getQueryString();
+
+ Map<String,String> getPathParameters();
+
+ Map<String,Object> getUserProperties();
+
+ Principal getUserPrincipal();
+
+ /**
+ * Obtain the set of open sessions associated with the same local endpoint
+ * as this session.
+ *
+ * @return The set of currently open sessions for the local endpoint that
+ * this session is associated with.
+ */
+ Set<Session> getOpenSessions();
+
+ /**
+ * Registers a {@link MessageHandler} for partial incoming messages. Only
+ * one {@link MessageHandler} may be registered for each message type (text
+ * or binary, pong messages are never presented as partial messages).
+ *
+ * @param <T> The type of message that the given handler is intended
+ * for
+ * @param clazz The Class that implements T
+ * @param handler The message handler for a incoming message
+ *
+ * @throws IllegalStateException If a message handler has already been
+ * registered for the associated message type
+ *
+ * @since WebSocket 1.1
+ */
+ <T> void addMessageHandler(Class<T> clazz, MessageHandler.Partial<T> handler)
+ throws IllegalStateException;
+
+ /**
+ * Registers a {@link MessageHandler} for whole incoming messages. Only
+ * one {@link MessageHandler} may be registered for each message type (text,
+ * binary, pong).
+ *
+ * @param <T> The type of message that the given handler is intended
+ * for
+ * @param clazz The Class that implements T
+ * @param handler The message handler for a incoming message
+ *
+ * @throws IllegalStateException If a message handler has already been
+ * registered for the associated message type
+ *
+ * @since WebSocket 1.1
+ */
+ <T> void addMessageHandler(Class<T> clazz, MessageHandler.Whole<T> handler)
+ throws IllegalStateException;
+}
diff --git a/src/java/javax/websocket/SessionException.java b/src/java/javax/websocket/SessionException.java
new file mode 100644
index 00000000..428b82ec
--- /dev/null
+++ b/src/java/javax/websocket/SessionException.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+public class SessionException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ private final Session session;
+
+
+ public SessionException(String message, Throwable cause, Session session) {
+ super(message, cause);
+ this.session = session;
+ }
+
+
+ public Session getSession() {
+ return session;
+ }
+}
diff --git a/src/java/javax/websocket/WebSocketContainer.java b/src/java/javax/websocket/WebSocketContainer.java
new file mode 100644
index 00000000..f2da3e43
--- /dev/null
+++ b/src/java/javax/websocket/WebSocketContainer.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Set;
+
+public interface WebSocketContainer {
+
+ /**
+ * Get the default timeout for sending a message asynchronously.
+ * @return The current default timeout in milliseconds. A non-positive value
+ * means an infinite timeout.
+ */
+ long getDefaultAsyncSendTimeout();
+
+ /**
+ * Set the default timeout for sending a message asynchronously.
+ * @param timeout The new default timeout in milliseconds. A non-positive
+ * value means an infinite timeout.
+ */
+ void setAsyncSendTimeout(long timeout);
+
+ Session connectToServer(Object endpoint, URI path)
+ throws DeploymentException, IOException;
+
+ Session connectToServer(Class<?> annotatedEndpointClass, URI path)
+ throws DeploymentException, IOException;
+
+ /**
+ * Creates a new connection to the WebSocket.
+ *
+ * @param endpoint
+ * The endpoint instance that will handle responses from the
+ * server
+ * @param clientEndpointConfiguration
+ * Used to configure the new connection
+ * @param path
+ * The full URL of the WebSocket endpoint to connect to
+ *
+ * @return The WebSocket session for the connection
+ *
+ * @throws DeploymentException If the connection cannot be established
+ * @throws IOException If an I/O occurred while trying to establish the
+ * connection
+ */
+ Session connectToServer(Endpoint endpoint,
+ ClientEndpointConfig clientEndpointConfiguration, URI path)
+ throws DeploymentException, IOException;
+
+ /**
+ * Creates a new connection to the WebSocket.
+ *
+ * @param endpoint
+ * An instance of this class will be created to handle responses
+ * from the server
+ * @param clientEndpointConfiguration
+ * Used to configure the new connection
+ * @param path
+ * The full URL of the WebSocket endpoint to connect to
+ *
+ * @return The WebSocket session for the connection
+ *
+ * @throws DeploymentException If the connection cannot be established
+ * @throws IOException If an I/O occurred while trying to establish the
+ * connection
+ */
+ Session connectToServer(Class<? extends Endpoint> endpoint,
+ ClientEndpointConfig clientEndpointConfiguration, URI path)
+ throws DeploymentException, IOException;
+
+ /**
+ * Get the current default session idle timeout.
+ * @return The current default session idle timeout in milliseconds. Zero or
+ * negative values indicate an infinite timeout.
+ */
+ long getDefaultMaxSessionIdleTimeout();
+
+ /**
+ * Set the default session idle timeout.
+ * @param timeout The new default session idle timeout in milliseconds. Zero
+ * or negative values indicate an infinite timeout.
+ */
+ void setDefaultMaxSessionIdleTimeout(long timeout);
+
+ /**
+ * Get the default maximum buffer size for binary messages.
+ * @return The current default maximum buffer size in bytes
+ */
+ int getDefaultMaxBinaryMessageBufferSize();
+
+ /**
+ * Set the default maximum buffer size for binary messages.
+ * @param max The new default maximum buffer size in bytes
+ */
+ void setDefaultMaxBinaryMessageBufferSize(int max);
+
+ /**
+ * Get the default maximum buffer size for text messages.
+ * @return The current default maximum buffer size in characters
+ */
+ int getDefaultMaxTextMessageBufferSize();
+
+ /**
+ * Set the default maximum buffer size for text messages.
+ * @param max The new default maximum buffer size in characters
+ */
+ void setDefaultMaxTextMessageBufferSize(int max);
+
+ /**
+ * Get the installed extensions.
+ * @return The set of extensions that are supported by this WebSocket
+ * implementation.
+ */
+ Set<Extension> getInstalledExtensions();
+}
diff --git a/src/java/javax/websocket/server/DefaultServerEndpointConfig.java b/src/java/javax/websocket/server/DefaultServerEndpointConfig.java
new file mode 100644
index 00000000..7c3b8d7d
--- /dev/null
+++ b/src/java/javax/websocket/server/DefaultServerEndpointConfig.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket.server;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.websocket.Decoder;
+import javax.websocket.Encoder;
+import javax.websocket.Extension;
+
+/**
+ * Provides the default configuration for WebSocket server endpoints.
+ */
+final class DefaultServerEndpointConfig implements ServerEndpointConfig {
+
+ private final Class<?> endpointClass;
+ private final String path;
+ private final List<String> subprotocols;
+ private final List<Extension> extensions;
+ private final List<Class<? extends Encoder>> encoders;
+ private final List<Class<? extends Decoder>> decoders;
+ private final Configurator serverEndpointConfigurator;
+ private final Map<String,Object> userProperties = new ConcurrentHashMap<>();
+
+ DefaultServerEndpointConfig(
+ Class<?> endpointClass, String path,
+ List<String> subprotocols, List<Extension> extensions,
+ List<Class<? extends Encoder>> encoders,
+ List<Class<? extends Decoder>> decoders,
+ Configurator serverEndpointConfigurator) {
+ this.endpointClass = endpointClass;
+ this.path = path;
+ this.subprotocols = subprotocols;
+ this.extensions = extensions;
+ this.encoders = encoders;
+ this.decoders = decoders;
+ this.serverEndpointConfigurator = serverEndpointConfigurator;
+ }
+
+ @Override
+ public Class<?> getEndpointClass() {
+ return endpointClass;
+ }
+
+ @Override
+ public List<Class<? extends Encoder>> getEncoders() {
+ return this.encoders;
+ }
+
+ @Override
+ public List<Class<? extends Decoder>> getDecoders() {
+ return this.decoders;
+ }
+
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ @Override
+ public Configurator getConfigurator() {
+ return serverEndpointConfigurator;
+ }
+
+ @Override
+ public final Map<String, Object> getUserProperties() {
+ return userProperties;
+ }
+
+ @Override
+ public final List<String> getSubprotocols() {
+ return subprotocols;
+ }
+
+ @Override
+ public final List<Extension> getExtensions() {
+ return extensions;
+ }
+}
diff --git a/src/java/javax/websocket/server/HandshakeRequest.java b/src/java/javax/websocket/server/HandshakeRequest.java
new file mode 100644
index 00000000..f2e33273
--- /dev/null
+++ b/src/java/javax/websocket/server/HandshakeRequest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket.server;
+
+import java.net.URI;
+import java.security.Principal;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Represents the HTTP request that asked to be upgraded to WebSocket.
+ */
+public interface HandshakeRequest {
+
+ static final String SEC_WEBSOCKET_KEY = "Sec-WebSocket-Key";
+ static final String SEC_WEBSOCKET_PROTOCOL = "Sec-WebSocket-Protocol";
+ static final String SEC_WEBSOCKET_VERSION = "Sec-WebSocket-Version";
+ static final String SEC_WEBSOCKET_EXTENSIONS= "Sec-WebSocket-Extensions";
+
+ Map<String,List<String>> getHeaders();
+
+ Principal getUserPrincipal();
+
+ URI getRequestURI();
+
+ boolean isUserInRole(String role);
+
+ /**
+ * Get the HTTP Session object associated with this request. Object is used
+ * to avoid a direct dependency on the Servlet API.
+ * @return The javax.servlet.http.HttpSession object associated with this
+ * request, if any.
+ */
+ Object getHttpSession();
+
+ Map<String, List<String>> getParameterMap();
+
+ String getQueryString();
+}
diff --git a/src/java/javax/websocket/server/PathParam.java b/src/java/javax/websocket/server/PathParam.java
new file mode 100644
index 00000000..ff1d085e
--- /dev/null
+++ b/src/java/javax/websocket/server/PathParam.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket.server;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Used to annotate method parameters on POJO endpoints the the {@link
+ * ServerEndpoint} has been defined with a {@link ServerEndpoint#value()} that
+ * uses a URI template.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface PathParam {
+ String value();
+}
diff --git a/src/java/javax/websocket/server/ServerApplicationConfig.java b/src/java/javax/websocket/server/ServerApplicationConfig.java
new file mode 100644
index 00000000..b91f1c43
--- /dev/null
+++ b/src/java/javax/websocket/server/ServerApplicationConfig.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket.server;
+
+import java.util.Set;
+
+import javax.websocket.Endpoint;
+
+/**
+ * Applications may provide an implementation of this interface to filter the
+ * discovered WebSocket endpoints that are deployed. Implementations of this
+ * class will be discovered via an ServletContainerInitializer scan.
+ */
+public interface ServerApplicationConfig {
+
+ /**
+ * Enables applications to filter the discovered implementations of
+ * {@link ServerEndpointConfig}.
+ *
+ * @param scanned The {@link Endpoint} implementations found in the
+ * application
+ * @return The set of configurations for the endpoint the application
+ * wishes to deploy
+ */
+ Set<ServerEndpointConfig> getEndpointConfigs(
+ Set<Class<? extends Endpoint>> scanned);
+
+ /**
+ * Enables applications to filter the discovered classes annotated with
+ * {@link ServerEndpoint}.
+ *
+ * @param scanned The POJOs annotated with {@link ServerEndpoint} found in
+ * the application
+ * @return The set of POJOs the application wishes to deploy
+ */
+ Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned);
+}
diff --git a/src/java/javax/websocket/server/ServerContainer.java b/src/java/javax/websocket/server/ServerContainer.java
new file mode 100644
index 00000000..3243a07c
--- /dev/null
+++ b/src/java/javax/websocket/server/ServerContainer.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket.server;
+
+import javax.websocket.DeploymentException;
+import javax.websocket.WebSocketContainer;
+
+/**
+ * Provides the ability to deploy endpoints programmatically.
+ */
+public interface ServerContainer extends WebSocketContainer {
+ public abstract void addEndpoint(Class<?> clazz) throws DeploymentException;
+
+ public abstract void addEndpoint(ServerEndpointConfig sec)
+ throws DeploymentException;
+}
diff --git a/src/java/javax/websocket/server/ServerEndpoint.java b/src/java/javax/websocket/server/ServerEndpoint.java
new file mode 100644
index 00000000..43b7dfa2
--- /dev/null
+++ b/src/java/javax/websocket/server/ServerEndpoint.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket.server;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.websocket.Decoder;
+import javax.websocket.Encoder;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface ServerEndpoint {
+
+ /**
+ * URI or URI-template that the annotated class should be mapped to.
+ * @return The URI or URI-template that the annotated class should be mapped
+ * to.
+ */
+ String value();
+
+ String[] subprotocols() default {};
+
+ Class<? extends Decoder>[] decoders() default {};
+
+ Class<? extends Encoder>[] encoders() default {};
+
+ public Class<? extends ServerEndpointConfig.Configurator> configurator()
+ default ServerEndpointConfig.Configurator.class;
+}
diff --git a/src/java/javax/websocket/server/ServerEndpointConfig.java b/src/java/javax/websocket/server/ServerEndpointConfig.java
new file mode 100644
index 00000000..5afdf79c
--- /dev/null
+++ b/src/java/javax/websocket/server/ServerEndpointConfig.java
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 javax.websocket.server;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ServiceLoader;
+
+import javax.websocket.Decoder;
+import javax.websocket.Encoder;
+import javax.websocket.EndpointConfig;
+import javax.websocket.Extension;
+import javax.websocket.HandshakeResponse;
+
+/**
+ * Provides configuration information for WebSocket endpoints published to a
+ * server. Applications may provide their own implementation or use
+ * {@link Builder}.
+ */
+public interface ServerEndpointConfig extends EndpointConfig {
+
+ Class<?> getEndpointClass();
+
+ /**
+ * Returns the path at which this WebSocket server endpoint has been
+ * registered. It may be a path or a level 0 URI template.
+ * @return The registered path
+ */
+ String getPath();
+
+ List<String> getSubprotocols();
+
+ List<Extension> getExtensions();
+
+ Configurator getConfigurator();
+
+
+ public final class Builder {
+
+ public static Builder create(
+ Class<?> endpointClass, String path) {
+ return new Builder(endpointClass, path);
+ }
+
+
+ private final Class<?> endpointClass;
+ private final String path;
+ private List<Class<? extends Encoder>> encoders =
+ Collections.emptyList();
+ private List<Class<? extends Decoder>> decoders =
+ Collections.emptyList();
+ private List<String> subprotocols = Collections.emptyList();
+ private List<Extension> extensions = Collections.emptyList();
+ private Configurator configurator =
+ Configurator.fetchContainerDefaultConfigurator();
+
+
+ private Builder(Class<?> endpointClass,
+ String path) {
+ this.endpointClass = endpointClass;
+ this.path = path;
+ }
+
+ public ServerEndpointConfig build() {
+ return new DefaultServerEndpointConfig(endpointClass, path,
+ subprotocols, extensions, encoders, decoders, configurator);
+ }
+
+
+ public Builder encoders(
+ List<Class<? extends Encoder>> encoders) {
+ if (encoders == null || encoders.size() == 0) {
+ this.encoders = Collections.emptyList();
+ } else {
+ this.encoders = Collections.unmodifiableList(encoders);
+ }
+ return this;
+ }
+
+
+ public Builder decoders(
+ List<Class<? extends Decoder>> decoders) {
+ if (decoders == null || decoders.size() == 0) {
+ this.decoders = Collections.emptyList();
+ } else {
+ this.decoders = Collections.unmodifiableList(decoders);
+ }
+ return this;
+ }
+
+
+ public Builder subprotocols(
+ List<String> subprotocols) {
+ if (subprotocols == null || subprotocols.size() == 0) {
+ this.subprotocols = Collections.emptyList();
+ } else {
+ this.subprotocols = Collections.unmodifiableList(subprotocols);
+ }
+ return this;
+ }
+
+
+ public Builder extensions(
+ List<Extension> extensions) {
+ if (extensions == null || extensions.size() == 0) {
+ this.extensions = Collections.emptyList();
+ } else {
+ this.extensions = Collections.unmodifiableList(extensions);
+ }
+ return this;
+ }
+
+
+ public Builder configurator(Configurator serverEndpointConfigurator) {
+ if (serverEndpointConfigurator == null) {
+ this.configurator = Configurator.fetchContainerDefaultConfigurator();
+ } else {
+ this.configurator = serverEndpointConfigurator;
+ }
+ return this;
+ }
+ }
+
+
+ public class Configurator {
+
+ private static volatile Configurator defaultImpl = null;
+ private static final Object defaultImplLock = new Object();
+
+ private static final String DEFAULT_IMPL_CLASSNAME =
+ "nginx.unit.websocket.server.DefaultServerEndpointConfigurator";
+
+ public static void setDefault(Configurator def) {
+ synchronized (defaultImplLock) {
+ defaultImpl = def;
+ }
+ }
+
+ static Configurator fetchContainerDefaultConfigurator() {
+ if (defaultImpl == null) {
+ synchronized (defaultImplLock) {
+ if (defaultImpl == null) {
+ defaultImpl = loadDefault();
+ }
+ }
+ }
+ return defaultImpl;
+ }
+
+
+ private static Configurator loadDefault() {
+ Configurator result = null;
+
+ ServiceLoader<Configurator> serviceLoader =
+ ServiceLoader.load(Configurator.class);
+
+ Iterator<Configurator> iter = serviceLoader.iterator();
+ while (result == null && iter.hasNext()) {
+ result = iter.next();
+ }
+
+ // Fall-back. Also used by unit tests
+ if (result == null) {
+ try {
+ @SuppressWarnings("unchecked")
+ Class<Configurator> clazz =
+ (Class<Configurator>) Class.forName(
+ DEFAULT_IMPL_CLASSNAME);
+ result = clazz.getConstructor().newInstance();
+ } catch (ReflectiveOperationException | IllegalArgumentException |
+ SecurityException e) {
+ // No options left. Just return null.
+ }
+ }
+ return result;
+ }
+
+ public String getNegotiatedSubprotocol(List<String> supported,
+ List<String> requested) {
+ return fetchContainerDefaultConfigurator().getNegotiatedSubprotocol(supported, requested);
+ }
+
+ public List<Extension> getNegotiatedExtensions(List<Extension> installed,
+ List<Extension> requested) {
+ return fetchContainerDefaultConfigurator().getNegotiatedExtensions(installed, requested);
+ }
+
+ public boolean checkOrigin(String originHeaderValue) {
+ return fetchContainerDefaultConfigurator().checkOrigin(originHeaderValue);
+ }
+
+ public void modifyHandshake(ServerEndpointConfig sec,
+ HandshakeRequest request, HandshakeResponse response) {
+ fetchContainerDefaultConfigurator().modifyHandshake(sec, request, response);
+ }
+
+ public <T extends Object> T getEndpointInstance(Class<T> clazz)
+ throws InstantiationException {
+ return fetchContainerDefaultConfigurator().getEndpointInstance(
+ clazz);
+ }
+ }
+}