/** * Log a debug message using the configured debug level. * * This method appends thread name information to the end of the logged message. * * @param message debug message. */ public void debugLog(final String message) { debugLog(message, (Object[]) null); }
/** * Log a debug message using the configured debug level. * * This method appends thread name information to the end of the logged message. * * @param message debug message. */ public void debugLog(final String message) { debugLog(message, (Object[]) null); }
/** * Release a single reference to the current request scope instance. * <p> * Once all instance references are released, the instance will be recycled. */ @Override public void release() { if (referenceCounter.decrementAndGet() < 1) { try { store.clear(); } finally { logger.debugLog("Released scope instance {0}", this); } } }
private void shutdown() { if (state.getAndSet(EventProcessor.State.CLOSED) != EventProcessor.State.CLOSED) { // shut down only if has not been shut down before LOGGER.debugLog("Shutting down event processing."); executor.close(); } }
ResponseWriter(final Response response, final boolean configSetStatusOverSendError) { this.grizzlyResponse = response; this.configSetStatusOverSendError = configSetStatusOverSendError; if (logger.isDebugLoggable()) { this.name = "ResponseWriter {" + "id=" + UUID.randomUUID().toString() + ", grizzlyResponse=" + grizzlyResponse.hashCode() + '}'; logger.debugLog("{0} - init", name); } else { this.name = "ResponseWriter"; } }
@Override public void setSuspendTimeout(final long timeOut, final TimeUnit timeUnit) throws IllegalStateException { try { TimeoutTimer timer = reference.get(); if (timer == null) { throw new IllegalStateException("Response has not been suspended"); } timer.reschedule(timeOut, timeUnit); } finally { logger.debugLog("setTimeout(...) called"); } }
/** * Release a single reference to the current request scope instance. * <p> * Once all instance references are released, the instance will be recycled. */ @Override public void release() { if (referenceCounter.decrementAndGet() < 1) { try { new HashSet<>(store.keySet()).forEach(this::remove); } finally { logger.debugLog("Released scope instance {0}", this); } } }
/** * Release a single reference to the current request scope instance. * <p> * Once all instance references are released, the instance will be recycled. */ @Override public void release() { if (referenceCounter.decrementAndGet() < 1) { try { new HashSet<>(store.keySet()).forEach(this::remove); } finally { logger.debugLog("Released scope instance {0}", this); } } }
/** * Await the initial contact with the SSE endpoint. */ public void awaitFirstContact() { LOGGER.debugLog("Awaiting first contact signal."); try { if (firstContactSignal == null) { return; } try { firstContactSignal.await(); } catch (InterruptedException ex) { LOGGER.log(CONNECTION_ERROR_LEVEL, LocalizationMessages.EVENT_SOURCE_OPEN_CONNECTION_INTERRUPTED(), ex); Thread.currentThread().interrupt(); } } finally { LOGGER.debugLog("First contact signal released."); } }
@Override public boolean suspend(final long timeOut, final TimeUnit timeUnit, final TimeoutHandler timeoutHandler) { try { grizzlyResponse.suspend(timeOut, timeUnit, EMPTY_COMPLETION_HANDLER, new org.glassfish.grizzly.http.server.TimeoutHandler() { @Override public boolean onTimeout(final Response response) { if (timeoutHandler != null) { timeoutHandler.onTimeout(ResponseWriter.this); } // TODO should we return true in some cases instead? // Returning false relies on the fact that the timeoutHandler will resume the response. return false; } } ); return true; } catch (final IllegalStateException ex) { return false; } finally { logger.debugLog("{0} - suspend(...) called", name); } }
@Override public void commit() { try { if (grizzlyResponse.isSuspended()) { grizzlyResponse.resume(); } } finally { logger.debugLog("{0} - commit() called", name); } }
@Override public void setSuspendTimeout(final long timeOut, final TimeUnit timeUnit) throws IllegalStateException { try { grizzlyResponse.getSuspendContext().setTimeout(timeOut, timeUnit); } finally { logger.debugLog("{0} - setTimeout(...) called", name); } }
@Override public void commit() { try { response.close(); } catch (final IOException e) { logger.log(Level.SEVERE, "Unable to send 500 error response.", e); } finally { logger.debugLog("commit() called"); } }
@Override public boolean suspend(final long timeOut, final TimeUnit timeUnit, final TimeoutHandler timeoutHandler) { try { TimeoutTimer timer = reference.get(); if (timer == null) { TimeoutDispatcher task = new TimeoutDispatcher(this, timeoutHandler); ScheduledFuture<?> future = scheduler.schedule(task, timeOut == 0 ? Integer.MAX_VALUE : timeOut, timeOut == 0 ? TimeUnit.SECONDS : timeUnit); timer = new TimeoutTimer(scheduler, future, task); reference.set(timer); return true; } return false; } catch (final IllegalStateException ex) { return false; } finally { logger.debugLog("suspend(...) called"); } }
@Override public void failure(final Throwable error) { try { if (!response.isCommitted()) { response.setCode(javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); response.setDescription(error.getMessage()); } } finally { logger.debugLog("failure(...) called"); commit(); rethrow(error); } }
/** * Schedule a new event processor task to reconnect after the specified {@code delay} [milliseconds]. * * If the {@code delay} is zero or negative, the new reconnect task will be scheduled immediately. * The {@code reconnectDelay} and {@code lastEventId} field values are propagated into the newly * scheduled task. * <p> * The method will silently abort in case the event source is not {@link EventSource#isOpen() open}. * </p> * * @param delay specifies the amount of time [milliseconds] to wait before attempting a reconnect. * If zero or negative, the new reconnect task will be scheduled immediately. */ private void scheduleReconnect(final long delay) { final State s = state.get(); if (s != State.OPEN) { LOGGER.debugLog("Aborting reconnect of event source in {0} state", state); return; } // propagate the current reconnectDelay, but schedule based on the delay parameter final EventProcessor processor = new EventProcessor(this); if (delay > 0) { executor.schedule(processor, delay, TimeUnit.MILLISECONDS); } else { executor.submit(processor); } }
@Override public OutputStream writeResponseStatusAndHeaders(final long contentLength, final ContainerResponse context) throws ContainerException { try { final javax.ws.rs.core.Response.StatusType statusInfo = context.getStatusInfo(); if (statusInfo.getReasonPhrase() == null) { grizzlyResponse.setStatus(statusInfo.getStatusCode()); } else { grizzlyResponse.setStatus(statusInfo.getStatusCode(), statusInfo.getReasonPhrase()); } grizzlyResponse.setContentLengthLong(contentLength); for (final Map.Entry<String, List<String>> e : context.getStringHeaders().entrySet()) { for (final String value : e.getValue()) { grizzlyResponse.addHeader(e.getKey(), value); } } return grizzlyResponse.getOutputStream(); } finally { logger.debugLog("{0} - writeResponseStatusAndHeaders() called", name); } }
/** * Called by the event source when an inbound event is received. * * This listener aggregator method is responsible for invoking {@link EventSource#onEvent(InboundEvent)} * method on the owning event source as well as for notifying all registered {@link EventListener event listeners}. * * @param event incoming {@link InboundEvent inbound event}. */ @Override public void onEvent(final InboundEvent event) { if (event == null) { return; } LOGGER.debugLog("New event received."); if (event.getId() != null) { lastEventId = event.getId(); } if (event.isReconnectDelaySet()) { reconnectDelay = event.getReconnectDelay(); } notify(eventListener, event); notify(unboundListeners, event); final String eventName = event.getName(); if (eventName != null) { final List<EventListener> eventListeners = boundListeners.get(eventName); if (eventListeners != null) { notify(eventListeners, event); } } }
@Override @SuppressWarnings("MagicNumber") public void failure(final Throwable error) { try { if (!grizzlyResponse.isCommitted()) { try { if (configSetStatusOverSendError) { grizzlyResponse.reset(); grizzlyResponse.setStatus(500, "Request failed."); } else { grizzlyResponse.sendError(500, "Request failed."); } } catch (final IllegalStateException ex) { // a race condition externally committing the response can still occur... logger.log(Level.FINER, "Unable to reset failed response.", ex); } catch (final IOException ex) { throw new ContainerException( LocalizationMessages.EXCEPTION_SENDING_ERROR_RESPONSE(500, "Request failed."), ex); } } } finally { logger.debugLog("{0} - failure(...) called", name); rethrow(error); } }
@Override public void service(final Request request, final Response response) { final ResponseWriter responseWriter = new ResponseWriter(response, configSetStatusOverSendError); try { logger.debugLog("GrizzlyHttpContainer.service(...) started"); URI baseUri = getBaseUri(request); URI requestUri = getRequestUri(request); final ContainerRequest requestContext = new ContainerRequest(baseUri, requestUri, request.getMethod().getMethodString(), getSecurityContext(request), new GrizzlyRequestPropertiesDelegate(request)); requestContext.setEntityStream(request.getInputStream()); for (final String headerName : request.getHeaderNames()) { requestContext.headers(headerName, request.getHeaders(headerName)); } requestContext.setWriter(responseWriter); requestContext.setRequestScopedInitializer(injectionManager -> { injectionManager.<Ref<Request>>getInstance(RequestTYPE).set(request); injectionManager.<Ref<Response>>getInstance(ResponseTYPE).set(response); }); appHandler.handle(requestContext); } finally { logger.debugLog("GrizzlyHttpContainer.service(...) finished"); } }