/*
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.max.ins.view;
import java.util.*;
import com.sun.max.ins.*;
import com.sun.max.ins.BootImageView.BootImageViewManager;
import com.sun.max.ins.InspectionSettings.AbstractSaveSettingsListener;
import com.sun.max.ins.InspectionSettings.SaveSettingsEvent;
import com.sun.max.ins.InspectionSettings.SaveSettingsListener;
import com.sun.max.ins.NotepadView.NotepadViewManager;
import com.sun.max.ins.UserFocusView.UserFocusViewManager;
import com.sun.max.ins.InvokeMethodLogView.InvokeMethodLogViewManager;
import com.sun.max.ins.debug.*;
import com.sun.max.ins.debug.BreakpointsView.BreakpointsViewManager;
import com.sun.max.ins.debug.MarkBitmapView.*;
import com.sun.max.ins.debug.CardTableView.CardTableViewManager;
import com.sun.max.ins.debug.RegistersView.RegistersViewManager;
import com.sun.max.ins.debug.StackFrameView.StackFrameViewManager;
import com.sun.max.ins.debug.StackView.StackViewManager;
import com.sun.max.ins.debug.ThreadLocalsView.ThreadLocalsViewManager;
import com.sun.max.ins.debug.ThreadsView.ThreadsViewManager;
import com.sun.max.ins.debug.WatchpointsView.WatchpointsViewManager;
import com.sun.max.ins.debug.vmlog.*;
import com.sun.max.ins.debug.vmlog.VMLogView.*;
import com.sun.max.ins.file.*;
import com.sun.max.ins.file.JavaSourceView.JavaSourceViewManager;
import com.sun.max.ins.gui.*;
import com.sun.max.ins.java.*;
import com.sun.max.ins.java.DebugInfoView.DebugInfoViewManager;
import com.sun.max.ins.memory.*;
import com.sun.max.ins.memory.AllocationsView.AllocationsViewManager;
import com.sun.max.ins.memory.MemoryBytesView.MemoryBytesViewManager;
import com.sun.max.ins.memory.MemoryView.MemoryViewManager;
import com.sun.max.ins.method.*;
import com.sun.max.ins.method.MethodViewContainer.MethodViewManager;
import com.sun.max.ins.object.HeapRegionInfoView.HeapRegionInfoViewManager;
import com.sun.max.ins.object.*;
import com.sun.max.program.option.*;
/**
* A generalized manager for views, some of which are singletons and some of which are not.
*/
public final class InspectionViews extends AbstractInspectionHolder {
private static final int TRACE_VALUE = 1;
/**
* The kinds of VM inspection views that can be activated (made visible).
*
*/
public enum ViewKind {
ALLOCATIONS(true, false, "Regions of memory allocated by the VM") {
@Override
public AllocationsViewManager viewManager() {
final AllocationsViewManager viewManager = AllocationsView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
BOOT_IMAGE(true, false, "Selected parameters in the VM's boot image") {
@Override
public BootImageViewManager viewManager() {
final BootImageViewManager viewManager = BootImageView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
BREAKPOINTS(true, false, "Breakpoints that currently exist for VM code") {
@Override
public BreakpointsViewManager viewManager() {
final BreakpointsViewManager viewManager = BreakpointsView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
CARD_TABLE(true, false, "The heap's CardTable") {
@Override
public CardTableViewManager viewManager() {
final CardTableViewManager viewManager = CardTableView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
DEBUG_INFO(true, false, "Debugging details at the currently selected position in compiled code") {
@Override
public DebugInfoViewManager viewManager() {
final DebugInfoViewManager viewManager = DebugInfoView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
HEAP_REGION_INFO(false, false, "The Heap Region Info for a memory location") {
@Override
public HeapRegionInfoViewManager viewManager() {
final HeapRegionInfoViewManager viewManager = HeapRegionInfoView.viewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
JAVA_SOURCE(false, false, "The contents of a Java source file") {
@Override
public JavaSourceViewManager viewManager() {
final JavaSourceViewManager viewManager = JavaSourceView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
MARK_BITMAP(true, false, "The heap's Mark Bitmap") {
@Override
public MarkBitmapViewManager viewManager() {
final MarkBitmapViewManager viewManager = MarkBitmapView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
MEMORY(false, false, "The contents of a region of VM memory, expressed as words") {
@Override
public MemoryViewManager viewManager() {
final MemoryViewManager viewManager = MemoryView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
MEMORY_BYTES(false, false, "The contents of a region of VM memory, expressed as bytes") {
@Override
public MemoryBytesViewManager viewManager() {
final MemoryBytesViewManager viewManager = MemoryBytesView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
METHODS(true, true, "Container for multiple disassembled methods from the VM") {
@Override
public MethodViewManager viewManager() {
final MethodViewManager viewManager = MethodViewContainer.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
// View management for methods is handled by the container
METHOD_CODE(false, false, "Disassembled code from a single method in the VM"),
NOTEPAD(true, false, "Notepad for keeping user notes") {
@Override
public NotepadViewManager viewManager() {
final NotepadViewManager viewManager = NotepadView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
INVOKE_METHOD_LOG(true, false, "Log of method invocation output") {
@Override
public InvokeMethodLogViewManager viewManager() {
final InvokeMethodLogViewManager viewManager = InvokeMethodLogView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
OBJECT(false, false, "The contents of a region of VM memory interpreted as an object representation") {
@Override
public ObjectViewManager viewManager() {
final ObjectViewManager viewManager = ObjectView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
REGISTERS(true, true, "Register contents in the VM for the currently selected thread") {
@Override
public RegistersViewManager viewManager() {
final RegistersViewManager viewManager = RegistersView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
STACK(true, true, "Stack contents in the VM for the currently selected thread") {
@Override
public StackViewManager viewManager() {
final StackViewManager viewManager = StackView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
STACK_FRAME(true, true, "Stack frame contents in the VM for the currently frame") {
@Override
public StackFrameViewManager viewManager() {
final StackFrameViewManager viewManager = StackFrameView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
THREADS(true, true, "Threads that currently exist in the VM") {
@Override
public ThreadsViewManager viewManager() {
final ThreadsViewManager viewManager = ThreadsView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
THREAD_LOCALS(true, false, "Thread locals in the VM for the currently selected thread") {
@Override
public ThreadLocalsViewManager viewManager() {
final ThreadLocalsViewManager viewManager = ThreadLocalsView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
USER_FOCUS(true, false, "The current state of session's user focus") {
@Override
public UserFocusViewManager viewManager() {
final UserFocusViewManager viewManager = UserFocusView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
WATCHPOINTS(true, false, "Watchpoints that currently exist for VM memory") {
@Override
public WatchpointsViewManager viewManager() {
final WatchpointsViewManager viewManager = WatchpointsView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
},
VMLOG(true, false, "VM Log View") {
@Override
public VMLogViewManager viewManager() {
final VMLogViewManager viewManager = VMLogView.makeViewManager(inspection);
assert viewManager.viewKind() == this;
return viewManager;
}
};
private static Inspection inspection;
private static ViewKind[] singletonViewKinds;
private static ViewKind[] multiViewKinds;
static {
// Rely on the language property that statics are executed
// after all initializations are complete.
final List<ViewKind> singletonKinds = new ArrayList<ViewKind>();
final List<ViewKind> multiKinds = new ArrayList<ViewKind>();
for (ViewKind kind : ViewKind.values()) {
if (kind.isSingleton) {
singletonKinds.add(kind);
} else {
multiKinds.add(kind);
}
}
singletonViewKinds = singletonKinds.toArray(new ViewKind[0]);
multiViewKinds = multiKinds.toArray(new ViewKind[0]);
}
private final boolean isSingleton;
private final boolean activeByDefault;
private final String description;
private final String key;
private ViewKind(boolean isSingleton, boolean activeByDefault, String description) {
this.isSingleton = isSingleton;
this.activeByDefault = activeByDefault;
this.description = description;
this.key = this.name().toLowerCase();
}
public ViewManager<? extends AbstractView> viewManager() {
return null;
}
private InspectorAction deactivateAllAction(InspectorView exceptInspector) {
final ViewManager< ? extends AbstractView> viewManager = viewManager();
return viewManager == null ? null : viewManager.deactivateAllAction(exceptInspector);
}
}
final SaveSettingsListener saveSettingsListener;
final InspectorAction resetViewsToDefaultAction;
final InspectorAction deactivateAllAction;
public InspectionViews(Inspection inspection) {
super(inspection);
ViewKind.inspection = inspection;
saveSettingsListener = new AbstractSaveSettingsListener("viewActive") {
public void saveSettings(SaveSettingsEvent saveSettingsEvent) {
for (ViewKind kind : ViewKind.singletonViewKinds) {
final SingletonViewManager singletonViewManager = (SingletonViewManager) kind.viewManager();
if (singletonViewManager.isSupported()) {
saveSettingsEvent.save(kind.key, singletonViewManager.isActive());
}
}
}
};
inspection.settings().addSaveSettingsListener(saveSettingsListener);
resetViewsToDefaultAction = new InspectorAction(inspection, "Reset to standard view set") {
@Override
protected void procedure() {
// The standard view set has no multi view instances; dispose all
for (InspectorView view : new ArrayList<InspectorView>(activeViews())) {
if (!view.viewManager().viewKind().isSingleton) {
view.dispose();
}
}
for (ViewKind kind : ViewKind.singletonViewKinds) {
final SingletonViewManager viewManager = (SingletonViewManager) kind.viewManager();
if (kind.activeByDefault) {
gui().restoreDefaultGeometry(viewManager.activateView());
} else if (viewManager.isActive()) {
viewManager.deactivateView();
}
}
}
};
deactivateAllAction = new InspectorAction(inspection, "Close all unpinned views") {
@Override
protected void procedure() {
for (InspectorView view : new ArrayList<InspectorView>(activeViews())) {
if (view.isPinned()) {
view.dispose();
}
}
}
};
}
/**
* @return all active views
*/
public List<AbstractView> activeViews() {
final List<AbstractView> views = new ArrayList<AbstractView>();
for (ViewKind kind : ViewKind.values()) {
final ViewManager<? extends AbstractView> viewManager = kind.viewManager();
if (viewManager != null) {
views.addAll(viewManager.activeViews());
}
}
return views;
}
/**
* @return all active views of a particular kind
*/
public List<? extends AbstractView> activeViews(ViewKind kind) {
final ViewManager<? extends AbstractView> viewManager = kind.viewManager();
if (viewManager != null) {
return viewManager.activeViews();
}
return Collections.emptyList();
}
/**
* Create all the views that should be present at the beginning of a session.
*/
public void activateInitialViews() {
final InspectionSettings settings = inspection().settings();
for (ViewKind kind : ViewKind.singletonViewKinds) {
if (kind.viewManager().isSupported() && settings.get(saveSettingsListener, kind.key, OptionTypes.BOOLEAN_TYPE, kind.activeByDefault)) {
final SingletonViewManager singletonViewManager = (SingletonViewManager) kind.viewManager();
singletonViewManager.activateView();
}
}
for (ViewKind kind : ViewKind.multiViewKinds) {
// Initialize any view managers that might need it.
kind.viewManager();
}
}
/**
* @return access to view creation for memory views.
*/
public MemoryViewFactory memory() {
return (MemoryViewFactory) ViewKind.MEMORY.viewManager();
}
/**
* @return access to view creation for memory bytes views.
*/
public MemoryBytesViewFactory memoryBytes() {
return (MemoryBytesViewFactory) ViewKind.MEMORY_BYTES.viewManager();
}
/**
* @return access to view creation for objects in the VM.
*/
public ObjectViewFactory objects() {
return (ObjectViewFactory) ViewKind.OBJECT.viewManager();
}
/**
* Activates a singleton view. It is an error to call this on a
* view kind that is not a singleton.
*
* @param kind the kind of view, must be a singleton.
* @return a new view
*/
public InspectorView activateSingletonView(ViewKind kind) {
assert kind.isSingleton;
final ViewManager< ? extends AbstractView> viewManager = kind.viewManager();
if (viewManager != null) {
SingletonViewManager singletonViewManager = (SingletonViewManager) viewManager;
return singletonViewManager.activateView();
}
return null;
}
/**
* Gets the action that will activate a singleton view.
*
* @param kind the kind of view to be activated, must be a singleton.
* @return the action for activating the view, null if not a singleton
*/
public InspectorAction activateSingletonViewAction(ViewKind kind) {
if (kind.isSingleton) {
final ViewManager< ? extends AbstractView> viewManager = kind.viewManager();
if (viewManager != null) {
SingletonViewManager singletonViewManager = (SingletonViewManager) viewManager;
return singletonViewManager.activateSingletonViewAction();
}
}
return null;
}
public Object resetViewsToDefaultAction() {
return resetViewsToDefaultAction;
}
/**
* Gets the action that will deactivate all active views.
*
* @return the action for deactivating views
*/
public InspectorAction deactivateAllViewsAction() {
return deactivateAllAction;
}
/**
* Gets the action that will deactivate all views of a particular kind.
*
* @param kind the kind of views to be deactivated
* @return the action for deactivating
*/
public InspectorAction deactivateAllViewsAction(ViewKind kind) {
return kind.deactivateAllAction(null);
}
/**
* Gets the action that will deactivate all views of a particular kind
* with one exception.
*
* @param kind the kind of views to be deactivated
* @param exceptInspector the one view that should not be deactivated
* @return the action for deactivating
*/
public InspectorAction deactivateOtherViewsAction(ViewKind kind, InspectorView exceptInspector) {
return kind.deactivateAllAction(exceptInspector);
}
}