From 68dd3e08b4eb4e5f8acd686b3fa64c2dd0939a02 Mon Sep 17 00:00:00 2001 From: bancika Date: Sat, 5 Dec 2020 21:43:29 +0100 Subject: [PATCH] Project Cloud: replace project file doesn't do what it's supposed to --- diylc-server-api/v1/replaceProjectFiles.php | 116 +++ diylc-server-api/v1/uploadProject.php | 6 +- .../plugins/cloud/model/IServiceAPI.java | 17 + .../cloud/presenter/CloudPresenter.java | 26 +- diylc/diylc-swing/.gitignore | 3 +- diylc/diylc-swing/izpack.xml | 3 - .../view/browser/ResultsScrollPanel.java | 700 +++++++++--------- 7 files changed, 507 insertions(+), 364 deletions(-) create mode 100644 diylc-server-api/v1/replaceProjectFiles.php diff --git a/diylc-server-api/v1/replaceProjectFiles.php b/diylc-server-api/v1/replaceProjectFiles.php new file mode 100644 index 00000000..254b6652 --- /dev/null +++ b/diylc-server-api/v1/replaceProjectFiles.php @@ -0,0 +1,116 @@ + 100000) { + echo "{\"string\":Thumbnail file is too big.}"; + exit; +} +if ($projectFile['size'] > 10000000) { + echo "{\"string\":Project file is too big.}"; + exit; +} +if (getimagesize($thumbnailFile['tmp_name']) == false) { + echo "{\"string\":Thumbnail image is not valid.}"; + exit; +} + +// Load help class +require_once("properties.php"); + +// Load properties +$dbProperties = new Properties(); +$propertiesFile = fopen("db.properties", "rb"); +$dbProperties->load($propertiesFile); + +// Connect to the DB +$username=$dbProperties->getProperty("user"); +$password=$dbProperties->getProperty("pass"); +$database=$dbProperties->getProperty("db"); +$mysqli = new mysqli(localhost,$username,$password,$database); + +// Verify that the user is logged in +$sql = " +SELECT user_id +FROM diylc_user +WHERE name = \"".addslashes($name)."\" AND token= \"".addslashes($token)."\" AND machine_id = \"".addslashes($machineId)."\""; + +if (!$result = $mysqli->query($sql)) { + echo "{\"string\":Error while looking up the user.}"; + exit; +} + +if ($row = $result->fetch_assoc()) { + $userId = $row["user_id"]; + + $sql = " + SELECT project_id + FROM diylc_project + WHERE project_id = \"".addslashes($projectId)."\" AND owner_user_id = \"".addslashes($userId)."\""; + + if (!$result = $mysqli->query($sql)) { + echo "{\"string\":Error while looking up the project.}"; + exit; + } + + $sql= " + UPDATE diylc_project + SET diylc_version=\"".$diylcVersion."\", last_update = NOW() + WHERE project_id=".addslashes($projectId)." AND owner_user_id=".$userId; + + if (!$result = $mysqli->query($sql) || $mysqli->affected_rows == 0) { + echo "{\"string\":\"Error while uploading the project into the database.".$mysqli->error."\"}"; + exit; + } else { + // Move the uploaded files + if (move_uploaded_file($thumbnailFile['tmp_name'], '/home/diyfever/public_html/diylc/thumbnails/'.$projectId.".png") and + move_uploaded_file($projectFile['tmp_name'], '/home/diyfever/public_html/diylc/uploads/'.$projectId.".diy")) + echo "{\"string\":Success}"; + else { + echo "{\"string\":Error processing uploaded files.}"; + } + } +} else { + echo "{\"string\":User is not logged in.}"; +} + +$mysqli->close(); + +?> \ No newline at end of file diff --git a/diylc-server-api/v1/uploadProject.php b/diylc-server-api/v1/uploadProject.php index 8752477d..2c2d7772 100644 --- a/diylc-server-api/v1/uploadProject.php +++ b/diylc-server-api/v1/uploadProject.php @@ -39,11 +39,11 @@ if (!$diylcVersion) { echo "{\"string\":DIYLC version not provided.}"; exit; } -if (!$thumbnailFile && !projectId) { +if (!$thumbnailFile && !$projectId) { echo "{\"string\":Thumbnail file not uploaded.}"; exit; } -if (!$projectFile && !projectId) { +if (!$projectFile && !$projectId) { echo "{\"string\":Project file not uploaded.}"; exit; } @@ -55,7 +55,7 @@ if ($projectFile['size'] > 10000000) { echo "{\"string\":Project file is too big.}"; exit; } -if (!projectId && getimagesize($thumbnailFile['tmp_name']) == false) { +if (!$projectId && getimagesize($thumbnailFile['tmp_name']) == false) { echo "{\"string\":Thumbnail image is not valid.}"; exit; } diff --git a/diylc/diylc-core/src/org/diylc/plugins/cloud/model/IServiceAPI.java b/diylc/diylc-core/src/org/diylc/plugins/cloud/model/IServiceAPI.java index 7eadbb1d..c7873032 100644 --- a/diylc/diylc-core/src/org/diylc/plugins/cloud/model/IServiceAPI.java +++ b/diylc/diylc-core/src/org/diylc/plugins/cloud/model/IServiceAPI.java @@ -149,6 +149,23 @@ public interface IServiceAPI { @ParamName("category") String category, @ParamName("description") String description, @ParamName("diylcVersion") String diylcVersion, @ParamName("keywords") String keywords, @ParamName("thumbnail") File thumbnail, @ParamName("project") File project, + @ParamName("projectId") Integer projectId); + + /** + * Replaces project files using token to authenticate. The project must belong to the user. + * + * @param username + * @param token + * @param machineId + * @param diylcVersion + * @param thumbnail + * @param project + * @param projectId + * @return "Success" if the upload was successful or error message if it failed. + */ + String replaceProjectFiles(@ParamName("username") String username, @ParamName("token") String token, + @ParamName("machineId") String machineId, @ParamName("diylcVersion") String diylcVersion, + @ParamName("thumbnail") File thumbnail, @ParamName("project") File project, @ParamName("projectId") Integer projectId); /** diff --git a/diylc/diylc-core/src/org/diylc/plugins/cloud/presenter/CloudPresenter.java b/diylc/diylc-core/src/org/diylc/plugins/cloud/presenter/CloudPresenter.java index 0a564461..385b292a 100644 --- a/diylc/diylc-core/src/org/diylc/plugins/cloud/presenter/CloudPresenter.java +++ b/diylc/diylc-core/src/org/diylc/plugins/cloud/presenter/CloudPresenter.java @@ -167,8 +167,12 @@ public class CloudPresenter { if (username == null || token == null) throw new CloudException("Login failed. Please try to login again."); - - LOG.info("Uploading a new project: " + projectName); + + if (projectId == null) + LOG.info("Uploading a new project: " + projectName); + else + LOG.info("Updating project: " + projectId); + try { String res = getService().uploadProject(username, token, getMachineId(), projectName, category, description, diylcVersion, @@ -178,6 +182,24 @@ public class CloudPresenter { } catch (Exception e) { throw new CloudException(e); } + } + + public void replaceProjectFile(String diylcVersion, File thumbnail, File project, Integer projectId) throws IOException, CloudException { + String username = ConfigurationManager.getInstance().readString(USERNAME_KEY, null); + String token = ConfigurationManager.getInstance().readString(TOKEN_KEY, null); + + if (username == null || token == null) + throw new CloudException("Login failed. Please try to login again."); + + LOG.info("Replacing project files for: " + projectId); + try { + String res = + getService().replaceProjectFiles(username, token, getMachineId(), diylcVersion, thumbnail, project, projectId); + if (!res.equals(SUCCESS)) + throw new CloudException(res); + } catch (Exception e) { + throw new CloudException(e); + } } public void updateProjectDetails(ProjectEntity project, String diylcVersion) throws IOException, CloudException { diff --git a/diylc/diylc-swing/.gitignore b/diylc/diylc-swing/.gitignore index c35c3382..6a7aab75 100644 --- a/diylc/diylc-swing/.gitignore +++ b/diylc/diylc-swing/.gitignore @@ -5,4 +5,5 @@ /library/ /lib/diylc-core.jar autoSave.diy -config.xml \ No newline at end of file +config.xml +/launch4j.log diff --git a/diylc/diylc-swing/izpack.xml b/diylc/diylc-swing/izpack.xml index 9aaacfd7..1df0aaaa 100644 --- a/diylc/diylc-swing/izpack.xml +++ b/diylc/diylc-swing/izpack.xml @@ -43,9 +43,6 @@ - - diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/browser/ResultsScrollPanel.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/browser/ResultsScrollPanel.java index 39e7d86d..29d89b96 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/browser/ResultsScrollPanel.java +++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/browser/ResultsScrollPanel.java @@ -1,215 +1,213 @@ /* + * + * DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with DIYLC. If not, see + * . + * + */ +package org.diylc.swing.plugins.cloud.view.browser; - DIY Layout Creator (DIYLC). - Copyright (c) 2009-2018 held jointly by the individual authors. +import java.awt.Color; +import java.awt.Cursor; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.util.List; - This file is part of DIYLC. +import javax.imageio.ImageIO; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JTextArea; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import javax.swing.text.DefaultCaret; - DIYLC is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DIYLC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with DIYLC. If not, see . - -*/ -package org.diylc.swing.plugins.cloud.view.browser; - -import java.awt.Color; -import java.awt.Cursor; -import java.awt.FlowLayout; -import java.awt.Graphics; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Point; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileOutputStream; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.List; - -import javax.imageio.ImageIO; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSeparator; -import javax.swing.JTextArea; -import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; -import javax.swing.SwingWorker; -import javax.swing.text.DefaultCaret; - import org.apache.log4j.Logger; import org.diylc.appframework.miscutils.InMemoryConfigurationManager; -import org.diylc.common.IPlugInPort; -import org.diylc.common.ITask; -import org.diylc.common.PropertyWrapper; +import org.diylc.common.IPlugInPort; +import org.diylc.common.ITask; +import org.diylc.common.PropertyWrapper; import org.diylc.core.IView; import org.diylc.swing.images.IconLoader; -import org.diylc.plugins.cloud.model.CommentEntity; -import org.diylc.plugins.cloud.model.ProjectEntity; -import org.diylc.plugins.cloud.presenter.CloudPresenter; -import org.diylc.plugins.cloud.presenter.SearchSession; -import org.diylc.presenter.Presenter; -import org.diylc.swing.ISimpleView; -import org.diylc.swing.ISwingUI; -import org.diylc.swing.gui.DialogFactory; -import org.diylc.swing.gui.DummyView; -import org.diylc.swing.gui.components.HTMLTextArea; -import org.diylc.swing.gui.editor.PropertyEditorDialog; -import org.diylc.swing.plugins.cloud.view.CommentDialog; -import org.diylc.swing.plugins.cloud.view.UploadDialog; -import org.diylc.swing.plugins.file.FileFilterEnum; -import org.diylc.swingframework.ButtonDialog; - -/** - * Component that is capable of showing a list of {@link ProjectEntity} objects. Can work in paging - * mode and pull one page of data at a time. - * - * @see {@link SearchSession} - * - * @author Branislav Stojkovic - */ -public class ResultsScrollPanel extends JScrollPane { - - private static final long serialVersionUID = 1L; - - private static final Logger LOG = Logger.getLogger(ResultsScrollPanel.class); - - private JPanel resultsPanel; - /** - * This label goes at the end of the page. When it gets rendered we know that we need to request - * another page. - */ - private JLabel loadMoreLabel; - - private JLabel topLabel; - - private ISwingUI mainUI; - private ISimpleView cloudUI; - - private IPlugInPort plugInPort; - - private int currentLocation; - /** - * This flag tells us whether the loadMoreLabel should invoke a new data pull or not. - */ - private boolean armed; - private SearchSession searchSession; - - private Icon spinnerIcon = IconLoader.Spinning.getIcon(); - - private boolean showEditControls; - - public ResultsScrollPanel(ISwingUI mainUI, ISimpleView cloudUI, IPlugInPort plugInPort, SearchSession searchSession, - boolean showEditControls) { - super(); - this.mainUI = mainUI; - this.cloudUI = cloudUI; - this.plugInPort = plugInPort; - this.searchSession = searchSession; - this.showEditControls = showEditControls; - - this.getVerticalScrollBar().setUnitIncrement(16); - this.setBorder(null); - setViewportView(getResultsPanel()); - } - - public void clearPrevious() { - currentLocation = 0; - getResultsPanel().removeAll(); - armed = false; - } - - public void startSearch(List projects) { - GridBagConstraints gbc = new GridBagConstraints(); - gbc.anchor = GridBagConstraints.NORTHWEST; - gbc.gridx = 0; - gbc.gridy = 10000; - gbc.fill = GridBagConstraints.BOTH; - gbc.weightx = 100; - gbc.weighty = 100; - gbc.gridwidth = 3; - resultsPanel.add(getLoadMoreLabel(), gbc); - - gbc.gridx = 3; - gbc.gridwidth = 2; - gbc.weightx = 0; - gbc.insets = new Insets(0, 0, 0, 2); - gbc.fill = GridBagConstraints.NONE; - gbc.anchor = GridBagConstraints.LINE_END; - resultsPanel.add(getTopLabel(), gbc); - - addData(projects); - } - - public void showNoMatches() { - JLabel label = - new JLabel("No projects match the search criteria."); - label.setHorizontalAlignment(SwingConstants.CENTER); - GridBagConstraints gbc = new GridBagConstraints(); - gbc.insets = new Insets(2, 2, 2, 2); - gbc.gridx = 0; - gbc.gridy = 0; - gbc.fill = GridBagConstraints.BOTH; - gbc.weightx = 1; - gbc.weighty = Integer.MAX_VALUE; - getResultsPanel().add(label, gbc); - getLoadMoreLabel().setText(""); - getLoadMoreLabel().setIcon(null); - remove(getTopLabel()); - } - - public void addData(List projects) { - if (projects == null || projects.isEmpty() && currentLocation == 0) { - showNoMatches(); - } else { - final Point old = getViewport().getViewPosition(); - LOG.info("Adding " + projects.size() + " projects to display."); - for (ProjectEntity project : projects) { - addProjectToDisplay(project); - this.currentLocation++; - } - getResultsPanel().invalidate(); - getResultsPanel().revalidate(); - - // Reset scrollbar position, for some reason it jumps to the last added element - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - old.translate(0, -16); - getViewport().setViewPosition(old); - LOG.info("Paging mechanism is armed"); - armed = true; - } - }); - - if (searchSession != null && searchSession.hasMoreData()) { - getLoadMoreLabel().setText("Querying the cloud for more results..."); - getLoadMoreLabel().setIcon(spinnerIcon); - } else { - getLoadMoreLabel().setText("No more results."); - getLoadMoreLabel().setIcon(null); - } - } - } - +import org.diylc.plugins.cloud.model.CommentEntity; +import org.diylc.plugins.cloud.model.ProjectEntity; +import org.diylc.plugins.cloud.presenter.CloudPresenter; +import org.diylc.plugins.cloud.presenter.SearchSession; +import org.diylc.presenter.Presenter; +import org.diylc.swing.ISimpleView; +import org.diylc.swing.ISwingUI; +import org.diylc.swing.gui.DialogFactory; +import org.diylc.swing.gui.DummyView; +import org.diylc.swing.gui.components.HTMLTextArea; +import org.diylc.swing.gui.editor.PropertyEditorDialog; +import org.diylc.swing.plugins.cloud.view.CommentDialog; +import org.diylc.swing.plugins.cloud.view.UploadDialog; +import org.diylc.swing.plugins.file.FileFilterEnum; +import org.diylc.swingframework.ButtonDialog; +import org.diylc.utils.Pair; + +/** + * Component that is capable of showing a list of {@link ProjectEntity} objects. Can work in paging + * mode and pull one page of data at a time. + * + * @see {@link SearchSession} + * + * @author Branislav Stojkovic + */ +public class ResultsScrollPanel extends JScrollPane { + + private static final long serialVersionUID = 1L; + + private static final Logger LOG = Logger.getLogger(ResultsScrollPanel.class); + + private JPanel resultsPanel; + /** + * This label goes at the end of the page. When it gets rendered we know that we need to request + * another page. + */ + private JLabel loadMoreLabel; + + private JLabel topLabel; + + private ISwingUI mainUI; + private ISimpleView cloudUI; + + private IPlugInPort plugInPort; + + private int currentLocation; + /** + * This flag tells us whether the loadMoreLabel should invoke a new data pull or not. + */ + private boolean armed; + private SearchSession searchSession; + + private Icon spinnerIcon = IconLoader.Spinning.getIcon(); + + private boolean showEditControls; + + public ResultsScrollPanel(ISwingUI mainUI, ISimpleView cloudUI, IPlugInPort plugInPort, + SearchSession searchSession, boolean showEditControls) { + super(); + this.mainUI = mainUI; + this.cloudUI = cloudUI; + this.plugInPort = plugInPort; + this.searchSession = searchSession; + this.showEditControls = showEditControls; + + this.getVerticalScrollBar().setUnitIncrement(16); + this.setBorder(null); + setViewportView(getResultsPanel()); + } + + public void clearPrevious() { + currentLocation = 0; + getResultsPanel().removeAll(); + armed = false; + } + + public void startSearch(List projects) { + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.gridx = 0; + gbc.gridy = 10000; + gbc.fill = GridBagConstraints.BOTH; + gbc.weightx = 100; + gbc.weighty = 100; + gbc.gridwidth = 3; + resultsPanel.add(getLoadMoreLabel(), gbc); + + gbc.gridx = 3; + gbc.gridwidth = 2; + gbc.weightx = 0; + gbc.insets = new Insets(0, 0, 0, 2); + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.LINE_END; + resultsPanel.add(getTopLabel(), gbc); + + addData(projects); + } + + public void showNoMatches() { + JLabel label = new JLabel( + "No projects match the search criteria."); + label.setHorizontalAlignment(SwingConstants.CENTER); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.insets = new Insets(2, 2, 2, 2); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.BOTH; + gbc.weightx = 1; + gbc.weighty = Integer.MAX_VALUE; + getResultsPanel().add(label, gbc); + getLoadMoreLabel().setText(""); + getLoadMoreLabel().setIcon(null); + remove(getTopLabel()); + } + + public void addData(List projects) { + if (projects == null || projects.isEmpty() && currentLocation == 0) { + showNoMatches(); + } else { + final Point old = getViewport().getViewPosition(); + LOG.info("Adding " + projects.size() + " projects to display."); + for (ProjectEntity project : projects) { + addProjectToDisplay(project); + this.currentLocation++; + } + getResultsPanel().invalidate(); + getResultsPanel().revalidate(); + + // Reset scrollbar position, for some reason it jumps to the last added element + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + old.translate(0, -16); + getViewport().setViewPosition(old); + LOG.info("Paging mechanism is armed"); + armed = true; + } + }); + + if (searchSession != null && searchSession.hasMoreData()) { + getLoadMoreLabel().setText("Querying the cloud for more results..."); + getLoadMoreLabel().setIcon(spinnerIcon); + } else { + getLoadMoreLabel().setText("No more results."); + getLoadMoreLabel().setIcon(null); + } + } + } + private JComponent addProjectToDisplay(final ProjectEntity project) { final JLabel thumbnailLabel = new JLabel(loadImage(project.getThumbnailUrl())); final JLabel nameLabel = new JLabel("" + project.getName() + ""); @@ -395,83 +393,74 @@ public class ResultsScrollPanel extends JScrollPane { replaceButton.setFocusable(true); replaceButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); replaceButton.setToolTipText("Replace project with a new version"); - replaceButton.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (cloudUI.showConfirmDialog( - "Are you sure you want to replace the project \"" - + project.getName() - + "\" with a new file?\nThis opperation is irreversible. Once replaced, the old version of the project cannot be restored.", - "Replace Project", IView.YES_NO_OPTION, IView.QUESTION_MESSAGE) == IView.YES_OPTION) { - final Presenter thumbnailPresenter = new Presenter(new DummyView(), InMemoryConfigurationManager.getInstance()); - final File file = - DialogFactory.getInstance().showOpenDialog(FileFilterEnum.DIY.getFilter(), null, - FileFilterEnum.DIY.getExtensions()[0], null, cloudUI.getOwnerFrame()); - if (file != null) { - LOG.info("Preparing replacement for project " + project.getName() + "(" + project.getId() + ")"); - cloudUI.executeBackgroundTask(new ITask() { - - @Override - public String[] doInBackground() throws Exception { - LOG.debug("Uploading from " + file.getAbsolutePath()); - thumbnailPresenter.loadProjectFromFile(file.getAbsolutePath()); - return CloudPresenter.Instance.getCategories(); - } - - @Override - public void complete(final String[] result) { - final UploadDialog dialog = - DialogFactory.getInstance().createUploadDialog(cloudUI.getOwnerFrame(), thumbnailPresenter, result, - true); - dialog.setVisible(true); - if (ButtonDialog.OK.equals(dialog.getSelectedButtonCaption())) { - try { - final File thumbnailFile = File.createTempFile("upload-thumbnail", ".png"); - if (ImageIO.write(dialog.getThumbnail(), "png", thumbnailFile)) { - cloudUI.executeBackgroundTask(new ITask() { - - @Override - public ProjectEntity doInBackground() throws Exception { - CloudPresenter.Instance.uploadProject(dialog.getName(), dialog.getCategory(), dialog - .getDescription(), dialog.getKeywords(), plugInPort.getCurrentVersionNumber().toString(), - thumbnailFile, file, project.getId()); - return CloudPresenter.Instance.fetchUserUploads(project.getId()).get(0); - } - - @Override - public void failed(Exception e) { - cloudUI.showMessage(e.getMessage(), "Upload Error", IView.ERROR_MESSAGE); - } - - @Override - public void complete(ProjectEntity result) { - nameLabel.setText("" + project.getName() + ""); - descriptionArea.setText(result.getDescription()); - categoryLabel.setText("Category: " + result.getCategory() + ""); - updatedLabel.setText("Last updated: " + result.getUpdated() + ""); - thumbnailLabel.setIcon(new ImageIcon(dialog.getThumbnail())); - cloudUI.showMessage("The project has been replaced successfully.", "Upload Success", - IView.INFORMATION_MESSAGE); - } - }); - } else { - cloudUI.showMessage("Could not prepare temporary files to be uploaded to the cloud.", - "Upload Error", IView.ERROR_MESSAGE); - } - } catch (Exception e) { - cloudUI.showMessage(e.getMessage(), "Upload Error", IView.ERROR_MESSAGE); - } - } - } - - @Override - public void failed(Exception e) { - cloudUI.showMessage("Could not open file. " + e.getMessage(), "Error", ISwingUI.ERROR_MESSAGE); - } - }); - } - } - } + replaceButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (cloudUI.showConfirmDialog("Are you sure you want to replace the project \"" + + project.getName() + + "\" with a new file?\nThis opperation is irreversible. Once replaced, the old version of the project cannot be restored.", + "Replace Project", IView.YES_NO_OPTION, IView.QUESTION_MESSAGE) == IView.YES_OPTION) { + final Presenter thumbnailPresenter = + new Presenter(new DummyView(), InMemoryConfigurationManager.getInstance()); + final File file = + DialogFactory.getInstance().showOpenDialog(FileFilterEnum.DIY.getFilter(), null, + FileFilterEnum.DIY.getExtensions()[0], null, cloudUI.getOwnerFrame()); + if (file != null) { + LOG.info("Preparing replacement for project " + project.getName() + "(" + + project.getId() + ")"); + cloudUI.executeBackgroundTask(new ITask>() { + + @Override + public Pair doInBackground() throws Exception { + LOG.debug("Uploading from " + file.getAbsolutePath()); + thumbnailPresenter.loadProjectFromFile(file.getAbsolutePath()); + final UploadDialog dialog = DialogFactory.getInstance().createUploadDialog( + cloudUI.getOwnerFrame(), thumbnailPresenter, new String[0], true); + final File thumbnailFile = File.createTempFile("upload-thumbnail", ".png"); + if (ImageIO.write(dialog.getThumbnail(), "png", thumbnailFile)) { + CloudPresenter.Instance.replaceProjectFile( + plugInPort.getCurrentVersionNumber().toString(), thumbnailFile, file, + project.getId()); + return new Pair(dialog.getThumbnail(), + CloudPresenter.Instance.fetchUserUploads(project.getId()).get(0)); + } else { + cloudUI.showMessage( + "Could not prepare temporary files to be uploaded to the cloud.", + "Upload Error", IView.ERROR_MESSAGE); + return null; + } + } + + @Override + public void complete(final Pair result) { + if (result != null) { + BufferedImage thumbnail = result.getFirst(); + ProjectEntity project = result.getSecond(); + nameLabel.setText("" + project.getName() + ""); + descriptionArea.setText(project.getDescription()); + categoryLabel + .setText("Category: " + project.getCategory() + ""); + updatedLabel + .setText("Last updated: " + project.getUpdated() + ""); + thumbnailLabel.setIcon(new ImageIcon(thumbnail)); + cloudUI.showMessage("The project has been replaced successfully.", + "Upload Success", IView.INFORMATION_MESSAGE); + } else { + cloudUI.showMessage("Unexpected error occurred while replacing the project.", + "Upload Error", IView.ERROR_MESSAGE); + } + } + + public void failed(Exception e) { + cloudUI.showMessage( + "Could not update the project. Detailed message is in the logs.", "Error", + ISwingUI.ERROR_MESSAGE); + LOG.error("Error replacing project files", e); + } + }); + } + } + } }); final JLabel deleteButton = new JLabel(IconLoader.CloudDelete.getIcon()); @@ -602,77 +591,78 @@ public class ResultsScrollPanel extends JScrollPane { getResultsPanel().add(separator, gbc); return nameLabel; - } - - public JLabel getTopLabel() { - if (topLabel == null) { - topLabel = new JLabel("To the top"); - topLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - topLabel.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - getViewport().setViewPosition(new Point(0, 0)); - } - }); - } - return topLabel; - } - - private JLabel getLoadMoreLabel() { - if (loadMoreLabel == null) { - loadMoreLabel = new JLabel("Loading more data...") { - - private static final long serialVersionUID = 1L; - - @Override - public void paint(Graphics g) { - super.paint(g); - if (armed && searchSession != null && searchSession.hasMoreData()) { - // disarm immediately so we don't trigger successive requests to the provider - LOG.info("Paging mechanism is disarmed"); - armed = false; - SwingWorker, Void> worker = new SwingWorker, Void>() { - - @Override - protected List doInBackground() throws Exception { - return searchSession.requestMoreData(); - } - - @Override - protected void done() { - try { - List newResults = get(); - addData(newResults); - } catch (Exception e) { - cloudUI.showMessage("Search failed! Detailed message is in the logs.", "Search Failed", - IView.ERROR_MESSAGE); - } - } - }; - worker.execute(); - } - } - }; - loadMoreLabel.setHorizontalAlignment(SwingConstants.CENTER); - loadMoreLabel.setFont(loadMoreLabel.getFont().deriveFont(10f)); - } - return loadMoreLabel; - } - - private JPanel getResultsPanel() { - if (resultsPanel == null) { - resultsPanel = new JPanel(new GridBagLayout()); - resultsPanel.setBackground(Color.white); - } - return resultsPanel; - } - - private Icon loadImage(String imageFile) { - try { - BufferedImage img = ImageIO.read(new File(imageFile)); - return new ImageIcon(img); - } catch (Exception e) { - return IconLoader.MissingImage.getIcon(); - } - } -} + } + + public JLabel getTopLabel() { + if (topLabel == null) { + topLabel = new JLabel("To the top"); + topLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + topLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + getViewport().setViewPosition(new Point(0, 0)); + } + }); + } + return topLabel; + } + + private JLabel getLoadMoreLabel() { + if (loadMoreLabel == null) { + loadMoreLabel = new JLabel("Loading more data...") { + + private static final long serialVersionUID = 1L; + + @Override + public void paint(Graphics g) { + super.paint(g); + if (armed && searchSession != null && searchSession.hasMoreData()) { + // disarm immediately so we don't trigger successive requests to the provider + LOG.info("Paging mechanism is disarmed"); + armed = false; + SwingWorker, Void> worker = + new SwingWorker, Void>() { + + @Override + protected List doInBackground() throws Exception { + return searchSession.requestMoreData(); + } + + @Override + protected void done() { + try { + List newResults = get(); + addData(newResults); + } catch (Exception e) { + cloudUI.showMessage("Search failed! Detailed message is in the logs.", + "Search Failed", IView.ERROR_MESSAGE); + } + } + }; + worker.execute(); + } + } + }; + loadMoreLabel.setHorizontalAlignment(SwingConstants.CENTER); + loadMoreLabel.setFont(loadMoreLabel.getFont().deriveFont(10f)); + } + return loadMoreLabel; + } + + private JPanel getResultsPanel() { + if (resultsPanel == null) { + resultsPanel = new JPanel(new GridBagLayout()); + resultsPanel.setBackground(Color.white); + } + return resultsPanel; + } + + private Icon loadImage(String imageFile) { + try { + BufferedImage img = ImageIO.read(new File(imageFile)); + return new ImageIcon(img); + } catch (Exception e) { + return IconLoader.MissingImage.getIcon(); + } + } +}