xLogs = xLogService.retrieveXLogDataListByGxid(gxidRequest);
return CommonResultView.success(xLogs);
}
diff --git a/scouter.webapp/src/main/java/scouterx/webapp/layer/service/UserTokenService.java b/scouter.webapp/src/main/java/scouterx/webapp/layer/service/UserTokenService.java
index e1347bdc1..5f7abc3c0 100644
--- a/scouter.webapp/src/main/java/scouterx/webapp/layer/service/UserTokenService.java
+++ b/scouter.webapp/src/main/java/scouterx/webapp/layer/service/UserTokenService.java
@@ -29,9 +29,14 @@
import scouterx.webapp.framework.session.UserTokenCache;
import scouterx.webapp.model.scouter.SUser;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
/**
* @author Gun Lee (gunlee01@gmail.com) on 2017. 8. 27.
- *
+ *
* It use scouter kv store in which data only can be added not delete or modify.
* (We will make it better in a latter version.)
*/
@@ -40,8 +45,8 @@ public class UserTokenService {
private ConfigureAdaptor conf = ConfigureManager.getConfigure();
private final static float TOUCH_RATE = 0.1f;
- private int sessionExpireSec = (int) (conf.getNetHttpApiSessionTimeout() * (1.0f + TOUCH_RATE));
- private int SessionTouchThresholdSec = (int) (conf.getNetHttpApiSessionTimeout() * TOUCH_RATE);
+ public int sessionExpireSec = (int) (conf.getNetHttpApiSessionTimeout() * (1.0f + TOUCH_RATE));
+ public int SessionTouchThresholdSec = (int) (conf.getNetHttpApiSessionTimeout() * TOUCH_RATE);
private SessionIdGenerator sessionIdGenerator = new SessionIdGenerator();
private CustomKvStoreService customKvStoreService = new CustomKvStoreService();
@@ -51,8 +56,11 @@ public class UserTokenService {
*/
public String publishToken(final Server server, final SUser user) {
UserToken userToken = UserToken.newToken(user.getId(), sessionIdGenerator.generateSessionId(), server.getId());
- UserTokenCache.getInstance().put(user.getId(), userToken);
- customKvStoreService.set(SESSION_STORE, userToken.getStoreKey(), userToken.toStoreValue(), sessionExpireSec, server);
+ UserTokenCache.getInstance().put(userToken);
+
+ String mergedStoreValue = getAndMergeToStoredValue(userToken);
+ customKvStoreService.set(SESSION_STORE, userToken.getUserId(), mergedStoreValue, sessionExpireSec, server);
+
return userToken.toBearerToken();
}
@@ -60,17 +68,14 @@ public String publishToken(final Server server, final SUser user) {
* check user session & renew token's footprint if valid
*/
public void validateToken(UserToken token) {
- UserToken tokenTrusted = UserTokenCache.getInstance().get(token.getId());
+ UserToken tokenTrusted = UserTokenCache.getInstance().get(token);
if (tokenTrusted == null) {
- String stored = customKvStoreService.get(SESSION_STORE, token.getStoreKey(), ServerManager.getInstance().getServerIfNullDefault(token.getServerId()));
- if (StringUtils.isNotBlank(stored)) {
- tokenTrusted = UserToken.fromStoreValue(stored, token.getServerId());
- if (tokenTrusted != null) {
- UserTokenCache.getInstance().put(tokenTrusted.getId(), tokenTrusted);
- }
+ tokenTrusted = getStoredMatchedToken(token);
+ if (tokenTrusted != null) {
+ UserTokenCache.getInstance().put(tokenTrusted);
}
}
- if (tokenTrusted == null || !tokenTrusted.getToken().equals(token.getToken()) || tokenTrusted.isExpired(sessionExpireSec)) {
+ if (tokenTrusted == null || tokenTrusted.isExpired(sessionExpireSec)) {
throw ErrorState.SESSION_EXPIRED.newBizException();
}
if (tokenTrusted.needToBeRenewed(SessionTouchThresholdSec)) {
@@ -82,9 +87,40 @@ public void validateToken(UserToken token) {
* renew token's footprint
*/
private void touchToken(UserToken token) {
- UserToken userToken = token.renew();
- UserTokenCache.getInstance().put(userToken.getId(), userToken);
- customKvStoreService.set(SESSION_STORE, userToken.getStoreKey(), userToken.toStoreValue(), sessionExpireSec,
- ServerManager.getInstance().getServer(token.getServerId()));
+ UserToken renewedToken = token.renew();
+
+ UserTokenCache.getInstance().putAsRecent(renewedToken);
+ String mergedStoreValue = getAndMergeToStoredValue(renewedToken);
+
+ customKvStoreService.set(SESSION_STORE, renewedToken.getUserId(), mergedStoreValue, sessionExpireSec, ServerManager.getInstance().getServer(renewedToken.getServerId()));
+ }
+
+ private UserToken getStoredMatchedToken(UserToken userToken) {
+ String tokens = customKvStoreService.get(SESSION_STORE, userToken.getUserId(), ServerManager.getInstance().getServerIfNullDefault(userToken.getServerId()));
+ Map userTokenMap = Arrays.stream(tokens.split(":"))
+ .map(v -> UserToken.fromStoreValue(v, 0))
+ .collect(Collectors.toMap(UserToken::getToken, Function.identity()));
+
+ return userTokenMap.get(userToken.getToken());
+ }
+
+ String getAndMergeToStoredValue(UserToken userToken) {
+ String tokens = customKvStoreService.get(SESSION_STORE, userToken.getUserId(), ServerManager.getInstance().getServerIfNullDefault(userToken.getServerId()));
+ return mergeStoredTokensWith(tokens, userToken);
+ }
+
+ String mergeStoredTokensWith(String tokens, UserToken userToken) {
+ if (StringUtils.isBlank(tokens)) {
+ return userToken.toStoreValue();
+ }
+ Map userTokenMap = Arrays.stream(tokens.split(":"))
+ .map(v -> UserToken.fromStoreValue(v, 0))
+ .filter(v -> v.isNotExpired(sessionExpireSec))
+ .collect(Collectors.toMap(UserToken::getToken, Function.identity()));
+
+ userTokenMap.put(userToken.getToken(), userToken);
+ return userTokenMap.values().stream()
+ .map(UserToken::toStoreValue)
+ .collect(Collectors.joining(":"));
}
}
diff --git a/scouter.webapp/src/main/java/scouterx/webapp/layer/service/XLogService.java b/scouter.webapp/src/main/java/scouterx/webapp/layer/service/XLogService.java
index 189deff28..7828a5bd4 100644
--- a/scouter.webapp/src/main/java/scouterx/webapp/layer/service/XLogService.java
+++ b/scouter.webapp/src/main/java/scouterx/webapp/layer/service/XLogService.java
@@ -22,6 +22,7 @@
import scouterx.webapp.layer.consumer.XLogConsumer;
import scouterx.webapp.model.XLogData;
import scouterx.webapp.model.scouter.SXLog;
+import scouterx.webapp.request.MultiXLogRequest;
import scouterx.webapp.request.SearchXLogRequest;
import scouterx.webapp.request.PageableXLogRequest;
import scouterx.webapp.request.RealTimeXLogRequest;
@@ -88,16 +89,24 @@ public SXLog retrieveSingleXLog(final SingleXLogRequest singleXlogRequest) {
/**
* retrieve Xlog List by gxid
*/
- public List retrieveXLogsByGxid(final GxidXLogRequest xlogRequest) {
- return xLogConsumer.retrieveXLogsByGxid(xlogRequest);
+ public List retrieveXLogListByGxid(final GxidXLogRequest xlogRequest) {
+ return xLogConsumer.retrieveXLogListByGxid(xlogRequest);
}
/**
* retrieve Xlog data List by gxid
*/
- public List retrieveXLogDatasByGxid(final GxidXLogRequest xlogRequest) {
- return xLogConsumer.retrieveXLogDatasByGxid(xlogRequest);
+ public List retrieveXLogDataListByGxid(final GxidXLogRequest xlogRequest) {
+ return xLogConsumer.retrieveXLogDataListByGxid(xlogRequest);
}
+ /**
+ * retrieve Xlog data List by txids
+ */
+ public List retrieveXLogDataListByTxids(final MultiXLogRequest multiXLogRequest) {
+ return xLogConsumer.retrieveXLogDataListByTxids(multiXLogRequest);
+ }
+
+
}
diff --git a/scouter.webapp/src/main/java/scouterx/webapp/layer/websock/BasicSocket.java b/scouter.webapp/src/main/java/scouterx/webapp/layer/websock/BasicSocket.java
new file mode 100644
index 000000000..19e12e85d
--- /dev/null
+++ b/scouter.webapp/src/main/java/scouterx/webapp/layer/websock/BasicSocket.java
@@ -0,0 +1,52 @@
+package scouterx.webapp.layer.websock;
+
+import lombok.extern.slf4j.Slf4j;
+
+import javax.websocket.CloseReason;
+import javax.websocket.OnClose;
+import javax.websocket.OnError;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.RemoteEndpoint;
+import javax.websocket.Session;
+import javax.websocket.server.ServerEndpoint;
+
+@ServerEndpoint("/basic")
+@Slf4j
+public class BasicSocket
+{
+ private Session session;
+ private RemoteEndpoint.Async remote;
+
+ @OnClose
+ public void onWebSocketClose(CloseReason close)
+ {
+ this.session = null;
+ this.remote = null;
+ log.info("WebSocket Close: {} - {}",close.getCloseCode(),close.getReasonPhrase());
+ }
+
+ @OnOpen
+ public void onWebSocketOpen(Session session)
+ {
+ this.session = session;
+ this.remote = this.session.getAsyncRemote();
+ log.info("WebSocket Connect: {}",session);
+ this.remote.sendText("You are now connected to " + this.getClass().getName());
+ }
+
+ @OnError
+ public void onWebSocketError(Throwable cause)
+ {
+ log.warn("WebSocket Error",cause);
+ }
+
+ @OnMessage
+ public String onWebSocketText(String message)
+ {
+ log.info("Echoing back text message [{}]",message);
+ // Using shortcut approach to sending messages.
+ // You could use a void method and use remote.sendText()
+ return message;
+ }
+}
diff --git a/scouter.webapp/src/main/java/scouterx/webapp/main/WebAppMain.java b/scouter.webapp/src/main/java/scouterx/webapp/main/WebAppMain.java
index c3c531cf4..465bb4ec5 100644
--- a/scouter.webapp/src/main/java/scouterx/webapp/main/WebAppMain.java
+++ b/scouter.webapp/src/main/java/scouterx/webapp/main/WebAppMain.java
@@ -26,6 +26,7 @@
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.glassfish.jersey.servlet.ServletContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,9 +45,13 @@
import scouterx.webapp.framework.filter.LoggingInitServletFilter;
import scouterx.webapp.framework.filter.NoCacheFilter;
import scouterx.webapp.framework.filter.ReleaseResourceFilter;
+import scouterx.webapp.layer.websock.BasicSocket;
import scouterx.webapp.swagger.Bootstrap;
import javax.servlet.DispatcherType;
+import javax.servlet.ServletException;
+import javax.websocket.DeploymentException;
+import javax.websocket.server.ServerContainer;
import javax.ws.rs.core.Application;
import java.io.File;
import java.util.EnumSet;
@@ -90,6 +95,8 @@ public static void main(String[] args) throws Exception {
handlers.addHandler(servletContextHandler);
server.setHandler(handlers);
+ setWebSocketServer(servletContextHandler);
+
try {
server.start();
@@ -99,6 +106,14 @@ public static void main(String[] args) throws Exception {
}
}
+ public static void setWebSocketServer(ServletContextHandler servletContextHandler) throws ServletException, DeploymentException {
+ // Add javax.websocket support
+ ServerContainer container = WebSocketServerContainerInitializer.configureContext(servletContextHandler);
+ container.setDefaultMaxSessionIdleTimeout(7*24*3600*1000);
+ // Add echo endpoint to server container
+ container.addEndpoint(BasicSocket.class);
+ }
+
private static ServletContextHandler setWebHttpApiHandler () {
ConfigureAdaptor conf = ConfigureManager.getConfigure();
@@ -241,12 +256,14 @@ private static void initializeLogDir() {
* (This method also can be invoked from scouter.server's Http Server when this webapp runs as an embedded mode.)
*
*/
- public static ServletContextHandler setWebAppContext() {
+ public static ServletContextHandler setWebAppContext() throws ServletException, DeploymentException {
//The case - embedded mode (run in-process of scouter server)
if (!standAloneMode) {
initializeLogDir();
connectScouterCollector();
}
- return setWebHttpApiHandler();
+ ServletContextHandler handler = setWebHttpApiHandler();
+
+ return handler;
}
}
diff --git a/scouter.webapp/src/main/java/scouterx/webapp/model/ProfileStepData.java b/scouter.webapp/src/main/java/scouterx/webapp/model/ProfileStepData.java
index 64ef2aa2d..f500a71dd 100644
--- a/scouter.webapp/src/main/java/scouterx/webapp/model/ProfileStepData.java
+++ b/scouter.webapp/src/main/java/scouterx/webapp/model/ProfileStepData.java
@@ -25,13 +25,16 @@
import scouter.lang.step.DispatchStep;
import scouter.lang.step.DumpStep;
import scouter.lang.step.HashedMessageStep;
+import scouter.lang.step.MessageStep;
import scouter.lang.step.MethodStep;
import scouter.lang.step.ParameterizedMessageStep;
+import scouter.lang.step.SocketStep;
import scouter.lang.step.SqlStep;
import scouter.lang.step.Step;
import scouter.lang.step.StepEnum;
import scouter.lang.step.ThreadCallPossibleStep;
import scouter.lang.step.ThreadSubmitStep;
+import scouter.util.IPUtil;
import scouterx.webapp.framework.client.model.TextLoader;
import scouterx.webapp.framework.client.model.TextModel;
import scouterx.webapp.framework.client.model.TextTypeEnum;
@@ -125,7 +128,8 @@ private static String getStepMainValue(Step step, long date, int serverId) {
mainValue = textTypeEnum.getTextModel().getTextIfNullDefault(date, ((HashedMessageStep) step).getHash(), serverId);
break;
case PARAMETERIZED_MESSAGE:
- mainValue = textTypeEnum.getTextModel().getTextIfNullDefault(date, ((ParameterizedMessageStep) step).getHash(), serverId);
+ ParameterizedMessageStep pmStep = (ParameterizedMessageStep) step;
+ mainValue = pmStep.buildMessasge(textTypeEnum.getTextModel().getTextIfNullDefault(date, pmStep.getHash(), serverId));
break;
case DISPATCH:
mainValue = textTypeEnum.getTextModel().getTextIfNullDefault(date, ((DispatchStep) step).getHash(), serverId);
@@ -136,7 +140,10 @@ private static String getStepMainValue(Step step, long date, int serverId) {
case DUMP:
break;
case MESSAGE:
+ mainValue = ((MessageStep) step).getMessage();
+ break;
case SOCKET:
+ mainValue = IPUtil.toString(((SocketStep) step).getIpaddr());
default:
break;
}
@@ -152,7 +159,7 @@ private static List getStepAdditionalValue(Step step, long date, int ser
case DUMP:
DumpStep dumpStep = (DumpStep) step;
for (int stackHash : dumpStep.stacks) {
- valueList.add(textTypeEnum.getTextModel().getTextIfNullDefault(date, stackHash, serverId));
+ valueList.add(TextTypeEnum.STACK_ELEMENT.getTextModel().getTextIfNullDefault(date, stackHash, serverId));
}
break;
@@ -220,7 +227,7 @@ private static void addAdditionalValueHashesToTextLoader(Step step, TextLoader t
case DUMP:
DumpStep dumpStep = (DumpStep) step;
for (int stackHash : dumpStep.stacks) {
- textLoader.addTextHash(textTypeEnum, stackHash);
+ textLoader.addTextHash(TextTypeEnum.STACK_ELEMENT, stackHash);
}
break;
diff --git a/scouter.webapp/src/main/java/scouterx/webapp/request/MultiXLogRequest.java b/scouter.webapp/src/main/java/scouterx/webapp/request/MultiXLogRequest.java
new file mode 100644
index 000000000..2b0c9bd30
--- /dev/null
+++ b/scouter.webapp/src/main/java/scouterx/webapp/request/MultiXLogRequest.java
@@ -0,0 +1,56 @@
+/*
+ * 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 scouterx.webapp.request;
+
+import lombok.Getter;
+import lombok.Setter;
+import scouterx.webapp.framework.client.server.ServerManager;
+import scouterx.webapp.framework.util.ZZ;
+
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import java.util.List;
+
+/**
+ * Created by jaco.ryu on 2017. 10. 13..
+ */
+@Getter
+@Setter
+public class MultiXLogRequest {
+ int serverId;
+
+ List txidList;
+
+ @NotNull
+ @PathParam("yyyymmdd")
+ String yyyymmdd;
+
+ @PathParam("txidList")
+ public void setTxidList(String txids) {
+ this.txidList = ZZ.splitParamAsLong(txids);
+ }
+
+ @QueryParam("serverId")
+ public void setServerId(int serverId) {
+ this.serverId = ServerManager.getInstance().getServerIfNullDefault(serverId).getId();
+ }
+
+
+}
diff --git a/scouter.webapp/src/main/resources/webroot/test/ws/index.html b/scouter.webapp/src/main/resources/webroot/test/ws/index.html
new file mode 100644
index 000000000..2a8eb355a
--- /dev/null
+++ b/scouter.webapp/src/main/resources/webroot/test/ws/index.html
@@ -0,0 +1,21 @@
+
+
+ Jetty WebSocket Echo Examples
+
+
+
+
+ Jetty WebSocket Echo Examples #console
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scouter.webapp/src/main/resources/webroot/test/ws/main.css b/scouter.webapp/src/main/resources/webroot/test/ws/main.css
new file mode 100644
index 000000000..9eebead46
--- /dev/null
+++ b/scouter.webapp/src/main/resources/webroot/test/ws/main.css
@@ -0,0 +1,29 @@
+body {
+ font-family: sans-serif;
+}
+
+div {
+ border: 0px solid black;
+}
+
+div#console {
+ clear: both;
+ width: 40em;
+ height: 20em;
+ overflow: auto;
+ background-color: #f0f0f0;
+ padding: 4px;
+ border: 1px solid black;
+}
+
+div#console .info {
+ color: black;
+}
+
+div#console .client {
+ color: blue;
+}
+
+div#console .server {
+ color: magenta;
+}
diff --git a/scouter.webapp/src/main/resources/webroot/test/ws/websocket.js b/scouter.webapp/src/main/resources/webroot/test/ws/websocket.js
new file mode 100644
index 000000000..2619d9228
--- /dev/null
+++ b/scouter.webapp/src/main/resources/webroot/test/ws/websocket.js
@@ -0,0 +1,125 @@
+if (!window.WebSocket && window.MozWebSocket) {
+ window.WebSocket = window.MozWebSocket;
+}
+
+if (!window.WebSocket) {
+ alert("WebSocket not supported by this browser");
+}
+
+function $() {
+ return document.getElementById(arguments[0]);
+}
+function $F() {
+ return document.getElementById(arguments[0]).value;
+}
+
+function getKeyCode(ev) {
+ if (window.event)
+ return window.event.keyCode;
+ return ev.keyCode;
+}
+
+var wstool = {
+ connect : function() {
+ var location = 'ws://' + document.location.host + "/basic";
+
+ wstool.info("Document URI: " + document.location);
+ wstool.info("WS URI: " + location);
+
+ this._scount = 0;
+
+ try {
+ this._ws = new WebSocket(location);
+ this._ws.onopen = this._onopen;
+ this._ws.onmessage = this._onmessage;
+ this._ws.onclose = this._onclose;
+ } catch (exception) {
+ wstool.info("Connect Error: " + exception);
+ }
+ },
+
+ close : function() {
+ this._ws.close(1000);
+ },
+
+ _out : function(css, message) {
+ var console = $('console');
+ var spanText = document.createElement('span');
+ spanText.className = 'text ' + css;
+ spanText.innerHTML = message;
+ var lineBreak = document.createElement('br');
+ console.appendChild(spanText);
+ console.appendChild(lineBreak);
+ console.scrollTop = console.scrollHeight - console.clientHeight;
+ },
+
+ setState : function(enabled) {
+ $('connect').disabled = enabled;
+ $('close').disabled = !enabled;
+ $('hello').disabled = !enabled;
+ },
+
+ info : function(message) {
+ wstool._out("info", message);
+ },
+
+ error : function(message) {
+ wstool._out("error", message);
+ },
+
+ infoc : function(message) {
+ wstool._out("client", "[c] " + message);
+ },
+
+ infos : function(message) {
+ this._scount++;
+ wstool._out("server", "[s" + this._scount + "] " + message);
+ },
+
+ _onopen : function() {
+ wstool.setState(true);
+ wstool.info("Websocket Connected");
+ },
+
+ _send : function(message) {
+ if (this._ws) {
+ this._ws.send(message);
+ wstool.infoc(message);
+ }
+ },
+
+ write : function(text) {
+ wstool._send(text);
+ },
+
+ _onmessage : function(m) {
+ if (m.data) {
+ wstool.infos(m.data);
+ }
+ },
+
+ _onclose : function(closeEvent) {
+ this._ws = null;
+ wstool.setState(false);
+ wstool.info("Websocket Closed");
+ wstool.info(" .wasClean = " + closeEvent.wasClean);
+
+ var codeMap = {};
+ codeMap[1000] = "(NORMAL)";
+ codeMap[1001] = "(ENDPOINT_GOING_AWAY)";
+ codeMap[1002] = "(PROTOCOL_ERROR)";
+ codeMap[1003] = "(UNSUPPORTED_DATA)";
+ codeMap[1004] = "(UNUSED/RESERVED)";
+ codeMap[1005] = "(INTERNAL/NO_CODE_PRESENT)";
+ codeMap[1006] = "(INTERNAL/ABNORMAL_CLOSE)";
+ codeMap[1007] = "(BAD_DATA)";
+ codeMap[1008] = "(POLICY_VIOLATION)";
+ codeMap[1009] = "(MESSAGE_TOO_BIG)";
+ codeMap[1010] = "(HANDSHAKE/EXT_FAILURE)";
+ codeMap[1011] = "(SERVER/UNEXPECTED_CONDITION)";
+ codeMap[1015] = "(INTERNAL/TLS_ERROR)";
+ var codeStr = codeMap[closeEvent.code];
+ wstool.info(" .code = " + closeEvent.code + " " + codeStr);
+ wstool.info(" .reason = " + closeEvent.reason);
+ }
+};
diff --git a/scouter.webapp/src/test/java/scouterx/webapp/framework/session/UserTokenTest.java b/scouter.webapp/src/test/java/scouterx/webapp/framework/session/UserTokenTest.java
index 97888c7c5..2c5837f06 100644
--- a/scouter.webapp/src/test/java/scouterx/webapp/framework/session/UserTokenTest.java
+++ b/scouter.webapp/src/test/java/scouterx/webapp/framework/session/UserTokenTest.java
@@ -33,7 +33,7 @@ public void toStoreValue_test() {
UserToken unmarshalled = UserToken.fromStoreValue(toStoreValue, token.getServerId());
assertEquals(unmarshalled.getFootprintSec(), token.getFootprintSec());
- assertEquals(unmarshalled.getId(), token.getId());
+ assertEquals(unmarshalled.getUserId(), token.getUserId());
assertEquals(unmarshalled.getToken(), token.getToken());
}
@@ -45,7 +45,7 @@ public void toBearerToken_test() {
assertTrue(token.getFootprintSec() > 0);
assertTrue(unmarshalled.getFootprintSec() == 0);
- assertEquals(unmarshalled.getId(), token.getId());
+ assertEquals(unmarshalled.getUserId(), token.getUserId());
assertEquals(unmarshalled.getToken(), token.getToken());
}
diff --git a/scouter.webapp/src/test/java/scouterx/webapp/layer/service/UserTokenServiceTest.java b/scouter.webapp/src/test/java/scouterx/webapp/layer/service/UserTokenServiceTest.java
new file mode 100644
index 000000000..c27e2f628
--- /dev/null
+++ b/scouter.webapp/src/test/java/scouterx/webapp/layer/service/UserTokenServiceTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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 scouterx.webapp.layer.service;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import scouterx.lib3.tomcat.SessionIdGenerator;
+import scouterx.webapp.framework.client.server.Server;
+import scouterx.webapp.framework.client.server.ServerManager;
+import scouterx.webapp.framework.session.UserToken;
+import scouterx.webapp.model.scouter.SUser;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+/**
+ * @author Gun Lee (gunlee01@gmail.com) on 2018. 3. 11.
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ServerManager.class})
+public class UserTokenServiceTest {
+ String vutUserId = "junit-user";
+
+ @Mock
+ CustomKvStoreService customKvStoreService;
+ @Mock
+ Server server;
+ @Mock
+ ServerManager serverManager;
+
+ SessionIdGenerator sessionIdGenerator = new SessionIdGenerator();
+
+ @InjectMocks
+ UserTokenService sut = new UserTokenService();
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mockStatic(ServerManager.class);
+ when(ServerManager.getInstance()).thenReturn(serverManager);
+ }
+
+ @Test
+ public void publishToken() {
+ String bearer = sut.publishToken(server, new SUser(vutUserId));
+ UserToken fromBearer = UserToken.fromBearerToken(bearer);
+ assertEquals(vutUserId, fromBearer.getUserId());
+ }
+
+ @Test
+ public void validateToken() {
+ String bearer = sut.publishToken(server, new SUser(vutUserId));
+ UserToken fromBearer = UserToken.fromBearerToken(bearer);
+
+ sut.validateToken(fromBearer);
+ }
+
+ @Test
+ public void getAndMergeToStoredValue() {
+ UserToken userToken = UserToken.newToken(vutUserId, sessionIdGenerator.generateSessionId(), server.getId());
+
+ UserToken token0 = UserToken.newToken(vutUserId, sessionIdGenerator.generateSessionId(), server.getId());
+ UserToken token1 = UserToken.newToken(vutUserId, sessionIdGenerator.generateSessionId(), server.getId());
+ UserToken token2 = UserToken.newToken(vutUserId, sessionIdGenerator.generateSessionId(), server.getId());
+
+ String tokens = token0.toStoreValue() + ":" + token1.toStoreValue() + ":" + token2.toStoreValue();
+ String merged = sut.mergeStoredTokensWith(tokens, userToken);
+
+ assertTrue(merged.contains(userToken.getToken()));
+ }
+
+ @Test
+ public void getAndMergeToStoredValue_with_expired_tokens() {
+ UserToken userToken = UserToken.newToken(vutUserId, sessionIdGenerator.generateSessionId(), server.getId());
+
+ UserToken token0 = UserToken.newToken(vutUserId, sessionIdGenerator.generateSessionId(), server.getId());
+ UserToken token1 = UserToken.newToken(vutUserId, sessionIdGenerator.generateSessionId(), server.getId());
+ UserToken token2 = UserToken.newToken(vutUserId, sessionIdGenerator.generateSessionId(), server.getId());
+
+ token0.setFootprintSec(System.currentTimeMillis()/1000L - sut.sessionExpireSec - 1);
+ token1.setFootprintSec(System.currentTimeMillis()/1000L - sut.sessionExpireSec - 1);
+ token2.setFootprintSec(System.currentTimeMillis()/1000L - sut.sessionExpireSec - 1);
+
+ String tokens = token0.toStoreValue() + ":" + token1.toStoreValue() + ":" + token2.toStoreValue();
+ String merged = sut.mergeStoredTokensWith(tokens, userToken);
+
+ assertEquals(merged, userToken.toStoreValue());
+ }
+}
\ No newline at end of file