/** * Copyright (C) 2013 Arman Gal * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.clevermore.monitor.client; import java.util.LinkedList; import org.clevermore.monitor.client.alerts.AlertsWidget; import org.clevermore.monitor.client.login.LoginWidget; import org.clevermore.monitor.client.login.LoginWidget.LoggedInCallBack; import org.clevermore.monitor.client.settings.SettingsPopup; import org.clevermore.monitor.client.smartpool.ThreadPoolsWidget; import org.clevermore.monitor.client.utils.MonitoringResources; import org.clevermore.monitor.client.widgets.IMonitoringWidget; import org.clevermore.monitor.client.widgets.ProgressLabel; import org.clevermore.monitor.shared.ServerTimeResult; import org.clevermore.monitor.shared.config.ClientConfigurations; import com.allen_sauer.gwt.log.client.Log; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.GWT.UncaughtExceptionHandler; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.RepeatingCommand; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Float; import com.google.gwt.dom.client.Style.FontWeight; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.RootPanel; public abstract class AbstractEntryPoint<CC extends ClientConfigurations> implements EntryPoint { /** * Create a remote service proxy to talk to the server-side service. */ private GeneralServiceAsync service; private final AlertsServiceAsync alertsService = GWT.create(AlertsService.class); private final LoginWidget<CC> loginWidget; private MonitoringResources resources = GWT.create(MonitoringResources.class); private LinkedList<IMonitoringWidget> widgets = new LinkedList<IMonitoringWidget>(); final FlowPanel mainPanel = new FlowPanel(); private CC clientConfigurations; private String loggedInUser; final Image refreshImg = new Image(resources.stopRefresh()); final Image alertImg = new Image(resources.stopAlerts()); boolean refresh = true; private FlowPanel mainHeader = new FlowPanel(); private HTML mainHeaderLabel = new HTML("--------------------------"); private ProgressLabel refProg = new ProgressLabel(); private HorizontalPanel footer = new HorizontalPanel(); AlertsWidget alertsWidget; private RepeatingCommand refreshCommand = new RepeatingCommand() { @Override public boolean execute() { if (refresh) { refresh(); } else { Log.debug("skipping refresh"); } return true; } }; private AsyncCallback<ServerTimeResult> refreshCallback = new AsyncCallback<ServerTimeResult>() { int errorCount = 0; @Override public void onSuccess(ServerTimeResult fullResult) { errorCount = 0; refProg.progress(); if (fullResult == null) { Log.debug("Received NULL response."); return; } Log.debug("Server time:" + fullResult.toString()); mainHeaderLabel.setHTML("<h1>" + clientConfigurations.getTitle() + ", v:" + clientConfigurations.getVersion() + " (" + fullResult.getServerTime() + "), User:" + loggedInUser + "</h1>"); // mainHeader.add(mainHeaderLabel); alertImg.getElement().setAttribute("state", fullResult.isAlertsEnabled() ? "2" : "1"); alertButtonClicked(fullResult.isAlertsEnabled() ? "2" : "1", fullResult.getTimeLeftForAutoEnable()); } @Override public void onFailure(Throwable caught) { Log.error("Received refresh response error:" + caught.getMessage() + ",\n errorCount:" + errorCount); errorCount++; refProg.progress(); if (errorCount > 3) { closeClient(); } } }; private void closeClient() { refresh = false; RootPanel.get().clear(); widgets.clear(); RootPanel.get().add(loginWidget); for (IMonitoringWidget widget : widgets) { // will reset last IDs, it's up it each widget to implement it widget.clear(); widget.setRefresh(false); widget.asWidget().removeFromParent(); } mainPanel.clear(); mainPanel.add(mainHeader); } /** * should override when configurations are extended * * @return */ public ConfigurationServiceAsync<CC> getConfigurationService() { return GWT.create(ConfigurationService.class); } public void setService(GeneralServiceAsync service) { this.service = service; } public AbstractEntryPoint() { GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { public void onUncaughtException(Throwable e) { Log.fatal("UncaughtException:" + e.getMessage(), e); } }); this.loginWidget = new LoginWidget<CC>(getConfigurationService()); this.loginWidget.registerCallBack(new LoggedInCallBack<CC>() { @Override public void loggedIn(final CC cc, final String loggedInUser) { try { AbstractEntryPoint.this.clientConfigurations = cc; AbstractEntryPoint.this.loggedInUser = loggedInUser; registerWidgets(); Log.debug("Authenticated"); RootPanel.get().clear(); addMainWidgets(); RootPanel.get().add(mainPanel); HTML footerText = new HTML("<span>  Created by </span><a target='blank' href=\"https://twitter.com/armangal\">@armangal</a><span>, based on </span><a href='https://github.com/armangal/SmartMonitoring' target='blank'>SmartMonitoring</a><span> project.</span></span>"); footer.setStyleName("footer"); footer.add(new Image("img/oo_icon.gif")); footer.add(footerText); mainPanel.add(footer); refresh = true; refresh(); Scheduler.get().scheduleFixedDelay(refreshCommand, GWT.isProdMode() ? 60000 : 20000); alertImg.getElement().setAttribute("state", cc.isAlertsEnabled() ? "2" : "1"); alertButtonClicked(cc.isAlertsEnabled() ? "2" : "1", 0); mainHeaderLabel.setHTML("<h1>" + clientConfigurations.getTitle() + ", v:" + clientConfigurations.getVersion() + "</h1>"); } catch (Exception e) { Log.error(e.getMessage(), e); Log.error(clientConfigurations.toString()); } } }); mainPanel.setStyleName("mainPanel"); Log.debug("AbstractEntryPoint created."); } /** * Add widget to the screen, the order matters. * * @param widget */ public void addMonitoringWidget(IMonitoringWidget widget) { widgets.add((IMonitoringWidget) widget); } /** * might be overridden to call other refresh function */ public void refresh() { Log.debug("Send refresh request."); refProg.progress(); service.refresh(refreshCallback); } /** * This is the entry point method. */ public void onModuleLoad() { Log.debug("Starting monitoring client."); Window.setMargin("0px"); RootPanel.get().clear(); RootPanel.get().add(loginWidget); refreshImg.getElement().setAttribute("state", "1"); alertImg.getElement().setAttribute("state", "1"); refreshImg.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { String attribute = refreshImg.getElement().getAttribute("state"); if ("1".equals(attribute)) { refreshImg.getElement().setAttribute("state", "2"); refresh = false; refreshImg.setResource(resources.continueRefresh()); refreshImg.setTitle("Start Refresh"); for (IMonitoringWidget widget : widgets) { widget.setRefresh(false); } } else { refreshImg.getElement().setAttribute("state", "1"); refresh = true; refresh(); refreshImg.setTitle("Stop Refresh"); refreshImg.setResource(resources.stopRefresh()); } } }); alertImg.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { String attribute = alertImg.getElement().getAttribute("state"); alertButtonClicked(attribute, 0); alertsService.stopAlerts("2".equals(attribute), new AsyncCallback<Boolean>() { @Override public void onSuccess(Boolean result) { } @Override public void onFailure(Throwable caught) { Window.alert(caught.getMessage()); } }); } }); mainHeader.setStyleName("mainHeader"); Style style = refProg.getElement().getStyle(); style.setWidth(20, Unit.PX); style.setFloat(Float.LEFT); mainHeader.add(refProg); refreshImg.addStyleName("settings"); refreshImg.setTitle("Stop Refresh"); mainHeader.add(refreshImg); alertImg.addStyleName("settings"); mainHeader.add(alertImg); Image settings = new Image(resources.settingsSmall()); settings.addStyleName("settings"); settings.setTitle("Settings"); settings.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { SettingsPopup sp = new SettingsPopup(service); sp.center(); } }); mainHeader.add(settings); Image logout = new Image(resources.logout()); logout.addStyleName("settings"); logout.setTitle("Logout"); logout.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { service.logout(new AsyncCallback<Void>() { @Override public void onSuccess(Void result) { closeClient(); } @Override public void onFailure(Throwable caught) { closeClient(); } }); } }); mainHeader.add(logout); mainHeader.add(mainHeaderLabel); mainPanel.add(mainHeader); } /** * should be overridden by extension project, the order is matters */ public abstract void registerWidgets(); protected void addSmartExecutorMonitoring() { if (getClientConfigurations().isSmartPoolMonEnabled()) { addMonitoringWidget(new ThreadPoolsWidget()); } } private void addMainWidgets() { for (IMonitoringWidget widget : widgets) { mainPanel.add(widget); } } public AsyncCallback<ServerTimeResult> getRefreshCallback() { return refreshCallback; } private void alertButtonClicked(String attribute, int timeLeft) { Style style = alertImg.getElement().getStyle(); if ("1".equals(attribute)) { alertImg.getElement().setAttribute("state", "2"); style.setColor("red"); style.setFontWeight(FontWeight.BOLDER); alertImg.setTitle("Continue Alerts, time left for auto-enable: " + timeLeft + " min."); alertImg.setResource(resources.continueAlerts()); } else { alertImg.getElement().setAttribute("state", "1"); style.setColor("black"); style.setFontWeight(FontWeight.NORMAL); alertImg.setTitle("Stop Alerts"); alertImg.setResource(resources.stopAlerts()); } } public CC getClientConfigurations() { return clientConfigurations; } public void hideHeaderAndFooter() { mainHeader.setVisible(false); footer.setVisible(false); } }