You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/02/23 11:06:22 UTC
[2/5] incubator-taverna-osgi git commit: Revert "temporarily empty
repository"
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-osgi-schemas/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-osgi-schemas/pom.xml b/taverna-osgi-schemas/pom.xml
new file mode 100644
index 0000000..853ff16
--- /dev/null
+++ b/taverna-osgi-schemas/pom.xml
@@ -0,0 +1,27 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.osgi</groupId>
+ <artifactId>taverna-osgi</artifactId>
+ <version>0.2.0-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>taverna-osgi-schemas</artifactId>
+ <name>Apache Taverna OSGi XML Schemas</name>
+ <packaging>bundle</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.jvnet.jaxb2.maven2</groupId>
+ <artifactId>maven-jaxb2-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-osgi-schemas/src/main/resources/ApplicationPlugin.xsd
----------------------------------------------------------------------
diff --git a/taverna-osgi-schemas/src/main/resources/ApplicationPlugin.xsd b/taverna-osgi-schemas/src/main/resources/ApplicationPlugin.xsd
new file mode 100644
index 0000000..180c8c2
--- /dev/null
+++ b/taverna-osgi-schemas/src/main/resources/ApplicationPlugin.xsd
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<xs:schema xmlns="http://ns.taverna.org.uk/2013/application/plugin"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:versions="http://ns.taverna.org.uk/2013/application/versions"
+ xmlns:ap="http://ns.taverna.org.uk/2013/application/profile"
+ xmlns:plugin="http://ns.taverna.org.uk/2013/application/plugin"
+ xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="1.0"
+ targetNamespace="http://ns.taverna.org.uk/2013/application/plugin"
+ elementFormDefault="qualified">
+
+ <xs:annotation>
+ <xs:appinfo>
+ <jxb:schemaBindings>
+ <jxb:package name="uk.org.taverna.commons.plugin.xml.jaxb" />
+ </jxb:schemaBindings>
+ </xs:appinfo>
+ </xs:annotation>
+
+ <xs:import namespace="http://ns.taverna.org.uk/2013/application/versions"
+ schemaLocation="ApplicationVersions.xsd" />
+
+ <xs:import namespace="http://ns.taverna.org.uk/2013/application/profile"
+ schemaLocation="ApplicationProfile.xsd" />
+
+ <xs:element name="pluginInfo">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" />
+ <xs:element name="name" type="xs:string" />
+ <xs:element name="description" type="xs:string" />
+ <xs:element name="organization" type="xs:string" />
+ <xs:element name="version" type="versions:semanticVersion" />
+ <xs:element name="bundle" type="ap:bundleInfo" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="pluginVersions">
+ <xs:complexContent>
+ <xs:extension base="versions:versions">
+ <xs:sequence>
+ <xs:element name="organization" type="xs:string" />
+ <xs:element name="pluginSiteUrl" type="xs:string" minOccurs="0" />
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:element name="plugins">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="plugin" type="pluginVersions"
+ minOccurs="1" maxOccurs="unbounded">
+ <xs:unique name="versionUnique">
+ <xs:selector
+ xpath="versions:previousVersion/versions:version|versions:latestVersion/versions:version" />
+ <xs:field xpath="." />
+ </xs:unique>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:unique name="versionsIdUnique">
+ <xs:selector xpath="plugin:versions/versions:id" />
+ <xs:field xpath="." />
+ </xs:unique>
+ </xs:element>
+
+</xs:schema>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-osgi-schemas/src/main/resources/ApplicationProfile.xsd
----------------------------------------------------------------------
diff --git a/taverna-osgi-schemas/src/main/resources/ApplicationProfile.xsd b/taverna-osgi-schemas/src/main/resources/ApplicationProfile.xsd
new file mode 100644
index 0000000..78073a2
--- /dev/null
+++ b/taverna-osgi-schemas/src/main/resources/ApplicationProfile.xsd
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<xs:schema xmlns="http://ns.taverna.org.uk/2013/application/profile"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:versions="http://ns.taverna.org.uk/2013/application/versions"
+ xmlns:ap="http://ns.taverna.org.uk/2013/application/profile" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
+ jxb:version="1.0" targetNamespace="http://ns.taverna.org.uk/2013/application/profile"
+ elementFormDefault="qualified">
+
+ <xs:annotation>
+ <xs:appinfo>
+ <jxb:schemaBindings>
+ <jxb:package name="uk.org.taverna.commons.profile.xml.jaxb" />
+ </jxb:schemaBindings>
+ </xs:appinfo>
+ </xs:annotation>
+
+ <xs:import namespace="http://ns.taverna.org.uk/2013/application/versions"
+ schemaLocation="ApplicationVersions.xsd" />
+
+ <xs:complexType name="frameworkConfiguration">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ <xs:attribute name="value" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="bundleInfo">
+ <xs:sequence>
+ <xs:element name="fileName" type="xs:anyURI" minOccurs="0" />
+ </xs:sequence>
+ <xs:attribute name="symbolicName" type="xs:string" use="required" />
+ <xs:attribute name="version" type="versions:semanticVersion"
+ use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="updates">
+ <xs:sequence>
+ <xs:element name="updateSite" type="xs:anyURI" />
+ <xs:element name="updatesFile" type="xs:string" />
+ <xs:element name="libDirectory" type="xs:string" />
+ <xs:element name="pluginSite" type="xs:string" />
+ <xs:element name="pluginsFile" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name="applicationProfile">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" />
+ <xs:element name="name" type="xs:string" />
+ <xs:element name="version" type="versions:semanticVersion" />
+ <xs:element name="updates" type="updates" />
+ <xs:element name="frameworkConfiguration" type="frameworkConfiguration"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="bundle" type="bundleInfo" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:unique name="symbolicNameUnique">
+ <xs:selector xpath="ap:bundles/ap:bundle"></xs:selector>
+ <xs:field xpath="@symbolicName"></xs:field>
+ </xs:unique>
+ </xs:element>
+
+ <xs:element name="updateSite">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="versions" type="versions:versions">
+ <xs:unique name="versionUnique">
+ <xs:selector
+ xpath="versions:previousVersion/versions:version|versions:latestVersion/versions:version" />
+ <xs:field xpath="." />
+ </xs:unique>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-osgi-schemas/src/main/resources/ApplicationVersions.xsd
----------------------------------------------------------------------
diff --git a/taverna-osgi-schemas/src/main/resources/ApplicationVersions.xsd b/taverna-osgi-schemas/src/main/resources/ApplicationVersions.xsd
new file mode 100644
index 0000000..706423c
--- /dev/null
+++ b/taverna-osgi-schemas/src/main/resources/ApplicationVersions.xsd
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<xs:schema xmlns="http://ns.taverna.org.uk/2013/application/versions"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:versions="http://ns.taverna.org.uk/2013/application/versions"
+ xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="1.0"
+ targetNamespace="http://ns.taverna.org.uk/2013/application/versions"
+ elementFormDefault="qualified">
+
+ <xs:annotation>
+ <xs:appinfo>
+ <jxb:schemaBindings>
+ <jxb:package name="uk.org.taverna.commons.versions.xml.jaxb" />
+ </jxb:schemaBindings>
+ </xs:appinfo>
+ </xs:annotation>
+
+ <xs:simpleType name="semanticVersion">
+ <xs:annotation>
+ <xs:documentation>A semantic version.</xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9]+\.[0-9]+(\.[0-9]+(\.[0-9A-Za-z_-]+)?)?" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="version">
+ <xs:sequence>
+ <xs:element name="version" type="semanticVersion" />
+ <xs:element name="file" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="versions">
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" />
+ <xs:element name="name" type="xs:string" />
+ <xs:element name="description" type="xs:string" />
+ <xs:element name="latestVersion" type="version" minOccurs="1"
+ maxOccurs="1" />
+ <xs:element name="previousVersion" type="version"
+ minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+</xs:schema>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-api/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-plugin-api/pom.xml b/taverna-plugin-api/pom.xml
new file mode 100644
index 0000000..1e7ed02
--- /dev/null
+++ b/taverna-plugin-api/pom.xml
@@ -0,0 +1,29 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.osgi</groupId>
+ <artifactId>taverna-osgi</artifactId>
+ <version>0.2.0-incubating-SNAPSHOT</version>
+ </parent>
+ <packaging>bundle</packaging>
+ <artifactId>taverna-plugin-api</artifactId>
+ <name>Apache Taverna Plugin API</name>
+ <dependencies>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-app-configuration-api</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-osgi-schemas</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>${osgi.core.version}</version>
+ </dependency>
+ </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/Plugin.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/Plugin.java b/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/Plugin.java
new file mode 100644
index 0000000..e9ea0a4
--- /dev/null
+++ b/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/Plugin.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.plugin;
+
+import java.io.File;
+import java.util.Set;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+
+/**
+ * A plugin adds functionality to the application by providing implementations of application
+ * services.
+ *
+ * @author David Withers
+ */
+public interface Plugin {
+
+ public static enum State {
+ UNINSTALLED, INSTALLED, STARTED, STOPPED
+ }
+
+ public String getId();
+
+ public String getName();
+
+ public String getDescription();
+
+ public String getOrganization();
+
+ public Version getVersion();
+
+ /**
+ * Returns the state of the plugin.
+ *
+ * @return the state of the plugin
+ */
+ public State getState();
+
+ /**
+ * Starts the plugin and sets the state to STARTED.
+ * <p>
+ * If the plugin state is STARTED this method will have no effect.
+ * <p>
+ * All plugin bundles are not currently started will be started.
+ *
+ * @throws PluginException
+ * if the plugin state is UNINSTALLED or any of the plugin bundles cannot be started
+ */
+ public void start() throws PluginException;
+
+ /**
+ * Stops the plugin and sets the state to STOPPED.
+ * <p>
+ * If the plugin state is not STARTED this method will have no effect.
+ * <p>
+ * All plugin bundles not used elsewhere will be stopped.
+ *
+ * @throws PluginException
+ * if any of the plugin bundles cannot be stopped
+ */
+ public void stop() throws PluginException;
+
+ public void uninstall() throws PluginException;
+
+ public File getFile();
+
+ public Set<Bundle> getBundles();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginException.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginException.java b/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginException.java
new file mode 100644
index 0000000..6bc3fe0
--- /dev/null
+++ b/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginException.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.plugin;
+
+/**
+ *
+ *
+ * @author David Withers
+ */
+public class PluginException extends Exception {
+
+ public PluginException() {
+ }
+
+ public PluginException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public PluginException(String message) {
+ super(message);
+ }
+
+ public PluginException(Throwable cause) {
+ super(cause);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginManager.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginManager.java b/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginManager.java
new file mode 100644
index 0000000..e9b2f83
--- /dev/null
+++ b/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginManager.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.plugin;
+
+import java.io.File;
+import java.util.List;
+
+import uk.org.taverna.commons.plugin.xml.jaxb.PluginVersions;
+
+/**
+ * Manages installing plugins and checking for plugin updates.
+ *
+ * @author David Withers
+ */
+public interface PluginManager {
+
+ public static final String EVENT_TOPIC_ROOT = "uk/org/taverna/commons/plugin/PluginManager/";
+ public static final String PLUGIN_INSTALLED = EVENT_TOPIC_ROOT + "PLUGIN_INSTALLED";
+ public static final String PLUGIN_UNINSTALLED = EVENT_TOPIC_ROOT + "PLUGIN_UNINSTALLED";
+ public static final String UPDATES_AVAILABLE = EVENT_TOPIC_ROOT + "UPDATES_AVAILABLE";
+
+ /**
+ * Loads plugins from the system and user plugin directories.
+ * <p>
+ * If the plugins are not already installed they will be installed and started.
+ *
+ * @throws PluginException
+ */
+ public void loadPlugins() throws PluginException;
+
+ /**
+ * Check if there are new versions of installed plugins available.
+ * <p>
+ * If updates are available and event with topic {@link UPDATES_AVAILABLE} will be posted.
+ *
+ * @throws PluginException
+ */
+ public void checkForUpdates() throws PluginException;
+
+ /**
+ * Returns updated versions of installed plugins.
+ * <p>
+ * Only plugins that the user has permission to update are returned.
+ *
+ * @return
+ */
+ public List<PluginVersions> getPluginUpdates() throws PluginException;
+
+ /**
+ * Returns new plugins available from all plugin sites.
+ *
+ * @return new plugins available from all plugin sites.
+ * @throws PluginException
+ */
+ public List<PluginVersions> getAvailablePlugins() throws PluginException;
+
+ /**
+ * Returns all the installed plugins.
+ *
+ * @return
+ * @throws PluginException
+ */
+ public List<Plugin> getInstalledPlugins() throws PluginException;
+
+ /**
+ * Installs a plugin from a plugin file.
+ *
+ * @param pluginFile
+ * the file to install the plugin from
+ * @return the installed plugin
+ * @throws PluginException
+ */
+ public Plugin installPlugin(File pluginFile) throws PluginException;
+
+ /**
+ * Installs a plugin from an update site.
+ *
+ * @param pluginSiteURL
+ * @param pluginFile
+ * @return
+ * @throws PluginException
+ */
+ public Plugin installPlugin(String pluginSiteURL, String pluginFile) throws PluginException;
+
+ public Plugin updatePlugin(PluginVersions pluginVersions) throws PluginException;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginSite.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginSite.java b/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginSite.java
new file mode 100644
index 0000000..54f8e3b
--- /dev/null
+++ b/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginSite.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.plugin;
+
+/**
+ * A plugin site specifies the location of a site that contains plugins.
+ * <p>
+ * There are two types of plugin site:
+ * <dl>
+ * <dt>SYSTEM</dt>
+ * <dd>plugin sites specified by the application profile</dd>
+ * <dt>USER</dt>
+ * <dd>plugin sites that can be added and removed by the user</dd>
+ * </dl>
+ *
+ * @author David Withers
+ */
+public interface PluginSite {
+
+ public static enum PluginSiteType {
+ SYSTEM, USER
+ };
+
+ /**
+ * Returns the name of the plugin site.
+ *
+ * @return the name of the plugin site
+ */
+ public String getName();
+
+ /**
+ * Returns the URL of the plugin site.
+ *
+ * @return the URL of the plugin site
+ */
+ public String getUrl();
+
+ /**
+ * Returns the type of the plugin site.
+ * <p>
+ * The type is either {@code SYSTEM} or {@code USER}
+ *
+ * @return the type of the plugin site
+ */
+ public PluginSiteType getType();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginSiteManager.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginSiteManager.java b/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginSiteManager.java
new file mode 100644
index 0000000..8cd32b5
--- /dev/null
+++ b/taverna-plugin-api/src/main/java/uk/org/taverna/commons/plugin/PluginSiteManager.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.plugin;
+
+import java.net.URL;
+import java.util.List;
+
+import uk.org.taverna.commons.plugin.xml.jaxb.PluginVersions;
+
+/**
+ * Manages plugin sites.
+ *
+ * @author David Withers
+ */
+public interface PluginSiteManager {
+
+ /**
+ * Returns all the managed plugin sites.
+ * <p>
+ * If there are no plugin sites an empty list is returned.
+ *
+ * @return all the managed plugin sites
+ * @throws PluginException
+ */
+ public List<PluginSite> getPluginSites();
+
+ /**
+ * Contacts the plugin site at the specified URL and return a new plugin site.
+ *
+ * @param pluginSiteURL the plugin site URL
+ * @throws PluginException if there is a problem contacting the plugin site
+ */
+ public PluginSite createPluginSite(URL pluginSiteURL) throws PluginException;
+
+ /**
+ * Adds a plugin site.
+ * <p>
+ * If the plugin site already exists this method does nothing.
+ *
+ * @param pluginSite the plugin site to add
+ * @throws PluginException
+ */
+ public void addPluginSite(PluginSite pluginSite) throws PluginException;
+
+ /**
+ * Removes a plugin site.
+ * <p>
+ * If the plugin site does not exist this method does nothing.
+ *
+ * @param pluginSite the plugin site to remove
+ * @throws PluginException
+ */
+ public void removePluginSite(PluginSite pluginSite) throws PluginException;
+
+ /**
+ * Returns all the plugins available at the specified plugin site.
+ * <p>
+ * If no plugins are available an empty list is returned.
+ *
+ * @param pluginSite
+ * the plugin site to contact
+ * @return all the plugins available at the specified plugin site
+ * @throws PluginException
+ * if there is a plroblem contacting the plugin site
+ */
+ public List<PluginVersions> getPlugins(PluginSite pluginSite) throws PluginException;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-impl/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-plugin-impl/pom.xml b/taverna-plugin-impl/pom.xml
new file mode 100644
index 0000000..488e777
--- /dev/null
+++ b/taverna-plugin-impl/pom.xml
@@ -0,0 +1,81 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.osgi</groupId>
+ <artifactId>taverna-osgi</artifactId>
+ <version>0.2.0-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>taverna-plugin-impl</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Taverna Plugin Implementation</name>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Import-Package>uk.org.taverna.commons.plugin;provide:=true,*</Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-plugin-api</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-download-api</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-osgi-schemas</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-app-configuration-api</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>${log4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>${osgi.core.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <version>${osgi.core.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>${commons.io.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginDirectoryWatcher.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginDirectoryWatcher.java b/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginDirectoryWatcher.java
new file mode 100644
index 0000000..9419d4e
--- /dev/null
+++ b/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginDirectoryWatcher.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.plugin.impl;
+
+import java.io.File;
+
+import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
+import org.apache.commons.io.monitor.FileAlterationMonitor;
+import org.apache.commons.io.monitor.FileAlterationObserver;
+import org.apache.log4j.Logger;
+
+import uk.org.taverna.commons.plugin.Plugin;
+import uk.org.taverna.commons.plugin.PluginException;
+
+/**
+ * Watches a plugin directory and adds or removes plugins when plugin files are added or removed
+ * from the directory.
+ *
+ * @author David Withers
+ */
+public class PluginDirectoryWatcher extends FileAlterationListenerAdaptor {
+
+ private static final Logger logger = Logger.getLogger(PluginDirectoryWatcher.class);
+
+ private final PluginManagerImpl pluginManager;
+ private final File directory;
+
+ private FileAlterationMonitor monitor;
+
+ public PluginDirectoryWatcher(PluginManagerImpl pluginManager, File directory) {
+ this.pluginManager = pluginManager;
+ this.directory = directory;
+ FileAlterationObserver observer = new FileAlterationObserver(directory);
+ observer.addListener(this);
+ monitor = new FileAlterationMonitor();
+ monitor.addObserver(observer);
+ }
+
+ /**
+ * Starts watching the plugin directory.
+ *
+ * @throws PluginException
+ */
+ public void start() throws PluginException {
+ try {
+ monitor.start();
+ } catch (Exception e) {
+ throw new PluginException(String.format("Error starting watch on %1$s.",
+ directory.getAbsolutePath()), e);
+ }
+ }
+
+ /**
+ * Stops watching the plugin directory.
+ *
+ * @throws PluginException
+ */
+ public void stop() throws PluginException {
+ try {
+ monitor.stop();
+ } catch (Exception e) {
+ throw new PluginException(String.format("Error stopping watch on %1$s.",
+ directory.getAbsolutePath()), e);
+ }
+ }
+
+ @Override
+ public void onFileCreate(File file) {
+ try {
+ Plugin plugin = pluginManager.installPlugin(file);
+ plugin.start();
+ } catch (PluginException e) {
+ logger.warn("Error loading plugin file " + file, e);
+ }
+ }
+
+ @Override
+ public void onFileChange(File file) {
+ onFileDelete(file);
+ onFileCreate(file);
+ }
+
+ @Override
+ public void onFileDelete(File file) {
+ pluginManager.uninstallPlugin(file);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginImpl.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginImpl.java b/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginImpl.java
new file mode 100644
index 0000000..5f31472
--- /dev/null
+++ b/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginImpl.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.plugin.impl;
+
+import static uk.org.taverna.commons.plugin.Plugin.State.STARTED;
+import static uk.org.taverna.commons.plugin.Plugin.State.STOPPED;
+import static uk.org.taverna.commons.plugin.Plugin.State.UNINSTALLED;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+
+import uk.org.taverna.commons.plugin.Plugin;
+import uk.org.taverna.commons.plugin.PluginException;
+import uk.org.taverna.commons.plugin.xml.jaxb.PluginInfo;
+
+/**
+ * @author David Withers
+ */
+public class PluginImpl implements Plugin {
+
+ private static final Logger logger = Logger.getLogger(PluginImpl.class);
+
+ private PluginManagerImpl pluginManager;
+
+ private State state = UNINSTALLED;
+
+ private File file;
+ private String id, name, description, organization;
+ private Version version;
+ private Set<Bundle> bundles = new HashSet<Bundle>();
+
+ public PluginImpl(PluginManagerImpl pluginManager, File file, PluginInfo pluginInfo) {
+ this.pluginManager = pluginManager;
+ this.file = file;
+ id = pluginInfo.getId();
+ name = pluginInfo.getName();
+ description = pluginInfo.getDescription();
+ organization = pluginInfo.getOrganization();
+ version = Version.parseVersion(pluginInfo.getVersion());
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getOrganization() {
+ return organization;
+ }
+
+ @Override
+ public Version getVersion() {
+ return version;
+ }
+
+ @Override
+ public State getState() {
+ return state;
+ }
+
+ void setState(State state) {
+ this.state = state;
+ }
+
+ @Override
+ public void start() throws PluginException {
+ if (state == STARTED) {
+ return;
+ }
+ if (state == UNINSTALLED) {
+ throw new PluginException("Cannot start an uninstalled plugin");
+ }
+ List<Bundle> startedBundles = new ArrayList<Bundle>();
+ for (Bundle bundle : getBundles()) {
+ if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) == null) {
+ if (bundle.getState() != Bundle.ACTIVE) {
+ try {
+ bundle.start();
+ startedBundles.add(bundle);
+ } catch (BundleException e) {
+ // clean up by stopping bundles already started
+ for (Bundle startedBundle : startedBundles) {
+ try {
+ startedBundle.stop();
+ } catch (BundleException ex) {
+ logger.warn("Error unistalling bundle", ex);
+ }
+ }
+ throw new PluginException(String.format("Error starting bundle %1$s",
+ bundle.getSymbolicName()), e);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void stop() throws PluginException {
+ if (state == STARTED) {
+ List<Plugin> installedPlugins = pluginManager.getInstalledPlugins();
+ for (Bundle bundle : getBundles()) {
+ // check if bundle is used by other plugins
+ boolean bundleUsed = false;
+ for (Plugin installedPlugin : installedPlugins) {
+ if (!installedPlugin.equals(this) && installedPlugin.getState() == STARTED) {
+ if (installedPlugin.getBundles().contains(bundle)) {
+ bundleUsed = true;
+ break;
+ }
+ }
+ }
+ if (!bundleUsed) {
+ try {
+ logger.info("Stopping bundle " + bundle.getSymbolicName());
+ bundle.stop();
+ } catch (BundleException e) {
+ logger.warn(
+ String.format("Error stopping bundle %1$s for plugin %2$s",
+ bundle.getSymbolicName(), getName()), e);
+ }
+ }
+ }
+ state = STOPPED;
+ }
+ }
+
+ @Override
+ public void uninstall() throws PluginException {
+ if (state != UNINSTALLED) {
+ pluginManager.uninstallPlugin(this);
+ state = UNINSTALLED;
+ }
+ }
+
+ @Override
+ public File getFile() {
+ return file;
+ }
+
+ @Override
+ public Set<Bundle> getBundles() {
+ return bundles;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginManagerImpl.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginManagerImpl.java b/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginManagerImpl.java
new file mode 100644
index 0000000..364551c
--- /dev/null
+++ b/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginManagerImpl.java
@@ -0,0 +1,466 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.plugin.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.log4j.Logger;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+
+import uk.org.taverna.commons.download.DownloadException;
+import uk.org.taverna.commons.download.DownloadManager;
+import uk.org.taverna.commons.plugin.Plugin;
+import uk.org.taverna.commons.plugin.Plugin.State;
+import uk.org.taverna.commons.plugin.PluginException;
+import uk.org.taverna.commons.plugin.PluginManager;
+import uk.org.taverna.commons.plugin.PluginSite;
+import uk.org.taverna.commons.plugin.PluginSiteManager;
+import uk.org.taverna.commons.plugin.xml.jaxb.PluginInfo;
+import uk.org.taverna.commons.plugin.xml.jaxb.PluginVersions;
+import uk.org.taverna.commons.profile.xml.jaxb.BundleInfo;
+import uk.org.taverna.configuration.app.ApplicationConfiguration;
+
+/**
+ * PluginManager implementation.
+ *
+ * @author David Withers
+ */
+public class PluginManagerImpl implements PluginManager {
+
+ private static final String DIGEST_ALGORITHM = "MD5";
+ private static final String PLUGIN_FILE_NAME = "META-INF/taverna/plugin.xml";
+
+ private static final Logger logger = Logger.getLogger(PluginManagerImpl.class);
+
+ private EventAdmin eventAdmin;
+ private ApplicationConfiguration applicationConfiguration;
+ private BundleContext bundleContext;
+ private DownloadManager downloadManager;
+ private PluginSiteManager pluginSiteManager;
+
+ private Map<String, Plugin> installedPlugins = new TreeMap<String, Plugin>();
+ private Map<String, PluginVersions> availablePlugins = new TreeMap<String, PluginVersions>();
+ private Map<String, PluginVersions> pluginUpdates = new TreeMap<String, PluginVersions>();
+
+ private boolean updateAvailablePlugins = true;
+
+ private Map<File, PluginDirectoryWatcher> pluginDirectoryWatchers = new HashMap<File, PluginDirectoryWatcher>();
+
+ private Set<Bundle> installedBundles = new HashSet<Bundle>();
+
+ private Unmarshaller unmarshaller;
+
+ public PluginManagerImpl() throws PluginException {
+ try {
+ JAXBContext jaxbContext = JAXBContext.newInstance(PluginInfo.class);
+ unmarshaller = jaxbContext.createUnmarshaller();
+ } catch (JAXBException e) {
+ throw new PluginException("Error creating JAXBContext", e);
+ }
+ }
+
+ @Override
+ public void checkForUpdates() throws PluginException {
+ boolean updatesFound = false;
+ synchronized (pluginUpdates) {
+ pluginUpdates.clear();
+ for (PluginSite pluginSite : pluginSiteManager.getPluginSites()) {
+ List<PluginVersions> plugins = pluginSiteManager.getPlugins(pluginSite);
+ for (PluginVersions plugin : plugins) {
+ if (installedPlugins.containsKey(plugin.getId())) {
+ Plugin installedPlugin = installedPlugins.get(plugin.getId());
+ if (installedPlugin.getFile().canWrite()) {
+ Version latestVersion = Version.parseVersion(plugin.getLatestVersion()
+ .getVersion());
+ if (latestVersion.compareTo(installedPlugin.getVersion()) > 0) {
+ pluginUpdates.put(plugin.getId(), plugin);
+ updatesFound = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (updatesFound) {
+ postEvent(PluginManager.UPDATES_AVAILABLE);
+ }
+ }
+
+ @Override
+ public List<PluginVersions> getPluginUpdates() throws PluginException {
+ synchronized (pluginUpdates) {
+ return new ArrayList<PluginVersions>(pluginUpdates.values());
+ }
+ }
+
+ @Override
+ public void loadPlugins() throws PluginException {
+ loadPlugins(applicationConfiguration.getSystemPluginDir());
+ loadPlugins(applicationConfiguration.getUserPluginDir());
+ }
+
+ @Override
+ public List<PluginVersions> getAvailablePlugins() throws PluginException {
+ if (updateAvailablePlugins) {
+ synchronized (availablePlugins) {
+ availablePlugins = new HashMap<String, PluginVersions>();
+ for (PluginSite pluginSite : pluginSiteManager.getPluginSites()) {
+ List<PluginVersions> plugins = pluginSiteManager.getPlugins(pluginSite);
+ for (PluginVersions plugin : plugins) {
+ if (!installedPlugins.containsKey(plugin.getId())) {
+ availablePlugins.put(plugin.getId(), plugin);
+ }
+ }
+ }
+ }
+ updateAvailablePlugins = false;
+ }
+ return new ArrayList<PluginVersions>(availablePlugins.values());
+ }
+
+ @Override
+ public List<Plugin> getInstalledPlugins() throws PluginException {
+ return new ArrayList<Plugin>(installedPlugins.values());
+ }
+
+ @Override
+ public Plugin installPlugin(File pluginFile) throws PluginException {
+ // check if already installed
+ synchronized (installedPlugins) {
+ for (Plugin plugin : installedPlugins.values()) {
+ if (plugin.getFile().equals(pluginFile)) {
+ return plugin;
+ }
+ }
+ // check plugin file
+ if (pluginFile.exists()) {
+ new PluginException(String.format("Plugin file %1$s does not exist", pluginFile));
+ }
+ if (pluginFile.isFile()) {
+ new PluginException(String.format("Plugin file %1$s is not a file", pluginFile));
+ }
+ if (!pluginFile.canRead()) {
+ new PluginException(String.format("Plugin file %1$s is not readable", pluginFile));
+ }
+ // install plugin from plugin file
+ logger.info(String.format("Installing plugin from '%s'", pluginFile));
+ JarFile jarFile;
+ try {
+ jarFile = new JarFile(pluginFile);
+ } catch (IOException e) {
+ throw new PluginException(String.format("Error reading plugin file %1$s",
+ pluginFile), e);
+ }
+ Plugin plugin = installPlugin(jarFile);
+ installedPlugins.put(plugin.getId(), plugin);
+ availablePlugins.remove(plugin.getId());
+ postEvent(PluginManager.PLUGIN_INSTALLED);
+ return plugin;
+ }
+ }
+
+ @Override
+ public Plugin installPlugin(String pluginSiteURL, String pluginFileName) throws PluginException {
+ File pluginFile = getPluginFile(pluginSiteURL, pluginFileName);
+ return installPlugin(pluginFile);
+ }
+
+ @Override
+ public Plugin updatePlugin(PluginVersions pluginVersions) throws PluginException {
+ String pluginId = pluginVersions.getId();
+ String pluginSiteUrl = pluginVersions.getPluginSiteUrl();
+ String pluginFile = pluginVersions.getLatestVersion().getFile();
+ Plugin plugin = installedPlugins.get(pluginId);
+ plugin.stop();
+ Plugin newPlugin;
+ try {
+ newPlugin = installPlugin(pluginSiteUrl, pluginFile);
+ } catch (PluginException e) {
+ plugin.start();
+ throw new PluginException("Failed to update plugin " + pluginId, e);
+ }
+ synchronized (pluginUpdates) {
+ pluginUpdates.remove(pluginId);
+ }
+ uninstallPlugin(plugin);
+ return newPlugin;
+ }
+
+ void uninstallPlugin(File pluginFile) {
+ synchronized (installedPlugins) {
+ for (Plugin plugin : installedPlugins.values()) {
+ if (plugin.getFile().equals(pluginFile)) {
+ uninstallPlugin(plugin);
+ break;
+ }
+ }
+ }
+ }
+
+ void uninstallPlugin(Plugin plugin) {
+ synchronized (installedPlugins) {
+ if (installedPlugins.containsKey(plugin.getId())) {
+ for (Bundle bundle : plugin.getBundles()) {
+ if (installedBundles.contains(bundle)) {
+ // check if bundle is used by other plugins
+ boolean bundleInUse = false;
+ for (Plugin installedPlugin : installedPlugins.values()) {
+ if (!installedPlugin.equals(plugin)) {
+ if (installedPlugin.getBundles().contains(bundle)) {
+ bundleInUse = true;
+ break;
+ }
+ }
+ }
+ if (!bundleInUse) {
+ try {
+ logger.info("Uninstalling bundle " + bundle.getSymbolicName());
+ bundle.uninstall();
+ installedBundles.remove(bundle);
+ System.out.println("Remove " + bundle.getSymbolicName());
+ } catch (BundleException e) {
+ logger.warn(String.format(
+ "Error uninstalling bundle %1$s for plugin %2$s",
+ bundle.getSymbolicName(), plugin.getName()), e);
+ }
+ }
+ }
+ }
+ installedPlugins.remove(plugin.getId());
+ pluginUpdates.remove(plugin.getId());
+ updateAvailablePlugins = true;
+ postEvent(PluginManager.PLUGIN_UNINSTALLED);
+ }
+ }
+ }
+
+ public void loadPlugins(File pluginDir) throws PluginException {
+ if (checkPluginDirectory(pluginDir, false)) {
+ for (File pluginFile : pluginDir.listFiles()) {
+ if (pluginFile.isFile() && pluginFile.canRead() && !pluginFile.isHidden()) {
+ try {
+ installPlugin(pluginFile).start();
+ } catch (PluginException e) {
+ logger.warn(String.format("Error loading plugin from '%s'", pluginFile), e);
+ }
+ }
+ }
+ }
+ startWatchingPluginDirectory(pluginDir);
+ }
+
+ private Plugin installPlugin(JarFile jarFile) throws PluginException {
+ PluginInfo pluginInfo = getPluginInfo(jarFile);
+
+ PluginImpl plugin = new PluginImpl(this, new File(jarFile.getName()), pluginInfo);
+
+ // check bundles exist in jar
+ for (BundleInfo bundleInfo : pluginInfo.getBundle()) {
+ // find the bundle in the plugin jar
+ JarEntry entry = jarFile.getJarEntry(bundleInfo.getFileName());
+ if (entry == null) {
+ throw new PluginException(String.format(
+ "Plugin file '%1$s' does not contain bundle file '%2$s'.",
+ jarFile.getName(), bundleInfo.getFileName()));
+ }
+ }
+
+ // install plugin bundles
+ Set<Bundle> pluginBundles = plugin.getBundles();
+ for (BundleInfo bundleInfo : pluginInfo.getBundle()) {
+ Bundle installedBundle = getInstalledBundle(bundleInfo);
+ if (installedBundle == null) {
+ // install the bundle from the jar
+ JarEntry entry = jarFile.getJarEntry(bundleInfo.getFileName());
+ String bundleURL = jarEntryToURL(jarFile, entry);
+ try {
+ Bundle bundle = bundleContext.installBundle(bundleURL);
+ pluginBundles.add(bundle);
+ installedBundles.add(bundle);
+ System.out.println("Add " + bundle.getSymbolicName());
+ } catch (BundleException e) {
+ // clean up by removing bundles already installed
+ for (Bundle bundle : pluginBundles) {
+ try {
+ bundle.uninstall();
+ installedBundles.remove(bundle);
+ } catch (BundleException ex) {
+ logger.warn("Error unistalling bundle", ex);
+ }
+ }
+ throw new PluginException(String.format("Error installing bundle file %1$s",
+ bundleURL), e);
+ }
+ } else {
+ pluginBundles.add(installedBundle);
+ }
+ }
+ plugin.setState(State.INSTALLED);
+ return plugin;
+ }
+
+ private Bundle getInstalledBundle(BundleInfo bundleInfo) {
+ for (Bundle installedBundle : bundleContext.getBundles()) {
+ if (installedBundle.getSymbolicName().equals(bundleInfo.getSymbolicName())) {
+ org.osgi.framework.Version installedVersion = installedBundle.getVersion();
+ if (installedVersion
+ .equals(new org.osgi.framework.Version(bundleInfo.getVersion()))) {
+ return installedBundle;
+ }
+ }
+ }
+ return null;
+ }
+
+ public PluginInfo getPluginInfo(JarFile jarFile) throws PluginException {
+ // TODO check manifest for non standard plugin info file
+ JarEntry pluginEntry = jarFile.getJarEntry(PLUGIN_FILE_NAME);
+ if (pluginEntry == null) {
+ throw new PluginException(String.format(
+ "Plugin file '%1$s' does not contain a %2$s file.", jarFile.getName(),
+ PLUGIN_FILE_NAME));
+ }
+ try {
+ InputStream inputStream = jarFile.getInputStream(pluginEntry);
+ return (PluginInfo) unmarshaller.unmarshal(inputStream);
+ } catch (JAXBException e) {
+ throw new PluginException(String.format("Error reading plugin file %1$s from %2$s",
+ pluginEntry, jarFile.getName()), e);
+ } catch (IOException e) {
+ throw new PluginException(String.format("Error reading plugin file %1$s from %2$s",
+ pluginEntry, jarFile.getName()), e);
+ }
+ }
+
+ private File getPluginFile(String pluginSiteURL, String pluginFileName) throws PluginException {
+ File pluginFile = new File(getPluginDirectory(), pluginFileName);
+ String pluginFileURL = pluginSiteURL + "/" + pluginFileName;
+ try {
+ downloadManager.download(new URL(pluginFileURL), pluginFile, DIGEST_ALGORITHM);
+ } catch (DownloadException e) {
+ throw new PluginException("Error downloading plugin file " + pluginFile, e);
+ } catch (MalformedURLException e) {
+ throw new PluginException("Invalid plugin file URL " + pluginFileURL, e);
+ }
+ return pluginFile;
+ }
+
+ public void startWatchingPluginDirectory(File pluginDir) throws PluginException {
+ if (!pluginDirectoryWatchers.containsKey(pluginDir)) {
+ pluginDirectoryWatchers.put(pluginDir, new PluginDirectoryWatcher(this, pluginDir));
+ }
+ pluginDirectoryWatchers.get(pluginDir).start();
+ }
+
+ public void stopWatchingPluginDirectory(File pluginDir) throws PluginException {
+ if (pluginDirectoryWatchers.containsKey(pluginDir)) {
+ pluginDirectoryWatchers.get(pluginDir).stop();
+ }
+ }
+
+ private File getPluginDirectory() throws PluginException {
+ File systemPluginsDir = applicationConfiguration.getSystemPluginDir();
+ if (checkPluginDirectory(systemPluginsDir, true)) {
+ return systemPluginsDir;
+ }
+ File userPluginsDir = applicationConfiguration.getUserPluginDir();
+ if (checkPluginDirectory(userPluginsDir, true)) {
+ return userPluginsDir;
+ }
+ throw new PluginException("No plugin directory avaliable");
+ }
+
+ public void setEventAdmin(EventAdmin eventAdmin) {
+ this.eventAdmin = eventAdmin;
+ }
+
+ public void setApplicationConfiguration(ApplicationConfiguration applicationConfiguration) {
+ this.applicationConfiguration = applicationConfiguration;
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public void setDownloadManager(DownloadManager downloadManager) {
+ this.downloadManager = downloadManager;
+ }
+
+ public void setPluginSiteManager(PluginSiteManager pluginSiteManager) {
+ this.pluginSiteManager = pluginSiteManager;
+ }
+
+ private boolean checkPluginDirectory(File pluginDirectory, boolean checkWritable) {
+ if (pluginDirectory == null) {
+ return false;
+ }
+ if (!pluginDirectory.exists()) {
+ logger.debug(String.format("Plugin directory %1$s does not exist", pluginDirectory));
+ return false;
+ }
+ if (!pluginDirectory.isDirectory()) {
+ logger.warn(String.format("Plugin directory %1$s is not a directory", pluginDirectory));
+ return false;
+ }
+ if (!pluginDirectory.canRead()) {
+ logger.debug(String.format("Plugin directory %1$s is not readable", pluginDirectory));
+ return false;
+ }
+ if (checkWritable && !pluginDirectory.canWrite()) {
+ logger.debug(String.format("Plugin directory %1$s is not writeable", pluginDirectory));
+ return false;
+ }
+ return true;
+ }
+
+ private String jarEntryToURL(JarFile jarFile, JarEntry jarEntry) {
+ File file = new File(jarFile.getName());
+ return "jar:" + file.toURI() + "!/" + jarEntry.getName();
+ }
+
+ private void postEvent(String topic) {
+ Event event = new Event(topic, new HashMap());
+ eventAdmin.postEvent(event);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginSiteImpl.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginSiteImpl.java b/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginSiteImpl.java
new file mode 100644
index 0000000..6458341
--- /dev/null
+++ b/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginSiteImpl.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.plugin.impl;
+
+import uk.org.taverna.commons.plugin.PluginSite;
+
+/**
+ * PluginSite implementation.
+ *
+ * @author David Withers
+ */
+public class PluginSiteImpl implements PluginSite {
+
+ private String name, url;
+
+ private PluginSiteType type;
+
+ public PluginSiteImpl() {
+ }
+
+ public PluginSiteImpl(String name, String url) {
+ this(name, url, PluginSiteType.USER);
+ }
+
+ public PluginSiteImpl(String name, String url, PluginSiteType type) {
+ this.name = name;
+ this.url = url;
+ this.type = type;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ @Override
+ public PluginSiteType getType() {
+ return type;
+ }
+
+ public void setType(PluginSiteType type) {
+ this.type = type;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginSiteManagerImpl.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginSiteManagerImpl.java b/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginSiteManagerImpl.java
new file mode 100644
index 0000000..1634d98
--- /dev/null
+++ b/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginSiteManagerImpl.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.plugin.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.log4j.Logger;
+
+import uk.org.taverna.commons.download.DownloadException;
+import uk.org.taverna.commons.download.DownloadManager;
+import uk.org.taverna.commons.plugin.PluginException;
+import uk.org.taverna.commons.plugin.PluginSite;
+import uk.org.taverna.commons.plugin.PluginSite.PluginSiteType;
+import uk.org.taverna.commons.plugin.PluginSiteManager;
+import uk.org.taverna.commons.plugin.xml.jaxb.PluginVersions;
+import uk.org.taverna.commons.plugin.xml.jaxb.Plugins;
+import uk.org.taverna.commons.profile.xml.jaxb.Updates;
+import uk.org.taverna.configuration.app.ApplicationConfiguration;
+
+/**
+ * PluginSiteManager implementation.
+ *
+ * @author David Withers
+ */
+public class PluginSiteManagerImpl implements PluginSiteManager {
+
+ private static final String PLUGIN_SITES_FILE = "plugin-sites.xml";
+ private static final String DIGEST_ALGORITHM = "MD5";
+ private static final String PLUGINS_FILE = "plugins.xml";
+
+ private static final Logger logger = Logger.getLogger(PluginSiteManagerImpl.class);
+
+ private ApplicationConfiguration applicationConfiguration;
+ private DownloadManager downloadManager;
+
+ private Unmarshaller unmarshaller;
+ private Marshaller marshaller;
+
+ private List<PluginSite> pluginSites;
+
+ public PluginSiteManagerImpl() throws PluginException {
+ try {
+ JAXBContext jaxbContext = JAXBContext.newInstance(Plugins.class, PluginSites.class);
+ unmarshaller = jaxbContext.createUnmarshaller();
+ marshaller = jaxbContext.createMarshaller();
+ } catch (JAXBException e) {
+ throw new PluginException("Error creating JAXBContext", e);
+ }
+ }
+
+ @Override
+ public List<PluginSite> getPluginSites() {
+ if (pluginSites == null) {
+ readPluginSitesFile();
+ if (pluginSites == null) {
+ pluginSites = new ArrayList<PluginSite>();
+ pluginSites.addAll(getSystemPluginSites());
+ }
+ }
+ return pluginSites;
+ }
+
+ @Override
+ public PluginSite createPluginSite(URL pluginSiteURL) throws PluginException {
+ try {
+ File tempFile = File.createTempFile("plugins", null);
+ tempFile.deleteOnExit();
+ URL pluginFileURL = new URL(pluginSiteURL + "/" + PLUGINS_FILE);
+ downloadManager.download(pluginFileURL, tempFile, DIGEST_ALGORITHM);
+ return new PluginSiteImpl("", pluginSiteURL.toExternalForm());
+ } catch (MalformedURLException e) {
+ throw new PluginException(String.format("Invalid plugin site URL %1$s", pluginSiteURL), e);
+ } catch (DownloadException e) {
+ throw new PluginException(String.format("Error contacting plugin site at %1$s", pluginSiteURL), e);
+ } catch (IOException e) {
+ throw new PluginException(String.format("Error contacting plugin site at %1$s", pluginSiteURL), e);
+ }
+ }
+
+ @Override
+ public void addPluginSite(PluginSite pluginSite) throws PluginException {
+ getPluginSites().add(pluginSite);
+ writePluginSitesFile();
+ }
+
+ @Override
+ public void removePluginSite(PluginSite pluginSite) throws PluginException {
+ getPluginSites().remove(pluginSite);
+ writePluginSitesFile();
+ }
+
+ @Override
+ public List<PluginVersions> getPlugins(PluginSite pluginSite) throws PluginException {
+ List<PluginVersions> plugins = new ArrayList<PluginVersions>();
+ try {
+ URL pluginSiteURL = new URL(pluginSite.getUrl() + "/" + PLUGINS_FILE);
+ File pluginsFile = new File(getDataDirectory(), PLUGINS_FILE);
+ downloadManager.download(pluginSiteURL, pluginsFile, DIGEST_ALGORITHM);
+ Plugins pluginsXML = (Plugins) unmarshaller.unmarshal(pluginsFile);
+ for (PluginVersions plugin : pluginsXML.getPlugin()) {
+ plugin.setPluginSiteUrl(pluginSite.getUrl());
+ plugins.add(plugin);
+ }
+ } catch (MalformedURLException e) {
+ throw new PluginException(String.format("Plugin site %1$s has an invalid location",
+ pluginSite.getName()), e);
+ } catch (DownloadException e) {
+ throw new PluginException(String.format("Error downloading from plugin site %1$s",
+ pluginSite.getName()), e);
+ } catch (JAXBException e) {
+ throw new PluginException(String.format("Error getting plugins from plugin site %1$s",
+ pluginSite.getName()), e);
+ }
+ return plugins;
+ }
+
+ private List<PluginSite> getSystemPluginSites() {
+ List<PluginSite> systemPluginSites = new ArrayList<PluginSite>();
+ Updates updates = applicationConfiguration.getApplicationProfile().getUpdates();
+ systemPluginSites
+ .add(new PluginSiteImpl("", updates.getPluginSite(), PluginSiteType.SYSTEM));
+ return systemPluginSites;
+ }
+
+ private void writePluginSitesFile() {
+ File pluginSitesFile = new File(getDataDirectory(), PLUGIN_SITES_FILE);
+ try {
+ marshaller.marshal(pluginSites, pluginSitesFile);
+ } catch (JAXBException e) {
+ logger.error("Error writing file " + pluginSitesFile, e);
+ }
+ }
+
+ private void readPluginSitesFile() {
+ File pluginSitesFile = new File(getDataDirectory(), PLUGIN_SITES_FILE);
+ if (pluginSitesFile.exists()) {
+ try {
+ pluginSites = new ArrayList<PluginSite>();
+ PluginSites pluginSitesStore = (PluginSites) unmarshaller
+ .unmarshal(pluginSitesFile);
+ for (PluginSiteImpl pluginSiteImpl : pluginSitesStore.getPluginSites()) {
+ pluginSites.add(pluginSiteImpl);
+ }
+ } catch (JAXBException e) {
+ logger.error("Error reading file " + pluginSitesFile, e);
+ }
+ }
+ }
+
+ private File getDataDirectory() {
+ return new File(applicationConfiguration.getApplicationHomeDir(), "plugin-data");
+ }
+
+ public void setApplicationConfiguration(ApplicationConfiguration applicationConfiguration) {
+ this.applicationConfiguration = applicationConfiguration;
+ }
+
+ public void setDownloadManager(DownloadManager downloadManager) {
+ this.downloadManager = downloadManager;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginSites.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginSites.java b/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginSites.java
new file mode 100644
index 0000000..1e5203f
--- /dev/null
+++ b/taverna-plugin-impl/src/main/java/uk/org/taverna/commons/plugin/impl/PluginSites.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.plugin.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ *
+ *
+ * @author David Withers
+ */
+@XmlRootElement
+public class PluginSites {
+
+ private List<PluginSiteImpl> pluginSites;
+
+ public List<PluginSiteImpl> getPluginSites() {
+ if (pluginSites == null) {
+ pluginSites = new ArrayList<PluginSiteImpl>();
+ }
+ return pluginSites;
+ }
+
+ public void setPluginSites(List<PluginSiteImpl> pluginSites) {
+ this.pluginSites = pluginSites;
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-impl/src/main/resources/META-INF/spring/plugin-context-osgi.xml
----------------------------------------------------------------------
diff --git a/taverna-plugin-impl/src/main/resources/META-INF/spring/plugin-context-osgi.xml b/taverna-plugin-impl/src/main/resources/META-INF/spring/plugin-context-osgi.xml
new file mode 100644
index 0000000..cd235f5
--- /dev/null
+++ b/taverna-plugin-impl/src/main/resources/META-INF/spring/plugin-context-osgi.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans:beans xmlns="http://www.springframework.org/schema/osgi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:beans="http://www.springframework.org/schema/beans"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/osgi
+ http://www.springframework.org/schema/osgi/spring-osgi.xsd">
+
+ <service ref="pluginManager" interface="uk.org.taverna.commons.plugin.PluginManager" />
+ <service ref="pluginSiteManager" interface="uk.org.taverna.commons.plugin.PluginSiteManager" />
+
+ <reference id="applicationConfiguration" interface="uk.org.taverna.configuration.app.ApplicationConfiguration" />
+ <reference id="downloadManager" interface="uk.org.taverna.commons.download.DownloadManager" />
+
+ <reference id="eventAdmin" interface="org.osgi.service.event.EventAdmin" />
+
+</beans:beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-impl/src/main/resources/META-INF/spring/plugin-context.xml
----------------------------------------------------------------------
diff --git a/taverna-plugin-impl/src/main/resources/META-INF/spring/plugin-context.xml b/taverna-plugin-impl/src/main/resources/META-INF/spring/plugin-context.xml
new file mode 100644
index 0000000..7315a1b
--- /dev/null
+++ b/taverna-plugin-impl/src/main/resources/META-INF/spring/plugin-context.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/osgi-compendium
+ http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd">
+
+ <!-- <osgix:cm-properties id="cfg.with.defaults" persistent-id="uk.org.taverna.commons.plugin.impl.PluginSiteManagerImpl">
+ <prop key="checkIntervalSeconds">300</prop>
+ </osgix:cm-properties> -->
+
+ <bean id="pluginManager" class="uk.org.taverna.commons.plugin.impl.PluginManagerImpl">
+ <property name="eventAdmin" ref="eventAdmin" />
+ <property name="applicationConfiguration" ref="applicationConfiguration" />
+ <property name="bundleContext" ref="bundleContext" />
+ <property name="downloadManager" ref="downloadManager" />
+ <property name="pluginSiteManager">
+ <ref local="pluginSiteManager" />
+ </property>
+
+ </bean>
+
+ <bean id="pluginSiteManager"
+ class="uk.org.taverna.commons.plugin.impl.PluginSiteManagerImpl">
+ <property name="applicationConfiguration" ref="applicationConfiguration" />
+ <property name="downloadManager" ref="downloadManager" />
+ <!-- <osgix:managed-properties persistent-id="uk.org.taverna.commons.plugin.impl.PluginSiteManagerImpl" /> -->
+ </bean>
+
+</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-impl/src/test/java/uk/org/taverna/commons/plugin/impl/PluginSiteImplTest.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-impl/src/test/java/uk/org/taverna/commons/plugin/impl/PluginSiteImplTest.java b/taverna-plugin-impl/src/test/java/uk/org/taverna/commons/plugin/impl/PluginSiteImplTest.java
new file mode 100644
index 0000000..02ccb6e
--- /dev/null
+++ b/taverna-plugin-impl/src/test/java/uk/org/taverna/commons/plugin/impl/PluginSiteImplTest.java
@@ -0,0 +1,72 @@
+package uk.org.taverna.commons.plugin.impl;
+
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import uk.org.taverna.commons.plugin.PluginSite.PluginSiteType;
+
+public class PluginSiteImplTest {
+
+ PluginSiteImpl pluginSiteImpl;
+ String name, url;
+ PluginSiteType type;
+
+ @Before
+ public void setUp() throws Exception {
+ name = "test name";
+ url = "test url";
+ type = PluginSiteType.SYSTEM;
+ pluginSiteImpl = new PluginSiteImpl(name, url, type);
+ }
+
+ @Test
+ public void testPluginSiteImpl() {
+ pluginSiteImpl = new PluginSiteImpl();
+ }
+
+ @Test
+ public void testPluginSiteImplStringStringPluginSiteType() {
+ pluginSiteImpl = new PluginSiteImpl(null, null, null);
+ pluginSiteImpl = new PluginSiteImpl("", "", PluginSiteType.USER);
+ }
+
+ @Test
+ public void testGetName() {
+ assertEquals(name, pluginSiteImpl.getName());
+ assertEquals(name, pluginSiteImpl.getName());
+ }
+
+ @Test
+ public void testSetName() {
+ pluginSiteImpl.setName("name");
+ assertEquals("name", pluginSiteImpl.getName());
+ }
+
+ @Test
+ public void testGetUrl() {
+ assertEquals(url, pluginSiteImpl.getUrl());
+ assertEquals(url, pluginSiteImpl.getUrl());
+ }
+
+ @Test
+ public void testSetUrl() {
+ pluginSiteImpl.setName("http://www.example.com/");
+ assertEquals("http://www.example.com/", pluginSiteImpl.getName());
+ }
+
+ @Test
+ public void testGetType() {
+ assertEquals(type, pluginSiteImpl.getType());
+ assertEquals(type, pluginSiteImpl.getType());
+ }
+
+ @Test
+ public void testSetType() {
+ pluginSiteImpl.setType(PluginSiteType.USER);
+ assertEquals(PluginSiteType.USER, pluginSiteImpl.getType());
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-plugin-impl/src/test/java/uk/org/taverna/commons/plugin/impl/PluginSiteManagerImplTest.java
----------------------------------------------------------------------
diff --git a/taverna-plugin-impl/src/test/java/uk/org/taverna/commons/plugin/impl/PluginSiteManagerImplTest.java b/taverna-plugin-impl/src/test/java/uk/org/taverna/commons/plugin/impl/PluginSiteManagerImplTest.java
new file mode 100644
index 0000000..0ca9485
--- /dev/null
+++ b/taverna-plugin-impl/src/test/java/uk/org/taverna/commons/plugin/impl/PluginSiteManagerImplTest.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.plugin.impl;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import uk.org.taverna.commons.download.DownloadException;
+import uk.org.taverna.commons.download.DownloadManager;
+import uk.org.taverna.commons.plugin.PluginException;
+import uk.org.taverna.configuration.app.ApplicationConfiguration;
+
+/**
+ *
+ *
+ * @author David Withers
+ */
+@Ignore
+public class PluginSiteManagerImplTest {
+
+ private PluginSiteManagerImpl pluginSiteManager;
+ private ApplicationConfiguration applicationConfiguration;
+ private DownloadManager downloadManager;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ pluginSiteManager = new PluginSiteManagerImpl();
+ applicationConfiguration = mock(ApplicationConfiguration.class);
+ }
+
+ /**
+ * Test method for {@link uk.org.taverna.commons.plugin.impl.PluginSiteManagerImpl#PluginSiteManagerImpl()}.
+ * @throws Exception
+ */
+ @Test
+ public void testPluginSiteManagerImpl() throws Exception {
+ new PluginSiteManagerImpl();
+ }
+
+ /**
+ * Test method for {@link uk.org.taverna.commons.plugin.impl.PluginSiteManagerImpl#getPluginSites()}.
+ */
+ @Test
+ public void testGetPluginSites() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link uk.org.taverna.commons.plugin.impl.PluginSiteManagerImpl#createPluginSite(java.net.URL)}.
+ * @throws DownloadException
+ */
+ @Test
+ public void testCreatePluginSite() throws Exception {
+ downloadManager = mock(DownloadManager.class);
+ doNothing().when(downloadManager).download(new URL("file:///"), null, "");
+
+ pluginSiteManager.setDownloadManager(downloadManager);
+
+ pluginSiteManager.createPluginSite(new URL("file:///"));
+
+ }
+
+ @Test(expected=PluginException.class)
+ public void testCreatePluginSiteDownloadException() throws Exception {
+ downloadManager = mock(DownloadManager.class);
+ doThrow(DownloadException.class).when(downloadManager).download(new URL("file:///"), null, "");
+
+ pluginSiteManager.setDownloadManager(downloadManager);
+
+ pluginSiteManager.createPluginSite(new URL("file:///"));
+ }
+
+ /**
+ * Test method for {@link uk.org.taverna.commons.plugin.impl.PluginSiteManagerImpl#addPluginSite(uk.org.taverna.commons.plugin.PluginSite)}.
+ */
+ @Test
+ public void testAddPluginSite() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link uk.org.taverna.commons.plugin.impl.PluginSiteManagerImpl#removePluginSite(uk.org.taverna.commons.plugin.PluginSite)}.
+ */
+ @Test
+ public void testRemovePluginSite() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link uk.org.taverna.commons.plugin.impl.PluginSiteManagerImpl#getPlugins(uk.org.taverna.commons.plugin.PluginSite)}.
+ */
+ @Test
+ public void testGetPlugins() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link uk.org.taverna.commons.plugin.impl.PluginSiteManagerImpl#setApplicationConfiguration(uk.org.taverna.configuration.app.ApplicationConfiguration)}.
+ */
+ @Test
+ public void testSetApplicationConfiguration() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link uk.org.taverna.commons.plugin.impl.PluginSiteManagerImpl#setDownloadManager(uk.org.taverna.commons.download.DownloadManager)}.
+ */
+ @Test
+ public void testSetDownloadManager() {
+ fail("Not yet implemented");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-update-api/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-update-api/pom.xml b/taverna-update-api/pom.xml
new file mode 100644
index 0000000..2b70a7d
--- /dev/null
+++ b/taverna-update-api/pom.xml
@@ -0,0 +1,12 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.osgi</groupId>
+ <artifactId>taverna-osgi</artifactId>
+ <version>0.2.0-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>taverna-update-api</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Taverna Update API</name>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-update-api/src/main/java/uk/org/taverna/commons/update/UpdateException.java
----------------------------------------------------------------------
diff --git a/taverna-update-api/src/main/java/uk/org/taverna/commons/update/UpdateException.java b/taverna-update-api/src/main/java/uk/org/taverna/commons/update/UpdateException.java
new file mode 100644
index 0000000..54019fc
--- /dev/null
+++ b/taverna-update-api/src/main/java/uk/org/taverna/commons/update/UpdateException.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.update;
+
+/**
+ * Thrown when an update fails.
+ *
+ * @author David Withers
+ */
+public class UpdateException extends Exception {
+
+ private static final long serialVersionUID = -5852543170339969041L;
+
+ public UpdateException() {
+ }
+
+ public UpdateException(String message) {
+ super(message);
+ }
+
+ public UpdateException(Throwable cause) {
+ super(cause);
+ }
+
+ public UpdateException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-update-api/src/main/java/uk/org/taverna/commons/update/UpdateManager.java
----------------------------------------------------------------------
diff --git a/taverna-update-api/src/main/java/uk/org/taverna/commons/update/UpdateManager.java b/taverna-update-api/src/main/java/uk/org/taverna/commons/update/UpdateManager.java
new file mode 100644
index 0000000..29415cc
--- /dev/null
+++ b/taverna-update-api/src/main/java/uk/org/taverna/commons/update/UpdateManager.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package uk.org.taverna.commons.update;
+
+/**
+ * Manager for updating Tavana Applications.
+ *
+ * @author David Withers
+ */
+public interface UpdateManager {
+
+ public boolean checkForUpdates() throws UpdateException;
+
+ public boolean update() throws UpdateException;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-osgi/blob/c9bb093a/taverna-update-impl/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-update-impl/pom.xml b/taverna-update-impl/pom.xml
new file mode 100644
index 0000000..ee081a2
--- /dev/null
+++ b/taverna-update-impl/pom.xml
@@ -0,0 +1,63 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.osgi</groupId>
+ <artifactId>taverna-osgi</artifactId>
+ <version>0.2.0-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>taverna-update-impl</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Taverna Update Implementation</name>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Import-Package>uk.org.taverna.commons.update;provide:=true,*</Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-update-api</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-download-api</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-osgi-schemas</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-app-configuration-api</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>${commons.io.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>${osgi.core.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <version>${osgi.core.version}</version>
+ </dependency>
+ </dependencies>
+</project>