public void stop(boolean now) throws Exception { log.info("Stopping Gravity (now=%s)...", now); synchronized (this) { if (adapterFactory != null) { try { adapterFactory.stopAll(); } catch (Exception e) { log.error(e, "Error while stopping adapter factory"); } adapterFactory = null; } if (serverChannel != null) { try { removeChannel(serverChannel.getId(), false); } catch (Exception e) { log.error(e, "Error while removing server channel: %s", serverChannel); } serverChannel = null; } if (channelsTimer != null) { try { channelsTimer.cancel(); } catch (Exception e) { log.error(e, "Error while cancelling channels timer"); } channelsTimer = null; } if (gravityPool != null) { try { if (now) gravityPool.shutdownNow(); else gravityPool.shutdown(); } catch (Exception e) { log.error(e, "Error while stopping thread pool"); } gravityPool = null; } if (udpReceiverFactory != null) { try { udpReceiverFactory.stop(); } catch (Exception e) { log.error(e, "Error while stopping udp receiver factory"); } udpReceiverFactory = null; } started = false; } log.info("Gravity sucessfully stopped."); }
protected void createUdpReceiver(UdpReceiverFactory factory, AsyncHttpContext asyncHttpContext) { OutputStream os = null; try { Message connectMessage = asyncHttpContext.getConnectMessage(); if (udpReceiver == null || udpReceiver.isClosed()) udpReceiver = factory.newReceiver(this, asyncHttpContext.getRequest(), connectMessage); AsyncMessage reply = udpReceiver.acknowledge(connectMessage); HttpServletRequest request = asyncHttpContext.getRequest(); HttpServletResponse response = asyncHttpContext.getResponse(); GraniteContext context = HttpGraniteContext.createThreadIntance( gravity.getGraniteConfig(), gravity.getServicesConfig(), null, request, response); ((AMFContextImpl) context.getAMFContext()) .setCurrentAmf3Message(asyncHttpContext.getConnectMessage()); GravityServletUtil.serialize( gravity, response, new AsyncMessage[] {reply}, ContentType.forMimeType(request.getContentType())); } catch (ServletException e) { log.error(e, "Could not send UDP connect acknowledgement to channel: %s", this); } catch (IOException e) { log.error(e, "Could not send UDP connect acknowledgement to channel: %s", this); } finally { try { GraniteContext.release(); } catch (Exception e) { // should never happen... } // Close output stream. try { if (os != null) { try { os.close(); } catch (IOException e) { log.warn(e, "Could not close output stream (ignored)"); } } } finally { releaseAsyncHttpContext(asyncHttpContext); } } }
private Message handleSecurityMessage(CommandMessage message) { GraniteConfig config = GraniteContext.getCurrentInstance().getGraniteConfig(); Message response = null; if (!config.hasSecurityService()) log.warn( "Ignored security operation (no security settings in granite-config.xml): %s", message); else if (!config.getSecurityService().acceptsContext()) log.info( "Ignored security operation (security service does not handle this kind of granite context)", message); else { SecurityService securityService = config.getSecurityService(); try { if (message.isLoginOperation()) securityService.login( message.getBody(), (String) message.getHeader(Message.CREDENTIALS_CHARSET_HEADER)); else securityService.logout(); } catch (Exception e) { if (e instanceof SecurityServiceException) log.debug(e, "Could not process security operation: %s", message); else log.error(e, "Could not process security operation: %s", message); response = new ErrorMessage(message, e, true); } } if (response == null) { response = new AcknowledgeMessage(message, true); // For SDK 2.0.1_Hotfix2. if (message.isSecurityOperation()) response.setBody("success"); } return response; }
public void receive(AsyncMessage message) throws MessageReceivingException { if (message == null) throw new NullPointerException("message cannot be null"); GravityInternal gravity = getGravity(); if (udpReceiver != null) { if (udpReceiver.isClosed()) return; try { udpReceiver.receive(message); } catch (MessageReceivingException e) { if (e.getCause() instanceof SocketException) { log.debug(e, "Closing unreachable UDP channel %s", getId()); udpReceiver.close(false); } else log.error(e, "Cannot access UDP channel %s", getId()); } return; } receivedQueueLock.lock(); try { if (receivedQueue.size() + 1 > gravity.getGravityConfig().getMaxMessagesQueuedPerChannel()) throw new MessageReceivingException( message, "Could not queue message (channel's queue is full) for channel: " + this); log.debug( "Channel %s queue message %s for client %s", getId(), message.getMessageId(), message.getClientId()); receivedQueue.add(message); } finally { receivedQueueLock.unlock(); } if (hasAsyncHttpContext()) receiver.queue(gravity); }
/* * (non-Javadoc) * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (log.isInfoEnabled()) try { GraniteContext context = HttpGraniteContext.createThreadIntance( graniteConfig, servicesConfig, getServletContext(), request, response); if (context == null) throw new ServletException("GraniteContext not Initialized!!"); // AMFContextImpl amf = (AMFContextImpl) context.getAMFContext(); // Phase1 Deserializing AMF0 request if (log.isInfoEnabled()) log.info(">>>>> Deserializing AMF0 request from..." + request.getRequestURI()); AMF0Deserializer deserializer = new AMF0Deserializer(new DataInputStream(request.getInputStream())); AMF0Message amf0Request = deserializer.getAMFMessage(); // Phase2 Processing AMF0 request if (log.isInfoEnabled()) log.info(">>>>> Processing AMF0 request: " + amf0Request); AMF0Message amf0Response = AMF0MessageProcessor.process(amf0Request); if (log.isInfoEnabled()) log.info("<<<<< Returning AMF0 response: " + amf0Response); // Phase3 Send back response to the client response.setContentType(AMF0Message.CONTENT_TYPE); AMF0Serializer serializer = new AMF0Serializer(new DataOutputStream(response.getOutputStream())); serializer.serializeMessage(amf0Response); if (log.isInfoEnabled()) log.info("...End of Processing AMF Request......"); } catch (Exception e) { log.error(e, "Could not handle AMF request"); throw new ServletException(e); } }
public boolean handleMarkerItem(ScannedItem item) { try { return handleProperties(item.loadAsProperties()); } catch (Exception e) { log.error(e, "Could not load properties: %s", item); } return true; }
public Channel removeChannel(String channelId, boolean timeout) { if (channelId == null) return null; // Remove existing channel id/subscriptions in distributed data (clustering). try { DistributedData gdd = graniteConfig.getDistributedDataFactory().getInstance(); if (gdd != null) { log.debug("Removing channel id from distributed data: %s", channelId); gdd.removeChannelId(channelId); } } catch (Exception e) { log.error(e, "Could not remove channel id from distributed data: %s", channelId); } TimeChannel<?> timeChannel = channels.get(channelId); Channel channel = null; if (timeChannel != null) { try { if (timeChannel.getTimerTask() != null) timeChannel.getTimerTask().cancel(); } catch (Exception e) { // Should never happen... } channel = timeChannel.getChannel(); try { for (Subscription subscription : channel.getSubscriptions()) { try { Message message = subscription.getUnsubscribeMessage(); handleMessage(channel.getFactory(), message, true); } catch (Exception e) { log.error( e, "Error while unsubscribing channel: %s from subscription: %s", channel, subscription); } } } finally { channels.remove(channelId); channel.destroy(timeout); } } return channel; }
private boolean handleProperties(Properties properties) { if (properties.getProperty("dependsOn") != null) { String dependsOn = properties.getProperty("dependsOn"); try { TypeUtil.forName(dependsOn); } catch (ClassNotFoundException e) { // Class not found, skip scan for this package return true; } } String classGetterName = properties.getProperty("classGetter"); if (!classGetterSet && classGetterName != null) { try { classGetter = TypeUtil.newInstance(classGetterName, ClassGetter.class); } catch (Throwable t) { log.error(t, "Could not create instance of: %s", classGetterName); } } String amf3MessageInterceptorName = properties.getProperty("amf3MessageInterceptor"); if (amf3MessageInterceptor == null && amf3MessageInterceptorName != null) { try { amf3MessageInterceptor = TypeUtil.newInstance(amf3MessageInterceptorName, AMF3MessageInterceptor.class); } catch (Throwable t) { log.error(t, "Could not create instance of: %s", amf3MessageInterceptorName); } } for (Map.Entry<?, ?> me : properties.entrySet()) { if (me.getKey().toString().startsWith("converter.")) { String converterName = me.getValue().toString(); try { converterClasses.add(TypeUtil.forName(converterName, Converter.class)); } catch (Exception e) { throw new GraniteConfigException( "Could not get converter class for: " + converterName, e); } } } return false; }
private void scanConfig(String graniteConfigProperties) { // if config overriding exists Scanner scanner = ScannerFactory.createScanner( this, graniteConfigProperties != null ? graniteConfigProperties : GRANITE_CONFIG_PROPERTIES); try { scanner.scan(); } catch (Exception e) { log.error(e, "Could not scan classpath for configuration"); } }
private void handleClass(Class<?> clazz) { if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) return; if (Externalizer.class.isAssignableFrom(clazz)) { try { scannedExternalizers.add(TypeUtil.newInstance(clazz, Externalizer.class)); } catch (Exception e) { log.error(e, "Could not create new instance of: %s", clazz); } } if (ExceptionConverter.class.isAssignableFrom(clazz)) { try { exceptionConverters.add(TypeUtil.newInstance(clazz, ExceptionConverter.class)); } catch (Exception e) { if (!clazz .getName() .equals("org.granite.tide.hibernate.HibernateValidatorExceptionConverter")) // GDS-582 log.error(e, "Could not create new instance of: %s", clazz); } } }
public void handleScannedItem(ScannedItem item) { if ("class".equals(item.getExtension()) && item.getName().indexOf('$') == -1) { try { handleClass(item.loadAsClass()); } catch (NoClassDefFoundError e) { // Ignore errors with Tide classes depending on Gravity } catch (LinkageError e) { // Ignore errors with GraniteDS/Hibernate classes depending on Hibernate 3 when using // Hibernate 4 } catch (Throwable t) { log.error(t, "Could not load class: %s", item); } } }
@Override public Set<Class<?>> scan(Set<String> packageNames) { Set<Class<?>> classes = new HashSet<Class<?>>(); Scanner scanner = ScannerFactory.createScanner(new MessagingScannedItemHandler(packageNames, classes), null); try { scanner.scan(); } catch (Exception e) { log.error(e, "Could not scan classpath for @RemoteAlias"); } return classes; }
@Validate public void start() { log.debug("Start OSGiServiceSimple: " + toString()); if (servicesConfig.findServiceById(id) == null) { // Clear destinations destinations.clear(); servicesConfig.addService(this); started = true; } else { log.error("Service \"" + id + "\" already registered"); } }
public void registerExceptionConverter( Class<? extends ExceptionConverter> exceptionConverterClass, boolean first) { for (ExceptionConverter ec : exceptionConverters) { if (ec.getClass() == exceptionConverterClass) return; } try { ExceptionConverter exceptionConverter = TypeUtil.newInstance(exceptionConverterClass, ExceptionConverter.class); if (first) exceptionConverters.add(0, exceptionConverter); else exceptionConverters.add(exceptionConverter); } catch (Exception e) { log.error(e, "Could not instantiate exception converter: %s", exceptionConverterClass); } }
@Override protected ServiceException getServiceException( Message request, Destination destination, String method, Throwable t) { if (t == null) throw new NullPointerException("Parameter t cannot be null"); Map<String, Object> extendedData = new HashMap<String, Object>(); if (t instanceof ServiceException) { ((ServiceException) t).getExtendedData().putAll(extendedData); return (ServiceException) t; } List<Throwable> causes = new ArrayList<Throwable>(); for (Throwable cause = t; cause != null; cause = getCause(cause)) causes.add(cause); String detail = "\n" + "- destination: " + (destination != null ? destination.getId() : "") + "\n" + "- method: " + method + "\n" + "- exception: " + t.toString() + "\n"; for (int i = causes.size() - 1; i >= 0; i--) { Throwable cause = causes.get(i); for (ExceptionConverter ec : GraniteContext.getCurrentInstance().getGraniteConfig().getExceptionConverters()) { if (ec.accepts(cause, t)) return ec.convert(cause, detail, extendedData); } } if (getLogException()) log.error(t, "Could not process remoting message: %s", request); // Default exception handler ServiceException se = new ServiceException( t.getClass().getSimpleName() + ".Call.Failed", t.getMessage(), detail, t); se.getExtendedData().putAll(extendedData); return se; }
private void dumpBytes(String label, byte[] bytes) { StringBuilder hexSb = new StringBuilder(); StringBuilder charSb = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { int b = bytes[i] & 0xFF; if (hexSb.length() > 0) { hexSb.append(' '); charSb.append(' '); } hexSb.append(HEXS.charAt(b >> 4)).append(HEXS.charAt(b & 0x0F)); if (b >= 0x20 && b <= 0x7e) charSb.append(' ').append((char) b); else charSb.append("##"); } log.info("[RAW %s] {\n%s\n%s\n}", label.toUpperCase(), hexSb.toString(), charSb.toString()); if (dumpDir != null) { File file = new File( dumpDir.getPath() + File.separator + label + "_" + System.currentTimeMillis() + ".amf"); for (int i = 1; i < 100 && file.exists(); i++) file = new File(file.getAbsolutePath() + "." + i); OutputStream os = null; try { os = new FileOutputStream(file); os.write(bytes); } catch (Exception e) { log.error(e, "Could not write dump file: %s", file); } finally { if (os != null) try { os.close(); } catch (Exception e) { } } } }
protected void internalStart() { gravityPool = new GravityPool(gravityConfig); channelsTimer = new Timer(); if (graniteConfig.isRegisterMBeans()) { try { ObjectName name = new ObjectName( "org.graniteds:type=Gravity,context=" + graniteConfig.getMBeanContextName()); log.info("Registering MBean: %s", name); OpenMBean mBean = OpenMBean.createMBean(this); MBeanServerLocator.getInstance().register(mBean, name, true); } catch (Exception e) { log.error( e, "Could not register Gravity MBean for context: %s", graniteConfig.getMBeanContextName()); } } }
private Message handleUnsubscribeMessage( final ChannelFactory<?> channelFactory, CommandMessage message) { Channel channel = getChannel(channelFactory, (String) message.getClientId()); if (channel == null) return handleUnknownClientMessage(message); AsyncMessage reply = null; ServiceAdapter adapter = adapterFactory.getServiceAdapter(message); reply = (AcknowledgeMessage) adapter.manage(channel, message); postManage(channel); if (!(reply instanceof ErrorMessage)) { // Remove subscription message in distributed data (clustering). try { DistributedData gdd = graniteConfig.getDistributedDataFactory().getInstance(); if (gdd != null) { String subscriptionId = (String) message.getHeader(AsyncMessage.DESTINATION_CLIENT_ID_HEADER); log.debug( "Removing subscription message from channel info: %s - %s", channel.getId(), subscriptionId); gdd.removeSubcription(channel.getId(), subscriptionId); } } catch (Exception e) { log.error( e, "Could not remove subscription from distributed data: %s - %s", channel.getId(), message.getHeader(AsyncMessage.DESTINATION_CLIENT_ID_HEADER)); } } reply.setDestination(message.getDestination()); reply.setClientId(channel.getId()); reply.getHeaders().putAll(message.getHeaders()); return reply; }
public boolean runPublish() { LinkedList<AsyncPublishedMessage> publishedCopy = null; publishedQueueLock.lock(); try { if (publishedQueue.isEmpty()) return false; publishedCopy = publishedQueue; publishedQueue = new LinkedList<AsyncPublishedMessage>(); } finally { publishedQueueLock.unlock(); } for (AsyncPublishedMessage message : publishedCopy) { try { message.publish(this); } catch (Exception e) { log.error(e, "Error while trying to publish message: %s", message); } } return true; }
/* * (non-Javadoc) * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig) */ @Override public void init(ServletConfig config) { try { super.init(config); Configuration configuration = Activator.getConfigurationService(); getServletContext() .setAttribute(ServletGraniteConfig.GRANITE_CONFIG_CONFIGURATION_KEY, configuration); graniteConfig = ServletGraniteConfig.loadConfig(getServletContext()); servicesConfig = ServletServicesConfig.loadConfig(getServletContext()); // register EventHandler ServicesConfig handle Add or Remove dataservice Dictionary<String, Object> properties = new Hashtable<String, Object>(); String[] topics = new String[] { OSGIConstants.TOPIC_GDS_ADD_SERVICE, OSGIConstants.TOPIC_GDS_REMOVE_SERVICE }; properties.put(EventConstants.EVENT_TOPIC, topics); context.registerService( EventHandler.class.getName(), new ServiceEventHandler(servicesConfig), properties); } catch (ServletException e) { log.error(e, "Could initialize OSGi service adaptor"); } }
@SuppressWarnings("unchecked") public <C extends Channel> C getChannel(ChannelFactory<C> channelFactory, String clientId) { if (clientId == null) return null; TimeChannel<C> timeChannel = (TimeChannel<C>) channels.get(clientId); if (timeChannel == null) { // Look for existing channel id/subscriptions in distributed data (clustering). log.debug("Lookup channel %s in distributed data", clientId); try { DistributedData gdd = graniteConfig.getDistributedDataFactory().getInstance(); if (gdd != null && gdd.hasChannelId(clientId)) { log.debug("Found channel id in distributed data: %s", clientId); String channelFactoryClassName = gdd.getChannelFactoryClassName(clientId); String clientType = gdd.getChannelClientType(clientId); channelFactory = (ChannelFactory<C>) TypeUtil.newInstance( channelFactoryClassName, new Class<?>[] {Gravity.class}, new Object[] {this}); C channel = channelFactory.newChannel(clientId, clientType); timeChannel = new TimeChannel<C>(channel); if (channels.putIfAbsent(clientId, timeChannel) == null) { for (CommandMessage subscription : gdd.getSubscriptions(clientId)) { log.debug("Resubscribing channel: %s - %s", clientId, subscription); handleSubscribeMessage(channelFactory, subscription, false); } access(clientId); } } } catch (Exception e) { log.error( e, "Could not recreate channel/subscriptions from distributed data: %s", clientId); } } return (timeChannel != null ? timeChannel.getChannel() : null); }
protected <C extends Channel> C createChannel(ChannelFactory<C> channelFactory, String clientId) { C channel = null; if (clientId != null) { channel = getChannel(channelFactory, clientId); if (channel != null) return channel; } String clientType = GraniteContext.getCurrentInstance().getClientType(); channel = channelFactory.newChannel(UUIDUtil.randomUUID(), clientType); TimeChannel<C> timeChannel = new TimeChannel<C>(channel); for (int i = 0; channels.putIfAbsent(channel.getId(), timeChannel) != null; i++) { if (i >= 10) throw new RuntimeException("Could not find random new clientId after 10 iterations"); channel.destroy(false); channel = channelFactory.newChannel(UUIDUtil.randomUUID(), clientType); timeChannel = new TimeChannel<C>(channel); } String channelId = channel.getId(); // Save channel id in distributed data (clustering). try { DistributedData gdd = graniteConfig.getDistributedDataFactory().getInstance(); if (gdd != null) { log.debug("Saving channel id in distributed data: %s", channelId); gdd.addChannelId(channelId, channelFactory.getClass().getName(), clientType); } } catch (Exception e) { log.error(e, "Could not add channel id in distributed data: %s", channelId); } // Initialize timer task. access(channelId); return channel; }
/* (non-Javadoc) * @see org.granite.tide.ejb.EJBServiceContextIntf#findComponent(java.lang.String) */ @Override public Object findComponent(String componentName, Class<?> componentClass) { if ("identity".equals(componentName)) return identity; EjbComponent component = ejbLookupCache.get(componentName); if (component != null) return component.ejbInstance; // Compute EJB JNDI binding. String name = componentName; if (lookup != null) { name = lookup; if (lookup.contains(CAPITALIZED_DESTINATION_ID)) name = lookup.replace(CAPITALIZED_DESTINATION_ID, capitalize(componentName)); if (lookup.contains(DESTINATION_ID)) name = lookup.replace(DESTINATION_ID, componentName); } InitialContext ic = null; try { ic = new InitialContext(); } catch (Exception e) { throw new ServiceException("Could not get InitialContext", e); } log.debug(">> New EjbServiceInvoker looking up: %s", name); try { component = new EjbComponent(); component.ejbInstance = ic.lookup(name); component.ejbClasses = new HashSet<Class<?>>(); Class<?> scannedClass = null; EjbScannedItemHandler itemHandler = EjbScannedItemHandler.instance(); for (Class<?> i : component.ejbInstance.getClass().getInterfaces()) { if (itemHandler.getScannedClasses().containsKey(i)) { scannedClass = itemHandler.getScannedClasses().get(i); break; } } if (scannedClass == null) scannedClass = itemHandler.getScannedClasses().get(component.ejbInstance.getClass()); // GDS-768: handle of proxied no-interface EJBs in GlassFish v3 if (scannedClass == null && component.ejbInstance.getClass().getSuperclass() != null) scannedClass = itemHandler.getScannedClasses().get(component.ejbInstance.getClass().getSuperclass()); if (scannedClass != null) { component.ejbClasses.add(scannedClass); for (Map.Entry<Class<?>, Class<?>> me : itemHandler.getScannedClasses().entrySet()) { if (me.getValue().equals(scannedClass)) component.ejbClasses.add(me.getKey()); } component.ejbMetadata = new EjbServiceMetadata(scannedClass, component.ejbInstance.getClass()); } else log.warn( "Ejb " + componentName + " was not scanned: remove method will not be called if it is a Stateful bean. Add META-INF/services-config.properties if needed."); ejbLookupCache.put(componentName, component); return component.ejbInstance; } catch (NamingException e) { log.error("EJB not found " + name + ": " + e.getMessage()); throw new ServiceException("Could not lookup for: " + name, e); } }
public boolean runReceived(AsyncHttpContext asyncHttpContext) { GravityInternal gravity = getGravity(); if (asyncHttpContext != null && gravity.hasUdpReceiverFactory()) { UdpReceiverFactory factory = gravity.getUdpReceiverFactory(); if (factory.isUdpConnectRequest(asyncHttpContext.getConnectMessage())) { createUdpReceiver(factory, asyncHttpContext); return true; } if (udpReceiver != null) { if (!udpReceiver.isClosed()) udpReceiver.close(false); udpReceiver = null; } } boolean httpAsParam = (asyncHttpContext != null); LinkedList<AsyncMessage> messages = null; OutputStream os = null; try { receivedQueueLock.lock(); try { // Do we have any pending messages? if (receivedQueue.isEmpty()) return false; // Do we have a valid http context? if (asyncHttpContext == null) { asyncHttpContext = acquireAsyncHttpContext(); if (asyncHttpContext == null) return false; } // Both conditions are ok, get all pending messages. messages = receivedQueue; receivedQueue = new LinkedList<AsyncMessage>(); } finally { receivedQueueLock.unlock(); } HttpServletRequest request = asyncHttpContext.getRequest(); HttpServletResponse response = asyncHttpContext.getResponse(); // Set response messages correlation ids to connect request message id. String correlationId = asyncHttpContext.getConnectMessage().getMessageId(); AsyncMessage[] messagesArray = new AsyncMessage[messages.size()]; int i = 0; for (AsyncMessage message : messages) { message.setCorrelationId(correlationId); messagesArray[i++] = message; } // Setup serialization context (thread local) GraniteContext context = HttpGraniteContext.createThreadIntance( gravity.getGraniteConfig(), gravity.getServicesConfig(), null, request, response); ((AMFContextImpl) context.getAMFContext()) .setCurrentAmf3Message(asyncHttpContext.getConnectMessage()); // Write messages to response output stream. GravityServletUtil.serialize( gravity, response, messagesArray, ContentType.forMimeType(request.getContentType())); return true; // Messages were delivered, http context isn't valid anymore. } catch (ServletException e) { log.error(e, "Configuration error for channel: %s", getId()); return true; } catch (IOException e) { log.warn(e, "Could not send messages to channel: %s (retrying later)", getId()); GravityConfig gravityConfig = getGravity().getGravityConfig(); if (gravityConfig.isRetryOnError()) { receivedQueueLock.lock(); try { if (receivedQueue.size() + messages.size() > gravityConfig.getMaxMessagesQueuedPerChannel()) { log.warn( "Channel %s has reached its maximum queue capacity %s (throwing %s messages)", getId(), gravityConfig.getMaxMessagesQueuedPerChannel(), messages.size()); } else receivedQueue.addAll(0, messages); } finally { receivedQueueLock.unlock(); } } return true; // Messages weren't delivered, but http context isn't valid anymore. } finally { // Cleanup serialization context (thread local) try { GraniteContext.release(); } catch (Exception e) { // should never happen... } // Close output stream. try { if (os != null) { try { os.close(); } catch (IOException e) { log.warn(e, "Could not close output stream (ignored)"); } } } finally { // Cleanup http context (only if this method wasn't explicitly called with a non null // AsyncHttpContext from the servlet). if (!httpAsParam) releaseAsyncHttpContext(asyncHttpContext); } } }