Merged branch 'jetty-9.4.x' into 'jetty-10.0.x'.

This commit is contained in:
Simone Bordet 2020-03-31 14:50:48 +02:00
commit 414a1dd396
8 changed files with 203 additions and 86 deletions

View File

@ -709,21 +709,15 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
statement.setLong(10, data.getExpiry());
statement.setLong(11, data.getMaxInactiveMs());
if (!data.getAllAttributes().isEmpty())
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos))
{
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos))
{
SessionData.serializeAttributes(data, oos);
byte[] bytes = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
statement.setBinaryStream(12, bais, bytes.length);//attribute map as blob
}
}
else
{
statement.setBinaryStream(12, EMPTY, 0);
SessionData.serializeAttributes(data, oos);
byte[] bytes = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
statement.setBinaryStream(12, bais, bytes.length);//attribute map as blob
}
statement.executeUpdate();
if (LOG.isDebugEnabled())
LOG.debug("Inserted session " + data);
@ -746,23 +740,17 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
statement.setLong(5, data.getExpiry());
statement.setLong(6, data.getMaxInactiveMs());
if (!data.getAllAttributes().isEmpty())
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos))
{
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos))
SessionData.serializeAttributes(data, oos);
byte[] bytes = baos.toByteArray();
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes))
{
SessionData.serializeAttributes(data, oos);
byte[] bytes = baos.toByteArray();
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes))
{
statement.setBinaryStream(7, bais, bytes.length);//attribute map as blob
}
statement.setBinaryStream(7, bais, bytes.length);//attribute map as blob
}
}
else
{
statement.setBinaryStream(7, EMPTY, 0);
}
statement.executeUpdate();
if (LOG.isDebugEnabled())

View File

@ -196,14 +196,14 @@ public class Module implements Comparable<Module>
process(basehome);
}
public static boolean isRequiredDependency(String depends)
public static boolean isConditionalDependency(String depends)
{
return (depends != null) && (depends.charAt(0) != '?');
return (depends != null) && (depends.charAt(0) == '?');
}
public static String normalizeModuleName(String name)
{
if (!isRequiredDependency(name))
if (isConditionalDependency(name))
return name.substring(1);
return name;
}

View File

@ -136,10 +136,8 @@ public class Modules implements Iterable<Module>
{
parent = Module.normalizeModuleName(parent);
System.out.printf(label, parent);
if (!Module.isRequiredDependency(parent))
{
System.out.print(" [not-required]");
}
if (Module.isConditionalDependency(parent))
System.out.print(" [conditional]");
label = ", %s";
}
System.out.println();
@ -420,7 +418,7 @@ public class Modules implements Iterable<Module>
StartLog.debug("Enabled module [%s] depends on %s", module.getName(), module.getDepends());
for (String dependsOnRaw : module.getDepends())
{
boolean isRequired = Module.isRequiredDependency(dependsOnRaw);
boolean isConditional = Module.isConditionalDependency(dependsOnRaw);
// Final to allow lambda's below to use name
final String dependentModule = Module.normalizeModuleName(dependsOnRaw);
@ -436,7 +434,7 @@ public class Modules implements Iterable<Module>
if (dependentModule.contains("/"))
{
Path file = _baseHome.getPath("modules/" + dependentModule + ".mod");
if (isRequired || Files.exists(file))
if (!isConditional || Files.exists(file))
{
registerModule(file).expandDependencies(_args.getProperties());
providers = _provided.get(dependentModule);
@ -447,10 +445,10 @@ public class Modules implements Iterable<Module>
continue;
}
}
// is this a non-required module
if (!isRequired)
// is this a conditional module
if (isConditional)
{
StartLog.debug("Skipping non-required module [%s]: doesn't exist", dependentModule);
StartLog.debug("Skipping conditional module [%s]: it does not exist", dependentModule);
continue;
}
// throw an exception (not a dynamic module and a required dependency)
@ -570,7 +568,7 @@ public class Modules implements Iterable<Module>
{
// Check dependencies
m.getDepends().stream()
.filter(Module::isRequiredDependency)
.filter(depends -> !Module.isConditionalDependency(depends))
.forEach(d ->
{
Set<Module> providers = getAvailableProviders(d);

View File

@ -234,6 +234,7 @@ public class ModulesTest
// Collect active module list
List<Module> active = modules.getEnabled();
modules.checkEnabledModules();
// Assert names are correct, and in the right order
List<String> expectedNames = new ArrayList<>();
@ -282,6 +283,7 @@ public class ModulesTest
// Collect active module list
List<Module> active = modules.getEnabled();
modules.checkEnabledModules();
// Assert names are correct, and in the right order
List<String> expectedNames = new ArrayList<>();
@ -331,6 +333,7 @@ public class ModulesTest
// Collect active module list
List<Module> active = modules.getEnabled();
modules.checkEnabledModules();
// Assert names are correct, and in the right order
List<String> expectedNames = new ArrayList<>();

View File

@ -49,19 +49,16 @@ public class JDBCSessionDataStoreTest extends AbstractSessionDataStoreTest
public void persistSession(SessionData data)
throws Exception
{
JdbcTestHelper.insertSession(data.getId(), data.getContextPath(), data.getVhost(), data.getLastNode(),
data.getCreated(), data.getAccessed(), data.getLastAccessed(),
data.getMaxInactiveMs(), data.getExpiry(), data.getCookieSet(),
data.getLastSaved(), data.getAllAttributes());
JdbcTestHelper.insertSession(data);
}
@Override
public void persistUnreadableSession(SessionData data) throws Exception
{
JdbcTestHelper.insertSession(data.getId(), data.getContextPath(), data.getVhost(), data.getLastNode(),
JdbcTestHelper.insertUnreadableSession(data.getId(), data.getContextPath(), data.getVhost(), data.getLastNode(),
data.getCreated(), data.getAccessed(), data.getLastAccessed(),
data.getMaxInactiveMs(), data.getExpiry(), data.getCookieSet(),
data.getLastSaved(), null);
data.getLastSaved());
}
@Override

View File

@ -29,7 +29,6 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
@ -132,6 +131,35 @@ public class JdbcTestHelper
sessionTableSchema.prepareTables();
}
public static void dumpRow(ResultSet row) throws SQLException
{
if (row != null)
{
String id = row.getString(ID_COL);
long created = row.getLong(CREATE_COL);
long accessed = row.getLong(ACCESS_COL);
long lastAccessed = row.getLong(LAST_ACCESS_COL);
long maxIdle = row.getLong(MAX_IDLE_COL);
long cookieSet = row.getLong(COOKIE_COL);
String node = row.getString(LAST_NODE_COL);
long expires = row.getLong(EXPIRY_COL);
long lastSaved = row.getLong(LAST_SAVE_COL);
String context = row.getString(CONTEXT_COL);
Blob blob = row.getBlob(MAP_COL);
String dump = "id=" + id +
" ctxt=" + context +
" node=" + node +
" exp=" + expires +
" acc=" + accessed +
" lacc=" + lastAccessed +
" ck=" + cookieSet +
" lsv=" + lastSaved +
" blob length=" + blob.length();
System.err.println(dump);
}
}
public static boolean existsInSessionTable(String id, boolean verbose)
throws Exception
{
@ -151,6 +179,7 @@ public class JdbcTestHelper
while (result.next())
{
results = true;
dumpRow(result);
}
return results;
}
@ -234,40 +263,52 @@ public class JdbcTestHelper
return true;
}
public static void insertSession(String id, String contextPath, String vhost)
throws Exception
public static void insertSession(SessionData data) throws Exception
{
Class.forName(DRIVER_CLASS);
try (Connection con = DriverManager.getConnection(DEFAULT_CONNECTION_URL);)
{
PreparedStatement statement = con.prepareStatement("insert into " + TABLE +
" (" + ID_COL + ", " + CONTEXT_COL + ", virtualHost, " + LAST_NODE_COL +
", " + ACCESS_COL + ", " + LAST_ACCESS_COL + ", " + CREATE_COL + ", " + COOKIE_COL +
", " + LAST_SAVE_COL + ", " + EXPIRY_COL + " " + ") " +
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
", " + LAST_SAVE_COL + ", " + EXPIRY_COL + ", " + MAX_IDLE_COL + "," + MAP_COL + " ) " +
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
statement.setString(1, id);
statement.setString(2, contextPath);
statement.setString(3, vhost);
statement.setString(4, "0");
statement.setString(1, data.getId());
statement.setString(2, data.getContextPath());
statement.setString(3, data.getVhost());
statement.setString(4, data.getLastNode());
statement.setLong(5, System.currentTimeMillis());
statement.setLong(6, System.currentTimeMillis());
statement.setLong(7, System.currentTimeMillis());
statement.setLong(8, System.currentTimeMillis());
statement.setLong(5, data.getAccessed());
statement.setLong(6, data.getLastAccessed());
statement.setLong(7, data.getCreated());
statement.setLong(8, data.getCookieSet());
statement.setLong(9, System.currentTimeMillis());
statement.setLong(10, System.currentTimeMillis());
statement.setLong(9, data.getLastSaved());
statement.setLong(10, data.getExpiry());
statement.setLong(11, data.getMaxInactiveMs());
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);)
{
SessionData.serializeAttributes(data, oos);
byte[] bytes = baos.toByteArray();
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);)
{
statement.setBinaryStream(12, bais, bytes.length);
}
}
statement.execute();
assertEquals(1, statement.getUpdateCount());
}
}
public static void insertSession(String id, String contextPath, String vhost,
public static void insertUnreadableSession(String id, String contextPath, String vhost,
String lastNode, long created, long accessed,
long lastAccessed, long maxIdle, long expiry,
long cookieSet, long lastSaved, Map<String, Object> attributes)
long cookieSet, long lastSaved)
throws Exception
{
Class.forName(DRIVER_CLASS);
@ -293,23 +334,7 @@ public class JdbcTestHelper
statement.setLong(10, expiry);
statement.setLong(11, maxIdle);
if (attributes != null)
{
SessionData tmp = new SessionData(id, contextPath, vhost, created, accessed, lastAccessed, maxIdle);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);)
{
SessionData.serializeAttributes(tmp, oos);
byte[] bytes = baos.toByteArray();
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);)
{
statement.setBinaryStream(12, bais, bytes.length);
}
}
}
else
statement.setBinaryStream(12, new ByteArrayInputStream("".getBytes()), 0);
statement.setBinaryStream(12, new ByteArrayInputStream("".getBytes()), 0);
statement.execute();
assertEquals(1, statement.getUpdateCount());

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.server.session;
import java.io.ByteArrayInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -67,6 +68,46 @@ public class SessionTableSchemaTest
JdbcTestHelper.shutdown(null);
}
/**
* This inserts a session into the db that does not set the session attributes MAP column. As such
* this results in a row that is unreadable by the JDBCSessionDataStore, but is readable by using
* only jdbc api, which is what this test does.
*
* @param id id of session
* @param contextPath the context path of the session
* @param vhost the virtual host of the session
* @throws Exception
*/
public static void insertSessionWithoutAttributes(String id, String contextPath, String vhost)
throws Exception
{
Class.forName(JdbcTestHelper.DRIVER_CLASS);
try (Connection con = DriverManager.getConnection(JdbcTestHelper.DEFAULT_CONNECTION_URL);)
{
PreparedStatement statement = con.prepareStatement("insert into " + JdbcTestHelper.TABLE +
" (" + JdbcTestHelper.ID_COL + ", " + JdbcTestHelper.CONTEXT_COL + ", virtualHost, " + JdbcTestHelper.LAST_NODE_COL +
", " + JdbcTestHelper.ACCESS_COL + ", " + JdbcTestHelper.LAST_ACCESS_COL + ", " + JdbcTestHelper.CREATE_COL + ", " + JdbcTestHelper.COOKIE_COL +
", " + JdbcTestHelper.LAST_SAVE_COL + ", " + JdbcTestHelper.EXPIRY_COL + " " + ") " +
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
statement.setString(1, id);
statement.setString(2, contextPath);
statement.setString(3, vhost);
statement.setString(4, "0");
statement.setLong(5, System.currentTimeMillis());
statement.setLong(6, System.currentTimeMillis());
statement.setLong(7, System.currentTimeMillis());
statement.setLong(8, System.currentTimeMillis());
statement.setLong(9, System.currentTimeMillis());
statement.setLong(10, System.currentTimeMillis());
statement.execute();
assertEquals(1, statement.getUpdateCount());
}
}
@Test
public void testLoad()
throws Exception
@ -76,7 +117,7 @@ public class SessionTableSchemaTest
_tableSchema.prepareTables();
//insert a fake session at the root context
JdbcTestHelper.insertSession("1234", "/", "0.0.0.0");
insertSessionWithoutAttributes("1234", "/", "0.0.0.0");
//test if it can be seen
try (Connection con = _da.getConnection())
@ -101,7 +142,7 @@ public class SessionTableSchemaTest
_tableSchema.prepareTables();
//insert a fake session at the root context
JdbcTestHelper.insertSession("1234", "/", "0.0.0.0");
insertSessionWithoutAttributes("1234", "/", "0.0.0.0");
//test if it can be seen
try (Connection con = _da.getConnection())
@ -125,7 +166,7 @@ public class SessionTableSchemaTest
_tableSchema.prepareTables();
//insert a fake session at the root context
JdbcTestHelper.insertSession("1234", "/", "0.0.0.0");
insertSessionWithoutAttributes("1234", "/", "0.0.0.0");
//test if it can be deleted
try (Connection con = _da.getConnection())
@ -149,7 +190,7 @@ public class SessionTableSchemaTest
_tableSchema.prepareTables();
//insert a fake session at the root context
JdbcTestHelper.insertSession("1234", "/", "0.0.0.0");
insertSessionWithoutAttributes("1234", "/", "0.0.0.0");
try (Connection con = _da.getConnection())
{
@ -175,7 +216,7 @@ public class SessionTableSchemaTest
_tableSchema.prepareTables();
//insert a fake session at the root context
JdbcTestHelper.insertSession("1234", "/", "0.0.0.0");
insertSessionWithoutAttributes("1234", "/", "0.0.0.0");
try (Connection con = _da.getConnection())
{
@ -200,7 +241,7 @@ public class SessionTableSchemaTest
_tableSchema.prepareTables();
//insert a fake session at the root context
JdbcTestHelper.insertSession("1234", "/", "0.0.0.0");
insertSessionWithoutAttributes("1234", "/", "0.0.0.0");
try (Connection con = _da.getConnection())
{

View File

@ -428,6 +428,71 @@ public abstract class AbstractSessionDataStoreTest
}
}
/**
* Test that a session containing no attributes can be stored and re-read
* @throws Exception
*/
@Test
public void testEmptyLoadSession() throws Exception
{
//create the SessionDataStore
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/test");
SessionDataStoreFactory factory = createSessionDataStoreFactory();
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(GRACE_PERIOD_SEC);
SessionDataStore store = factory.getSessionDataStore(context.getSessionHandler());
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
store.initialize(sessionContext);
store.start();
//persist a session that has no attributes
long now = System.currentTimeMillis();
SessionData data = store.newSessionData("222", 100, now, now - 1, -1);
data.setLastNode(sessionContext.getWorkerName());
//persistSession(data);
store.store("222", data);
//test that we can retrieve it
SessionData savedSession = store.load("222");
assertEquals(0, savedSession.getAllAttributes().size());
}
//Test that a session that had attributes can be modified to contain no
//attributes, and still read
@Test
public void testModifyEmptyLoadSession() throws Exception
{
//create the SessionDataStore
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/test");
SessionDataStoreFactory factory = createSessionDataStoreFactory();
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(GRACE_PERIOD_SEC);
SessionDataStore store = factory.getSessionDataStore(context.getSessionHandler());
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
store.initialize(sessionContext);
store.start();
//persist a session that has attributes
long now = System.currentTimeMillis();
SessionData data = store.newSessionData("222", 100, now, now - 1, -1);
data.setAttribute("foo", "bar");
data.setLastNode(sessionContext.getWorkerName());
store.store("222", data);
//test that we can retrieve it
SessionData savedSession = store.load("222");
assertEquals("bar", savedSession.getAttribute("foo"));
//now modify so there are no attributes
savedSession.setAttribute("foo", null);
store.store("222", savedSession);
//check its still readable
savedSession = store.load("222");
assertEquals(0, savedSession.getAllAttributes().size());
}
/**
* Test that we can delete a persisted session.
*/