Package org.geoserver.jdbcconfig.config

Source Code of org.geoserver.jdbcconfig.config.JDBCGeoServerFacade

/* (c) 2014 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.jdbcconfig.config;

import static org.geoserver.catalog.CatalogFacade.ANY_WORKSPACE;
import static org.geoserver.catalog.Predicates.and;
import static org.geoserver.catalog.Predicates.equal;
import static org.geoserver.catalog.Predicates.isNull;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.rmi.server.UID;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;

import org.geoserver.catalog.Info;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.catalog.impl.ModificationProxy;
import org.geoserver.catalog.util.CloseableIterator;
import org.geoserver.catalog.util.CloseableIteratorAdapter;
import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerFacade;
import org.geoserver.config.GeoServerInfo;
import org.geoserver.config.LoggingInfo;
import org.geoserver.config.ServiceInfo;
import org.geoserver.config.SettingsInfo;
import org.geoserver.jdbcconfig.internal.ConfigDatabase;
import org.geoserver.logging.LoggingStartupContextListener;
import org.geoserver.logging.LoggingUtils;
import org.geoserver.ows.util.OwsUtils;
import org.geoserver.ows.util.ClassProperties;
import org.geoserver.platform.GeoServerResourceLoader;
import org.geotools.util.logging.Logging;
import org.opengis.filter.Filter;
import org.opengis.filter.sort.SortBy;

import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;

@ParametersAreNonnullByDefault
public class JDBCGeoServerFacade implements GeoServerFacade {

    static final Logger LOGGER = Logging.getLogger(JDBCGeoServerFacade.class);

    private static final String GLOBAL_ID = "GeoServerInfo.global";

    private static final String GLOBAL_LOGGING_ID = "LoggingInfo.global";

    private GeoServer geoServer;

    private final ConfigDatabase db;
   
    private GeoServerResourceLoader resourceLoader;

    public void setResourceLoader(GeoServerResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    public JDBCGeoServerFacade(final ConfigDatabase db) {
        this.db = db;
    }

    @SuppressWarnings("deprecation")
    private void reinitializeLogging() {
        try {
            LoggingInfo realLogInfo = this.getLogging();
            if (realLogInfo == null) {
                return;
            }
            LoggingInfo startLogInfo = LoggingStartupContextListener.getLogging(resourceLoader);
           
            // Doing this reflectively so that if LoggingInfo gets new properties, this should still
            // work. KS
           
            ClassProperties properties = OwsUtils.getClassProperties(LoggingInfo.class);
           
            List<String> propertyNames = new ArrayList<String>(properties.properties().size());
            List<Object> newValues = new ArrayList<Object>(properties.properties().size());
            List<Object> oldValues = new ArrayList<Object>(properties.properties().size());
           
            final Level propertyTableLevel = Level.FINE;
            LOGGER.log(propertyTableLevel, "Checking Logging configuration in case it neeeds to be reinitialized");
            for (String propName : properties.properties()) {
               
                // Don't care about the return type
                Method read = properties.getter(propName, null);
               
                Object newVal = read.invoke(realLogInfo);
                Object oldVal = read.invoke(startLogInfo);
               
                if((newVal==null && oldVal==null) || (newVal!=null && newVal.equals(oldVal))) {
                    // Values the same
                    LOGGER.log(propertyTableLevel, "=== {0} (logging.xml: {1}, JDBCConfig: {2})", new Object[] {read.getName(), oldVal, newVal});
                } else {
                    // Values different
                    propertyNames.add(propName);
                    newValues.add(newVal);
                    oldValues.add(oldVal);
                    LOGGER.log(propertyTableLevel, "=/= {0} (logging.xml: {1}, JDBCConfig: {2})", new Object[] {read.getName(), oldVal, newVal});
                }
            }
            // If there's a difference other than the ID
            if(!(propertyNames.isEmpty() || (propertyNames.size()==1 && propertyNames.get(0).equals("Id")))) {
                LOGGER.log(Level.WARNING, "Start up logging config does not match that in JDBCConfig.  Reconfiguring now.  Logs preceding this message may reflect a different configuration.");
                LoggingUtils.initLogging(resourceLoader, realLogInfo.getLevel(), !realLogInfo.isStdOutLogging(), realLogInfo.getLocation());
            }
        } catch (Exception ex) {
            // If something bad happens, log it and keep going with the wrong logging config
            LOGGER.log(Level.SEVERE, "Problem while reinitializing Logging from JDBC Config.  Log configuration may not be correct.", ex);
        }
    }
   
    @Override
    public GeoServer getGeoServer() {
        return geoServer;
    }

    @Override
    public void setGeoServer(GeoServer geoServer) {
        this.geoServer = geoServer;
        this.db.setGeoServer(geoServer);
        reinitializeLogging();
    }

    @Override
    public GeoServerInfo getGlobal() {
        GeoServerInfo global = db.getById(GLOBAL_ID, GeoServerInfo.class);
        return global;
    }

    @Override
    public void setGlobal(GeoServerInfo global) {
        OwsUtils.set(global, "id", GLOBAL_ID);
        if (global.getSettings() == null) {
            SettingsInfo defaultSettings = geoServer.getFactory().createSettings();
            add(defaultSettings);
            global.setSettings(defaultSettings);
        //JD: disabling this check, global settings should have an id
        //}else if(null == global.getSettings().getId()){
        }else {
            add(global.getSettings());
        }
        if (null == getGlobal()) {
            db.add(global);
        } else {
            db.save(ModificationProxy.create(global, GeoServerInfo.class));
        }
        GeoServerInfo saved = getGlobal();
        Preconditions.checkNotNull(saved);
    }

    @Override
    public void save(GeoServerInfo global) {
        // this object is a proxy
        ModificationProxy h = (ModificationProxy) Proxy.getInvocationHandler(global);
        // fire out what changed
        List<String> propertyNames = h.getPropertyNames();
        List<Object> newValues = h.getNewValues();
        List<Object> oldValues = h.getOldValues();

        geoServer.fireGlobalModified(global, propertyNames, oldValues, newValues);

        db.save(global);
    }

    @Override
    public LoggingInfo getLogging() {
        LoggingInfo loggingInfo = db.getById(GLOBAL_LOGGING_ID, LoggingInfo.class);
        return loggingInfo;
    }

    @Override
    public void setLogging(LoggingInfo logging) {
        OwsUtils.set(logging, "id", GLOBAL_LOGGING_ID);
        if (null == getLogging()) {
            db.add(logging);
        } else {
            db.save(ModificationProxy.create(logging, LoggingInfo.class));
        }
        LoggingInfo saved = getLogging();
        Preconditions.checkNotNull(saved);
    }

    @Override
    public void save(LoggingInfo logging) {
        // this object is a proxy
        ModificationProxy h = (ModificationProxy) Proxy.getInvocationHandler(logging);
        // fire out what changed
        List<String> propertyNames = h.getPropertyNames();
        List<Object> newValues = h.getNewValues();
        List<Object> oldValues = h.getOldValues();

        geoServer.fireLoggingModified(logging, propertyNames, oldValues, newValues);

        db.save(logging);
    }

    @Override
    public void add(ServiceInfo service) {
        setId(service, ServiceInfo.class);
        service.setGeoServer(geoServer);
        db.add(service);
    }

    @Override
    public void remove(ServiceInfo service) {
        db.remove(service);
    }

    @Override
    public void save(ServiceInfo service) {
        // this object is a proxy
        ModificationProxy h = (ModificationProxy) Proxy.getInvocationHandler(service);
        // fire out what changed
        List<String> propertyNames = h.getPropertyNames();
        List<Object> newValues = h.getNewValues();
        List<Object> oldValues = h.getOldValues();

        geoServer.fireServiceModified(service, propertyNames, oldValues, newValues);

        db.save(service);
    }

    @Override
    public SettingsInfo getSettings(WorkspaceInfo workspace) {
        Filter filter = equal("workspace.id", workspace.getId());

        return get(SettingsInfo.class, filter);

    }

    @Override
    public void add(SettingsInfo settings) {
        setId(settings, SettingsInfo.class);
        db.add(settings);
    }

    @Override
    public void save(SettingsInfo settings) {
        // this object is a proxy
        ModificationProxy h = (ModificationProxy) Proxy.getInvocationHandler(settings);
        // fire out what changed
        List<String> propertyNames = h.getPropertyNames();
        List<Object> newValues = h.getNewValues();
        List<Object> oldValues = h.getOldValues();

        geoServer.fireSettingsModified(settings, propertyNames, oldValues, newValues);

        db.save(settings);
    }

    @Override
    public void remove(SettingsInfo settings) {
        db.remove(settings);
    }

    @Override
    public Collection<? extends ServiceInfo> getServices() {
        return getServices((WorkspaceInfo) null);
    }

    private Filter filterForWorkspace(WorkspaceInfo workspace) {
        if (workspace != null && workspace != ANY_WORKSPACE) {
            return equal("workspace.id", workspace.getId());
        } else {
            return filterForGlobal();
        }
    }
    private Filter filterForGlobal() {
        return isNull("workspace.id");
    }
   
    @SuppressWarnings("unchecked")
    private <T extends ServiceInfo> CloseableIterator<T> filterServices(final Class<T> clazz, CloseableIterator<ServiceInfo> it) {
        return (CloseableIterator<T>) CloseableIteratorAdapter.filter(it, new Predicate<ServiceInfo>(){
           
            @Override
            public boolean apply(@Nullable ServiceInfo input) {
                return clazz.isAssignableFrom(input.getClass());
            }
           
        });
    }
   
    @Override
    public Collection<? extends ServiceInfo> getServices(WorkspaceInfo workspace) {
       
        Filter filter = filterForWorkspace(workspace);
        return db.queryAsList(ServiceInfo.class, filter, null, null, null);
    }

    @Override
    public <T extends ServiceInfo> T getService(final Class<T> clazz) {
        Filter filter = filterForGlobal();
        List<ServiceInfo> all = db.queryAsList(ServiceInfo.class, filter, null, null, null);
        for (ServiceInfo si : all) {
            if (clazz.isAssignableFrom(si.getClass())) {
                return clazz.cast(si);
            }
        }
        return null;
    }

    @Override
    public <T extends ServiceInfo> T getService(final WorkspaceInfo workspace, final Class<T> clazz) {
       
        Filter filter = filterForWorkspace(workspace);
       
        // In order to handle new service types, get all services, deserialize them, and then filter
        // by checking if the implement the given interface.  Since there shouldn't be too many per
        // workspace, this shouldn't be a significant performance problem.
        CloseableIterator<T> it = filterServices(clazz, db.query(ServiceInfo.class, filter, null, null, (SortBy)null));
       
        T service;
        if (it.hasNext()){
            service = it.next();
        } else {
            if(LOGGER.isLoggable(Level.FINE)) LOGGER.log(Level.FINE, "Could not find service of type "+clazz+" in "+workspace);
            return null;
        }
       
        if(it.hasNext()) {
            LOGGER.log(Level.WARNING, "Found multiple services of type "+clazz+" in "+ workspace);
            return null;
        }
        return service;
    }

    @Override
    public <T extends ServiceInfo> T getService(final String id, final Class<T> clazz) {
        return db.getById(id, clazz);
    }

    @Override
    public <T extends ServiceInfo> T getServiceByName(final String name, final Class<T> clazz) {
        return findByName(name, null, clazz);
    }

    @Override
    public <T extends ServiceInfo> T getServiceByName(final String name,
            final WorkspaceInfo workspace, final Class<T> clazz) {

        return findByName(name, workspace, clazz);
    }

    private <T extends Info> T findByName(@Nonnull final String name,
            @Nullable final WorkspaceInfo workspace, @Nonnull final Class<T> clazz)
            throws AssertionError {

        Filter filter = equal("name", name);
        if (null != workspace && ANY_WORKSPACE != workspace) {
            final String wsId = workspace.getId();
            Filter wsFilter = equal("workspace.id", wsId);
            filter = and(filter, wsFilter);
        }
        try {
            return get(clazz, filter);
        } catch (IllegalArgumentException multipleResults) {
            return null;
        }
    }

    public <T extends Info> T get(Class<T> type, Filter filter) throws IllegalArgumentException {

        CloseableIterator<T> it = db.query(type, filter, null, 2, (org.opengis.filter.sort.SortBy)null);
        T result = null;
        try {
            if (it.hasNext()) {
                result = it.next();
                if (it.hasNext()) {
                    throw new IllegalArgumentException(
                            "Specified query predicate resulted in more than one object");
                }
            }
        } finally {
            it.close();
        }
        return result;
    }

    @Override
    public void dispose() {
        db.dispose();
    }

    private void setId(Info info, Class<? extends Info> type) {
        final String curId = info.getId();
        if (null == curId) {
            final String uid = new UID().toString();
            final String id = type.getSimpleName() + "." + uid;
            OwsUtils.set(info, "id", id);
        }
    }
}
TOP

Related Classes of org.geoserver.jdbcconfig.config.JDBCGeoServerFacade

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.