/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.gwc;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geoserver.gwc.config.GeoserverXMLResourceProvider;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.ResourceStore;
import org.geoserver.platform.resource.Resources;
import org.geoserver.security.GeoServerSecurityManager;
import org.geoserver.security.SecurityManagerListener;
import org.geotools.util.logging.Logging;
import org.geowebcache.config.ConfigurationException;
import org.geowebcache.diskquota.DiskQuotaConfig;
import org.geowebcache.diskquota.QuotaStore;
import org.geowebcache.diskquota.jdbc.JDBCConfiguration;
import org.geowebcache.diskquota.jdbc.JDBCQuotaStoreFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* Loads/save and tests the JDBC configuration in the GeoServer environment, adding support for the
* GUI and password encryption
*
* @author Andrea Aime - GeoSolutions
*
*/
class JDBCConfigurationStorage implements ApplicationContextAware, SecurityManagerListener {
static final Logger LOGGER = Logging.getLogger(JDBCConfigurationStorage.class);
private JDBCPasswordEncryptionHelper passwordHelper;
private ApplicationContext applicationContext;
private Resource configDir;
public JDBCConfigurationStorage(ResourceStore store,
GeoServerSecurityManager securityManager) {
GeoserverXMLResourceProvider configProvider = (GeoserverXMLResourceProvider)
GeoServerExtensions.bean("jdbcDiskQuotaConfigResourceProvider");
this.configDir = configProvider.getConfigDirectory();
this.passwordHelper = new JDBCPasswordEncryptionHelper(securityManager);
securityManager.addListener(this);
}
public synchronized void saveDiskQuotaConfig(DiskQuotaConfig config,
JDBCConfiguration jdbcConfig) throws ConfigurationException, IOException,
InterruptedException {
Resource configFile = configDir.get("geowebcache-diskquota-jdbc.xml");
if ("JDBC".equals(config.getQuotaStore())) {
JDBCConfiguration encrypted = passwordHelper.encryptPassword(jdbcConfig);
try (OutputStream os = configFile.out()) {
JDBCConfiguration.store(encrypted, os);
}
} else {
if (Resources.exists(configFile) && !configFile.delete()) {
LOGGER.log(Level.SEVERE, "Failed to delete " + configFile
+ ", this might cause misbehavior on GeoServer restart");
}
}
}
public synchronized JDBCConfiguration getJDBCDiskQuotaConfig() throws IOException,
org.geowebcache.config.ConfigurationException {
Resource configFile = configDir.get("geowebcache-diskquota-jdbc.xml");
if (!Resources.exists(configFile)) {
return null;
}
try {
JDBCConfiguration configuration;
try (InputStream is = configFile.in()) {
configuration = JDBCConfiguration.load(is);
}
return passwordHelper.unencryptPassword(configuration);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Failed to load geowebcache-diskquota-jdbc.xml", e);
return null;
}
}
/**
* Checks the JDBC quota store can be instantiated
*
* @param config
* @param jdbcConfiguration
* @throws ConfigurationException
*/
public void testQuotaConfiguration(JDBCConfiguration jdbcConfiguration)
throws ConfigurationException, IOException {
JDBCQuotaStoreFactory factory = GeoServerExtensions.bean(JDBCQuotaStoreFactory.class);
QuotaStore qs = null;
try {
qs = factory.getJDBCStore(applicationContext, jdbcConfiguration);
} finally {
if (qs != null) {
try {
qs.close();
} catch (Exception e) {
LOGGER.log(Level.FINE, "Failed to dispose test quota store", e);
}
}
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void handlePostChanged(GeoServerSecurityManager securityManager) {
// we can't know if the password encoder changed, so we check if the encrypted pwd changed
// (unfortunately some password encoders change the encrypted password every time they are called...)
try {
JDBCConfiguration config = getJDBCDiskQuotaConfig();
if(config != null) {
Resource configFile = configDir.get("geowebcache-diskquota-jdbc.xml");
if(!Resources.exists(configFile)) {
return;
}
JDBCConfiguration c1;
try (InputStream is = configFile.in()) {
c1 = JDBCConfiguration.load(is);
}
if(c1 == null || c1.getConnectionPool() == null) {
return;
}
String originalEncrypted = c1.getConnectionPool().getPassword();
if(originalEncrypted == null) {
return;
}
JDBCConfiguration c2 = passwordHelper.unencryptPassword(c1);
JDBCConfiguration c3 = passwordHelper.encryptPassword(c2);
String newEncrypted = c3.getConnectionPool().getPassword();
if(!originalEncrypted.equals(newEncrypted)) {
try (OutputStream os = configFile.out()) {
JDBCConfiguration.store(c3, os);
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}