/*
* Copyright 2011-2016 the original author or authors.
*
* 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 org.glowroot.agent.plugin.servlet;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpSession;
import org.glowroot.agent.it.harness.Container;
import org.glowroot.agent.it.harness.Containers;
import org.glowroot.wire.api.model.TraceOuterClass.Trace;
import static org.assertj.core.api.Assertions.assertThat;
public class SessionAttributeIT {
private static final String PLUGIN_ID = "servlet";
private static Container container;
@BeforeClass
public static void setUp() throws Exception {
container = Containers.create();
}
@AfterClass
public static void tearDown() throws Exception {
container.close();
}
@After
public void afterEachTest() throws Exception {
container.checkAndReset();
}
@Test
public void testHasSessionAttribute() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"testattr");
// when
Trace trace = container.execute(HasSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNotNull();
assertThat(getSessionAttributes(trace).get("testattr")).isEqualTo("val");
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testHasSessionAttributeWithoutTrimmedAttributeName() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
" testattr , other");
// when
Trace trace = container.execute(HasSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNotNull();
assertThat(getSessionAttributes(trace).get("testattr")).isEqualTo("val");
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testHasSessionAttributeUsingWildcard() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes", "*");
// when
Trace trace = container.execute(HasSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNotNull();
assertThat(getSessionAttributes(trace).get("testattr")).isEqualTo("val");
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testHasSessionAttributeUsingWildcardPlusOther() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"*,other,::id");
// when
Trace trace = container.execute(HasSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNotNull();
assertThat(getSessionAttributes(trace).get("testattr")).isEqualTo("val");
assertThat(getSessionAttributes(trace).get("::id")).isEqualTo("123456789");
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testHasSessionAttributeNotReadable() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes", "");
// when
Trace trace = container.execute(HasSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testSetSessionAttribute() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"testattr,testother");
// when
Trace trace = container.execute(SetSessionAttribute.class);
// then
assertThat(getInitialSessionAttributes(trace)).isNotNull();
assertThat(getInitialSessionAttributes(trace).get("testother")).isEqualTo("v");
assertThat(getUpdatedSessionAttributes(trace)).isNotNull();
assertThat(getUpdatedSessionAttributes(trace).get("testattr")).isEqualTo("val");
}
@Test
public void testSetSessionAttributeUsingWildcard() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes", "*");
// when
Trace trace = container.execute(SetSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNotNull();
assertThat(getUpdatedSessionAttributes(trace).get("testattr")).isEqualTo("val");
}
@Test
public void testSetSessionAttributeUsingWildcardAndOther() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"*,other");
// when
Trace trace = container.execute(SetSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNotNull();
assertThat(getUpdatedSessionAttributes(trace).get("testattr")).isEqualTo("val");
}
@Test
public void testSetSessionAttributeNotReadable() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes", "");
// when
Trace trace = container.execute(SetSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testSetSessionAttributeNull() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes", "*");
// when
Trace trace = container.execute(SetSessionAttributeNull.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNotNull();
assertThat(getUpdatedSessionAttributes(trace).containsValue("testattr")).isFalse();
}
@Test
public void testHasNestedSessionAttributePath() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"one.two.three,one.amap.x");
// when
Trace trace = container.execute(HasNestedSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNotNull();
assertThat(getSessionAttributes(trace).get("one.two.three")).isEqualTo("four");
assertThat(getSessionAttributes(trace).get("one.amap.x")).isEqualTo("y");
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testSetNestedSessionAttributePath() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"one.two.three,one.amap.x");
// when
Trace trace = container.execute(SetNestedSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNotNull();
assertThat(getUpdatedSessionAttributes(trace).get("one.two.three")).isEqualTo("four");
assertThat(getUpdatedSessionAttributes(trace).get("one.amap.x")).isEqualTo("y");
}
@Test
public void testHasMissingSessionAttribute() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"missingtestattr");
// when
Trace trace = container.execute(HasSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testHasMissingNestedSessionAttributePath() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"one.missingtwo");
// when
Trace trace = container.execute(HasNestedSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testHasNestedSessionAttributePath2() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"one.*,one.two.*,one.amap.*");
// when
Trace trace = container.execute(HasNestedSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNotNull();
assertThat(getSessionAttributes(trace)).hasSize(5);
assertThat(getSessionAttributes(trace).get("one.two.three")).isEqualTo("four");
assertThat(getSessionAttributes(trace).get("one.amap.x")).isEqualTo("y");
assertThat(getSessionAttributes(trace).get("one.another")).isEqualTo("3");
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testSetNestedSessionAttributePath2() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"one.*,one.two.*,one.amap.*");
// when
Trace trace = container.execute(SetNestedSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNotNull();
assertThat(getUpdatedSessionAttributes(trace)).hasSize(5);
assertThat(getUpdatedSessionAttributes(trace).get("one.two.three")).isEqualTo("four");
assertThat(getUpdatedSessionAttributes(trace).get("one.amap.x")).isEqualTo("y");
assertThat(getUpdatedSessionAttributes(trace).get("one.another")).isEqualTo("3");
}
@Test
public void testSetNestedSessionAttributeToNull() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"one.*");
// when
Trace trace = container.execute(SetNestedSessionAttributeToNull.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNotNull();
assertThat(getUpdatedSessionAttributes(trace)).hasSize(1);
assertThat(getUpdatedSessionAttributes(trace).containsKey("one")).isTrue();
assertThat(getUpdatedSessionAttributes(trace).get("one")).isNull();
}
@Test
public void testSetSessionAttributeToNull() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"one.two");
// when
Trace trace = container.execute(SetNestedSessionAttributeToNull.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNotNull();
assertThat(getUpdatedSessionAttributes(trace)).hasSize(1);
assertThat(getUpdatedSessionAttributes(trace).containsKey("one.two")).isTrue();
assertThat(getUpdatedSessionAttributes(trace).get("one.two")).isNull();
}
@Test
public void testHasMissingSessionAttribute2() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"missingtestattr.*");
// when
Trace trace = container.execute(HasSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testHasMissingNestedSessionAttributePath2() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"one.missingtwo.*");
// when
Trace trace = container.execute(HasNestedSessionAttribute.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testGetBadAttributeNames() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes", "*");
// when
Trace trace = container.execute(GetBadAttributeNames.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testHasHttpSession() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"::id");
// when
Trace trace = container.execute(HasHttpSession.class);
// then
assertThat(getSessionAttributes(trace)).isNotNull();
assertThat(getSessionAttributes(trace).get("::id")).isEqualTo("123456789");
assertThat(getInitialSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testHasNoHttpSession() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"::id");
// when
Trace trace = container.execute(HasNoHttpSession.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getInitialSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testCreateHttpSession() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"::id");
// when
Trace trace = container.execute(CreateHttpSession.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getInitialSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace).get("::id")).isEqualTo("123456789");
}
@Test
public void testCreateHttpSessionTrue() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"::id");
// when
Trace trace = container.execute(CreateHttpSessionTrue.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getInitialSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace).get("::id")).isEqualTo("123456789");
}
@Test
public void testCreateHttpSessionFalse() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"::id");
// when
Trace trace = container.execute(CreateHttpSessionFalse.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getInitialSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace)).isNull();
}
@Test
public void testChangeHttpSession() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"::id");
// when
Trace trace = container.execute(ChangeHttpSession.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getInitialSessionAttributes(trace).get("::id")).isEqualTo("123456789");
assertThat(getUpdatedSessionAttributes(trace).get("::id")).isEqualTo("abcdef");
}
@Test
public void testCreateAndChangeHttpSession() throws Exception {
// given
container.getConfigService().setPluginProperty(PLUGIN_ID, "captureSessionAttributes",
"::id");
// when
Trace trace = container.execute(CreateAndChangeHttpSession.class);
// then
assertThat(getSessionAttributes(trace)).isNull();
assertThat(getInitialSessionAttributes(trace)).isNull();
assertThat(getUpdatedSessionAttributes(trace).get("::id")).isEqualTo("abcdef");
}
static @Nullable Map<String, String> getSessionAttributes(Trace trace) {
return getDetailMap(trace, "Session attributes");
}
static @Nullable Map<String, String> getInitialSessionAttributes(Trace trace) {
return getDetailMap(trace, "Session attributes (at beginning of this request)");
}
static @Nullable Map<String, String> getUpdatedSessionAttributes(Trace trace) {
return getDetailMap(trace, "Session attributes (updated during this request)");
}
private static @Nullable Map<String, String> getDetailMap(Trace trace, String name) {
List<Trace.DetailEntry> details = trace.getHeader().getDetailEntryList();
Trace.DetailEntry found = null;
for (Trace.DetailEntry detail : details) {
if (detail.getName().equals(name)) {
found = detail;
break;
}
}
if (found == null) {
return null;
}
Map<String, String> responseHeaders = Maps.newLinkedHashMap();
for (Trace.DetailEntry detail : found.getChildEntryList()) {
if (detail.getValueList().isEmpty()) {
responseHeaders.put(detail.getName(), null);
} else {
responseHeaders.put(detail.getName(), detail.getValueList().get(0).getString());
}
}
return responseHeaders;
}
@SuppressWarnings("serial")
public static class HasSessionAttribute extends TestServlet {
@Override
protected void before(HttpServletRequest request, HttpServletResponse response) {
MockHttpSession session = new MockHttpSession(request.getServletContext(), "123456789");
((MockHttpServletRequest) request).setSession(session);
request.getSession().setAttribute("testattr", "val");
}
}
@SuppressWarnings("serial")
public static class SetSessionAttribute extends TestServlet {
@Override
protected void before(HttpServletRequest request, HttpServletResponse response) {
request.getSession().setAttribute("testother", "v");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
request.getSession().setAttribute("testattr", "val");
}
}
@SuppressWarnings("serial")
public static class SetSessionAttributeNull extends TestServlet {
@Override
protected void before(HttpServletRequest request, HttpServletResponse response) {
request.getSession().setAttribute("testattr", "something");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
request.getSession().setAttribute("testattr", null);
}
}
@SuppressWarnings("serial")
public static class HasNestedSessionAttribute extends TestServlet {
@Override
protected void before(HttpServletRequest request, HttpServletResponse response) {
request.getSession().setAttribute("one", new NestedTwo("four", "3"));
}
}
@SuppressWarnings("serial")
public static class SetNestedSessionAttribute extends TestServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
request.getSession().setAttribute("one", new NestedTwo("four", "3"));
}
}
@SuppressWarnings("serial")
public static class SetNestedSessionAttributeToNull extends TestServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
request.getSession().setAttribute("one", null);
}
}
@SuppressWarnings("serial")
public static class GetBadAttributeNames extends TestServlet {
@Override
protected void before(HttpServletRequest request, HttpServletResponse response) {
((MockHttpServletRequest) request).setSession(new MockHttpSession() {
@Override
public Enumeration<String> getAttributeNames() {
return Collections.enumeration(Lists.newArrayList((String) null));
}
});
}
}
@SuppressWarnings("serial")
public static class HasHttpSession extends TestServlet {
@Override
protected void before(HttpServletRequest request, HttpServletResponse response) {
MockHttpSession session = new MockHttpSession(request.getServletContext(), "123456789");
((MockHttpServletRequest) request).setSession(session);
}
}
@SuppressWarnings("serial")
public static class HasNoHttpSession extends TestServlet {
@Override
protected void before(HttpServletRequest request, HttpServletResponse response) {}
}
@SuppressWarnings("serial")
public static class CreateHttpSession extends TestServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
MockHttpSession session = new MockHttpSession(request.getServletContext(), "123456789");
((MockHttpServletRequest) request).setSession(session);
request.getSession();
}
}
@SuppressWarnings("serial")
public static class CreateHttpSessionTrue extends TestServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
MockHttpSession session = new MockHttpSession(request.getServletContext(), "123456789");
((MockHttpServletRequest) request).setSession(session);
request.getSession(true);
super.service(request, response);
}
}
@SuppressWarnings("serial")
public static class CreateHttpSessionFalse extends TestServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getSession(false);
super.service(request, response);
}
}
@SuppressWarnings("serial")
public static class ChangeHttpSession extends TestServlet {
@Override
protected void before(HttpServletRequest request, HttpServletResponse response) {
MockHttpSession session = new MockHttpSession(request.getServletContext(), "123456789");
((MockHttpServletRequest) request).setSession(session);
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getSession().invalidate();
MockHttpSession session = new MockHttpSession(request.getServletContext(), "abcdef");
((MockHttpServletRequest) request).setSession(session);
request.getSession();
super.service(request, response);
}
}
@SuppressWarnings("serial")
public static class CreateAndChangeHttpSession extends TestServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
MockHttpSession session = new MockHttpSession(request.getServletContext(), "123456789");
((MockHttpServletRequest) request).setSession(session);
request.getSession().invalidate();
session = new MockHttpSession(request.getServletContext(), "abcdef");
((MockHttpServletRequest) request).setSession(session);
request.getSession();
super.service(request, response);
}
}
public static class NestedTwo {
private final NestedThree two;
private final StringBuilder another;
private final String iamnull = null;
private final Map<String, String> amap = ImmutableMap.of("x", "y");
public NestedTwo(String two, String another) {
this.two = new NestedThree(two);
this.another = new StringBuilder(another);
}
public NestedThree getTwo() {
return two;
}
public StringBuilder getAnother() {
return another;
}
public String getIamnull() {
return iamnull;
}
public Map<String, String> getAmap() {
return amap;
}
}
public static class NestedThree {
private final String three;
public NestedThree(String three) {
this.three = three;
}
public String getThree() {
return three;
}
}
}