/**
* 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.api.impl;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.commons.lang3.StringUtils;
import org.openmrs.ConceptSource;
import org.openmrs.GlobalProperty;
import org.openmrs.ImplementationId;
import org.openmrs.OpenmrsObject;
import org.openmrs.User;
import org.openmrs.api.APIException;
import org.openmrs.api.AdministrationService;
import org.openmrs.api.EventListeners;
import org.openmrs.api.GlobalPropertyListener;
import org.openmrs.api.context.Context;
import org.openmrs.api.db.AdministrationDAO;
import org.openmrs.customdatatype.CustomDatatypeUtil;
import org.openmrs.module.Module;
import org.openmrs.module.ModuleFactory;
import org.openmrs.module.ModuleUtil;
import org.openmrs.util.HttpClient;
import org.openmrs.util.LocaleUtility;
import org.openmrs.util.OpenmrsConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.Errors;
/**
* Default implementation of the administration services. This class should not be used on its own.
* The current OpenMRS implementation should be fetched from the Context
*
* @see org.openmrs.api.AdministrationService
* @see org.openmrs.api.context.Context
*/
@Transactional
public class AdministrationServiceImpl extends BaseOpenmrsService implements AdministrationService, GlobalPropertyListener {
protected Logger log = LoggerFactory.getLogger(getClass());
protected AdministrationDAO dao;
private EventListeners eventListeners;
/**
* An always up-to-date collection of the allowed locales.
*/
private GlobalLocaleList globalLocaleList;
private HttpClient implementationIdHttpClient;
/**
* Default empty constructor
*/
public AdministrationServiceImpl() {
}
/**
* @see org.openmrs.api.AdministrationService#setAdministrationDAO(org.openmrs.api.db.AdministrationDAO)
*/
@Override
public void setAdministrationDAO(AdministrationDAO dao) {
this.dao = dao;
}
public void setEventListeners(EventListeners eventListeners) {
this.eventListeners = eventListeners;
}
/**
* Static-ish variable used to cache the system variables. This is not static so that every time
* a module is loaded or removed the variable is destroyed (along with the administration
* service) and recreated the next time it is called
*/
protected SortedMap<String, String> systemVariables = null;
/**
* Set of locales which can be used to present messages in the user interface. Created lazily as
* needed by {@link #getAllowedLocales()}.
*/
private Set<Locale> presentationLocales;
/**
* @see org.openmrs.api.AdministrationService#getSystemVariables()
*/
@Override
@Transactional(readOnly = true)
public SortedMap<String, String> getSystemVariables() throws APIException {
if (systemVariables == null) {
systemVariables = new TreeMap<String, String>();
// Added the server's fully qualified domain name
try {
systemVariables.put("OPENMRS_HOSTNAME", InetAddress.getLocalHost().getCanonicalHostName());
}
catch (UnknownHostException e) {
systemVariables.put("OPENMRS_HOSTNAME", "Unknown host: " + e.getMessage());
}
systemVariables.put("OPENMRS_VERSION", String.valueOf(OpenmrsConstants.OPENMRS_VERSION));
systemVariables.put("DATABASE_NAME", OpenmrsConstants.DATABASE_NAME);
systemVariables.put("DATABASE_BUSINESS_NAME", OpenmrsConstants.DATABASE_BUSINESS_NAME);
systemVariables.put("OBSCURE_PATIENTS", String.valueOf(OpenmrsConstants.OBSCURE_PATIENTS));
systemVariables.put("OBSCURE_PATIENTS_FAMILY_NAME", OpenmrsConstants.OBSCURE_PATIENTS_FAMILY_NAME);
systemVariables.put("OBSCURE_PATIENTS_GIVEN_NAME", OpenmrsConstants.OBSCURE_PATIENTS_GIVEN_NAME);
systemVariables.put("OBSCURE_PATIENTS_MIDDLE_NAME", OpenmrsConstants.OBSCURE_PATIENTS_MIDDLE_NAME);
systemVariables.put("MODULE_REPOSITORY_PATH", ModuleUtil.getModuleRepository().getAbsolutePath());
systemVariables.put("OPERATING_SYSTEM_KEY", String.valueOf(OpenmrsConstants.OPERATING_SYSTEM_KEY));
systemVariables.put("OPERATING_SYSTEM", String.valueOf(OpenmrsConstants.OPERATING_SYSTEM));
}
return systemVariables;
}
/**
* @see org.openmrs.api.AdministrationService#getGlobalProperty(java.lang.String)
*/
@Override
@Transactional(readOnly = true)
public String getGlobalProperty(String propertyName) throws APIException {
// This method should not have any authorization check
if (propertyName == null) {
return null;
}
return dao.getGlobalProperty(propertyName);
}
/**
* @see org.openmrs.api.AdministrationService#getGlobalProperty(java.lang.String,
* java.lang.String)
*/
@Override
@Transactional(readOnly = true)
public String getGlobalProperty(String propertyName, String defaultValue) throws APIException {
String s = Context.getAdministrationService().getGlobalProperty(propertyName);
if (s == null) {
return defaultValue;
}
return s;
}
/**
* @see org.openmrs.api.AdministrationService#getGlobalPropertyObject(java.lang.String)
*/
@Override
@Transactional(readOnly = true)
public GlobalProperty getGlobalPropertyObject(String propertyName) {
return dao.getGlobalPropertyObject(propertyName);
}
/**
* @see org.openmrs.api.AdministrationService#setGlobalProperty(java.lang.String,
* java.lang.String)
*/
@Override
public void setGlobalProperty(String propertyName, String propertyValue) throws APIException {
GlobalProperty gp = Context.getAdministrationService().getGlobalPropertyObject(propertyName);
if (gp == null) {
gp = new GlobalProperty();
gp.setProperty(propertyName);
}
gp.setPropertyValue(propertyValue);
Context.getAdministrationService().saveGlobalProperty(gp);
}
/**
* @see org.openmrs.api.AdministrationService#updateGlobalProperty(java.lang.String,
* java.lang.String)
*/
@Override
public void updateGlobalProperty(String propertyName, String propertyValue) throws IllegalStateException {
GlobalProperty gp = Context.getAdministrationService().getGlobalPropertyObject(propertyName);
if (gp == null) {
throw new IllegalStateException("Global property with the given propertyName does not exist" + propertyName);
}
gp.setPropertyValue(propertyValue);
dao.saveGlobalProperty(gp);
}
/**
* @see org.openmrs.api.AdministrationService#getAllGlobalProperties()
*/
@Override
@Transactional(readOnly = true)
public List<GlobalProperty> getAllGlobalProperties() throws APIException {
return dao.getAllGlobalProperties();
}
/**
* @see org.openmrs.api.AdministrationService#getGlobalPropertiesByPrefix(java.lang.String)
*/
@Override
@Transactional(readOnly = true)
public List<GlobalProperty> getGlobalPropertiesByPrefix(String prefix) {
return dao.getGlobalPropertiesByPrefix(prefix);
}
/**
* @see org.openmrs.api.AdministrationService#getGlobalPropertiesBySuffix(java.lang.String)
*/
@Override
@Transactional(readOnly = true)
public List<GlobalProperty> getGlobalPropertiesBySuffix(String suffix) {
return dao.getGlobalPropertiesBySuffix(suffix);
}
/**
* @see org.openmrs.api.AdministrationService#purgeGlobalProperty(org.openmrs.GlobalProperty)
*/
@Override
public void purgeGlobalProperty(GlobalProperty globalProperty) throws APIException {
notifyGlobalPropertyDelete(globalProperty.getProperty());
dao.deleteGlobalProperty(globalProperty);
}
/**
* @see org.openmrs.api.AdministrationService#saveGlobalProperties(java.util.List)
*/
@Override
@CacheEvict(value = "userSearchLocales", allEntries = true)
public List<GlobalProperty> saveGlobalProperties(List<GlobalProperty> props) throws APIException {
log.debug("saving a list of global properties");
// add all of the new properties
for (GlobalProperty prop : props) {
if (prop.getProperty() != null && prop.getProperty().length() > 0) {
Context.getAdministrationService().saveGlobalProperty(prop);
}
}
return props;
}
/**
* @see org.openmrs.api.AdministrationService#saveGlobalProperty(org.openmrs.GlobalProperty)
*/
@Override
@CacheEvict(value = "userSearchLocales", allEntries = true)
public GlobalProperty saveGlobalProperty(GlobalProperty gp) throws APIException {
// only try to save it if the global property has a key
if (gp.getProperty() != null && gp.getProperty().length() > 0) {
if (gp.getProperty().equals(OpenmrsConstants.GLOBAL_PROPERTY_LOCALE_ALLOWED_LIST)) {
if (gp.getPropertyValue() != null) {
List<Locale> localeList = new ArrayList<Locale>();
for (String localeString : gp.getPropertyValue().split(",")) {
localeList.add(LocaleUtility.fromSpecification(localeString.trim()));
}
if (!localeList.contains(LocaleUtility.getDefaultLocale())) {
gp.setPropertyValue(StringUtils.join(getAllowedLocales(), ", "));
throw new APIException(Context.getMessageSourceService().getMessage(
"general.locale.localeListNotIncludingDefaultLocale",
new Object[] { LocaleUtility.getDefaultLocale() }, null));
}
}
} else if (gp.getProperty().equals(OpenmrsConstants.GLOBAL_PROPERTY_DEFAULT_LOCALE)
&& gp.getPropertyValue() != null) {
List<Locale> localeList = getAllowedLocales();
if (!localeList.contains(LocaleUtility.fromSpecification(gp.getPropertyValue().trim()))) {
String value = gp.getPropertyValue();
gp.setPropertyValue(LocaleUtility.getDefaultLocale().toString());
throw new APIException((Context.getMessageSourceService().getMessage(
"general.locale.defaultNotInAllowedLocalesList", new Object[] { value }, null)));
}
}
CustomDatatypeUtil.saveIfDirty(gp);
dao.saveGlobalProperty(gp);
notifyGlobalPropertyChange(gp);
return gp;
}
return gp;
}
/**
* @see org.openmrs.api.AdministrationService#executeSQL(java.lang.String, boolean)
*/
@Override
public List<List<Object>> executeSQL(String sql, boolean selectOnly) throws APIException {
if (sql == null || "".equals(sql.trim())) {
return null;
}
return dao.executeSQL(sql, selectOnly);
}
/**
* @see org.openmrs.api.AdministrationService#addGlobalPropertyListener(GlobalPropertyListener)
*/
@Override
public void addGlobalPropertyListener(GlobalPropertyListener listener) {
eventListeners.getGlobalPropertyListeners().add(listener);
}
/**
* @see org.openmrs.api.AdministrationService#removeGlobalPropertyListener(GlobalPropertyListener)
*/
@Override
public void removeGlobalPropertyListener(GlobalPropertyListener listener) {
eventListeners.getGlobalPropertyListeners().remove(listener);
}
/**
* Calls global property listeners registered for this create/change
*
* @param gp
*/
private void notifyGlobalPropertyChange(GlobalProperty gp) {
for (GlobalPropertyListener listener : eventListeners.getGlobalPropertyListeners()) {
if (listener.supportsPropertyName(gp.getProperty())) {
listener.globalPropertyChanged(gp);
}
}
}
/**
* Calls global property listeners registered for this delete
*
* @param propertyName
*/
private void notifyGlobalPropertyDelete(String propertyName) {
for (GlobalPropertyListener listener : eventListeners.getGlobalPropertyListeners()) {
if (listener.supportsPropertyName(propertyName)) {
listener.globalPropertyDeleted(propertyName);
}
}
}
/**
* @see org.openmrs.api.AdministrationService#getImplementationId()
*/
@Override
@Transactional(readOnly = true)
public ImplementationId getImplementationId() throws APIException {
String property = Context.getAdministrationService().getGlobalProperty(
OpenmrsConstants.GLOBAL_PROPERTY_IMPLEMENTATION_ID);
// fail early if no gp has been defined yet
if (property == null) {
return null;
}
try {
ImplementationId implId = Context.getSerializationService().getDefaultSerializer().deserialize(property, ImplementationId.class);
return implId;
}
catch (Exception e) {
log.debug("Error while getting implementation id", e);
}
return null;
}
/**
* @see org.openmrs.api.AdministrationService#setImplementationId(org.openmrs.ImplementationId)
*/
@Override
public void setImplementationId(ImplementationId implementationId) throws APIException {
if (implementationId == null) {
return;
}
// check the validity of this implementation id with the server
String description = implementationId.getDescription();
try {
// check that source id is valid
description = checkImplementationIdValidity(implementationId.getImplementationId(), description,
implementationId.getPassphrase());
// save the server's description back to this concept source object
implementationId.setDescription(description);
boolean foundMatchingSource = false;
// loop over the concept sources to make sure one exists for this hl7Code/implementationId
List<ConceptSource> sources = Context.getConceptService().getAllConceptSources(false);
if (sources != null) {
for (ConceptSource source : sources) {
if (implementationId.getImplementationId().equals(source.getHl7Code())) {
foundMatchingSource = true;
}
}
}
// if no ConceptSource currently exists with this implementationId, save this implId
// as a new ConceptSource
if (!foundMatchingSource) {
ConceptSource newConceptSource = new ConceptSource();
newConceptSource.setName(implementationId.getName());
newConceptSource.setDescription(implementationId.getDescription());
newConceptSource.setHl7Code(implementationId.getImplementationId());
if (Context.getAuthenticatedUser() == null) {
// (hackish)
newConceptSource.setCreator(new User(1)); // fake the user because no one is logged in
}
Context.getConceptService().saveConceptSource(newConceptSource);
}
// serialize and save the ImplementationId to the global properties table
String value = Context.getSerializationService().getDefaultSerializer().serialize(implementationId);
Context.getAdministrationService().saveGlobalProperty(
new GlobalProperty(OpenmrsConstants.GLOBAL_PROPERTY_IMPLEMENTATION_ID, value));
}
catch (APIException e) {
throw e;
}
catch (Exception e) {
// pass any other exceptions on up the train
throw new APIException(e);
}
finally {
// save an empty concept source to the database when something fails?
}
}
/**
* Checks the remote server for this exact implementation id. Returns the description if 1)
* there is no implementation id or 2) there is a implementation id and this passphrase matches
* it. In the case of 1), this implementation id and passphrase are saved to the remote server's
* database
*
* @param implementationId
* @param description
* @param passphrase
* @return the stored description on the remote server
* @throws APIException
* @throws UnsupportedEncodingException
*/
private String checkImplementationIdValidity(String implementationId, String description, String passphrase)
throws APIException {
if (StringUtils.isEmpty(implementationId)) {
throw new APIException("cannot.be.empty", new Object[] { "implementationid" });
}
if (StringUtils.isEmpty(description)) {
throw new APIException("cannot.be.empty", new Object[] { "description" });
}
if (StringUtils.isEmpty(passphrase)) {
throw new APIException("cannot.be.empty", new Object[] { "passphrase" });
}
// set up the data map to post to the openmrs server
Map<String, String> data = new HashMap<String, String>();
data.put("implementationId", implementationId);
data.put("description", description);
data.put("passphrase", passphrase);
String response = implementationIdHttpClient.post(data);
response = response.trim();
if ("".equals(response)) {
String ms = Context.getMessageSourceService().getMessage("ImplementationId.connectionError",
new String[] { implementationId }, Context.getLocale());
throw new APIException(ms);
}
if (log.isDebugEnabled()) {
log.debug("Response: " + response);
}
if (response.startsWith("Success")) {
response = response.replace("Success", "");
return response.trim();
}
String ms = Context.getMessageSourceService().getMessage("ImplementationId.invalidIdorPassphrase",
new String[] { description }, Context.getLocale());
throw new APIException(ms);
}
/**
* @see org.openmrs.api.AdministrationService#getAllowedLocales()
*/
@Override
@Transactional(readOnly = true)
public List<Locale> getAllowedLocales() {
// lazy-load the global locale list and initialize with current global property value
if (globalLocaleList == null) {
globalLocaleList = new GlobalLocaleList();
Context.getAdministrationService().addGlobalPropertyListener(globalLocaleList);
}
Set<Locale> allowedLocales = globalLocaleList.getAllowedLocales();
// update the GlobalLocaleList.allowedLocales by faking a global property change
if (allowedLocales == null) {
// use a default language of "english" if they have cleared this GP for some reason
String currentPropertyValue = Context.getAdministrationService().getGlobalProperty(
OpenmrsConstants.GLOBAL_PROPERTY_LOCALE_ALLOWED_LIST, LocaleUtility.getDefaultLocale().toString());
GlobalProperty allowedLocalesProperty = new GlobalProperty(OpenmrsConstants.GLOBAL_PROPERTY_LOCALE_ALLOWED_LIST,
currentPropertyValue);
globalLocaleList.globalPropertyChanged(allowedLocalesProperty);
allowedLocales = globalLocaleList.getAllowedLocales();
}
// allowedLocales is guaranteed to not be null at this point
return new ArrayList<Locale>(allowedLocales);
}
/**
* Used by spring to set the GlobalLocaleList on this implementation
*
* @param gll the GlobalLocaleList object that is registered to the GlobalPropertyListeners as
* well
*/
public void setGlobalLocaleList(GlobalLocaleList gll) {
globalLocaleList = gll;
}
/**
* @see org.openmrs.api.AdministrationService#getPresentationLocales()
*/
@Override
@Transactional(readOnly = true)
public Set<Locale> getPresentationLocales() {
if (presentationLocales == null) {
presentationLocales = new LinkedHashSet<Locale>();
Collection<Locale> messageLocales = Context.getMessageSourceService().getLocales();
List<Locale> allowedLocales = getAllowedLocales();
for (Locale locale : allowedLocales) {
// if no country is specified all countries with this language will be added
if (StringUtils.isEmpty(locale.getCountry())) {
List<Locale> localsWithSameLanguage = new ArrayList<Locale>();
for (Locale possibleLocale : messageLocales) {
if (locale.getLanguage().equals(possibleLocale.getLanguage())
&& !StringUtils.isEmpty(possibleLocale.getCountry())) {
localsWithSameLanguage.add(possibleLocale);
}
}
// if there are country locales we add those only
if (!localsWithSameLanguage.isEmpty()) {
presentationLocales.addAll(localsWithSameLanguage);
} else {
// if there are no country locales we add possibleLocale which has country as ""
// e.g: if 'es' locale has no country based entries es_CL etc. we show default 'es'
if (messageLocales.contains(locale)) {
presentationLocales.add(locale);
}
}
} else {
// if locales list contains exact <language,country> pair add it
if (messageLocales.contains(locale)) {
presentationLocales.add(locale);
} else {
// if no such entry add possibleLocale with country ""
// e.g: we specify es_CL but it is not in list so we add es locale here
for (Locale possibleLocale : messageLocales) {
if (locale.getLanguage().equals(possibleLocale.getLanguage())
&& StringUtils.isEmpty(possibleLocale.getCountry())) {
presentationLocales.add(possibleLocale);
}
}
}
}
}
}
return presentationLocales;
}
/**
* @see org.openmrs.api.GlobalPropertyListener#globalPropertyChanged(org.openmrs.GlobalProperty)
*/
@Override
public void globalPropertyChanged(GlobalProperty newValue) {
if (newValue.getProperty().equals(OpenmrsConstants.GLOBAL_PROPERTY_LOCALE_ALLOWED_LIST)) {
// reset the calculated locale values
presentationLocales = null;
}
}
/**
* @see org.openmrs.api.GlobalPropertyListener#globalPropertyDeleted(java.lang.String)
*/
@Override
public void globalPropertyDeleted(String propertyName) {
// TODO Auto-generated method stub
}
/**
* @see org.openmrs.api.GlobalPropertyListener#supportsPropertyName(java.lang.String)
*/
@Override
public boolean supportsPropertyName(String propertyName) {
return propertyName.equals(OpenmrsConstants.GLOBAL_PROPERTY_LOCALE_ALLOWED_LIST);
}
/**
* @see org.openmrs.api.AdministrationService#getGlobalPropertyByUuid(java.lang.String)
*/
@Override
@Transactional(readOnly = true)
public GlobalProperty getGlobalPropertyByUuid(String uuid) {
return dao.getGlobalPropertyByUuid(uuid);
}
/**
* @see org.openmrs.api.AdministrationService#getGlobalPropertyValue(java.lang.String,
* java.lang.Object)
*/
@Override
@SuppressWarnings("unchecked")
public <T> T getGlobalPropertyValue(String propertyName, T defaultValue) throws APIException {
if (defaultValue == null) {
throw new IllegalArgumentException("The defaultValue argument cannot be null");
}
String propVal = Context.getAdministrationService().getGlobalProperty(propertyName);
if (StringUtils.isEmpty(propVal)) {
return defaultValue;
}
try {
return (T) defaultValue.getClass().getDeclaredConstructor(String.class).newInstance(propVal);
}
catch (InstantiationException e) {
throw new APIException("is.not.able.instantiated", new Object[] { defaultValue.getClass().getName(), propVal },
e);
}
catch (NoSuchMethodException e) {
throw new APIException("does.not.have.string.constructor", new Object[] { defaultValue.getClass().getName() }, e);
}
catch (Exception e) {
log.error("Unable to turn value '" + propVal + "' into type " + defaultValue.getClass().getName(), e);
return defaultValue;
}
}
/**
* @see org.openmrs.api.AdministrationService#getSystemInformation()
*/
@Override
@Transactional(readOnly = true)
public Map<String, Map<String, String>> getSystemInformation() throws APIException {
Map<String, Map<String, String>> systemInfoMap = new LinkedHashMap<String, Map<String, String>>();
systemInfoMap.put("SystemInfo.title.openmrsInformation", new LinkedHashMap<String, String>() {
private static final long serialVersionUID = 1L;
{
put("SystemInfo.OpenMRSInstallation.systemDate", new SimpleDateFormat("yyyy-MM-dd").format(Calendar
.getInstance().getTime()));
put("SystemInfo.OpenMRSInstallation.systemTime", new SimpleDateFormat("HH:mm:ss").format(Calendar
.getInstance().getTime()));
put("SystemInfo.OpenMRSInstallation.openmrsVersion", OpenmrsConstants.OPENMRS_VERSION);
try {
put("SystemInfo.hostname", InetAddress.getLocalHost().getCanonicalHostName());
}
catch (UnknownHostException e) {
put("SystemInfo.hostname", "Unknown host: " + e.getMessage());
}
}
});
systemInfoMap.put("SystemInfo.title.javaRuntimeEnvironmentInformation", new LinkedHashMap<String, String>() {
Properties properties = System.getProperties();
private static final long serialVersionUID = 1L;
{
put("SystemInfo.JavaRuntimeEnv.operatingSystem", properties.getProperty("os.name"));
put("SystemInfo.JavaRuntimeEnv.operatingSystemArch", properties.getProperty("os.arch"));
put("SystemInfo.JavaRuntimeEnv.operatingSystemVersion", properties.getProperty("os.version"));
put("SystemInfo.JavaRuntimeEnv.javaVersion", properties.getProperty("java.version"));
put("SystemInfo.JavaRuntimeEnv.javaVendor", properties.getProperty("java.vendor"));
put("SystemInfo.JavaRuntimeEnv.jvmVersion", properties.getProperty("java.vm.version"));
put("SystemInfo.JavaRuntimeEnv.jvmVendor", properties.getProperty("java.vm.vendor"));
put("SystemInfo.JavaRuntimeEnv.javaRuntimeName", properties.getProperty("java.runtime.name"));
put("SystemInfo.JavaRuntimeEnv.javaRuntimeVersion", properties.getProperty("java.runtime.version"));
put("SystemInfo.JavaRuntimeEnv.userName", properties.getProperty("user.name"));
put("SystemInfo.JavaRuntimeEnv.systemLanguage", properties.getProperty("user.language"));
put("SystemInfo.JavaRuntimeEnv.systemTimezone", properties.getProperty("user.timezone"));
put("SystemInfo.JavaRuntimeEnv.fileSystemEncoding", properties.getProperty("sun.jnu.encoding"));
put("SystemInfo.JavaRuntimeEnv.userDirectory", properties.getProperty("user.dir"));
put("SystemInfo.JavaRuntimeEnv.tempDirectory", properties.getProperty("java.io.tmpdir"));
}
});
systemInfoMap.put("SystemInfo.title.memoryInformation", new LinkedHashMap<String, String>() {
private static final long serialVersionUID = 1L;
Runtime runtime = Runtime.getRuntime();
{
put("SystemInfo.Memory.totalMemory", convertToMegaBytes(runtime.totalMemory()));
put("SystemInfo.Memory.freeMemory", convertToMegaBytes(runtime.freeMemory()));
put("SystemInfo.Memory.maximumHeapSize", convertToMegaBytes(runtime.maxMemory()));
}
});
systemInfoMap.put("SystemInfo.title.dataBaseInformation", new LinkedHashMap<String, String>() {
Properties properties = Context.getRuntimeProperties();
private static final long serialVersionUID = 1L;
{
put("SystemInfo.Database.name", OpenmrsConstants.DATABASE_NAME);
put("SystemInfo.Database.connectionURL", properties.getProperty("connection.url"));
put("SystemInfo.Database.userName", properties.getProperty("connection.username"));
put("SystemInfo.Database.driver", properties.getProperty("hibernate.connection.driver_class"));
put("SystemInfo.Database.dialect", properties.getProperty("hibernate.dialect"));
}
});
systemInfoMap.put("SystemInfo.title.moduleInformation", new LinkedHashMap<String, String>() {
private static final long serialVersionUID = 1L;
{
put("SystemInfo.Module.repositoryPath", ModuleUtil.getModuleRepository().getAbsolutePath());
Collection<Module> loadedModules = ModuleFactory.getLoadedModules();
for (Module module : loadedModules) {
String moduleInfo = module.getVersion() + " "
+ (module.isStarted() ? "" : Context.getMessageSourceService().getMessage("Module.notStarted"));
put(module.getName(), moduleInfo);
}
}
});
return systemInfoMap;
}
/**
* @param bytes to be converted into mega bytes
* @return memory in mega bytes
*/
private String convertToMegaBytes(long bytes) {
int ONE_KILO_BYTE = 1024;
return String.valueOf(bytes / ONE_KILO_BYTE / ONE_KILO_BYTE) + " MB";
}
/**
* @see org.openmrs.api.AdministrationService#purgeGlobalProperties(java.util.List)
*/
@Override
public void purgeGlobalProperties(List<GlobalProperty> globalProperties) throws APIException {
for (GlobalProperty globalProperty : globalProperties) {
Context.getAdministrationService().purgeGlobalProperty(globalProperty);
}
}
/**
* @see AdministrationService#getMaximumPropertyLength(Class, String)
*/
@Override
@Transactional(readOnly = true)
public int getMaximumPropertyLength(Class<? extends OpenmrsObject> aClass, String fieldName) {
return dao.getMaximumPropertyLength(aClass, fieldName);
}
/**
* @see org.openmrs.api.AdministrationService#validate(java.lang.Object, Errors)
*/
@Override
@Transactional(readOnly = true)
public void validate(Object object, Errors errors) throws APIException {
if (object == null) {
throw new APIException("error.null", (Object[]) null);
}
dao.validate(object, errors);
}
@Override
@Cacheable(value = "userSearchLocales")
public List<Locale> getSearchLocales(Locale currentLocale, User user) throws APIException {
Set<Locale> locales = new LinkedHashSet<Locale>();
locales.add(currentLocale); //the currently used full locale
locales.add(new Locale(currentLocale.getLanguage()));
if (user != null) {
List<Locale> proficientLocales = user.getProficientLocales();
if (proficientLocales != null) {
locales.addAll(proficientLocales);
}
}
//limit locales to only allowed locales
List<Locale> allowedLocales = Context.getAdministrationService().getAllowedLocales();
if (allowedLocales != null) {
Set<Locale> retainLocales = new HashSet<Locale>();
for (Locale allowedLocale : allowedLocales) {
retainLocales.add(allowedLocale);
retainLocales.add(new Locale(allowedLocale.getLanguage()));
}
locales.retainAll(retainLocales);
}
return new ArrayList<Locale>(locales);
}
/**
* @see AdministrationService#getSearchLocales()
*/
@Override
@Transactional(readOnly = true)
public List<Locale> getSearchLocales(){
//call it via interface, so cache interceptor is invoked
return Context.getAdministrationService().getSearchLocales(Context.getLocale(), Context.getAuthenticatedUser());
}
@Override
public void setImplementationIdHttpClient(HttpClient implementationIdHttpClient) {
this.implementationIdHttpClient = implementationIdHttpClient;
}
/**
* @see org.openmrs.api.AdministrationService#isDatabaseStringComparisonCaseSensitive()
*/
@Override
public boolean isDatabaseStringComparisonCaseSensitive() {
return dao.isDatabaseStringComparisonCaseSensitive();
}
}