| /* |
| * 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 org.apache.felix.http.samples.cometd; |
| |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.text.SimpleDateFormat; |
| import java.util.ArrayList; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Timer; |
| import java.util.TimerTask; |
| |
| import javax.servlet.ServletConfig; |
| import javax.servlet.ServletException; |
| import javax.servlet.http.HttpServlet; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.cometd.bayeux.MarkedReference; |
| import org.cometd.bayeux.server.BayeuxServer; |
| import org.cometd.bayeux.server.ConfigurableServerChannel; |
| import org.cometd.bayeux.server.LocalSession; |
| import org.cometd.bayeux.server.ServerChannel; |
| import org.cometd.bayeux.server.ServerMessage; |
| |
| public class TimeServlet |
| extends HttpServlet |
| { |
| private static final long serialVersionUID = 1L; |
| |
| private enum SystemTopics { |
| Time |
| }; |
| |
| private BayeuxServer bayeuxServer; |
| private LocalSession session; |
| private List<ServerChannel> channels; |
| private Timer updateTimer; |
| private SimpleDateFormat logDateFormat; |
| private String html = |
| "<html>\n" + |
| " <head>\n" + |
| " <title>System Information</title>\n" + |
| " <script type='text/javascript' src='/js/dojo/dojo.js'></script>\n" + |
| " <script type='text/javascript'>\n" + |
| " dojo.require('dojox.cometd');\n" + |
| "dojo.addOnLoad(function()\n" + |
| "{\n" + |
| " var cometd = dojox.cometd;\n" + |
| "\n" + |
| " function _connectionEstablished()\n" + |
| " {\n" + |
| " dojo.byId('body').innerHTML += '<div>CometD Connection Established</div>';\n" + |
| " }\n" + |
| "\n" + |
| " function _connectionBroken()\n" + |
| " {\n" + |
| " dojo.byId('body').innerHTML += '<div>CometD Connection Broken</div>';\n" + |
| " }\n" + |
| "\n" + |
| " function _connectionClosed()\n" + |
| " {\n" + |
| " dojo.byId('body').innerHTML += '<div>CometD Connection Closed</div>';\n" + |
| " }\n" + |
| "\n" + |
| " // Function that manages the connection status with the Bayeux server\n" + |
| " var _connected = false;\n" + |
| " function _metaConnect(message)\n" + |
| " {\n" + |
| " if (cometd.isDisconnected())\n" + |
| " {\n" + |
| " _connected = false;\n" + |
| " _connectionClosed();\n" + |
| " return;\n" + |
| " }\n" + |
| "\n" + |
| " var wasConnected = _connected;\n" + |
| " _connected = message.successful === true;\n" + |
| " if (!wasConnected && _connected)\n" + |
| " {\n" + |
| " _connectionEstablished();\n" + |
| " }\n" + |
| " else if (wasConnected && !_connected)\n" + |
| " {\n" + |
| " _connectionBroken();\n" + |
| " }\n" + |
| " }\n" + |
| "\n" + |
| " // Function invoked when first contacting the server and\n" + |
| " // when the server has lost the state of this client\n" + |
| " function _metaHandshake(handshake)\n" + |
| " {\n" + |
| " if (handshake.successful === true)\n" + |
| " {\n" + |
| " cometd.batch(function()\n" + |
| " {\n" + |
| " cometd.subscribe('/System/Time', function(message)\n" + |
| " {\n" + |
| " dojo.byId('systemTime').innerHTML = '<div>' + message.data + '</div>';\n" + |
| " });\n" + |
| " });\n" + |
| " }\n" + |
| " }\n" + |
| "\n" + |
| " // Disconnect when the page unloads\n" + |
| " dojo.addOnUnload(function()\n" + |
| " {\n" + |
| " cometd.disconnect(true);\n" + |
| " });\n" + |
| "\n" + |
| " var cometURL = \"http://localhost:8080/system/cometd\";\n" + |
| " cometd.configure({\n" + |
| " url: cometURL,\n" + |
| " logLevel: 'debug'\n" + |
| " });\n" + |
| "\n" + |
| " cometd.addListener('/meta/handshake', _metaHandshake);\n" + |
| " cometd.addListener('/meta/connect', _metaConnect);\n" + |
| "\n" + |
| " cometd.handshake();\n" + |
| "});\n" + |
| " </script>\n" + |
| " </head>\n" + |
| " <body>\n" + |
| " <h2 id='systemTime'></h2>\n" + |
| " </body>\n" + |
| "</html>\n"; |
| |
| public TimeServlet(BayeuxServer bayeuxServer) |
| { |
| this.bayeuxServer = bayeuxServer; |
| this.channels = new ArrayList<ServerChannel>(); |
| for (SystemTopics topic : SystemTopics.values()) { |
| MarkedReference<ServerChannel> created = bayeuxServer.createChannelIfAbsent("/System/" + topic, new ConfigurableServerChannel.Initializer() { |
| @Override |
| public void configureChannel(ConfigurableServerChannel channel) { |
| channel.setPersistent(true); |
| } |
| }); |
| this.channels.add(topic.ordinal(), created.getReference()); |
| } |
| this.logDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); |
| this.updateTimer = new Timer("System.Time.ClientNotifier"); |
| this.updateTimer.scheduleAtFixedRate(new ClientNotifier(), 1000, 1000); |
| this.session = bayeuxServer.newLocalSession(TimeServlet.class.getName()); |
| this.session.handshake(); |
| } |
| |
| @Override |
| public void init(ServletConfig config) |
| throws ServletException |
| { |
| doLog("Init with config [" + config + "]"); |
| super.init(config); |
| } |
| |
| @Override |
| public void destroy() |
| { |
| doLog("Destroyed servlet"); |
| this.updateTimer.cancel(); |
| this.session.disconnect(); |
| super.destroy(); |
| } |
| |
| @Override |
| protected void doGet(HttpServletRequest req, HttpServletResponse res) |
| throws ServletException, IOException |
| { |
| res.setContentType("text/html"); |
| PrintWriter out = res.getWriter(); |
| out.println(this.html); |
| } |
| |
| private void doLog(String message) |
| { |
| System.out.println("## TimeServlet: " + message); |
| } |
| |
| private class ClientNotifier |
| extends TimerTask |
| { |
| |
| @Override |
| public void run() { |
| for (SystemTopics topic : SystemTopics.values()) { |
| String topicData; |
| switch (topic) { |
| case Time: |
| topicData = logDateFormat.format(new Date()); |
| break; |
| default: |
| topicData = "unknown topic: " + topic.toString(); |
| } |
| ServerMessage.Mutable message = bayeuxServer.newMessage(); |
| message.setChannel(channels.get(topic.ordinal()).getId()); |
| message.setData(topicData); |
| channels.get(topic.ordinal()).publish(session, message); |
| } |
| } |
| } |
| |
| } |