IMPALA-3223: Relocate squeasel and mustache directories

This change moves the source and header files of squeasel
and mustache to be/src/thirdparty. This is a step towards
removing thirdparty as a preparation to move to ASF.

There is also corresponding change to Impala-lzo to update
its include path.

Change-Id: I782e493bc28086a1587274b3c474ea6b6f201855
Reviewed-on: http://gerrit.cloudera.org:8080/3206
Reviewed-by: Michael Ho <[email protected]>
Tested-by: Michael Ho <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/incubator-impala/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-impala/commit/0b7ae6e4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-impala/tree/0b7ae6e4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-impala/diff/0b7ae6e4

Branch: refs/heads/master
Commit: 0b7ae6e4eb4e363d6d67ff98f1fe78d7f73a6fce
Parents: a485d44
Author: Michael Ho <[email protected]>
Authored: Wed May 25 18:26:14 2016 -0700
Committer: Tim Armstrong <[email protected]>
Committed: Tue May 31 23:31:41 2016 -0700

----------------------------------------------------------------------
 CMakeLists.txt                         |    8 -
 be/src/thirdparty/mustache/README      |    3 +
 be/src/thirdparty/mustache/mustache.cc |  366 ++
 be/src/thirdparty/mustache/mustache.h  |   27 +
 be/src/thirdparty/squeasel/LICENSE     |   19 +
 be/src/thirdparty/squeasel/squeasel.c  | 4914 +++++++++++++++++++++++++++
 be/src/thirdparty/squeasel/squeasel.h  |  432 +++
 be/src/util/CMakeLists.txt             |    3 +
 be/src/util/webserver.cc               |    8 +-
 be/src/util/webserver.h                |    6 +-
 cmake_modules/FindMustache.cmake       |   26 -
 cmake_modules/FindSqueasel.cmake       |   25 -
 12 files changed, 5771 insertions(+), 66 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0b7ae6e4/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6451371..dc0ec57 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -191,14 +191,6 @@ else()
   set(HDFS_LIB HDFS_STATIC)
 endif()
 
-# find the Squeasel webserver library
-find_package(Squeasel REQUIRED)
-include_directories(${SQUEASEL_INCLUDE_DIR})
-
-# find the Mustache template library
-find_package(Mustache REQUIRED)
-include_directories(${MUSTACHE_INCLUDE_DIR})
-
 # find GLog headers and libs.  Must include glog headers before the other
 # google libraries.  They all have a config.h and we want glog's to be picked
 # up first.

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0b7ae6e4/be/src/thirdparty/mustache/README
----------------------------------------------------------------------
diff --git a/be/src/thirdparty/mustache/README 
b/be/src/thirdparty/mustache/README
new file mode 100644
index 0000000..9834079
--- /dev/null
+++ b/be/src/thirdparty/mustache/README
@@ -0,0 +1,3 @@
+This Mustache template library is taken from the Apache licensed version at 
https://github.com/henryr/cpp-mustache
+
+The current commit is: 80cbe5

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0b7ae6e4/be/src/thirdparty/mustache/mustache.cc
----------------------------------------------------------------------
diff --git a/be/src/thirdparty/mustache/mustache.cc 
b/be/src/thirdparty/mustache/mustache.cc
new file mode 100644
index 0000000..59aeafc
--- /dev/null
+++ b/be/src/thirdparty/mustache/mustache.cc
@@ -0,0 +1,366 @@
+// Licensed 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.
+
+#include "mustache.h"
+
+#include "rapidjson/stringbuffer.h"
+#include "rapidjson/writer.h"
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/foreach.hpp>
+
+using namespace rapidjson;
+using namespace std;
+using namespace boost::algorithm;
+
+namespace mustache {
+
+// TODO:
+// # Handle malformed templates better
+// # Support array_tag.length?
+// # Better support for reading templates from files
+
+enum TagOperator {
+  SUBSTITUTION,
+  SECTION_START,
+  NEGATED_SECTION_START,
+  PREDICATE_SECTION_START,
+  SECTION_END,
+  PARTIAL,
+  COMMENT,
+  LENGTH,
+  NONE
+};
+
+TagOperator GetOperator(const string& tag) {
+  if (tag.size() == 0) return SUBSTITUTION;
+  switch (tag[0]) {
+    case '#': return SECTION_START;
+    case '^': return NEGATED_SECTION_START;
+    case '?': return PREDICATE_SECTION_START;
+    case '/': return SECTION_END;
+    case '>': return PARTIAL;
+    case '!': return COMMENT;
+    case '%': return LENGTH;
+    default: return SUBSTITUTION;
+  }
+}
+
+int EvaluateTag(const string& document, const string& document_root, int idx,
+    const Value* context, TagOperator tag, const string& tag_name, bool 
is_triple,
+    stringstream* out);
+
+void EscapeHtml(const string& in, stringstream *out) {
+  BOOST_FOREACH(const char& c, in) {
+    switch (c) {
+      case '&': (*out) << "&amp;";
+        break;
+      case '"': (*out) << "&quot;";
+        break;
+      case '\'': (*out) << "&apos;";
+        break;
+      case '<': (*out) << "&lt;";
+        break;
+      case '>': (*out) << "&gt;";
+        break;
+      default: (*out) << c;
+        break;
+    }
+  }
+}
+
+// Breaks a dotted path into individual components. One wrinkle, which stops 
this from
+// being a simple split() is that we allow path components to be quoted, e.g.: 
"foo".bar,
+// and any '.' characters inside those quoted sections aren't considered to be
+// delimiters. This is to allow Json keys that contain periods.
+void FindJsonPathComponents(const string& path, vector<string>* components) {
+  bool in_quote = false;
+  bool escape_this_char = false;
+  int start = 0;
+  for (int i = start; i < path.size(); ++i) {
+    if (path[i] == '"' && !escape_this_char) in_quote = !in_quote;
+    if (path[i] == '.' && !escape_this_char && !in_quote) {
+      // Current char == delimiter and not escaped and not in a quote pair => 
found a
+      // component
+      if (i - start > 0) {
+        if (path[start] == '"' && path[(i - 1) - start] == '"') {
+          if (i - start > 3) {
+            components->push_back(path.substr(start + 1, i - (start + 2)));
+          }
+        } else {
+          components->push_back(path.substr(start, i - start));
+        }
+        start = i + 1;
+      }
+    }
+
+    escape_this_char = (path[i] == '\\' && !escape_this_char);
+  }
+
+  if (path.size() - start > 0) {
+    if (path[start] == '"' && path[(path.size() - 1) - start] == '"') {
+      if (path.size() - start > 3) {
+        components->push_back(path.substr(start + 1, path.size() - (start + 
2)));
+      }
+    } else {
+      components->push_back(path.substr(start, path.size() - start));
+    }
+  }
+}
+
+// Looks up the json entity at 'path' in 'parent_context', and places it in 
'resolved'. If
+// the entity does not exist (i.e. the path is invalid), 'resolved' will be 
set to NULL.
+void ResolveJsonContext(const string& path, const Value& parent_context,
+    const Value** resolved) {
+  if (path == ".") {
+    *resolved = &parent_context;
+    return;
+  }
+  vector<string> components;
+  FindJsonPathComponents(path, &components);
+  const Value* cur = &parent_context;
+  BOOST_FOREACH(const string& c, components) {
+    if (cur->IsObject() && cur->HasMember(c.c_str())) {
+      cur = &(*cur)[c.c_str()];
+    } else {
+      *resolved = NULL;
+      return;
+    }
+  }
+
+  *resolved = cur;
+}
+
+int FindNextTag(const string& document, int idx, TagOperator* tag_op, string* 
tag_name,
+    bool* is_triple, stringstream* out) {
+  *tag_op = NONE;
+  while (idx < document.size()) {
+    if (document[idx] == '{' && idx < (document.size() - 3) && document[idx + 
1] == '{') {
+      if (document[idx + 2] == '{') {
+        idx += 3;
+        *is_triple = true;
+      } else {
+        *is_triple = false;
+        idx += 2; // Now at start of template expression
+      }
+      stringstream expr;
+      while (idx < document.size()) {
+        if (document[idx] != '}') {
+          expr << document[idx];
+          ++idx;
+        } else {
+          if (!*is_triple && idx < document.size() - 1 && document[idx + 1] == 
'}') {
+            ++idx;
+            break;
+          } else if (*is_triple && idx < document.size() - 2 && document[idx + 
1] == '}'
+              && document[idx + 2] == '}') {
+            idx += 2;
+            break;
+          } else {
+            expr << '}';
+          }
+        }
+      }
+
+      string key = expr.str();
+      trim(key);
+      if (key != ".") trim_if(key, is_any_of("."));
+      if (key.size() == 0) continue;
+      *tag_op = GetOperator(key);
+      if (*tag_op != SUBSTITUTION) {
+        key = key.substr(1);
+        trim(key);
+      }
+      if (key.size() == 0) continue;
+      *tag_name = key;
+      return ++idx;
+    } else {
+      if (out != NULL) (*out) << document[idx];
+    }
+    ++idx;
+  }
+  return idx;
+}
+
+// Evaluates a [PREDICATE_|NEGATED_]SECTION_START / SECTION_END pair by 
evaluating the tag
+// in 'parent_context'. False or non-existant values cause the entire section 
to be
+// skipped. True values cause the section to be evaluated as though it were a 
normal
+// section, but with the parent context being the root context for that 
section.
+//
+// If 'is_negation' is true, the behaviour is the opposite of the above: false 
values
+// cause the section to be normally evaluated etc.
+int EvaluateSection(const string& document, const string& document_root, int 
idx,
+    const Value* parent_context, TagOperator op, const string& tag_name,
+    stringstream* out) {
+  // Precondition: idx is the immedate next character after an opening {{ 
#tag_name }}
+  const Value* context;
+  ResolveJsonContext(tag_name, *parent_context, &context);
+
+  // If we a) cannot resolve the context from the tag name or b) the context 
evaluates to
+  // false, we should skip the contents of the template until a closing 
{{/tag_name}}.
+  bool skip_contents = (context == NULL || context->IsFalse());
+
+  // If the tag is a negative block (i.e. {{^tag_name}}), do the opposite: if 
the context
+  // exists and is true, skip the contents, else echo them.
+  if (op == NEGATED_SECTION_START) {
+    context = parent_context;
+    skip_contents = !skip_contents;
+  } else if (op == PREDICATE_SECTION_START) {
+    context = parent_context;
+  }
+
+  vector<const Value*> values;
+  if (!skip_contents && context != NULL && context->IsArray()) {
+    for (int i = 0; i < context->Size(); ++i) {
+      values.push_back(&(*context)[i]);
+    }
+  } else {
+    values.push_back(skip_contents ? NULL : context);
+  }
+  if (values.size() == 0) {
+    skip_contents = true;
+    values.push_back(NULL);
+  }
+
+  int start_idx = idx;
+  BOOST_FOREACH(const Value* v, values) {
+    idx = start_idx;
+    while (idx < document.size()) {
+      TagOperator tag_op;
+      string next_tag_name;
+      bool is_triple;
+      idx = FindNextTag(document, idx, &tag_op, &next_tag_name, &is_triple,
+          skip_contents ? NULL : out);
+
+      if (idx > document.size()) return idx;
+      if (tag_op == SECTION_END && next_tag_name == tag_name) {
+        break;
+      }
+
+      // Don't need to evaluate any templates if we're skipping the contents
+      if (!skip_contents) {
+        idx = EvaluateTag(document, document_root, idx, v, tag_op, 
next_tag_name,
+            is_triple, out);
+      }
+    }
+  }
+  return idx;
+}
+
+// Evaluates a SUBSTITUTION tag, by replacing its contents with the value of 
the tag's
+// name in 'parent_context'.
+int EvaluateSubstitution(const string& document, const int idx,
+    const Value* parent_context, const string& tag_name, bool is_triple,
+    stringstream* out) {
+  const Value* context;
+  ResolveJsonContext(tag_name, *parent_context, &context);
+  if (context == NULL) return idx;
+  if (context->IsString()) {
+    if (!is_triple) {
+      EscapeHtml(context->GetString(), out);
+    } else {
+      // TODO: Triple {{{ means don't escape
+      (*out) << context->GetString();
+    }
+  } else if (context->IsInt()) {
+    (*out) << context->GetInt();
+  } else if (context->IsDouble()) {
+    (*out) << context->GetDouble();
+  } else if (context->IsBool()) {
+    (*out) << boolalpha << context->GetBool();
+  }
+  return idx;
+}
+
+// Evaluates a LENGTH tag by replacing its contents with the type-dependent 
'size' of the
+// value.
+int EvaluateLength(const string& document, const int idx, const Value* 
parent_context,
+    const string& tag_name, stringstream* out) {
+  const Value* context;
+  ResolveJsonContext(tag_name, *parent_context, &context);
+  if (context == NULL) return idx;
+  if (context->IsArray()) {
+    (*out) << context->Size();
+  } else if (context->IsString()) {
+    (*out) << context->GetStringLength();
+  };
+
+  return idx;
+}
+
+// Evaluates a 'partial' template by reading it fully from disk, then 
rendering it
+// directly into the current output with the current context.
+//
+// TODO: This could obviously be more efficient (and there are lots of file 
accesses in a
+// long list context).
+void EvaluatePartial(const string& tag_name, const string& document_root,
+    const Value* parent_context, stringstream* out) {
+  stringstream ss;
+  ss << document_root << tag_name;
+  ifstream tmpl(ss.str().c_str());
+  if (!tmpl.is_open()) {
+    ss << ".mustache";
+    tmpl.open(ss.str().c_str());
+    if (!tmpl.is_open()) return;
+  }
+  stringstream file_ss;
+  file_ss << tmpl.rdbuf();
+  RenderTemplate(file_ss.str(), document_root, *parent_context, out);
+}
+
+// Given a tag name, and its operator, evaluate the tag in the given context 
and write the
+// output to 'out'. The heavy-lifting is delegated to specific Evaluate*()
+// methods. Returns the new cursor position within 'document', or -1 on error.
+int EvaluateTag(const string& document, const string& document_root, int idx,
+    const Value* context, TagOperator tag,
+    const string& tag_name, bool is_triple, stringstream* out) {
+  if (idx == -1) return idx;
+  switch (tag) {
+    case SECTION_START:
+    case PREDICATE_SECTION_START:
+    case NEGATED_SECTION_START:
+      return EvaluateSection(document, document_root, idx, context, tag, 
tag_name, out);
+    case SUBSTITUTION:
+      return EvaluateSubstitution(document, idx, context, tag_name, is_triple, 
out);
+    case COMMENT:
+      return idx; // Ignored
+    case PARTIAL:
+      EvaluatePartial(tag_name, document_root, context, out);
+      return idx;
+    case LENGTH:
+      return EvaluateLength(document, idx, context, tag_name, out);
+    case NONE:
+      return idx; // No tag was found
+    default:
+      cout << "Unknown tag: " << tag << endl;
+      return -1;
+  }
+}
+
+void RenderTemplate(const string& document, const string& document_root,
+    const Value& context, stringstream* out) {
+  int idx = 0;
+  while (idx < document.size() && idx != -1) {
+    string tag_name;
+    TagOperator tag_op;
+    bool is_triple;
+    idx = FindNextTag(document, idx, &tag_op, &tag_name, &is_triple, out);
+    idx = EvaluateTag(document, document_root, idx, &context, tag_op, 
tag_name, is_triple,
+        out);
+  }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0b7ae6e4/be/src/thirdparty/mustache/mustache.h
----------------------------------------------------------------------
diff --git a/be/src/thirdparty/mustache/mustache.h 
b/be/src/thirdparty/mustache/mustache.h
new file mode 100644
index 0000000..e4168d3
--- /dev/null
+++ b/be/src/thirdparty/mustache/mustache.h
@@ -0,0 +1,27 @@
+// Licensed 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.
+
+#include "rapidjson/document.h"
+#include <sstream>
+
+// Routines for rendering Mustache (http://mustache.github.io) templates with 
RapidJson
+// (https://code.google.com/p/rapidjson/) documents.
+namespace mustache {
+
+// Render a template contained in 'document' with respect to the json context
+// 'context'. Alternately finds a tag and then evaluates it. Returns when an 
error is
+// signalled (TODO: probably doesn't work in all paths), and evaluates that 
tag. Output is
+// accumulated in 'out'.
+void RenderTemplate(const std::string& document, const std::string& 
document_root,
+    const rapidjson::Value& context, std::stringstream* out);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/0b7ae6e4/be/src/thirdparty/squeasel/LICENSE
----------------------------------------------------------------------
diff --git a/be/src/thirdparty/squeasel/LICENSE 
b/be/src/thirdparty/squeasel/LICENSE
new file mode 100644
index 0000000..edb1983
--- /dev/null
+++ b/be/src/thirdparty/squeasel/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2013 Sergey Lyubka
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

Reply via email to