diff options
10 files changed, 300 insertions, 20 deletions
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/filetransfer/DownloadTask.java b/dozentenmodul/src/main/java/org/openslx/dozmod/filetransfer/DownloadTask.java index 03abada4..ba236c58 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/filetransfer/DownloadTask.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/filetransfer/DownloadTask.java @@ -3,9 +3,7 @@ package org.openslx.dozmod.filetransfer; import java.io.File; import java.io.FileNotFoundException; import java.io.RandomAccessFile; -import java.nio.ByteBuffer; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.Logger; import org.openslx.bwlp.thrift.iface.TransferState; @@ -37,7 +35,7 @@ public class DownloadTask extends TransferTask { private boolean fileWritable = true; public DownloadTask(String host, int port, String downloadToken, File destinationFile, long fileSize, - List<ByteBuffer> sha1Sums) throws FileNotFoundException { + List<byte[]> sha1Sums) throws FileNotFoundException { super(destinationFile, fileSize); this.host = host; this.port = port; diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/CustomImagePermissionWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/CustomImagePermissionWindow.java new file mode 100644 index 00000000..f096163f --- /dev/null +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/CustomImagePermissionWindow.java @@ -0,0 +1,123 @@ +package org.openslx.dozmod.gui.window; + +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.Map; +import java.util.Map.Entry; + +import javax.swing.JOptionPane; + +import org.apache.log4j.Logger; +import org.apache.thrift.TException; +import org.openslx.bwlp.thrift.iface.ImagePermissions; +import org.openslx.bwlp.thrift.iface.UserInfo; +import org.openslx.dozmod.gui.Gui; +import org.openslx.dozmod.gui.control.table.ImagePermissionTable.UserImagePermissions; +import org.openslx.dozmod.gui.helper.MessageType; +import org.openslx.dozmod.gui.window.UserListWindow.UserAddedCallback; +import org.openslx.dozmod.gui.window.layout.CustomImagePermissionWindowLayout; +import org.openslx.dozmod.thrift.Session; +import org.openslx.thrifthelper.ThriftManager; + + +@SuppressWarnings("serial") +public class CustomImagePermissionWindow extends CustomImagePermissionWindowLayout { + + private static final Logger LOGGER = Logger.getLogger(CustomImagePermissionWindow.class); + + + private final CustomImagePermissionWindow me; + private ArrayList<UserImagePermissions> permissionList = new ArrayList<>(); + + protected CustomImagePermissionWindow(final Frame modalParent, final Map<String, ImagePermissions> permissionMap, final ImagePermissions defaultPermissions, final String imageBaseId) { + super(modalParent); + me = this; + + + for (Entry<String, ImagePermissions> e : permissionMap.entrySet()) { + permissionList.add(new UserImagePermissions(e.getKey(), e.getValue())); + } + + permissionTable.setData(permissionList, false); + + // add user button adapter + btnAddUser.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + // TODO again: which frame to giev? JOptionPane.getFrameForComponent(me) sounds cool at least :) + UserListWindow.open(JOptionPane.getFrameForComponent(me), new UserAddedCallback() { + @Override + public void userAdded(final UserInfo newUser, UserListWindow window) { + + // check if we have this user already + for (UserImagePermissions current : permissionList) { + if (current.userId.equals(newUser.userId)) { + LOGGER.debug("User already present in the list, skipping!"); + return; + } + } + // add it to the list with default permissions + permissionList.add(new UserImagePermissions(newUser.userId, new ImagePermissions(defaultPermissions))); + LOGGER.debug("User added: " + newUser); + permissionTable.setData(permissionList, false); + } + }, "Hinzufügen"); + } + }); + // delete user button adapter + btnRemoveUser.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + final UserImagePermissions selected = permissionTable.getSelectedItem(); + LOGGER.debug("Removing: " + selected); + if (!permissionList.remove(selected)) { + LOGGER.debug("Could not remove: " + selected); + } + permissionTable.setData(permissionList, false); + } + }); + + btnClose.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent arg0) { + dispose(); + } + }); + + btnSave.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + // save the table stuff to our upload wizard state + if (permissionList == null || permissionList.isEmpty()) + return; + + permissionMap.clear(); + + // put permissions of the list into the map to upload + for (UserImagePermissions perm : permissionList) { + permissionMap.put(perm.userId, perm.permissions); + } + + // TODO allow admin permission changes? + // push permissions to satellite server + try { + ThriftManager.getSatClient().writeImagePermissions(Session.getSatelliteToken(), + imageBaseId, permissionMap); + } catch (TException er) { + Gui.showMessageBox(me, "Konnte Berechtigungen nicht an den Satelliten übertragen: ", MessageType.ERROR, LOGGER, er); + } + dispose(); + } + }); + + } + + public static void open(Frame modalParent, Map<String, ImagePermissions> permissionMap, ImagePermissions defaultPermissions, String imageBaseId) { + new CustomImagePermissionWindow(modalParent, permissionMap, defaultPermissions, imageBaseId).setVisible(true); + } +} diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ImageDetailsWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ImageDetailsWindow.java index 9d6e56e5..8a46b4dd 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ImageDetailsWindow.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/ImageDetailsWindow.java @@ -10,6 +10,7 @@ import java.awt.event.MouseEvent; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Map; import javax.swing.JMenuItem; import javax.swing.JOptionPane; @@ -20,6 +21,7 @@ import org.apache.log4j.Logger; import org.apache.thrift.TException; import org.openslx.bwlp.thrift.iface.ImageBaseWrite; 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.OperatingSystem; @@ -70,6 +72,8 @@ public class ImageDetailsWindow extends ImageDetailsWindowLayout implements UiFe * Image that this window shows the details of */ private ImageDetailsRead image = null; + + private Map<String, ImagePermissions> permissionMap; /** * Popup menu items @@ -123,6 +127,15 @@ public class ImageDetailsWindow extends ImageDetailsWindowLayout implements UiFe }, "Besitzer festlegen"); } }); + btnCustomPermissions.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent arg0) { + CustomImagePermissionWindow.open(JOptionPane.getFrameForComponent(me), permissionMap, image.defaultPermissions, image.imageBaseId); + + + } + }); /** * Popup menu for the version table on the right side @@ -213,6 +226,7 @@ public class ImageDetailsWindow extends ImageDetailsWindowLayout implements UiFe return; image = ThriftManager.getSatClient().getImageDetails(Session.getSatelliteToken(), imageBaseId); + permissionMap = ThriftManager.getSatClient().getImagePermissions(Session.getSatelliteToken(), imageBaseId); } } catch (Exception e) { error = e; @@ -456,6 +470,7 @@ public class ImageDetailsWindow extends ImageDetailsWindowLayout implements UiFe txtTags.setEditable(editable); cboOperatingSystem.setEnabled(editable); cboShareMode.setEnabled(editable); + btnCustomPermissions.setEnabled(editable); btnChangeOwner.setEnabled(editable && ImagePerms.canAdmin(image)); } diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/CustomImagePermissionWindowLayout.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/CustomImagePermissionWindowLayout.java new file mode 100644 index 00000000..8c48a8f1 --- /dev/null +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/CustomImagePermissionWindowLayout.java @@ -0,0 +1,71 @@ +package org.openslx.dozmod.gui.window.layout; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.JScrollPane; + +import org.apache.log4j.Logger; +import org.openslx.dozmod.gui.control.table.ImagePermissionTable; + + +@SuppressWarnings("serial") +public class CustomImagePermissionWindowLayout extends JDialog { + + private static final Logger LOGGER = Logger.getLogger(CustomImagePermissionWindowLayout.class); + + protected final ImagePermissionTable permissionTable; + + protected final JButton btnSave; + protected final JButton btnClose; + protected final JButton btnAddUser; + protected final JButton btnRemoveUser; + + protected boolean imagePermPage; + + + private static String title = "Benutzerdefinierte Berechtigungen"; + + protected CustomImagePermissionWindowLayout(Frame modalParent) { + super(modalParent, title, modalParent != null ? ModalityType.APPLICATION_MODAL + : ModalityType.MODELESS); + + JPanel tablePane = new JPanel(); + tablePane.setLayout(new BorderLayout()); + tablePane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + permissionTable = new ImagePermissionTable(); + tablePane.add(new JScrollPane(permissionTable), BorderLayout.CENTER); + JPanel userButtonPane = new JPanel(); + btnAddUser = new JButton("Benutzer hinzufügern"); + userButtonPane.add(btnAddUser); + btnRemoveUser = new JButton("Benutzer entfernen"); + userButtonPane.add(btnRemoveUser); + tablePane.add(userButtonPane, BorderLayout.SOUTH); + + // spaced buttons + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); + buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); + btnSave = new JButton("Änderungen speichern"); + buttonPane.add(btnSave); + buttonPane.add(Box.createGlue()); + btnClose = new JButton("Abbrechen"); + buttonPane.add(btnClose); + + // pack it all + Container contentPane = getContentPane(); + contentPane.add(tablePane, BorderLayout.CENTER); + contentPane.add(buttonPane, BorderLayout.PAGE_END); + setPreferredSize(new Dimension(480, 350)); + pack(); + setLocationRelativeTo( modalParent ); + } +} diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/ImageDetailsWindowLayout.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/ImageDetailsWindowLayout.java index b42bbd6e..54c478e3 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/ImageDetailsWindowLayout.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/layout/ImageDetailsWindowLayout.java @@ -50,6 +50,7 @@ public abstract class ImageDetailsWindowLayout extends JDialog { protected final JTextField txtId; protected final JTextField txtVersion; + protected final JButton btnCustomPermissions; protected final JButton btnSaveChanges; protected final JButton btnUpdateImage; protected final JButton btnClose; @@ -171,7 +172,10 @@ public abstract class ImageDetailsWindowLayout extends JDialog { grid.add(new JLabel("Image-UUID")); grid.add(txtId, 2).expand(true, false).fill(true, false); grid.nextRow(); - + btnCustomPermissions = new JButton("Benutzerdefinierte Berechtigungen"); + grid.add(btnCustomPermissions); + grid.skip(2); + grid.nextRow(); grid.finish(true); infoPanel.setPreferredSize(new Dimension(500, 400)); diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/ThriftActions.java b/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/ThriftActions.java index 458498c0..e57a9310 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/ThriftActions.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/ThriftActions.java @@ -142,31 +142,33 @@ public class ThriftActions { return fileName; } + public interface DeleteCallback { + void isDeleted(boolean success); + } + /******************************************************************************** * * DELETE ACTION * - * Deletes a specific image version or the latest if none is specified + * Deletes a specific image version * ********************************************************************************/ - public interface DeleteCallback { - void isDeleted(boolean success); - } - public static void deleteImageVersion(final Frame frame, final String imageBaseId, final String imageVersionId, final DeleteCallback callback) { + public static void deleteImageVersion(final Frame frame, final String imageBaseId, + final String imageVersionId, final DeleteCallback callback) { // requires confirmation of the user - if (!Gui.showMessageBox(frame, "Wollen Sie die Version dieses Images wirklich löschen?", + if (!Gui.showMessageBox(frame, "Wollen Sie diese Image-Version wirklich löschen?", MessageType.QUESTION_YESNO, LOGGER, null)) return; // try to actually delete this version of the image QuickTimer.scheduleOnce(new Task() { boolean success = false; + @Override public void fire() { try { ThriftManager.getSatClient().deleteImageVersion(Session.getSatelliteToken(), imageVersionId); - LOGGER.info("Deleted version '" + imageVersionId + "' of image '" - + imageBaseId + "'."); + LOGGER.info("Deleted version '" + imageVersionId + "' of image '" + imageBaseId + "'."); success = true; } catch (TException e) { ThriftError.showMessage(frame, LOGGER, e, "Das Löschen der Version ist gescheitert"); 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 81898d7c..2f913ba0 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/App.java @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import javax.net.ssl.SSLContext; + import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Logger; import org.apache.thrift.transport.TTransportException; @@ -78,7 +80,8 @@ public class App { } }); - ThriftManager.setMasterServerAddress("bwlp-masterserver.ruf.uni-freiburg.de"); + ThriftManager.setMasterServerAddress(SSLContext.getDefault(), + "bwlp-masterserver.ruf.uni-freiburg.de", 9091, 30000); // Load useful things from master server OrganizationList.get(); diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/ActiveUpload.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/ActiveUpload.java index 01cd072d..f03c06f3 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/ActiveUpload.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/ActiveUpload.java @@ -4,7 +4,6 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; -import java.nio.ByteBuffer; import java.security.NoSuchAlgorithmException; import java.sql.SQLException; import java.util.ArrayList; @@ -115,7 +114,7 @@ public class ActiveUpload implements HashCheckCallback { } public ActiveUpload(String uploadId, UserInfo owner, ImageDetailsRead image, File destinationFile, - long fileSize, List<ByteBuffer> sha1Sums, byte[] machineDescription) throws FileNotFoundException { + long fileSize, List<byte[]> sha1Sums, byte[] machineDescription) throws FileNotFoundException { this.destinationFile = destinationFile; this.outFile = new RandomAccessFile(destinationFile, "rw"); this.chunks = new ChunkList(fileSize, sha1Sums); @@ -326,7 +325,7 @@ public class ActiveUpload implements HashCheckCallback { @Override public FileRange get() { if (currentChunk != null) { - if (currentChunk.hasSha1Sum() && hashChecker != null) { + if (hashChecker != null && currentChunk.getSha1Sum() != null) { try { hashChecker.queue(currentChunk, buffer, activeUpload); } catch (InterruptedException e) { @@ -365,7 +364,8 @@ public class ActiveUpload implements HashCheckCallback { public void hashCheckDone(HashResult result, byte[] data, FileChunk chunk) { switch (result) { case FAILURE: - LOGGER.warn("Hash check of chunk " + chunk.toString() + " failed. Assuming valid."); + LOGGER.warn("Hash check of chunk " + chunk.toString() + + " could not be executed. Assuming valid :-("); // Fall through case VALID: writeFileData(chunk.range.startOffset, chunk.range.getLength(), data); @@ -376,6 +376,38 @@ public class ActiveUpload implements HashCheckCallback { } } + private byte[] loadChunkFromFile(FileChunk chunk) { + synchronized (outFile) { + try { + outFile.seek(chunk.range.startOffset); + byte[] buffer = new byte[chunk.range.getLength()]; + outFile.readFully(buffer); + return buffer; + } catch (IOException e) { + LOGGER.error( + "Could not read chunk " + chunk.getChunkIndex() + " of File " + + destinationFile.toString(), e); + return null; + } + } + } + + public void updateBlockHashList(List<byte[]> hashList) { + if (hashChecker == null) + return; + chunks.updateSha1Sums(hashList); + for (FileChunk chunk = chunks.getUnhashedComplete(); chunk != null;) { + byte[] data = loadChunkFromFile(chunk); + try { + hashChecker.queue(chunk, data, this); + } catch (InterruptedException e) { + LOGGER.warn("Got interrupted while queueing block for hash check", e); + Thread.currentThread().interrupt(); + return; + } + } + } + // TODO: Clean up old stale uploads } diff --git a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/FileServer.java b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/FileServer.java index cc54ba94..a71b7b3f 100644 --- a/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/FileServer.java +++ b/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/fileserv/FileServer.java @@ -3,7 +3,6 @@ package org.openslx.bwlp.sat.fileserv; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import java.nio.ByteBuffer; import java.sql.SQLException; import java.util.Iterator; import java.util.List; @@ -117,7 +116,7 @@ public class FileServer implements IncomingEvent { } public ActiveUpload createNewUserUpload(UserInfo owner, ImageDetailsRead image, long fileSize, - List<ByteBuffer> sha1Sums, byte[] machineDescription) throws TTransferRejectedException { + List<byte[]> sha1Sums, byte[] machineDescription) throws TTransferRejectedException { Iterator<ActiveUpload> it = uploads.values().iterator(); int activeUploads = 0; while (it.hasNext()) { 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 f1240c21..b3e6208e 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 @@ -2,6 +2,7 @@ package org.openslx.bwlp.sat.thrift; import java.nio.ByteBuffer; import java.sql.SQLException; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -71,6 +72,18 @@ public class ServerHandler implements SatelliteServer.Iface { * File Transfer */ + private List<byte[]> unwrapHashes(List<ByteBuffer> blockHashes) { + if (blockHashes == null || blockHashes.isEmpty()) + return null; + List<byte[]> hashList = new ArrayList<>(blockHashes.size()); + for (ByteBuffer hash : blockHashes) { + byte[] buffer = new byte[hash.remaining()]; + hash.get(buffer); + hashList.add(buffer); + } + return hashList; + } + @Override public TransferInformation requestImageVersionUpload(String userToken, String imageBaseId, long fileSize, List<ByteBuffer> blockHashes, ByteBuffer machineDescription) throws TTransferRejectedException, @@ -83,16 +96,29 @@ public class ServerHandler implements SatelliteServer.Iface { } catch (SQLException e) { throw new TInternalServerError(); } + // Unwrap machine description byte[] mDesc = null; if (machineDescription != null) { mDesc = new byte[machineDescription.remaining()]; machineDescription.get(mDesc); } - ActiveUpload transfer = fileServer.createNewUserUpload(user, image, fileSize, blockHashes, mDesc); + // Unwrap sha1sum list + List<byte[]> hashList = unwrapHashes(blockHashes); + ActiveUpload transfer = fileServer.createNewUserUpload(user, image, fileSize, hashList, mDesc); return new TransferInformation(transfer.getId(), fileServer.getPlainPort(), fileServer.getSslPort()); } @Override + public void updateBlockHashes(String uploadToken, List<ByteBuffer> blockHashes) + throws TInvalidTokenException { + ActiveUpload upload = fileServer.getUploadByToken(uploadToken); + if (upload == null) + throw new TInvalidTokenException(); + List<byte[]> hashList = unwrapHashes(blockHashes); + upload.updateBlockHashList(hashList); + } + + @Override public ByteBuffer getMachineDescription(String userToken, String imageVersionId) throws TAuthorizationException, TInternalServerError, TNotFoundException, TException { // TODO Auto-generated method stub @@ -300,6 +326,13 @@ public class ServerHandler implements SatelliteServer.Iface { } @Override + public void deleteImageBase(String userToken, String imageBaseId) throws TAuthorizationException, + TNotFoundException, TInternalServerError { + // TODO Auto-generated method stub + + } + + @Override public void writeImagePermissions(String userToken, String imageBaseId, Map<String, ImagePermissions> permissions) throws TAuthorizationException, TNotFoundException, TInternalServerError { |
