diff --git a/plugins/scm-git-plugin/src/main/resources/META-INF/scm/plugin.xml b/plugins/scm-git-plugin/src/main/resources/META-INF/scm/plugin.xml index 84863f195f..3ccdb97d5d 100644 --- a/plugins/scm-git-plugin/src/main/resources/META-INF/scm/plugin.xml +++ b/plugins/scm-git-plugin/src/main/resources/META-INF/scm/plugin.xml @@ -43,10 +43,12 @@ + ${project.groupId} + ${project.artifactId} + ${project.version} ${project.name} ${project.description} Sebastian Sdorra - ${project.version} ${project.url} diff --git a/plugins/scm-graph-plugin/src/main/resources/META-INF/scm/plugin.xml b/plugins/scm-graph-plugin/src/main/resources/META-INF/scm/plugin.xml index 0fec159379..131fc005d0 100644 --- a/plugins/scm-graph-plugin/src/main/resources/META-INF/scm/plugin.xml +++ b/plugins/scm-graph-plugin/src/main/resources/META-INF/scm/plugin.xml @@ -43,9 +43,12 @@ - ${project.name} - Sebastian Sdorra + ${project.groupId} + ${project.artifactId} ${project.version} + ${project.name} + ${project.description} + Sebastian Sdorra ${project.url} diff --git a/plugins/scm-hg-plugin/src/main/resources/META-INF/scm/plugin.xml b/plugins/scm-hg-plugin/src/main/resources/META-INF/scm/plugin.xml index d4144969c2..01bd5acc25 100644 --- a/plugins/scm-hg-plugin/src/main/resources/META-INF/scm/plugin.xml +++ b/plugins/scm-hg-plugin/src/main/resources/META-INF/scm/plugin.xml @@ -43,10 +43,12 @@ + ${project.groupId} + ${project.artifactId} + ${project.version} ${project.name} ${project.description} Sebastian Sdorra - ${project.version} ${project.url} diff --git a/plugins/scm-svn-plugin/src/main/resources/META-INF/scm/plugin.xml b/plugins/scm-svn-plugin/src/main/resources/META-INF/scm/plugin.xml index 2c34327c2a..9a0d6721cb 100644 --- a/plugins/scm-svn-plugin/src/main/resources/META-INF/scm/plugin.xml +++ b/plugins/scm-svn-plugin/src/main/resources/META-INF/scm/plugin.xml @@ -43,10 +43,12 @@ + ${project.groupId} + ${project.artifactId} + ${project.version} ${project.name} ${project.description} Sebastian Sdorra - ${project.version} ${project.url} diff --git a/samples/scm-sample-auth/src/main/resources/META-INF/scm/plugin.xml b/samples/scm-sample-auth/src/main/resources/META-INF/scm/plugin.xml index 8d240fe27e..8776d2aec3 100644 --- a/samples/scm-sample-auth/src/main/resources/META-INF/scm/plugin.xml +++ b/samples/scm-sample-auth/src/main/resources/META-INF/scm/plugin.xml @@ -35,10 +35,12 @@ + ${project.groupId} + ${project.artifactId} + ${project.version} ${project.name} ${project.description} Sebastian Sdorra - ${project.version} ${project.url} diff --git a/scm-core/src/main/java/sonia/scm/plugin/PluginCenter.java b/scm-core/src/main/java/sonia/scm/plugin/PluginCenter.java new file mode 100644 index 0000000000..e1598e0490 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/plugin/PluginCenter.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.plugin; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.Serializable; + +import java.util.HashSet; +import java.util.Set; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * @author Sebastian Sdorra + */ +@XmlRootElement(name = "plugin-center") +@XmlAccessorType(XmlAccessType.FIELD) +public class PluginCenter implements Serializable +{ + + /** Field description */ + private static final long serialVersionUID = -6414175308610267397L; + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public Set getPlugins() + { + return plugins; + } + + /** + * Method description + * + * + * @return + */ + public Set getRepositories() + { + return repositories; + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param plugins + */ + public void setPlugins(Set plugins) + { + this.plugins = plugins; + } + + /** + * Method description + * + * + * @param repositories + */ + public void setRepositories(Set repositories) + { + this.repositories = repositories; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + @XmlElement(name = "plugin") + @XmlElementWrapper(name = "plugins") + private Set plugins = new HashSet(); + + /** Field description */ + @XmlElement(name = "repository") + @XmlElementWrapper(name = "repositories") + private Set repositories = new HashSet(); +} diff --git a/scm-core/src/main/java/sonia/scm/plugin/PluginInformation.java b/scm-core/src/main/java/sonia/scm/plugin/PluginInformation.java index 2f29d870b5..127ce74056 100644 --- a/scm-core/src/main/java/sonia/scm/plugin/PluginInformation.java +++ b/scm-core/src/main/java/sonia/scm/plugin/PluginInformation.java @@ -45,6 +45,17 @@ import javax.xml.bind.annotation.XmlRootElement; public class PluginInformation { + /** + * Method description + * + * + * @return + */ + public String getArtifactId() + { + return artifactId; + } + /** * Method description * @@ -67,6 +78,17 @@ public class PluginInformation return description; } + /** + * Method description + * + * + * @return + */ + public String getGroupId() + { + return groupId; + } + /** * Method description * @@ -102,6 +124,17 @@ public class PluginInformation //~--- set methods ---------------------------------------------------------- + /** + * Method description + * + * + * @param artifactId + */ + public void setArtifactId(String artifactId) + { + this.artifactId = artifactId; + } + /** * Method description * @@ -124,6 +157,17 @@ public class PluginInformation this.description = description; } + /** + * Method description + * + * + * @param groupId + */ + public void setGroupId(String groupId) + { + this.groupId = groupId; + } + /** * Method description * @@ -159,12 +203,18 @@ public class PluginInformation //~--- fields --------------------------------------------------------------- + /** Field description */ + private String artifactId; + /** Field description */ private String author; /** Field description */ private String description; + /** Field description */ + private String groupId; + /** Field description */ private String name; diff --git a/scm-core/src/main/java/sonia/scm/plugin/PluginLoadException.java b/scm-core/src/main/java/sonia/scm/plugin/PluginLoadException.java new file mode 100644 index 0000000000..1c1f4eee36 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/plugin/PluginLoadException.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.plugin; + +/** + * + * @author Sebastian Sdorra + */ +public class PluginLoadException extends RuntimeException +{ + + /** Field description */ + private static final long serialVersionUID = -8683647962850692519L; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + */ + public PluginLoadException() + { + super(); + } + + /** + * Constructs ... + * + * + * @param message + */ + public PluginLoadException(String message) + { + super(message); + } + + /** + * Constructs ... + * + * + * @param cause + */ + public PluginLoadException(Throwable cause) + { + super(cause); + } + + /** + * Constructs ... + * + * + * @param message + * @param cause + */ + public PluginLoadException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/scm-core/src/main/java/sonia/scm/plugin/PluginLoader.java b/scm-core/src/main/java/sonia/scm/plugin/PluginLoader.java new file mode 100644 index 0000000000..f48ecb658a --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/plugin/PluginLoader.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.plugin; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.plugin.ext.ExtensionProcessor; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Collection; + +/** + * + * @author Sebastian Sdorra + */ +public interface PluginLoader +{ + + /** + * Method description + * + * + * @param processor + */ + public void processExtensions(ExtensionProcessor processor); + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public Collection getInstalledPlugins(); +} diff --git a/scm-core/src/main/java/sonia/scm/plugin/PluginManager.java b/scm-core/src/main/java/sonia/scm/plugin/PluginManager.java index 614d6681d2..16c2f81e0f 100644 --- a/scm-core/src/main/java/sonia/scm/plugin/PluginManager.java +++ b/scm-core/src/main/java/sonia/scm/plugin/PluginManager.java @@ -33,14 +33,9 @@ package sonia.scm.plugin; -//~--- non-JDK imports -------------------------------------------------------- - -import com.google.inject.Binder; - //~--- JDK imports ------------------------------------------------------------ import java.util.Collection; -import sonia.scm.plugin.ext.ExtensionProcessor; /** * @@ -53,10 +48,17 @@ public interface PluginManager * Method description * * - * @param binder + * @param id */ - public void processExtensions(ExtensionProcessor processor); + public void install(String id); + /** + * Method description + * + * + * @param id + */ + public void uninstall(String id); //~--- get methods ---------------------------------------------------------- @@ -64,7 +66,25 @@ public interface PluginManager * Method description * * + * @param id + * * @return */ - public Collection getPlugins(); + public PluginInformation get(String id); + + /** + * Method description + * + * + * @return + */ + public Collection getAvailable(); + + /** + * Method description + * + * + * @return + */ + public Collection getInstalled(); } diff --git a/scm-core/src/main/java/sonia/scm/plugin/PluginRepository.java b/scm-core/src/main/java/sonia/scm/plugin/PluginRepository.java new file mode 100644 index 0000000000..3ea5f40186 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/plugin/PluginRepository.java @@ -0,0 +1,196 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.plugin; + +/** + * + * @author Sebastian Sdorra + */ +public class PluginRepository +{ + + /** + * Constructs ... + * + */ + public PluginRepository() {} + + /** + * Constructs ... + * + * + * @param id + * @param url + */ + public PluginRepository(String id, String url) + { + this.id = id; + this.url = url; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param obj + * + * @return + */ + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + final PluginRepository other = (PluginRepository) obj; + + if ((this.id == null) + ? (other.id != null) + : !this.id.equals(other.id)) + { + return false; + } + + if ((this.url == null) + ? (other.url != null) + : !this.url.equals(other.url)) + { + return false; + } + + return true; + } + + /** + * Method description + * + * + * @return + */ + @Override + public int hashCode() + { + int hash = 7; + + hash = 37 * hash + ((this.id != null) + ? this.id.hashCode() + : 0); + hash = 37 * hash + ((this.url != null) + ? this.url.hashCode() + : 0); + + return hash; + } + + /** + * Method description + * + * + * @return + */ + @Override + public String toString() + { + StringBuilder out = new StringBuilder("PluginRepository{id="); + + out.append(id).append(", url=").append(url).append(")"); + + return out.toString(); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public String getId() + { + return id; + } + + /** + * Method description + * + * + * @return + */ + public String getUrl() + { + return url; + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param id + */ + public void setId(String id) + { + this.id = id; + } + + /** + * Method description + * + * + * @param url + */ + public void setUrl(String url) + { + this.url = url; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private String id; + + /** Field description */ + private String url; +} diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index a8ffff0dc9..ac2530eb07 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -58,6 +58,10 @@ stax-api stax + + jaxb-impl + com.sun.xml.bind + diff --git a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java index bc1110604f..c2579095f5 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java @@ -40,8 +40,8 @@ import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.servlet.GuiceServletContextListener; -import sonia.scm.plugin.DefaultPluginManager; -import sonia.scm.plugin.PluginManager; +import sonia.scm.plugin.DefaultPluginLoader; +import sonia.scm.plugin.PluginLoader; import sonia.scm.repository.RepositoryManager; import sonia.scm.store.StoreFactory; import sonia.scm.user.UserManager; @@ -101,13 +101,14 @@ public class ScmContextListener extends GuiceServletContextListener @Override protected Injector getInjector() { - PluginManager manager = new DefaultPluginManager(); + PluginLoader pluginLoader = new DefaultPluginLoader(); BindingExtensionProcessor bindExtProcessor = new BindingExtensionProcessor(); - manager.processExtensions(bindExtProcessor); + pluginLoader.processExtensions(bindExtProcessor); - ScmServletModule main = new ScmServletModule(manager, bindExtProcessor); + ScmServletModule main = new ScmServletModule(pluginLoader, + bindExtProcessor); List moduleList = new ArrayList(bindExtProcessor.getModuleSet()); diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index cab9cf8dec..91763e9b67 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -45,7 +45,9 @@ import sonia.scm.cache.CacheManager; import sonia.scm.cache.EhCacheManager; import sonia.scm.config.ScmConfiguration; import sonia.scm.filter.SecurityFilter; +import sonia.scm.plugin.DefaultPluginManager; import sonia.scm.plugin.Plugin; +import sonia.scm.plugin.PluginLoader; import sonia.scm.plugin.PluginManager; import sonia.scm.plugin.ScriptResourceServlet; import sonia.scm.repository.RepositoryManager; @@ -129,13 +131,13 @@ public class ScmServletModule extends ServletModule * Constructs ... * * - * @param manager + * @param pluginLoader * @param bindExtProcessor */ - ScmServletModule(PluginManager manager, + ScmServletModule(PluginLoader pluginLoader, BindingExtensionProcessor bindExtProcessor) { - this.pluginManager = manager; + this.pluginLoader = pluginLoader; this.bindExtProcessor = bindExtProcessor; } @@ -156,7 +158,8 @@ public class ScmServletModule extends ServletModule bind(StoreFactory.class).to(JAXBStoreFactory.class); bind(ScmConfiguration.class).toInstance(config); - bind(PluginManager.class).toInstance(pluginManager); + bind(PluginLoader.class).toInstance(pluginLoader); + bind(PluginManager.class).to(DefaultPluginManager.class); bind(EncryptionHandler.class).to(MessageDigestEncryptionHandler.class); bindExtProcessor.bindExtensions(binder()); @@ -276,7 +279,7 @@ public class ScmServletModule extends ServletModule packageSet.add(SCMContext.DEFAULT_PACKAGE); - Collection plugins = pluginManager.getPlugins(); + Collection plugins = pluginLoader.getInstalledPlugins(); if (plugins != null) { @@ -341,5 +344,5 @@ public class ScmServletModule extends ServletModule private BindingExtensionProcessor bindExtProcessor; /** Field description */ - private PluginManager pluginManager; + private PluginLoader pluginLoader; } diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AvailablePluginResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AvailablePluginResource.java new file mode 100644 index 0000000000..b3e1e1c887 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AvailablePluginResource.java @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.api.rest.resources; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import sonia.scm.plugin.PluginInformation; +import sonia.scm.plugin.PluginManager; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Collection; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +/** + * + * @author Sebastian Sdorra + */ +@Singleton +@Path("plugins/available") +public class AvailablePluginResource +{ + + /** + * Constructs ... + * + * + * @param pluginManager + */ + @Inject + public AvailablePluginResource(PluginManager pluginManager) + { + this.pluginManager = pluginManager; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @GET + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public PluginInformation[] getAvailablePlugins() + { + Collection pluginCollection = + pluginManager.getAvailable(); + PluginInformation[] plugins = null; + + if (pluginCollection != null) + { + plugins = pluginCollection.toArray(new PluginInformation[0]); + } + else + { + plugins = new PluginInformation[0]; + } + + return plugins; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private PluginManager pluginManager; +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/PluginResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/InstalledPluginResource.java similarity index 81% rename from scm-webapp/src/main/java/sonia/scm/api/rest/resources/PluginResource.java rename to scm-webapp/src/main/java/sonia/scm/api/rest/resources/InstalledPluginResource.java index 99a68b27e1..eecbe39806 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/PluginResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/InstalledPluginResource.java @@ -38,15 +38,12 @@ package sonia.scm.api.rest.resources; import com.google.inject.Inject; import com.google.inject.Singleton; -import sonia.scm.plugin.Plugin; import sonia.scm.plugin.PluginInformation; import sonia.scm.plugin.PluginManager; //~--- JDK imports ------------------------------------------------------------ -import java.util.ArrayList; import java.util.Collection; -import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -58,8 +55,8 @@ import javax.ws.rs.core.MediaType; * @author Sebastian Sdorra */ @Singleton -@Path("plugins") -public class PluginResource +@Path("plugins/installed") +public class InstalledPluginResource { /** @@ -69,25 +66,19 @@ public class PluginResource * @param pluginManager */ @Inject - public PluginResource(PluginManager pluginManager) + public InstalledPluginResource(PluginManager pluginManager) { - Collection pluginCollection = pluginManager.getPlugins(); - List informations = new ArrayList(); + Collection pluginCollection = + pluginManager.getInstalled(); if (pluginCollection != null) { - for (Plugin plugin : pluginCollection) - { - PluginInformation pluginInfo = plugin.getInformation(); - - if (pluginInfo != null) - { - informations.add(pluginInfo); - } - } + plugins = pluginCollection.toArray(new PluginInformation[0]); + } + else + { + plugins = new PluginInformation[0]; } - - plugins = informations.toArray(new PluginInformation[0]); } //~--- get methods ---------------------------------------------------------- diff --git a/scm-webapp/src/main/java/sonia/scm/config/ScmConfiguration.java b/scm-webapp/src/main/java/sonia/scm/config/ScmConfiguration.java index fd54c6ea3c..8f66c6cd69 100644 --- a/scm-webapp/src/main/java/sonia/scm/config/ScmConfiguration.java +++ b/scm-webapp/src/main/java/sonia/scm/config/ScmConfiguration.java @@ -43,6 +43,7 @@ import java.io.File; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; /** @@ -55,6 +56,10 @@ import javax.xml.bind.annotation.XmlRootElement; public class ScmConfiguration { + /** Field description */ + public static final String DEFAULT_PLUGINURL = + "http://plugins.scm-manager.org/plugins.xml"; + /** Field description */ public static final String PATH = "config".concat(File.separator).concat("config.xml"); @@ -74,6 +79,17 @@ public class ScmConfiguration //~--- get methods ---------------------------------------------------------- + /** + * Method description + * + * + * @return + */ + public String getPluginUrl() + { + return pluginUrl; + } + /** * Method description * @@ -87,6 +103,17 @@ public class ScmConfiguration //~--- set methods ---------------------------------------------------------- + /** + * Method description + * + * + * @param pluginUrl + */ + public void setPluginUrl(String pluginUrl) + { + this.pluginUrl = pluginUrl; + } + /** * Method description * @@ -100,6 +127,10 @@ public class ScmConfiguration //~--- fields --------------------------------------------------------------- + /** Field description */ + @XmlElement(name = "plugin-url") + private String pluginUrl = DEFAULT_PLUGINURL; + /** Field description */ private String servername = "localhost"; } diff --git a/scm-core/src/main/java/sonia/scm/plugin/DefaultPluginManager.java b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginLoader.java similarity index 93% rename from scm-core/src/main/java/sonia/scm/plugin/DefaultPluginManager.java rename to scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginLoader.java index e145afec51..bc64b39e23 100644 --- a/scm-core/src/main/java/sonia/scm/plugin/DefaultPluginManager.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginLoader.java @@ -63,15 +63,15 @@ import javax.xml.bind.JAXB; * * @author Sebastian Sdorra */ -public class DefaultPluginManager implements PluginManager +public class DefaultPluginLoader implements PluginLoader { /** Field description */ public static final String PATH_PLUGINCONFIG = "META-INF/scm/plugin.xml"; - /** the logger for DefaultPluginManager */ + /** the logger for DefaultPluginLoader */ private static final Logger logger = - LoggerFactory.getLogger(DefaultPluginManager.class); + LoggerFactory.getLogger(DefaultPluginLoader.class); //~--- constructors --------------------------------------------------------- @@ -79,7 +79,7 @@ public class DefaultPluginManager implements PluginManager * Constructs ... * */ - public DefaultPluginManager() + public DefaultPluginLoader() { ClassLoader classLoader = getClassLoader(); @@ -108,7 +108,7 @@ public class DefaultPluginManager implements PluginManager ClassLoader classLoader = getClassLoader(); JARExtensionScanner scanner = new JARExtensionScanner(); - for (Plugin plugin : plugins) + for (Plugin plugin : installedPlugins) { InputStream input = null; @@ -150,9 +150,9 @@ public class DefaultPluginManager implements PluginManager * @return */ @Override - public Collection getPlugins() + public Collection getInstalledPlugins() { - return plugins; + return installedPlugins; } //~--- methods -------------------------------------------------------------- @@ -204,7 +204,7 @@ public class DefaultPluginManager implements PluginManager Plugin plugin = JAXB.unmarshal(url, Plugin.class); plugin.setPath(path); - plugins.add(plugin); + installedPlugins.add(plugin); } catch (Exception ex) { @@ -235,5 +235,5 @@ public class DefaultPluginManager implements PluginManager //~--- fields --------------------------------------------------------------- /** Field description */ - private Set plugins = new HashSet(); + private Set installedPlugins = new HashSet(); } diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java new file mode 100644 index 0000000000..75c4866992 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java @@ -0,0 +1,249 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.plugin; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sonia.scm.ConfigurationException; +import sonia.scm.cache.CacheManager; +import sonia.scm.cache.SimpleCache; +import sonia.scm.config.ScmConfiguration; + +//~--- JDK imports ------------------------------------------------------------ + +import java.net.URL; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +/** + * + * @author Sebastian Sdorra + */ +@Singleton +public class DefaultPluginManager implements PluginManager +{ + + /** Field description */ + public static final String CACHE_NAME = "sonia.cache.plugins"; + + /** the logger for DefaultPluginManager */ + private static final Logger logger = + LoggerFactory.getLogger(DefaultPluginManager.class); + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * + * @param configuration + * @param pluginLoader + * @param cacheManager + */ + @Inject + public DefaultPluginManager(ScmConfiguration configuration, + PluginLoader pluginLoader, + CacheManager cacheManager) + { + this.configuration = configuration; + this.cache = cacheManager.getSimpleCache(String.class, PluginCenter.class, + CACHE_NAME); + installedPlugins = new HashMap(); + + for (Plugin plugin : pluginLoader.getInstalledPlugins()) + { + PluginInformation info = plugin.getInformation(); + + if (info != null) + { + String id = getPluginId(info); + + installedPlugins.put(id, plugin.getInformation()); + } + } + + try + { + unmarshaller = + JAXBContext.newInstance(PluginCenter.class).createUnmarshaller(); + } + catch (JAXBException ex) + { + throw new ConfigurationException(ex); + } + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param id + */ + @Override + public void install(String id) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Method description + * + * + * @param id + */ + @Override + public void uninstall(String id) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param id + * + * @return + */ + @Override + public PluginInformation get(String id) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Method description + * + * + * @return + */ + @Override + public Collection getAvailable() + { + return getPluginCenter().getPlugins(); + } + + /** + * Method description + * + * + * @return + */ + @Override + public Collection getInstalled() + { + return installedPlugins.values(); + } + + /** + * Method description + * + * + * @return + */ + private PluginCenter getPluginCenter() + { + PluginCenter center = cache.get(PluginCenter.class.getName()); + + if (center == null) + { + if (logger.isInfoEnabled()) + { + logger.info("fetch plugin informations from {}", + configuration.getPluginUrl()); + } + + try + { + center = (PluginCenter) unmarshaller.unmarshal( + new URL(configuration.getPluginUrl())); + cache.put(PluginCenter.class.getName(), center); + } + catch (Exception ex) + { + throw new PluginLoadException(ex); + } + } + + return center; + } + + /** + * Method description + * + * + * @param info + * + * @return + */ + private String getPluginId(PluginInformation info) + { + StringBuilder id = new StringBuilder(info.getGroupId()); + + id.append(":").append(info.getArtifactId()).append(":"); + + return id.append(info.getVersion()).toString(); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private SimpleCache cache; + + /** Field description */ + private ScmConfiguration configuration; + + /** Field description */ + private Map installedPlugins; + + /** Field description */ + private Unmarshaller unmarshaller; +} diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/ScriptResourceServlet.java b/scm-webapp/src/main/java/sonia/scm/plugin/ScriptResourceServlet.java index e9c4a4b41a..b3c7bc5ee1 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/ScriptResourceServlet.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/ScriptResourceServlet.java @@ -74,12 +74,12 @@ public class ScriptResourceServlet extends AbstractResourceServlet * Constructs ... * * - * @param manager + * @param pluginLoader */ @Inject - public ScriptResourceServlet(PluginManager manager) + public ScriptResourceServlet(PluginLoader pluginLoader) { - this.manager = manager; + this.pluginLoader = pluginLoader; } //~--- methods -------------------------------------------------------------- @@ -222,7 +222,7 @@ public class ScriptResourceServlet extends AbstractResourceServlet private Collection getScriptResources() { Set resources = new TreeSet(); - Collection plugins = manager.getPlugins(); + Collection plugins = pluginLoader.getInstalledPlugins(); if (plugins != null) { @@ -238,5 +238,5 @@ public class ScriptResourceServlet extends AbstractResourceServlet //~--- fields --------------------------------------------------------------- /** Field description */ - private PluginManager manager; + private PluginLoader pluginLoader; } diff --git a/scm-webapp/src/main/resources/config/ehcache.xml b/scm-webapp/src/main/resources/config/ehcache.xml index 9387d37ef4..528780bea1 100644 --- a/scm-webapp/src/main/resources/config/ehcache.xml +++ b/scm-webapp/src/main/resources/config/ehcache.xml @@ -108,4 +108,15 @@ diskExpiryThreadIntervalSeconds="2400" /> + + diff --git a/scm-webapp/src/main/webapp/resources/js/sonia.plugin.js b/scm-webapp/src/main/webapp/resources/js/sonia.plugin.js index e6d147d887..1a44029e3d 100644 --- a/scm-webapp/src/main/webapp/resources/js/sonia.plugin.js +++ b/scm-webapp/src/main/webapp/resources/js/sonia.plugin.js @@ -39,7 +39,7 @@ Sonia.plugin.Grid = Ext.extend(Sonia.rest.Grid, { initComponent: function(){ var pluginStore = new Sonia.rest.JsonStore({ - url: restUrl + 'plugins.json', + url: restUrl + 'plugins/installed.json', root: 'plugin-information', fields: [ 'name', 'author', 'description', 'url', 'version' ], sortInfo: {