/*
* Copyright 2015 the original author or authors.
* @https://github.com/scouter-project/scouter
*
* 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 scouter.client.group.view;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.TreeColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import scouter.client.Images;
import scouter.client.actions.OpenAddGroupAction;
import scouter.client.actions.OpenEQGroupViewAction;
import scouter.client.actions.OpenManageGroupAction;
import scouter.client.actions.OpenServiceGroupElapsedGroupAction;
import scouter.client.actions.OpenServiceGroupTPSGroupAction;
import scouter.client.actions.OpenVerticalEQGroupViewAction;
import scouter.client.constants.MenuStr;
import scouter.client.context.actions.OpenCxtmenuAssginGroupAction;
import scouter.client.counter.actions.OpenActiveSpeedGroupViewAction;
import scouter.client.counter.actions.OpenPastDateGroupAllViewAction;
import scouter.client.counter.actions.OpenPastDateGroupCountViewAction;
import scouter.client.counter.actions.OpenPastDateGroupTotalViewAction;
import scouter.client.counter.actions.OpenPastTimeGroupAllViewAction;
import scouter.client.counter.actions.OpenPastTimeGroupTotalViewAction;
import scouter.client.counter.actions.OpenPastTimeTranXGroupViewAction;
import scouter.client.counter.actions.OpenRealTimeGroupAllViewAction;
import scouter.client.counter.actions.OpenRealTimeGroupTotalViewAction;
import scouter.client.counter.actions.OpenRealTimeTranXGroupViewAction;
import scouter.client.counter.actions.OpenTodayGroupAllViewAction;
import scouter.client.counter.actions.OpenTodayGroupCountViewAction;
import scouter.client.counter.actions.OpenTodayGroupTotalViewAction;
import scouter.client.group.GroupManager;
import scouter.client.model.AgentModelThread;
import scouter.client.model.AgentObject;
import scouter.client.model.DummyObject;
import scouter.client.model.GroupObject;
import scouter.client.model.HierarchyObject;
import scouter.client.model.RefreshThread;
import scouter.client.popup.AddGroupDialog.IAddGroup;
import scouter.client.popup.GroupAssignmentDialog.IGroupAssign;
import scouter.client.popup.ManageGroupDialog.IManageGroup;
import scouter.client.server.Server;
import scouter.client.server.ServerManager;
import scouter.client.util.ColorUtil;
import scouter.client.util.DummyAction;
import scouter.client.util.ExUtil;
import scouter.client.util.ImageUtil;
import scouter.client.util.MenuUtil;
import scouter.client.util.ScouterUtil;
import scouter.lang.Counter;
import scouter.lang.counters.CounterConstants;
import scouter.lang.counters.CounterEngine;
import scouter.lang.value.Value;
import scouter.util.CastUtil;
import scouter.util.FormatUtil;
import scouter.util.LinkedMap;
public class GroupNavigationView extends ViewPart implements RefreshThread.Refreshable, IAddGroup, IManageGroup, IGroupAssign {
public static final String ID = GroupNavigationView.class.getName();
IWorkbenchWindow win = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
private RefreshThread thread;
private TreeViewer viewer;
private Tree tree;
LinkedMap<String, HierarchyObject> groupMap = new LinkedMap<String, HierarchyObject>();
TreeItem selectedItem;
public void createPartControl(Composite parent) {
parent.setLayout(new FillLayout());
Composite mainComp = new Composite(parent, SWT.NONE);
tree = new Tree(mainComp, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
tree.setHeaderVisible(true);
tree.setLinesVisible(true);
viewer = new TreeViewer(tree);
TreeColumn column1 = new TreeColumn(tree, SWT.LEFT);
column1.setAlignment(SWT.LEFT);
column1.setText("Group/Object");
TreeColumn column2 = new TreeColumn(tree, SWT.RIGHT);
column2.setAlignment(SWT.RIGHT);
column2.setText("Perf");
TreeColumnLayout layout = new TreeColumnLayout();
mainComp.setLayout( layout );
layout.setColumnData(column1, new ColumnWeightData( 68 ));
layout.setColumnData(column2, new ColumnWeightData( 22 ));
viewer.setContentProvider(new TreeContentProvider());
viewer.setLabelProvider(new TreeLabelProvider());
viewer.setInput(groupMap);
createContextMenu(viewer, new IMenuListener() {
public void menuAboutToShow(IMenuManager manager){
if (selectedItem == null) {
manager.add(new OpenAddGroupAction(win, GroupNavigationView.this));
} else {
ISelection selection = viewer.getSelection();
if (selection instanceof IStructuredSelection) {
IStructuredSelection sel = (IStructuredSelection)selection;
Object[] elements = sel.toArray();
if (elements == null || elements.length < 1) {
return;
}
Object selObject = elements[elements.length - 1];
if (selObject instanceof GroupObject) {
GroupObject grpObj = (GroupObject) selObject;
String grpName = grpObj.getName();
String objType = grpObj.getObjType();
boolean userGroupObj = !(grpObj.getParent() != null && grpObj.getParent() instanceof DummyObject);
AgentObject defaultObj = (grpObj.getFirstChild() != null) ? (AgentObject) grpObj.getFirstChild() : null;
Server server = ServerManager.getInstance().getDefaultServer();
if (defaultObj != null) {
server = ServerManager.getInstance().getServer(defaultObj.getServerId());
}
manager.add(new DummyAction(grpName, Images.getObjectIcon(objType, false, server.getId())));
if (userGroupObj) {
manager.add(new Separator());
manager.add(new OpenManageGroupAction(win, grpName, objType, GroupNavigationView.this));
manager.add(new RemoveGroupAction(grpName));
manager.add(new Separator());
Set<Counter> counters = listCounters(objType);
for (Counter counter : counters) {
String name = counter.getName();
String display = counter.getDisplayName();
MenuManager counterMenu = new MenuManager(display
, Images.getCounterImageDescriptor(objType, name, server.getId()), "scouter.group."+objType+"."+name);
manager.add(counterMenu);
MenuManager liveMenuManager = new MenuManager(MenuStr.LIVE_CHART
, ImageUtil.getImageDescriptor(Images.monitor)
, "scouter.group.live.id."+objType+"."+name);
counterMenu.add(liveMenuManager);
MenuManager loadMenuManager = new MenuManager(MenuStr.LOAD_CHART
, ImageUtil.getImageDescriptor(Images.drive)
, "scouter.group.load.id."+objType+"."+name);
counterMenu.add(loadMenuManager);
if (counter.isAll()) {
liveMenuManager.add(new OpenRealTimeGroupAllViewAction(win, MenuStr.TIME_ALL, name, grpObj));
}
if (counter.isTotal()) {
liveMenuManager.add(new OpenRealTimeGroupTotalViewAction(win, MenuStr.TIME_TOTAL, name, grpObj));
}
if (counter.isAll()) {
liveMenuManager.add(new OpenTodayGroupAllViewAction(win, MenuStr.DAILY_ALL, name, grpObj));
}
if (counter.isTotal()) {
liveMenuManager.add(new OpenTodayGroupTotalViewAction(win, MenuStr.DAILY_TOTAL, name, grpObj));
}
if (counter.isAll()) {
loadMenuManager.add(new OpenPastTimeGroupAllViewAction(win, MenuStr.TIME_ALL, name, grpObj));
}
if (counter.isTotal()) {
loadMenuManager.add(new OpenPastTimeGroupTotalViewAction(win, MenuStr.TIME_TOTAL, name, grpObj));
}
if (counter.isAll()) {
loadMenuManager.add(new OpenPastDateGroupAllViewAction(win, MenuStr.DAILY_ALL, name, grpObj));
}
if (counter.isTotal()) {
loadMenuManager.add(new OpenPastDateGroupTotalViewAction(win, MenuStr.DAILY_TOTAL, name, grpObj));
}
}
manager.add(new Separator());
if (isChildOf(objType, CounterConstants.FAMILY_JAVAEE)) {
manager.add(new OpenEQGroupViewAction(win, grpObj.getName()));
manager.add(new OpenVerticalEQGroupViewAction(win, grpObj.getName()));
manager.add(new OpenActiveSpeedGroupViewAction(win, MenuStr.ACTIVE_SPEED_REAL, grpObj));
MenuManager xLogMenu = new MenuManager(MenuStr.XLOG, ImageUtil.getImageDescriptor(Images.transrealtime), MenuStr.XLOG_ID);
manager.add(xLogMenu);
xLogMenu.add(new OpenRealTimeTranXGroupViewAction(win, MenuStr.REALTIME_XLOG, grpObj));
xLogMenu.add(new OpenPastTimeTranXGroupViewAction(win, MenuStr.PASTTIME_XLOG, grpObj));
MenuManager scMenu = new MenuManager(MenuStr.HOURLY_CHART, ImageUtil.getImageDescriptor(Images.bar), MenuStr.HOURLY_CHART_ID);
manager.add(scMenu);
scMenu.add(new OpenPastDateGroupCountViewAction(win, MenuStr.LOAD_SERVICE_COUNT, CounterConstants.WAS_SERVICE_COUNT, grpObj));
scMenu.add(new OpenTodayGroupCountViewAction(win, MenuStr.TODAY_SERVICE_COUNT, CounterConstants.WAS_SERVICE_COUNT, grpObj));
MenuManager serviceGroupMgr = new MenuManager("Serivce Group", ImageUtil.getImageDescriptor(Images.sum), "scouter.menu.id.group.javee.servicegroup");
manager.add(serviceGroupMgr);
serviceGroupMgr.add(new OpenServiceGroupTPSGroupAction(win, grpName));
serviceGroupMgr.add(new OpenServiceGroupElapsedGroupAction(win, grpName));
}
}
} else if (selObject instanceof AgentObject) {
AgentObject agent = (AgentObject) selObject;
int objHash = agent.getObjHash();
String objName = agent.getObjName();
String objType = agent.getObjType();
int serverId = agent.getServerId();
manager.add(new DummyAction(ServerManager.getInstance().getServer(serverId).getName()
, Images.SERVER_INACT));
manager.add(new Separator());
manager.add(new OpenCxtmenuAssginGroupAction(win, serverId, objHash, objName, objType, GroupNavigationView.this));
manager.add(new Separator());
MenuUtil.addObjectContextMenu(manager, win, agent);
}
}
}
}
});
tree.addListener(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
Point point = new Point(event.x, event.y);
selectedItem = tree.getItem(point);
}
});
createQuickMenus();
thread = new RefreshThread(this, 3000);
thread.setName(ID);
thread.start();
}
private void createContextMenu(Viewer viewer, IMenuListener listener){
MenuManager contextMenu = new MenuManager();
contextMenu.setRemoveAllWhenShown(true);
contextMenu.addMenuListener(listener);
Menu menu = contextMenu.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
getSite().registerContextMenu(contextMenu, viewer);
}
private void createQuickMenus(){
IToolBarManager man = getViewSite().getActionBars().getToolBarManager();
man.add(new Action("Expand All", ImageUtil.getImageDescriptor(Images.expand)) {
public void run() {
viewer.expandAll();
}
});
man.add(new Action("Collapse All", ImageUtil.getImageDescriptor(Images.collapse)) {
public void run() {
viewer.collapseAll();
}
});
man.add(new Separator());
man.add(new Action("Reload", ImageUtil.getImageDescriptor(Images.refresh)) {
public void run() {
forceRefresh();
}
});
}
public void setFocus() {
viewer.getControl().setFocus();
}
public void dispose() {
super.dispose();
if(thread != null && thread.isAlive()){
thread.shutdown();
thread = null;
}
}
private void forceRefresh() {
AgentModelThread.getInstance().fetchObjectList();
refresh();
}
public void refresh() {
organizeGroup();
try {
ExUtil.exec(tree, new Runnable() {
public void run() {
viewer.refresh();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
private Set<Counter> listCounters(String objType) {
Set<Counter> counterSet = new TreeSet<Counter>();
Set<Integer> serverList = ServerManager.getInstance().getOpenServerList();
for (int serverId : serverList) {
Server server = ServerManager.getInstance().getServer(serverId);
CounterEngine engine = server.getCounterEngine();
counterSet.addAll(engine.getCounterObjectSet(objType));
}
return counterSet;
}
private boolean isActionEnable(String objType, String attrName) {
boolean result = false;
Set<Integer> serverList = ServerManager.getInstance().getOpenServerList();
for (int serverId : serverList) {
Server server = ServerManager.getInstance().getServer(serverId);
CounterEngine engine = server.getCounterEngine();
if (engine.isTrueAction(objType, attrName)) {
result = true;
break;
}
}
return result;
}
private boolean isChildOf(String objType, String family) {
boolean result = false;
Set<Integer> serverList = ServerManager.getInstance().getOpenServerList();
for (int serverId : serverList) {
Server server = ServerManager.getInstance().getServer(serverId);
CounterEngine engine = server.getCounterEngine();
if (engine.isChildOf(objType, family)) {
result = true;
break;
}
}
return result;
}
class TreeContentProvider implements ITreeContentProvider {
public void dispose() {
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
public Object[] getElements(Object inputElement) {
if (inputElement instanceof LinkedMap) {
Enumeration e = ((LinkedMap) inputElement).values();
Object[] objArray = new Object[((LinkedMap) inputElement).size()];
int cnt = 0;
while (e.hasMoreElements()) {
objArray[cnt] = e.nextElement();
cnt++;
}
return objArray;
}
return new Object[0];
}
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof HierarchyObject){
if (parentElement instanceof AgentObject) {
return new Object[0];
} else {
return ((HierarchyObject) parentElement).getSortedChildArray();
}
}
return new Object[0];
}
public Object getParent(Object element) {
if (element instanceof HierarchyObject) {
return ((HierarchyObject) element).getParent();
}
return null;
}
public boolean hasChildren(Object element) {
if (element instanceof HierarchyObject){
if(element instanceof AgentObject) {
return false;
} else {
return ((HierarchyObject) element).getChildSize() > 0;
}
}
return false;
}
}
class TreeLabelProvider implements ITableLabelProvider, IColorProvider {
public void addListener(ILabelProviderListener listener) {
}
public void dispose() {
}
public boolean isLabelProperty(Object element, String property) {
return false;
}
public void removeListener(ILabelProviderListener listener) {
}
public Color getForeground(Object element) {
if (element instanceof AgentObject) {
AgentObject a = (AgentObject) element;
if(!a.isAlive()){
return ColorUtil.getInstance().getColor("gray");
}
}
return null;
}
public Color getBackground(Object element) {
return null;
}
public Image getColumnImage(Object element, int columnIndex) {
switch (columnIndex) {
case 0:
if (element instanceof DummyObject) {
DummyObject dummyObj = (DummyObject) element;
if (dummyObj.getChildSize() > 0) {
return Images.folder;
} else {
return Images.default_context;
}
} else if (element instanceof GroupObject) {
GroupObject grpObj = (GroupObject) element;
return Images.getObjectIcon(grpObj.getObjType(), true, 0);
} else if (element instanceof AgentObject) {
AgentObject agent = (AgentObject) element;
if (agent.isAlive()) {
return Images.active;
} else {
return Images.dead;
}
}
break;
case 1:
// if (element instanceof AgentObject) {
// AgentObject a = (AgentObject) element;
// if (a.isAlive()) {
// return ImageCache.getInstance().getObjectImage(a.getObjHash());
// }
// }
// break;
}
return null;
}
public String getColumnText(Object obj, int columnIndex) {
switch (columnIndex) {
case 0:
if (obj instanceof AgentObject) {
AgentObject agent = (AgentObject) obj;
return agent.getObjName();
} else if (obj instanceof DummyObject) {
return ((DummyObject) obj).getName();
} else if (obj instanceof GroupObject) {
return ((GroupObject) obj).getName();
}
return obj.toString();
case 1:
if (obj instanceof AgentObject) {
AgentObject agent = (AgentObject) obj;
if(agent.isAlive()) {
Value value = agent.getMasterCounter();
if (value == null) {
return "";
}
Server server = ServerManager.getInstance().getServer(agent.getServerId());
if(server == null)
return "?";
return getColumnTextForByte(value, server.getCounterEngine().getMasterCounterUnit(agent.getObjType()));
}
}
}
return null;
}
public String getColumnTextForByte(Value value, String unit){
if("bytes".equals(unit)){
double v = CastUtil.cdouble(value);
return ScouterUtil.humanReadableByteCount(v, true);
// if(v > 1024*1024){
// return new Format(v/(1024*1024)).print("#,##0.0") + " MB";
// }else if(v > 1024){
// return new Format(v/(1024)).print("#,##0.0") + " KB";
// }
}
return FormatUtil.print(value, "#,###.##") + " " + unit;
}
}
public boolean addedGroup(String objType, String name) {
boolean result = GroupManager.getInstance().addGroup(objType, name);
if (result) {
forceRefresh();
}
return result;
}
public void setResult(String groupName, int[] addObjHashs, int[] removeObjHashs) {
GroupManager manager = GroupManager.getInstance();
if (manager.addObject(addObjHashs, groupName)) {
manager.removeObject(removeObjHashs, groupName);
forceRefresh();
}
}
public class RemoveGroupAction extends Action {
String groupName;
public RemoveGroupAction(String groupName) {
this.groupName = groupName;
setText("&Remove");
setImageDescriptor(ImageUtil.getImageDescriptor(Images.group_delete));
}
public void run() {
if (win != null) {
if (MessageDialog.openConfirm(win.getShell(), "Remove " + groupName, groupName + " group will be removed. Continue?")) {
GroupManager.getInstance().removeGroup(groupName);
forceRefresh();
}
}
}
}
public void endGroupAssignment(int objHash, String[] groups) {
GroupManager.getInstance().assginGroups(objHash, groups);
forceRefresh();
}
private void organizeGroup() {
GroupManager manager = GroupManager.getInstance();
List<String> userGroupList = manager.listGroup();
groupMap.clear();
// 1. Make Groups
for (int i = 0; i < userGroupList.size(); i++) {
String name = userGroupList.get(i);
String objType = manager.getGroupObjType(name);
if (objType != null) {
groupMap.put(name, new GroupObject(objType, name));
}
}
DummyObject othersObj = new DummyObject(GroupManager.OTHERS);
// 2. Make Others
groupMap.put(GroupManager.OTHERS, othersObj);
// 3. Put agent in group
AgentObject[] objectList = AgentModelThread.getInstance().getObjectList();
for (AgentObject agent : objectList) {
boolean others = true;
Set<String> objGroupList = manager.getObjGroups(agent.getObjHash());
for (String value : objGroupList) {
HierarchyObject hiObj = groupMap.get(value);
if (hiObj != null && hiObj instanceof GroupObject) {
GroupObject grpObj = (GroupObject) hiObj;
if (grpObj.getObjType().equals(agent.getObjType())) {
grpObj.putChild(agent.getObjName(), agent);
others = false;
}
}
}
// if any group do not include this object, put in others group
if (others) {
String objType = agent.getObjType();
HierarchyObject hiObj = othersObj.getChild(objType);
if (hiObj == null) {
hiObj = new GroupObject(objType, ServerManager.getInstance().getServer(agent.getServerId()).getCounterEngine().getDisplayNameObjectType(objType));
othersObj.putChild(objType, hiObj);
hiObj.setParent(othersObj);
}
hiObj.putChild(agent.getObjName(), agent);
}
}
}
}