/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is part of dcm4che, an implementation of DICOM(TM) in
* Java(TM), hosted at https://github.com/dcm4che.
*
* The Initial Developer of the Original Code is
* Agfa Healthcare.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* See @authors listed below
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.dcm4chee.wizard;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.prefs.Preferences;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.naming.InitialContext;
import org.apache.wicket.request.Url;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.http.WebRequest;
import org.dcm4che3.conf.api.ConfigurationException;
import org.dcm4che3.conf.api.DicomConfiguration;
import org.dcm4che3.conf.api.hl7.HL7Configuration;
import org.dcm4che3.conf.ldap.LdapDicomConfiguration;
import org.dcm4che3.conf.ldap.audit.LdapAuditLoggerConfiguration;
import org.dcm4che3.conf.ldap.audit.LdapAuditRecordRepositoryConfiguration;
import org.dcm4che3.conf.ldap.generic.LdapGenericConfigExtension;
import org.dcm4che3.conf.ldap.hl7.LdapHL7Configuration;
import org.dcm4che3.conf.prefs.PreferencesDicomConfiguration;
import org.dcm4che3.conf.prefs.audit.PreferencesAuditLoggerConfiguration;
import org.dcm4che3.conf.prefs.audit.PreferencesAuditRecordRepositoryConfiguration;
import org.dcm4che3.conf.prefs.cdi.PrefsFactory;
import org.dcm4che3.conf.prefs.generic.PreferencesGenericConfigExtension;
import org.dcm4che3.conf.prefs.hl7.PreferencesHL7Configuration;
import org.dcm4che3.net.ApplicationEntity;
import org.dcm4che3.net.Device;
import org.dcm4che3.util.SafeClose;
import org.dcm4che3.util.StringUtils;
import org.dcm4chee.proxy.conf.ldap.LdapProxyConfigurationExtension;
import org.dcm4chee.proxy.conf.prefs.PreferencesProxyConfigurationExtension;
import org.dcm4chee.storage.conf.StorageConfiguration;
import org.dcm4chee.wizard.panel.BasicConfigurationPanel;
import org.dcm4chee.wizard.tree.ConfigTreeNode;
import org.dcm4chee.wizard.tree.ConfigTreeNode.TreeNodeType;
import org.dcm4chee.xds2.conf.XCAInitiatingGWCfg;
import org.dcm4chee.xds2.conf.XCARespondingGWCfg;
import org.dcm4chee.xds2.conf.XCAiInitiatingGWCfg;
import org.dcm4chee.xds2.conf.XCAiRespondingGWCfg;
import org.dcm4chee.xds2.conf.XDSiSourceCfg;
import org.dcm4chee.xds2.conf.XdsRegistry;
import org.dcm4chee.xds2.conf.XdsRepository;
import org.dcm4chee.xds2.conf.XdsSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Robert David <robert.david@agfa.com>
* @author Michael Backhaus <michael.backhaus@agfa.com>
*/
public class DicomConfigurationManager implements Serializable {
private static final long serialVersionUID = 1L;
private static Logger log = LoggerFactory.getLogger(DicomConfigurationManager.class);
private DicomConfiguration dicomConfiguration;
private HashMap<String, Device> deviceMap;
private Date lastModificationTime;
private Map<String, Set<String>> reloadList;
private HL7Configuration hl7Configuration;
private HashMap<String, String> connectedDeviceUrls;
public DicomConfigurationManager(String ldapPropertiesURL) {
try {
ldapPropertiesURL = StringUtils.replaceSystemProperties(
System.getProperty("org.dcm4chee.proxy.ldapPropertiesURL", ldapPropertiesURL)).replace('\\', '/');
InputStream ldapConf = null;
try {
ldapConf = new URL(ldapPropertiesURL).openStream();
Properties p = new Properties();
p.load(ldapConf);
LdapDicomConfiguration ldapConfig = new LdapDicomConfiguration(p);
LdapHL7Configuration hl7Config = new LdapHL7Configuration();
ldapConfig.addDicomConfigurationExtension(hl7Config);
ldapConfig.addDicomConfigurationExtension(new LdapProxyConfigurationExtension());
ldapConfig.addDicomConfigurationExtension(new LdapAuditLoggerConfiguration());
ldapConfig.addDicomConfigurationExtension(new LdapAuditRecordRepositoryConfiguration());
ldapConfig.addDicomConfigurationExtension(new LdapGenericConfigExtension<XdsRegistry>(XdsRegistry.class));
ldapConfig.addDicomConfigurationExtension(new LdapGenericConfigExtension<XdsRepository>(XdsRepository.class));
ldapConfig.addDicomConfigurationExtension(new LdapGenericConfigExtension<XCARespondingGWCfg>(XCARespondingGWCfg.class));
ldapConfig.addDicomConfigurationExtension(new LdapGenericConfigExtension<XCAInitiatingGWCfg>(XCAInitiatingGWCfg.class));
ldapConfig.addDicomConfigurationExtension(new LdapGenericConfigExtension<XCAiRespondingGWCfg>(XCAiRespondingGWCfg.class));
ldapConfig.addDicomConfigurationExtension(new LdapGenericConfigExtension<XCAiInitiatingGWCfg>(XCAiInitiatingGWCfg.class));
ldapConfig.addDicomConfigurationExtension(new LdapGenericConfigExtension<XdsSource>(XdsSource.class));
ldapConfig.addDicomConfigurationExtension(new LdapGenericConfigExtension<StorageConfiguration>(StorageConfiguration.class));
ldapConfig.addDicomConfigurationExtension(new LdapGenericConfigExtension<XDSiSourceCfg>(XDSiSourceCfg.class));
dicomConfiguration = ldapConfig;
hl7Configuration = hl7Config;
} catch (FileNotFoundException e) {
String pf = System.getProperty("java.util.prefs.PreferencesFactory");
if (pf != null && pf.equals("org.dcm4che.jdbc.prefs.PreferencesFactoryImpl"))
log.info("Using JDBC Preferences as Configuration Backend");
else
log.info("Using Java Preferences as Configuration Backend");
// manual cdi..
PrefsFactory prefsFactory = null;
try {
BeanManager manager;
manager = (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
Set<Bean<?>> beans = manager.getBeans(PrefsFactory.class);
Bean<PrefsFactory> prefsFactoryBean = (Bean<PrefsFactory>) beans.iterator().next();
CreationalContext cc = manager.createCreationalContext(prefsFactoryBean);
prefsFactory = (PrefsFactory) manager.getReference(prefsFactoryBean, PrefsFactory.class, cc);
} catch (Exception cdie) {
log.warn("Could not inject PrefsFacory",cdie); // noop, no prefsFactory
}
PreferencesDicomConfiguration prefsConfig;
if (prefsFactory != null)
prefsConfig = new PreferencesDicomConfiguration(prefsFactory.getPreferences()); else
prefsConfig = new PreferencesDicomConfiguration();
log.info("Preferences runtime class {}", prefsConfig.getRootPrefs().getClass().toString());
PreferencesHL7Configuration hl7Config = new PreferencesHL7Configuration();
prefsConfig.addDicomConfigurationExtension(hl7Config);
prefsConfig.addDicomConfigurationExtension(new PreferencesProxyConfigurationExtension());
prefsConfig.addDicomConfigurationExtension(new PreferencesAuditLoggerConfiguration());
prefsConfig.addDicomConfigurationExtension(new PreferencesAuditRecordRepositoryConfiguration());
prefsConfig.addDicomConfigurationExtension(new PreferencesGenericConfigExtension<XdsRegistry>(XdsRegistry.class));
prefsConfig.addDicomConfigurationExtension(new PreferencesGenericConfigExtension<XdsRepository>(XdsRepository.class));
prefsConfig.addDicomConfigurationExtension(new PreferencesGenericConfigExtension<XCARespondingGWCfg>(XCARespondingGWCfg.class));
prefsConfig.addDicomConfigurationExtension(new PreferencesGenericConfigExtension<XCAInitiatingGWCfg>(XCAInitiatingGWCfg.class));
prefsConfig.addDicomConfigurationExtension(new PreferencesGenericConfigExtension<XCAiRespondingGWCfg>(XCAiRespondingGWCfg.class));
prefsConfig.addDicomConfigurationExtension(new PreferencesGenericConfigExtension<XCAiInitiatingGWCfg>(XCAiInitiatingGWCfg.class));
prefsConfig.addDicomConfigurationExtension(new PreferencesGenericConfigExtension<XdsSource>(XdsSource.class));
prefsConfig.addDicomConfigurationExtension(new PreferencesGenericConfigExtension<StorageConfiguration>(StorageConfiguration.class));
prefsConfig.addDicomConfigurationExtension(new PreferencesGenericConfigExtension<XDSiSourceCfg>(XDSiSourceCfg.class));
dicomConfiguration = prefsConfig;
hl7Configuration = hl7Config;
} finally {
SafeClose.close(ldapConf);
}
for (String deviceName : getDeviceMap().keySet())
getDevice(deviceName);
lastModificationTime = new Date();
reloadList = new HashMap<String, Set<String>>();
} catch (Exception e) {
if (dicomConfiguration != null)
dicomConfiguration.close();
log.error("Error loading device configuration: " + e.getMessage());
if (log.isDebugEnabled())
e.printStackTrace();
throw new RuntimeException(e);
}
}
public DicomConfiguration getDicomConfiguration() {
return dicomConfiguration;
}
public HL7Configuration getHL7Configuration() {
return hl7Configuration;
}
public synchronized HashMap<String, Device> getDeviceMap() {
if (deviceMap == null)
try {
deviceMap = new HashMap<String, Device>();
for (String deviceName : Arrays.asList(dicomConfiguration.listDeviceNames()))
deviceMap.put(deviceName, null);
} catch (Exception e) {
log.error("Error loading device list", e);
throw new RuntimeException(e);
}
return deviceMap;
}
public synchronized void resetDeviceMap() {
deviceMap = null;
}
public synchronized ArrayList<String> listDevices() throws ConfigurationException {
ArrayList<String> deviceNameList = new ArrayList<String>(getDeviceMap().keySet());
Collections.sort(deviceNameList);
return deviceNameList;
}
public synchronized Device getDevice(String deviceName) throws ConfigurationException {
Device device = getDeviceMap().get(deviceName);
if (device == null) {
device = dicomConfiguration.findDevice(deviceName);
getDeviceMap().put(deviceName, device);
}
return device;
}
public synchronized void save(Device device, Date date) throws ConfigurationException {
if (getDeviceMap().containsKey(device.getDeviceName()))
dicomConfiguration.merge(device);
else
dicomConfiguration.persist(device);
getDeviceMap().put(device.getDeviceName(), device);
lastModificationTime = date;
}
public synchronized void remove(String deviceName) throws ConfigurationException {
dicomConfiguration.removeDevice(deviceName);
getDeviceMap().remove(deviceName);
}
public synchronized void resetDevice(String deviceName) {
getDeviceMap().put(deviceName, null);
}
public Map<String, String> getConnectedDeviceUrls() {
if (connectedDeviceUrls == null) {
connectedDeviceUrls = new HashMap<String, String>();
try {
for (String deviceName : listDevices()) {
String connectedDeviceUrl = System.getProperty("org.dcm4chee.device." + deviceName);
if (connectedDeviceUrl != null) {
try {
if (!connectedDeviceUrl.startsWith("http")) {
Url url = ((WebRequest) RequestCycle.get().getRequest()).getUrl();
connectedDeviceUrl = url.getProtocol().concat("://")
.concat(url.getHost()).concat(":")
.concat(url.getPort().toString())
.concat(connectedDeviceUrl);
}
connectedDeviceUrls
.put(deviceName, StringUtils.replaceSystemProperties(connectedDeviceUrl));
} catch (Exception e) {
log.error("Error processing URL " + connectedDeviceUrl + " for connected device "
+ deviceName, e);
}
}
}
} catch (ConfigurationException ce) {
log.error("Error retrieving connected device URLs", ce);
}
}
return connectedDeviceUrls;
}
public String getConnectedDeviceURL(Device d, TreeNodeType treeNodeType) {
String url = getConnectedDeviceUrls().get(d.getDeviceName());
if (url == null)
return null;
String restPath = treeNodeType == null ? null : BasicConfigurationPanel.XDS_REST_PATH.get(treeNodeType);
return restPath == null ? url : url+restPath;
}
public ApplicationEntity getApplicationEntity(String aet) throws ConfigurationException {
return dicomConfiguration.findApplicationEntity(aet);
}
public synchronized Date getLastModificationTime() {
return lastModificationTime;
}
public synchronized boolean isReload(String deviceName) {
Set<String> urls = reloadList.get(deviceName);
return urls != null && urls.size() > 0;
}
public synchronized boolean isReload(String deviceName, String reloadURL) {
Set<String> urls = reloadList.get(deviceName);
return urls != null && urls.contains(reloadURL);
}
public synchronized void setReload(String deviceName, String... reloadURLs) {
Set<String> urls = reloadList.get(deviceName);
if (urls == null) {
urls = new HashSet<String>();
reloadList.put(deviceName, urls);
}
for (String url : reloadURLs) {
if (url != null)
urls.add(url);
}
}
public synchronized void clearReload(String deviceName, String... reloadURLs) {
Set<String> urls = reloadList.get(deviceName);
if (urls != null) {
for (String url : reloadURLs) {
if (url != null)
urls.remove(url);
}
if (urls.isEmpty())
reloadList.remove(deviceName);
}
}
}