package org.geoserver.proxy;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.LinkedHashSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Logger;
import org.vfny.geoserver.global.ConfigurationException;
import org.vfny.geoserver.global.GeoserverDataDirectory;
import com.thoughtworks.xstream.XStream;
/**
* This class holds the the configuration for the Proxy server module during runtime. It is also
* serialized as XML to persistently store settings.
*
* @author Alan Gerber <agerber@openplans.org>
*/
//vvv everybody else is doing this
@SuppressWarnings("serial")
public class ProxyConfig implements java.io.Serializable{
//This rwlock controls access to the file in which proxy configuration is stored.
private static ReadWriteLock configFileLock = new ReentrantReadWriteLock();
private static Lock configReadLock = configFileLock.readLock();
private static Lock configWriteLock = configFileLock.writeLock();
/*
* Sets the mode of the proxy server: -HOSTNAMEORMIMETYPE means a request must match have
* matches on the hostname AND MIMEType whitelists -HOSTNAMEANDMIMETYPE means a request must
* match have matches on the hostname OR MIMEType whitelists -HOSTNAME means a request must
* match have a match on the hostname whitelist alone -MIMETYPE means a request must match have
* a match on the MIMEType whitelist alone
*/
public enum Mode {
HOSTNAMEORMIMETYPE ("Hostname OR MIMEType"),
HOSTNAMEANDMIMETYPE ("Hostname AND MIMEType"),
HOSTNAME ("Hostname only"),
MIMETYPE ("MIMEType only");
public final String modeName;
Mode(String modeName){
this.modeName = modeName;
}
public static List<String> modeNames() {
List<String> modeNames = new ArrayList<String>();
for (Mode mode : Mode.values())
{
modeNames.add(mode.modeName);
}
return modeNames;
}
};
public Mode mode;
/* A list of regular expressions describing hostnames the proxy is permitted to forward to */
public LinkedHashSet<String> hostnameWhitelist;
/* A list of regular expressions describing MIMETypes the proxy is permitted to forward */
public LinkedHashSet<String> mimetypeWhitelist;
/*The name of the directory where configuration is stored*/
private static final String confDirName = "proxy";
/*The name of the file the configuration is stored in*/
private static final String confFileName = "proxy.xml";
/* Attempts to grab the proxy's config file from the data dir.
* @return the proxy's configuration's File
* @throws ConfigurationException if the config system is busted
*/
public static File getConfigFile() throws ConfigurationException
{
File dir = GeoserverDataDirectory.findCreateConfigDir(confDirName);
File proxyConfFile = new File(dir, confFileName);
return proxyConfFile;
}
/*The default proxy configuration allows all requests to localhost and all OGC mimetypes*/
private static final ProxyConfig DEFAULT;
static {
DEFAULT = new ProxyConfig();
DEFAULT.mode = Mode.HOSTNAMEORMIMETYPE;
DEFAULT.hostnameWhitelist = new LinkedHashSet<String>();
DEFAULT.mimetypeWhitelist = new LinkedHashSet<String>(Arrays.asList(
"application/xml", "text/xml",
"application/vnd.ogc.se_xml", // OGC Service Exception
"application/vnd.ogc.se+xml", // OGC Service Exception
"application/vnd.ogc.success+xml", // OGC Success (SLD Put)
"application/vnd.ogc.wms_xml", // WMS Capabilities
"application/vnd.ogc.context+xml", // WMC
"application/vnd.ogc.gml", // GML
"application/vnd.ogc.sld+xml", // SLD
"application/vnd.google-earth.kml+xml" // KML;
));
}
private static final Logger LOG = org.geotools.util.logging.Logging
.getLogger("org.geoserver.proxy");
/* this is pretty unappealingly hackish */
public static ProxyConfig loadConfFromDisk() {
ProxyConfig retval;
try {
File proxyConfFile = getConfigFile();
InputStream proxyConfStream = new FileInputStream(proxyConfFile);
XStream xs = new XStream();
//Take the read lock, then read the file
configReadLock.lock();
retval = (ProxyConfig) (xs.fromXML(proxyConfStream));
configReadLock.unlock();
} catch (Exception e) {
LOG.warning("Failed to open configuration for Proxy module. Using default. Exception:"
+ e.toString());
//writeConfigToDisk(DEFAULT);
retval = DEFAULT;
}
return retval;
}
public static boolean writeConfigToDisk(ProxyConfig pc) {
try {
File proxyConfFile = getConfigFile();
XStream xs = new XStream();
String xml = xs.toXML(pc);
FileWriter fw = new FileWriter(proxyConfFile, false); // false means overwrite old file
//Take the write lock on the file & lock it
configWriteLock.lock();
fw.write(xml);
fw.close();
configWriteLock.unlock();
return true;
} catch (Exception e) {
LOG.warning("Failed to save configuration for Proxy module. Exception:"
+ e.toString());
return false;
}
}
/*Output a textual representation of the config
*@return a String representation of the config
*/
@Override
public String toString(){
StringBuilder stringForm = new StringBuilder(256);
stringForm.append("Mode: " + this.mode.modeName + "\n");
stringForm.append("Hostname regex whitelist: \n");
for (String hostname : this.hostnameWhitelist)
stringForm.append(hostname + "\n");
stringForm.append("MIMEType regex whitelist: \n");
for (String mimetype : this.mimetypeWhitelist)
stringForm.append(mimetype + "\n");
stringForm.append(this.mode.modeName + "\n");
return stringForm.toString();
}
}