/*
* Copyright 2000-2016 Vaadin Ltd.
*
* 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 com.vaadin.tests.rpclogger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.vaadin.server.ClientConnector;
import com.vaadin.server.ErrorHandler;
import com.vaadin.server.ServerRpcMethodInvocation;
import com.vaadin.server.VaadinRequest;
import com.vaadin.shared.communication.LegacyChangeVariablesInvocation;
import com.vaadin.shared.communication.MethodInvocation;
import com.vaadin.tests.components.AbstractTestUIWithLog;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Notification.Type;
import com.vaadin.v7.ui.ListSelect;
public class RPCLoggerUI extends AbstractTestUIWithLog implements ErrorHandler {
private List<Action> lastActions = new ArrayList<>();
public static class Action {
public Action(ClientConnector connector, MethodInvocation invocation) {
target = connector;
this.invocation = invocation;
}
private MethodInvocation invocation;
private ClientConnector target;
}
@Override
protected int getLogSize() {
return 10;
}
@Override
protected void setup(VaadinRequest request) {
setErrorHandler(this);
addComponent(new Button("Do something"));
ListSelect s = new ListSelect();
s.setMultiSelect(true);
s.addItem("foo");
s.addItem("bar");
addComponent(s);
addComponent(new Button("Action, which will fail", new ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
throw new RuntimeException("Something went wrong");
}
}));
}
public void recordInvocation(ClientConnector connector,
LegacyChangeVariablesInvocation legacyInvocation) {
addAction(new Action(connector, legacyInvocation));
}
public void recordInvocation(ClientConnector connector,
ServerRpcMethodInvocation invocation) {
addAction(new Action(connector, invocation));
}
private void addAction(Action action) {
while (lastActions.size() >= 5) {
lastActions.remove(0);
}
lastActions.add(action);
}
public String formatAction(ClientConnector connector,
LegacyChangeVariablesInvocation legacyInvocation) {
String connectorIdentifier = getConnectorIdentifier(connector);
Map<String, Object> changes = legacyInvocation.getVariableChanges();
String rpcInfo = "";
for (String key : changes.keySet()) {
Object value = changes.get(key);
rpcInfo += key + ": " + formatValue(value);
}
return "Legacy RPC " + rpcInfo + " for " + connectorIdentifier;
}
public String formatAction(ClientConnector connector,
ServerRpcMethodInvocation invocation) {
String connectorIdentifier = getConnectorIdentifier(connector);
String rpcInfo = invocation.getInterfaceName() + "."
+ invocation.getMethodName() + " (";
for (Object o : invocation.getParameters()) {
rpcInfo += formatValue(o);
rpcInfo += ",";
}
rpcInfo = rpcInfo.substring(0, rpcInfo.length() - 2) + ")";
return "RPC " + rpcInfo + " for " + connectorIdentifier;
}
private String formatValue(Object value) {
if (value == null) {
return "null";
}
if (value instanceof String) {
return (String) value;
} else if (value instanceof Object[]) {
String formatted = "";
for (Object o : ((Object[]) value)) {
formatted += formatValue(o) + ",";
}
return formatted;
} else {
return value.toString();
}
}
private String getConnectorIdentifier(ClientConnector connector) {
String connectorIdentifier = connector.getClass().getSimpleName();
if (connector instanceof AbstractComponent) {
String caption = ((AbstractComponent) connector).getCaption();
if (caption != null) {
connectorIdentifier += " - " + caption;
}
}
return "'" + connectorIdentifier + "'";
}
@Override
public void error(com.vaadin.server.ErrorEvent event) {
String msg = "";
for (int i = 0; i < lastActions.size(); i++) {
Action action = lastActions.get(i);
if (action.invocation instanceof ServerRpcMethodInvocation) {
msg += "\n" + (i + 1) + " " + formatAction(action.target,
(ServerRpcMethodInvocation) action.invocation);
} else {
msg += "\n" + (i + 1) + " " + formatAction(action.target,
(LegacyChangeVariablesInvocation) action.invocation);
}
}
msg += "\n";
msg += "\n";
msg += "This error should not really be shown but logged for later analysis.";
Notification.show(
"Something went wrong. Actions leading up to this error were:",
msg, Type.ERROR_MESSAGE);
// log(msg);
}
}