normalized line endings

This commit is contained in:
Steffen Schaefer
2017-05-16 09:42:02 +02:00
parent 8cf9053d37
commit 9123771f34
2780 changed files with 301735 additions and 301735 deletions
+28 -28
View File
@@ -1,28 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.sap.sse.gwt.adminconsole</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.sap.sse.gwt.adminconsole</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
@@ -1,3 +1,3 @@
eclipse.preferences.version=1
pluginProject.extensions=false
resolve.requirebundle=false
eclipse.preferences.version=1
pluginProject.extensions=false
resolve.requirebundle=false
@@ -1,4 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.
@@ -1,458 +1,458 @@
package com.sap.sse.gwt.adminconsole;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.common.Util.Triple;
import com.sap.sse.gwt.client.AbstractEntryPoint;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.ServerInfoRetriever;
import com.sap.sse.gwt.client.panels.AbstractTabLayoutPanel;
import com.sap.sse.gwt.client.panels.HorizontalTabLayoutPanel;
import com.sap.sse.gwt.client.panels.VerticalTabLayoutPanel;
import com.sap.sse.security.shared.Permission;
import com.sap.sse.security.shared.PermissionsForRoleProvider;
import com.sap.sse.security.shared.WildcardPermission;
import com.sap.sse.security.ui.client.UserService;
import com.sap.sse.security.ui.client.UserStatusEventHandler;
import com.sap.sse.security.ui.loginpanel.LoginPanelCss;
import com.sap.sse.security.ui.shared.UserDTO;
/**
* A panel that can be used to implement an administration console. Widgets can be arranged in vertical and horizontal
* tabs ("L-shape"). The top-level element is the vertical tab panel. Widgets may either be added directly as the
* content of one vertical tab, or a horizontal tab panel can be added as the content widget of a vertical tab, in turn
* holding widgets in horizontal tabs.
* <p>
*
* After constructing an instance of this class, there are three ways for adding widgets:
* <ul>
* <li>{@link #addToVerticalTabPanel(RefreshableAdminConsolePanel, String, Permission)} adds a widget as a content
* element of a vertical tab</li>
* <li>{@link #addVerticalTab(String, String, Permission)} creates a horizontal tab panel and adds it as a content
* element of a vertical tab</li>
* <li>{@link #addToTabPanel(TabLayoutPanel, RefreshableAdminConsolePanel, String, Permission)} adds a widget as a
* content element of a horizontal tab</li>
* </ul>
*
* Widgets to be added need to be wrapped as {@link RefreshableAdminConsolePanel} holding the widget and receiving the
* refresh call when the widget is shown because the user has selected the tab. If the component doesn't require any
* refresh logic, an instance of {@link DefaultRefreshableAdminConsolePanel} can be used to wrap the widget.
* <p>
*
* After the widgets have been added, {@link #initUI()} must be called to assemble all tabs for the current user's
* roles. The {@link #initUI()} method must be called each time more widgets have been added dynamically.
* <p>
*
* For each widget added, a {@link Permission set of permissions} needs to be specified, any of which is sufficient to
* get to see the widget. When the user changes or has his/her permissions updated the set of tabs visible will be
* adjusted according to the new roles available for the logged-in user.
* <p>
*
* @author Axel Uhl (D043530)
*
*/
public class AdminConsolePanel extends DockLayoutPanel implements HandleTabSelectable{
private final UserService userService;
/**
* The administration console's UI depends on the user's roles. When the roles change then so shall the display of
* tabs. Required {@link Permission}s tell when they are to be made available based on the user's actual
* permissions. This map keeps track of the dependencies and allows the UI to adjust to role changes.<p>
*
* The values are the permissions, at least one of which is required from the user to be able to see the widget.
*/
private final LinkedHashSet<Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String>> roleSpecificTabs;
private final Map<Widget, Set<Permission>> permissionsAnyOfWhichIsRequiredToSeeWidget;
private final SelectionHandler<Integer> tabSelectionHandler;
/**
* The top-level vertical tab panel
*/
private final VerticalTabLayoutPanel topLevelTabPanel;
private final VerticalOrHorizontalTabLayoutPanel topLevelTabPanelWrapper;
/**
* Keys are the results of calling {@link RefreshableAdminConsolePanel#getWidget()} on their associated values. This
* allows the panel to find the refresh target when a widget has been selected in a tab panel.
*/
private final Map<Widget, RefreshableAdminConsolePanel> panelsByWidget;
private final PermissionsForRoleProvider permissionsForRoleProvider;
/**
* Generic selection handler that forwards selected tabs to a refresher that ensures that data gets reloaded. If
* you add a new tab then make sure to have a look at #refreshDataFor(Widget widget) to ensure that upon
* selection your tab gets the data refreshed.
*/
private class TabSelectionHandler implements SelectionHandler<Integer> {
@Override
public void onSelection(SelectionEvent<Integer> event) {
Object source = event.getSource();
if (source != null) {
if (source instanceof HorizontalTabLayoutPanel) {
final HorizontalTabLayoutPanel tabPanel = ((HorizontalTabLayoutPanel) source);
final Widget selectedPanel = tabPanel.getWidget(event.getSelectedItem());
refreshDataFor(selectedPanel);
} else if (source instanceof VerticalTabLayoutPanel) {
final VerticalTabLayoutPanel verticalTabLayoutPanel = (VerticalTabLayoutPanel) source;
Widget widgetAssociatedToVerticalTab = verticalTabLayoutPanel.getWidget(verticalTabLayoutPanel.getSelectedIndex());
if (widgetAssociatedToVerticalTab instanceof HorizontalTabLayoutPanel) {
HorizontalTabLayoutPanel selectedTabLayoutPanel = (HorizontalTabLayoutPanel) widgetAssociatedToVerticalTab;
final int selectedIndex = selectedTabLayoutPanel.getSelectedIndex();
if (selectedIndex >= 0) {
widgetAssociatedToVerticalTab = selectedTabLayoutPanel.getWidget(selectedIndex);
}
}
refreshDataFor(widgetAssociatedToVerticalTab);
}
}
}
private void refreshDataFor(Widget target) {
RefreshableAdminConsolePanel refreshTarget = panelsByWidget.get(unwrapScrollPanel(target));
if (refreshTarget != null) {
refreshTarget.refreshAfterBecomingVisible();
}
}
}
/**
* If the <code>widgetMaybeWrappedByScrollPanel</code> is a scroll panel, returns the content widget,
* otherwise <code>widgetMaybeWrappedByScrollPanel</code> is returned.
*/
private static Widget unwrapScrollPanel(Widget widgetMaybeWrappedByScrollPanel) {
final Widget target;
if (widgetMaybeWrappedByScrollPanel instanceof ScrollPanel) {
target = ((ScrollPanel) widgetMaybeWrappedByScrollPanel).getWidget();
} else {
target = widgetMaybeWrappedByScrollPanel;
}
return target;
}
public AdminConsolePanel(UserService userService, PermissionsForRoleProvider permissionsForRoleProvider,
ServerInfoRetriever buildVersionRetriever, String releaseNotesAnchorLabel,
String releaseNotesURL, ErrorReporter errorReporter, LoginPanelCss loginPanelCss, StringMessages stringMessages) {
super(Unit.EM);
this.permissionsForRoleProvider = permissionsForRoleProvider;
this.permissionsAnyOfWhichIsRequiredToSeeWidget = new HashMap<>();
this.userService = userService;
roleSpecificTabs = new LinkedHashSet<>();
this.panelsByWidget = new HashMap<>();
getUserService().addUserStatusEventHandler(new UserStatusEventHandler() {
@Override
public void onUserStatusChange(UserDTO user) {
updateTabDisplayForCurrentUser(user);
}
});
tabSelectionHandler = new TabSelectionHandler();
topLevelTabPanel = new VerticalTabLayoutPanel(2.5, Unit.EM);
topLevelTabPanel.addSelectionHandler(tabSelectionHandler);
topLevelTabPanel.ensureDebugId("AdministrationTabs");
topLevelTabPanelWrapper = new VerticalOrHorizontalTabLayoutPanel() {
@Override
public void add(Widget child, String text, boolean asHtml) {
topLevelTabPanel.add(child, text, asHtml);
topLevelTabPanel.forceLayout();
}
@Override
public boolean remove(Widget child) {
return topLevelTabPanel.remove(child);
}
@Override
public boolean remove(Widget child, boolean fireEvents) {
return topLevelTabPanel.remove(topLevelTabPanel.getWidgetIndex(child), fireEvents);
}
@Override
public Widget getPanel() {
return topLevelTabPanel;
}
@Override
public void selectTab(int index) {
topLevelTabPanel.selectTab(index);
}
@Override
public int getWidgetIndex(Widget child) {
return topLevelTabPanel.getWidgetIndex(child);
}
};
final DockPanel informationPanel = new DockPanel();
informationPanel.setSize("100%", "95%");
informationPanel.setSpacing(10);
informationPanel.add(errorReporter.getPersistentInformationWidget(), DockPanel.CENTER);
SystemInformationPanel sysinfoPanel = new SystemInformationPanel(buildVersionRetriever, errorReporter, stringMessages);
sysinfoPanel.ensureDebugId("SystemInformation");
final Anchor releaseNotesLink = new Anchor(new SafeHtmlBuilder().appendEscaped(releaseNotesAnchorLabel).toSafeHtml(), releaseNotesURL);
sysinfoPanel.add(releaseNotesLink);
informationPanel.add(sysinfoPanel, DockPanel.EAST);
informationPanel.setCellHorizontalAlignment(sysinfoPanel, HasHorizontalAlignment.ALIGN_RIGHT);
this.addSouth(informationPanel, 2.5);
this.add(topLevelTabPanel);
}
/**
* Invoke this method after having added all panels using
* {@link #addToTabPanel(TabLayoutPanel, RefreshableAdminConsolePanel, String, AdminConsoleFeatures)} or
* {@link #addToVerticalTabPanel(RefreshableAdminConsolePanel, String, AdminConsoleFeatures)} or
* {@link #addVerticalTab(String, String, AdminConsoleFeatures)}. Tabs can also dynamically be added after calling
* this method, but then this method needs to be invoked again to ensure that all all tabs are properly displayed
* for the current panel's state.
*/
public void initUI() {
updateTabDisplayForCurrentUser(getUserService().getCurrentUser());
if (topLevelTabPanel.getWidgetCount() > 0) {
topLevelTabPanel.selectTab(0);
}
}
private UserService getUserService() {
return userService;
}
private static interface VerticalOrHorizontalTabLayoutPanel {
void add(Widget child, String text, boolean asHtml);
boolean remove(Widget child);
boolean remove(Widget child, boolean fireEvents);
Widget getPanel();
void selectTab(int index);
int getWidgetIndex(Widget child);
}
/**
* Adds a new horizontal tab panel to the top-level vertical tab panel.
*
* @return the horizontal tab panel that was created and added to the top-level vertical tab panel; the panel returned can be specified
* as argument to {@link #addToTabPanel(TabLayoutPanel, Widget, String, AdminConsoleFeatures)}.
*/
public HorizontalTabLayoutPanel addVerticalTab(String tabTitle, String tabDebugId, Permission... requiresAnyOfThesePermissions) {
final HorizontalTabLayoutPanel newTabPanel = new HorizontalTabLayoutPanel(2.5, Unit.EM);
AbstractEntryPoint.setTabPanelSize(newTabPanel, "100%", "100%");
newTabPanel.addSelectionHandler(tabSelectionHandler);
newTabPanel.ensureDebugId(tabDebugId);
remeberWidgetLocationAndPermissions(topLevelTabPanelWrapper, newTabPanel, tabTitle, requiresAnyOfThesePermissions);
return newTabPanel;
}
/**
* Adds an administration panel as an entry to the top-level vertical panel, without an intermediary horizontal tab panel.
* This is useful for panels that form a top-level category of its own but don't require multiple panels to represent this
* top-level category.
*/
public void addToVerticalTabPanel(final RefreshableAdminConsolePanel panelToAdd, String tabTitle, Permission... requiresAnyOfThesePermissions) {
addToTabPanel(topLevelTabPanelWrapper, panelToAdd, tabTitle, requiresAnyOfThesePermissions);
}
private ScrollPanel wrapInScrollPanel(Widget panelToAdd) {
ScrollPanel scrollPanel = new ScrollPanel();
scrollPanel.add(panelToAdd);
panelToAdd.setSize("100%", "100%");
return scrollPanel;
}
public void addToTabPanel(final HorizontalTabLayoutPanel tabPanel, RefreshableAdminConsolePanel panelToAdd, String tabTitle, Permission... requiresAnyOfThesePermissions) {
VerticalOrHorizontalTabLayoutPanel wrapper = new VerticalOrHorizontalTabLayoutPanel() {
@Override
public void add(Widget child, String text, boolean asHtml) {
tabPanel.add(child, text, asHtml);
tabPanel.forceLayout();
}
@Override
public boolean remove(Widget child) {
return tabPanel.remove(child);
}
@Override
public boolean remove(Widget child, boolean fireEvents) {
return tabPanel.remove(tabPanel.getWidgetIndex(child), fireEvents);
}
@Override
public Widget getPanel() {
return tabPanel;
}
@Override
public void selectTab(int index) {
tabPanel.selectTab(index);
}
@Override
public int getWidgetIndex(Widget child) {
return tabPanel.getWidgetIndex(child);
}
};
addToTabPanel(wrapper, panelToAdd, tabTitle, requiresAnyOfThesePermissions);
}
/**
* Remembers in which tab panel the <code>panelToAdd</code> is to be displayed and for which feature; additionally, remembers adds
* a hook so that when the <code>panelToAdd</code>'s widget is selected then the {@link RefreshableAdminConsolePanel#refreshAfterBecomingVisible()}
* method can be called.
*/
private void addToTabPanel(VerticalOrHorizontalTabLayoutPanel tabPanel, RefreshableAdminConsolePanel panelToAdd, String tabTitle, Permission... requiresAnyOfThesePermissions) {
remeberWidgetLocationAndPermissions(tabPanel, wrapInScrollPanel(panelToAdd.getWidget()), tabTitle, requiresAnyOfThesePermissions);
panelsByWidget.put(panelToAdd.getWidget(), panelToAdd);
}
/**
* Remembers the tab panel in which the <code>widgetToAdd</code> is to be displayed and which permissions are
* sufficient to see the widget. For the <code>tabPanel</code>, all permissions provided here are added to the tab
* panel's permissions so that the user will see the tab panel as soon as the user may see any of the widgets inside
* that panel
*
* @param requiresAnyOfThesePermissions
* zero or more permissions; if no permissions are provided, the user will never be able to see the
* widget. Otherwise, if any of these permissions implies any of the permissions the user has, the user
* will be shown the widget. In particular, a "*" wildcard permission will show the widget to all users,
* regardless their actual permissions.
*/
private void remeberWidgetLocationAndPermissions(VerticalOrHorizontalTabLayoutPanel tabPanel, Widget widgetToAdd,
String tabTitle, Permission... requiresAnyOfThesePermissions) {
roleSpecificTabs.add(new Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String>(tabPanel, widgetToAdd, tabTitle));
final HashSet<Permission> permissionsAsSet = new HashSet<>(Arrays.asList(requiresAnyOfThesePermissions));
permissionsAnyOfWhichIsRequiredToSeeWidget.put(widgetToAdd, permissionsAsSet);
Set<Permission> permissionsForTabPanel = permissionsAnyOfWhichIsRequiredToSeeWidget.get(tabPanel.getPanel());
if (permissionsForTabPanel == null) {
permissionsForTabPanel = new HashSet<>();
permissionsAnyOfWhichIsRequiredToSeeWidget.put(tabPanel.getPanel(), permissionsForTabPanel);
}
permissionsForTabPanel.addAll(permissionsAsSet);
}
/**
* After initialization or whenever the user changes, the tab display is adjusted based on which roles are required
* to see which tabs. See {@link #roleSpecificTabs}. A selection event is fired when the tab currently selected
* was removed and another tab was therefore selected.
*/
private void updateTabDisplayForCurrentUser(UserDTO user) {
final Widget selectedPanel = getSelectedTab(null);
for (Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String> e : roleSpecificTabs) {
final Widget widgetToAddOrRemove = e.getB();
if (user != null && userHasPermissionsToSeeWidget(user, e.getB())) {
if (e.getA().getWidgetIndex(widgetToAddOrRemove) == -1) {
e.getA().add(widgetToAddOrRemove, e.getC(), /* asHtml */false);
}
} else {
e.getA().remove(widgetToAddOrRemove, /* fireEvents */ false);
}
}
getSelectedTab(selectedPanel);
}
/**
* If the top-level selected tab is a horizontal tab panel, its selected panel is returned; otherwise, the selected
* top-level panel is returned. If no top-level panel exists or is selected, {@code null} is returned.
*
* @param reselectCurrentSelectionIfNotSameAsThis
* if not {@code null}, the selected panel is {@link AbstractTabLayoutPanel#selectTab(Widget) selected}
* again in case it isn't the same as {@code reselectCurrentSelectionIfNotSameAsThis}, firing a selection
* event
*/
private Widget getSelectedTab(Widget reselectCurrentSelectionIfNotSameAsThis) {
final Widget topLevelSelectedTab;
Widget selectedTabInHorizontalTabPanel = null;
if (topLevelTabPanel.getSelectedIndex() != -1) {
topLevelSelectedTab = unwrapScrollPanel(topLevelTabPanel.getWidget(topLevelTabPanel.getSelectedIndex()));
if (topLevelSelectedTab instanceof AbstractTabLayoutPanel) {
AbstractTabLayoutPanel p = (AbstractTabLayoutPanel) topLevelSelectedTab;
if (p.getSelectedIndex() != -1) {
selectedTabInHorizontalTabPanel = unwrapScrollPanel(p.getWidget(p.getSelectedIndex()));
if (reselectCurrentSelectionIfNotSameAsThis != null && selectedTabInHorizontalTabPanel != reselectCurrentSelectionIfNotSameAsThis) {
SelectionEvent.fire(p, p.getSelectedIndex());
}
} else {
selectedTabInHorizontalTabPanel = null;
}
} else {
if (reselectCurrentSelectionIfNotSameAsThis != null && topLevelSelectedTab != reselectCurrentSelectionIfNotSameAsThis) {
SelectionEvent.fire(topLevelTabPanel, topLevelTabPanel.getSelectedIndex());
}
}
} else {
topLevelSelectedTab = null;
}
return selectedTabInHorizontalTabPanel != null ? selectedTabInHorizontalTabPanel : topLevelSelectedTab;
}
@Override
public void selectTabByNames(String verticalTabName, String horizontalTabName, Map<String, String> params) {
if (verticalTabName == null) {
return;
}
Widget widgetForSetup = null; //Remember widget for set up
for (Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String> e : roleSpecificTabs) {
VerticalOrHorizontalTabLayoutPanel panel = e.getA();
Widget currentWidget = e.getB();
if (panel == topLevelTabPanelWrapper && verticalTabName.equals(e.getC())) { // for vertical panel
int index = panel.getWidgetIndex(currentWidget);
panel.selectTab(index);
if (horizontalTabName == null) {//If we don't have horizontal tab will setup vertical tab.
widgetForSetup = currentWidget;
}
} else if (horizontalTabName != null && horizontalTabName.equals(e.getC())) { // for horizontal panel
int index = panel.getWidgetIndex(currentWidget);
panel.selectTab(index);
widgetForSetup = currentWidget;
}
}
panelsByWidget.get(unwrapScrollPanel(widgetForSetup)).setupWidgetByParams(params);;
}
/**
* A user is defined to have permission to see a widget if the widget's required permissions imply any of the permissions the
* user has. This may at first seem the wrong way around. However, the problem is that a widget cannot express a general permission
* that is implied by any detailed permissions. Wildcard permissions don't work this way. Instead, a wildcard permission implies
* detailed permissions. This way, if the widget requires, say, "event:*:*" (or "event" for short), this permission implies
* all more detailed event permissions such as "event:write:9456192873". Therefore, the permissions provided for widgets
* must imply a permission the user has in order for the user to see the tab. More detailed permissions checks can then be
* applied at a more detailed level of the UI and, of course, in the back end. Additionally, if any of the user's permissions
* implies the required permission (e.g., the user having "*" as the administrator's permission), permission to see the widget
* is also implied.
*/
private boolean userHasPermissionsToSeeWidget(UserDTO user, Widget widget) {
for (Permission requiredStringPermission : permissionsAnyOfWhichIsRequiredToSeeWidget.get(widget)) {
WildcardPermission requiredPermission = new WildcardPermission(requiredStringPermission.getStringPermission());
for (String userStringPermission : user.getAllPermissions(permissionsForRoleProvider)) {
WildcardPermission userPermission = new WildcardPermission(userStringPermission);
if (requiredPermission.implies(userPermission) || userPermission.implies(requiredPermission)) {
return true;
}
}
}
return false;
}
}
package com.sap.sse.gwt.adminconsole;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.common.Util.Triple;
import com.sap.sse.gwt.client.AbstractEntryPoint;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.ServerInfoRetriever;
import com.sap.sse.gwt.client.panels.AbstractTabLayoutPanel;
import com.sap.sse.gwt.client.panels.HorizontalTabLayoutPanel;
import com.sap.sse.gwt.client.panels.VerticalTabLayoutPanel;
import com.sap.sse.security.shared.Permission;
import com.sap.sse.security.shared.PermissionsForRoleProvider;
import com.sap.sse.security.shared.WildcardPermission;
import com.sap.sse.security.ui.client.UserService;
import com.sap.sse.security.ui.client.UserStatusEventHandler;
import com.sap.sse.security.ui.loginpanel.LoginPanelCss;
import com.sap.sse.security.ui.shared.UserDTO;
/**
* A panel that can be used to implement an administration console. Widgets can be arranged in vertical and horizontal
* tabs ("L-shape"). The top-level element is the vertical tab panel. Widgets may either be added directly as the
* content of one vertical tab, or a horizontal tab panel can be added as the content widget of a vertical tab, in turn
* holding widgets in horizontal tabs.
* <p>
*
* After constructing an instance of this class, there are three ways for adding widgets:
* <ul>
* <li>{@link #addToVerticalTabPanel(RefreshableAdminConsolePanel, String, Permission)} adds a widget as a content
* element of a vertical tab</li>
* <li>{@link #addVerticalTab(String, String, Permission)} creates a horizontal tab panel and adds it as a content
* element of a vertical tab</li>
* <li>{@link #addToTabPanel(TabLayoutPanel, RefreshableAdminConsolePanel, String, Permission)} adds a widget as a
* content element of a horizontal tab</li>
* </ul>
*
* Widgets to be added need to be wrapped as {@link RefreshableAdminConsolePanel} holding the widget and receiving the
* refresh call when the widget is shown because the user has selected the tab. If the component doesn't require any
* refresh logic, an instance of {@link DefaultRefreshableAdminConsolePanel} can be used to wrap the widget.
* <p>
*
* After the widgets have been added, {@link #initUI()} must be called to assemble all tabs for the current user's
* roles. The {@link #initUI()} method must be called each time more widgets have been added dynamically.
* <p>
*
* For each widget added, a {@link Permission set of permissions} needs to be specified, any of which is sufficient to
* get to see the widget. When the user changes or has his/her permissions updated the set of tabs visible will be
* adjusted according to the new roles available for the logged-in user.
* <p>
*
* @author Axel Uhl (D043530)
*
*/
public class AdminConsolePanel extends DockLayoutPanel implements HandleTabSelectable{
private final UserService userService;
/**
* The administration console's UI depends on the user's roles. When the roles change then so shall the display of
* tabs. Required {@link Permission}s tell when they are to be made available based on the user's actual
* permissions. This map keeps track of the dependencies and allows the UI to adjust to role changes.<p>
*
* The values are the permissions, at least one of which is required from the user to be able to see the widget.
*/
private final LinkedHashSet<Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String>> roleSpecificTabs;
private final Map<Widget, Set<Permission>> permissionsAnyOfWhichIsRequiredToSeeWidget;
private final SelectionHandler<Integer> tabSelectionHandler;
/**
* The top-level vertical tab panel
*/
private final VerticalTabLayoutPanel topLevelTabPanel;
private final VerticalOrHorizontalTabLayoutPanel topLevelTabPanelWrapper;
/**
* Keys are the results of calling {@link RefreshableAdminConsolePanel#getWidget()} on their associated values. This
* allows the panel to find the refresh target when a widget has been selected in a tab panel.
*/
private final Map<Widget, RefreshableAdminConsolePanel> panelsByWidget;
private final PermissionsForRoleProvider permissionsForRoleProvider;
/**
* Generic selection handler that forwards selected tabs to a refresher that ensures that data gets reloaded. If
* you add a new tab then make sure to have a look at #refreshDataFor(Widget widget) to ensure that upon
* selection your tab gets the data refreshed.
*/
private class TabSelectionHandler implements SelectionHandler<Integer> {
@Override
public void onSelection(SelectionEvent<Integer> event) {
Object source = event.getSource();
if (source != null) {
if (source instanceof HorizontalTabLayoutPanel) {
final HorizontalTabLayoutPanel tabPanel = ((HorizontalTabLayoutPanel) source);
final Widget selectedPanel = tabPanel.getWidget(event.getSelectedItem());
refreshDataFor(selectedPanel);
} else if (source instanceof VerticalTabLayoutPanel) {
final VerticalTabLayoutPanel verticalTabLayoutPanel = (VerticalTabLayoutPanel) source;
Widget widgetAssociatedToVerticalTab = verticalTabLayoutPanel.getWidget(verticalTabLayoutPanel.getSelectedIndex());
if (widgetAssociatedToVerticalTab instanceof HorizontalTabLayoutPanel) {
HorizontalTabLayoutPanel selectedTabLayoutPanel = (HorizontalTabLayoutPanel) widgetAssociatedToVerticalTab;
final int selectedIndex = selectedTabLayoutPanel.getSelectedIndex();
if (selectedIndex >= 0) {
widgetAssociatedToVerticalTab = selectedTabLayoutPanel.getWidget(selectedIndex);
}
}
refreshDataFor(widgetAssociatedToVerticalTab);
}
}
}
private void refreshDataFor(Widget target) {
RefreshableAdminConsolePanel refreshTarget = panelsByWidget.get(unwrapScrollPanel(target));
if (refreshTarget != null) {
refreshTarget.refreshAfterBecomingVisible();
}
}
}
/**
* If the <code>widgetMaybeWrappedByScrollPanel</code> is a scroll panel, returns the content widget,
* otherwise <code>widgetMaybeWrappedByScrollPanel</code> is returned.
*/
private static Widget unwrapScrollPanel(Widget widgetMaybeWrappedByScrollPanel) {
final Widget target;
if (widgetMaybeWrappedByScrollPanel instanceof ScrollPanel) {
target = ((ScrollPanel) widgetMaybeWrappedByScrollPanel).getWidget();
} else {
target = widgetMaybeWrappedByScrollPanel;
}
return target;
}
public AdminConsolePanel(UserService userService, PermissionsForRoleProvider permissionsForRoleProvider,
ServerInfoRetriever buildVersionRetriever, String releaseNotesAnchorLabel,
String releaseNotesURL, ErrorReporter errorReporter, LoginPanelCss loginPanelCss, StringMessages stringMessages) {
super(Unit.EM);
this.permissionsForRoleProvider = permissionsForRoleProvider;
this.permissionsAnyOfWhichIsRequiredToSeeWidget = new HashMap<>();
this.userService = userService;
roleSpecificTabs = new LinkedHashSet<>();
this.panelsByWidget = new HashMap<>();
getUserService().addUserStatusEventHandler(new UserStatusEventHandler() {
@Override
public void onUserStatusChange(UserDTO user) {
updateTabDisplayForCurrentUser(user);
}
});
tabSelectionHandler = new TabSelectionHandler();
topLevelTabPanel = new VerticalTabLayoutPanel(2.5, Unit.EM);
topLevelTabPanel.addSelectionHandler(tabSelectionHandler);
topLevelTabPanel.ensureDebugId("AdministrationTabs");
topLevelTabPanelWrapper = new VerticalOrHorizontalTabLayoutPanel() {
@Override
public void add(Widget child, String text, boolean asHtml) {
topLevelTabPanel.add(child, text, asHtml);
topLevelTabPanel.forceLayout();
}
@Override
public boolean remove(Widget child) {
return topLevelTabPanel.remove(child);
}
@Override
public boolean remove(Widget child, boolean fireEvents) {
return topLevelTabPanel.remove(topLevelTabPanel.getWidgetIndex(child), fireEvents);
}
@Override
public Widget getPanel() {
return topLevelTabPanel;
}
@Override
public void selectTab(int index) {
topLevelTabPanel.selectTab(index);
}
@Override
public int getWidgetIndex(Widget child) {
return topLevelTabPanel.getWidgetIndex(child);
}
};
final DockPanel informationPanel = new DockPanel();
informationPanel.setSize("100%", "95%");
informationPanel.setSpacing(10);
informationPanel.add(errorReporter.getPersistentInformationWidget(), DockPanel.CENTER);
SystemInformationPanel sysinfoPanel = new SystemInformationPanel(buildVersionRetriever, errorReporter, stringMessages);
sysinfoPanel.ensureDebugId("SystemInformation");
final Anchor releaseNotesLink = new Anchor(new SafeHtmlBuilder().appendEscaped(releaseNotesAnchorLabel).toSafeHtml(), releaseNotesURL);
sysinfoPanel.add(releaseNotesLink);
informationPanel.add(sysinfoPanel, DockPanel.EAST);
informationPanel.setCellHorizontalAlignment(sysinfoPanel, HasHorizontalAlignment.ALIGN_RIGHT);
this.addSouth(informationPanel, 2.5);
this.add(topLevelTabPanel);
}
/**
* Invoke this method after having added all panels using
* {@link #addToTabPanel(TabLayoutPanel, RefreshableAdminConsolePanel, String, AdminConsoleFeatures)} or
* {@link #addToVerticalTabPanel(RefreshableAdminConsolePanel, String, AdminConsoleFeatures)} or
* {@link #addVerticalTab(String, String, AdminConsoleFeatures)}. Tabs can also dynamically be added after calling
* this method, but then this method needs to be invoked again to ensure that all all tabs are properly displayed
* for the current panel's state.
*/
public void initUI() {
updateTabDisplayForCurrentUser(getUserService().getCurrentUser());
if (topLevelTabPanel.getWidgetCount() > 0) {
topLevelTabPanel.selectTab(0);
}
}
private UserService getUserService() {
return userService;
}
private static interface VerticalOrHorizontalTabLayoutPanel {
void add(Widget child, String text, boolean asHtml);
boolean remove(Widget child);
boolean remove(Widget child, boolean fireEvents);
Widget getPanel();
void selectTab(int index);
int getWidgetIndex(Widget child);
}
/**
* Adds a new horizontal tab panel to the top-level vertical tab panel.
*
* @return the horizontal tab panel that was created and added to the top-level vertical tab panel; the panel returned can be specified
* as argument to {@link #addToTabPanel(TabLayoutPanel, Widget, String, AdminConsoleFeatures)}.
*/
public HorizontalTabLayoutPanel addVerticalTab(String tabTitle, String tabDebugId, Permission... requiresAnyOfThesePermissions) {
final HorizontalTabLayoutPanel newTabPanel = new HorizontalTabLayoutPanel(2.5, Unit.EM);
AbstractEntryPoint.setTabPanelSize(newTabPanel, "100%", "100%");
newTabPanel.addSelectionHandler(tabSelectionHandler);
newTabPanel.ensureDebugId(tabDebugId);
remeberWidgetLocationAndPermissions(topLevelTabPanelWrapper, newTabPanel, tabTitle, requiresAnyOfThesePermissions);
return newTabPanel;
}
/**
* Adds an administration panel as an entry to the top-level vertical panel, without an intermediary horizontal tab panel.
* This is useful for panels that form a top-level category of its own but don't require multiple panels to represent this
* top-level category.
*/
public void addToVerticalTabPanel(final RefreshableAdminConsolePanel panelToAdd, String tabTitle, Permission... requiresAnyOfThesePermissions) {
addToTabPanel(topLevelTabPanelWrapper, panelToAdd, tabTitle, requiresAnyOfThesePermissions);
}
private ScrollPanel wrapInScrollPanel(Widget panelToAdd) {
ScrollPanel scrollPanel = new ScrollPanel();
scrollPanel.add(panelToAdd);
panelToAdd.setSize("100%", "100%");
return scrollPanel;
}
public void addToTabPanel(final HorizontalTabLayoutPanel tabPanel, RefreshableAdminConsolePanel panelToAdd, String tabTitle, Permission... requiresAnyOfThesePermissions) {
VerticalOrHorizontalTabLayoutPanel wrapper = new VerticalOrHorizontalTabLayoutPanel() {
@Override
public void add(Widget child, String text, boolean asHtml) {
tabPanel.add(child, text, asHtml);
tabPanel.forceLayout();
}
@Override
public boolean remove(Widget child) {
return tabPanel.remove(child);
}
@Override
public boolean remove(Widget child, boolean fireEvents) {
return tabPanel.remove(tabPanel.getWidgetIndex(child), fireEvents);
}
@Override
public Widget getPanel() {
return tabPanel;
}
@Override
public void selectTab(int index) {
tabPanel.selectTab(index);
}
@Override
public int getWidgetIndex(Widget child) {
return tabPanel.getWidgetIndex(child);
}
};
addToTabPanel(wrapper, panelToAdd, tabTitle, requiresAnyOfThesePermissions);
}
/**
* Remembers in which tab panel the <code>panelToAdd</code> is to be displayed and for which feature; additionally, remembers adds
* a hook so that when the <code>panelToAdd</code>'s widget is selected then the {@link RefreshableAdminConsolePanel#refreshAfterBecomingVisible()}
* method can be called.
*/
private void addToTabPanel(VerticalOrHorizontalTabLayoutPanel tabPanel, RefreshableAdminConsolePanel panelToAdd, String tabTitle, Permission... requiresAnyOfThesePermissions) {
remeberWidgetLocationAndPermissions(tabPanel, wrapInScrollPanel(panelToAdd.getWidget()), tabTitle, requiresAnyOfThesePermissions);
panelsByWidget.put(panelToAdd.getWidget(), panelToAdd);
}
/**
* Remembers the tab panel in which the <code>widgetToAdd</code> is to be displayed and which permissions are
* sufficient to see the widget. For the <code>tabPanel</code>, all permissions provided here are added to the tab
* panel's permissions so that the user will see the tab panel as soon as the user may see any of the widgets inside
* that panel
*
* @param requiresAnyOfThesePermissions
* zero or more permissions; if no permissions are provided, the user will never be able to see the
* widget. Otherwise, if any of these permissions implies any of the permissions the user has, the user
* will be shown the widget. In particular, a "*" wildcard permission will show the widget to all users,
* regardless their actual permissions.
*/
private void remeberWidgetLocationAndPermissions(VerticalOrHorizontalTabLayoutPanel tabPanel, Widget widgetToAdd,
String tabTitle, Permission... requiresAnyOfThesePermissions) {
roleSpecificTabs.add(new Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String>(tabPanel, widgetToAdd, tabTitle));
final HashSet<Permission> permissionsAsSet = new HashSet<>(Arrays.asList(requiresAnyOfThesePermissions));
permissionsAnyOfWhichIsRequiredToSeeWidget.put(widgetToAdd, permissionsAsSet);
Set<Permission> permissionsForTabPanel = permissionsAnyOfWhichIsRequiredToSeeWidget.get(tabPanel.getPanel());
if (permissionsForTabPanel == null) {
permissionsForTabPanel = new HashSet<>();
permissionsAnyOfWhichIsRequiredToSeeWidget.put(tabPanel.getPanel(), permissionsForTabPanel);
}
permissionsForTabPanel.addAll(permissionsAsSet);
}
/**
* After initialization or whenever the user changes, the tab display is adjusted based on which roles are required
* to see which tabs. See {@link #roleSpecificTabs}. A selection event is fired when the tab currently selected
* was removed and another tab was therefore selected.
*/
private void updateTabDisplayForCurrentUser(UserDTO user) {
final Widget selectedPanel = getSelectedTab(null);
for (Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String> e : roleSpecificTabs) {
final Widget widgetToAddOrRemove = e.getB();
if (user != null && userHasPermissionsToSeeWidget(user, e.getB())) {
if (e.getA().getWidgetIndex(widgetToAddOrRemove) == -1) {
e.getA().add(widgetToAddOrRemove, e.getC(), /* asHtml */false);
}
} else {
e.getA().remove(widgetToAddOrRemove, /* fireEvents */ false);
}
}
getSelectedTab(selectedPanel);
}
/**
* If the top-level selected tab is a horizontal tab panel, its selected panel is returned; otherwise, the selected
* top-level panel is returned. If no top-level panel exists or is selected, {@code null} is returned.
*
* @param reselectCurrentSelectionIfNotSameAsThis
* if not {@code null}, the selected panel is {@link AbstractTabLayoutPanel#selectTab(Widget) selected}
* again in case it isn't the same as {@code reselectCurrentSelectionIfNotSameAsThis}, firing a selection
* event
*/
private Widget getSelectedTab(Widget reselectCurrentSelectionIfNotSameAsThis) {
final Widget topLevelSelectedTab;
Widget selectedTabInHorizontalTabPanel = null;
if (topLevelTabPanel.getSelectedIndex() != -1) {
topLevelSelectedTab = unwrapScrollPanel(topLevelTabPanel.getWidget(topLevelTabPanel.getSelectedIndex()));
if (topLevelSelectedTab instanceof AbstractTabLayoutPanel) {
AbstractTabLayoutPanel p = (AbstractTabLayoutPanel) topLevelSelectedTab;
if (p.getSelectedIndex() != -1) {
selectedTabInHorizontalTabPanel = unwrapScrollPanel(p.getWidget(p.getSelectedIndex()));
if (reselectCurrentSelectionIfNotSameAsThis != null && selectedTabInHorizontalTabPanel != reselectCurrentSelectionIfNotSameAsThis) {
SelectionEvent.fire(p, p.getSelectedIndex());
}
} else {
selectedTabInHorizontalTabPanel = null;
}
} else {
if (reselectCurrentSelectionIfNotSameAsThis != null && topLevelSelectedTab != reselectCurrentSelectionIfNotSameAsThis) {
SelectionEvent.fire(topLevelTabPanel, topLevelTabPanel.getSelectedIndex());
}
}
} else {
topLevelSelectedTab = null;
}
return selectedTabInHorizontalTabPanel != null ? selectedTabInHorizontalTabPanel : topLevelSelectedTab;
}
@Override
public void selectTabByNames(String verticalTabName, String horizontalTabName, Map<String, String> params) {
if (verticalTabName == null) {
return;
}
Widget widgetForSetup = null; //Remember widget for set up
for (Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String> e : roleSpecificTabs) {
VerticalOrHorizontalTabLayoutPanel panel = e.getA();
Widget currentWidget = e.getB();
if (panel == topLevelTabPanelWrapper && verticalTabName.equals(e.getC())) { // for vertical panel
int index = panel.getWidgetIndex(currentWidget);
panel.selectTab(index);
if (horizontalTabName == null) {//If we don't have horizontal tab will setup vertical tab.
widgetForSetup = currentWidget;
}
} else if (horizontalTabName != null && horizontalTabName.equals(e.getC())) { // for horizontal panel
int index = panel.getWidgetIndex(currentWidget);
panel.selectTab(index);
widgetForSetup = currentWidget;
}
}
panelsByWidget.get(unwrapScrollPanel(widgetForSetup)).setupWidgetByParams(params);;
}
/**
* A user is defined to have permission to see a widget if the widget's required permissions imply any of the permissions the
* user has. This may at first seem the wrong way around. However, the problem is that a widget cannot express a general permission
* that is implied by any detailed permissions. Wildcard permissions don't work this way. Instead, a wildcard permission implies
* detailed permissions. This way, if the widget requires, say, "event:*:*" (or "event" for short), this permission implies
* all more detailed event permissions such as "event:write:9456192873". Therefore, the permissions provided for widgets
* must imply a permission the user has in order for the user to see the tab. More detailed permissions checks can then be
* applied at a more detailed level of the UI and, of course, in the back end. Additionally, if any of the user's permissions
* implies the required permission (e.g., the user having "*" as the administrator's permission), permission to see the widget
* is also implied.
*/
private boolean userHasPermissionsToSeeWidget(UserDTO user, Widget widget) {
for (Permission requiredStringPermission : permissionsAnyOfWhichIsRequiredToSeeWidget.get(widget)) {
WildcardPermission requiredPermission = new WildcardPermission(requiredStringPermission.getStringPermission());
for (String userStringPermission : user.getAllPermissions(permissionsForRoleProvider)) {
WildcardPermission userPermission = new WildcardPermission(userStringPermission);
if (requiredPermission.implies(userPermission) || userPermission.implies(requiredPermission)) {
return true;
}
}
}
return false;
}
}
@@ -1,26 +1,26 @@
package com.sap.sse.gwt.adminconsole;
import java.util.Map;
import com.google.gwt.user.client.ui.Widget;
public class DefaultRefreshableAdminConsolePanel<W extends Widget> implements RefreshableAdminConsolePanel {
@Override
public void refreshAfterBecomingVisible() {
}
private final W widget;
public DefaultRefreshableAdminConsolePanel(W widget) {
this.widget = widget;
}
@Override
public void setupWidgetByParams(Map<String, String> params){
}
@Override
public W getWidget() {
return widget;
}
}
package com.sap.sse.gwt.adminconsole;
import java.util.Map;
import com.google.gwt.user.client.ui.Widget;
public class DefaultRefreshableAdminConsolePanel<W extends Widget> implements RefreshableAdminConsolePanel {
@Override
public void refreshAfterBecomingVisible() {
}
private final W widget;
public DefaultRefreshableAdminConsolePanel(W widget) {
this.widget = widget;
}
@Override
public void setupWidgetByParams(Map<String, String> params){
}
@Override
public W getWidget() {
return widget;
}
}
@@ -1,23 +1,23 @@
package com.sap.sse.gwt.adminconsole;
import java.util.Map;
import com.google.gwt.user.client.ui.Widget;
public interface RefreshableAdminConsolePanel {
/**
* Invoked when the {@link #getWidget widget} has become visible, e.g., by the user
* selecting the tab holding the panel.
*/
void refreshAfterBecomingVisible();
/**
* The widget representing the panel to place in the administration console
*/
Widget getWidget();
/**
* Invoked when the we handle selected tab by name {@link HandleTabSelectable} to set up a tab with parameters.
*/
void setupWidgetByParams(Map<String, String> params);
}
package com.sap.sse.gwt.adminconsole;
import java.util.Map;
import com.google.gwt.user.client.ui.Widget;
public interface RefreshableAdminConsolePanel {
/**
* Invoked when the {@link #getWidget widget} has become visible, e.g., by the user
* selecting the tab holding the panel.
*/
void refreshAfterBecomingVisible();
/**
* The widget representing the panel to place in the administration console
*/
Widget getWidget();
/**
* Invoked when the we handle selected tab by name {@link HandleTabSelectable} to set up a tab with parameters.
*/
void setupWidgetByParams(Map<String, String> params);
}
@@ -1,96 +1,96 @@
package com.sap.sse.gwt.adminconsole;
import com.google.gwt.i18n.client.Messages;
public interface StringMessages extends Messages {
String upload();
String remove();
String removeResult(String status, String message);
String uploadSuccessful();
String fileUploadResult(String status, String message);
String removeUploadedFile();
String pleaseOnlyUploadContentYouHaveAllUsageRightsFor();
String send();
String version(String buildVersion);
String unknown();
String refresh();
String explainReplicasRegistered();
String explainConnectionsToMaster();
String stopAllReplicas();
String connectToMaster();
String stopConnectionToMaster();
String errorStartingReplication(String b, String c, String message);
String loading();
String registeredAt(String string);
String dropReplicaConnection();
String replicables();
String averageNumberOfOperationsPerMessage();
String numberOfQueueMessagesSent();
String averageMessageSize();
String totalSize();
String totalNumberOfOperations();
String explainNoConnectionsFromReplicas();
String warningServerIsReplica();
String replicatingFromMaster(String hostname, int messagingPort, int servletPort, String messagingHostname,
String exchangeName, String string);
String explainNoConnectionsToMaster();
String errorFetchingReplicaData(String message);
String connect();
String enterMaster();
String cancel();
String hostname();
String explainReplicationHostname();
String exchangeHost();
String explainExchangeHostName();
String exchangeName();
String explainReplicationExchangeName();
String messagingPortNumber();
String explainReplicationExchangePort();
String servletPortNumber();
String explainReplicationServletPort();
String ok();
}
package com.sap.sse.gwt.adminconsole;
import com.google.gwt.i18n.client.Messages;
public interface StringMessages extends Messages {
String upload();
String remove();
String removeResult(String status, String message);
String uploadSuccessful();
String fileUploadResult(String status, String message);
String removeUploadedFile();
String pleaseOnlyUploadContentYouHaveAllUsageRightsFor();
String send();
String version(String buildVersion);
String unknown();
String refresh();
String explainReplicasRegistered();
String explainConnectionsToMaster();
String stopAllReplicas();
String connectToMaster();
String stopConnectionToMaster();
String errorStartingReplication(String b, String c, String message);
String loading();
String registeredAt(String string);
String dropReplicaConnection();
String replicables();
String averageNumberOfOperationsPerMessage();
String numberOfQueueMessagesSent();
String averageMessageSize();
String totalSize();
String totalNumberOfOperations();
String explainNoConnectionsFromReplicas();
String warningServerIsReplica();
String replicatingFromMaster(String hostname, int messagingPort, int servletPort, String messagingHostname,
String exchangeName, String string);
String explainNoConnectionsToMaster();
String errorFetchingReplicaData(String message);
String connect();
String enterMaster();
String cancel();
String hostname();
String explainReplicationHostname();
String exchangeHost();
String explainExchangeHostName();
String exchangeName();
String explainReplicationExchangeName();
String messagingPortNumber();
String explainReplicationExchangePort();
String servletPortNumber();
String explainReplicationServletPort();
String ok();
}
@@ -1,37 +1,37 @@
package com.sap.sse.gwt.adminconsole;
import com.google.gwt.dom.client.Style;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.ServerInfoDTO;
import com.sap.sse.gwt.client.ServerInfoRetriever;
public class SystemInformationPanel extends FlowPanel {
private final Label buildVersionText;
public SystemInformationPanel(final ServerInfoRetriever buildVersionRetriever, final ErrorReporter errorReporter, final StringMessages stringMessages) {
super();
buildVersionText = new Label("");
addFloatingWidget(buildVersionText);
buildVersionRetriever.getServerInfo(new AsyncCallback<ServerInfoDTO>() {
@Override
public void onSuccess(ServerInfoDTO result) {
buildVersionText.setText(stringMessages.version(result.getBuildVersion()));
}
@Override
public void onFailure(Throwable caught) {
buildVersionText.setText(stringMessages.version(stringMessages.unknown()));
}
});
}
private void addFloatingWidget(Widget w) {
w.getElement().getStyle().setFloat(Style.Float.LEFT);
add(w);
}
}
package com.sap.sse.gwt.adminconsole;
import com.google.gwt.dom.client.Style;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.ServerInfoDTO;
import com.sap.sse.gwt.client.ServerInfoRetriever;
public class SystemInformationPanel extends FlowPanel {
private final Label buildVersionText;
public SystemInformationPanel(final ServerInfoRetriever buildVersionRetriever, final ErrorReporter errorReporter, final StringMessages stringMessages) {
super();
buildVersionText = new Label("");
addFloatingWidget(buildVersionText);
buildVersionRetriever.getServerInfo(new AsyncCallback<ServerInfoDTO>() {
@Override
public void onSuccess(ServerInfoDTO result) {
buildVersionText.setText(stringMessages.version(result.getBuildVersion()));
}
@Override
public void onFailure(Throwable caught) {
buildVersionText.setText(stringMessages.version(stringMessages.unknown()));
}
});
}
private void addFloatingWidget(Widget w) {
w.getElement().getStyle().setFloat(Style.Float.LEFT);
add(w);
}
}
@@ -1,200 +1,200 @@
package com.sap.sse.gwt.adminconsole;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SubmitButton;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
/**
* A {@link TextBox} together with an upload button that can use the file storage service to
* save the file and produce a URL for it which is then taken over into the text field.
*
* @author Axel Uhl (d043530)
*
*/
public class URLFieldWithFileUpload extends Composite implements HasValue<String> {
private final TextBox urlTextBox;
private final FileUpload fileUploadField;
private String uri;
private final Button removeButton;
private boolean valueChangeHandlerInitialized = false;
public URLFieldWithFileUpload(final StringMessages stringMessages) {
final VerticalPanel mainPanel = new VerticalPanel();
final HorizontalPanel imageUrlPanel = new HorizontalPanel();
mainPanel.add(new Label(stringMessages.pleaseOnlyUploadContentYouHaveAllUsageRightsFor()));
mainPanel.add(imageUrlPanel);
final FormPanel removePanel = new FormPanel();
removePanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
@Override
public void onSubmitComplete(SubmitCompleteEvent event) {
final JSONObject resultJson = parseAfterReplacingSurroundingPreElement(event.getResults()).isObject();
Window.alert(stringMessages.removeResult(resultJson.get("status").isString().stringValue(),
resultJson.get("message") == null ? "" : resultJson.get("message").isString().stringValue()));
setURL("");
}
});
removePanel.setMethod(FormPanel.METHOD_POST);
removeButton = new Button(stringMessages.removeUploadedFile());
removeButton.setEnabled(false); // the button shall only be enabled as long as we know the URI for removal
removeButton.ensureDebugId("RemoveButton");
removeButton.setTitle(stringMessages.remove());
removeButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
removePanel.setAction("/sailingserver/api/v1/file?uri="+uri);
removePanel.submit();
uri = null;
}
});
removePanel.add(removeButton);
urlTextBox = new TextBox();
urlTextBox.setWidth("400px");
imageUrlPanel.add(urlTextBox);
imageUrlPanel.add(removePanel);
// the upload panel
FormPanel uploadFormPanel = new FormPanel();
mainPanel.add(uploadFormPanel);
HorizontalPanel uploadPanel = new HorizontalPanel();
uploadPanel.setSpacing(3);
uploadFormPanel.add(uploadPanel);
uploadFormPanel.setAction("/sailingserver/fileupload");
uploadFormPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
uploadFormPanel.setMethod(FormPanel.METHOD_POST);
fileUploadField = new FileUpload();
final Label uploadLabel = new Label(stringMessages.upload()+ ":");
uploadPanel.add(uploadLabel);
uploadPanel.setCellVerticalAlignment(uploadLabel, HasVerticalAlignment.ALIGN_MIDDLE);
uploadPanel.add(fileUploadField);
final InputElement inputElement = fileUploadField.getElement().cast();
inputElement.setName("file");
final SubmitButton submitButton = new SubmitButton(stringMessages.send());
submitButton.setEnabled(false);
fileUploadField.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
if(fileUploadField.getFilename() != null && !fileUploadField.getFilename().isEmpty()) {
submitButton.setEnabled(true);
}
}
});
uploadPanel.add(submitButton);
uploadFormPanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
@Override
public void onSubmitComplete(SubmitCompleteEvent event) {
String result = event.getResults();
JSONArray resultJson = parseAfterReplacingSurroundingPreElement(result).isArray();
if (resultJson != null) {
if (resultJson.get(0).isObject().get("file_uri") != null) {
uri = resultJson.get(0).isObject().get("file_uri").isString().stringValue();
setValue(uri, true);
removeButton.setEnabled(true);
Window.alert(stringMessages.uploadSuccessful());
} else {
Window.alert(stringMessages.fileUploadResult(resultJson.get(0).isObject().get("status").isString().stringValue(),
resultJson.get(0).isObject().get("message").isString().stringValue()));
}
}
}
});
initWidget(mainPanel);
}
/**
* Returns <code>null</code> if the trimmed URL field contents are empty
*/
public String getURL() {
final String trimmedUrl = urlTextBox.getValue().trim();
return trimmedUrl.isEmpty() ? null : trimmedUrl;
}
public void setURL(String imageURL) {
if (imageURL == null) {
urlTextBox.setValue("");
uri = null;
removeButton.setEnabled(false);
} else {
urlTextBox.setValue(imageURL);
uri = imageURL;
removeButton.setEnabled(true);
}
}
public FocusWidget getInitialFocusWidget() {
return urlTextBox;
}
private HandlerRegistration addChangeHandler(ChangeHandler handler) {
return addDomHandler(handler, ChangeEvent.getType());
}
@Override
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) {
if (!valueChangeHandlerInitialized) {
valueChangeHandlerInitialized = true;
addChangeHandler(new ChangeHandler() {
public void onChange(ChangeEvent event) {
ValueChangeEvent.fire(URLFieldWithFileUpload.this, getValue());
}
});
}
return addHandler(handler, ValueChangeEvent.getType());
}
@Override
public String getValue() {
return getURL();
}
@Override
public void setValue(String value) {
setURL(value);
}
@Override
public void setValue(String value, boolean fireEvents) {
setValue(value);
if (fireEvents) {
ValueChangeEvent.fire(this, value);
}
}
/**
* See https://github.com/twilson63/ngUpload/issues/43 and
* https://www.sencha.com/forum/showthread.php?132949-Fileupload-Invalid-JSON-string. The JSON response of the file
* upload is wrapped by a &lt;pre&gt; element which needs to be stripped off if present to allow the JSON parser to
* succeed.
*/
private JSONValue parseAfterReplacingSurroundingPreElement(String jsonString) {
return JSONParser.parseStrict(jsonString.replaceFirst("<pre[^>]*>(.*)</pre>", "$1"));
}
}
package com.sap.sse.gwt.adminconsole;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SubmitButton;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
/**
* A {@link TextBox} together with an upload button that can use the file storage service to
* save the file and produce a URL for it which is then taken over into the text field.
*
* @author Axel Uhl (d043530)
*
*/
public class URLFieldWithFileUpload extends Composite implements HasValue<String> {
private final TextBox urlTextBox;
private final FileUpload fileUploadField;
private String uri;
private final Button removeButton;
private boolean valueChangeHandlerInitialized = false;
public URLFieldWithFileUpload(final StringMessages stringMessages) {
final VerticalPanel mainPanel = new VerticalPanel();
final HorizontalPanel imageUrlPanel = new HorizontalPanel();
mainPanel.add(new Label(stringMessages.pleaseOnlyUploadContentYouHaveAllUsageRightsFor()));
mainPanel.add(imageUrlPanel);
final FormPanel removePanel = new FormPanel();
removePanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
@Override
public void onSubmitComplete(SubmitCompleteEvent event) {
final JSONObject resultJson = parseAfterReplacingSurroundingPreElement(event.getResults()).isObject();
Window.alert(stringMessages.removeResult(resultJson.get("status").isString().stringValue(),
resultJson.get("message") == null ? "" : resultJson.get("message").isString().stringValue()));
setURL("");
}
});
removePanel.setMethod(FormPanel.METHOD_POST);
removeButton = new Button(stringMessages.removeUploadedFile());
removeButton.setEnabled(false); // the button shall only be enabled as long as we know the URI for removal
removeButton.ensureDebugId("RemoveButton");
removeButton.setTitle(stringMessages.remove());
removeButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
removePanel.setAction("/sailingserver/api/v1/file?uri="+uri);
removePanel.submit();
uri = null;
}
});
removePanel.add(removeButton);
urlTextBox = new TextBox();
urlTextBox.setWidth("400px");
imageUrlPanel.add(urlTextBox);
imageUrlPanel.add(removePanel);
// the upload panel
FormPanel uploadFormPanel = new FormPanel();
mainPanel.add(uploadFormPanel);
HorizontalPanel uploadPanel = new HorizontalPanel();
uploadPanel.setSpacing(3);
uploadFormPanel.add(uploadPanel);
uploadFormPanel.setAction("/sailingserver/fileupload");
uploadFormPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
uploadFormPanel.setMethod(FormPanel.METHOD_POST);
fileUploadField = new FileUpload();
final Label uploadLabel = new Label(stringMessages.upload()+ ":");
uploadPanel.add(uploadLabel);
uploadPanel.setCellVerticalAlignment(uploadLabel, HasVerticalAlignment.ALIGN_MIDDLE);
uploadPanel.add(fileUploadField);
final InputElement inputElement = fileUploadField.getElement().cast();
inputElement.setName("file");
final SubmitButton submitButton = new SubmitButton(stringMessages.send());
submitButton.setEnabled(false);
fileUploadField.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
if(fileUploadField.getFilename() != null && !fileUploadField.getFilename().isEmpty()) {
submitButton.setEnabled(true);
}
}
});
uploadPanel.add(submitButton);
uploadFormPanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
@Override
public void onSubmitComplete(SubmitCompleteEvent event) {
String result = event.getResults();
JSONArray resultJson = parseAfterReplacingSurroundingPreElement(result).isArray();
if (resultJson != null) {
if (resultJson.get(0).isObject().get("file_uri") != null) {
uri = resultJson.get(0).isObject().get("file_uri").isString().stringValue();
setValue(uri, true);
removeButton.setEnabled(true);
Window.alert(stringMessages.uploadSuccessful());
} else {
Window.alert(stringMessages.fileUploadResult(resultJson.get(0).isObject().get("status").isString().stringValue(),
resultJson.get(0).isObject().get("message").isString().stringValue()));
}
}
}
});
initWidget(mainPanel);
}
/**
* Returns <code>null</code> if the trimmed URL field contents are empty
*/
public String getURL() {
final String trimmedUrl = urlTextBox.getValue().trim();
return trimmedUrl.isEmpty() ? null : trimmedUrl;
}
public void setURL(String imageURL) {
if (imageURL == null) {
urlTextBox.setValue("");
uri = null;
removeButton.setEnabled(false);
} else {
urlTextBox.setValue(imageURL);
uri = imageURL;
removeButton.setEnabled(true);
}
}
public FocusWidget getInitialFocusWidget() {
return urlTextBox;
}
private HandlerRegistration addChangeHandler(ChangeHandler handler) {
return addDomHandler(handler, ChangeEvent.getType());
}
@Override
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) {
if (!valueChangeHandlerInitialized) {
valueChangeHandlerInitialized = true;
addChangeHandler(new ChangeHandler() {
public void onChange(ChangeEvent event) {
ValueChangeEvent.fire(URLFieldWithFileUpload.this, getValue());
}
});
}
return addHandler(handler, ValueChangeEvent.getType());
}
@Override
public String getValue() {
return getURL();
}
@Override
public void setValue(String value) {
setURL(value);
}
@Override
public void setValue(String value, boolean fireEvents) {
setValue(value);
if (fireEvents) {
ValueChangeEvent.fire(this, value);
}
}
/**
* See https://github.com/twilson63/ngUpload/issues/43 and
* https://www.sencha.com/forum/showthread.php?132949-Fileupload-Invalid-JSON-string. The JSON response of the file
* upload is wrapped by a &lt;pre&gt; element which needs to be stripped off if present to allow the JSON parser to
* succeed.
*/
private JSONValue parseAfterReplacingSurroundingPreElement(String jsonString) {
return JSONParser.parseStrict(jsonString.replaceFirst("<pre[^>]*>(.*)</pre>", "$1"));
}
}