mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-11 07:55:47 +01:00
use jaxb to parse plugin descriptor
This commit is contained in:
@@ -36,6 +36,7 @@ package sonia.scm.plugin;
|
|||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
@@ -165,6 +166,11 @@ public final class Plugin extends ScmModule
|
|||||||
*/
|
*/
|
||||||
public Set<String> getDependencies()
|
public Set<String> getDependencies()
|
||||||
{
|
{
|
||||||
|
if (dependencies == null)
|
||||||
|
{
|
||||||
|
dependencies = ImmutableSet.of();
|
||||||
|
}
|
||||||
|
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,17 +39,8 @@ package sonia.scm.plugin;
|
|||||||
public interface PluginConstants
|
public interface PluginConstants
|
||||||
{
|
{
|
||||||
|
|
||||||
/** descriptor xml element artifactId */
|
/** Field description */
|
||||||
public static final String EL_ARTIFACTID = "artifactId";
|
public static final String ID_DELIMITER = ":";
|
||||||
|
|
||||||
/** descriptor xml element dependency */
|
|
||||||
public static final String EL_DEPENDENCY = "dependency";
|
|
||||||
|
|
||||||
/** descriptor xml element groupId */
|
|
||||||
public static final String EL_GROUPID = "groupId";
|
|
||||||
|
|
||||||
/** descriptor xml element version */
|
|
||||||
public static final String EL_VERSION = "version";
|
|
||||||
|
|
||||||
/** checksum file */
|
/** checksum file */
|
||||||
public static final String FILE_CHECKSUM = "checksum";
|
public static final String FILE_CHECKSUM = "checksum";
|
||||||
|
|||||||
@@ -33,38 +33,53 @@ package sonia.scm.plugin;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.io.ByteSource;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
|
||||||
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import javax.xml.bind.JAXBContext;
|
||||||
|
import javax.xml.bind.JAXBException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Id of a plugin. The id of a plugin consists of the groupId, artifactId and
|
* Util methods to handle plugins.
|
||||||
* the version of the plugin.
|
|
||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
public final class PluginId
|
public final class Plugins
|
||||||
{
|
{
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private static final String DELIMITER = ":";
|
private static JAXBContext context;
|
||||||
|
|
||||||
|
//~--- static initializers --------------------------------------------------
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
context = JAXBContext.newInstance(Plugin.class, ScmModule.class);
|
||||||
|
}
|
||||||
|
catch (JAXBException ex)
|
||||||
|
{
|
||||||
|
throw new PluginException("could not create jaxb context", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//~--- constructors ---------------------------------------------------------
|
//~--- constructors ---------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs ...
|
* Constructs ...
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @param groupId
|
|
||||||
* @param artifactId
|
|
||||||
* @param version
|
|
||||||
*/
|
*/
|
||||||
public PluginId(String groupId, String artifactId, String version)
|
private Plugins() {}
|
||||||
{
|
|
||||||
this.groupId = groupId;
|
|
||||||
this.artifactId = artifactId;
|
|
||||||
this.version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
//~--- methods --------------------------------------------------------------
|
||||||
|
|
||||||
@@ -72,119 +87,42 @@ public final class PluginId
|
|||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param obj
|
* @param path
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
public static Plugin parsePluginDescriptor(Path path)
|
||||||
public boolean equals(Object obj)
|
|
||||||
{
|
{
|
||||||
if (obj == null)
|
return parsePluginDescriptor(Files.asByteSource(path.toFile()));
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getClass() != obj.getClass())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final PluginId other = (PluginId) obj;
|
|
||||||
|
|
||||||
return Objects.equal(this.groupId, other.groupId)
|
|
||||||
&& Objects.equal(this.artifactId, other.artifactId)
|
|
||||||
&& Objects.equal(this.version, other.version);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @return
|
* @param data
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int hashCode()
|
|
||||||
{
|
|
||||||
return Objects.hashCode(groupId, artifactId, version);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
public static Plugin parsePluginDescriptor(ByteSource data)
|
||||||
public String toString()
|
|
||||||
{
|
{
|
||||||
return Joiner.on(DELIMITER).join(groupId, artifactId, version);
|
Preconditions.checkNotNull(data, "data parameter is required");
|
||||||
}
|
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
Plugin plugin;
|
||||||
|
|
||||||
/**
|
try (InputStream stream = data.openStream())
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getArtifactId()
|
|
||||||
{
|
{
|
||||||
return artifactId;
|
plugin = (Plugin) context.createUnmarshaller().unmarshal(stream);
|
||||||
}
|
}
|
||||||
|
catch (JAXBException ex)
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getGroupId()
|
|
||||||
{
|
{
|
||||||
return groupId;
|
throw new PluginLoadException("could not parse plugin descriptor", ex);
|
||||||
}
|
}
|
||||||
|
catch (IOException ex)
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getId()
|
|
||||||
{
|
{
|
||||||
return toString();
|
throw new PluginLoadException("could not read plugin descriptor", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return plugin;
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getIdWithoutVersion()
|
|
||||||
{
|
|
||||||
return Joiner.on(DELIMITER).join(groupId, artifactId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getVersion()
|
|
||||||
{
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private final String artifactId;
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private final String groupId;
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private final String version;
|
|
||||||
}
|
}
|
||||||
@@ -35,18 +35,12 @@ package sonia.scm.plugin;
|
|||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
import com.google.common.io.ByteSource;
|
import com.google.common.io.ByteSource;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.common.io.Resources;
|
import com.google.common.io.Resources;
|
||||||
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
|
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
|
|
||||||
import sonia.scm.util.IOUtil;
|
import sonia.scm.util.IOUtil;
|
||||||
import sonia.scm.util.XmlUtil;
|
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
@@ -60,12 +54,9 @@ import java.net.URL;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Smp plugin archive.
|
* Smp plugin archive.
|
||||||
*
|
*
|
||||||
@@ -74,7 +65,6 @@ import javax.xml.parsers.ParserConfigurationException;
|
|||||||
*/
|
*/
|
||||||
public final class SmpArchive
|
public final class SmpArchive
|
||||||
{
|
{
|
||||||
//~--- constructors ---------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs ...
|
* Constructs ...
|
||||||
@@ -163,30 +153,6 @@ public final class SmpArchive
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param map
|
|
||||||
* @param key
|
|
||||||
* @param <K>
|
|
||||||
* @param <V>
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static <K, V> V getSingleValue(Multimap<K, V> map, K key)
|
|
||||||
{
|
|
||||||
V value = null;
|
|
||||||
Collection<V> values = map.get(key);
|
|
||||||
|
|
||||||
if (!values.isEmpty())
|
|
||||||
{
|
|
||||||
value = values.iterator().next();
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
//~--- methods --------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -240,39 +206,39 @@ public final class SmpArchive
|
|||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public Document getDescriptorDocument() throws IOException
|
public Plugin getPlugin() throws IOException
|
||||||
{
|
{
|
||||||
if (descriptorDocument == null)
|
if (plugin == null)
|
||||||
{
|
{
|
||||||
try
|
plugin = createPlugin();
|
||||||
|
|
||||||
|
PluginInformation info = plugin.getInformation();
|
||||||
|
|
||||||
|
if (info == null)
|
||||||
{
|
{
|
||||||
descriptorDocument = createDescriptorDocument();
|
throw new PluginException("could not find information section");
|
||||||
}
|
}
|
||||||
catch (ParserConfigurationException | SAXException ex)
|
|
||||||
|
if (Strings.isNullOrEmpty(info.getGroupId()))
|
||||||
{
|
{
|
||||||
throw new PluginException("could not parse descriptor", ex);
|
throw new PluginException(
|
||||||
|
"could not find groupId in plugin descriptor");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Strings.isNullOrEmpty(info.getArtifactId()))
|
||||||
|
{
|
||||||
|
throw new PluginException(
|
||||||
|
"could not find artifactId in plugin descriptor");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Strings.isNullOrEmpty(info.getVersion()))
|
||||||
|
{
|
||||||
|
throw new PluginException(
|
||||||
|
"could not find version in plugin descriptor");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptorDocument;
|
return plugin;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public PluginId getPluginId() throws IOException
|
|
||||||
{
|
|
||||||
if (pluginId == null)
|
|
||||||
{
|
|
||||||
pluginId = createPluginId();
|
|
||||||
}
|
|
||||||
|
|
||||||
return pluginId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
//~--- methods --------------------------------------------------------------
|
||||||
@@ -281,17 +247,13 @@ public final class SmpArchive
|
|||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @return
|
* @return
|
||||||
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws ParserConfigurationException
|
|
||||||
* @throws SAXException
|
|
||||||
*/
|
*/
|
||||||
private Document createDescriptorDocument()
|
private Plugin createPlugin() throws IOException
|
||||||
throws IOException, ParserConfigurationException, SAXException
|
|
||||||
{
|
{
|
||||||
Document doc = null;
|
Plugin p = null;
|
||||||
|
|
||||||
NonClosingZipInputStream zis = null;
|
NonClosingZipInputStream zis = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -304,7 +266,7 @@ public final class SmpArchive
|
|||||||
{
|
{
|
||||||
if (PluginConstants.PATH_DESCRIPTOR.equals(getPath(entry)))
|
if (PluginConstants.PATH_DESCRIPTOR.equals(getPath(entry)))
|
||||||
{
|
{
|
||||||
doc = XmlUtil.createDocument(zis);
|
p = Plugins.parsePluginDescriptor(new InputStreamByteSource(zis));
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = zis.getNextEntry();
|
entry = zis.getNextEntry();
|
||||||
@@ -320,56 +282,12 @@ public final class SmpArchive
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doc == null)
|
if (p == null)
|
||||||
{
|
{
|
||||||
throw new PluginException("could not find descritor");
|
throw new PluginLoadException("could not find plugin descriptor");
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc;
|
return p;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private PluginId createPluginId() throws IOException
|
|
||||||
{
|
|
||||||
//J-
|
|
||||||
Multimap<String, String> entries = XmlUtil.values(
|
|
||||||
getDescriptorDocument(),
|
|
||||||
PluginConstants.EL_GROUPID,
|
|
||||||
PluginConstants.EL_ARTIFACTID,
|
|
||||||
PluginConstants.EL_VERSION
|
|
||||||
);
|
|
||||||
//J+
|
|
||||||
|
|
||||||
String groupId = getSingleValue(entries, PluginConstants.EL_GROUPID);
|
|
||||||
|
|
||||||
if (Strings.isNullOrEmpty(groupId))
|
|
||||||
{
|
|
||||||
throw new PluginException("could not find groupId in plugin descriptor");
|
|
||||||
}
|
|
||||||
|
|
||||||
String artifactId = getSingleValue(entries, PluginConstants.EL_ARTIFACTID);
|
|
||||||
|
|
||||||
if (Strings.isNullOrEmpty(artifactId))
|
|
||||||
{
|
|
||||||
throw new PluginException(
|
|
||||||
"could not find artifactId in plugin descriptor ");
|
|
||||||
}
|
|
||||||
|
|
||||||
String version = getSingleValue(entries, PluginConstants.EL_VERSION);
|
|
||||||
|
|
||||||
if (Strings.isNullOrEmpty(version))
|
|
||||||
{
|
|
||||||
throw new PluginException("could not find version in plugin descriptor ");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PluginId(groupId, artifactId, version);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -400,6 +318,50 @@ public final class SmpArchive
|
|||||||
|
|
||||||
//~--- inner classes --------------------------------------------------------
|
//~--- inner classes --------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @version Enter version here..., 14/07/13
|
||||||
|
* @author Enter your name here...
|
||||||
|
*/
|
||||||
|
private static class InputStreamByteSource extends ByteSource
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs ...
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param input
|
||||||
|
*/
|
||||||
|
public InputStreamByteSource(InputStream input)
|
||||||
|
{
|
||||||
|
this.input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
//~--- methods ------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public InputStream openStream() throws IOException
|
||||||
|
{
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
//~--- fields -------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
private final InputStream input;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class description
|
* Class description
|
||||||
*
|
*
|
||||||
@@ -456,8 +418,5 @@ public final class SmpArchive
|
|||||||
private final ByteSource archive;
|
private final ByteSource archive;
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private Document descriptorDocument;
|
private Plugin plugin;
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private PluginId pluginId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,31 +110,20 @@ public class SmpArchiveTest
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetDescriptorDocument() throws IOException
|
public void testGetPlugin() throws IOException
|
||||||
{
|
{
|
||||||
File archive = createArchive("sonia.sample", "sample", "1.0");
|
File archive = createArchive("sonia.sample", "sample", "1.0");
|
||||||
Document doc = SmpArchive.create(archive).getDescriptorDocument();
|
Plugin plugin = SmpArchive.create(archive).getPlugin();
|
||||||
|
|
||||||
assertNotNull(doc);
|
assertNotNull(plugin);
|
||||||
assertEquals("plugin", doc.getDocumentElement().getNodeName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
PluginInformation info = plugin.getInformation();
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testGetPluginId() throws IOException
|
|
||||||
{
|
|
||||||
File archive = createArchive("sonia.sample", "sample", "1.0");
|
|
||||||
PluginId pluginId = SmpArchive.create(archive).getPluginId();
|
|
||||||
|
|
||||||
assertNotNull(pluginId);
|
assertNotNull(info);
|
||||||
assertEquals("sonia.sample", pluginId.getGroupId());
|
|
||||||
assertEquals("sample", pluginId.getArtifactId());
|
assertEquals("sonia.sample", info.getGroupId());
|
||||||
assertEquals("1.0", pluginId.getVersion());
|
assertEquals("sample", info.getArtifactId());
|
||||||
|
assertEquals("1.0", info.getVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -147,7 +136,7 @@ public class SmpArchiveTest
|
|||||||
{
|
{
|
||||||
File archive = createArchive("sonia.sample", null, "1.0");
|
File archive = createArchive("sonia.sample", null, "1.0");
|
||||||
|
|
||||||
SmpArchive.create(archive).getPluginId();
|
SmpArchive.create(archive).getPlugin();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,7 +149,7 @@ public class SmpArchiveTest
|
|||||||
{
|
{
|
||||||
File archive = createArchive(null, "sample", "1.0");
|
File archive = createArchive(null, "sample", "1.0");
|
||||||
|
|
||||||
SmpArchive.create(archive).getPluginId();
|
SmpArchive.create(archive).getPlugin();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -173,7 +162,7 @@ public class SmpArchiveTest
|
|||||||
{
|
{
|
||||||
File archive = createArchive("sonia.sample", "sample", null);
|
File archive = createArchive("sonia.sample", "sample", null);
|
||||||
|
|
||||||
SmpArchive.create(archive).getPluginId();
|
SmpArchive.create(archive).getPlugin();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import sonia.scm.SCMContext;
|
import sonia.scm.SCMContext;
|
||||||
import sonia.scm.ScmContextListener;
|
import sonia.scm.ScmContextListener;
|
||||||
|
import sonia.scm.plugin.Plugin;
|
||||||
import sonia.scm.plugin.PluginException;
|
import sonia.scm.plugin.PluginException;
|
||||||
import sonia.scm.plugin.PluginId;
|
|
||||||
import sonia.scm.plugin.PluginLoadException;
|
import sonia.scm.plugin.PluginLoadException;
|
||||||
import sonia.scm.plugin.PluginWrapper;
|
import sonia.scm.plugin.PluginWrapper;
|
||||||
import sonia.scm.plugin.Plugins;
|
import sonia.scm.plugin.PluginsInternal;
|
||||||
import sonia.scm.plugin.SmpArchive;
|
import sonia.scm.plugin.SmpArchive;
|
||||||
import sonia.scm.util.ClassLoaders;
|
import sonia.scm.util.ClassLoaders;
|
||||||
import sonia.scm.util.IOUtil;
|
import sonia.scm.util.IOUtil;
|
||||||
@@ -152,7 +152,7 @@ public class BootstrapContextListener implements ServletContextListener
|
|||||||
ClassLoader cl =
|
ClassLoader cl =
|
||||||
ClassLoaders.getContextClassLoader(BootstrapContextListener.class);
|
ClassLoaders.getContextClassLoader(BootstrapContextListener.class);
|
||||||
|
|
||||||
Set<PluginWrapper> plugins = Plugins.collectPlugins(cl,
|
Set<PluginWrapper> plugins = PluginsInternal.collectPlugins(cl,
|
||||||
pluginDirectory.toPath());
|
pluginDirectory.toPath());
|
||||||
|
|
||||||
contextListener = new ScmContextListener(cl, plugins);
|
contextListener = new ScmContextListener(cl, plugins);
|
||||||
@@ -182,23 +182,24 @@ public class BootstrapContextListener implements ServletContextListener
|
|||||||
{
|
{
|
||||||
URL url = context.getResource(PLUGIN_DIRECTORY.concat(entry.getName()));
|
URL url = context.getResource(PLUGIN_DIRECTORY.concat(entry.getName()));
|
||||||
SmpArchive archive = SmpArchive.create(url);
|
SmpArchive archive = SmpArchive.create(url);
|
||||||
PluginId id = archive.getPluginId();
|
Plugin plugin = archive.getPlugin();
|
||||||
|
|
||||||
File directory = Plugins.createPluginDirectory(pluginDirectory, id);
|
File directory = PluginsInternal.createPluginDirectory(pluginDirectory,
|
||||||
File checksumFile = Plugins.getChecksumFile(directory);
|
plugin);
|
||||||
|
File checksumFile = PluginsInternal.getChecksumFile(directory);
|
||||||
|
|
||||||
if (!directory.exists())
|
if (!directory.exists())
|
||||||
{
|
{
|
||||||
logger.warn("install plugin {}", id);
|
logger.warn("install plugin {}", plugin.getInformation().getId());
|
||||||
Plugins.extract(archive, entry.getChecksum(), directory, checksumFile,
|
PluginsInternal.extract(archive, entry.getChecksum(), directory,
|
||||||
true);
|
checksumFile, true);
|
||||||
}
|
}
|
||||||
else if (!checksumFile.exists())
|
else if (!checksumFile.exists())
|
||||||
{
|
{
|
||||||
logger.warn("plugin directory {} exists without checksum file.",
|
logger.warn("plugin directory {} exists without checksum file.",
|
||||||
directory);
|
directory);
|
||||||
Plugins.extract(archive, entry.getChecksum(), directory, checksumFile,
|
PluginsInternal.extract(archive, entry.getChecksum(), directory,
|
||||||
true);
|
checksumFile, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -206,13 +207,15 @@ public class BootstrapContextListener implements ServletContextListener
|
|||||||
|
|
||||||
if (checksum.equals(entry.getChecksum()))
|
if (checksum.equals(entry.getChecksum()))
|
||||||
{
|
{
|
||||||
logger.debug("plugin {} is up to date", id);
|
logger.debug("plugin {} is up to date",
|
||||||
|
plugin.getInformation().getId());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.warn("checksum mismatch of pluing {}, start update", id);
|
logger.warn("checksum mismatch of pluing {}, start update",
|
||||||
Plugins.extract(archive, entry.getChecksum(), directory, checksumFile,
|
plugin.getInformation().getId());
|
||||||
true);
|
PluginsInternal.extract(archive, entry.getChecksum(), directory,
|
||||||
|
checksumFile, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class DefaultPluginLoader implements PluginLoader
|
|||||||
Builder<Plugin> builder = ImmutableSet.builder();
|
Builder<Plugin> builder = ImmutableSet.builder();
|
||||||
|
|
||||||
builder.addAll(ips);
|
builder.addAll(ips);
|
||||||
builder.addAll(Plugins.unwrap(wrappedPlugins));
|
builder.addAll(PluginsInternal.unwrap(wrappedPlugins));
|
||||||
plugins = builder.build();
|
plugins = builder.build();
|
||||||
|
|
||||||
appendExtensions(multiple, single, extensions, modules);
|
appendExtensions(multiple, single, extensions, modules);
|
||||||
|
|||||||
@@ -34,20 +34,14 @@ package sonia.scm.plugin;
|
|||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
|
|
||||||
import sonia.scm.util.Util;
|
|
||||||
import sonia.scm.util.XmlUtil;
|
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -56,8 +50,6 @@ import java.util.Collection;
|
|||||||
public final class ExplodedSmp implements Comparable<ExplodedSmp>
|
public final class ExplodedSmp implements Comparable<ExplodedSmp>
|
||||||
{
|
{
|
||||||
|
|
||||||
//~--- constructors ---------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs ...
|
* Constructs ...
|
||||||
*
|
*
|
||||||
@@ -65,12 +57,12 @@ public final class ExplodedSmp implements Comparable<ExplodedSmp>
|
|||||||
* @param path
|
* @param path
|
||||||
* @param pluginId
|
* @param pluginId
|
||||||
* @param dependencies
|
* @param dependencies
|
||||||
|
* @param plugin
|
||||||
*/
|
*/
|
||||||
ExplodedSmp(Path path, PluginId pluginId, Collection<String> dependencies)
|
ExplodedSmp(Path path, Plugin plugin)
|
||||||
{
|
{
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.pluginId = pluginId;
|
this.plugin = plugin;
|
||||||
this.dependencies = dependencies;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
//~--- methods --------------------------------------------------------------
|
||||||
@@ -87,35 +79,9 @@ public final class ExplodedSmp implements Comparable<ExplodedSmp>
|
|||||||
*/
|
*/
|
||||||
public static ExplodedSmp create(Path directory) throws IOException
|
public static ExplodedSmp create(Path directory) throws IOException
|
||||||
{
|
{
|
||||||
ExplodedSmp smp;
|
Path desc = directory.resolve(PluginConstants.FILE_DESCRIPTOR);
|
||||||
|
|
||||||
Path descriptor = directory.resolve(PluginConstants.FILE_DESCRIPTOR);
|
return new ExplodedSmp(directory, Plugins.parsePluginDescriptor(desc));
|
||||||
|
|
||||||
try (InputStream in = Files.newInputStream(descriptor))
|
|
||||||
{
|
|
||||||
//J-
|
|
||||||
Multimap<String,String> values = XmlUtil.values(in,
|
|
||||||
PluginConstants.EL_GROUPID,
|
|
||||||
PluginConstants.EL_ARTIFACTID,
|
|
||||||
PluginConstants.EL_VERSION,
|
|
||||||
PluginConstants.EL_DEPENDENCY
|
|
||||||
);
|
|
||||||
|
|
||||||
PluginId pluginId = new PluginId(
|
|
||||||
Util.getFirst(values, PluginConstants.EL_GROUPID),
|
|
||||||
Util.getFirst(values, PluginConstants.EL_ARTIFACTID),
|
|
||||||
Util.getFirst(values, PluginConstants.EL_VERSION)
|
|
||||||
);
|
|
||||||
|
|
||||||
smp = new ExplodedSmp(
|
|
||||||
directory,
|
|
||||||
pluginId,
|
|
||||||
values.get(PluginConstants.EL_DEPENDENCY)
|
|
||||||
);
|
|
||||||
//J+
|
|
||||||
}
|
|
||||||
|
|
||||||
return smp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -131,24 +97,27 @@ public final class ExplodedSmp implements Comparable<ExplodedSmp>
|
|||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (dependencies.isEmpty() && o.dependencies.isEmpty())
|
Set<String> depends = plugin.getDependencies();
|
||||||
|
Set<String> odepends = o.plugin.getDependencies();
|
||||||
|
|
||||||
|
if (depends.isEmpty() && odepends.isEmpty())
|
||||||
{
|
{
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
else if (dependencies.isEmpty() &&!o.dependencies.isEmpty())
|
else if (depends.isEmpty() &&!odepends.isEmpty())
|
||||||
{
|
{
|
||||||
result = -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
else if (!dependencies.isEmpty() && o.dependencies.isEmpty())
|
else if (!depends.isEmpty() && odepends.isEmpty())
|
||||||
{
|
{
|
||||||
result = 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String id = pluginId.getIdWithoutVersion();
|
String id = plugin.getInformation().getId(false);
|
||||||
String oid = o.pluginId.getIdWithoutVersion();
|
String oid = o.plugin.getInformation().getId(false);
|
||||||
|
|
||||||
if (dependencies.contains(oid) && o.dependencies.contains(id))
|
if (depends.contains(oid) && odepends.contains(id))
|
||||||
{
|
{
|
||||||
StringBuilder b = new StringBuilder("circular dependency detected: ");
|
StringBuilder b = new StringBuilder("circular dependency detected: ");
|
||||||
|
|
||||||
@@ -157,11 +126,11 @@ public final class ExplodedSmp implements Comparable<ExplodedSmp>
|
|||||||
|
|
||||||
throw new PluginCircularDependencyException(b.toString());
|
throw new PluginCircularDependencyException(b.toString());
|
||||||
}
|
}
|
||||||
else if (dependencies.contains(oid))
|
else if (depends.contains(oid))
|
||||||
{
|
{
|
||||||
result = 999;
|
result = 999;
|
||||||
}
|
}
|
||||||
else if (o.dependencies.contains(id))
|
else if (odepends.contains(id))
|
||||||
{
|
{
|
||||||
result = -999;
|
result = -999;
|
||||||
}
|
}
|
||||||
@@ -176,17 +145,6 @@ public final class ExplodedSmp implements Comparable<ExplodedSmp>
|
|||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
//~--- get methods ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Collection<String> getDependencies()
|
|
||||||
{
|
|
||||||
return dependencies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
@@ -204,9 +162,9 @@ public final class ExplodedSmp implements Comparable<ExplodedSmp>
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public PluginId getPluginId()
|
public Plugin getPlugin()
|
||||||
{
|
{
|
||||||
return pluginId;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- inner classes --------------------------------------------------------
|
//~--- inner classes --------------------------------------------------------
|
||||||
@@ -246,12 +204,9 @@ public final class ExplodedSmp implements Comparable<ExplodedSmp>
|
|||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
//~--- fields ---------------------------------------------------------------
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
private final Collection<String> dependencies;
|
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private final Path path;
|
private final Path path;
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private final PluginId pluginId;
|
private final Plugin plugin;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -451,16 +451,17 @@ public final class PluginProcessor
|
|||||||
|
|
||||||
SmpArchive smp = SmpArchive.create(archive);
|
SmpArchive smp = SmpArchive.create(archive);
|
||||||
|
|
||||||
logger.debug("extract plugin {}", smp.getPluginId());
|
logger.debug("extract plugin {}", smp.getPlugin());
|
||||||
|
|
||||||
File directory = Plugins.createPluginDirectory(pluginDirectory.toFile(),
|
File directory =
|
||||||
smp.getPluginId());
|
PluginsInternal.createPluginDirectory(pluginDirectory.toFile(),
|
||||||
|
smp.getPlugin());
|
||||||
|
|
||||||
String checksum = com.google.common.io.Files.hash(archiveFile,
|
String checksum = com.google.common.io.Files.hash(archiveFile,
|
||||||
Hashing.sha256()).toString();
|
Hashing.sha256()).toString();
|
||||||
File checksumFile = Plugins.getChecksumFile(directory);
|
File checksumFile = PluginsInternal.getChecksumFile(directory);
|
||||||
|
|
||||||
Plugins.extract(smp, checksum, directory, checksumFile, false);
|
PluginsInternal.extract(smp, checksum, directory, checksumFile, false);
|
||||||
moveArchive(archive);
|
moveArchive(archive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,13 +56,14 @@ import java.util.Set;
|
|||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
*/
|
*/
|
||||||
public final class Plugins
|
public final class PluginsInternal
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the logger for Plugins
|
* the logger for PluginsInternal
|
||||||
*/
|
*/
|
||||||
private static final Logger logger = LoggerFactory.getLogger(Plugins.class);
|
private static final Logger logger =
|
||||||
|
LoggerFactory.getLogger(PluginsInternal.class);
|
||||||
|
|
||||||
//~--- constructors ---------------------------------------------------------
|
//~--- constructors ---------------------------------------------------------
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ public final class Plugins
|
|||||||
* Constructs ...
|
* Constructs ...
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private Plugins() {}
|
private PluginsInternal() {}
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
//~--- methods --------------------------------------------------------------
|
||||||
|
|
||||||
@@ -99,13 +100,15 @@ public final class Plugins
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param parent
|
* @param parent
|
||||||
* @param id
|
* @param plugin
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static File createPluginDirectory(File parent, PluginId id)
|
public static File createPluginDirectory(File parent, Plugin plugin)
|
||||||
{
|
{
|
||||||
return new File(new File(parent, id.getGroupId()), id.getArtifactId());
|
PluginInformation info = plugin.getInformation();
|
||||||
|
|
||||||
|
return new File(new File(parent, info.getGroupId()), info.getArtifactId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,13 +130,14 @@ public final class Plugins
|
|||||||
if (directory.exists())
|
if (directory.exists())
|
||||||
{
|
{
|
||||||
logger.debug("delete directory {} for plugin extraction",
|
logger.debug("delete directory {} for plugin extraction",
|
||||||
archive.getPluginId());
|
archive.getPlugin().getInformation().getId(false));
|
||||||
IOUtil.delete(directory);
|
IOUtil.delete(directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
IOUtil.mkdirs(directory);
|
IOUtil.mkdirs(directory);
|
||||||
|
|
||||||
logger.debug("extract plugin {}", archive.getPluginId());
|
logger.debug("extract plugin {}",
|
||||||
|
archive.getPlugin().getInformation().getId(false));
|
||||||
archive.extract(directory);
|
archive.extract(directory);
|
||||||
Files.write(checksum, checksumFile, Charsets.UTF_8);
|
Files.write(checksum, checksumFile, Charsets.UTF_8);
|
||||||
|
|
||||||
@@ -37,6 +37,8 @@ import com.google.common.collect.Lists;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.mockito.internal.util.collections.Sets;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
@@ -127,8 +129,15 @@ public class ExplodedSmpTest
|
|||||||
private ExplodedSmp create(String groupId, String artifactId, String version,
|
private ExplodedSmp create(String groupId, String artifactId, String version,
|
||||||
String... dependencies)
|
String... dependencies)
|
||||||
{
|
{
|
||||||
return new ExplodedSmp(null, new PluginId(groupId, artifactId, version),
|
PluginInformation info = new PluginInformation();
|
||||||
Lists.newArrayList(dependencies));
|
|
||||||
|
info.setGroupId(groupId);
|
||||||
|
info.setArtifactId(artifactId);
|
||||||
|
info.setVersion(version);
|
||||||
|
|
||||||
|
Plugin plugin = new Plugin(info, null, null, Sets.newSet(dependencies));
|
||||||
|
|
||||||
|
return new ExplodedSmp(null, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,6 +169,6 @@ public class ExplodedSmpTest
|
|||||||
*/
|
*/
|
||||||
private void is(List<ExplodedSmp> es, int p, String a)
|
private void is(List<ExplodedSmp> es, int p, String a)
|
||||||
{
|
{
|
||||||
assertEquals(a, es.get(p).getPluginId().getArtifactId());
|
assertEquals(a, es.get(p).getPlugin().getInformation().getArtifactId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user