From 9085dcdcb35ae1f9e3a592c8cd5dfecdd4e9bde1 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Jun 2015 18:22:54 +0200 Subject: [server] Add script field to lecture table; implement getImageDetails method to get detailed information about an image from the database --- .../src/main/java/org/openslx/bwlp/sat/App.java | 11 +++- .../org/openslx/bwlp/sat/database/Database.java | 7 +++ .../openslx/bwlp/sat/database/mappers/DbImage.java | 73 +++++++++++++++++++++- .../bwlp/sat/database/mappers/DbSoftwareTag.java | 70 +++++++++++++++++++++ .../bwlp/sat/permissions/UserPermissions.java | 52 +++++++++++++++ .../org/openslx/bwlp/sat/thrift/ServerHandler.java | 16 ++++- .../openslx/bwlp/sat/thrift/cache/CacheBase.java | 43 +++++++++++++ .../openslx/bwlp/sat/thrift/cache/CachedList.java | 33 ---------- .../bwlp/sat/thrift/cache/OperatingSystemList.java | 2 +- .../bwlp/sat/thrift/cache/OrganizationList.java | 14 ++++- .../java/org/openslx/bwlp/sat/util/QuickTimer.java | 4 ++ 11 files changed, 280 insertions(+), 45 deletions(-) create mode 100644 dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbSoftwareTag.java create mode 100644 dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/UserPermissions.java create mode 100644 dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/CacheBase.java delete mode 100644 dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/CachedList.java (limited to 'dozentenmodulserver/src/main/java') diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java index 8aac1fcb..aaa344f8 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java @@ -1,6 +1,7 @@ package org.openslx.bwlp.sat; import java.security.NoSuchAlgorithmException; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -64,9 +65,13 @@ public class App { // DEBUG if (DEBUG) { Database.printCharsetInformation(); - List allVisible = DbImage.getAllVisible(new UserInfo("bla", "blu", null, null, - null), null); - log.info("Got " + allVisible.size()); + List allVisible; + try { + allVisible = DbImage.getAllVisible(new UserInfo("bla", "blu", null, null, null), null); + log.info("Got " + allVisible.size()); + } catch (SQLException e) { + log.warn("could not test query getallvisible"); + } QuickTimer.scheduleAtFixedDelay(new TimerTask() { @Override public void run() { diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/Database.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/Database.java index cfc6530b..422db229 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/Database.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/Database.java @@ -11,6 +11,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.log4j.Logger; +import org.openslx.bwlp.sat.App; import org.openslx.bwlp.sat.util.Configuration; public class Database { @@ -43,6 +44,9 @@ public class Database { * @return connection to database, or null */ public static MysqlConnection getConnection() { + if (App.DEBUG) { + LOGGER.info("CONNECTION GET", new RuntimeException()); + } MysqlConnection con; for (;;) { con = pool.poll(); @@ -87,6 +91,9 @@ public class Database { * @param connection */ static void returnConnection(MysqlConnection connection) { + if (App.DEBUG) { + LOGGER.info("CONNECTION RETURN", new RuntimeException()); + } if (!busyConnections.remove(connection)) throw new RuntimeException("Tried to return a mysql connection to the pool that was not taken!"); pool.add(connection); diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java index b772edb4..bbb5dad9 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbImage.java @@ -9,16 +9,31 @@ import org.apache.log4j.Logger; import org.openslx.bwlp.sat.database.Database; import org.openslx.bwlp.sat.database.MysqlConnection; import org.openslx.bwlp.sat.database.MysqlStatement; +import org.openslx.bwlp.thrift.iface.ImageDetailsRead; import org.openslx.bwlp.thrift.iface.ImagePermissions; import org.openslx.bwlp.thrift.iface.ImageSummaryRead; +import org.openslx.bwlp.thrift.iface.ImageVersionDetails; import org.openslx.bwlp.thrift.iface.ShareMode; +import org.openslx.bwlp.thrift.iface.TNotFoundException; import org.openslx.bwlp.thrift.iface.UserInfo; public class DbImage { private static final Logger LOGGER = Logger.getLogger(DbImage.class); - public static List getAllVisible(UserInfo user, List tagSearch) { + /** + * Get list of all images visible to the given user, optionally filtered by + * the given list of tags. + * + * @param user Instance of {@link UserInfo} representing the user in + * question + * @param tagSearch list of tags an image must have to be included in the + * list. + * @return {@link List} of {@link ImageSummaryRead} + * @throws SQLException + */ + public static List getAllVisible(UserInfo user, List tagSearch) + throws SQLException { try (MysqlConnection connection = Database.getConnection()) { MysqlStatement stmt = connection.prepareStatement("SELECT" + " i.imagebaseid, i.currentversionid, i.latestversionid, i.displayname," @@ -51,10 +66,64 @@ public class DbImage { return list; } catch (SQLException e) { LOGGER.error("Query failed in DbImage.getAllVisible()", e); - return null; + throw e; } } + public static ImageDetailsRead getImageDetails(UserInfo user, String imageBaseId) + throws TNotFoundException, SQLException { + try (MysqlConnection connection = Database.getConnection()) { + MysqlStatement stmt = connection.prepareStatement("SELECT imagebaseid, currentversionid, latestversionid," + + " displayname, description, osid, virtid, createtime, updatetime, ownerid, updaterid," + + " sharemode, istemplate," + + " canlinkdefault, candownloaddefault, caneditdefault, canadmindefault," + + " perm.canlink, perm.candownload, perm.canedit, perm.canadmin" + + " FROM imagebase i" + + " LEFT JOIN imagepermission perm ON (i.imagebaseid = perm.imagebaseid AND perm.userid = :userid)" + + " WHERE i.imagebaseid = :imagebaseid"); + stmt.setString("userid", user.userId); + stmt.setString("imagebaseid", imageBaseId); + ResultSet rs = stmt.executeQuery(); + if (!rs.next()) + throw new TNotFoundException(); + // Exists: + List tags = DbSoftwareTag.getImageTags(connection, imageBaseId); + List versions = getImageVersions(connection, imageBaseId); + ImagePermissions defaultPermissions = DbImagePermissions.fromResultSetDefault(rs); + ImageDetailsRead image = new ImageDetailsRead(rs.getString("imagebaseid"), + rs.getString("currentversionid"), rs.getString("latestversionid"), versions, + rs.getString("displayname"), rs.getString("description"), tags, rs.getInt("osid"), + rs.getString("virtid"), rs.getLong("createtime"), rs.getLong("updatetime"), + rs.getString("ownerid"), rs.getString("updaterid"), + toShareMode(rs.getString("sharemode")), rs.getByte("istemplate") != 0, defaultPermissions); + return image; + } catch (SQLException e) { + LOGGER.error("Query failed in DbImage.getImage()", e); + throw e; + } + } + + public static List getImageVersions(MysqlConnection connection, String imageBaseId) + throws SQLException { + List versionList = new ArrayList<>(); + MysqlStatement stmt = connection.prepareStatement("SELECT" + + " imageversionid, createtime, expiretime, filesize, uploaderid, isenabled," + + " isrestricted, isvalid, isprocessed" + " FROM imageversion" + + " WHERE imagebaseid = :imagebaseid"); + stmt.setString("imagebaseid", imageBaseId); + ResultSet rs = stmt.executeQuery(); + while (rs.next()) { + String imageVersionId = rs.getString("imageversionid"); + versionList.add(new ImageVersionDetails(imageVersionId, rs.getLong("createtime"), + rs.getLong("expiretime"), rs.getLong("filesize"), rs.getString("uploaderid"), + rs.getByte("isenabled") != 0, rs.getByte("isrestricted") != 0, + rs.getByte("isvalid") != 0, rs.getByte("isprocessed") != 0, + DbSoftwareTag.getImageVersionSoftwareList(connection, imageVersionId))); + } + stmt.close(); + return versionList; + } + private static ShareMode toShareMode(String string) { return ShareMode.valueOf(string); } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbSoftwareTag.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbSoftwareTag.java new file mode 100644 index 00000000..6cabd021 --- /dev/null +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/database/mappers/DbSoftwareTag.java @@ -0,0 +1,70 @@ +package org.openslx.bwlp.sat.database.mappers; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.openslx.bwlp.sat.database.Database; +import org.openslx.bwlp.sat.database.MysqlConnection; +import org.openslx.bwlp.sat.database.MysqlStatement; + +public class DbSoftwareTag { + + private static final Logger LOGGER = Logger.getLogger(DbSoftwareTag.class); + + /** + * Get list of software installed in a certain image version. + * + * @param connection database connection to use + * @param imageVersionId UUID of image version + * @return list of software products + * @throws SQLException + */ + public static List getImageVersionSoftwareList(MysqlConnection connection, String imageVersionId) + throws SQLException { + MysqlStatement stmt = connection.prepareStatement("SELECT softwarestring FROM software" + + " INNER JOIN imageversion_x_software USING (softwareid)" + + " WHERE imageversionid = :imageversionid"); + stmt.setString("imageversionid", imageVersionId); + ResultSet rs = stmt.executeQuery(); + List softwareList = new ArrayList<>(); + while (rs.next()) { + softwareList.add(rs.getString("softwarestring")); + } + stmt.close(); + return softwareList; + } + + /** + * Get list of software installed in a certain image version. + * + * @param imageVersionId UUID of image version + * @return list of software products + * @throws SQLException + */ + public static List getImageVersionSoftwareList(String imageVersionId) throws SQLException { + try (MysqlConnection connection = Database.getConnection()) { + return getImageVersionSoftwareList(connection, imageVersionId); + } catch (SQLException e) { + LOGGER.error("Query failed in DbSoftware.getImageVersionSoftwareList()", e); + throw e; + } + } + + public static List getImageTags(MysqlConnection connection, String imageBaseId) throws SQLException { + MysqlStatement stmt = connection.prepareStatement("SELECT displayname FROM tag" + + " INNER JOIN imagebase_x_tag USING (tagid)" + + " WHERE imagebaseid = :imagebaseid"); + stmt.setString("imagebaseid", imageBaseId); + ResultSet rs = stmt.executeQuery(); + List tagList = new ArrayList<>(); + while (rs.next()) { + tagList.add(rs.getString("displayname")); + } + stmt.close(); + return tagList; + } + +} diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/UserPermissions.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/UserPermissions.java new file mode 100644 index 00000000..d741aa4b --- /dev/null +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/permissions/UserPermissions.java @@ -0,0 +1,52 @@ +package org.openslx.bwlp.sat.permissions; + +import org.openslx.bwlp.thrift.iface.ImagePermissions; +import org.openslx.bwlp.thrift.iface.UserInfo; + +public class UserPermissions { + + private enum Permission { + LINK, + DOWNLOAD, + EDIT, + ADMIN + } + + public static boolean canLinkImage(UserInfo ui, ImagePermissions... imagePermissions) { + return canActionImage(Permission.LINK, imagePermissions) || isSuperUser(ui); + } + + public static boolean canDownloadImage(UserInfo ui, ImagePermissions... imagePermissions) { + return canActionImage(Permission.DOWNLOAD, imagePermissions) || isSuperUser(ui); + } + + public static boolean canEditImage(UserInfo ui, ImagePermissions... imagePermissions) { + return canActionImage(Permission.EDIT, imagePermissions) || isSuperUser(ui); + } + + public static boolean canAdminImage(UserInfo ui, ImagePermissions... imagePermissions) { + return canActionImage(Permission.ADMIN, imagePermissions) || isSuperUser(ui); + } + + private static boolean canActionImage(Permission checkPerm, ImagePermissions... imagePermissions) { + for (ImagePermissions perm : imagePermissions) { + if (perm == null) + continue; + if (checkPerm == Permission.LINK && perm.link) + return true; + if (checkPerm == Permission.DOWNLOAD && perm.download) + return true; + if (checkPerm == Permission.EDIT && perm.edit) + return true; + if (checkPerm == Permission.ADMIN && perm.admin) + return true; + } + return false; + } + + public static boolean isSuperUser(UserInfo ui) { + // TODO: for superuser override + return false; + } + +} diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java index cf26b510..7307fbae 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/ServerHandler.java @@ -1,6 +1,7 @@ package org.openslx.bwlp.sat.thrift; import java.nio.ByteBuffer; +import java.sql.SQLException; import java.util.List; import java.util.Map; @@ -23,6 +24,7 @@ import org.openslx.bwlp.thrift.iface.OperatingSystem; import org.openslx.bwlp.thrift.iface.Organization; import org.openslx.bwlp.thrift.iface.SatelliteServer; import org.openslx.bwlp.thrift.iface.TAuthorizationException; +import org.openslx.bwlp.thrift.iface.TInternalServerError; import org.openslx.bwlp.thrift.iface.TInvalidTokenException; import org.openslx.bwlp.thrift.iface.TNotFoundException; import org.openslx.bwlp.thrift.iface.TTransferRejectedException; @@ -109,14 +111,22 @@ public class ServerHandler implements SatelliteServer.Iface { public List getImageList(String userToken, List tagSearch) throws TAuthorizationException, TException { UserInfo user = SessionManager.getOrFail(userToken); - return DbImage.getAllVisible(user, tagSearch); + try { + return DbImage.getAllVisible(user, tagSearch); + } catch (SQLException e) { + throw new TInternalServerError(); + } } @Override public ImageDetailsRead getImageDetails(String userToken, String imageBaseId) throws TAuthorizationException, TNotFoundException, TException { - // TODO Auto-generated method stub - return null; + UserInfo user = SessionManager.getOrFail(userToken); + try { + return DbImage.getImageDetails(user, imageBaseId); + } catch (SQLException e) { + throw new TInternalServerError(); + } } @Override diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/CacheBase.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/CacheBase.java new file mode 100644 index 00000000..e42ee9fe --- /dev/null +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/CacheBase.java @@ -0,0 +1,43 @@ +package org.openslx.bwlp.sat.thrift.cache; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.apache.thrift.TException; + +/** + * Class that caches an instance of a given class for 10 minutes. + * If the cache expired and a fresh instance cannot be acquired, + * the old instance will be returned. + * + * @param The class to cache + */ +public abstract class CacheBase { + + private static final Logger LOGGER = Logger.getLogger(CacheBase.class); + + private static final int TIMEOUT = 10 * 60 * 1000; + + private T cachedInstance = null; + + private long cacheTimeout = 0; + + protected abstract T getCallback() throws TException; + + protected synchronized T getInternal() { + final long now = System.currentTimeMillis(); + if (cachedInstance == null || now > cacheTimeout) { + try { + T freshInstance = getCallback(); + if (freshInstance != null) { + cachedInstance = freshInstance; + cacheTimeout = now + TIMEOUT; + } + } catch (TException e) { + LOGGER.warn("Could not retrieve fresh instance of " + getClass().getSimpleName(), e); + } + } + return cachedInstance; + } + +} diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/CachedList.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/CachedList.java deleted file mode 100644 index 4c986fd2..00000000 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/CachedList.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.openslx.bwlp.sat.thrift.cache; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.apache.thrift.TException; -import org.openslx.util.TimeoutReference; - - -public abstract class CachedList { - - private static final Logger LOGGER = Logger.getLogger(CachedList.class); - - private final TimeoutReference> cachedList = new TimeoutReference<>(600000, null); - - protected abstract List getCallback() throws TException; - - protected synchronized List getInternal() { - List list = cachedList.get(); - if (list == null) { - try { - list = getCallback(); - } catch (TException e) { - LOGGER.warn("Could not retrieve " + getClass().getSimpleName() + " list from master server", - e); - return null; - } - cachedList.set(list); - } - return list; - } - -} diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/OperatingSystemList.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/OperatingSystemList.java index 020ae4ff..58b5d84e 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/OperatingSystemList.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/OperatingSystemList.java @@ -10,7 +10,7 @@ import org.openslx.thrifthelper.ThriftManager; * Holds the list of all known organizations. The list is synchronized with * the master server. */ -public class OperatingSystemList extends CachedList { +public class OperatingSystemList extends CacheBase> { private static final OperatingSystemList instance = new OperatingSystemList(); diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/OrganizationList.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/OrganizationList.java index 8db7e7e5..e012e5e2 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/OrganizationList.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/cache/OrganizationList.java @@ -1,9 +1,11 @@ package org.openslx.bwlp.sat.thrift.cache; import java.util.List; +import java.util.TimerTask; import org.apache.thrift.TException; import org.openslx.bwlp.sat.database.mappers.DbOrganization; +import org.openslx.bwlp.sat.util.QuickTimer; import org.openslx.bwlp.thrift.iface.Organization; import org.openslx.thrifthelper.ThriftManager; @@ -11,7 +13,7 @@ import org.openslx.thrifthelper.ThriftManager; * Holds the list of all known organizations. The list is synchronized with * the master server. */ -public class OrganizationList extends CachedList { +public class OrganizationList extends CacheBase> { private static final OrganizationList instance = new OrganizationList(); @@ -21,8 +23,14 @@ public class OrganizationList extends CachedList { @Override protected List getCallback() throws TException { - List organizations = ThriftManager.getMasterClient().getOrganizations(); - DbOrganization.storeOrganizations(organizations); + final List organizations = ThriftManager.getMasterClient().getOrganizations(); + // Also store the list in the local data base (asynchronous, in the timer thread) + QuickTimer.scheduleOnce(new TimerTask() { + @Override + public void run() { + DbOrganization.storeOrganizations(organizations); + } + }); return organizations; } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/QuickTimer.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/QuickTimer.java index 7a317ff7..ea5831ad 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/QuickTimer.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/util/QuickTimer.java @@ -27,6 +27,10 @@ public class QuickTimer { timer.schedule(task, delay); } + public static void scheduleOnce(TimerTask timerTask) { + scheduleOnce(timerTask, 1); + } + /** * Cancel this timer. Should only be called when the server is shutting * down. -- cgit v1.2.3-55-g7522