/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.config.impl; import static org.geoserver.ows.util.OwsUtils.resolveCollections; 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.WorkspaceInfo; import org.geoserver.catalog.Wrapper; import org.geoserver.catalog.impl.CatalogImpl; import org.geoserver.catalog.impl.LocalWorkspaceCatalog; import org.geoserver.config.ConfigurationListener; import org.geoserver.config.GeoServer; import org.geoserver.config.GeoServerFacade; import org.geoserver.config.GeoServerFactory; import org.geoserver.config.GeoServerInfo; import org.geoserver.config.GeoServerLoaderProxy; import org.geoserver.config.LoggingInfo; import org.geoserver.config.ServiceInfo; import org.geoserver.config.SettingsInfo; import org.geoserver.ows.LocalWorkspace; import org.geoserver.platform.GeoServerExtensions; import org.geotools.referencing.CRS; import org.geotools.util.logging.Logging; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class GeoServerImpl implements GeoServer, ApplicationContextAware { private static final Logger LOGGER = Logging.getLogger(GeoServerImpl.class); /** * factory for creating objects */ GeoServerFactory factory = new GeoServerFactoryImpl(this); /** * the catalog */ Catalog catalog; /** * data access object */ GeoServerFacade facade; /** * listeners */ List<ConfigurationListener> listeners = new ArrayList<ConfigurationListener>(); public GeoServerImpl() { this.facade = new DefaultGeoServerFacade(this); } public GeoServerFacade getFacade() { return facade; } public void setFacade(GeoServerFacade facade) { this.facade = facade; facade.setGeoServer(this); } public GeoServerFactory getFactory() { return factory; } public void setFactory(GeoServerFactory factory) { this.factory = factory; } public Catalog getCatalog() { return catalog; } public void setCatalog(Catalog catalog) { this.catalog = catalog; // This instance of check is has to be here because this Geoserver cannot be injected // into LocalWorkspaceCatalog because it causes a circular reference if (catalog instanceof LocalWorkspaceCatalog) { LocalWorkspaceCatalog lwCatalog = (LocalWorkspaceCatalog) catalog; lwCatalog.setGeoServer(this); } } public GeoServerInfo getGlobal() { return facade.getGlobal(); } public void setGlobal(GeoServerInfo global) { facade.setGlobal(global); //fire the modification event fireGlobalPostModified(); } public SettingsInfo getSettings() { SettingsInfo settings = null; if (LocalWorkspace.get() != null) { settings = getSettings(LocalWorkspace.get()); } return settings != null ? settings : getGlobal().getSettings(); } public SettingsInfo getSettings(WorkspaceInfo workspace) { return facade.getSettings(workspace); } public void add(SettingsInfo settings) { validate(settings); resolve(settings); WorkspaceInfo workspace = settings.getWorkspace(); if (facade.getSettings(workspace) != null) { throw new IllegalArgumentException("Settings already exist for workspace '" + workspace.getName() + "'"); } facade.add(settings); fireSettingsAdded(settings); } public void save(SettingsInfo settings) { validate(settings); facade.save(settings); fireSettingsPostModified(settings); } public void remove(SettingsInfo settings) { facade.remove(settings); fireSettingsRemoved(settings); } void validate(SettingsInfo settings) { WorkspaceInfo workspace = settings.getWorkspace(); if (workspace == null) { throw new IllegalArgumentException("Settings must be part of a workspace"); } } void resolve(SettingsInfo settings) { resolveCollections(settings); } void fireSettingsAdded(SettingsInfo settings) { for ( ConfigurationListener l : listeners ) { try { l.handleSettingsAdded(settings); } catch( Exception e ) { LOGGER.log(Level.SEVERE, "Error occurred processing a configuration change listener", e); } } } public void fireSettingsModified(SettingsInfo settings, List<String> changed, List oldValues, List newValues) { for ( ConfigurationListener l : listeners ) { try { l.handleSettingsModified(settings, changed, oldValues, newValues); } catch( Exception e ) { LOGGER.log(Level.SEVERE, "Error occurred processing a configuration change listener", e); } } } void fireSettingsPostModified(SettingsInfo settings) { for ( ConfigurationListener l : listeners ) { try { l.handleSettingsPostModified(settings); } catch( Exception e ) { LOGGER.log(Level.SEVERE, "Error occurred processing a configuration change listener", e); } } } void fireSettingsRemoved(SettingsInfo settings) { for ( ConfigurationListener l : listeners ) { try { l.handleSettingsRemoved(settings); } catch( Exception e ) { LOGGER.log(Level.SEVERE, "Error occurred processing a configuration change listener", e); } } } public LoggingInfo getLogging() { return facade.getLogging(); } public void setLogging(LoggingInfo logging) { facade.setLogging(logging); fireLoggingPostModified(); } @Override public void setApplicationContext(ApplicationContext context) throws BeansException { if (factory instanceof ApplicationContextAware) { ((ApplicationContextAware)factory).setApplicationContext(context); } } public void add(ServiceInfo service) { if (service.getId() != null && facade.getService(service.getId(), ServiceInfo.class) != null) { throw new IllegalArgumentException( "service with id '" + service.getId() + "' already exists" ); } resolve(service); WorkspaceInfo workspace = service.getWorkspace(); if (workspace != null) { if (facade.getServiceByName(service.getName(), workspace, ServiceInfo.class) != null) { throw new IllegalArgumentException( "service with name '" + service.getName() + "' already exists in workspace '" + workspace.getName() + "'" ); } } facade.add(service); //fire post modification event firePostServiceModified(service); } void resolve(ServiceInfo service) { resolveCollections(service); } public static <T> T unwrap(T obj) { return DefaultGeoServerFacade.unwrap(obj); } public <T extends ServiceInfo> T getService(Class<T> clazz) { WorkspaceInfo ws = LocalWorkspace.get(); T service = ws != null ? facade.getService(ws, clazz) : null; service = service != null ? service : facade.getService(clazz); if(service == null) { LOGGER.log(Level.SEVERE, "Could not locate service of type " + clazz + ", local workspace is " + ws); } return service; } @Override public <T extends ServiceInfo> T getService(WorkspaceInfo workspace, Class<T> clazz) { return facade.getService(workspace, clazz); } public <T extends ServiceInfo> T getService(String id, Class<T> clazz) { return facade.getService(id, clazz); } public <T extends ServiceInfo> T getServiceByName(String name, Class<T> clazz) { T service = LocalWorkspace.get() != null ? facade.getServiceByName(name, LocalWorkspace.get(), clazz) : null; return service != null ? service : facade.getServiceByName(name, clazz); } public <T extends ServiceInfo> T getServiceByName(WorkspaceInfo workspace, String name, Class<T> clazz) { return facade.getServiceByName(name, workspace, clazz); } public Collection<? extends ServiceInfo> getServices() { Collection<? extends ServiceInfo> services = LocalWorkspace.get() != null ? facade.getServices(LocalWorkspace.get()) : null; return services != null ? services : facade.getServices(); } @Override public Collection<? extends ServiceInfo> getServices(WorkspaceInfo workspace) { return facade.getServices(workspace); } public void remove(ServiceInfo service) { facade.remove(service); fireServiceRemoved(service); } public void save(GeoServerInfo geoServer) { facade.save(geoServer); //fire post modification event fireGlobalPostModified(); } public void save(LoggingInfo logging) { facade.save(logging); //fire post modification event fireLoggingPostModified(); } void fireGlobalPostModified() { for ( ConfigurationListener l : listeners ) { try { l.handlePostGlobalChange( facade.getGlobal() ); } catch( Exception e ) { LOGGER.log(Level.SEVERE, "Error occurred processing a configuration change listener", e); } } } public void fireGlobalModified(GeoServerInfo global, List<String> changed, List oldValues, List newValues) { for ( ConfigurationListener l : getListeners() ) { try { l.handleGlobalChange( global, changed, oldValues, newValues); } catch( Exception e ) { LOGGER.log(Level.SEVERE, "Error occurred processing a configuration change listener", e); } } } public void fireLoggingModified(LoggingInfo logging, List<String> changed, List oldValues, List newValues) { for ( ConfigurationListener l : getListeners() ) { try { l.handleLoggingChange( logging, changed, oldValues, newValues); } catch( Exception e ) { LOGGER.log(Level.SEVERE, "Error occurred processing a configuration change listener", e); } } } void fireLoggingPostModified() { for ( ConfigurationListener l : listeners ) { try { l.handlePostLoggingChange( facade.getLogging() ); } catch( Exception e ) { LOGGER.log(Level.SEVERE, "Error occurred processing a configuration change listener", e); } } } public void save(ServiceInfo service) { validate(service); facade.save(service); //fire post modification event firePostServiceModified(service); } void validate(ServiceInfo service) { CatalogImpl.validateKeywords(service.getKeywords()); } public void fireServiceModified(ServiceInfo service, List<String> changed, List oldValues, List newValues) { for ( ConfigurationListener l : getListeners() ) { try { l.handleServiceChange( service, changed, oldValues, newValues); } catch( Exception e ) { LOGGER.log(Level.SEVERE, "Error occurred processing a configuration change listener", e); } } } void firePostServiceModified(ServiceInfo service) { for ( ConfigurationListener l : listeners ) { try { l.handlePostServiceChange( service ); } catch( Exception e ) { LOGGER.log(Level.SEVERE, "Error occurred processing a configuration change listener", e); } } } void fireServiceRemoved(ServiceInfo service) { for ( ConfigurationListener l : getListeners() ) { try { l.handleServiceRemove(service); } catch( Exception e ) { LOGGER.log(Level.SEVERE, "Error occurred processing a configuration change listener", e); } } } public void addListener(ConfigurationListener listener) { listeners.add( listener ); } public void removeListener(ConfigurationListener listener) { listeners.remove( listener ); } public Collection<ConfigurationListener> getListeners() { return listeners; } public void dispose() { // look for pluggable handlers for(GeoServerLifecycleHandler handler : GeoServerExtensions.extensions(GeoServerLifecycleHandler.class)) { try { handler.onDispose(); } catch(Throwable t) { LOGGER.log(Level.SEVERE, "A GeoServer lifecycle handler threw an exception during dispose", t); } } // internal cleanup if ( catalog != null ) catalog.dispose(); if ( facade != null ) facade.dispose(); } public void reload() throws Exception { this.reload(null); } public void reload(Catalog newCatalog) throws Exception { // notify start of reload List<GeoServerLifecycleHandler> handlers = GeoServerExtensions .extensions(GeoServerLifecycleHandler.class); for (GeoServerLifecycleHandler handler : handlers) { try { handler.beforeReload(); } catch (Throwable t) { LOGGER.log(Level.SEVERE, "A GeoServer lifecycle handler threw an exception during reload", t); } } // perform the reload try { // flush caches reset(); // reload configuration GeoServerLoaderProxy loader = GeoServerExtensions.bean(GeoServerLoaderProxy.class); synchronized (org.geoserver.config.GeoServer.CONFIGURATION_LOCK) { getCatalog().getResourcePool().dispose(); if(newCatalog != null) { dispose(); //reload catalog, make sure we reload the underlying catalog, not any wrappers Catalog catalog = getCatalog(); if ( catalog instanceof Wrapper ) { catalog = ((Wrapper)getCatalog()).unwrap(Catalog.class); } ((CatalogImpl)catalog).sync((CatalogImpl) newCatalog); ((CatalogImpl)catalog).resolve(); } else { loader.reload(); } } } finally { // notify end of reload for (GeoServerLifecycleHandler handler : handlers) { try { handler.onReload(); } catch (Throwable t) { LOGGER.log(Level.SEVERE, "A GeoServer lifecycle handler threw an exception during reload", t); } } } } public void reset() { // drop all the catalog store/feature types/raster caches catalog.getResourcePool().dispose(); // reset the referencing subsystem CRS.reset("all"); // look for pluggable handlers for(GeoServerLifecycleHandler handler : GeoServerExtensions.extensions(GeoServerLifecycleHandler.class)) { try { handler.onReset(); } catch(Throwable t) { LOGGER.log(Level.SEVERE, "A GeoServer lifecycle handler threw an exception during reset", t); } } } }