diff --git a/config/alfresco/public-rest-context.xml b/config/alfresco/public-rest-context.xml
index 45461da251..12de17f01d 100644
--- a/config/alfresco/public-rest-context.xml
+++ b/config/alfresco/public-rest-context.xml
@@ -147,6 +147,8 @@
/> -->
+
+
diff --git a/source/java/org/alfresco/rest/api/model/ModulePackage.java b/source/java/org/alfresco/rest/api/model/ModulePackage.java
new file mode 100644
index 0000000000..e91b309009
--- /dev/null
+++ b/source/java/org/alfresco/rest/api/model/ModulePackage.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ */
+package org.alfresco.rest.api.model;
+
+import org.alfresco.repo.module.ModuleVersionNumber;
+import org.alfresco.service.cmr.module.ModuleDetails;
+import org.alfresco.service.cmr.module.ModuleInstallState;
+import org.alfresco.util.VersionNumber;
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+
+import java.util.Date;
+
+/**
+ * POJO representation of Module Details for Serialization as JSON.
+ * @author Gethin James.
+ */
+public class ModulePackage
+{
+ private final String id;
+ private final String title;
+ private final String description;
+ private final String version;
+ private final Date installDate;
+ private final ModuleInstallState installState;
+ private final String versionMin;
+ private final String versionMax;
+
+ private ModulePackage(ModuleDetails moduleDetails)
+ {
+ this.id = moduleDetails.getId();
+ this.title = moduleDetails.getTitle();
+ this.description = moduleDetails.getDescription();
+ this.version = moduleDetails.getModuleVersionNumber().toString();
+ this.installDate = moduleDetails.getInstallDate();
+ this.installState = moduleDetails.getInstallState();
+ this.versionMin = moduleDetails.getRepoVersionMin().toString();
+ this.versionMax = moduleDetails.getRepoVersionMax().toString();
+ }
+
+ public static ModulePackage fromModuleDetails(ModuleDetails moduleDetails)
+ {
+ try
+ {
+ return new ModulePackage(moduleDetails);
+ }
+ catch (NullPointerException npe)
+ {
+ //Something went wrong with the definition of the Module.
+ //These are just POJO properties, I am unable to represent
+ //the data so will return null
+ return null;
+ }
+ }
+
+ public String getId()
+ {
+ return id;
+ }
+
+ public String getTitle()
+ {
+ return title;
+ }
+
+ public String getDescription()
+ {
+ return description;
+ }
+
+ public String getVersion()
+ {
+ return version;
+ }
+
+ public Date getInstallDate()
+ {
+ return installDate;
+ }
+
+ public ModuleInstallState getInstallState()
+ {
+ return installState;
+ }
+
+ public String getVersionMin()
+ {
+ return versionMin;
+ }
+
+ public String getVersionMax()
+ {
+ return versionMax;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder("ModulePackage{");
+ sb.append("id='").append(id).append('\'');
+ sb.append(", title='").append(title).append('\'');
+ sb.append(", description='").append(description).append('\'');
+ sb.append(", version=").append(version);
+ sb.append(", installDate=").append(installDate);
+ sb.append(", installState=").append(installState);
+ sb.append(", versionMin='").append(versionMin).append('\'');
+ sb.append(", versionMax='").append(versionMax).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+}
+
+
diff --git a/source/java/org/alfresco/rest/api/modules/ModulePackagesEntityResource.java b/source/java/org/alfresco/rest/api/modules/ModulePackagesEntityResource.java
new file mode 100644
index 0000000000..a3b6654ef6
--- /dev/null
+++ b/source/java/org/alfresco/rest/api/modules/ModulePackagesEntityResource.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ */
+package org.alfresco.rest.api.modules;
+
+import org.alfresco.rest.api.model.CustomModel;
+import org.alfresco.rest.api.model.ModulePackage;
+import org.alfresco.rest.api.model.Site;
+import org.alfresco.rest.framework.WebApiDescription;
+import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
+import org.alfresco.rest.framework.resource.EntityResource;
+import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
+import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
+import org.alfresco.rest.framework.resource.parameters.Parameters;
+import org.alfresco.service.cmr.module.ModuleDetails;
+import org.alfresco.service.cmr.module.ModuleService;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Returns Alfresco Module Information.
+ */
+@EntityResource(name="modulepackages", title = "Installed Modules Packages")
+public class ModulePackagesEntityResource implements EntityResourceAction.Read,
+ EntityResourceAction.ReadById
+{
+ @Autowired
+ ModuleService moduleService;
+
+ @Override
+ @WebApiDescription(title="Returns ModulePackage information for the given module.")
+ public ModulePackage readById(String modelName, Parameters parameters) throws EntityNotFoundException
+ {
+ ModuleDetails moduleDetails = moduleService.getModule(modelName);
+ if(moduleDetails == null)
+ {
+ // module does not exist
+ throw new EntityNotFoundException(modelName);
+ }
+ return ModulePackage.fromModuleDetails(moduleDetails);
+ }
+
+ @Override
+ @WebApiDescription(title="Returns a paged list of all Modules.")
+ public CollectionWithPagingInfo readAll(Parameters parameters)
+ {
+ List details = moduleService.getAllModules();
+ if (details!= null && details.size()>0)
+ {
+ List packages = new ArrayList<>(details.size());
+ for (ModuleDetails detail : details)
+ {
+ packages.add(ModulePackage.fromModuleDetails(detail));
+ }
+ return CollectionWithPagingInfo.asPaged(parameters.getPaging(), packages);
+ }
+
+ return CollectionWithPagingInfo.asPaged(parameters.getPaging(), Collections.EMPTY_LIST);
+ }
+}
diff --git a/source/java/org/alfresco/rest/api/modules/package-info.java b/source/java/org/alfresco/rest/api/modules/package-info.java
new file mode 100644
index 0000000000..7cfacd716d
--- /dev/null
+++ b/source/java/org/alfresco/rest/api/modules/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ */
+@WebApi(name="alfresco", scope=Api.SCOPE.PRIVATE, version=1)
+package org.alfresco.rest.api.modules;
+import org.alfresco.rest.framework.Api;
+import org.alfresco.rest.framework.WebApi;
diff --git a/source/test-java/org/alfresco/remoteapi/AllUnitTestsSuite.java b/source/test-java/org/alfresco/remoteapi/AllUnitTestsSuite.java
index baa8faf2b7..1abe288c7e 100644
--- a/source/test-java/org/alfresco/remoteapi/AllUnitTestsSuite.java
+++ b/source/test-java/org/alfresco/remoteapi/AllUnitTestsSuite.java
@@ -12,6 +12,7 @@ import org.alfresco.repo.webdav.LockInfoImplTest;
import org.alfresco.repo.webdav.RenameShuffleDetectionTest;
import org.alfresco.repo.webdav.WebDAVHelperTest;
import org.alfresco.repo.webdav.WebDAVLockServiceImplTest;
+import org.alfresco.rest.api.tests.ModulePackageTest;
import org.alfresco.rest.framework.tests.core.AllRestFrameworkTest;
import org.alfresco.rest.framework.tests.metadata.WriterTests;
@@ -41,6 +42,7 @@ public class AllUnitTestsSuite extends TestSuite
{
suite.addTest(new JUnit4TestAdapter(AllRestFrameworkTest.class));
suite.addTest(new JUnit4TestAdapter(WriterTests.class));
+ suite.addTest(new JUnit4TestAdapter(ModulePackageTest.class));
}
static void webdavTests(TestSuite suite)
diff --git a/source/test-java/org/alfresco/rest/api/tests/ModulePackageTest.java b/source/test-java/org/alfresco/rest/api/tests/ModulePackageTest.java
new file mode 100644
index 0000000000..da56ad7183
--- /dev/null
+++ b/source/test-java/org/alfresco/rest/api/tests/ModulePackageTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ */
+package org.alfresco.rest.api.tests;
+
+import static org.junit.Assert.*;
+
+import org.alfresco.repo.module.ModuleDetailsImpl;
+import org.alfresco.repo.module.ModuleDetailsImplTest;
+import org.alfresco.rest.api.model.ModulePackage;
+import org.alfresco.service.cmr.module.ModuleDetails;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * Basic tests for taking ModuleDetailsImpl and representing it as a ModulePackage class.
+ * @author Gethin James.
+ */
+public class ModulePackageTest
+{
+ static Properties props = ModuleDetailsImplTest.DEFAULT_PROPS;
+
+ @Test
+ public void testConstructor() throws IOException
+ {
+ ModuleDetails details = new ModuleDetailsImpl(props);
+ ModulePackage modulePackage = ModulePackage.fromModuleDetails(details);
+ assertNotNull(modulePackage);
+ assertEquals(props.getProperty(ModuleDetails.PROP_ID), modulePackage.getId());
+ assertEquals(props.getProperty(ModuleDetails.PROP_VERSION),modulePackage.getVersion());
+ assertEquals(props.getProperty(ModuleDetails.PROP_REPO_VERSION_MIN),modulePackage.getVersionMin());
+ assertEquals(props.getProperty(ModuleDetails.PROP_REPO_VERSION_MAX),modulePackage.getVersionMax());
+ assertEquals(props.getProperty(ModuleDetails.PROP_INSTALL_STATE),modulePackage.getInstallState().toString());
+ }
+
+ @Test
+ public void testInvalidConstructor() throws IOException
+ {
+ ModulePackage modulePackage = ModulePackage.fromModuleDetails(null);
+ assertNull(modulePackage);
+ }
+}