package org.geoserver.config.hibernate;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.hibernate.HibCatalogImpl;
import org.geoserver.config.ConfigurationListener;
import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerFactory;
import org.geoserver.config.GeoServerInfo;
import org.geoserver.config.JAIInfo;
import org.geoserver.config.LoggingInfo;
import org.geoserver.config.ServiceInfo;
import org.geoserver.config.hibernate.beans.GeoServerInfoImplHb;
import org.geoserver.config.impl.ServiceInfoImpl;
import org.geoserver.hibernate.HibMapper;
import org.geoserver.hibernate.Hibernable;
import org.geoserver.hibernate.dao.ServiceDAO;
import org.geoserver.jai.JAIInitializer;
import org.geotools.util.logging.Logging;
public class HibGeoServerImpl implements Serializable
// , GeoServer
{
private static final Logger LOGGER = Logging.getLogger("org.geoserver.config.hibernate");
/**
* factory to create config objects.
*/
private HibGeoServerFactoryImpl factory;
transient private HibCatalogImpl catalog;
transient private List<ConfigurationListener> listeners = new ArrayList<ConfigurationListener>();
/**
*
*/
transient private ServiceDAO serviceDAO;
/**
* TODO: please doublecheck the updates to this field<BR>
* We need to cache JAI info because it has many transient values, and we prefer to cache twe
* whole class instead of single values.
*/
transient JAIInfo cachedJAI = null;
private final GeoServer proxy;
/**
*
*/
private HibGeoServerImpl() {
super();
proxy = GSProxy.newInstance(this);
}
public GeoServer getProxy() {
return proxy;
}
/**
*
*/
public Catalog getCatalog() {
return catalog;
}
public void setCatalog(Catalog catalog) {
this.catalog = (HibCatalogImpl) catalog;
}
public GeoServerFactory getFactory() {
return factory;
}
public void setFactory(GeoServerFactory factory) {
this.factory = (HibGeoServerFactoryImpl) factory;
}
public GeoServerInfo getGlobal() {
if (LOGGER.isLoggable(Level.FINEST))
LOGGER.finest("Querying geoserver global configuration");
GeoServerInfo geoserver = this.serviceDAO.getGeoServer();
if (geoserver == null) {
LOGGER.warning("Database is empty");
geoserver = null;
} else {
if (cachedJAI == null) {
LOGGER.info("getGlobal: JAI was null, inizitialized.");
cachedJAI = geoserver.getJAI();
} else {
// The cached jai may have been updated.
// Updated values should already be in db, but we need
// the transient runtime values that are stored in cachedJAI.
geoserver.setJAI(cachedJAI);
}
}
return geoserver;
}
public void setGlobal(GeoServerInfo configuration) {
// ensure contactinfo is not null
if (configuration.getContact() == null) {
LOGGER.warning("GeoServerInfo contact is not set. Creating empty one...");
configuration.setContact(getFactory().createContact());
}
// retrieve existing global
GeoServerInfo currentGlobal = getGlobal();
GeoServerInfoImplHb merged = null;
if (currentGlobal == null) {
if (LOGGER.isLoggable(Level.INFO))
LOGGER.info("Storing first instance of GeoServerInfo");
GeoServerInfoImplHb inserted = (GeoServerInfoImplHb) this.serviceDAO
.save(configuration);
inserted.copyTo((GeoServerInfoImplHb) configuration);
((GeoServerInfoImplHb) configuration).setId(inserted.getId());
} else {
GeoServerInfoImplHb oldconf = (GeoServerInfoImplHb) currentGlobal;
GeoServerInfoImplHb newconf = (GeoServerInfoImplHb) configuration;
newconf.setId(oldconf.getId());
merged = (GeoServerInfoImplHb) this.serviceDAO.update(newconf);
merged.copyTo(newconf);
}
JAIInitializer initializer = new JAIInitializer();
try {
initializer.initialize(proxy);
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, "Error initializing JAI: " + ex.getMessage(), ex);
}
cachedJAI = configuration.getJAI();
if (merged != null)
merged.setJAI(cachedJAI);
// fire the modification event
firePostGlobalModified(merged);
}
public void save(GeoServerInfo geoServer) {
setGlobal(geoServer);
for (ConfigurationListener l : listeners) {
try {
l.handleGlobalChange(geoServer, new ArrayList<String>(), // FIXME: if really needed,
// reload from DB and
// compare
new ArrayList<Object>(), // FIXME: if really needed, reload from DB and
// compare
new ArrayList<Object>());// FIXME: if really needed, reload from DB and
// compare
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Exception calling handleGlobalChange", e);
}
}
// fire post modification event
firePostGlobalModified(geoServer);
}
/**
* @see GeoServer#add(ServiceInfo)
*/
public void add(ServiceInfo service) {
final String serviceId = service.getId();
if (serviceId == null) {
throw new NullPointerException("service id must not be null");
}
ServiceInfo existing = getService(serviceId);
if (existing != null) {
throw new IllegalArgumentException("service with id '" + serviceId + "' already exists");
}
// GeoServerInfo global = getGlobal();
service.setGeoServer(proxy);
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("CREATING SERVICE id:" + serviceId + " name:" + service.getName()
+ " title:" + service.getTitle());
if (service instanceof Hibernable) {
this.serviceDAO.save(service);
} else {
LOGGER.info("Translating unhibernable instance of " + service.getClass().getName());
HibServiceTranslator translator = new HibServiceTranslator(factory);
ServiceInfoImpl hservice = translator.translate(service);
this.serviceDAO.save(hservice);
}
// fire post modification event
firePostServiceModified(service);
}
/**
*
*/
public void remove(ServiceInfo service) {
this.serviceDAO.delete(service);
}
/**
*
*/
public void save(ServiceInfo service) {
this.serviceDAO.update(service);
for (ConfigurationListener l : listeners) {
try {
l.handleServiceChange(service, new ArrayList<String>(), // FIXME: if really needed,
// reload from DB and
// compare
new ArrayList<Object>(), // FIXME: if really needed, reload from DB and
// compare
new ArrayList<Object>());// FIXME: if really needed, reload from DB and
// compare
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Exception calling handleServiceChange", e);
}
}
// fire post modification event
firePostServiceModified(service);
}
/**
*
*/
public Collection<? extends ServiceInfo> getServices() {
return getServices(ServiceInfo.class);
}
/**
*
* @param clazz
* @return
*/
protected Collection<? extends ServiceInfo> getServices(Class<?> clazz) {
Collection<ServiceInfoImpl> sis = (Collection<ServiceInfoImpl>) this.serviceDAO
.getServices(clazz);
for (ServiceInfoImpl serviceInfoImpl : sis) {
serviceInfoImpl.setGeoServer(proxy);
}
return sis;
}
/**
*/
public <T extends ServiceInfo> T getService(Class<T> clazz) {
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("getService(" + clazz.getName() + ")");
Class clazz2 = HibMapper.mapHibernableClass(clazz);
// TODO: create dao.findService
for (ServiceInfo si : getServices(clazz2)) {
if (clazz2.isAssignableFrom(si.getClass())) {
si.setGeoServer(proxy);
return (T) si;
}
}
return null;
}
/**
*
*/
protected ServiceInfo getService(String id) {
return getService(id, ServiceInfo.class);
}
/**
*
*/
public <T extends ServiceInfo> T getService(String id, Class<T> clazz) {
T ret = this.serviceDAO.getService(id, clazz);
if (ret != null)
ret.setGeoServer(proxy);
return ret;
}
/**
*
*/
public <T extends ServiceInfo> T getServiceByName(String name, Class<T> clazz) {
T ret = this.serviceDAO.getServiceByName(name, clazz);
if (ret != null)
ret.setGeoServer(proxy);
return ret;
}
public void addListener(ConfigurationListener listener) {
listeners.add(listener);
}
public void removeListener(ConfigurationListener listener) {
listeners.remove(listener);
}
public void dispose() {
catalog.dispose();
listeners.clear();
}
public ServiceDAO getServiceDAO() {
return serviceDAO;
}
public void setServiceDAO(ServiceDAO serviceDAO) {
this.serviceDAO = serviceDAO;
}
public void setCatalog(HibCatalogImpl catalog) {
this.catalog = catalog;
}
public Collection<ConfigurationListener> getListeners() {
return listeners;
}
public LoggingInfo getLogging() {
return serviceDAO.getLogging();
}
public void setLogging(LoggingInfo logging) {
serviceDAO.setLogging(logging);
firePostLoggingModified(logging);
}
public void save(LoggingInfo logging) {
serviceDAO.setLogging(logging);
for (ConfigurationListener l : listeners) {
try {
l.handleLoggingChange(logging, new ArrayList<String>(), // FIXME: if really needed,
// reload from DB and
// compare
new ArrayList<Object>(), // FIXME: if really needed, reload from DB and
// compare
new ArrayList<Object>());// FIXME: if really needed, reload from DB and
// compare
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Exception calling handleLoggingChange", e);
}
}
// fire post modification event
firePostLoggingModified(logging);
}
private void firePostGlobalModified(GeoServerInfo global) {
for (ConfigurationListener l : listeners) {
try {
l.handlePostGlobalChange(global);
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Exception in fireGlobalPostModified", e);
}
}
}
private void firePostLoggingModified(LoggingInfo logging) {
for (ConfigurationListener l : listeners) {
try {
l.handlePostLoggingChange(logging);
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Exception in fireLoggingPostModified", e);
}
}
}
void firePostServiceModified(ServiceInfo service) {
for (ConfigurationListener l : listeners) {
try {
l.handlePostServiceChange(service);
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Exception in firePostServiceModified", e);
}
}
}
}
class GSProxy implements InvocationHandler, Serializable {
private HibGeoServerImpl geoserverimpl;
public static GeoServer newInstance(HibGeoServerImpl gsi) {
return (GeoServer) Proxy.newProxyInstance(gsi.getClass().getClassLoader(),
new Class[] { GeoServer.class }, new GSProxy(gsi));
}
private GSProxy(HibGeoServerImpl obj) {
this.geoserverimpl = obj;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Object result;
try {
// System.out.println("before method " + m.getName());
Method pmethod = geoserverimpl.getClass().getMethod(m.getName(), m.getParameterTypes());
result = pmethod.invoke(geoserverimpl, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}
return result;
}
}