http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/96522874/modules/control-center-web/src/main/js/public/stylesheets/style.scss ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/public/stylesheets/style.scss b/modules/control-center-web/src/main/js/public/stylesheets/style.scss new file mode 100644 index 0000000..e2542ce --- /dev/null +++ b/modules/control-center-web/src/main/js/public/stylesheets/style.scss @@ -0,0 +1,1270 @@ +/* + * 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: 20px 0; +} + +.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: 100%; + 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; + + 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 table.links { + 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 table.links; + + margin-top: 5px; + margin-bottom: 5px; + + label { + line-height: $input-height; + color: #666; + } +} + +.theme-line table.links-edit-details { + @extend table.links; + + 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; + } + } + } +} + +.theme-line table.sql-results { + [class*="col-"] { + padding-left: 0 !important; + padding-right: 0 !important; + } + + td { + padding: 3px 6px; + } + + > thead > tr > td { + padding: 3px 0; + } + + thead > tr > th { + padding: 3px 6px; + + line-height: $input-height; + } +} + +.panel-title a { + font-size: 14px; +} + +.panel-details { + margin-top: 10px; + + padding: 0; + + border-radius: 5px; + border: thin dotted lightgrey; +} + +.table-details { + border-radius: 5px; + border: thin dotted lightgrey; + + margin-top: 10px; + + padding-left: 10px; + padding-right: 5px; +} + +.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 table.links; + + 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; +} + +.nav-tabs > 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 10px; + 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 { + margin: 0.65em 0 0 0; + + width: 100%; + height: 400px; + + .ace_gutter { + background: transparent !important; + border: 1px #ddd; + border-right-style: solid; + } + + .ace_gutter-cell, .ace_folding-enabled > .ace_gutter-cell { + padding-left: 0.65em; + padding-right: 0.9em; + } +} + +.loading-indicator { + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + width: 100%; + text-align: center; + padding: 0.7em; + + :before { + display: inline-block; + margin: 0 0.4em; + min-width: 1em; + min-height: 1em; + border: 4px solid #646464; + border-right-color: #e6e6e6; + border-left-color: #e6e6e6; + content: ""; + -webkit-animation: halfspin 1s ease infinite; + -moz-animation: halfspin 1s ease infinite; + -o-animation: halfspin 1s ease infinite; + animation: halfspin 1s ease infinite; + border-radius: 100%; + } +} + +@-webkit-keyframes halfspin { + to { + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + transform: rotate(180deg); + } +} + +@-moz-keyframes halfspin { + to { + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + transform: rotate(180deg); + } +} + +@keyframes halfspin { + to { + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + transform: rotate(180deg); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/96522874/modules/control-center-web/src/main/js/routes/admin.js ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/routes/admin.js b/modules/control-center-web/src/main/js/routes/admin.js new file mode 100644 index 0000000..5af72f7 --- /dev/null +++ b/modules/control-center-web/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/96522874/modules/control-center-web/src/main/js/routes/caches.js ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/routes/caches.js b/modules/control-center-web/src/main/js/routes/caches.js new file mode 100644 index 0000000..24152af --- /dev/null +++ b/modules/control-center-web/src/main/js/routes/caches.js @@ -0,0 +1,105 @@ +/* + * 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 type metadata for spaces. + db.CacheTypeMetadata.find({space: {$in: space_ids}}, '_id name kind', function (err, metadatas) { + if (err) + return res.status(500).send(err); + + // 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); + + var metadatasJson = metadatas.map(function (meta) { + return {value: meta._id, label: meta.name, kind: meta.kind}; + }); + + res.json({spaces: spaces, metadatas: metadatasJson, 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({space: req.body.space, 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/96522874/modules/control-center-web/src/main/js/routes/clusters.js ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/routes/clusters.js b/modules/control-center-web/src/main/js/routes/clusters.js new file mode 100644 index 0000000..683630e --- /dev/null +++ b/modules/control-center-web/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({space: req.body.space, 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/96522874/modules/control-center-web/src/main/js/routes/generator/common.js ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/routes/generator/common.js b/modules/control-center-web/src/main/js/routes/generator/common.js new file mode 100644 index 0000000..44ddf31 --- /dev/null +++ b/modules/control-center-web/src/main/js/routes/generator/common.js @@ -0,0 +1,312 @@ +/* + * 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', {}) +}; + +var javaBuildInClasses = { + BigDecimal: {className: 'java.math.Boolean'}, + Boolean: {className: 'java.lang.Boolean'}, + Byte: {className: 'java.lang.Byte'}, + Date: {className: 'java.sql.Date'}, + Double: {className: 'java.lang.Double'}, + Float: {className: 'java.lang.Float'}, + Integer: {className: 'java.lang.Integer'}, + Long: {className: 'java.lang.Long'}, + Short: {className: 'java.lang.Short'}, + String: {className: 'java.lang.String'}, + Time: {className: 'java.sql.Time'}, + Timestamp: {className: 'java.sql.Timestamp'}, + UUID: {className: 'java.util.UUID'} +}; + +exports.javaBuildInClass = function (className) { + var fullClassName = javaBuildInClasses[className]; + + if (fullClassName) + return fullClassName.className; + + return className; +}; + +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; +}; + +/** + * 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/96522874/modules/control-center-web/src/main/js/routes/generator/docker.js ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/routes/generator/docker.js b/modules/control-center-web/src/main/js/routes/generator/docker.js new file mode 100644 index 0000000..93faf8e --- /dev/null +++ b/modules/control-center-web/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/96522874/modules/control-center-web/src/main/js/routes/generator/java.js ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/routes/generator/java.js b/modules/control-center-web/src/main/js/routes/generator/java.js new file mode 100644 index 0000000..41b9bb8 --- /dev/null +++ b/modules/control-center-web/src/main/js/routes/generator/java.js @@ -0,0 +1,788 @@ +/* + * 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"); + +/** + * Convert some name to valid java name. + * + * @param name to convert. + * @returns {string} Valid java name. + */ +function toJavaName(name) { + var javaName = name.replace(/[^A-Za-z_0-9]+/, '_'); + + return javaName.charAt(0).toLocaleUpperCase() + javaName.slice(1); +} + +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' + toJavaName(cache.name); + + names.push(cacheName); + + generateCacheConfiguration(res, cache, cacheName); + + 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); + } +} + +function addCacheTypeMetadataDatabaseFields(res, meta, varName, fieldsProperty) { + var fields = meta[fieldsProperty]; + + if (fields && fields.length > 0) { + res.line('addCacheTypeMetadataDatabaseFields for ' + varName); + //res.startBlock('<property name="' + fieldsProperty + '">'); + // + //res.startBlock('<list>'); + // + //_.forEach(fields, function (field) { + // res.startBlock('<bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">'); + // + // addProperty(res, field, 'databaseName'); + // + // res.startBlock('<property name="databaseType">'); + // res.line('<util:constant static-field="java.sql.Types.' + field.databaseType + '"/>'); + // res.endBlock('</property>'); + // + // addProperty(res, field, 'javaName'); + // + // addElement(res, 'property', 'name', 'javaType', 'value', generatorUtils.javaBuildInClass(field.javaType)); + // + // res.endBlock('</bean>'); + //}); + // + //res.endBlock('</list>'); + //res.endBlock('</property>'); + } +} + +function addCacheTypeMetadataQueryFields(res, meta, varName, fieldsProperty) { + var fields = meta[fieldsProperty]; + + if (fields && fields.length > 0) { + res.line('addCacheTypeMetadataQueryFields for ' + varName); + //res.startBlock('<property name="' + fieldsProperty + '">'); + // + //res.startBlock('<map>'); + // + //_.forEach(fields, function (field) { + // addElement(res, 'entry', 'key', field.name, 'value', generatorUtils.javaBuildInClass(field.className)); + //}); + // + //res.endBlock('</map>'); + // + //res.endBlock('</property>'); + } +} + +function addCacheTypeMetadataGroups(res, meta, varName) { + var groups = meta.groups; + + if (groups && groups.length > 0) { + res.line('addCacheTypeMetadataGroups for ' + varName); + //res.startBlock('<property name="groups">'); + //res.startBlock('<map>'); + // + //_.forEach(groups, function (group) { + // var fields = group.fields; + // + // if (fields && fields.length > 0) { + // res.startBlock('<entry key="' + group.name + '">'); + // res.startBlock('<map>'); + // + // _.forEach(fields, function (field) { + // res.startBlock('<entry key="' + field.name + '">'); + // + // res.startBlock('<bean class="org.apache.ignite.lang.IgniteBiTuple">'); + // res.line('<constructor-arg value="' + generatorUtils.javaBuildInClass(field.className) + '"/>'); + // res.line('<constructor-arg value="' + field.direction + '"/>'); + // res.endBlock('</bean>'); + // + // res.endBlock('</entry>'); + // }); + // + // res.endBlock('</map>'); + // res.endBlock('</entry>'); + // } + //}); + // + //res.endBlock('</map>'); + //res.endBlock('</property>'); + } +} + +function generateCacheTypeMetadataConfiguration(res, meta, varCacheTypeMetadata) { + if (!res) + res = generatorUtils.builder(); + + res.importClass('org.apache.ignite.cache.CacheTypeMetadata'); + + var varType = varCacheTypeMetadata + 'Item'; + + addProperty(res, meta, varType, 'databaseSchema'); + addProperty(res, meta, varType, 'databaseTable'); + + addProperty(res, meta, varType, 'keyType'); + addProperty(res, meta, varType, 'valueType'); + + addCacheTypeMetadataDatabaseFields(res, meta, varType, 'keyFields'); + addCacheTypeMetadataDatabaseFields(res, meta, varType, 'valueFields'); + + addCacheTypeMetadataQueryFields(res, meta, varType, 'queryFields'); + addCacheTypeMetadataQueryFields(res, meta, varType, 'ascendingFields'); + addCacheTypeMetadataQueryFields(res, meta, varType, 'descendingFields'); + + addListProperty(res, meta, varType, 'textFields'); + + addCacheTypeMetadataGroups(res, varType, meta); + + res.line(varCacheTypeMetadata + '.add(' + varType + ')'); + + return res; +} + +/** + * Generate java code for cache configuration. + * + * @param cache Cache config. + * @param varName Variable name. + * @param res Result builder. + * @returns {*} Append generated java code to builder and return it. + */ +function generateCacheConfiguration(res, cache, varName) { + 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, cache, varName, 'name'); + + addProperty(res, cache, varName, 'mode', 'CacheMode', 'cacheMode'); + + addProperty(res, cache, varName, 'atomicityMode', 'CacheAtomicityMode'); + addProperty(res, cache, varName, 'backups'); + addProperty(res, cache, varName, 'startSize'); + addProperty(res, cache, varName, 'readFromBackup'); + + res.needEmptyLine = true; + + addProperty(res, cache, varName, 'memoryMode', 'CacheMemoryMode'); + addProperty(res, cache, varName, 'offHeapMaxMemory'); + addProperty(res, cache, varName, 'swapEnabled'); + addProperty(res, cache, varName, 'copyOnRead'); + + res.needEmptyLine = true; + + createEvictionPolicy(res, cache.evictionPolicy, varName, 'evictionPolicy'); + + if (cache.nearCacheEnabled) { + res.needEmptyLine = true; + + res.importClass('org.apache.ignite.configuration.NearCacheConfiguration'); + + addBeanWithProperties(res, cache.nearConfiguration, varName, 'nearConfiguration', 'nearConfiguration', + 'NearCacheConfiguration', {nearStartSize: null}, true); + + if (cache.nearConfiguration && cache.nearConfiguration.nearEvictionPolicy && cache.nearConfiguration.nearEvictionPolicy.kind) { + createEvictionPolicy(res, cache.nearConfiguration.nearEvictionPolicy, 'nearConfiguration', 'nearEvictionPolicy'); + } + } + + res.needEmptyLine = true; + + addProperty(res, cache, varName, 'sqlEscapeAll'); + addProperty(res, cache, varName, 'sqlOnheapRowCacheSize'); + addProperty(res, cache, varName, 'longQueryWarningTimeout'); + + if (cache.indexedTypes && cache.indexedTypes.length > 0) { + res.emptyLineIfNeeded(); + + res.append(varName + '.setIndexedTypes('); + + for (var i = 0; i < cache.indexedTypes.length; i++) { + if (i > 0) + res.append(', '); + + var pair = cache.indexedTypes[i]; + + res.append(toJavaCode(pair.keyClass, 'class')).append(', ').append(toJavaCode(pair.valueClass, 'class')) + } + + res.line(');'); + } + + addMultiparamProperty(res, cache, varName, 'sqlFunctionClasses', 'class'); + + res.needEmptyLine = true; + + addProperty(res, cache, varName, 'rebalanceMode', 'CacheRebalanceMode'); + addProperty(res, cache, varName, 'rebalanceThreadPoolSize'); + addProperty(res, cache, varName, 'rebalanceBatchSize'); + addProperty(res, cache, varName, 'rebalanceOrder'); + addProperty(res, cache, varName, 'rebalanceDelay'); + addProperty(res, cache, varName, 'rebalanceTimeout'); + addProperty(res, cache, varName, 'rebalanceThrottle'); + + res.needEmptyLine = true; + + if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind) { + var storeFactory = cache.cacheStoreFactory[cache.cacheStoreFactory.kind]; + var data = generatorUtils.storeFactories[cache.cacheStoreFactory.kind]; + + var sfVarName = 'storeFactory' + toJavaName(cache.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, cache, varName, 'loadPreviousValue'); + addProperty(res, cache, varName, 'readThrough'); + addProperty(res, cache, varName, 'writeThrough'); + + res.needEmptyLine = true; + + addProperty(res, cache, varName, 'invalidate'); + addProperty(res, cache, varName, 'defaultLockTimeout'); + addProperty(res, cache, varName, 'transactionManagerLookupClassName'); + + res.needEmptyLine = true; + + addProperty(res, cache, varName, 'writeBehindEnabled'); + addProperty(res, cache, varName, 'writeBehindBatchSize'); + addProperty(res, cache, varName, 'writeBehindFlushSize'); + addProperty(res, cache, varName, 'writeBehindFlushFrequency'); + addProperty(res, cache, varName, 'writeBehindFlushThreadCount'); + + res.needEmptyLine = true; + + addProperty(res, cache, varName, 'statisticsEnabled'); + addProperty(res, cache, varName, 'managementEnabled'); + + res.needEmptyLine = true; + + addProperty(res, cache, varName, 'maxConcurrentAsyncOperations'); + + res.needEmptyLine = true; + + // Generate cache type metadata configs. + if ((cache.queryMetadata && cache.queryMetadata.length > 0) || + (cache.storeMetadata && cache.storeMetadata.length > 0)) { + res.emptyLineIfNeeded(); + + var varCacheTypeMetadata = varName + 'TypeMetadata'; + + res.line('Collection ' + varCacheTypeMetadata + ' = new ArrayList();'); + res.line(); + + var metaNames = []; + + if (cache.queryMetadata && cache.queryMetadata.length > 0) { + _.forEach(cache.queryMetadata, function (meta) { + if (!_.contains(metaNames, meta.name)) { + metaNames.push(meta.name); + + generateCacheTypeMetadataConfiguration(res, meta, varCacheTypeMetadata); + } + }); + } + + if (cache.storeMetadata && cache.storeMetadata.length > 0) { + _.forEach(cache.storeMetadata, function (meta) { + if (!_.contains(metaNames, meta.name)) { + metaNames.push(meta.name); + + generateCacheTypeMetadataConfiguration(meta, res); + } + }); + } + + res.line(varName + '.setCacheTypeMetadata(' + varCacheTypeMetadata + ');'); + } + + 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 + '());'); + } +}