You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by an...@apache.org on 2015/07/22 13:00:31 UTC

[03/10] incubator-ignite git commit: # ignite-843 moved

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/public/stylesheets/style.less
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/public/stylesheets/style.less b/modules/web-control-center/src/main/js/public/stylesheets/style.less
new file mode 100644
index 0000000..4900581
--- /dev/null
+++ b/modules/web-control-center/src/main/js/public/stylesheets/style.less
@@ -0,0 +1,1172 @@
+/*
+ * 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.
+ */
+
+@logo-path: "https://www.filepicker.io/api/file/QagunjDGRFul2JgNCAli";
+@input-height: 28px;
+@ignite-red: #ec1c24;
+@ignite-block-callout-background: #f3f8f3;
+@ignite-block-callout: #50af51;
+
+hr {
+  margin-top: 20px;
+  margin-bottom: 20px;
+}
+
+.main-header .logo {
+  height: auto;
+}
+
+.main-sidebar {
+  padding-top: 60px;
+}
+
+.navbar-default .navbar-brand, .navbar-default .navbar-brand:hover {
+  position: absolute;
+  width: 100%;
+  left: 0;
+  text-align: center;
+}
+
+.modal-backdrop.am-fade {
+  opacity: .5;
+  transition: opacity .15s linear;
+  &.ng-enter {
+    opacity: 0;
+    &.ng-enter-active {
+      opacity: .5;
+    }
+  }
+  &.ng-leave {
+    opacity: .5;
+    &.ng-leave-active {
+      opacity: 0;
+    }
+  }
+}
+
+.modal.center .modal-dialog {
+  position: fixed;
+  top: 50%;
+  left: 50%;
+  -webkit-transform: translateX(-50%) translateY(-50%);
+  transform: translateX(-50%) translateY(-50%);
+}
+
+.border-left {
+  box-shadow: 1px 0 0 0 #eee inset;
+}
+
+.border-right {
+  box-shadow: 1px 0 0 0 #eee;
+}
+
+.theme-line {
+  background-color: #f9f9f9;
+}
+
+.theme-line header {
+  background-color: #fff;
+}
+
+.theme-line header a.btn {
+  border: 0 none;
+  padding: 10px 25px;
+  background-color: rgba(0, 0, 0, 0.15);
+}
+
+.theme-line header a.btn:hover {
+  background-color: rgba(0, 0, 0, 0.25);
+}
+
+.theme-line header a.btn.btn-link {
+  background: transparent;
+  color: rgba(255, 255, 255, 0.8);
+}
+
+.theme-line header a.btn.btn-link:hover {
+  color: #fff;
+  text-decoration: none;
+}
+
+.theme-line .navbar-nav a {
+  background-color: transparent;
+}
+
+.theme-line .navbar-nav a:hover,
+.theme-line .navbar-nav a:active,
+.theme-line .navbar-nav a:focus {
+  background-color: transparent;
+}
+
+.theme-line .main-links {
+  padding-top: 50px;
+}
+
+.theme-line .main-links h3 {
+  margin-top: 0;
+  font-size: 17px;
+}
+
+.theme-line .main-links .links a {
+  color: #888;
+}
+
+.theme-line .main-links .links a:hover {
+  text-decoration: none;
+}
+
+.theme-line #category-columns,
+.theme-solid #category-columns {
+  margin: 50px 30px 0;
+}
+
+.theme-line #category-columns h4 {
+  text-transform: uppercase;
+  font-weight: 300;
+  color: #999;
+  font-size: 14px;
+}
+
+.theme-line #category-columns ul {
+  list-style: none;
+  padding: 0;
+  margin-bottom: 15px;
+}
+
+.theme-line #category-columns ul li a {
+  padding: 5px 0;
+  display: block;
+  font-size: 16px;
+}
+
+.theme-line #category-columns ul .view-all {
+  font-size: 0.85em;
+}
+
+.theme-line .docs-header {
+  color: #999;
+  overflow: hidden;
+}
+
+.theme-line .docs-header h1 {
+  color: #444;
+  margin-top: 0;
+  font-size: 22px;
+}
+
+.theme-line .btn-primary {
+  border: 0 none;
+  background-color: @ignite-red;
+}
+
+.theme-line .btn-primary:hover {
+  background-color: #950d12;
+}
+
+.theme-line .main-content .nav-horizontal a {
+  box-shadow: 0 0;
+  border: 0 none;
+  background-color: #fff;
+  border-radius: 0;
+  color: #aaa;
+  padding: 6px;
+  margin: 0 14px;
+}
+
+.theme-line .main-content .nav-horizontal a:hover {
+  color: #999;
+  border-bottom: 5px solid #ddd;
+}
+
+.theme-line .main-content .nav-horizontal a.active {
+  border-bottom: 5px solid #888;
+}
+
+.theme-line .navbar-nav, .theme-line .sidebar-nav {
+  ul li > a.active {
+    cursor: default;
+    pointer-events: none;
+  }
+}
+
+.theme-line .sidebar-nav {
+  color: #474a54;
+  padding-bottom: 30px;
+
+  ul {
+    padding: 0;
+    list-style: none;
+    font-size: 14px;
+    margin: 3px 0 0;
+    li {
+      color: #666;
+      line-height: @input-height;
+
+      span.fa-stack {
+        margin-right: 5px;
+        font-size: 12px;
+        height: 26px;
+      }
+
+      a {
+        font-size: 18px;
+        color: #666;
+        position: relative;
+        white-space: nowrap;
+        overflow: hidden;
+        -o-text-overflow: ellipsis;
+        text-overflow: ellipsis;
+      }
+    }
+  }
+}
+
+.theme-line .sidebar-nav ul li a:hover {
+  text-decoration: none;
+}
+
+.theme-line .select,
+.theme-line .typeahead {
+  li a {
+    color: #666;
+    background-color: transparent;
+  }
+
+  li a:hover {
+    color: @ignite-red;
+  }
+
+  .active {
+    background-color: #eee;
+  }
+}
+
+.theme-line .sidebar-nav ul li .subcategory {
+  padding-left: 15px;
+}
+
+.theme-line .sidebar-nav h4 {
+  margin-top: 2em;
+  font-weight: normal;
+  text-transform: uppercase;
+  font-size: 11px;
+  margin-bottom: 10px;
+  color: #bbb;
+}
+
+.theme-line .sidebar-nav h4:first-child {
+  margin-top: 0;
+}
+
+.theme-line .sidebar-nav .ask {
+  width: 100%;
+  text-align: center;
+  padding: 10px;
+}
+
+.theme-line .border-left .sidebar-nav {
+  padding-left: 15px;
+}
+
+.theme-line .suggest {
+  padding: 5px;
+  display: inline-block;
+  font-size: 12px;
+}
+
+.header {
+  padding: 15px;
+}
+
+.header .has-github {
+  padding-right: 136px;
+}
+
+.header h1.navbar-brand {
+  height: 40px;
+  width: 200px;
+  padding: 0;
+  margin: 5px 15px 0 0;
+}
+
+.header h1.navbar-brand a {
+  text-indent: -99999px;
+  background: no-repeat center center;
+  display: block;
+  width: 100%;
+  height: 100%;
+  background-size: contain;
+}
+
+.header .nav.navbar-nav.pull-right {
+  position: relative;
+  right: -30px;
+}
+
+.header .nav.navbar-nav .not-link {
+  padding: 15px;
+  display: inline-block;
+}
+
+.header .nav.navbar-nav .stable,
+.header .nav.navbar-nav .beta,
+.header .nav.navbar-nav .private {
+  font-size: 9px;
+  padding: 3px 5px;
+  display: inline-block;
+  line-height: 8px;
+  border-radius: 3px;
+  margin-left: 6px;
+  color: #fff;
+  top: -2px;
+  position: relative;
+  opacity: 0.6;
+  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";
+  filter: alpha(opacity=60);
+}
+
+.header .nav.navbar-nav a:hover > .stable,
+.header .nav.navbar-nav a:hover > .beta,
+.header .nav.navbar-nav a:hover > .private {
+  opacity: 1;
+  -ms-filter: none;
+  filter: none;
+}
+
+.header .nav.navbar-nav .beta {
+  background-color: #59c3d1;
+}
+
+.header .nav.navbar-nav .stable {
+  background-color: #41b841;
+}
+
+.header .nav.navbar-nav .private {
+  background-color: #333;
+}
+
+.theme-line header {
+  border-bottom: 8px solid;
+}
+
+.theme-line header h2 {
+  color: #aaa;
+}
+
+.theme-line header p {
+  color: #666;
+}
+
+.theme-line header {
+  border-bottom-color: @ignite-red;
+}
+
+.theme-line .navbar-nav {
+  color: #888;
+}
+
+.theme-line .navbar-nav a {
+  color: #bbb;
+}
+
+.theme-line header a.btn {
+  background-color: @ignite-red;
+}
+
+.theme-line header a.btn:hover {
+  background-color: #950d12;
+}
+
+.theme-line header .navbar-nav .tt-cursor {
+  background-color: @ignite-red;
+}
+
+.theme-line header .navbar-nav a:hover, .theme-line header .navbar-nav .open > a {
+  color: @ignite-red;
+}
+
+.theme-line .navbar-nav .active a {
+  //font-weight: bold;
+  color: @ignite-red;
+}
+
+.theme-line .navbar-nav .active a:hover {
+  color: #950d12;
+}
+
+.theme-line .main-links .links a:hover {
+  color: @ignite-red;
+}
+
+.theme-line .main-content a {
+  color: #666;
+}
+
+.theme-line .main-content a:hover {
+  color: #950d12;
+}
+
+.theme-line .sidebar-nav ul li a.active:before {
+  background-color: @ignite-red;
+}
+
+.theme-line .sidebar-nav ul li a.active {
+  color: @ignite-red;
+}
+
+.theme-line .sidebar-nav ul li a:hover, .theme-line .sidebar-nav ul li a.active:hover {
+  color: #950d12;
+}
+
+.theme-line .main-content .nav-horizontal a.active {
+  border-color: @ignite-red;
+  color: @ignite-red;
+}
+
+.theme-line .main-content .nav-horizontal a:hover {
+  color: #950d12;
+}
+
+.theme-line .main-content .nav-horizontal a.active:hover {
+  border-color: #950d12;
+}
+
+.theme-line header .navbar-nav a.active, .theme-line #versions-list li a:hover strong, .theme-line #versions-list li a.active .current, .theme-line #versions-list li a:active .current {
+  color: @ignite-red;
+}
+
+.theme-line header .navbar-nav a {
+  font-size: 18px;
+}
+
+.theme-line.body-threes .section-right .threes-nav .btn-default:hover, .theme-line.page-docs.body-threes .section-right .threes-nav .pull-right a:hover {
+  color: @ignite-red;
+  border-color: @ignite-red;
+}
+
+.theme-line .section-right {
+  padding-left: 30px;
+}
+
+.body-overlap .main-content {
+  margin-top: 30px;
+}
+
+.body-box .main-content,
+.body-overlap .main-content {
+  padding: 30px;
+  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
+  background-color: #fff;
+}
+
+body {
+  font-weight: 400;
+  font-family: Roboto Slab, serif;;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  font-weight: 700;
+  font-family: Roboto Slab, serif;
+  margin-bottom: 10px;
+}
+
+.submit-vote.submit-vote-parent.voted a.submit-vote-button, .submit-vote.submit-vote-parent a.submit-vote-button:hover {
+  background-color: @ignite-red;
+}
+
+div.submit-vote.submit-vote-parent.voted a.submit-vote-button:hover {
+  background-color: #950d12;
+}
+
+a, .link .title {
+  color: @ignite-red;
+}
+
+a:hover, .link:hover .title {
+  color: #950d12;
+}
+
+.header h1.navbar-brand a {
+  background-image: url("@{logo-path}");
+}
+
+.header h1.navbar-brand {
+  width: 96px;
+}
+
+.block-edit-parameters {
+  text-align: right;
+  padding-bottom: 5px;
+}
+
+.container-footer {
+  margin-top: 20px;
+}
+
+/* Modal */
+.modal {
+  display: block;
+  overflow: hidden;
+}
+
+.modal .close {
+  position: absolute;
+  top: 10px;
+  right: 10px;
+  float: none;
+}
+
+// Close icon
+.modal-header .close {
+  margin-right: -2px;
+}
+
+.modal .modal-dialog {
+  width: 610px;
+}
+
+.modal .modal-content {
+  border-radius: 0;
+  background-color: #f7f7f7;
+}
+
+.modal .modal-content .modal-header {
+  background-color: #fff;
+  text-align: center;
+  color: #555;
+  padding: 15px;
+  font-family: "myriad-pro", sans-serif;
+}
+
+.modal .modal-content .modal-header h4 {
+  font-family: "myriad-pro", sans-serif;
+  font-size: 22px;
+}
+
+.modal .modal-content .modal-header h4 .fa {
+  display: block;
+  font-size: 41px;
+  color: #ddd;
+  margin-bottom: 5px;
+}
+
+.modal .modal-content .modal-header p {
+  color: #aaa;
+  font-size: 1em;
+  margin: 3px 0 0;
+}
+
+.modal .modal-content .modal-spacer {
+  padding: 10px 10px 0 10px;
+}
+
+.modal .modal-content .modal-footer {
+  margin-top: 0;
+}
+
+.modal-body {
+  padding-top: 15px;
+}
+
+h1.ignite-logo {
+  background-image: url("@{logo-path}");
+}
+
+.block-display-image img {
+  max-width: 100%;
+  max-height: 450px;
+  margin: auto;
+  display: block;
+}
+
+.greedy {
+  min-height: 200px;
+  height: ~"calc(100vh - 290px)";
+}
+
+@media (min-width: 768px) {
+  .navbar-nav > li > a {
+    padding-top: 18px;
+    padding-bottom: 10px;
+  }
+}
+
+.details-row {
+  padding: 0 10px;
+}
+
+.details-row, .settings-row {
+  display: block;
+  margin: 10px 0;
+
+  label.table-header {
+    line-height: @input-height;
+  }
+
+  [class*="col-"] {
+    display: inline-block;
+    vertical-align: middle;
+    float: none;
+
+    padding-left: 0 !important;
+    padding-right: 0 !important;
+  }
+
+  input[type="checkbox"] {
+    line-height: 20px;
+    margin-right: 5px;
+  }
+
+  .checkbox label {
+    line-height: 20px;
+    vertical-align: middle;
+  }
+}
+
+button {
+  margin-right: 5px;
+}
+
+h1,
+h2,
+h3 {
+  user-select: none;
+  font-weight: normal;
+  /* Makes the vertical size of the text the same for all fonts. */
+  line-height: 1;
+}
+
+h3 {
+  color: black;
+  font-size: 1.2em;
+  margin-top: 0;
+  margin-bottom: 1.5em;
+}
+
+table tr:hover {
+  cursor: pointer;
+}
+
+.btn {
+  padding: 3px 6px;
+}
+
+button .caret, .btn .caret {
+  float: right;
+  margin-left: 5px;
+  margin-top: 7px;
+}
+
+.base-control {
+  text-align: left;
+  padding: 3px 3px;
+  height: @input-height;
+}
+
+.form-control:extend(.base-control all) {
+  display: inline-block;
+
+  button {
+    text-align: left;
+  }
+}
+
+.theme-line .panel-heading {
+  padding: 10px 10px;
+  margin: 0;
+
+  h3 {
+    margin-bottom: 0;
+  }
+
+  h3 > a {
+    color: black;
+  }
+}
+
+.theme-line .panel-title {
+  a {
+    color: @ignite-red;
+  }
+
+  h3 {
+    margin-bottom: 20px;
+  }
+}
+
+.theme-line .panel-body {
+  padding: 10px 20px;
+}
+
+.theme-line .main-content a.customize {
+  margin-left: 5px;
+  color: @ignite-red;
+}
+
+.theme-line .panel-collapse {
+  margin: 0;
+}
+
+.theme-line .links table {
+  display: table;
+  table-layout: fixed;
+
+  td {
+    padding-left: 18px;
+  }
+
+  .active a {
+    color: @ignite-red;
+    font-weight: bold;
+  }
+
+  a:hover {
+    color: #950d12;
+  }
+
+  a {
+    color: #666;
+  }
+}
+
+.theme-line table.links-edit:extend(.theme-line .links table all) {
+  margin-top: 5px;
+  margin-bottom: 5px;
+
+  label {
+    line-height: @input-height;
+    color: #666;
+  }
+}
+
+.theme-line table.links-edit-details:extend(.theme-line .links table all) {
+  margin-bottom: 10px;
+
+  label {
+    line-height: @input-height;
+    color: #666;
+  }
+
+  td {
+    padding: 0;
+
+    .input-tip {
+      padding: 0;
+    }
+  }
+}
+
+.theme-line table.admin {
+  tr:hover {
+    cursor: default;
+  }
+
+  thead > tr th.header {
+    padding: 0 0 10px;
+
+    div {
+      padding: 0
+    }
+  }
+
+  margin-bottom: 10px;
+
+  label {
+    line-height: @input-height;
+    color: #666;
+  }
+
+  thead > tr th, td {
+    padding: 10px 10px;
+
+    .input-tip {
+      padding: 0;
+    }
+  }
+
+  tfoot > tr > td {
+    padding: 0;
+
+    .pagination {
+      margin: 10px 0;
+
+      > .active > a {
+        color: @ignite-red;
+        font-weight: bold;
+        border-color: #ddd;
+        background-color: #eee;
+      }
+    }
+  }
+}
+
+.panel-title a {
+  font-size: 14px;
+}
+
+.panel-details {
+  margin-top: 10px;
+
+  padding: 0;
+
+  border-radius: 5px;
+  border: thin dotted lightgrey;
+}
+
+.tooltip.right .tooltip-arrow {
+  border-right-color: @ignite-red;
+}
+
+.tooltip > .tooltip-inner {
+  max-width: 400px;
+  text-align: left;
+  background-color: @ignite-red;
+}
+
+label {
+  font-weight: normal;
+  margin-bottom: 0;
+}
+
+.form-horizontal .checkbox {
+  padding-top: 0;
+}
+
+.input-tip {
+  display: block;
+  overflow: hidden;
+}
+
+.labelField {
+  float: left;
+  margin-right: 5px;
+}
+
+.labelFormField {
+  float: left;
+  line-height: @input-height;
+}
+
+.form-horizontal .form-group {
+  margin: 0;
+}
+
+.form-horizontal .has-feedback .form-control-feedback {
+  right: 0;
+}
+
+.tipField {
+  float: right;
+  line-height: @input-height;
+  margin-left: 5px;
+}
+
+.tipLabel {
+  font-size: 14px;
+  margin-left: 5px;
+}
+
+.fieldSep {
+  float: right;
+  line-height: @input-height;
+  margin: 0 5px;
+}
+
+.fieldButton {
+  float: right;
+  margin-left: 5px;
+  margin-right: 0;
+}
+
+.fa-plus {
+  cursor: pointer;
+}
+
+.fa-remove {
+  color: @ignite-red;
+  cursor: pointer;
+}
+
+.fa-floppy-o {
+  cursor: pointer;
+}
+
+.fa-arrow-up {
+  cursor: pointer;
+}
+
+.fa-arrow-down {
+  cursor: pointer;
+}
+
+label.required:after {
+  color: @ignite-red;
+  content: ' *';
+  display: inline;
+}
+
+.blank {
+  visibility: hidden;
+}
+
+.alert {
+  outline: 0
+}
+
+.alert.bottom, .alert.bottom-left, .alert.bottom-right, .alert.top,
+.alert.top-left, .alert.top-right {
+  position: fixed;
+  z-index: 1050;
+  margin: 20px
+}
+
+.alert.top, .alert.top-left, .alert.top-right {
+  top: 50px
+}
+
+.alert.top {
+  right: 0;
+  left: 0
+}
+
+.alert.top-right {
+  right: 0
+}
+
+.alert.top-right .close {
+  padding-left: 10px
+}
+
+.alert.top-left {
+  left: 0
+}
+
+.alert.top-left .close {
+  padding-right: 10px
+}
+
+.alert.bottom, .alert.bottom-left, .alert.bottom-right {
+  bottom: 0
+}
+
+.alert.bottom {
+  right: 0;
+  left: 0
+}
+
+.alert.bottom-right {
+  right: 0
+}
+
+.alert.bottom-right .close {
+  padding-left: 10px
+}
+
+.alert.bottom-left {
+  left: 0
+}
+
+.alert.bottom-left .close {
+  padding-right: 10px
+}
+
+//  Summary page
+#cfgResult textarea {
+  font-family: monospace;
+  font-size: 12px;
+}
+
+input[type="number"]::-webkit-outer-spin-button,
+input[type="number"]::-webkit-inner-spin-button {
+  -webkit-appearance: none;
+  margin: 0;
+}
+
+input[type="number"] {
+  -moz-appearance: textfield;
+}
+
+input.ng-dirty.ng-invalid, button.ng-dirty.ng-invalid {
+  border-color: @ignite-red;
+
+  :focus {
+    border-color: @ignite-red;
+  }
+}
+
+.form-control-feedback {
+  display: inline-block;
+  color: @ignite-red;
+  right: 18px;
+  line-height: @input-height;
+  pointer-events: initial;
+}
+
+.syntaxhighlighter {
+  padding: 10px 5px;
+  border-radius: 6px;
+}
+
+.theme-line table.links-edit-small-padding:extend(.theme-line .links table all) {
+  label {
+    line-height: @input-height;
+    color: #666;
+  }
+
+  a {
+    line-height: @input-height;
+  }
+
+  input[type="checkbox"] {
+    line-height: 20px;
+    margin-right: 5px;
+  }
+
+  .checkbox label {
+    line-height: 20px;
+    vertical-align: middle;
+  }
+
+  th {
+    text-align: center;
+  }
+
+  td {
+    padding-left: 10px;
+  }
+
+  margin-top: 10px;
+}
+
+.configBox .nav > li > a {
+  padding: 5px 5px;
+}
+
+.viewedUser {
+  position: absolute;
+  width: 100%;
+  left: 0;
+
+  text-align: center;
+
+  margin-top: -15px;
+
+  background-color: #f8d5d8;
+}
+
+a {
+  cursor: pointer;
+}
+
+.st-sort-ascent:after {
+  content: '\25B2';
+}
+
+.st-sort-descent:after {
+  content: '\25BC';
+}
+
+.panel {
+  margin-bottom: 0;
+}
+
+.panel-group {
+  margin-bottom: 0;
+}
+
+.panel-group .panel + .panel {
+  margin-top: 20px;
+}
+
+.margin-top-dflt {
+  margin-top: 10px;
+}
+
+.margin-bottom-dflt {
+  margin-bottom: 10px;
+}
+
+.margin-dflt {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+
+.padding-top-dflt {
+  padding-top: 10px;
+}
+
+.padding-bottom-dflt {
+  padding-bottom: 10px;
+}
+
+.padding-dflt {
+  padding-top: 10px;
+  padding-bottom: 10px;
+}
+
+.theme-line .panel-title h3 {
+  margin-top: 20px;
+  margin-bottom: 20px;
+}
+
+.block-callout-parent {
+  background-color: @ignite-block-callout-background;
+  overflow: hidden;
+}
+
+.block-callout {
+  background-color: @ignite-block-callout-background;
+  display: inline-block;
+  vertical-align: top;
+  width: 50%;
+
+  i {
+    padding: 10px 5px 0 10px;
+    color: @ignite-block-callout;
+  }
+
+  ul {
+    padding-left: 20px;
+    margin-bottom: 0;
+  }
+
+  p {
+    padding: 5px 0 10px 20px;
+    margin: 0;
+  }
+
+  label {
+    font-weight: bold;
+    color: @ignite-block-callout;
+  }
+}
+
+.block-callout-border {
+  border-left: 5px solid;
+  border-color: @ignite-block-callout;
+}
+
+.labelHeader {
+  font-weight: bold;
+}
+
+.ace_editor, #ace_document {
+  width: 100%;
+  height: 400px;
+}
+
+

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/admin.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/admin.js b/modules/web-control-center/src/main/js/routes/admin.js
new file mode 100644
index 0000000..5af72f7
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/admin.js
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+var router = require('express').Router();
+var db = require('../db');
+
+router.get('/', function (req, res) {
+    res.render('settings/admin');
+});
+
+/**
+ * Get list of user accounts.
+ */
+router.post('/list', function (req, res) {
+    db.Account.find({}).sort('username').exec(function (err, users) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        res.json(users);
+    });
+});
+
+router.post('/remove', function (req, res) {
+    var userId = req.body.userId;
+
+    db.Account.findByIdAndRemove(userId, function (err) {
+        if (err)
+            return res.status(500).send(err);
+
+        res.sendStatus(200);
+    });
+});
+
+router.post('/save', function (req, res) {
+    var userId = req.body.userId;
+    var adminFlag = req.body.adminFlag;
+
+    db.Account.findByIdAndUpdate(userId, {admin: adminFlag}, function (err) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        res.sendStatus(200);
+    });
+});
+
+router.get('/become', function (req, res) {
+    var viewedUserId = req.query.viewedUserId;
+
+    if (!viewedUserId) {
+        req.session.viewedUser = null;
+
+        return res.redirect('/admin');
+    }
+
+    db.Account.findById(viewedUserId).exec(function (err, viewedUser) {
+        if (err)
+            return res.sendStatus(404);
+
+        req.session.viewedUser = viewedUser;
+
+        res.redirect('/');
+    })
+});
+
+module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/caches.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/caches.js b/modules/web-control-center/src/main/js/routes/caches.js
new file mode 100644
index 0000000..3fefd37
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/caches.js
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+var router = require('express').Router();
+var db = require('../db');
+
+/* GET caches page. */
+router.get('/', function (req, res) {
+    res.render('configuration/caches');
+});
+
+/**
+ * Get spaces and caches accessed for user account.
+ *
+ * @param req Request.
+ * @param res Response.
+ */
+router.post('/list', function (req, res) {
+    var user_id = req.currentUserId();
+
+    // Get owned space and all accessed space.
+    db.Space.find({$or: [{owner: user_id}, {usedBy: {$elemMatch: {account: user_id}}}]}, function (err, spaces) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        var space_ids = spaces.map(function (value) {
+            return value._id;
+        });
+
+        // Get all caches for spaces.
+        db.Cache.find({space: {$in: space_ids}}).sort('name').exec(function (err, caches) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            res.json({spaces: spaces, caches: caches});
+        });
+    });
+});
+
+/**
+ * Save cache.
+ */
+router.post('/save', function (req, res) {
+    if (req.body._id)
+        db.Cache.update({_id: req.body._id}, req.body, {upsert: true}, function (err) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            res.send(req.body._id);
+        });
+    else {
+        db.Cache.findOne({name: req.body.name}, function (err, cache) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            if (cache)
+                return res.status(500).send('Cache with name: "' + cache.name + '" already exist.');
+
+            (new db.Cache(req.body)).save(function (err, cache) {
+                if (err)
+                    return res.status(500).send(err.message);
+
+                res.send(cache._id);
+            });
+        });
+    }
+});
+
+/**
+ * Remove cache by ._id.
+ */
+router.post('/remove', function (req, res) {
+    db.Cache.remove(req.body, function (err) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        res.sendStatus(200);
+    })
+});
+
+module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/clusters.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/clusters.js b/modules/web-control-center/src/main/js/routes/clusters.js
new file mode 100644
index 0000000..182130d
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/clusters.js
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+var router = require('express').Router();
+var db = require('../db');
+
+/* GET clusters page. */
+router.get('/', function (req, res) {
+    res.render('configuration/clusters');
+});
+
+/**
+ * Get spaces and clusters accessed for user account.
+ *
+ * @param req Request.
+ * @param res Response.
+ */
+router.post('/list', function (req, res) {
+    var user_id = req.currentUserId();
+
+    // Get owned space and all accessed space.
+    db.Space.find({$or: [{owner: user_id}, {usedBy: {$elemMatch: {account: user_id}}}]}, function (err, spaces) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        var space_ids = spaces.map(function (value) {
+            return value._id;
+        });
+
+        db.Cache.find({space: {$in: space_ids}}, '_id name swapEnabled', function (err, caches) {
+            if (err)
+                return res.status(500).send(err);
+
+            // Get all clusters for spaces.
+            db.Cluster.find({space: {$in: space_ids}}).sort('name').exec(function (err, clusters) {
+                if (err)
+                    return res.status(500).send(err.message);
+
+                var cachesJson = caches.map(function (cache) {
+                    return {value: cache._id, label: cache.name, swapEnabled: cache.swapEnabled};
+                });
+
+                res.json({spaces: spaces, caches: cachesJson, clusters: clusters});
+            });
+        });
+    });
+});
+
+/**
+ * Save cluster.
+ */
+router.post('/save', function (req, res) {
+    if (req.body._id)
+        db.Cluster.update({_id: req.body._id}, req.body, {upsert: true}, function (err) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            res.send(req.body._id);
+        });
+    else {
+        db.Cluster.findOne({name: req.body.name}, function (err, cluster) {
+            if (err)
+                return res.status(500).send(err.message);
+
+            if (cluster)
+                return res.status(500).send('Cluster with name: "' + cluster.name + '" already exist.');
+
+            (new db.Cluster(req.body)).save(function (err, cluster) {
+                if (err)
+                    return res.status(500).send(err.message);
+
+                res.send(cluster._id);
+            });
+        });
+    }
+});
+
+/**
+ * Remove cluster by ._id.
+ */
+router.post('/remove', function (req, res) {
+    db.Cluster.remove(req.body, function (err) {
+        if (err)
+            return res.status(500).send(err.message);
+
+        res.sendStatus(200);
+    })
+});
+
+module.exports = router;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/generator/common.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/generator/common.js b/modules/web-control-center/src/main/js/routes/generator/common.js
new file mode 100644
index 0000000..dcbf156
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/generator/common.js
@@ -0,0 +1,299 @@
+/*
+ * 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.
+ */
+
+var _ = require('lodash');
+
+exports.isDefined = function (v) {
+    return !(v === undefined || v === null);
+};
+
+exports.mainComment = mainComment;
+
+function mainComment() {
+    return 'This configuration was generated by Ignite Control Center ('
+        + formatDate(new Date()) + ')';
+}
+
+function addLeadingZero(numberStr, minSize) {
+    if (typeof (numberStr) != 'string')
+        numberStr = '' + numberStr;
+
+    while (numberStr.length < minSize) {
+        numberStr = '0' + numberStr;
+    }
+
+    return numberStr;
+}
+
+exports.formatDate = formatDate;
+
+function formatDate(date) {
+    var dd = addLeadingZero(date.getDate(), 2);
+    var mm = addLeadingZero(date.getMonth() + 1, 2);
+
+    var yyyy = date.getFullYear();
+
+    return mm + '/' + dd + '/' + yyyy + ' ' + addLeadingZero(date.getHours(), 2) + ':' + addLeadingZero(date.getMinutes(), 2);
+}
+
+exports.builder = function () {
+    var res = [];
+
+    res.deep = 0;
+    res.lineStart = true;
+
+    res.append = function (s) {
+        if (this.lineStart) {
+            for (var i = 0; i < this.deep; i++)
+                this.push('    ');
+
+            this.lineStart = false;
+        }
+
+        this.push(s);
+
+        return this;
+    };
+
+    res.line = function (s) {
+        if (s)
+            this.append(s);
+
+        this.push('\n');
+        this.lineStart = true;
+
+        return this;
+    };
+
+    res.startBlock = function (s) {
+        if (s)
+            this.append(s);
+
+        this.push('\n');
+        this.lineStart = true;
+        this.deep++;
+
+        return this;
+    };
+
+    res.endBlock = function (s) {
+        this.deep--;
+
+        if (s)
+            this.append(s);
+
+        this.push('\n');
+        this.lineStart = true;
+
+        return this;
+    };
+
+    res.emptyLineIfNeeded = function () {
+        if (this.needEmptyLine) {
+            this.line();
+
+            this.needEmptyLine = false;
+
+            return true;
+        }
+
+        return false;
+    };
+
+    res.imports = {};
+
+    res.importClass = function (fullClassName) {
+        var dotIdx = fullClassName.lastIndexOf('.');
+
+        var shortName;
+
+        if (dotIdx > 0)
+            shortName = fullClassName.substr(dotIdx + 1);
+        else
+            shortName = fullClassName;
+
+        if (this.imports[shortName]) {
+            if (this.imports[shortName] != fullClassName)
+                throw "Class name conflict: " + this.imports[shortName] + ' and ' + fullClassName;
+        }
+        else {
+            this.imports[shortName] = fullClassName;
+        }
+
+        return shortName;
+    };
+
+    res.generateImports = function () {
+        var res = [];
+
+        for (var clsName in this.imports) {
+            if (this.imports.hasOwnProperty(clsName))
+                res.push('import ' + this.imports[clsName] + ';');
+        }
+
+        return res.join('\n')
+    };
+
+    return res;
+};
+
+function ClassDescriptor(className, fields) {
+    this.className = className;
+    this.fields = fields;
+}
+
+exports.evictionPolicies = {
+    'LRU': new ClassDescriptor('org.apache.ignite.cache.eviction.lru.LruEvictionPolicy',
+        {batchSize: null, maxMemorySize: null, maxSize: null}),
+    'RND': new ClassDescriptor('org.apache.ignite.cache.eviction.random.RandomEvictionPolicy', {maxSize: null}),
+    'FIFO': new ClassDescriptor('org.apache.ignite.cache.eviction.fifo.FifoEvictionPolicy',
+        {batchSize: null, maxMemorySize: null, maxSize: null}),
+    'SORTED': new ClassDescriptor('org.apache.ignite.cache.eviction.sorted.SortedEvictionPolicy',
+        {batchSize: null, maxMemorySize: null, maxSize: null})
+};
+
+exports.marshallers = {
+    OptimizedMarshaller: new ClassDescriptor('org.apache.ignite.marshaller.optimized.OptimizedMarshaller', {
+        poolSize: null,
+        requireSerializable: null
+    }),
+    JdkMarshaller: new ClassDescriptor('org.apache.ignite.marshaller.jdk.JdkMarshaller', {})
+};
+
+exports.knownClasses = {
+    Oracle: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.OracleDialect', {}),
+    DB2: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.DB2Dialect', {}),
+    SQLServer: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.SQLServerDialect', {}),
+    MySQL: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.MySQLDialect', {}),
+    PostgreSQL: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect', {}),
+    H2: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.dialect.H2Dialect', {})
+};
+
+exports.dataSources = {
+    Oracle: 'oracle.jdbc.pool.OracleDataSource',
+    DB2: 'com.ibm.db2.jcc.DB2ConnectionPoolDataSource',
+    SQLServer: 'com.microsoft.sqlserver.jdbc.SQLServerDataSource',
+    MySQL: 'com.mysql.jdbc.jdbc2.optional.MysqlDataSource',
+    PostgreSQL: 'org.postgresql.ds.PGPoolingDataSource',
+    H2: 'org.h2.jdbcx.JdbcDataSource'
+};
+
+exports.storeFactories = {
+    CacheJdbcPojoStoreFactory: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory', {
+        dataSourceBean: null,
+        dialect: {type: 'className'}
+    }),
+
+    CacheJdbcBlobStoreFactory: new ClassDescriptor('org.apache.ignite.cache.store.jdbc.CacheJdbcBlobStoreFactory', {
+        user: null,
+        dataSourceBean: null,
+        initSchema: null,
+        createTableQuery: null,
+        loadQuery: null,
+        insertQuery: null,
+        updateQuery: null,
+        deleteQuery: null
+    }),
+
+    CacheHibernateBlobStoreFactory: new ClassDescriptor('org.apache.ignite.cache.store.hibernate.CacheHibernateBlobStoreFactory', {
+        hibernateProperties: {type: 'propertiesAsList', propVarName: 'props'}
+    })
+};
+
+exports.atomicConfiguration = new ClassDescriptor('org.apache.ignite.configuration.AtomicConfiguration', {
+    backups: null,
+    cacheMode: {type: 'enum', enumClass: 'CacheMode'},
+    atomicSequenceReserveSize: null
+});
+
+exports.swapSpaceSpi = new ClassDescriptor('org.apache.ignite.spi.swapspace.file.FileSwapSpaceSpi', {
+    baseDirectory: null,
+    readStripesNumber: null,
+    maximumSparsity: {type: 'float'},
+    maxWriteQueueSize: null,
+    writeBufferSize: null
+});
+
+exports.transactionConfiguration = new ClassDescriptor('org.apache.ignite.configuration.TransactionConfiguration', {
+    defaultTxConcurrency: {type: 'enum', enumClass: 'TransactionConcurrency'},
+    transactionIsolation: {type: 'TransactionIsolation', setterName: 'defaultTxIsolation'},
+    defaultTxTimeout: null,
+    pessimisticTxLogLinger: null,
+    pessimisticTxLogSize: null,
+    txSerializableEnabled: null
+});
+
+exports.hasProperty = function (obj, props) {
+    for (var propName in props) {
+        if (props.hasOwnProperty(propName)) {
+            if (obj[propName])
+                return true;
+        }
+    }
+
+    return false;
+};
+
+/**
+ * Convert some name to valid java name.
+ *
+ * @param name to convert.
+ * @returns {string} Valid java name.
+ */
+exports.toJavaName = function (name) {
+    var javaName = name.replace(/[^A-Za-z_0-9]+/, '_');
+
+    return javaName.charAt(0).toLocaleUpperCase() + javaName.slice(1);
+};
+
+/**
+ * Generate properties file with properties stubs for stores data sources.
+ *
+ * @param cluster Configuration to process.
+ * @returns {string} Generated content.
+ */
+exports.generateProperties = function (cluster) {
+    var res = exports.builder();
+
+    var datasources = [];
+
+    if (cluster.caches && cluster.caches.length > 0) {
+        _.forEach(cluster.caches, function (cache) {
+            if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind) {
+                var storeFactory = cache.cacheStoreFactory[cache.cacheStoreFactory.kind];
+
+                if (storeFactory.dialect) {
+                    var beanId = storeFactory.dataSourceBean;
+
+                    if (!_.contains(datasources, beanId)) {
+                        datasources.push(beanId);
+
+                        res.line(beanId + '.jdbc.url=YOUR_JDBC_URL');
+                        res.line(beanId + '.jdbc.username=YOUR_USER_NAME');
+                        res.line(beanId + '.jdbc.password=YOUR_PASSWORD');
+                        res.line();
+                    }
+                }
+            }
+        });
+    }
+
+    if (datasources.length > 0)
+        return '# ' + mainComment() + '\n\n' + res.join();
+
+    return undefined;
+};

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/generator/docker.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/generator/docker.js b/modules/web-control-center/src/main/js/routes/generator/docker.js
new file mode 100644
index 0000000..93faf8e
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/generator/docker.js
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+exports.generateClusterConfiguration = function(cluster, os) {
+    if (!os)
+        os = 'debian:8';
+
+    return "" +
+        "# Start from a OS image.\n"+
+        "FROM " + os + "\n"+
+        "\n"+
+        "# Install tools.\n"+
+        "RUN apt-get update && apt-get install -y --fix-missing \\\n"+
+        "  wget \\\n"+
+        "  dstat \\\n"+
+        "  maven \\\n"+
+        "  git\n"+
+        "\n"+
+        "# Install Oracle JDK.\n"+
+        "RUN mkdir /opt/jdk\n"+
+        "\n"+
+        "RUN wget --header \"Cookie: oraclelicense=accept-securebackup-cookie\" \\\n"+
+        "  http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.tar.gz\n"+
+        "\n"+
+        "RUN tar -zxf jdk-7u79-linux-x64.tar.gz -C /opt/jdk\n"+
+        "\n"+
+        "RUN rm jdk-7u79-linux-x64.tar.gz\n"+
+        "\n"+
+        "RUN update-alternatives --install /usr/bin/java java /opt/jdk/jdk1.7.0_79/bin/java 100\n"+
+        "\n"+
+        "RUN update-alternatives --install /usr/bin/javac javac /opt/jdk/jdk1.7.0_79/bin/javac 100\n"+
+        "\n"+
+        "# Sets java variables.\n"+
+        "ENV JAVA_HOME /opt/jdk/jdk1.7.0_79/\n"+
+        "\n"+
+        "# Create working directory\n"+
+        "WORKDIR /home\n"+
+        "\n"+
+        "RUN wget -O ignite.zip http://tiny.cc/updater/download_ignite.php && unzip ignite.zip && rm ignite.zip\n"+
+        "\n"+
+        "COPY *.xml /tmp/\n"+
+        "\n"+
+        "RUN mv /tmp/*.xml /home/$(ls)/config";
+};

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/generator/java.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/generator/java.js b/modules/web-control-center/src/main/js/routes/generator/java.js
new file mode 100644
index 0000000..31cd2ac
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/generator/java.js
@@ -0,0 +1,626 @@
+/*
+ * 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.
+ */
+
+var _ = require('lodash');
+
+var generatorUtils = require("./common");
+
+exports.generateClusterConfiguration = function(cluster, javaClass, clientNearConfiguration) {
+    var res = generatorUtils.builder();
+
+    res.datasourceBeans = [];
+
+    if (javaClass) {
+        res.line('/**');
+        res.line(' * ' + generatorUtils.mainComment());
+        res.line(' */');
+        res.startBlock('public class ConfigurationFactory {');
+        res.line('/**');
+        res.line(' * Configure grid.');
+        res.line(' */');
+        res.startBlock('public IgniteConfiguration createConfiguration() {');
+    }
+    
+    res.importClass('org.apache.ignite.configuration.IgniteConfiguration');
+    
+    res.line('IgniteConfiguration cfg = new IgniteConfiguration();');
+    res.line();
+
+    if (clientNearConfiguration) {
+        res.line('cfg.setClientMode(true);');
+
+        res.line();
+    }
+
+    if (cluster.discovery) {
+        var d = cluster.discovery;
+
+        res.importClass('org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi');
+        res.line('TcpDiscoverySpi discovery = new TcpDiscoverySpi();');
+
+        switch (d.kind) {
+            case 'Multicast':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder');
+
+                addBeanWithProperties(res, d.Multicast, 'discovery', 'ipFinder', 'ipFinder',
+                    'TcpDiscoveryMulticastIpFinder', {
+                        multicastGroup: null,
+                        multicastPort: null,
+                        responseWaitTime: null,
+                        addressRequestAttempts: null,
+                        localAddress: null
+                    }, true);
+
+                break;
+
+            case 'Vm':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder');
+
+                addBeanWithProperties(res, d.Vm, 'discovery', 'ipFinder', 'ipFinder', 'TcpDiscoveryVmIpFinder', {
+                        addresses: {type: 'list'}
+                    }, true);
+
+                break;
+
+            case 'S3':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.s3.TcpDiscoveryS3IpFinder');
+
+                if (d.S3)
+                    addBeanWithProperties(res, d.S3, 'discovery', 'ipFinder', 'ipFinder', 'TcpDiscoveryS3IpFinder',
+                        {bucketName: null}, true);
+                else
+                    res.line('discovery.setIpFinder(new TcpDiscoveryS3IpFinder());');
+
+                break;
+
+            case 'Cloud':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.cloud.TcpDiscoveryCloudIpFinder');
+
+                addBeanWithProperties(res, d.Cloud, 'discovery', 'ipFinder', 'ipFinder', 'TcpDiscoveryCloudIpFinder', {
+                        credential: null,
+                        credentialPath: null,
+                        identity: null,
+                        provider: null,
+                        regions: {type: 'list'},
+                        zones: {type: 'list'}
+                    }, true);
+
+                break;
+
+            case 'GoogleStorage':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.gce.TcpDiscoveryGoogleStorageIpFinder');
+
+                addBeanWithProperties(res, d.GoogleStorage, 'discovery', 'ipFinder', 'ipFinder',
+                    'TcpDiscoveryGoogleStorageIpFinder', {
+                        projectName: null,
+                        bucketName: null,
+                        serviceAccountP12FilePath: null
+                    }, true);
+
+                //if (d.GoogleStorage.addrReqAttempts) todo ????
+                //    res.line('<property name="serviceAccountP12FilePath" value="' + escapeAttr(d.GoogleStorage.addrReqAttempts) + '"/>');
+
+                break;
+
+            case 'Jdbc':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.jdbc.TcpDiscoveryJdbcIpFinder');
+                
+                res.line();
+                res.line('TcpDiscoveryJdbcIpFinder ipFinder = new TcpDiscoveryJdbcIpFinder();');
+                res.line('ipFinder.setInitSchema(' + (d.Jdbc.initSchema != null || d.Jdbc.initSchema) + ');');
+                res.line('discovery.setIpFinder(ipFinder);');
+                res.needEmptyLine = true;
+
+                break;
+
+            case 'SharedFs':
+                res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs.TcpDiscoverySharedFsIpFinder');
+
+                addBeanWithProperties(res, d.SharedFs, 'discovery', 'ipFinder', 'ipFinder',
+                    'TcpDiscoverySharedFsIpFinder', {path: null}, true);
+
+                break;
+
+            default:
+                throw "Unknown discovery kind: " + d.kind;
+        }
+
+        res.emptyLineIfNeeded();
+
+        res.line('cfg.setDiscoverySpi(discovery);');
+
+        res.needEmptyLine = true;
+    }
+
+    if (cluster.caches && cluster.caches.length > 0) {
+        res.emptyLineIfNeeded();
+
+        var names = [];
+
+        for (var i = 0; i < cluster.caches.length; i++) {
+            res.emptyLineIfNeeded();
+
+            var cache = cluster.caches[i];
+
+            var cacheName = 'cache' + generatorUtils.toJavaName(cache.name);
+
+            names.push(cacheName);
+
+            generateCacheConfiguration(cache, cacheName, res);
+
+            res.needEmptyLine = true;
+        }
+
+        res.emptyLineIfNeeded();
+
+        res.append('cfg.setCacheConfiguration(');
+
+        for (i = 0; i < names.length; i++) {
+            if (i > 0)
+                res.append(', ');
+
+            res.append(names[i]);
+        }
+
+        res.line(');');
+
+        res.needEmptyLine = true;
+    }
+
+    addBeanWithProperties(res, cluster.atomicConfiguration, 'cfg', 'atomicConfiguration', 'atomicCfg',
+        generatorUtils.atomicConfiguration.className, generatorUtils.atomicConfiguration.fields);
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cluster, 'cfg', 'networkTimeout');
+    addProperty(res, cluster, 'cfg', 'networkSendRetryDelay');
+    addProperty(res, cluster, 'cfg', 'networkSendRetryCount');
+    addProperty(res, cluster, 'cfg', 'segmentCheckFrequency');
+    addProperty(res, cluster, 'cfg', 'waitForSegmentOnStart');
+    addProperty(res, cluster, 'cfg', 'discoveryStartupDelay');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cluster, 'cfg', 'deploymentMode', 'DeploymentMode');
+
+    res.needEmptyLine = true;
+
+    if (cluster.includeEventTypes && cluster.includeEventTypes.length > 0) {
+        res.emptyLineIfNeeded();
+        
+        if (cluster.includeEventTypes.length == 1) {
+            res.importClass('org.apache.ignite.events.EventType');
+            
+            res.line('cfg.setIncludeEventTypes(EventType.' + cluster.includeEventTypes[0] + ');');
+        }
+        else {
+            res.append('int[] events = new int[EventType.' + cluster.includeEventTypes[0] + '.length');
+            
+            for (i = 1; i < cluster.includeEventTypes.length; i++) {
+                res.line();
+                
+                res.append('    + EventType.' + cluster.includeEventTypes[i] + '.length');
+            }
+            
+            res.line('];');
+            res.line();
+            res.line('int k = 0;');
+
+            for (i = 0; i < cluster.includeEventTypes.length; i++) {
+                res.line();
+
+                var e = cluster.includeEventTypes[i];
+                
+                res.line('System.arraycopy(EventType.' + e + ', 0, events, k, EventType.' + e + '.length);');
+                res.line('k += EventType.' + e + '.length;');
+            }
+            
+            res.line();
+            res.line('cfg.setIncludeEventTypes(events);');
+        }
+
+        res.needEmptyLine = true;
+    }
+
+    res.needEmptyLine = true;
+
+    var marshaller = cluster.marshaller;
+
+    if (marshaller && marshaller.kind) {
+        var marshallerDesc = generatorUtils.marshallers[marshaller.kind];
+
+        addBeanWithProperties(res, marshaller[marshaller.kind], 'cfg', 'marshaller', 'marshaller',
+            marshallerDesc.className, marshallerDesc.fields, true);
+
+        addBeanWithProperties(res, marshaller[marshaller.kind], 'marshaller', marshallerDesc.className, marshallerDesc.fields, true);
+    }
+
+    addProperty(res, cluster, 'cfg', 'marshalLocalJobs');
+    addProperty(res, cluster, 'cfg', 'marshallerCacheKeepAliveTime');
+    addProperty(res, cluster, 'cfg', 'marshallerCacheThreadPoolSize');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cluster, 'cfg', 'metricsExpireTime');
+    addProperty(res, cluster, 'cfg', 'metricsHistorySize');
+    addProperty(res, cluster, 'cfg', 'metricsLogFrequency');
+    addProperty(res, cluster, 'cfg', 'metricsUpdateFrequency');
+    res.needEmptyLine = true;
+
+    addProperty(res, cluster, 'cfg', 'peerClassLoadingEnabled');
+    addMultiparamProperty(res, cluster, 'cfg', 'peerClassLoadingLocalClassPathExclude');
+    addProperty(res, cluster, 'cfg', 'peerClassLoadingMissedResourcesCacheSize');
+    addProperty(res, cluster, 'cfg', 'peerClassLoadingThreadPoolSize');
+    res.needEmptyLine = true;
+
+    if (cluster.swapSpaceSpi && cluster.swapSpaceSpi.kind == 'FileSwapSpaceSpi') {
+        addBeanWithProperties(res, cluster.swapSpaceSpi.FileSwapSpaceSpi, 'cfg', 'swapSpaceSpi', 'swapSpi',
+            generatorUtils.swapSpaceSpi.className, generatorUtils.swapSpaceSpi.fields, true);
+
+        res.needEmptyLine = true;
+    }
+
+    addProperty(res, cluster, 'cfg', 'clockSyncSamples');
+    addProperty(res, cluster, 'cfg', 'clockSyncFrequency');
+    addProperty(res, cluster, 'cfg', 'timeServerPortBase');
+    addProperty(res, cluster, 'cfg', 'timeServerPortRange');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cluster, 'cfg', 'publicThreadPoolSize');
+    addProperty(res, cluster, 'cfg', 'systemThreadPoolSize');
+    addProperty(res, cluster, 'cfg', 'managementThreadPoolSize');
+    addProperty(res, cluster, 'cfg', 'igfsThreadPoolSize');
+
+    res.needEmptyLine = true;
+
+    addBeanWithProperties(res, cluster.transactionConfiguration, 'cfg', 'transactionConfiguration',
+        'transactionConfiguration', generatorUtils.transactionConfiguration.className,
+        generatorUtils.transactionConfiguration.fields);
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cluster, 'cfg', 'cacheSanityCheckEnabled');
+
+    res.needEmptyLine = true;
+
+    if (javaClass) {
+        res.line();
+        res.line('return cfg;');
+        res.endBlock('}');
+        res.endBlock('}');
+        
+        return res.generateImports() + '\n\n' + res.join('')
+    }
+    
+    return res.join('');
+};
+
+function createEvictionPolicy(res, evictionPolicy, varName, propertyName) {
+    if (evictionPolicy && evictionPolicy.kind) {
+        var e = generatorUtils.evictionPolicies[evictionPolicy.kind];
+
+        var obj = evictionPolicy[evictionPolicy.kind.toUpperCase()];
+
+        addBeanWithProperties(res, obj, varName, propertyName, propertyName, e.className, e.fields, true);
+    }
+}
+
+exports.generateCacheConfiguration = generateCacheConfiguration;
+
+/**
+ * Generate java code for cache configuration.
+ *
+ * @param cacheCfg Cache config.
+ * @param varName Variable name.
+ * @param res Result builder.
+ * @returns {*} Append generated java code to builder and return it.
+ */
+function generateCacheConfiguration(cacheCfg, varName, res) {
+    if (!res)
+        res = generatorUtils.builder();
+
+    res.emptyLineIfNeeded();
+
+    res.importClass('org.apache.ignite.cache.CacheAtomicityMode');
+    res.importClass('org.apache.ignite.cache.CacheMode');
+    res.importClass('org.apache.ignite.configuration.CacheConfiguration');
+
+    res.line('CacheConfiguration ' + varName + ' = new CacheConfiguration();');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, varName, 'name');
+    
+    addProperty(res, cacheCfg, varName, 'mode', 'CacheMode', 'cacheMode');
+
+    addProperty(res, cacheCfg, varName, 'atomicityMode', 'CacheAtomicityMode');
+    addProperty(res, cacheCfg, varName, 'backups');
+    addProperty(res, cacheCfg, varName, 'startSize');
+    addProperty(res, cacheCfg, varName, 'readFromBackup');
+
+    res.needEmptyLine = true;
+    
+    addProperty(res, cacheCfg, varName, 'memoryMode', 'CacheMemoryMode');
+    addProperty(res, cacheCfg, varName, 'offHeapMaxMemory');
+    addProperty(res, cacheCfg, varName, 'swapEnabled');
+    addProperty(res, cacheCfg, varName, 'copyOnRead');
+
+    res.needEmptyLine = true;
+
+    createEvictionPolicy(res, cacheCfg.evictionPolicy, varName, 'evictionPolicy');
+
+    if (cacheCfg.nearCacheEnabled) {
+        res.needEmptyLine = true;
+
+        res.importClass('org.apache.ignite.configuration.NearCacheConfiguration');
+
+        addBeanWithProperties(res, cacheCfg.nearConfiguration, varName, 'nearConfiguration', 'nearConfiguration',
+            'NearCacheConfiguration', {nearStartSize: null}, true);
+
+        if (cacheCfg.nearConfiguration && cacheCfg.nearConfiguration.nearEvictionPolicy && cacheCfg.nearConfiguration.nearEvictionPolicy.kind) {
+            createEvictionPolicy(res, cacheCfg.nearConfiguration.nearEvictionPolicy, 'nearConfiguration', 'nearEvictionPolicy');
+        }
+    }
+
+    res.needEmptyLine = true;
+    
+    addProperty(res, cacheCfg, varName, 'sqlEscapeAll');
+    addProperty(res, cacheCfg, varName, 'sqlOnheapRowCacheSize');
+    addProperty(res, cacheCfg, varName, 'longQueryWarningTimeout');
+    
+    if (cacheCfg.indexedTypes && cacheCfg.indexedTypes.length > 0) {
+        res.emptyLineIfNeeded();
+        
+        res.append(varName + '.setIndexedTypes(');
+        
+        for (var i = 0; i < cacheCfg.indexedTypes.length; i++) {
+            if (i > 0)
+                res.append(', ');
+
+            var pair = cacheCfg.indexedTypes[i];
+            
+            res.append(toJavaCode(pair.keyClass, 'class')).append(', ').append(toJavaCode(pair.valueClass, 'class'))
+        }
+        
+        res.line(');');
+    }
+
+    addMultiparamProperty(res, cacheCfg, varName, 'sqlFunctionClasses', 'class');
+    
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, varName, 'rebalanceMode', 'CacheRebalanceMode');
+    addProperty(res, cacheCfg, varName, 'rebalanceThreadPoolSize');
+    addProperty(res, cacheCfg, varName, 'rebalanceBatchSize');
+    addProperty(res, cacheCfg, varName, 'rebalanceOrder');
+    addProperty(res, cacheCfg, varName, 'rebalanceDelay');
+    addProperty(res, cacheCfg, varName, 'rebalanceTimeout');
+    addProperty(res, cacheCfg, varName, 'rebalanceThrottle');
+
+    res.needEmptyLine = true;
+    
+    if (cacheCfg.cacheStoreFactory && cacheCfg.cacheStoreFactory.kind) {
+        var storeFactory = cacheCfg.cacheStoreFactory[cacheCfg.cacheStoreFactory.kind];
+        var data = generatorUtils.storeFactories[cacheCfg.cacheStoreFactory.kind];
+
+        var sfVarName = 'storeFactory' + generatorUtils.toJavaName(cacheCfg.name);
+        var dsVarName = 'none';
+
+        if (storeFactory.dialect) {
+            var dataSourceBean = storeFactory.dataSourceBean;
+
+            dsVarName = 'dataSource' + generatorUtils.toJavaName(dataSourceBean);
+
+            if (!_.contains(res.datasourceBeans, dataSourceBean)) {
+                res.datasourceBeans.push(dataSourceBean);
+
+                var dataSource = generatorUtils.dataSources[storeFactory.dialect];
+
+                res.line();
+                res.line(dataSource.className + ' ' + dsVarName + ' = new ' + dataSource.className + '();');
+                res.line(dsVarName + '.setURL(_URL_);');
+                res.line(dsVarName + '.setUsername(_User_Name_);');
+                res.line(dsVarName + '.setPassword(_Password_);');
+            }
+        }
+
+        addBeanWithProperties(res, storeFactory, varName, 'cacheStoreFactory', sfVarName, data.className,
+            data.fields, true);
+
+        if (dsVarName != 'none')
+            res.line(sfVarName + '.setDataSource(' + dsVarName + ');');
+    }
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, varName, 'loadPreviousValue');
+    addProperty(res, cacheCfg, varName, 'readThrough');
+    addProperty(res, cacheCfg, varName, 'writeThrough');
+
+    res.needEmptyLine = true;
+    
+    addProperty(res, cacheCfg, varName, 'invalidate');
+    addProperty(res, cacheCfg, varName, 'defaultLockTimeout');
+    addProperty(res, cacheCfg, varName, 'transactionManagerLookupClassName');
+    
+    res.needEmptyLine = true;
+    
+    addProperty(res, cacheCfg, varName, 'writeBehindEnabled');
+    addProperty(res, cacheCfg, varName, 'writeBehindBatchSize');
+    addProperty(res, cacheCfg, varName, 'writeBehindFlushSize');
+    addProperty(res, cacheCfg, varName, 'writeBehindFlushFrequency');
+    addProperty(res, cacheCfg, varName, 'writeBehindFlushThreadCount');
+    
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, varName, 'statisticsEnabled');
+    addProperty(res, cacheCfg, varName, 'managementEnabled');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, varName, 'maxConcurrentAsyncOperations');
+    
+    return res;
+}
+
+function toJavaCode(val, type) {
+    if (val == null)
+       return 'null';
+
+    if (type == 'float')
+        return val + 'f';
+    
+    if (type == 'class')
+        return val + '.class';
+    
+    if (type)
+        return type + '.' + val;
+    
+    if (typeof(val) == 'string')
+        return '"' + val.replace('"', '\\"') + '"';
+
+    if (typeof(val) == 'number' || typeof(val) == 'boolean')
+        return '' + val;
+
+    throw "Unknown type: " + typeof(val) + ' (' + val + ')';
+}
+
+function addProperty(res, obj, objVariableName, propName, enumType, setterName) {
+    var val = obj[propName];
+    
+    if (generatorUtils.isDefined(val)) {
+        res.emptyLineIfNeeded();
+
+        res.line(objVariableName + '.' + getSetterName(setterName ? setterName : propName)
+            + '(' + toJavaCode(val, enumType)  + ');');
+    }
+}
+
+function getSetterName(propName) {
+    return 'set' + propName.charAt(0).toLocaleUpperCase() + propName.slice(1);
+}
+
+function addListProperty(res, obj, objVariableName, propName, enumType, setterName) {
+    var val = obj[propName];
+    
+    if (val && val.length > 0) {
+        res.append(objVariableName + '.' + getSetterName(setterName ? setterName : propName) + '(Arrays.asList(');
+
+        for (var i = 0; i < val.length; i++) {
+            if (i > 0)
+                res.append(', ');
+            
+            res.append(toJavaCode(val[i], enumType));
+        }
+        
+        res.line('));');
+    }
+}
+
+function addMultiparamProperty(res, obj, objVariableName, propName, type, setterName) {
+    var val = obj[propName];
+    
+    if (val && val.length > 0) {
+        res.append(objVariableName + '.' + getSetterName(setterName ? setterName : propName) + '(');
+
+        for (var i = 0; i < val.length; i++) {
+            if (i > 0)
+                res.append(', ');
+            
+            res.append(toJavaCode(val[i], type));
+        }
+        
+        res.line(');');
+    }
+}
+
+function addBeanWithProperties(res, bean, objVarName, beanPropName, beanVarName, beanClass, props, createBeanAlthoughNoProps) {
+    if (bean && generatorUtils.hasProperty(bean, props)) {
+        if (!res.emptyLineIfNeeded()) {
+            res.line();
+        }
+        
+        res.line(beanClass + ' ' + beanVarName + ' = new ' + beanClass + '();');
+
+        for (var propName in props) {
+            if (props.hasOwnProperty(propName)) {
+                var descr = props[propName];
+
+                if (descr) {
+                    switch (descr.type) {
+                        case 'list':
+                            addListProperty(res, bean, beanVarName, propName, descr.elementsType, descr.setterName);
+                            break;
+                        
+                        case 'enum':
+                            addProperty(res, bean, beanVarName, propName, descr.enumClass, descr.setterName);
+                            break;
+                        
+                        case 'float':
+                            addProperty(res, bean, beanVarName, propName, 'float', descr.setterName);
+                            break;
+                        
+                        case 'propertiesAsList':
+                            var val = bean[propName];
+                            
+                            if (val && val.length > 0) {
+                                res.line('Properties ' + descr.propVarName + ' = new Properties();');
+                                
+                                for (var i = 0; i < val.length; i++) {
+                                    var nameAndValue = val[i];
+                                    
+                                    var eqIndex = nameAndValue.indexOf('=');
+                                    if (eqIndex >= 0) {
+                                        res.line(descr.propVarName + '.setProperty(' 
+                                            + nameAndValue.substring(0, eqIndex) + ', ' 
+                                            + nameAndValue.substr(eqIndex + 1) + ');');
+                                    }
+
+                                }
+                                
+                                res.line(beanVarName + '.' + getSetterName(propName) + '(' + descr.propVarName + ');');
+                            }
+                            break;
+                        
+                        case 'className':
+                            if (bean[propName]) {
+                                res.line(beanVarName + '.' + getSetterName(propName) + '(new ' + generatorUtils.knownClasses[bean[propName]].className + '());');
+                            }
+
+                            break;
+                        
+                        default:
+                            addProperty(res, bean, beanVarName, propName, null, descr.setterName);
+                    }
+                }
+                else {
+                    addProperty(res, bean, beanVarName, propName);
+                }
+            }
+        }
+        
+        res.line(objVarName + '.' + getSetterName(beanPropName) + '(' + beanVarName + ');');
+        
+        res.needEmptyLine = true;
+    }
+    else if (createBeanAlthoughNoProps) {
+        res.emptyLineIfNeeded();
+        
+        res.line(objVarName + '.' + getSetterName(beanPropName) + '(new ' + beanClass + '());');
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8a335724/modules/web-control-center/src/main/js/routes/generator/xml.js
----------------------------------------------------------------------
diff --git a/modules/web-control-center/src/main/js/routes/generator/xml.js b/modules/web-control-center/src/main/js/routes/generator/xml.js
new file mode 100644
index 0000000..16ef23b
--- /dev/null
+++ b/modules/web-control-center/src/main/js/routes/generator/xml.js
@@ -0,0 +1,580 @@
+/*
+ * 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.
+ */
+
+var _ = require('lodash');
+
+var generatorUtils = require("./common");
+var dataStructures = require("../../helpers/data-structures.js");
+
+exports.generateClusterConfiguration = function(cluster, clientNearConfiguration) {
+    var res = generatorUtils.builder();
+
+    res.datasources = [];
+    res.deep = 1;
+
+    if (clientNearConfiguration) {
+        res.startBlock('<bean id="nearCacheBean" class="org.apache.ignite.configuration.NearCacheConfiguration">');
+
+        if (clientNearConfiguration.nearStartSize)
+            addProperty(res, clientNearConfiguration, 'nearStartSize');
+
+        if (clientNearConfiguration.nearEvictionPolicy && clientNearConfiguration.nearEvictionPolicy.kind)
+            createEvictionPolicy(res, clientNearConfiguration.nearEvictionPolicy, 'nearEvictionPolicy');
+
+        res.endBlock('</bean>');
+
+        res.line();
+    }
+
+    // Generate Ignite Configuration.
+    res.startBlock('<bean class="org.apache.ignite.configuration.IgniteConfiguration">');
+
+    if (clientNearConfiguration) {
+        res.line('<property name="clientMode" value="true" />');
+
+        res.line();
+    }
+
+    // Generate discovery.
+    if (cluster.discovery) {
+        res.startBlock('<property name="discoverySpi">');
+        res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">');
+        res.startBlock('<property name="ipFinder">');
+
+        var d = cluster.discovery;
+
+        switch (d.kind) {
+            case 'Multicast':
+                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">');
+
+                addProperty(res, d.Multicast, 'multicastGroup');
+                addProperty(res, d.Multicast, 'multicastPort');
+                addProperty(res, d.Multicast, 'responseWaitTime');
+                addProperty(res, d.Multicast, 'addressRequestAttempts');
+                addProperty(res, d.Multicast, 'localAddress');
+
+                res.endBlock('</bean>');
+
+                break;
+
+            case 'Vm':
+                if (d.Vm.addresses.length > 0) {
+                    res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">');
+
+                    addListProperty(res, d.Vm, 'addresses');
+
+                    res.endBlock('</bean>');
+                }
+                else {
+                    res.line('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder"/>');
+                }
+
+                break;
+
+            case 'S3':
+                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.s3.TcpDiscoveryS3IpFinder">');
+
+                if (d.S3 && d.S3.bucketName)
+                    res.line('<property name="bucketName" value="' + escapeAttr(d.S3.bucketName) + '" />');
+
+                res.endBlock('</bean>');
+
+                break;
+
+            case 'Cloud':
+                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.cloud.TcpDiscoveryCloudIpFinder">');
+
+                addProperty(res, d.Cloud, 'credential');
+                addProperty(res, d.Cloud, 'credentialPath');
+                addProperty(res, d.Cloud, 'identity');
+                addProperty(res, d.Cloud, 'provider');
+                addListProperty(res, d.Cloud, 'regions');
+                addListProperty(res, d.Cloud, 'zones');
+
+                res.endBlock('</bean>');
+
+                break;
+
+            case 'GoogleStorage':
+                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.gce.TcpDiscoveryGoogleStorageIpFinder">');
+
+                addProperty(res, d.GoogleStorage, 'projectName');
+                addProperty(res, d.GoogleStorage, 'bucketName');
+                addProperty(res, d.GoogleStorage, 'serviceAccountP12FilePath');
+
+                //if (d.GoogleStorage.addrReqAttempts) todo ????
+                //    res.line('<property name="serviceAccountP12FilePath" value="' + escapeAttr(d.GoogleStorage.addrReqAttempts) + '"/>');
+
+                res.endBlock('</bean>');
+
+                break;
+
+            case 'Jdbc':
+                res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.jdbc.TcpDiscoveryJdbcIpFinder">');
+                res.line('<property name="initSchema" value="' + (d.Jdbc.initSchema != null || d.Jdbc.initSchema) + '"/>');
+                res.endBlock('</bean>');
+
+                break;
+
+            case 'SharedFs':
+                if (d.SharedFs.path) {
+                    res.startBlock('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs.TcpDiscoverySharedFsIpFinder">');
+                    addProperty(res, d.SharedFs, 'path');
+                    res.endBlock('</bean>');
+                }
+                else {
+                    res.line('<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs.TcpDiscoverySharedFsIpFinder"/>');
+                }
+
+                break;
+
+            default:
+                throw "Unknown discovery kind: " + d.kind;
+        }
+
+        res.endBlock('</property>');
+        res.endBlock('</bean>');
+        res.endBlock('</property>');
+
+        res.needEmptyLine = true
+    }
+
+    // Generate atomics group.
+    addBeanWithProperties(res, cluster.atomicConfiguration, 'atomicConfiguration',
+        generatorUtils.atomicConfiguration.className, generatorUtils.atomicConfiguration.fields);
+    res.needEmptyLine = true;
+
+    // Generate communication group.
+    addProperty(res, cluster, 'networkTimeout');
+    addProperty(res, cluster, 'networkSendRetryDelay');
+    addProperty(res, cluster, 'networkSendRetryCount');
+    addProperty(res, cluster, 'segmentCheckFrequency');
+    addProperty(res, cluster, 'waitForSegmentOnStart');
+    addProperty(res, cluster, 'discoveryStartupDelay');
+    res.needEmptyLine = true;
+
+    // Generate deployment group.
+    addProperty(res, cluster, 'deploymentMode');
+    res.needEmptyLine = true;
+
+    // Generate events group.
+    if (cluster.includeEventTypes && cluster.includeEventTypes.length > 0) {
+        res.emptyLineIfNeeded();
+        
+        res.startBlock('<property name="includeEventTypes">');
+        
+        if (cluster.includeEventTypes.length == 1)
+            res.line('<util:constant static-field="org.apache.ignite.events.EventType.' + cluster.includeEventTypes[0] + '"/>');
+        else {
+            res.startBlock('<array>');
+
+            for (i = 0; i < cluster.includeEventTypes.length; i++) {
+                if (i > 0)
+                    res.line();
+
+                var eventGroup = cluster.includeEventTypes[i];
+
+                res.line('<!-- EventType.' + eventGroup + ' -->');
+
+                var eventList = dataStructures.eventGroups[eventGroup];
+
+                for (var k = 0; k < eventList.length; k++) {
+                    res.line('<util:constant static-field="org.apache.ignite.events.EventType.' + eventList[k] + '"/>')
+                }
+            }
+
+            res.endBlock('</array>');
+        }
+        
+        res.endBlock('</property>');
+
+        res.needEmptyLine = true;
+    }
+
+    // Generate marshaller group.
+    var marshaller = cluster.marshaller;
+
+    if (marshaller && marshaller.kind) {
+        var marshallerDesc = generatorUtils.marshallers[marshaller.kind];
+
+        addBeanWithProperties(res, marshaller[marshaller.kind], 'marshaller', marshallerDesc.className, marshallerDesc.fields, true);
+        res.needEmptyLine = true;
+    }
+
+    addProperty(res, cluster, 'marshalLocalJobs');
+    addProperty(res, cluster, 'marshallerCacheKeepAliveTime');
+    addProperty(res, cluster, 'marshallerCacheThreadPoolSize');
+    res.needEmptyLine = true;
+
+    // Generate metrics group.
+    addProperty(res, cluster, 'metricsExpireTime');
+    addProperty(res, cluster, 'metricsHistorySize');
+    addProperty(res, cluster, 'metricsLogFrequency');
+    addProperty(res, cluster, 'metricsUpdateFrequency');
+    res.needEmptyLine = true;
+
+    // Generate PeerClassLoading group.
+    addProperty(res, cluster, 'peerClassLoadingEnabled');
+    addListProperty(res, cluster, 'peerClassLoadingLocalClassPathExclude');
+    addProperty(res, cluster, 'peerClassLoadingMissedResourcesCacheSize');
+    addProperty(res, cluster, 'peerClassLoadingThreadPoolSize');
+    res.needEmptyLine = true;
+
+    // Generate swap group.
+    if (cluster.swapSpaceSpi && cluster.swapSpaceSpi.kind == 'FileSwapSpaceSpi') {
+        addBeanWithProperties(res, cluster.swapSpaceSpi.FileSwapSpaceSpi, 'swapSpaceSpi',
+            generatorUtils.swapSpaceSpi.className, generatorUtils.swapSpaceSpi.fields, true);
+
+        res.needEmptyLine = true;
+    }
+
+    // Generate time group.
+    addProperty(res, cluster, 'clockSyncSamples');
+    addProperty(res, cluster, 'clockSyncFrequency');
+    addProperty(res, cluster, 'timeServerPortBase');
+    addProperty(res, cluster, 'timeServerPortRange');
+    res.needEmptyLine = true;
+
+    // Generate thread pools group.
+    addProperty(res, cluster, 'publicThreadPoolSize');
+    addProperty(res, cluster, 'systemThreadPoolSize');
+    addProperty(res, cluster, 'managementThreadPoolSize');
+    addProperty(res, cluster, 'igfsThreadPoolSize');
+    res.needEmptyLine = true;
+
+    // Generate transactions group.
+    addBeanWithProperties(res, cluster.transactionConfiguration, 'transactionConfiguration',
+        generatorUtils.transactionConfiguration.className, generatorUtils.transactionConfiguration.fields);
+    res.needEmptyLine = true;
+
+    // Generate caches configs.
+    if (cluster.caches && cluster.caches.length > 0) {
+        res.emptyLineIfNeeded();
+
+        res.startBlock('<property name="cacheConfiguration">');
+        res.startBlock('<list>');
+
+        for (var i = 0; i < cluster.caches.length; i++) {
+            if (i > 0)
+                res.line();
+
+            var cache = cluster.caches[i];
+
+            generateCacheConfiguration(cache, res);
+        }
+
+        res.endBlock('</list>');
+        res.endBlock('</property>');
+
+        res.needEmptyLine = true;
+    }
+
+    res.endBlock('</bean>');
+
+    // Build final XML:
+    // 1. Add header.
+    var xml = '<?xml version="1.0" encoding="UTF-8"?>\n\n';
+
+    xml += '<!-- ' + generatorUtils.mainComment() + ' -->\n';
+    xml += '<beans xmlns="http://www.springframework.org/schema/beans"\n';
+    xml += '       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n';
+    xml += '       xmlns:util="http://www.springframework.org/schema/util"\n';
+    xml += '       xsi:schemaLocation="http://www.springframework.org/schema/beans\n';
+    xml += '                           http://www.springframework.org/schema/beans/spring-beans.xsd\n';
+    xml += '                           http://www.springframework.org/schema/util\n';
+    xml += '                           http://www.springframework.org/schema/util/spring-util.xsd">\n';
+
+    // 2. Add external property file and all data sources.
+    if (res.datasources.length > 0) {
+        xml += '    <!-- Load external properties file. -->\n';
+        xml += '    <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">\n';
+        xml += '        <property name="location" value="classpath:secret.properties"/>\n';
+        xml += '    </bean>\n\n';
+
+        xml += '    <!-- Data source beans will be initialized from external properties file. -->\n';
+
+        _.forEach(res.datasources, function(item) {
+            var beanId = item.dataSourceBean;
+
+            xml += '    <bean id= "' + beanId + '" class="' + item.className + '">\n';
+            xml += '        <property name="URL" value="${' + beanId + '.jdbc.url}" />\n';
+            xml += '        <property name="user" value="${' + beanId + '.jdbc.username}" />\n';
+            xml += '        <property name="password" value="${' + beanId + '.jdbc.password}" />\n';
+            xml += '    </bean>\n\n';
+        });
+    }
+
+    // 3. Add main content.
+    xml += res.join('');
+
+    // 4. Add footer.
+    xml += '</beans>\n';
+
+    return xml;
+};
+
+function createEvictionPolicy(res, evictionPolicy, propertyName) {
+    if (evictionPolicy && evictionPolicy.kind) {
+        var e = generatorUtils.evictionPolicies[evictionPolicy.kind];
+
+        var obj = evictionPolicy[evictionPolicy.kind.toUpperCase()];
+
+        addBeanWithProperties(res, obj, propertyName, e.className, e.fields, true);
+    }
+}
+
+function generateCacheConfiguration(cacheCfg, res) {
+    if (!res)
+        res = generatorUtils.builder();
+
+    res.startBlock('<bean class="org.apache.ignite.configuration.CacheConfiguration">');
+
+    addProperty(res, cacheCfg, 'name');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'mode', 'cacheMode');
+
+    addProperty(res, cacheCfg, 'atomicityMode');
+    addProperty(res, cacheCfg, 'backups');
+    addProperty(res, cacheCfg, 'startSize');
+    addProperty(res, cacheCfg, 'readFromBackup');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'memoryMode');
+    addProperty(res, cacheCfg, 'offHeapMaxMemory');
+    addProperty(res, cacheCfg, 'swapEnabled');
+    addProperty(res, cacheCfg, 'copyOnRead');
+
+    res.needEmptyLine = true;
+
+    createEvictionPolicy(res, cacheCfg.evictionPolicy, 'evictionPolicy');
+
+    res.needEmptyLine = true;
+
+    if (cacheCfg.nearCacheEnabled) {
+        res.emptyLineIfNeeded();
+
+        res.startBlock('<property name="nearConfiguration">');
+        res.startBlock('<bean class="org.apache.ignite.configuration.NearCacheConfiguration">');
+
+        if (cacheCfg.nearConfiguration && cacheCfg.nearConfiguration.nearStartSize)
+            addProperty(res, cacheCfg.nearConfiguration, 'nearStartSize');
+
+        if (cacheCfg.nearConfiguration && cacheCfg.nearConfiguration.nearEvictionPolicy.kind)
+            createEvictionPolicy(res, cacheCfg.nearConfiguration.nearEvictionPolicy, 'nearEvictionPolicy');
+
+        res.endBlock('</bean>');
+        res.endBlock('</property>');
+    }
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'sqlEscapeAll');
+    addProperty(res, cacheCfg, 'sqlOnheapRowCacheSize');
+    addProperty(res, cacheCfg, 'longQueryWarningTimeout');
+
+    if (cacheCfg.indexedTypes && cacheCfg.indexedTypes.length > 0) {
+        res.startBlock('<property name="indexedTypes">');
+        res.startBlock('<list>');
+
+        for (var i = 0; i < cacheCfg.indexedTypes.length; i++) {
+            var pair = cacheCfg.indexedTypes[i];
+
+            res.line('<value>' + escape(pair.keyClass) + '</value>');
+            res.line('<value>' + escape(pair.valueClass) + '</value>');
+        }
+
+        res.endBlock('</list>');
+        res.endBlock('</property>');
+    }
+
+    addListProperty(res, cacheCfg, 'sqlFunctionClasses', 'array');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'rebalanceMode');
+    addProperty(res, cacheCfg, 'rebalanceThreadPoolSize');
+    addProperty(res, cacheCfg, 'rebalanceBatchSize');
+    addProperty(res, cacheCfg, 'rebalanceOrder');
+    addProperty(res, cacheCfg, 'rebalanceDelay');
+    addProperty(res, cacheCfg, 'rebalanceTimeout');
+    addProperty(res, cacheCfg, 'rebalanceThrottle');
+
+    res.needEmptyLine = true;
+
+    if (cacheCfg.cacheStoreFactory && cacheCfg.cacheStoreFactory.kind) {
+        var storeFactory = cacheCfg.cacheStoreFactory[cacheCfg.cacheStoreFactory.kind];
+        var data = generatorUtils.storeFactories[cacheCfg.cacheStoreFactory.kind];
+
+        addBeanWithProperties(res, storeFactory, 'cacheStoreFactory', data.className, data.fields, true);
+
+        if (storeFactory.dialect) {
+            if (_.findIndex(res.datasources, function (ds) {
+                    return ds.dataSourceBean == storeFactory.dataSourceBean;
+                }) < 0) {
+                res.datasources.push({
+                    dataSourceBean: storeFactory.dataSourceBean,
+                    className: generatorUtils.dataSources[storeFactory.dialect]
+                });
+            }
+        }
+    }
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'loadPreviousValue');
+    addProperty(res, cacheCfg, 'readThrough');
+    addProperty(res, cacheCfg, 'writeThrough');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'invalidate');
+    addProperty(res, cacheCfg, 'defaultLockTimeout');
+    addProperty(res, cacheCfg, 'transactionManagerLookupClassName');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'writeBehindEnabled');
+    addProperty(res, cacheCfg, 'writeBehindBatchSize');
+    addProperty(res, cacheCfg, 'writeBehindFlushSize');
+    addProperty(res, cacheCfg, 'writeBehindFlushFrequency');
+    addProperty(res, cacheCfg, 'writeBehindFlushThreadCount');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'statisticsEnabled');
+    addProperty(res, cacheCfg, 'managementEnabled');
+
+    res.needEmptyLine = true;
+
+    addProperty(res, cacheCfg, 'maxConcurrentAsyncOperations');
+    
+    res.endBlock('</bean>');
+
+    return res;
+}
+
+exports.generateCacheConfiguration = generateCacheConfiguration;
+
+function addProperty(res, obj, propName, setterName) {
+    var val = obj[propName];
+
+    if (generatorUtils.isDefined(val)) {
+        res.emptyLineIfNeeded();
+
+        res.line('<property name="' + (setterName ? setterName : propName) + '" value="' + escapeAttr(val) + '"/>');
+    }
+}
+
+function addBeanWithProperties(res, bean, beanPropName, beanClass, props, createBeanAlthoughNoProps) {
+    if (bean && generatorUtils.hasProperty(bean, props)) {
+        res.emptyLineIfNeeded();
+        res.startBlock('<property name="' + beanPropName + '">');
+        res.startBlock('<bean class="' + beanClass + '">');
+
+        for (var propName in props) {
+            if (props.hasOwnProperty(propName)) {
+                var descr = props[propName];
+
+                if (descr) {
+                    if (descr.type == 'list') {
+                        addListProperty(res, bean, propName, descr.setterName);
+                    }
+                    else if (descr.type == 'className') {
+                        if (bean[propName]) {
+                            res.startBlock('<property name="' + propName + '">');
+                            res.line('<bean class="' + generatorUtils.knownClasses[bean[propName]].className + '"/>');
+                            res.endBlock('</property>');
+                        }
+                    }
+                    else if (descr.type == 'propertiesAsList') {
+                        var val = bean[propName];
+
+                        if (val && val.length > 0) {
+                            res.startBlock('<property name="' + propName + '">');
+                            res.startBlock('<props>');
+
+                            for (var i = 0; i < val.length; i++) {
+                                var nameAndValue = val[i];
+
+                                var eqIndex = nameAndValue.indexOf('=');
+                                if (eqIndex >= 0) {
+                                    res.line('<prop key="' + escapeAttr(nameAndValue.substring(0, eqIndex)) + '">' +
+                                            + escape(nameAndValue.substr(eqIndex + 1)) + '</prop>');
+                                }
+                            }
+
+                            res.endBlock('</props>');
+                            res.endBlock('</property>');
+                        }
+                    }
+                    else
+                        addProperty(res, bean, propName, descr.setterName);
+                }
+                else
+                    addProperty(res, bean, propName);
+            }
+        }
+
+        res.endBlock('</bean>');
+        res.endBlock('</property>');
+    }
+    else if (createBeanAlthoughNoProps) {
+        res.emptyLineIfNeeded();
+        res.line('<property name="' + beanPropName + '">');
+        res.line('    <bean class="' + beanClass + '"/>');
+        res.line('</property>');
+    }
+}
+function addListProperty(res, obj, propName, listType, rowFactory) {
+    var val = obj[propName];
+
+    if (val && val.length > 0) {
+        res.emptyLineIfNeeded();
+
+        if (!listType)
+            listType = 'list';
+
+        if (!rowFactory)
+            rowFactory = function(val) { return '<value>' + escape(val) + '</value>' };
+
+        res.startBlock('<property name="' + propName + '">');
+        res.startBlock('<' + listType + '>');
+
+        for (var i = 0; i < val.length; i++)
+            res.line(rowFactory(val[i]));
+
+        res.endBlock('</' + listType + '>');
+        res.endBlock('</property>');
+    }
+}
+
+function escapeAttr(s) {
+    if (typeof(s) != 'string')
+        return s;
+
+    return s.replace(/&/g, '&amp;').replace(/"/g, '&quot;');
+}
+
+function escape(s) {
+    if (typeof(s) != 'string')
+        return s;
+
+    return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+}