Skip to content

Commit

Permalink
Enable installation of modules through rest calls
Browse files Browse the repository at this point in the history
  • Loading branch information
Male Michael committed Dec 21, 2017
1 parent 4f9abc0 commit 37ac262
Show file tree
Hide file tree
Showing 3 changed files with 305 additions and 0 deletions.
@@ -0,0 +1,154 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
*
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
* graphic logo is a trademark of OpenMRS Inc.
*/
package org.openmrs.module.webservices.rest.web.v1_0.resource.openmrs1_8;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import javax.servlet.ServletContext;
import org.springframework.util.ResourceUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.openmrs.module.Module;
import org.openmrs.module.ModuleUtil;
import org.openmrs.module.webservices.helper.ModuleInstall;
import org.openmrs.module.webservices.helper.ModuleFactoryWrapper;
import org.openmrs.module.webservices.rest.SimpleObject;
import org.openmrs.module.webservices.rest.web.ConversionUtil;
import org.openmrs.module.webservices.rest.web.RequestContext;
import org.openmrs.module.webservices.rest.web.RestConstants;
import org.openmrs.module.webservices.rest.web.annotation.Resource;
import org.openmrs.module.webservices.rest.web.representation.Representation;
import org.openmrs.module.webservices.rest.web.resource.api.Creatable;
import org.openmrs.module.webservices.rest.web.resource.impl.BaseDelegatingResource;
import org.openmrs.module.webservices.rest.web.resource.impl.DelegatingResourceDescription;
import org.openmrs.module.webservices.rest.web.response.IllegalRequestException;
import org.openmrs.module.webservices.rest.web.response.ResourceDoesNotSupportOperationException;
import org.openmrs.module.webservices.rest.web.response.ResponseException;

@Resource(name = RestConstants.VERSION_1 + "/moduleinstall", supportedClass = ModuleInstall.class, supportedOpenmrsVersions = {
"1.10.*", "1.11.*", "1.12.*", "1.8.*", "1.9.*", "2.0.*", "2.1.*" })
public class ModuleInstallResource1_8 extends BaseDelegatingResource<ModuleInstall> implements Creatable {

private ModuleFactoryWrapper moduleFactoryWrapper = new ModuleFactoryWrapper();

public void setModuleFactoryWrapper(ModuleFactoryWrapper moduleFactoryWrapper) {
this.moduleFactoryWrapper = moduleFactoryWrapper;
}

@Override
public Object create(SimpleObject post, RequestContext context) throws ResponseException {
moduleFactoryWrapper.checkPrivilege();
ModuleInstall moduleInstall = newDelegate();
setConvertedProperties(moduleInstall, post, getCreatableProperties(), true);

String moduleUuid = moduleInstall.getModuleUuid();
String installUri = moduleInstall.getInstallUri();
Module module = null;
File moduleFile = null;

ServletContext servletContext = getServletContext(context);

if (moduleUuid == null && installUri == null) {
throw new IllegalRequestException("The moduleUuid and installUri is needed to perform this action");
}

if (ResourceUtils.isUrl(installUri)) {
try {
Module existingModule = moduleFactoryWrapper.getModuleById(moduleUuid);
if (existingModule != null) {
List<Module> dependentModulesStopped = moduleFactoryWrapper.stopModuleAndGetDependent(existingModule);

for (Module depMod : dependentModulesStopped) {
moduleFactoryWrapper.stopModuleSkipRefresh(depMod, servletContext);
}

moduleFactoryWrapper.stopModuleSkipRefresh(existingModule, servletContext);
moduleFactoryWrapper.unloadModule(existingModule);
}

URL downloadUrl = new URL(installUri);
String fileName = FilenameUtils.getName(downloadUrl.getPath());
InputStream inputStream = ModuleUtil.getURLStream(downloadUrl);
moduleFile = ModuleUtil.insertModuleFile(inputStream, fileName);
module = moduleFactoryWrapper.loadModule(moduleFile);
moduleFactoryWrapper.startModule(module, servletContext);

return ConversionUtil.convertToRepresentation(moduleInstall, Representation.DEFAULT);
}
catch (MalformedURLException e) {
throw new RuntimeException(e.getMessage());
}
catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
finally {
if (module == null && moduleFile != null) {
FileUtils.deleteQuietly(moduleFile);
}
}
}

throw new IllegalRequestException("The installUri needs to be a URL for this action to be performed");
}

@Override
public String getUri(Object instance) {
return null;
}

@Override
public ModuleInstall newDelegate() {
return new ModuleInstall();
}

@Override
public ModuleInstall save(ModuleInstall delegate) {
throw new UnsupportedOperationException("ModuleInstall can not be saved");
}

@Override
public ModuleInstall getByUniqueId(String uniqueId) {
throw new UnsupportedOperationException("ModuleInstall can not be saved");
}

@Override
protected void delete(ModuleInstall delegate, String reason, RequestContext context) throws ResponseException {
throw new UnsupportedOperationException("ModuleInstall can not be deleted");
}

@Override
public void purge(ModuleInstall delegate, RequestContext context) throws ResponseException {
throw new UnsupportedOperationException("ModuleInstall can not be purged");
}

@Override
public DelegatingResourceDescription getRepresentationDescription(Representation rep) {
DelegatingResourceDescription description = new DelegatingResourceDescription();
description.addProperty("moduleUuid");
description.addProperty("installUri");
return description;
}

@Override
public DelegatingResourceDescription getCreatableProperties() throws ResourceDoesNotSupportOperationException {
DelegatingResourceDescription description = new DelegatingResourceDescription();
description.addProperty("moduleUuid");
description.addProperty("installUri");
return description;
}

private ServletContext getServletContext(RequestContext context) {
return context.getRequest().getSession().getServletContext();
}
}
@@ -0,0 +1,107 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
*
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
* graphic logo is a trademark of OpenMRS Inc.
*/
package org.openmrs.module.webservices.rest.web.v1_0.controller.openmrs1_8;

import org.junit.Test;
import org.junit.Assert;
import org.junit.Before;
import org.openmrs.module.Module;
import org.openmrs.module.webservices.helper.ModuleInstall;
import org.openmrs.module.webservices.rest.SimpleObject;
import org.openmrs.module.webservices.rest.web.MockModuleFactoryWrapper;
import org.openmrs.module.webservices.rest.web.api.RestService;
import org.openmrs.module.webservices.rest.web.response.IllegalRequestException;
import org.openmrs.module.webservices.rest.web.v1_0.controller.MainResourceControllerTest;
import org.openmrs.module.webservices.rest.web.v1_0.resource.openmrs1_8.ModuleInstallResource1_8;
import org.springframework.beans.factory.annotation.Autowired;

import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.MatcherAssert.assertThat;

public class ModuleInstallResource1_8Test extends MainResourceControllerTest {

@Autowired
RestService restService;

private Module mockModuleToLoad = new Module("MockModule", "mockModule", "name", "author", "description", "version");

MockModuleFactoryWrapper mockModuleFactory = new MockModuleFactoryWrapper();

@Before
public void setUp() throws Exception {
ModuleInstallResource1_8 resource = (ModuleInstallResource1_8) restService
.getResourceBySupportedClass(ModuleInstall.class);
resource.setModuleFactoryWrapper(mockModuleFactory);
}

@Test
public void shouldLoadModule() throws Exception {
mockModuleFactory.loadModuleMock = mockModuleToLoad;
SimpleObject simpleObject = deserialize(handle(newPostRequest(getURI(),
"{\"installUri\":\"" + getInstallUri() + "\", \"moduleUuid\":\"" + getUuid()
+ "\"}")));

assertThat(mockModuleFactory.loadedModules, hasItem(mockModuleToLoad));
assertThat(mockModuleFactory.startedModules, hasItem(mockModuleToLoad));
Assert.assertEquals(simpleObject.get("moduleUuid"), getUuid());
Assert.assertEquals(simpleObject.get("installUri"), getInstallUri());

}

@Test(expected = IllegalRequestException.class)
public void shouldThrowErrorOnPoorUri() throws Exception {
deserialize(handle(newPostRequest(getURI(), "{\"installUri\":\"anystring\", \"moduleUuid\":\"" + getUuid() + "\"}")));
}

//ModuleUpdate resource does not support these operations
@Override
@Test(expected = Exception.class)
public void shouldGetDefaultByUuid() throws Exception {
super.shouldGetDefaultByUuid();
}

@Override
@Test(expected = Exception.class)
public void shouldGetRefByUuid() throws Exception {
super.shouldGetRefByUuid();
}

@Override
@Test(expected = Exception.class)
public void shouldGetFullByUuid() throws Exception {
super.shouldGetFullByUuid();
}

@Override
@Test(expected = Exception.class)
public void shouldGetAll() throws Exception {
super.shouldGetAll();
}

@Override
public String getURI() {
return "moduleinstall";
}

@Override
public String getUuid() {
return "XForms";
}

@Override
public long getAllCount() {
return 0;
}

public String getInstallUri() {
return "https://dl.bintray.com/openmrs/omod/xforms-4.3.11.omod";
}

}
@@ -0,0 +1,44 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
*
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
* graphic logo is a trademark of OpenMRS Inc.
*/
package org.openmrs.module.webservices.helper;

import org.openmrs.module.Module;

public class ModuleInstall {

public ModuleInstall() {
}

public ModuleInstall(String moduleUuid, String installUri) {
this.moduleUuid = moduleUuid;
this.installUri = installUri;
}

private String moduleUuid;

private String installUri;

public void setModuleUuid(String moduleUuid) {
this.moduleUuid = moduleUuid;
}

public String getModuleUuid() {
return moduleUuid;
}

public void setInstallUri(String installUri) {
this.installUri = installUri;
}

public String getInstallUri() {
return installUri;
}

}

0 comments on commit 37ac262

Please sign in to comment.