Fawkes API  Fawkes Development Version
blackboard_processor.cpp
00001 
00002 /***************************************************************************
00003  *  blackboard_processor.cpp - Web request processor for BlackBoard info
00004  *
00005  *  Created: Thu Oct 23 16:10:21 2008
00006  *  Copyright  2006-2008  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  Read the full text in the LICENSE.GPL file in the doc directory.
00021  */
00022 
00023 #include "blackboard_processor.h"
00024 #include <webview/page_reply.h>
00025 
00026 #include <blackboard/blackboard.h>
00027 #include <interface/interface.h>
00028 #include <interface/field_iterator.h>
00029 #include <interface/interface_info.h>
00030 #include <utils/time/time.h>
00031 
00032 #include <string>
00033 #include <cstring>
00034 #include <cstdlib>
00035 
00036 using namespace fawkes;
00037 
00038 /** @class WebviewBlackBoardRequestProcessor "blackboard_processor.h"
00039  * BlackBoard web request processor.
00040  * Provides access to BlackBoard introspection features.
00041  * @author Tim Niemueller
00042  */
00043 
00044 /** Constructor.
00045  * @param baseurl Base URL where processor is mounted
00046  * @param blackboard BlackBoard instance
00047  */
00048 WebviewBlackBoardRequestProcessor::WebviewBlackBoardRequestProcessor(const char *baseurl,
00049                                                              BlackBoard *blackboard)
00050 {
00051   __baseurl     = strdup(baseurl);
00052   __baseurl_len = strlen(__baseurl);
00053   __blackboard  = blackboard;
00054 }
00055 
00056 
00057 /** Destructor. */
00058 WebviewBlackBoardRequestProcessor::~WebviewBlackBoardRequestProcessor()
00059 {
00060   free(__baseurl);
00061   for (__ifi = __interfaces.begin(); __ifi != __interfaces.end(); ++__ifi) {
00062     __blackboard->close(__ifi->second);
00063   }
00064   __interfaces.clear();
00065 }
00066 
00067 
00068 WebReply *
00069 WebviewBlackBoardRequestProcessor::process_request(const char *url,
00070                                                const char *method,
00071                                                const char *version,
00072                                                const char *upload_data,
00073                                                size_t *upload_data_size,
00074                                                void **session_data)
00075 {
00076   if ( strncmp(__baseurl, url, __baseurl_len) == 0 ) {
00077     // It is in our URL prefix range
00078     std::string subpath = std::string(url).substr(__baseurl_len);
00079 
00080     WebPageReply *r = new WebPageReply("BlackBoard");
00081     r->set_html_header("  <link type=\"text/css\" href=\"/static/css/jqtheme/jquery-ui.custom.css\" rel=\"stylesheet\" />\n"
00082                        "  <script type=\"text/javascript\" src=\"/static/js/jquery.min.js\"></script>\n"
00083                        "  <script type=\"text/javascript\" src=\"/static/js/jquery-ui.custom.min.js\"></script>\n");
00084 
00085     *r += "<script type=\"text/javascript\">\n"
00086       "  $(function(){\n"
00087       "    $(\"#blackboard-interfaces-title\").click(function(){\n"
00088       "      if ( $(\"#blackboard-interfaces\").is(\":visible\") ) {\n"
00089       "        $(\"#blackboard-interfaces\").hide(\"blind\");\n"
00090       "        $(\"#blackboard-interfaces-icon\").attr(\"src\", \"/static/images/icon-triangle-e.png\");\n"
00091       "      } else {\n"
00092       "        $(\"#blackboard-interfaces\").show(\"blind\");\n"
00093       "        $(\"#blackboard-interfaces-icon\").attr(\"src\", \"/static/images/icon-triangle-s.png\");\n"
00094       "      }\n"
00095       "    });\n"
00096       "    $(\"#blackboard-interfaces\").hide();\n"
00097       "  });\n"
00098       "</script>\n"
00099       "<div id=\"blackboard-box\">\n"
00100       "  <div><a id=\"blackboard-interfaces-title\" href=\"#\"><img id=\"blackboard-interfaces-icon\" "
00101       "class=\"blackboard-interfaces-icon\" src=\"/static/images/icon-triangle-e.png\" />"
00102       "BlackBoard Interfaces</a></div>\n"
00103       "  <div id=\"blackboard-interfaces\">\n";
00104 
00105     bool found_some = false;
00106     InterfaceInfoList *iil = __blackboard->list_all();
00107     iil->sort();
00108     for (InterfaceInfoList::iterator i = iil->begin(); i != iil->end(); ++i) {
00109       if (! found_some) {
00110         *r += "<table>\n";
00111         *r += "<tr><th>Interface</th><th>Reader(s)</th><th>Writer</th></tr>\n";
00112         found_some = true;
00113       }
00114       r->append_body("<tr><td><a href=\"%s/view/%s::%s\">%s::%s</a></td><td>%u</td><td style=\"color:%s\">%s</td></tr>\n",
00115                      __baseurl, i->type(), i->id(), i->type(), i->id(),
00116                      i->num_readers(), i->has_writer() ? "green" : "red", i->has_writer() ? "yes" : "no");
00117     }
00118     delete iil;
00119 
00120     if (found_some) {
00121       *r += "</table>\n";
00122     } else {
00123       *r += "<b>No interfaces found.</b>\n";
00124     }
00125 
00126     *r += "  </div>\n"
00127       "</div>\n";
00128 
00129     if (subpath.find("/view/") == 0) {
00130       std::string iuid = subpath.substr(subpath.find_first_not_of("/", std::string("/view/").length()));
00131       std::string iftype = iuid.substr(0, iuid.find("::"));
00132       std::string ifname = iuid.substr(iuid.find("::") + 2);
00133 
00134       r->append_body("<h2>Interface: %s</h2>\n", iuid.c_str());
00135       if (__interfaces.find(iuid) == __interfaces.end()) {
00136         try {
00137           Interface *iface = __blackboard->open_for_reading(iftype.c_str(), ifname.c_str());
00138           __interfaces[iuid] = iface;
00139         } catch (Exception &e) {
00140           r->append_body("Failed to open interface: %s\n", e.what());
00141         }
00142       }
00143       if (__interfaces.find(iuid) != __interfaces.end()) {
00144         Interface *iface = __interfaces[iuid];
00145         iface->read();
00146 
00147         /*
00148         *r += "<script type=\"text/javascript\">\n"
00149           "  $(function(){\n"
00150           "    $(\"#blackboard-interface-details-title\").click(function(){\n"
00151           "          if ( $(\"#blackboard-interface-details\").is(\":visible\") ) {\n"
00152           "        $(\"#blackboard-interface-details\").hide(\"blind\");\n"
00153           "        $(\"#blackboard-interfaces-icon\").attr(\"src\", "
00154           "\"/static/images/icon-triangle-e.png\");\n"
00155           "      } else {\n"
00156           "            $(\"#blackboard-interface-details\").show(\"blind\");\n"
00157           "        $(\"#blackboard-interfaces-icon\").attr(\"src\", "
00158           "\"/static/images/icon-triangle-s.png\");\n"
00159           "      }\n"
00160           "    });\n"
00161           "    $(\"#blackboard-interface-details\").hide();\n"
00162           "  });\n"
00163           "</script>\n"
00164           "<div id=\"blackboard-box\">\n"
00165           "  <div><a id=\"blackboard-interface-details-title\" href=\"#\">"
00166           "<img id=\"blackboard-interfaces-icon\" "
00167           "class=\"blackboard-interfaces-icon\" "
00168           "src=\"/static/images/icon-triangle-e.png\" />"
00169           "Interface details</a></div>\n"
00170           "  <div id=\"blackboard-interface-details\">\n";
00171         */
00172 
00173         r->append_body("<table>\n"
00174                        " <tr><td><b>Type:</b></td><td>%s</td></tr>\n"
00175                        " <tr><td><b>ID:</b></td><td>%s</td></tr>\n"
00176                        " <tr><td><b>Has writer?:</b></td><td>%s</td></tr>\n"
00177                        " <tr><td><b>Num readers:</b></td><td>%u</td></tr>\n"
00178                        " <tr><td><b>Serial:</b></td><td>%u</td></tr>\n"
00179                        " <tr><td><b>Data size:</b></td><td>%u</td></tr>\n"
00180                        " <tr><td><b>Hash:</b></td><td>%s</td></tr>\n"
00181                        " <tr><td><b>Data changed:</b></td>"
00182                        "<td>%s (last at %s)</td></tr>\n"
00183                        "</table>\n",
00184                        iface->type(), iface->id(), iface->has_writer() ? "yes" : "no",
00185                        iface->num_readers(), iface->serial(),
00186                        iface->datasize(), iface->hash_printable(),
00187                        iface->changed() ? "yes" : "no", iface->timestamp()->str());
00188 
00189         /*
00190         *r += "  </div>\n"
00191           "</div>\n";
00192         */
00193 
00194         r->append_body("<table>\n"
00195                        " <tr>\n"
00196                        "  <th>Name</th><th>Type</th><th>Value</th>\n"
00197                        " </tr>\n");
00198         for (InterfaceFieldIterator fi = iface->fields(); fi != iface->fields_end(); ++fi) {
00199           bool is_string = (fi.get_type() == IFT_STRING);
00200           *r += " <tr>\n";
00201           if ( fi.get_length() > 1 ) {
00202             r->append_body("  <td>%s</td><td>%s [%zu]</td><td>%s%s%s</td>\n",
00203                            fi.get_name(), fi.get_typename(),
00204                            fi.get_length(), is_string ? "<pre>" : "",
00205                            fi.get_value_string(), is_string ? "</pre>" : "");
00206           } else {
00207             r->append_body("  <td>%s</td><td>%s</td><td>%s%s%s</td>\n",
00208                            fi.get_name(), fi.get_typename(), is_string ? "<pre>" : "",
00209                            fi.get_value_string(), is_string ? "</pre>" : "");
00210           }
00211           *r += " </tr>\n";
00212         }
00213         r->append_body("</table>\n");
00214         r->append_body("<p><a href=\"%s\">Clear detailed</a></p>\n", __baseurl);
00215       }
00216     }
00217 
00218 
00219     return r;
00220   } else {
00221     return NULL;
00222   }
00223 }