Author: paperwing
Date: 2012-05-22 14:00:52 -0700 (Tue, 22 May 2012)
New Revision: 29318
Modified:
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/pom.xml
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/manager/App.java
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/manager/AppManager.java
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/net/WebQuerier.java
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/ui/CurrentlyInstalledAppsPanel.java
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/ui/InstallFromStorePanel.java
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/ui/InstallFromStorePanelOld.java
Log:
Updated pom file to remove dynamic import as was done recently with old app
manager, now able to download and install apps from app store using the app
listing interface, added method to resolve filename collisions when copying
files to storage directories
Modified: csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/pom.xml
===================================================================
--- csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/pom.xml
2012-05-22 19:52:23 UTC (rev 29317)
+++ csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/pom.xml
2012-05-22 21:00:52 UTC (rev 29318)
@@ -35,14 +35,6 @@
</resources>
<plugins>
<plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
-
<version>${maven-surefire-plugin.version}</version>
- <configuration>
-
<redirectTestOutputToFile>true</redirectTestOutputToFile>
- </configuration>
- </plugin>
- <plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${maven-bundle-plugin.version}</version>
@@ -54,10 +46,6 @@
<Export-Package>!${bundle.namespace}.*</Export-Package>
<Private-Package>${bundle.namespace}.*</Private-Package>
<Bundle-Activator>${bundle.namespace}.CyActivator</Bundle-Activator>
- <!-- Dynamic import is
necessary, because it allows apps to
- access packages that
aren't imported as because of the code
- in this bundle. -->
-
<DynamicImport-Package>*</DynamicImport-Package>
</instructions>
</configuration>
</plugin>
Modified:
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/manager/App.java
===================================================================
---
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/manager/App.java
2012-05-22 19:52:23 UTC (rev 29317)
+++
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/manager/App.java
2012-05-22 21:00:52 UTC (rev 29318)
@@ -1,8 +1,12 @@
package org.cytoscape.app.internal.manager;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.IOException;
import java.net.URL;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.cytoscape.app.AbstractCyApp;
@@ -154,20 +158,71 @@
try {
File appFile = this.getAppFile();
+ // Make sure no app with the same filename and app name
is already installed
+ File installedDirectoryTargetFile = new
File(installedAppsPath + File.separator + appFile.getName());
+ File uninstalledDirectoryTargetFile = new
File(uninstalledAppsPath + File.separator + appFile.getName());
+
+ String copyDestinationFileName = appFile.getName();
+
+ // Check for filename collisions in both the installed
apps directory as well as the
+ // uninstalled apps directory
+ if (installedDirectoryTargetFile.exists() ||
uninstalledDirectoryTargetFile.exists()) {
+ Set<App> registeredApps = appManager.getApps();
+
+ // The app registered to the app manager that
happens to have the same filename
+ App conflictingApp = null;
+
+ for (App registeredApp : registeredApps) {
+ if
(registeredApp.getAppFile().getName().equalsIgnoreCase(appFile.getName())) {
+ conflictingApp = registeredApp;
+ }
+ }
+
+ // Only prevent the overwrite if the filename
conflict is with an app registered
+ // to the app manager
+ if (conflictingApp != null) {
+
+ // Check if the apps have the same name
+ if
(this.getAppName().equalsIgnoreCase(conflictingApp.getAppName())) {
+
+ // Same filename, same app name
found
+ // return;
+
+ Collection<String>
directoryPaths = new LinkedList<String>();
+
directoryPaths.add(installedAppsPath);
+
directoryPaths.add(uninstalledAppsPath);
+
+ copyDestinationFileName =
suggestFileName(directoryPaths, appFile.getName());
+
+ } else {
+
+ // Same filename, different app
name found
+ // Rename file
+ Collection<String>
directoryPaths = new LinkedList<String>();
+
directoryPaths.add(installedAppsPath);
+
directoryPaths.add(uninstalledAppsPath);
+
+ copyDestinationFileName =
suggestFileName(directoryPaths, appFile.getName());
+ }
+
+ }
+ }
+
// Only perform the copy if the app was not already in
the target directory
if
(!appFile.getParentFile().getCanonicalPath().equals(installedAppsPath)) {
// Uses Apache Commons library; overwrites
files with the same name.
- FileUtils.copyFileToDirectory(appFile, new
File(installedAppsPath));
+ // FileUtils.copyFileToDirectory(appFile, new
File(installedAppsPath));
+ FileUtils.copyFile(appFile, new
File(installedAppsPath + File.separator + copyDestinationFileName));
+
// If we copied it from the uninstalled apps
directory, remove it from that directory
if
(appFile.getParentFile().getCanonicalPath().equals(uninstalledAppsPath)) {
appFile.delete();
}
// Update the app's path
- String fileName = this.getAppFile().getName();
- this.setAppFile(new File(installedAppsPath +
File.separator + fileName));
+ this.setAppFile(new File(installedAppsPath +
File.separator + copyDestinationFileName));
}
} catch (IOException e) {
throw new AppInstallException("Unable to copy app file
to installed apps directory: " + e.getMessage());
@@ -191,6 +246,59 @@
}
/**
+ * Given a set of canonical directory paths, find a name for a given
file that does not
+ * collide with names of files in any of the given directories.
+ *
+ * For example, if the name file.txt is taken, this method will return
file-2.txt. If the
+ * latter is taken, it will return file-3.txt, and so on.
+ *
+ * @param directoryPaths A collection of canonical directory paths used
to check for files
+ * that have colliding names
+ * @param desiredFileName The desired name for the given file, used as
a base to which the
+ * number tag is added.
+ * @return A new name of the file that does not collide with any
non-directory file in the given
+ * paths. If the given filename had no collisions, then an identical
filename is returned.
+ */
+ private String suggestFileName(Collection<String> directoryPaths,
String desiredFileName) {
+
+ int postfixNumber = 1;
+ boolean nameCollision = false;
+ File file;
+
+ for (String directoryPath : directoryPaths) {
+ file = new File(directoryPath + File.separator +
desiredFileName);
+
+ nameCollision = nameCollision || (file.exists() &&
!file.isDirectory());
+ }
+
+ String fileBaseName = desiredFileName;
+ String fileFullExtension = "";
+ int lastPeriodIndex = desiredFileName.lastIndexOf(".");
+
+ if (lastPeriodIndex != -1) {
+ fileBaseName = desiredFileName.substring(0,
lastPeriodIndex);
+ fileFullExtension =
desiredFileName.substring(lastPeriodIndex, desiredFileName.length());
+ }
+
+ String newFileName = desiredFileName;
+
+ while(nameCollision) {
+ postfixNumber++;
+ nameCollision = false;
+
+ for (String directoryPath : directoryPaths) {
+ // If the old name is basename.extension, then
the new name is basename-postfixNumber.extension
+ newFileName = fileBaseName + "-" +
postfixNumber + fileFullExtension;
+ file = new File(directoryPath + File.separator
+ newFileName);
+
+ nameCollision = nameCollision || (file.exists()
&& !file.isDirectory());
+ }
+ }
+
+ return newFileName;
+ }
+
+ /**
* Default app uninstallation method that can be used by classes
extending this class.
*
* The default app uninstallation procedure consists of simply moving
the app to the uninstalled apps
Modified:
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/manager/AppManager.java
===================================================================
---
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/manager/AppManager.java
2012-05-22 19:52:23 UTC (rev 29317)
+++
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/manager/AppManager.java
2012-05-22 21:00:52 UTC (rev 29318)
@@ -107,6 +107,14 @@
*/
public void addApp(App app) {
apps.add(app);
+
+ /*
+ // Let the listeners know that an app has changed
+ for (AppsChangedListener appListener : appListeners) {
+ AppsChangedEvent appEvent = new AppsChangedEvent(this);
+ appListener.appsChanged(appEvent);
+ }
+ */
}
/**
@@ -126,17 +134,12 @@
* Apps that have not been validated are ignored. Also, apps that are
already installed are left alone.
*
* @param app The {@link App} object representing and providing
information about the app to install
- * @throws AppMoveException If there was an IO-related error during the
copy operation that prevents the app from
- * being successfully installed.
+ * @throws AppInstallException If there was an error while attempting
to install the app such as being
+ * unable to copy the app to the installed apps directory or to
instance the app's entry point class
*/
- public void installApp(App app) {
+ public void installApp(App app) throws AppInstallException {
- try {
- app.install(this);
- } catch (AppInstallException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
+ app.install(this);
// Let the listeners know that an app has been installed
for (AppsChangedListener appListener : appListeners) {
@@ -152,17 +155,13 @@
* The app will only be uninstalled if it is currently installed.
*
* @param app The app to be uninstalled.
- * @throws AppMoveException If there was an error while moving the app
from the installed apps subdirectory
- * to the subdirectory containing currently uninstalled apps.
+ * @throws AppUninstallException If there was an error while attempting
to uninstall the app such as
+ * attempting to uninstall an app that isn't installed, or being unable
to move the app to the uninstalled
+ * apps directory
*/
- public void uninstallApp(App app) {
+ public void uninstallApp(App app) throws AppUninstallException {
- try {
- app.uninstall(this);
- } catch (AppUninstallException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
+ app.uninstall(this);
// Let the listeners know that an app has been uninstalled
for (AppsChangedListener appListener : appListeners) {
@@ -247,7 +246,11 @@
// Install each app
for (App parsedApp : parsedApps) {
- installApp(parsedApp);
+ try {
+ installApp(parsedApp);
+ } catch (AppInstallException e) {
+ System.out.println("Unable to install app: " +
e.getMessage());
+ }
}
System.out.println("Number of apps installed from directory: "
+ parsedApps.size());
Modified:
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/net/WebQuerier.java
===================================================================
---
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/net/WebQuerier.java
2012-05-22 19:52:23 UTC (rev 29317)
+++
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/net/WebQuerier.java
2012-05-22 21:00:52 UTC (rev 29318)
@@ -271,7 +271,7 @@
*
* @param appName The unique app name used by the app store
*/
- public void downloadApp(String appName, File directory) throws
AppDownloadException {
+ public File downloadApp(String appName, File directory) throws
AppDownloadException {
Set<WebApp> apps = getAllApps();
boolean appFound = false;
@@ -295,27 +295,40 @@
System.out.println("Releases for " + appName +
": " + releases.length());
+ String latestReleaseUrl = null;
+ String latestReleaseDate = null;
+ String releaseDate;
+
for (int index = 0; index < releases.length();
index++) {
JSONObject release =
releases.getJSONObject(index);
+
+ releaseDate =
release.getString("created_iso");
+ if (latestReleaseDate == null ||
releaseDate.compareToIgnoreCase(releaseDate) >= 0) {
+ latestReleaseUrl =
APP_STORE_URL + release.getString("release_file_url");
+ }
}
- String url =
"http://apps.cytoscape.org/media/releases/CyTestSimpleApp1.jar";
+ // String url =
"http://apps.cytoscape.org/media/releases/CyTestSimpleApp1.jar";
- URL downloadUrl = new URL(url);
-
- ReadableByteChannel readableByteChannel =
Channels.newChannel(downloadUrl.openStream());
-
- File outputFile = new
File(directory.getCanonicalPath() + File.separator + "CyTestSimpleApp1d.jar");
-
- if (outputFile.exists()) {
- outputFile.delete();
+ if (latestReleaseUrl != null) {
+ URL downloadUrl = new
URL(latestReleaseUrl);
+
+ ReadableByteChannel readableByteChannel
= Channels.newChannel(downloadUrl.openStream());
+
+ File outputFile = new
File(directory.getCanonicalPath() + File.separator + appName + ".jar");
+
+ if (outputFile.exists()) {
+ outputFile.delete();
+ }
+
+ outputFile.createNewFile();
+
+ FileOutputStream fileOutputStream = new
FileOutputStream(outputFile);
+
fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, 1 << 24);
+
+ return outputFile;
}
-
- outputFile.createNewFile();
-
- FileOutputStream fileOutputStream = new
FileOutputStream(outputFile);
-
fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, 1 << 24);
-
+
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -327,6 +340,8 @@
} else {
System.out.println("No app with name " + appName + "
found.");
}
+
+ return null;
}
public Set<WebApp> getAppsByTag(String tagName) {
Modified:
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/ui/CurrentlyInstalledAppsPanel.java
===================================================================
---
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/ui/CurrentlyInstalledAppsPanel.java
2012-05-22 19:52:23 UTC (rev 29317)
+++
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/ui/CurrentlyInstalledAppsPanel.java
2012-05-22 21:00:52 UTC (rev 29318)
@@ -9,6 +9,8 @@
import org.cytoscape.app.internal.event.AppsChangedEvent;
import org.cytoscape.app.internal.event.AppsChangedListener;
+import org.cytoscape.app.internal.exception.AppInstallException;
+import org.cytoscape.app.internal.exception.AppUninstallException;
import org.cytoscape.app.internal.manager.App;
import org.cytoscape.app.internal.manager.App.AppStatus;
import org.cytoscape.app.internal.manager.AppManager;
@@ -146,7 +148,12 @@
for (App app : selectedApps) {
// Only install apps that are not already installed
if (app.getStatus() != AppStatus.INSTALLED) {
- appManager.installApp(app);
+ try {
+ appManager.installApp(app);
+ } catch (AppInstallException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
}
}
@@ -161,7 +168,12 @@
for (App app : selectedApps) {
// Only uninstall apps that are installed
if (app.getStatus() == AppStatus.INSTALLED) {
- appManager.uninstallApp(app);
+ try {
+ appManager.uninstallApp(app);
+ } catch (AppUninstallException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
}
}
Modified:
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/ui/InstallFromStorePanel.java
===================================================================
---
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/ui/InstallFromStorePanel.java
2012-05-22 19:52:23 UTC (rev 29317)
+++
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/ui/InstallFromStorePanel.java
2012-05-22 21:00:52 UTC (rev 29318)
@@ -37,6 +37,7 @@
import javax.swing.tree.TreePath;
import org.cytoscape.app.internal.exception.AppDownloadException;
+import org.cytoscape.app.internal.exception.AppInstallException;
import org.cytoscape.app.internal.exception.AppParsingException;
import org.cytoscape.app.internal.manager.App;
import org.cytoscape.app.internal.manager.AppManager;
@@ -283,7 +284,12 @@
// Install the app if parsing was
successful
if (app != null) {
- appManager.installApp(app);
+ try {
+
appManager.installApp(app);
+ } catch (AppInstallException e)
{
+
JOptionPane.showMessageDialog(parent, "Error installing app: " + e.getMessage(),
+ "Error",
JOptionPane.ERROR_MESSAGE);
+ }
}
}
}
@@ -347,13 +353,28 @@
for (WebApp webApp : selectedApps) {
try {
System.out.println("Download path: " +
appManager.getDownloadedAppsPath());
- webQuerier.downloadApp(webApp.getName(), new
File(appManager.getDownloadedAppsPath()));
+
+ // Download app
+ File appFile = webQuerier.downloadApp(webApp.getName(),
new File(appManager.getDownloadedAppsPath()));
+
+ // Parse app
+ App parsedApp =
appManager.getAppParser().parseApp(appFile);
+
+ // Install app
+ appManager.installApp(parsedApp);
+
} catch (AppDownloadException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ JOptionPane.showMessageDialog(parent, "Error
downloading app: " + e.getMessage(),
+ "Error", JOptionPane.ERROR_MESSAGE);
+ } catch (AppParsingException e) {
+ JOptionPane.showMessageDialog(parent, "Error
parsing app: " + e.getMessage(),
+ "Error", JOptionPane.ERROR_MESSAGE);
+ } catch (AppInstallException e) {
+ JOptionPane.showMessageDialog(parent, "Error
installing app: " + e.getMessage(),
+ "Error", JOptionPane.ERROR_MESSAGE);
}
}
- }
+ }
private void resetButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
Modified:
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/ui/InstallFromStorePanelOld.java
===================================================================
---
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/ui/InstallFromStorePanelOld.java
2012-05-22 19:52:23 UTC (rev 29317)
+++
csplugins/trunk/toronto/yuedong/app_manager/impl/app-impl/src/main/java/org/cytoscape/app/internal/ui/InstallFromStorePanelOld.java
2012-05-22 21:00:52 UTC (rev 29318)
@@ -11,6 +11,8 @@
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.DefaultTableModel;
+
+import org.cytoscape.app.internal.exception.AppInstallException;
import org.cytoscape.app.internal.exception.AppParsingException;
import org.cytoscape.app.internal.manager.App;
import org.cytoscape.app.internal.manager.AppManager;
@@ -235,7 +237,12 @@
// Install the app if parsing was
successful
if (app != null) {
- appManager.installApp(app);
+ try {
+
appManager.installApp(app);
+ } catch (AppInstallException e)
{
+
JOptionPane.showMessageDialog(this, "Error installing app: " + e.getMessage(),
+ "Error",
JOptionPane.ERROR_MESSAGE);
+ }
}
}
}
--
You received this message because you are subscribed to the Google Groups
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/cytoscape-cvs?hl=en.