/**
* 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.api.APIAuthenticationException;
import org.openmrs.api.context.Context;
import org.openmrs.module.Module;
import org.openmrs.module.ModuleFactory;
import org.openmrs.module.ModuleFileParser;
import org.openmrs.module.ModuleUtil;
import org.openmrs.module.web.WebModuleUtil;
import org.openmrs.util.PrivilegeConstants;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
/**
* ModuleFactoryWrapper wraps static methods of ModuleFactory to make code operating on modules
* testable
*/
public class ModuleFactoryWrapper {
public static final String STOP_MODULE_SKIP_REFRESH_EXCEPTION_MESSAGE = "Failed to stop module without WAC refresh";
public Module parseModuleFile(MultipartFile file) throws IOException {
return new ModuleFileParser(file.getInputStream()).parse();
}
public Module getModuleById(String id) {
return ModuleFactory.getModuleById(id);
}
public void refreshWebApplicationContext(ServletContext context) {
WebModuleUtil.refreshWAC(context, false, null);
}
public Collection<Module> getLoadedModules() {
return ModuleFactory.getLoadedModules();
}
public boolean isModuleStarted(Module module) {
return module.isStarted();
}
public boolean isModuleStopped(Module module) {
return !isModuleStarted(module);
}
public void unloadModule(Module module) {
ModuleFactory.unloadModule(module);
}
public File insertModuleFile(Module module, String filename) throws FileNotFoundException {
return ModuleUtil.insertModuleFile(new FileInputStream(module.getFile()), filename);
}
public Module loadModule(File moduleFile) {
return ModuleFactory.loadModule(moduleFile);
}
public List<Module> stopModuleAndGetDependent(Module module) {
return ModuleFactory.stopModule(module, false, true);
}
public void stopModule(Module module, ServletContext servletContext) {
ModuleFactory.stopModule(module);
WebModuleUtil.stopModule(module, servletContext);
if (module.isStarted()) {
throw new RuntimeException("Failed to stop module: " + module.getName() + ", " + module.getStartupErrorMessage());
}
}
public boolean startModule(Module module, ServletContext servletContext) {
return startModule(module, servletContext, false);
}
public boolean startModule(Module module, ServletContext servletContext, boolean delayRefreshContext) {
ModuleFactory.startModule(module);
return WebModuleUtil.startModule(module, servletContext, delayRefreshContext);
}
public boolean startModuleSkipRefresh(Module module, ServletContext servletContext) {
return startModule(module, servletContext, true);
}
/**
* It's hacky method to workaround the fact that before 2.x platform
* {@link WebModuleUtil#stopModule(Module, ServletContext, boolean)} was private. It is
* essential to support uploading modules 1.x platform via REST api
*/
public void stopModuleSkipRefresh(Module module, ServletContext servletContext) {
ModuleFactory.stopModule(module);
try {
Method stopModule = WebModuleUtil.class.getDeclaredMethod("stopModule", Module.class, ServletContext.class,
Boolean.TYPE);
stopModule.setAccessible(true);
stopModule.invoke(null, module, servletContext, true);
}
catch (NoSuchMethodException e) {
throw new RuntimeException(STOP_MODULE_SKIP_REFRESH_EXCEPTION_MESSAGE, e);
}
catch (InvocationTargetException e) {
throw new RuntimeException(STOP_MODULE_SKIP_REFRESH_EXCEPTION_MESSAGE, e);
}
catch (IllegalAccessException e) {
throw new RuntimeException(STOP_MODULE_SKIP_REFRESH_EXCEPTION_MESSAGE, e);
}
}
/**
* hack to work around the change in ModuleFactory API
*/
@SuppressWarnings("unchecked")
public Collection<Module> getModulesInStartupOrder(Collection<Module> modules) {
try {
try {
Method getModulesInStartupOrder = ModuleFactory.class.getDeclaredMethod("getModulesInStartupOrder",
Collection.class);
return (Collection<Module>) getModulesInStartupOrder.invoke(null, modules);
}
catch (NoSuchMethodException e) {
try {
Method getModulesInStartOrder = ModuleFactory.class.getDeclaredMethod("getModulesInStartOrder");
return (Collection<Module>) getModulesInStartOrder.invoke(null);
}
catch (NoSuchMethodException e1) {
throw new RuntimeException(e1);
}
}
}
catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public void checkPrivilege() throws APIAuthenticationException {
if (!Context.hasPrivilege(PrivilegeConstants.MANAGE_MODULES)) {
throw new APIAuthenticationException("Privilege required: " + PrivilegeConstants.MANAGE_MODULES);
}
}
}