Major refactoring of page and navigation

This commit is contained in:
Ziver Koc 2016-07-22 21:37:51 +02:00
parent bb546ce046
commit 3a0f40dab9
25 changed files with 353 additions and 669 deletions

View file

@ -6,17 +6,17 @@
<title>WebAdmin</title>
<!-- CSS -->
<link href="css/magic-bootstrap.css" rel="stylesheet">
<link href="css/bootstrap-switch.min.css" rel="stylesheet">
<link href="css/main.css" rel="stylesheet">
<link href="/css/magic-bootstrap.css" rel="stylesheet">
<link href="/css/bootstrap-switch.min.css" rel="stylesheet">
<link href="/css/main.css" rel="stylesheet">
<!-- Javascript -->
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/bootstrap-table.min.js"></script>
<script src="js/Chart.min.js"></script>
<script src="js/bootstrap-switch.min.js"></script>
<script src="/js/jquery.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
<script src="/js/bootstrap-table.min.js"></script>
<script src="/js/Chart.min.js"></script>
<script src="/js/bootstrap-switch.min.js"></script>
<script>
$(function() {
@ -32,7 +32,7 @@
{{#top-nav}}
{{^.getSubNavs().length}}
<li class="{{#.isActive()}}active{{/.isActive()}}">
<a href="{{.getUrl()}}">{{.getName()}}</a>
<a href="{{.getURL()}}">{{.getName()}}</a>
</li>
{{/.getSubNavs().length}}
{{#.getSubNavs().length}}
@ -42,7 +42,7 @@
</a>
<ul class="dropdown-menu">
{{#.getSubNavs()}}
<li><a href="{{.getUrl()}}">{{.getName()}}</a></li>
<li><a href="{{.getURL()}}">{{.getName()}}</a></li>
{{/.getSubNavs()}}
</ul>
</li>
@ -98,7 +98,7 @@
{{#side-nav}}
{{^.getSubNavs().length}}
<li class="{{#.isActive()}}active{{/.isActive()}}">
<a href="{{.getUrl()}}">{{.getName()}}</a>
<a href="{{.getURL()}}">{{.getName()}}</a>
</li>
{{/.getSubNavs().length}}
{{#.getSubNavs().length}}
@ -124,7 +124,7 @@
<div class="row">
<ol class="breadcrumb">
{{#breadcrumb}}
<li><a href="{{.getUrl()}}">{{.getName()}}</a></li>
<li><a href="{{.getURL()}}">{{.getName()}}</a></li>
{{/breadcrumb}}
</ol>
</div>

View file

@ -22,20 +22,16 @@
package wa.server;
import com.sun.beans.editors.IntegerEditor;
import wa.server.page.struct.WAAlert;
import wa.server.page.struct.WANavigation;
import zutil.db.DBConnection;
import zutil.db.DBUpgradeHandler;
import zutil.db.SQLResultHandler;
import zutil.db.handler.SimpleSQLResult;
import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
import zutil.net.http.HttpHeader;
import zutil.ui.Navigation;
import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -47,20 +43,20 @@ import java.util.logging.Logger;
*/
public class WAContext {
private static final Logger logger = LogUtil.getLogger();
private static WANavigation rootNav;
private static Navigation rootNav;
public static DBConnection db;
private ArrayList<WAAlert> alerts;
// Navigation
private WANavigation.NavInstance navInstance;
private List<WANavigation> breadcrumb;
private Navigation.NavInstance navInstance;
private List<Navigation> breadcrumb;
public WAContext(Map<String, String> request){
public WAContext(HttpHeader header){
// Navigation
navInstance = rootNav.createNavInstance(request);
navInstance = rootNav.createPagedNavInstance(header);
// Breadcrumb
breadcrumb = WANavigation.getBreadcrumb(request);
breadcrumb = Navigation.getBreadcrumb(Navigation.getPagedNavigation(header));
if(!breadcrumb.isEmpty())
breadcrumb.remove(0);
}
@ -69,10 +65,10 @@ public class WAContext {
public ArrayList<WAAlert> getAlerts() {
return alerts;
}
public WANavigation.NavInstance getNavigationInstance(){
public Navigation.NavInstance getNavigationInstance(){
return navInstance;
}
public List<WANavigation> getBreadcrumb(){
public List<Navigation> getBreadcrumb(){
return breadcrumb;
}
@ -81,7 +77,7 @@ public class WAContext {
protected static void initialize(){
try {
rootNav = WANavigation.createRootNav();
rootNav = Navigation.createRootNav();
// Setup DB
@ -120,7 +116,7 @@ public class WAContext {
public static DBConnection getDB(){
return db;
}
public static WANavigation getRootNav(){
public static Navigation getRootNav(){
return rootNav;
}

View file

@ -1,5 +1,6 @@
package wa.server;
import wa.server.plugin.WAPage;
import zutil.io.file.FileUtil;
import zutil.log.CompactLogFormatter;
import zutil.log.LogUtil;
@ -7,14 +8,13 @@ import zutil.net.http.HttpServer;
import zutil.net.http.page.HttpFilePage;
import zutil.plugin.PluginManager;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WebAdminServer {
private static Logger log = LogUtil.getLogger();
private PluginManager pluginManager;
public static void main(String[] args){
LogUtil.setGlobalLevel(Level.FINEST);
@ -26,14 +26,14 @@ public class WebAdminServer {
public WebAdminServer(){
try {
WAContext.initialize();
pluginManager = new PluginManager();
PluginManager pluginManager = new PluginManager();
HttpServer http = new HttpServer(80);
http.setPage("/", new WAAbstractPage(pluginManager));
//http.setPage("status", new StatusPage(pluginManager));
//http.setPage("service", new ServicePage(pluginManager));
//http.setPage("servicestatus", new ServiceStatusPage(pluginManager));
//http.setPage("config", new ConfigPage(pluginManager));
for (Iterator<WAPage> it = pluginManager.getObjectIterator(WAPage.class); it.hasNext(); ){
WAPage page = it.next();
if (page.getPageName() != null)
http.setPage(page.getPageName(), page);
}
http.setDefaultPage(new HttpFilePage(FileUtil.find("WebContent/")));
http.start();

View file

@ -24,6 +24,7 @@ package wa.server.page;
import wa.server.WAContext;
import wa.server.plugin.WAConfigEntry;
import wa.server.plugin.WAPage;
import wa.server.plugin.WAServiceConfig;
import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
@ -45,7 +46,7 @@ import java.util.logging.Logger;
*
* Created by Ziver on 2015-07-27.
*/
public class ConfigPage implements WAPage{
public class ConfigPage extends WAPage {
private static final Logger log = LogUtil.getLogger();
private static final String TMPL_FILE = "WebContent/page/ConfigPage.tmpl";
@ -75,13 +76,9 @@ public class ConfigPage implements WAPage{
Configurator<WAConfigEntry> target = findObj(confList, index);
switch (request.get("action")){
case "create":
target = new Configurator(config.createConfig());
target = new Configurator(config.createConfig()).applyConfiguration();
case "modify":
for(Configurator.ConfigurationParam param : target.getConfiguration()){
if(request.containsKey(param.getName()))
param.setValue(request.get(param.getName()));
}
target.applyConfiguration();
target.setValues(request).applyConfiguration();
break;
case "delete":
config.deleteConfig(index);

View file

@ -42,7 +42,7 @@ import java.util.logging.LogRecord;
/**
* Created by Ziver on 2015-09-22.
*/
public class LogPage extends Handler implements HttpPage, WAPage {
public class LogPage extends Handler implements HttpPage {
private static final String TMPL_FILE = "WebContent/page/Log.tmpl";
private CircularBuffer<LogRecord> logBuffer;
@ -69,7 +69,7 @@ public class LogPage extends Handler implements HttpPage, WAPage {
}
@Override
//@Override
public Templator htmlResponse(WAContext context, HttpHeader client_info, Map<String, Object> session, Map<String, String> cookie, Map<String, String> request) {
try {
return new Templator(FileUtil.find(TMPL_FILE));
@ -92,10 +92,12 @@ public class LogPage extends Handler implements HttpPage, WAPage {
writer.write(jsonResponse());
writer.close();
}
@Override
//@Override
public DataNode jsonResponse(WAContext context, HttpHeader client_info, Map<String, Object> session, Map<String, String> cookie, Map<String, String> request) {
return jsonResponse();
}
public DataNode jsonResponse() {
DataNode logNode = new DataNode(DataNode.DataType.List);
Iterator<LogRecord> it = logBuffer.iterator();

View file

@ -23,15 +23,15 @@
package wa.server.page;
import wa.server.WAContext;
import wa.server.page.struct.WANavigation;
import wa.server.plugin.WAPage;
import wa.server.plugin.WAService;
import wa.server.plugin.WAServiceConfig;
import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
import zutil.net.http.HttpHeader;
import zutil.parser.DataNode;
import zutil.parser.Templator;
import zutil.plugin.PluginManager;
import zutil.ui.Navigation;
import java.io.IOException;
import java.util.ArrayList;
@ -42,31 +42,36 @@ import java.util.logging.Logger;
/**
* Created by Ziver on 2015-04-06.
*/
public class ServicePage implements WAPage {
public class ServicePage extends WAPage {
private static final Logger log = LogUtil.getLogger();
public static final String NAVIGATION_NAME = "Services";
private static final String TMPL_FILE = "WebContent/page/ServicePage.tmpl";
private ServiceStatusPage rootStatusPage;
private ArrayList<WAService> services;
private ArrayList<ServiceStatusPage> statusPages;
private ArrayList<LogPage> logPages;
private ArrayList<ConfigPage> configPages;
public ServicePage(PluginManager pluginManager){
public ServicePage(){
super.setPageName("service");
PluginManager pluginManager = new PluginManager();
this.services = pluginManager.toArray(WAService.class);
this.rootStatusPage = new ServiceStatusPage(pluginManager);
this.statusPages = new ArrayList<>();
this.logPages = new ArrayList<>();
this.configPages = new ArrayList<>();
WANavigation nav = WAContext.getRootNav().createSubNav(NAVIGATION_NAME);
Navigation nav = WAContext.getRootNav().createSubNav(this.getPageName(), NAVIGATION_NAME);
nav.setResource(this);
nav.setWeight(100);
for(WAService plugin : services) {
statusPages.add(new ServiceStatusPage(plugin.getStatus()));
logPages.add(new LogPage(plugin.getLog()));
WANavigation serviceNav = nav.createSubNav(plugin.getName());
Navigation serviceNav = nav.createSubNav(plugin.getName());
serviceNav.setResource(plugin);
for(WAServiceConfig conf : plugin.getConfigurations()){
ConfigPage page = new ConfigPage(conf);
@ -115,14 +120,6 @@ public class ServicePage implements WAPage {
return null;
}
public DataNode jsonResponse(WAContext context,
HttpHeader client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request){
return null;
}
}

View file

@ -23,7 +23,7 @@
package wa.server.page;
import wa.server.WAContext;
import wa.server.page.struct.WANavigation;
import wa.server.plugin.WAPage;
import wa.server.plugin.WAServiceStatus;
import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
@ -31,6 +31,7 @@ import zutil.net.http.HttpHeader;
import zutil.parser.DataNode;
import zutil.parser.Templator;
import zutil.plugin.PluginManager;
import zutil.ui.Navigation;
import java.io.IOException;
import java.util.ArrayList;
@ -41,7 +42,7 @@ import java.util.logging.Logger;
/**
* Created by Ziver on 2015-04-06.
*/
public class ServiceStatusPage implements WAPage {
public class ServiceStatusPage extends WAPage {
private static final Logger log = LogUtil.getLogger();
public static final String NAVIGATION_NAME = "Service Status";
private static final String TMPL_FILE = "WebContent/page/ServiceStatusPage.tmpl";
@ -56,7 +57,7 @@ public class ServiceStatusPage implements WAPage {
public ServiceStatusPage(PluginManager pluginManager){
this.services = pluginManager.toArray(WAServiceStatus.class);
WANavigation nav = WAContext.getRootNav().createSubNav(ServicePage.NAVIGATION_NAME)
Navigation nav = WAContext.getRootNav().createSubNav(ServicePage.NAVIGATION_NAME)
.createSubNav(NAVIGATION_NAME);
nav.setResource(this);
}

View file

@ -1,91 +0,0 @@
/*
* Copyright (c) 2015 Ziver
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package wa.server.page;
import wa.server.WAContext;
import wa.server.page.struct.WANavigation;
import wa.server.plugin.WAStatus;
import zutil.net.http.HttpHeader;
import zutil.parser.DataNode;
import zutil.parser.Templator;
import zutil.plugin.PluginManager;
import java.util.ArrayList;
import java.util.Map;
/**
* Created by Ziver on 2015-04-06.
*/
public class StatusPage implements WAPage {
public static final String NAVIGATION_NAME = "Status";
private ArrayList<WAStatus> plugins;
public StatusPage(PluginManager pluginManager){
this.plugins = pluginManager.toArray(WAStatus.class);
WANavigation nav = WAContext.getRootNav().createSubNav(NAVIGATION_NAME);
nav.setResource(this);
for(WAStatus plugin : plugins)
nav.createSubNav(plugin.getName()).setResource(plugin);
}
@Override
public Templator htmlResponse(WAContext context,
HttpHeader client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) {
WAStatus obj = getPlugin(context);
if(obj != null) {
return new Templator(obj.html());
}
return null;
}
public DataNode jsonResponse(WAContext context,
HttpHeader client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request){
// Do JSON request in all status plugins
DataNode root = new DataNode(DataNode.DataType.Map);
for(WAStatus obj : plugins) {
if (obj != null)
obj.jsonUpdate(request, root);
}
return root;
}
private WAStatus getPlugin(WAContext context){
if(context.getBreadcrumb().size() >= 2){
int i = plugins.indexOf(context.getBreadcrumb().get(1).getResource());
if(i >= 0)
return plugins.get(i);
}
return null;
}
}

View file

@ -1,49 +0,0 @@
/*
* Copyright (c) 2015 Ziver
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package wa.server.page;
import wa.server.WAContext;
import zutil.net.http.HttpHeader;
import zutil.parser.DataNode;
import zutil.parser.Templator;
import java.util.Map;
/**
* Created by Ziver on 2015-04-25.
*/
public interface WAPage {
public abstract Templator htmlResponse(WAContext context,
HttpHeader client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request);
public DataNode jsonResponse(WAContext context,
HttpHeader client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request);
}

View file

@ -1,230 +0,0 @@
/*
* Copyright (c) 2015 Ziver
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package wa.server.page.struct;
import java.util.*;
/**
* A class representing a navigation hierarchy/tree for a web application.
*
* Created by Ziver on 2015-04-02.
*/
public class WANavigation implements Iterable{
private static final String NAVIGATION_URL_KEY = "i";
private static int nextId = 0;
private static HashMap<Integer, WANavigation> navMap = new HashMap<Integer, WANavigation>();
private final int id;
private String url;
private String name;
private int weight;
private WANavigation parentNav;
private ArrayList<WANavigation> subNav;
private Object resource;
private WANavigation(String name) {
this.id = nextId++;
this.navMap.put(this.id, this);
this.url = "?"+NAVIGATION_URL_KEY+"="+this.id;
this.name = name;
this.subNav = new ArrayList<>();
}
public List<WANavigation> getSubNavs() {
return subNav;
}
/**
* Will create a new sub-nav if it does not already exist or return a existing one.
*/
public WANavigation createSubNav(String name) {
WANavigation nav = getSubNav(name);
if(nav != null)
return nav;
nav = new WANavigation(name);
nav.setParentNav(this);
subNav.add(nav);
sortSubNavs();
return nav;
}
/**
* Searches for and returns the specified sub-nav or returns null if it was not found.
*/
private WANavigation getSubNav(String name) {
for(WANavigation nav : subNav) {
if(nav.equals(name))
return nav;
}
return null;
}
private void sortSubNavs(){
Collections.sort(subNav, new Comparator<WANavigation>() {
@Override
public int compare(WANavigation o1, WANavigation o2) {
if (o1.weight == o2.weight)
return o1.name.compareToIgnoreCase(o2.name);
return o1.weight - o2.weight;
}
});
}
@Override
public Iterator iterator() {
return subNav.iterator();
}
public String getName(){
return name;
}
public String getUrl(){
return url;
}
private void setParentNav(WANavigation nav){
this.parentNav = nav;
}
/**
* Assign a resource object specific to this navigation object.
* This can be used if target page needs some additional information.
*/
public void setResource(Object obj){
resource = obj;
}
public Object getResource(){
return resource;
}
/**
* Sets the weight of this navigation object. The weight is
* used for deciding the order the parent will sort all sub navigation.
* Lower values will be at the top of sub-nav list.
*/
public void setWeight(int weightOrder){
this.weight = weightOrder;
if(parentNav != null)
parentNav.sortSubNavs();
}
@Override
public boolean equals(Object o){
if(o instanceof String)
return this.name.equals(o);
return this == o ||
(o != null && this.id == (((WANavigation)o).id));
}
/**
* Will create a clone of the navigation tree with some request instance specific information
*/
public NavInstance createNavInstance(Map<String, String> request){
return createNavInstance(getBreadcrumb(request));
}
private NavInstance createNavInstance(List<WANavigation> activeList){
NavInstance instance = new NavInstance(this);
instance.setActive(activeList.contains(this));
for (WANavigation nav : subNav)
instance.addSubNav(nav.createNavInstance(activeList));
return instance;
}
public static WANavigation createRootNav(){
return new WANavigation(null);
}
public static WANavigation getRootNav(Map<String, String> request) {
List<WANavigation> breadcrumb = getBreadcrumb(request);
if (!breadcrumb.isEmpty())
return breadcrumb.get(0);
return null;
}
/**
* @return the specific WANavigation object requested by client
*/
public static WANavigation getNavigation(Map<String, String> request) {
if(request.containsKey(NAVIGATION_URL_KEY))
return navMap.get(Integer.parseInt(request.get(NAVIGATION_URL_KEY)));
return null;
}
/**
* @param request A map of all url parameters sent from client
* @return a List of WANavigation objects depicting the navigation hierarchy for the
* requested page from the client. First entry will be the root navigation object.
*/
public static List<WANavigation> getBreadcrumb(Map<String, String> request) {
LinkedList list = new LinkedList();
WANavigation current = getNavigation(request);
if (current != null){
while(current != null){
list.addFirst(current);
current = current.parentNav;
}
}
return list;
}
public static class NavInstance{
private WANavigation nav;
private boolean active;
private ArrayList<NavInstance> subNavs;
protected NavInstance(WANavigation nav){
this.nav = nav;
this.subNavs = new ArrayList<>();
}
protected void setActive(boolean active){
this.active = active;
}
protected void addSubNav(NavInstance subNav){
subNavs.add(subNav);
}
public boolean isActive(){
return active;
}
public List<NavInstance> getSubNavs() { return subNavs; }
// Mirror getters from WANavigation
public String getName(){ return nav.getName(); }
public String getUrl(){ return nav.getUrl(); }
public Object getResource(){ return nav.getResource(); }
public boolean equals(Object o){
if (o instanceof WANavigation)
return nav.equals(o);
else if (o instanceof NavInstance)
return nav.equals(((NavInstance) o).nav);
return false;
}
}
}

5
src/wa/server/plugin.json Executable file
View file

@ -0,0 +1,5 @@
{
"version": "1.0",
"name": "WA Core",
"interfaces": [ ]
}

View file

@ -1,123 +1,130 @@
/*
* Copyright (c) 2015 Ziver
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package wa.server;
import wa.server.page.ServicePage;
import wa.server.page.StatusPage;
import wa.server.page.WAPage;
import wa.server.page.struct.WANavigation;
import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
import zutil.net.http.HttpHeader;
import zutil.net.http.HttpPage;
import zutil.net.http.HttpPrintStream;
import zutil.parser.DataNode;
import zutil.parser.Templator;
import zutil.parser.json.JSONWriter;
import zutil.plugin.PluginManager;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Created by Ziver on 2015-04-02.
*/
public class WAAbstractPage implements HttpPage{
private static final Logger log = LogUtil.getLogger();
private static final String TMPL_FILE = "WebContent/page/Index.tmpl";
private List<WAPage> pages;
private Templator tmpl;
public WAAbstractPage(PluginManager pluginManager) {
try {
pages = Arrays.asList(new WAPage[] {
new StatusPage(pluginManager),
new ServicePage(pluginManager)
});
tmpl = new Templator(FileUtil.find(TMPL_FILE));
} catch(IOException e){
log.log(Level.SEVERE, null, e);
tmpl = new Templator(e.getMessage());
}
}
@Override
public final synchronized void respond(HttpPrintStream out,
HttpHeader client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) throws IOException {
WAContext context = new WAContext(request);
List<WANavigation> breadcrumb = context.getBreadcrumb();
WAPage page = null;
if(breadcrumb.size() > 0){
int i = pages.indexOf(breadcrumb.get(0).getResource());
if(i >= 0)
page = pages.get(i);
}
if(("application/json").equals(client_info.getHeader("ContentType")) ||
request.containsKey("json")){
DataNode node = null;
if(page != null)
node = page.jsonResponse(context, client_info, session, cookie, request);
if(node != null) {
out.setHeader("Content-Type", "application/json");
JSONWriter writer = new JSONWriter(out);
writer.write(node);
writer.close();
}
}
else {
tmpl.clear();
tmpl.set("title", "WebAdmin");
tmpl.set("top-nav", context.getNavigationInstance().getSubNavs());
tmpl.set("side-nav-show", true);
if(!breadcrumb.isEmpty())
tmpl.set("side-nav", breadcrumb.get(0).createNavInstance(request).getSubNavs());
tmpl.set("breadcrumb", breadcrumb);
tmpl.set("alerts", context.getAlerts());
//tmpl.set("footer", null);
Templator content = null;
if(page != null)
content = page.htmlResponse(context, client_info, session, cookie, request);
if(content != null) {
if(!breadcrumb.isEmpty())
content.set("nav", breadcrumb.get(breadcrumb.size() - 1));
tmpl.set("content", content);
}
out.print(tmpl.compile());
}
}
}
/*
* Copyright (c) 2015 Ziver
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package wa.server.plugin;
import wa.server.WAContext;
import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
import zutil.net.http.HttpHeader;
import zutil.net.http.HttpPage;
import zutil.net.http.HttpPrintStream;
import zutil.parser.DataNode;
import zutil.parser.Templator;
import zutil.parser.json.JSONWriter;
import zutil.plugin.PluginManager;
import zutil.ui.Navigation;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Created by Ziver on 2015-04-25.
*/
public abstract class WAPage implements HttpPage{
private static final Logger log = LogUtil.getLogger();
private static final String TMPL_FILE = "WebContent/page/Index.tmpl";
private String pageName;
private Templator tmpl;
public WAPage() {
try {
tmpl = new Templator(FileUtil.find(TMPL_FILE));
} catch(IOException e){
log.log(Level.SEVERE, null, e);
tmpl = new Templator(e.getMessage());
}
}
@Override
public final void respond(HttpPrintStream out,
HttpHeader header,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) throws IOException {
WAContext context = new WAContext(header);
List<Navigation> breadcrumb = context.getBreadcrumb();
if(("application/json").equals(header.getHeader("ContentType")) ||
request.containsKey("json")){
DataNode node = this.jsonResponse(context, header, session, cookie, request);
if(node != null) {
out.setHeader("Content-Type", "application/json");
JSONWriter writer = new JSONWriter(out);
writer.write(node);
writer.close();
}
}
else {
tmpl.clear();
tmpl.set("title", "WebAdmin");
tmpl.set("top-nav", context.getNavigationInstance().getSubNavs());
tmpl.set("side-nav-show", true);
if(!breadcrumb.isEmpty())
tmpl.set("side-nav", breadcrumb.get(0).createPagedNavInstance(header).getSubNavs());
tmpl.set("breadcrumb", breadcrumb);
tmpl.set("alerts", context.getAlerts());
//tmpl.set("footer", null);
Templator content = this.htmlResponse(context, header, session, cookie, request);
if(content != null) {
if(!breadcrumb.isEmpty())
content.set("nav", breadcrumb.get(breadcrumb.size() - 1));
tmpl.set("content", content);
}
out.print(tmpl.compile());
}
}
public void setPageName(String pageName){
this.pageName = pageName;
}
public String getPageName(){
return pageName;
}
public abstract Templator htmlResponse(WAContext context,
HttpHeader client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) throws IOException;
public DataNode jsonResponse(WAContext context,
HttpHeader client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) {
return null;
}
}

View file

@ -2,25 +2,25 @@ package wa.server.plugin;
public interface WAService {
public String getName();
String getName();
/**
* @return a service status object or null if it is not possible to check status
*/
public WAServiceStatus getStatus();
WAServiceStatus getStatus();
/**
* @return a service log object or null if it is not possible to read logs
*/
public WALog getLog();
WALog getLog();
/**
* @return a installer object that will install the service or null if the installer is not available
*/
public WAInstaller getInstaller();
WAInstaller getInstaller();
/**
* @return a array of configuration objects
*/
public WAServiceConfig[] getConfigurations();
WAServiceConfig[] getConfigurations();
}

View file

@ -32,7 +32,7 @@ public interface WAServiceConfig {
/**
* @return a list of configuration objects, the object
* configuration can be changed with the
* {@link zutil.db.bean.Configurator} class.
* {@link zutil.ui.Configurator} class.
*/
public List<? extends WAConfigEntry> getConfigData();

View file

@ -1,39 +1,45 @@
/*
* Copyright (c) 2015 Ziver
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package wa.server.plugin;
import zutil.parser.DataNode;
import java.util.Map;
/**
* Created by Ziver on 2015-04-06.
*/
public interface WAStatus {
public String getName();
public String html();
public void jsonUpdate(Map<String, String> request, DataNode root);
}
/*
* Copyright (c) 2015 Ziver
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package wa.server.page;
import wa.server.WAContext;
import wa.server.plugin.WAPage;
/**
* Created by Ziver on 2015-04-06.
*/
public abstract class WAStatusPage extends WAPage {
public static final String NAVIGATION_NAME = "Status";
public WAStatusPage(String subPageName, String niceName){
super.setPageName("status/"+subPageName);
WAContext.getRootNav().createSubNav("status", NAVIGATION_NAME)
.setWeight(0).createSubNav(this.getPageName(), niceName);
}
}

View file

@ -47,12 +47,10 @@ public class ApacheConfigVirtualHost implements WAServiceConfig{
@Override
public void configure() throws Exception {
// Update main configuration file
FileInputStream in = new FileInputStream(STATIC_PRE_CONF);
ConfigFileUtil.writeBetweenBoundary(
WAConstants.getConfigFile(APACHE_MAIN_CONFIG_FILE),
"#",
IOUtil.readContentAsString(in));
in.close();
IOUtil.readContentAsString(new FileInputStream(STATIC_PRE_CONF), true));
// Write Vhost configuration
for(ApacheVirtualHostEntry vhost : vhosts){
vhost.configure();

View file

@ -27,9 +27,12 @@ import org.hyperic.sigar.FileSystemUsage;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.hyperic.sigar.cmd.Shell;
import wa.server.plugin.WAStatus;
import wa.server.WAContext;
import wa.server.page.WAStatusPage;
import zutil.io.file.FileUtil;
import zutil.net.http.HttpHeader;
import zutil.parser.DataNode;
import zutil.parser.Templator;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@ -39,26 +42,35 @@ import java.util.Map;
/**
* Created by Ziver on 2015-04-17.
*/
public class HDDStatus implements WAStatus {
public class HDDStatus extends WAStatusPage {
private static final String TEMPLATE = "wa/server/plugin/hwstatus/HddStatus.tmpl";
private static final String NAVIGATION_NAME = "wa/server/plugin/hwstatus/HddStatus.tmpl";
private Templator tmpl;
private int nextId;
private HashMap<String,Integer> idMap = new HashMap<String,Integer>();
public HDDStatus() {
super("hdd", "Harddrives");
}
@Override
public String getName() {
return "Harddrives";
public Templator htmlResponse(WAContext context, HttpHeader client_info, Map<String, Object> session, Map<String, String> cookie, Map<String, String> request) throws IOException {
if (tmpl == null)
tmpl = new Templator(FileUtil.getContent(FileUtil.find(TEMPLATE)));
return tmpl;
}
@Override
public String html() {
try {
return FileUtil.getContent(FileUtil.findURL("wa/server/plugin/hwstatus/HddStatus.tmpl"));
} catch (IOException e) {
return e.getMessage();
}
}
@Override
public void jsonUpdate(Map<String, String> request, DataNode root) {
public DataNode jsonResponse(WAContext context,
HttpHeader client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) {
DataNode root = new DataNode(DataNode.DataType.Map);
if (request.containsKey("hdd")) {
DataNode hdd_root = new DataNode(DataNode.DataType.List);
root.set("hdd", hdd_root);
@ -95,5 +107,7 @@ public class HDDStatus implements WAStatus {
e.printStackTrace();
}
}
return root;
}
}

View file

@ -16,7 +16,7 @@ $(function() {
});
function updateHdd(){
$.getJSON("{{nav.getUrl()}}&json&hdd", function( data ) {
$.getJSON("?json&hdd", function( data ) {
$.each(data['hdd'], function( index, hdd ){
var element = null;
var html_id = "hdd-id-" + hdd.id;

41
src/wa/server/plugin/hwstatus/HwStatus.java Normal file → Executable file
View file

@ -24,11 +24,14 @@ package wa.server.plugin.hwstatus;
import org.hyperic.sigar.*;
import org.hyperic.sigar.cmd.Shell;
import wa.server.plugin.WAStatus;
import wa.server.WAContext;
import wa.server.page.WAStatusPage;
import zutil.StringUtil;
import zutil.io.file.FileUtil;
import zutil.net.http.HttpHeader;
import zutil.parser.DataNode;
import zutil.parser.DataNode.DataType;
import zutil.parser.Templator;
import java.io.IOException;
import java.util.Map;
@ -36,23 +39,32 @@ import java.util.Map;
/**
* Created by Ziver on 2015-04-07.
*/
public class HwStatus implements WAStatus {
public class HwStatus extends WAStatusPage {
private static final String TEMPLATE = "wa/server/plugin/hwstatus/HwStatus.tmpl";
private Templator tmpl;
public HwStatus() {
super("hw", "Hardware Summary");
}
@Override
public String getName() {
return "Hardware Summary";
public Templator htmlResponse(WAContext context, HttpHeader client_info, Map<String, Object> session, Map<String, String> cookie, Map<String, String> request) throws IOException {
if (tmpl == null)
tmpl = new Templator(FileUtil.getContent(FileUtil.find(TEMPLATE)));
return tmpl;
}
@Override
public String html() {
try {
return FileUtil.getContent(FileUtil.findURL("wa/server/plugin/hwstatus/HwStatus.tmpl"));
} catch (IOException e) {
return e.getMessage();
}
}
@Override
public void jsonUpdate(Map<String, String> request, DataNode root) {
public DataNode jsonResponse(WAContext context,
HttpHeader client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) {
DataNode root = new DataNode(DataNode.DataType.Map);
try{
Sigar sigar = new Shell().getSigar();
@ -107,6 +119,7 @@ public class HwStatus implements WAStatus {
} catch (SigarException e) {
e.printStackTrace();
}
return root;
}
/**

View file

@ -54,7 +54,7 @@ var cpu_data = {
};
function updateCpuChart(){
$.getJSON("{{nav.getUrl()}}&json&cpu", function( data ) {
$.getJSON("?json&cpu", function( data ) {
// Setup graph
if(cpu_chart == null){
// Fill in cpus
@ -102,7 +102,7 @@ var mem_data = [
];
function updateMemChart(){
$.getJSON("{{nav.getUrl()}}&json&memory", function( data ) {
$.getJSON("?json&memory", function( data ) {
if(mem_chart == null){
var ctx = $("#mem-chart").get(0).getContext("2d");
mem_chart = new Chart(ctx).Doughnut(mem_data, {
@ -123,7 +123,7 @@ function updateMemChart(){
function updateProcTable(){
$.getJSON("{{nav.getUrl()}}&json&proc", function( data ) {
$.getJSON("?json&proc", function( data ) {
$('#proc-list').bootstrapTable({
data: data['proc']
});

View file

@ -24,10 +24,13 @@ package wa.server.plugin.hwstatus;
import org.hyperic.sigar.*;
import org.hyperic.sigar.cmd.Shell;
import wa.server.plugin.WAStatus;
import wa.server.WAContext;
import wa.server.page.WAStatusPage;
import zutil.io.file.FileUtil;
import zutil.net.ThroughputCalculator;
import zutil.net.http.HttpHeader;
import zutil.parser.DataNode;
import zutil.parser.Templator;
import java.io.IOException;
import java.util.HashMap;
@ -36,29 +39,37 @@ import java.util.Map;
/**
* Created by Ziver on 2015-04-28.
*/
public class NetStatus implements WAStatus{
public class NetStatus extends WAStatusPage {
private static final String TEMPLATE = "wa/server/plugin/hwstatus/NetStatus.tmpl";
private Templator tmpl;
private int nextId;
private HashMap<String,Integer> idMap = new HashMap<String,Integer>();
private HashMap<String,ThroughputCalculator> txMap = new HashMap<String,ThroughputCalculator>();
private HashMap<String,ThroughputCalculator> rxMap = new HashMap<String,ThroughputCalculator>();
public NetStatus() {
super("net", "Network");
}
@Override
public String getName() {
return "Network";
public Templator htmlResponse(WAContext context, HttpHeader client_info, Map<String, Object> session, Map<String, String> cookie, Map<String, String> request) throws IOException {
if (tmpl == null)
tmpl = new Templator(FileUtil.getContent(FileUtil.find(TEMPLATE)));
return tmpl;
}
@Override
public String html() {
try {
return FileUtil.getContent(FileUtil.findURL("wa/server/plugin/hwstatus/NetStatus.tmpl"));
} catch (IOException e) {
return e.getMessage();
}
}
@Override
public void jsonUpdate(Map<String, String> request, DataNode root) {
public DataNode jsonResponse(WAContext context,
HttpHeader client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) {
DataNode root = new DataNode(DataNode.DataType.Map);
try{
Sigar sigar = new Shell().getSigar();
@ -129,6 +140,7 @@ public class NetStatus implements WAStatus{
} catch (SigarException e) {
e.printStackTrace();
}
return root;
}

View file

@ -47,7 +47,7 @@ var net_chart_data = {
};
function updateNet(){
$.getJSON("{{nav.getUrl()}}&json&net", function( data ) {
$.getJSON("?json&net", function( data ) {
$.each(data['net'], function( index, net ){
var element = null;
var html_id = "net-" + net.id;

6
src/wa/server/plugin/hwstatus/plugin.json Normal file → Executable file
View file

@ -2,8 +2,8 @@
"version": "1.0",
"name": "HW Status",
"interfaces": [
{"wa.server.plugin.WAStatus": "wa.server.plugin.hwstatus.HwStatus"},
{"wa.server.plugin.WAStatus": "wa.server.plugin.hwstatus.HDDStatus"},
{"wa.server.plugin.WAStatus": "wa.server.plugin.hwstatus.NetStatus"}
{"wa.server.plugin.WAPage": "wa.server.plugin.hwstatus.HwStatus"},
{"wa.server.plugin.WAPage": "wa.server.plugin.hwstatus.HDDStatus"},
{"wa.server.plugin.WAPage": "wa.server.plugin.hwstatus.NetStatus"}
]
}

View file

@ -1,9 +1,12 @@
package wa.server.plugin.nutups;
import wa.server.plugin.WAStatus;
import wa.server.WAContext;
import wa.server.page.WAStatusPage;
import zutil.io.file.FileUtil;
import zutil.net.http.HttpHeader;
import zutil.osal.app.linux.NutUPSClient;
import zutil.parser.DataNode;
import zutil.parser.Templator;
import java.io.IOException;
import java.util.Map;
@ -11,32 +14,34 @@ import java.util.Map;
/**
* Created by Ziver on 2016-04-02.
*/
public class UPSStatus implements WAStatus {
public class UPSStatus extends WAStatusPage {
private static final String TEMPLATE = "wa/server/plugin/nutups/UPSStatus.tmpl";
private Templator tmpl;
private NutUPSClient nutClient;
public UPSStatus(){
super("ups", "UPS Status");
nutClient = new NutUPSClient("192.168.1.110", NutUPSClient.DEFAULT_PORT);
}
@Override
public String getName() {
return "UPS Status";
public Templator htmlResponse(WAContext context, HttpHeader client_info, Map<String, Object> session, Map<String, String> cookie, Map<String, String> request) throws IOException {
if (tmpl == null)
tmpl = new Templator(FileUtil.getContent(FileUtil.find(TEMPLATE)));
return tmpl;
}
@Override
public String html() {
try {
return FileUtil.getContent(FileUtil.findURL("wa/server/plugin/nutups/UPSStatus.tmpl"));
} catch (IOException e) {
return e.getMessage();
}
}
@Override
public void jsonUpdate(Map<String, String> request, DataNode root) {
public DataNode jsonResponse(WAContext context,
HttpHeader client_info,
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) {
DataNode root = new DataNode(DataNode.DataType.Map);
if(request.containsKey("ups")) {
DataNode upsRoot = new DataNode(DataNode.DataType.List);
for (NutUPSClient.UPSDevice ups : nutClient.getUPSList()){
@ -52,5 +57,6 @@ public class UPSStatus implements WAStatus {
}
root.set("ups", upsRoot);
}
return root;
}
}

View file

@ -2,6 +2,6 @@
"version": "1.0",
"name": "NUT UPS",
"interfaces": [
{"wa.server.plugin.WAStatus": "wa.server.plugin.nutups.UPSStatus"}
{"wa.server.plugin.WAPage": "wa.server.plugin.nutups.UPSStatus"}
]
}