activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dej...@apache.org
Subject svn commit: r1499777 [1/2] - in /activemq/trunk: activemq-http/ activemq-http/src/main/java/org/apache/activemq/transport/ws/ activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/ activemq-web-demo/src/main/webapp/mqtt/ activemq-web-demo/src/...
Date Thu, 04 Jul 2013 14:54:29 GMT
Author: dejanb
Date: Thu Jul  4 14:54:29 2013
New Revision: 1499777

URL: http://svn.apache.org/r1499777
Log:
https://issues.apache.org/jira/browse/AMQ-4617 - mqtt over ws protocol

Added:
    activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/MQTTSocket.java
    activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/WSServlet.java
      - copied, changed from r1498875, activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/StompServlet.java
    activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/
    activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/chat.css
    activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/chat.js
      - copied, changed from r1498875, activemq/trunk/activemq-web-demo/src/main/webapp/websocket/chat.js
    activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/index.html
    activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/mqttws31.js
Removed:
    activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/StompServlet.java
Modified:
    activemq/trunk/activemq-http/pom.xml
    activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/WSTransportServer.java
    activemq/trunk/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTProtocolConverter.java
    activemq/trunk/activemq-web-demo/src/main/webapp/websocket/chat.js

Modified: activemq/trunk/activemq-http/pom.xml
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-http/pom.xml?rev=1499777&r1=1499776&r2=1499777&view=diff
==============================================================================
--- activemq/trunk/activemq-http/pom.xml (original)
+++ activemq/trunk/activemq-http/pom.xml Thu Jul  4 14:54:29 2013
@@ -40,6 +40,10 @@
       <artifactId>activemq-stomp</artifactId>
     </dependency>
     <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>activemq-mqtt</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>

Added: activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/MQTTSocket.java
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/MQTTSocket.java?rev=1499777&view=auto
==============================================================================
--- activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/MQTTSocket.java
(added)
+++ activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/MQTTSocket.java
Thu Jul  4 14:54:29 2013
@@ -0,0 +1,135 @@
+/**
+ * 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.activemq.transport.ws;
+
+import org.apache.activemq.command.Command;
+import org.apache.activemq.transport.TransportSupport;
+import org.apache.activemq.transport.mqtt.MQTTInactivityMonitor;
+import org.apache.activemq.transport.mqtt.MQTTProtocolConverter;
+import org.apache.activemq.transport.mqtt.MQTTTransport;
+import org.apache.activemq.transport.mqtt.MQTTWireFormat;
+import org.apache.activemq.util.ByteSequence;
+import org.apache.activemq.util.IOExceptionSupport;
+import org.apache.activemq.util.ServiceStopper;
+import org.eclipse.jetty.websocket.WebSocket;
+import org.fusesource.mqtt.codec.DISCONNECT;
+import org.fusesource.mqtt.codec.MQTTFrame;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.CountDownLatch;
+
+public class MQTTSocket  extends TransportSupport implements WebSocket.OnBinaryMessage, MQTTTransport
{
+
+    private static final Logger LOG = LoggerFactory.getLogger(MQTTSocket.class);
+    Connection outbound;
+    MQTTProtocolConverter protocolConverter = new MQTTProtocolConverter(this, null);
+    MQTTWireFormat wireFormat = new MQTTWireFormat();
+    private final CountDownLatch socketTransportStarted = new CountDownLatch(1);
+
+    @Override
+    public void onMessage(byte[] bytes, int offset, int length) {
+        if (!transportStartedAtLeastOnce()) {
+            LOG.debug("Waiting for StompSocket to be properly started...");
+            try {
+                socketTransportStarted.await();
+            } catch (InterruptedException e) {
+                LOG.warn("While waiting for StompSocket to be properly started, we got interrupted!!
Should be okay, but you could see race conditions...");
+            }
+        }
+
+        try {
+            MQTTFrame frame = (MQTTFrame)wireFormat.unmarshal(new ByteSequence(bytes, offset,
length));
+            protocolConverter.onMQTTCommand(frame);
+        } catch (Exception e) {
+            onException(IOExceptionSupport.create(e));
+        }
+    }
+
+    @Override
+    public void onOpen(Connection connection) {
+        this.outbound = connection;
+    }
+
+    @Override
+    public void onClose(int closeCode, String message) {
+        try {
+            protocolConverter.onMQTTCommand(new DISCONNECT().encode());
+        } catch (Exception e) {
+            LOG.warn("Failed to close WebSocket", e);
+        }
+    }
+
+    protected void doStart() throws Exception {
+        socketTransportStarted.countDown();
+    }
+
+    @Override
+    protected void doStop(ServiceStopper stopper) throws Exception {
+    }
+
+    private boolean transportStartedAtLeastOnce() {
+        return socketTransportStarted.getCount() == 0;
+    }
+
+    @Override
+    public int getReceiveCounter() {
+        return 0;
+    }
+
+    @Override
+    public String getRemoteAddress() {
+        return "MQTTSocket_" + this.hashCode();
+    }
+
+    @Override
+    public void oneway(Object command) throws IOException {
+        try {
+            protocolConverter.onActiveMQCommand((Command)command);
+        } catch (Exception e) {
+            onException(IOExceptionSupport.create(e));
+        }
+    }
+
+    @Override
+    public void sendToActiveMQ(Command command) {
+        doConsume(command);
+    }
+
+    @Override
+    public void sendToMQTT(MQTTFrame command) throws IOException {
+        ByteSequence bytes = wireFormat.marshal(command);
+        outbound.sendMessage(bytes.getData(), 0, bytes.getLength());
+    }
+
+    @Override
+    public X509Certificate[] getPeerCertificates() {
+        return new X509Certificate[0];
+    }
+
+    @Override
+    public MQTTInactivityMonitor getInactivityMonitor() {
+        return null;
+    }
+
+    @Override
+    public MQTTWireFormat getWireFormat() {
+        return wireFormat;
+    }
+}

Copied: activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/WSServlet.java
(from r1498875, activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/StompServlet.java)
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/WSServlet.java?p2=activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/WSServlet.java&p1=activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/StompServlet.java&r1=1498875&r2=1499777&rev=1499777&view=diff
==============================================================================
--- activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/StompServlet.java
(original)
+++ activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/WSServlet.java
Thu Jul  4 14:54:29 2013
@@ -22,6 +22,7 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.activemq.transport.Transport;
 import org.apache.activemq.transport.TransportAcceptListener;
 import org.eclipse.jetty.websocket.WebSocket;
 import org.eclipse.jetty.websocket.WebSocketServlet;
@@ -29,7 +30,7 @@ import org.eclipse.jetty.websocket.WebSo
 /**
  * Handle connection upgrade requests and creates web sockets
  */
-public class StompServlet extends WebSocketServlet {
+public class WSServlet extends WebSocketServlet {
     private static final long serialVersionUID = -4716657876092884139L;
 
     private TransportAcceptListener listener;
@@ -49,8 +50,13 @@ public class StompServlet extends WebSoc
 
     @Override
     public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
-        StompSocket socket = new StompSocket();
-        listener.onAccept(socket);
+        WebSocket socket;
+        if (protocol.startsWith("mqtt")) {
+            socket = new MQTTSocket();
+        } else {
+            socket = new StompSocket();
+        }
+        listener.onAccept((Transport)socket);
         return socket;
     }
 }

Modified: activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/WSTransportServer.java
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/WSTransportServer.java?rev=1499777&r1=1499776&r2=1499777&view=diff
==============================================================================
--- activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/WSTransportServer.java
(original)
+++ activemq/trunk/activemq-http/src/main/java/org/apache/activemq/transport/ws/WSTransportServer.java
Thu Jul  4 14:54:29 2013
@@ -65,7 +65,7 @@ public class WSTransportServer extends W
             }
         }
 
-        holder.setServlet(new StompServlet());
+        holder.setServlet(new WSServlet());
         contextHandler.addServlet(holder, "/");
 
         contextHandler.setAttribute("acceptListener", getAcceptListener());

Modified: activemq/trunk/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTProtocolConverter.java
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTProtocolConverter.java?rev=1499777&r1=1499776&r2=1499777&view=diff
==============================================================================
--- activemq/trunk/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTProtocolConverter.java
(original)
+++ activemq/trunk/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTProtocolConverter.java
Thu Jul  4 14:54:29 2013
@@ -79,7 +79,7 @@ import org.fusesource.mqtt.codec.UNSUBSC
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-class MQTTProtocolConverter {
+public class MQTTProtocolConverter {
 
     private static final Logger LOG = LoggerFactory.getLogger(MQTTProtocolConverter.class);
 

Added: activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/chat.css
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/chat.css?rev=1499777&view=auto
==============================================================================
--- activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/chat.css (added)
+++ activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/chat.css Thu Jul  4 14:54:29 2013
@@ -0,0 +1,112 @@
+/**
+ * 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.
+ */
+* {
+  margin: 0;
+  padding: 0;
+}
+
+body {
+  font-family: 'Helvetica Neue', Helvetica, Verdana, Arial, sans-serif;
+  padding: 10px;
+}
+
+#disconnect {
+  display: none;
+}
+#subscribe {
+  display: none;
+}
+
+#debug {
+  background-color: #F0F0F0;
+  font-size: 12px;
+  width: 800px;
+  margin-left: 0px;
+  margin-top: 10px;
+  margin-right: 0px;
+  padding: 10px;
+  border: 1px solid #CCC;
+}
+
+#send_form {
+  width: 800px;
+  bottom: 10px;
+}
+
+#send_form #send_form_input {
+  border: 1px solid #CCC;
+  font-size: 16px;
+  height: 20px;
+  padding: 10px;
+  width: 800px;
+}
+
+#send_form input[disabled] {
+  background-color: #EEE;
+}
+
+#messages {
+  bottom: 25px;
+  left: 0;
+  overflow: auto;
+  padding: 5px;
+  right: 0;
+  top: 2em;
+  z-index: -1;
+}
+
+.message {
+  width: 95%;
+}
+
+.timestamp {
+  font-size: 12px;
+}
+
+.me, .nick {
+  float: left;
+  width: 100px;
+}
+
+.me {
+  color: #F99;
+}
+
+.nick {
+  color: #99F;
+}
+
+.status {
+  background-color: #DDD;
+}
+
+form dt {
+   clear:both;
+   width:19%;
+   float:left;
+   text-align:right;
+}
+
+form dd {
+   float:left;
+   width:80%;
+   margin:0 0 0.5em 0.25em;
+}
+
+input {
+   width: 320px;
+}
\ No newline at end of file

Copied: activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/chat.js (from r1498875, activemq/trunk/activemq-web-demo/src/main/webapp/websocket/chat.js)
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/chat.js?p2=activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/chat.js&p1=activemq/trunk/activemq-web-demo/src/main/webapp/websocket/chat.js&r1=1498875&r2=1499777&rev=1499777&view=diff
==============================================================================
--- activemq/trunk/activemq-web-demo/src/main/webapp/websocket/chat.js (original)
+++ activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/chat.js Thu Jul  4 14:54:29 2013
@@ -16,53 +16,76 @@
  * limitations under the License.
  */
 $(document).ready(function(){
-
   var client, destination;
 
   $('#connect_form').submit(function() {
-    var url = $("#connect_url").val();
-    var login = $("#connect_login").val();
-    var passcode = $("#connect_passcode").val();
+    
+    var host = $("#connect_host").val();    
+    var port = $("#connect_port").val();
+    var clientId = $("#connect_clientId").val();
     destination = $("#destination").val();
 
-    client = Stomp.client(url);
+    
+    client = new Messaging.Client(host, Number(port), clientId);
+
+    client.onConnect = onConnect;
+  
+    client.onMessageArrived = onMessageArrived;
+    client.onConnectionLost = onConnectionLost;            
+
+    client.connect({onSuccess:onConnect, onFailure:onFailure}); 
+    return false;
+  });  
 
-    // this allows to display debug logs directly on the web page
-    client.debug = function(str) {
-      $("#debug").append(document.createTextNode(str + "\n"));
-    };
     // the client is notified when it is connected to the server.
-    var onconnect = function(frame) {
-      client.debug("connected to Stomp");
+    var onConnect = function(frame) {
+      debug("connected to MQTT");
       $('#connect').fadeOut({ duration: 'fast' });
       $('#disconnect').fadeIn();
       $('#send_form_input').removeAttr('disabled');
+      client.subscribe(destination);
+    };  
 
-      client.subscribe(destination, function(message) {
-        $("#messages").append(document.createTextNode("<p>" + message.body + "</p>\n"));
-      });
-    };
-    client.connect(login, passcode, onconnect);
-
-    return false;
-  });
+    // this allows to display debug logs directly on the web page
+    var debug = function(str) {
+      $("#debug").append(document.createTextNode(str + "\n"));
+    };  
 
   $('#disconnect_form').submit(function() {
-    client.disconnect(function() {
-      $('#disconnect').fadeOut({ duration: 'fast' });
-      $('#connect').fadeIn();
-      $('#send_form_input').addAttr('disabled');
-    });
+    client.disconnect();
+    $('#disconnect').fadeOut({ duration: 'fast' });
+    $('#connect').fadeIn();
+    $('#send_form_input').addAttr('disabled');
     return false;
   });
 
   $('#send_form').submit(function() {
     var text = $('#send_form_input').val();
     if (text) {
-      client.send(destination, {foo: 1}, text);
+      message = new Messaging.Message(text);
+      message.destinationName = destination;
+      client.send(message);
       $('#send_form_input').val("");
     }
     return false;
   });
 
+  function onFailure(failure) {
+    debug("failure");
+    debug(failure.errorMessage);
+  }  
+
+  function onMessageArrived(message) {
+    var p = document.createElement("p");
+    var t = document.createTextNode(message.payloadString);
+    p.appendChild(t);
+    $("#messages").append(p);
+  }
+
+  function onConnectionLost(responseObject) {
+    if (responseObject.errorCode !== 0) {
+      debug(client.clientId + ": " + responseObject.errorCode + "\n");
+    }
+  }
+
 });
\ No newline at end of file

Added: activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/index.html
URL: http://svn.apache.org/viewvc/activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/index.html?rev=1499777&view=auto
==============================================================================
--- activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/index.html (added)
+++ activemq/trunk/activemq-web-demo/src/main/webapp/mqtt/index.html Thu Jul  4 14:54:29 2013
@@ -0,0 +1,174 @@
+<!--
+  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.
+-->
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+    <link rel="stylesheet" href="chat.css" type="text/css">
+    <style type="text/css" media="screen">
+        @import url(../styles/sorttable.css);
+        @import url(../styles/type-settings.css);
+        @import url(../styles/site.css);
+        @import url(../styles/prettify.css);
+    </style>
+    <title>Chat Example Using Stomp Over WebSocket</title>
+    <link rel="stylesheet" type="text/css" href="chat.css"></link>
+    <script type="text/javascript" src="../js/jquery-1.4.2.min.js"></script>
+    <script src='mqttws31.js'></script>
+    <script src='chat.js'></script>
+    <script>
+        $(document).ready(function() {
+        var supported = ("WebSocket" in window);
+        if(!supported) {
+        var msg = "Your browser does not support Web Sockets. This example will not work
properly.<br>";
+        msg += "Please use a Web Browser with Web Sockets support (WebKit or Google Chrome).";
+        $("#connect").html(msg);
+        }
+        });
+    </script>
+</head>
+<body>
+
+<div class="white_box">
+    <div class="header">
+        <div class="header_l">
+            <div class="header_r">
+            </div>
+        </div>
+    </div>
+    <div class="content">
+        <div class="content_l">
+            <div class="content_r">
+
+                <div>
+
+                    <!-- Banner -->
+                    <div id="asf_logo">
+                        <div id="activemq_logo">
+                            <a style="float:left; width:280px;display:block;text-indent:-5000px;text-decoration:none;line-height:60px;
margin-top:10px; margin-left:100px;"
+                               href="http://activemq.apache.org/"
+                               title="The most popular and powerful open source Message Broker">ActiveMQ</a>
+                            <a style="float:right; width:210px;display:block;text-indent:-5000px;text-decoration:none;line-height:60px;
margin-top:15px; margin-right:10px;"
+                               href="http://www.apache.org/" title="The Apache Software Foundation">ASF</a>
+                        </div>
+                    </div>
+
+
+                    <div class="top_red_bar">
+                        <div id="site-breadcrumbs">
+                            <a href="../index.html" title="Home">Home</a>
+                        </div>
+                        <div id="site-quicklinks"><P>
+                            <a href="http://activemq.apache.org/support.html"
+                               title="Get help and support using Apache ActiveMQ">Support</a></p>
+                        </div>
+                    </div>
+
+                    <table border="0">
+                        <tbody>
+                        <tr>
+                            <td valign="top" width="100%" style="overflow:hidden;">
+                                <div class="body-content">
+
+<div id='connect'>
+    <form id='connect_form'>
+        <dl>
+            <dt><label for=connect_url>Server Host</label></dt>
+            <dd><input name=url id='connect_host' value='localhost'></dd>
+            <dt><label for=connect_port>Server Port</label></dt>
+            <dd><input id='connect_port' placeholder="Server Port" value="61614"></dd>
+            <dt><label for=connect_clientId>Client ID</label></dt>
+            <dd><input id='connect_clientId' placeholder="Client ID" value="clientId"></dd>
+            <dt><label for=destination>Destination</label></dt>
+            <dd><input id='destination' placeholder="Destination" value="/test"></dd>
+            <dt>&nbsp;</dt>
+            <dd><input type=submit id='connect_submit' value="Connect"></dd>
+        </dl>
+    </form>
+
+    <p><b>Make sure you have enabled <a href="http://activemq.apache.org/websockets.html">websockets
transport</a> before running this demo</b></p>
+    <p>This is adapted <a href="https://github.com/jmesnil/stomp-websocket">stomp-websocket</a>
library demo</p>
+    <p>Use the form above to connect to the Stomp server and subscribe to the destination.</p>
+    <p>Once connected, you can send messages to the destination with the text field
at the bottom of this page</p>
+
+
+</div>
+<div id="disconnect">
+    <form id='disconnect_form'>
+        <input type=submit id='disconnect_submit' value="Disconnect">
+    </form>
+</div>
+<div id="messages">
+</div>
+
+<form id='send_form'>
+    <input id='send_form_input' placeholder="Type your message here" disabled />
+</form>
+
+<pre id="debug"></pre>
+
+                                </div>
+                            </td>
+                            <td valign="top">
+
+                                <div class="navigation">
+                                    <div class="navigation_top">
+                                        <div class="navigation_bottom">
+                                            <H3>Useful Links</H3>
+
+                                            <ul class="alternate" type="square">
+                                                <li><a href="http://activemq.apache.org/"
+                                                       title="The most popular and powerful
open source Message Broker">Documentation</a></li>
+                                                <li><a href="http://activemq.apache.org/faq.html">FAQ</a></li>
+                                                <li><a href="http://activemq.apache.org/download.html">Downloads</a>
+                                                </li>
+                                                <li><a href="http://activemq.apache.org/discussion-forums.html">Forums</a>
+                                                </li>
+                                            </ul>
+                                        </div>
+                                    </div>
+                                </div>
+                            </td>
+                        </tr>
+                        </tbody>
+                    </table>
+
+
+                    <div class="bottom_red_bar"></div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="black_box">
+        <div class="footer">
+            <div class="footer_l">
+                <div class="footer_r">
+                    <div>
+                        Copyright 2005-2012 The Apache Software Foundation.
+
+                        (<a href="?printable=true">printable version</a>)
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<div class="design_attribution"><a href="http://hiramchirino.com/">Graphic Design
By Hiram</a></div>
+
+</body>
+</html>
\ No newline at end of file



Mime
View raw message