Package org.vfny.geoserver.global

Source Code of org.vfny.geoserver.global.Data

/* Copyright (c) 2001, 2003 TOPP - www.openplans.org.  All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.vfny.geoserver.global;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.logging.Level;

import org.geotools.data.DataStore;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FeatureSource;
import org.geotools.data.LockingManager;
import org.geotools.data.Transaction;
import org.geotools.feature.AttributeType;
import org.geotools.feature.FeatureType;
import org.geotools.styling.SLDParser;
import org.geotools.styling.Style;
import org.geotools.styling.StyleFactory;
import org.vfny.geoserver.global.dto.AttributeTypeInfoDTO;
import org.vfny.geoserver.global.dto.DataDTO;
import org.vfny.geoserver.global.dto.DataStoreInfoDTO;
import org.vfny.geoserver.global.dto.DataTransferObjectFactory;
import org.vfny.geoserver.global.dto.FeatureTypeInfoDTO;
import org.vfny.geoserver.global.dto.NameSpaceInfoDTO;
import org.vfny.geoserver.global.dto.StyleDTO;


/**
* This class stores all the information that a catalog would (and
* CatalogConfig used to).
*
* @author Gabriel Roldan, Axios Engineering
* @author Chris Holmes
* @author dzwiers
* @version $Id: Data.java,v 1.45 2004/09/13 16:05:10 cholmesny Exp $
*/
public class Data extends GlobalLayerSupertype /*implements Repository*/ {
    public static final String WEB_CONTAINER_KEY = "DATA";

    /** Default name of feature type information */
    private static final String INFO_FILE = "info.xml";

    /** used to create styles */
    private static StyleFactory styleFactory = StyleFactory.createStyleFactory();

    /** holds the mappings between prefixes and NameSpaceInfo objects */
    private Map nameSpaces;

    /** NameSpaceInfo */
    private NameSpaceInfo defaultNameSpace;

    /** Mapping of DataStoreInfo by dataStoreId */
    private Map dataStores;

    /** holds the mapping of Styles and style names */
    private Map styles;
    private Map stFiles;

    /**
     * Map of <code>FeatureTypeInfo</code>'s stored by full qualified name
     * (NameSpaceInfo prefix + PREFIX_DELIMITER + typeName)
     */
    private Map featureTypes;

    /** Base directory for use with file based relative paths */
    private File baseDir;

    /**
     * Data constructor.
     *
     * <p>
     * Creates a Data object from the data provided.
     * </p>
     */
    private GeoServer gs;

    /**
     * map of all featureTypeDTO -> load status (Boolean.True, Boolean.False,
     * Exception) Boolean.True when feature was loaded. Boolean.False when
     * something was disabled. Exception the error.
     */
    private Map errors;

    public Data(DataDTO config, File dir, GeoServer g)
        throws ConfigurationException {
        baseDir = dir;
        load(config);
        gs = g;
    }

    public Data(File dir, GeoServer g) throws ConfigurationException {
        baseDir = dir;
        gs = g;
    }

    GeoServer getGeoServer() {
        return gs;
    }

    /**
     * Data constructor.
     *
     * <p>
     * package only constructor for GeoServer to call.
     * </p>
     *
     * @param config DOCUMENT ME!
     *
     * @throws NullPointerException DOCUMENT ME!
     */

    /*Data() {
       nameSpaces = new HashMap();
       styles = new HashMap();
       featureTypes = new HashMap();
       dataStores = new HashMap();
       }*/

    /**
     * Places the data in this container and innitializes it. Complex tests are
     * performed to detect existing datasources,  while the remainder only
     * include simplistic id checks.
     *
     * @param config
     *
     * @throws NullPointerException
     */
    public void load(DataDTO config) {
        if (config == null) {
            throw new NullPointerException("Non null DataDTO required for load");
        }

        // Step 1: load dataStores and Namespaces
        dataStores = loadDataStores(config);
        nameSpaces = loadNamespaces(config);
        defaultNameSpace = (NameSpaceInfo) nameSpaces.get(config
                .getDefaultNameSpacePrefix());

        // Step 2: set up styles
        styles = loadStyles(config);

        // Step 3: load featureTypes
        featureTypes = loadFeatureTypes(config);
    }

    public Set getDataStores() {
        return new HashSet(dataStores.values());
    }

    /**
     * Configure a map of DataStoreInfo by dataStoreId.
     *
     * <p>
     * This method is order dependent and should be called by load( DataDTO ).
     * This method may have to be smarter in the face of reloads.
     * </p>
     *
     * <p>
     * Note that any disabled DTO will not be added to the map.
     * </p>
     *
     * <p>
     * This method is just to make laod( DataDTO ) readable, making it private
     * final will help
     * </p>
     *
     * @param dto
     *
     * @return DOCUMENT ME!
     *
     * @throws NullPointerException DOCUMENT ME!
     */
    private final Map loadDataStores(DataDTO dto) {
        if ((dto == null) || (dto.getDataStores() == null)) {
            throw new NullPointerException(
                "Non null list of DataStores required");
        }

        Map map = new HashMap();

        for (Iterator i = dto.getDataStores().values().iterator(); i.hasNext();) {
            DataStoreInfoDTO dataStoreDTO = (DataStoreInfoDTO) i.next();
            String id = dataStoreDTO.getId();

            DataStoreInfo dataStoreInfo = new DataStoreInfo(dataStoreDTO, this);
            map.put(id, dataStoreInfo);

            if (dataStoreDTO.isEnabled()) {
                LOGGER.finer("Register DataStore '" + id + "'");
            } else {
                LOGGER.fine("Did not Register DataStore '" + id
                    + "' as it was not enabled");
            }
        }

        return map;
    }

    /**
     * Configure a map of NamespaceInfo by prefix.
     *
     * <p>
     * This method is order dependent and should be called by load( DataDTO ).
     * This method may have to be smarter in the face of reloads.
     * </p>
     *
     * <p>
     * This method is just to make laod( DataDTO ) readable, making it private
     * final will help
     * </p>
     *
     * @param dto
     *
     * @return DOCUMENT ME!
     *
     * @throws NullPointerException DOCUMENT ME!
     */
    private final Map loadNamespaces(DataDTO dto) {
        if ((dto == null) || (dto.getNameSpaces() == null)) {
            throw new NullPointerException(
                "Non null list of NameSpaces required");
        }

        Map map = new HashMap();

        for (Iterator i = dto.getNameSpaces().values().iterator(); i.hasNext();) {
            NameSpaceInfoDTO namespaceDto = (NameSpaceInfoDTO) i.next();
            String prefix = namespaceDto.getPrefix();
            NameSpaceInfo namespaceInfo = new NameSpaceInfo(this, namespaceDto);

            map.put(prefix, namespaceInfo);
        }

        return map;
    }

    /**
     * Configure a map of FeatureTypeInfo by prefix:typeName.
     *
     * <p>
     * Note that this map uses namespace prefix (not datastore ID like the the
     * configuration system). That is because this is the actual runtime, in
     * which we access FeatureTypes by namespace. The configuration system
     * uses dataStoreId which is assumed to be more stable across changes (one
     * can reassing a FeatureType to a different namespace, but not a
     * different dataStore).
     * </p>
     *
     * <p>
     * Note loadDataStores() and loadNamespaces() must be called prior to using
     * this function!
     * </p>
     *
     * @param dto configDTO
     *
     * @return
     *
     * @throws NullPointerException DOCUMENT ME!
     */
    private final Map loadFeatureTypes(DataDTO dto) {
        errors = new HashMap();
        featureTypes = new HashMap(); // to fix lazy loading

        if ((dto == null) || (dto.getFeaturesTypes() == null)) {
            errors = null;
            throw new NullPointerException(
                "Non null list of FeatureTypes required");
        }

        Map map = new HashMap();

SCHEMA:
        for (Iterator i = dto.getFeaturesTypes().values().iterator();
                i.hasNext();) {
            FeatureTypeInfoDTO featureTypeDTO = (FeatureTypeInfoDTO) i.next();

            if (featureTypeDTO == null) {
                LOGGER.warning("Ignore null FeatureTypeInfo DTO!");

                continue;
            }

            String key = featureTypeDTO.getKey(); // dataStoreId:typeName

            LOGGER.finer("FeatureType " + key
                + ": loading feature type info dto:" + featureTypeDTO);

            String dataStoreId = featureTypeDTO.getDataStoreId();
            LOGGER.finest("FeatureType " + key + " looking up :" + dataStoreId);

            DataStoreInfo dataStoreInfo = (DataStoreInfo) dataStores.get(dataStoreId);

            if (dataStoreInfo == null) {
                LOGGER.severe("FeatureTypeInfo " + key
                    + " could not be used - DataStore " + dataStoreId
                    + " is not defined!");

                DataStoreInfoDTO tmp = (DataStoreInfoDTO) dto.getDataStores()
                                                             .get(dataStoreId);

                if ((tmp != null) && (!tmp.isEnabled())) {
                    errors.put(featureTypeDTO, Boolean.FALSE);
                } else {
                    errors.put(featureTypeDTO,
                        new ConfigurationException("FeatureTypeInfo " + key
                            + " could not be used - DataStore " + dataStoreId
                            + " is not defined!"));
                }

                continue;
            } else {
                LOGGER.finest(key + " datastore found :" + dataStoreInfo);
            }

            Style s = getStyle(featureTypeDTO.getDefaultStyle());
           
            if (s == null) {
                LOGGER.severe("FeatureTypeInfo " + key + " ignored - Style '"
                    + featureTypeDTO.getDefaultStyle() + "' not found!");

                errors.put(featureTypeDTO,
                    new ConfigurationException("FeatureTypeInfo " + key
                        + " ignored - Style '"
                        + featureTypeDTO.getDefaultStyle() + "' not found!"));

                continue SCHEMA;
            }

            // Check attributes configured correctly against schema
            String typeName = featureTypeDTO.getName();

            try {
                DataStore dataStore = dataStoreInfo.getDataStore();
                FeatureType featureType = dataStore.getSchema(typeName);

                Set attributeNames = new HashSet();
                Set ATTRIBUTENames = new HashSet();

                //as far as I can tell an emtpy list indicates that no
                //schema.xml file was found.  I may be approaching this
                //all wrong, is this logic contained elsewhere?
                //CH: Yeah, this shit was super messed up.  It was causing null pointer
                //exceptions, and then it created this createAttrDTO flag that wasn't
                //then used by anyone.  So I fixed the null and made it so it creates
                //AttributeTypeInfoDTO's (once again, I hate these) from the FeatureType
                //of the real datastore.
                //boolean createAttrDTO = (featureTypeDTO.getSchemaAttributes().size() == 0);
                LOGGER.fine("loading datastore " + typeName);

                boolean createAttrDTO;

                if (featureTypeDTO.getSchemaAttributes() == null) {
                    createAttrDTO = true;
                } else {
                    createAttrDTO = featureTypeDTO.getSchemaAttributes().size() == 0;
                }

                if (createAttrDTO) {
                    List attributeDTOs = createAttrDTOsFromSchema(featureType);
                    featureTypeDTO.setSchemaAttributes(attributeDTOs);
                    LOGGER.finer(
                        "No schema found, setting featureTypeDTO with "
                        + attributeDTOs);
                } else {
                    for (int index = 0;
                            index < featureType.getAttributeCount(); index++) {
                        AttributeType attrib = featureType.getAttributeType(index);
                        attributeNames.add(attrib.getName());
                        ATTRIBUTENames.add(attrib.getName().toUpperCase());
                    }

                    if (featureTypeDTO.getSchemaAttributes() != null) {
                        for (Iterator a = featureTypeDTO.getSchemaAttributes()
                                                        .iterator();
                                a.hasNext();) {
                            AttributeTypeInfoDTO attribDTO = (AttributeTypeInfoDTO) a
                                .next();
                            String attributeName = attribDTO.getName();

                            if (!attributeNames.contains(attributeName)) {
                                if (ATTRIBUTENames.contains(
                                            attributeName.toUpperCase())) {
                                    LOGGER.severe("FeatureTypeInfo " + key
                                        + " ignored - attribute '"
                                        + attributeName
                                        + "' not found - please check captialization");
                                } else {
                                    LOGGER.severe("FeatureTypeInfo " + key
                                        + " ignored - attribute '"
                                        + attributeName + "' not found!");

                                    String names = "";
                                    Iterator x = attributeNames.iterator();

                                    if (x.hasNext()) {
                                        names = x.next().toString();
                                    }

                                    while (x.hasNext())
                                        names = ":::" + x.next().toString();

                                    LOGGER.severe(
                                        "Valid attribute names include :::"
                                        + names);
                                }

                                errors.put(featureTypeDTO,
                                    new ConfigurationException(
                                        "FeatureTypeInfo " + key
                                        + " could not be used - DataStore "
                                        + dataStoreId + " is not defined!"));

                                continue SCHEMA;
                            }
                        }
                    }
                }
            } catch (IllegalStateException illegalState) {
                LOGGER.severe("FeatureTypeInfo " + key
                    + " ignored - as DataStore " + dataStoreId
                    + " is disabled!");
                errors.put(featureTypeDTO, Boolean.FALSE);

                continue;
            } catch (IOException ioException) {
                LOGGER.log(Level.SEVERE,
                    "FeatureTypeInfo " + key + " ignored - as DataStore "
                    + dataStoreId + " is unavailable:" + ioException);
                LOGGER.log(Level.FINEST, key + " unavailable", ioException);
                errors.put(featureTypeDTO, ioException);

                continue;
            } catch (Throwable unExpected) {
                LOGGER.log(Level.SEVERE,
                    "FeatureTypeInfo " + key + " ignored - as DataStore "
                    + dataStoreId + " is broken:" + unExpected);
                unExpected.printStackTrace();
                LOGGER.log(Level.FINEST, key + " unavailable", unExpected);

                errors.put(featureTypeDTO, unExpected);

                continue;
            }

            String prefix = dataStoreInfo.getNamesSpacePrefix();

            LOGGER.finest("FeatureType " + key
                + " creating FeatureTypeInfo for " + prefix + ":" + typeName);

            FeatureTypeInfo featureTypeInfo = null;

            try {
                featureTypeInfo = new FeatureTypeInfo(featureTypeDTO, this);
            } catch (ConfigurationException configException) {
                LOGGER.log(Level.SEVERE,
                    "FeatureTypeInfo " + key
                    + " ignored - configuration problem:" + configException);
                LOGGER.log(Level.FINEST, key + " unavailable", configException);
                errors.put(featureTypeDTO, configException);

                continue;
            }

            String key2 = prefix + ":" + typeName;

            if (map.containsKey(key2)) {
                LOGGER.severe("FeatureTypeInfo '" + key2
                    + "' already defined - you must have duplicate defined?");
                errors.put(featureTypeDTO,
                    new ConfigurationException("FeatureTypeInfo '" + key2
                        + "' already defined - you must have duplicate defined?"));
            } else {
                LOGGER.finest("FeatureTypeInfo " + key2
                    + " has been created...");
                map.put(key2, featureTypeInfo);

                LOGGER.finest("FeatureTypeInfo '" + key2 + "' is registered:"
                    + dataStoreInfo);
                errors.put(featureTypeDTO, Boolean.TRUE);
            }
        }

        return map;
    }

    private List createAttrDTOsFromSchema(FeatureType featureType) {
        List attrList = DataTransferObjectFactory.generateAttributes(featureType);

        /*   new ArrayList(featureType.getAttributeCount());
           for (int index = 0; index < featureType.getAttributeCount(); index++) {
               AttributeType attrib = featureType.getAttributeType(index);
               attrList.add(new AttributeTypeInfoDTO(attrib));
           }*/
        return attrList;
    }

    /**
     * Generate map of geotools2 Styles by id.
     *
     * <p>
     * The filename specified by the StyleDTO will be used to generate the
     * resulting Styles.
     * </p>
     *
     * @param dto requested configuration
     *
     * @return Map of Style by id
     *
     * @throws NullPointerException If the style could not be loaded from the
     *         filename
     *
     * @see Data.loadStyle() for more information
     */
    private final Map loadStyles(DataDTO dto) {
        Map map = new HashMap();
        stFiles = new HashMap();

        if ((dto == null) || (dto.getStyles() == null)) {
            throw new NullPointerException("List of styles is required");
        }

        for (Iterator i = dto.getStyles().values().iterator(); i.hasNext();) {
            StyleDTO styleDTO = (StyleDTO) i.next();
            String id = styleDTO.getId();
            Style style;

            try {
                style = loadStyle(styleDTO.getFilename());
                //HACK: due to our crappy weird id shit we rename the style's specified
                //name with the id we (and our clients) refer to the style as.
                //Should redo style management to not make use of our weird ids, just
                //use the style's name out of the styles directory.
                style.setName(id);
            } catch (Exception ioException) { // was IOException
                LOGGER.log(Level.SEVERE, "Could not load style " + id,
                    ioException);

                continue;
            }

            stFiles.put(id, styleDTO.getFilename());
            map.put(id, style);
        }

        LOGGER.finer("returning styles " + map + "\n and set map " + stFiles);

        return map;
    }

    /**
     * Status output
     *
     * @param title DOCUMENT ME!
     * @param status DOCUMENT ME!
     */
    static final void outputStatus(String title, Map status) {
        LOGGER.info(title);

        for (Iterator i = status.entrySet().iterator(); i.hasNext();) {
            Map.Entry entry = (Map.Entry) i.next();
            String key = (String) entry.getKey();
            Object value = entry.getValue();

            if (value == Boolean.TRUE) {
                LOGGER.fine(key + ": ready");
            } else if (value instanceof Throwable) {
                Throwable t = (Throwable) value;
                LOGGER.log(Level.SEVERE, key + " not ready", t);
            } else {
                LOGGER.warning(key + ": '" + value + "'");
            }
        }
    }

    /**
     * Dynamically tries to connect to every DataStore!
     *
     * <p>
     * Returns a map of Exception by dataStoreId:typeName. If by some marvel
     * the we could connect to a FeatureSource we will record Boolean.TRUE.
     * </p>
     *
     * @return Map of Exception by dataStoreId:typeName
     */
    public Map statusDataStores() {
        Map m = new HashMap();
        Iterator i = errors.entrySet().iterator();

        while (i.hasNext()) {
            Map.Entry e = (Map.Entry) i.next();
            FeatureTypeInfoDTO ftdto = (FeatureTypeInfoDTO) e.getKey();
            m.put(ftdto.getDataStoreId() + ":" + ftdto.getName(), e.getValue());
        }

        return m;
    }

    /**
     * Dynamically tries to connect to every Namespace!
     *
     * <p>
     * Returns a map of Exception by prefix:typeName. If by some marvel the we
     * could connect to a FeatureSource we will record Boolean.TRUE.
     * </p>
     *
     * @return Map of Exception by prefix:typeName
     */
    public Map statusNamespaces() {
        Map m = new HashMap();
        Iterator i = errors.entrySet().iterator();

        while (i.hasNext()) {
            Map.Entry e = (Map.Entry) i.next();
            FeatureTypeInfoDTO ftdto = (FeatureTypeInfoDTO) e.getKey();
            DataStoreInfo dsdto = (DataStoreInfo) dataStores.get(ftdto
                    .getDataStoreId());

            if (dsdto != null) {
                m.put(dsdto.getNamesSpacePrefix() + ":" + ftdto.getName(),
                    e.getValue());
            }
        }

        return m;
    }

   

    /**
     * toDTO purpose.
     *
     * <p>
     * This method is package visible only, and returns a reference to the
     * GeoServerDTO. This method is unsafe, and should only be used with
     * extreme caution.
     * </p>
     *
     * @return DataDTO the generated object
     */
    public Object toDTO() {
        DataDTO dto = new DataDTO();

        HashMap tmp;
        Iterator i;
        tmp = new HashMap();
        i = nameSpaces.keySet().iterator();

        while (i.hasNext()) {
            NameSpaceInfo nsi = (NameSpaceInfo) nameSpaces.get(i.next());
            tmp.put(nsi.getPrefix(), nsi.toDTO());
        }

        dto.setNameSpaces(tmp);

        if (defaultNameSpace != null) {
            dto.setDefaultNameSpacePrefix(defaultNameSpace.getPrefix());
        }

        tmp = new HashMap();
        i = styles.keySet().iterator();

        while (i.hasNext()) {
            String id = (String) i.next();
            Style st = (Style) styles.get(id);
            StyleDTO sdto = new StyleDTO();
            sdto.setDefault(st.isDefault());
            sdto.setFilename((File) stFiles.get(id));
            sdto.setId(id);
            tmp.put(id, sdto);
        }

        LOGGER.finer("setting styles to: " + tmp);
        dto.setStyles(tmp);

        tmp = new HashMap();
        i = dataStores.keySet().iterator();

        while (i.hasNext()) {
            DataStoreInfo dsi = (DataStoreInfo) dataStores.get(i.next());
            tmp.put(dsi.getId(), dsi.toDTO());
        }

        dto.setDataStores(tmp);

        tmp = new HashMap();
        i = errors.keySet().iterator();

        while (i.hasNext()) {
            FeatureTypeInfoDTO fti = (FeatureTypeInfoDTO) i.next();
            tmp.put(fti.getKey(), fti.clone());   //DJB:  changed to getKey() from getName() which was NOT unique!
        }

        dto.setFeaturesTypes(tmp);

        return dto;
    }

    /**
     * Locate a DataStoreInfo by its id attribute.
     *
     * @param id the DataStoreInfo id looked for
     *
     * @return the DataStoreInfo with id attribute equals to <code>id</code> or
     *         null if there no exists
     */
    public DataStoreInfo getDataStoreInfo(String id) {
        DataStoreInfo dsi = (DataStoreInfo) dataStores.get(id);

        if ((dsi != null) && dsi.isEnabled()) {
            return dsi;
        }

        return null;
    }

    /**
     * getNameSpaces purpose.
     *
     * <p>
     * List of all relevant namespaces
     * </p>
     *
     * @return NameSpaceInfo[]
     */
    public NameSpaceInfo[] getNameSpaces() {
        NameSpaceInfo[] ns = new NameSpaceInfo[nameSpaces.values().size()];

        return (NameSpaceInfo[]) new ArrayList(nameSpaces.values()).toArray(ns);
    }

    /**
     * getNameSpace purpose.
     *
     * <p>
     * The NameSpaceInfo from the specified prefix
     * </p>
     *
     * @param prefix
     *
     * @return NameSpaceInfo resulting from the specified prefix
     */
    public NameSpaceInfo getNameSpace(String prefix) {
        NameSpaceInfo retNS = (NameSpaceInfo) nameSpaces.get(prefix);

        return retNS;
    }

    /**
     * getDefaultNameSpace purpose.
     *
     * <p>
     * Returns the default NameSpaceInfo for this Data object.
     * </p>
     *
     * @return NameSpaceInfo the default name space
     */
    public NameSpaceInfo getDefaultNameSpace() {
        return defaultNameSpace;
    }

    /**
     * getStyles purpose.
     *
     * <p>
     * A reference to the map of styles
     * </p>
     *
     * @return Map A map containing the Styles.
     */
    public Map getStyles() {
        return this.styles;
    }

    public Style getStyle(String id) {
        return (Style) styles.get(id);
    }

    /**
     * Locate FeatureTypeInfo by name
     *
     * <p>
     * The following searchness is used::
     *
     * <ul>
     * <li>
     * search prefix:typeName for direct match with name
     * </li>
     * <li>
     * search prefix:typeName for match with defaultnamespaceprefix:name
     * </li>
     * <li>
     * linear search of typeName for direct match
     * </li>
     * </ul>
     * </p>
     *
     * <p>
     * Yes this is the magic method used by TransasctionResponse. If you
     * wondered what it was doing - this is it.
     * </p>
     *
     * @param name String The FeatureTypeInfo Name
     *
     * @return FeatureTypeInfo
     *
     * @throws NoSuchElementException
     */
    public FeatureTypeInfo getFeatureTypeInfo(String name)
        throws NoSuchElementException {
        LOGGER.fine("getting type " + name);

        FeatureTypeInfo found = null;

        found = (FeatureTypeInfo) featureTypes.get(name);

        if (found != null) {
            return found;
        }

        String defaultPrefix = defaultNameSpace.getPrefix();
        found = (FeatureTypeInfo) featureTypes.get(defaultPrefix + ":" + name);

        if (found != null) {
            return found;
        }

        for (Iterator i = featureTypes.values().iterator(); i.hasNext();) {
            FeatureTypeInfo fto = (FeatureTypeInfo) i.next();

            if ((name != null) && name.equals(fto.getName())) {
                found = fto;
            }
        }

        if (found != null) {
            return found;
        }

        throw new NoSuchElementException("Could not locate FeatureTypeConfig '"
            + name + "'");
    }

    /**
     * Gets a FeatureTypeInfo from a local type name (ie unprefixed), and a
     * uri.
     *
     * <p>
     * This method is slow, use getFeatureType(String typeName), where
     * possible.  For not he only user should be TransactionFeatureHandler.
     * </p>
     *
     * <p>
     * TODO: Jody here - David is this still correct?
     * </p>
     *
     * @param typename Name NameSpaceInfo name
     * @param uri NameSpaceInfo uri
     *
     * @return FeatureTypeInfo
     */
    public FeatureTypeInfo getFeatureTypeInfo(String typename, String uri) {
        //System.out.println("Finding TypeName = "+typename+" URI = "+uri);
        for (Iterator it = featureTypes.values().iterator(); it.hasNext();) {
            FeatureTypeInfo fType = (FeatureTypeInfo) it.next();

            if (fType.isEnabled()) {
                String typeId = fType.getNameSpace().getPrefix() + ":"
                    + typename;
                boolean t1 = fType.getName().equals(typeId);
                boolean t2 = fType.getNameSpace().getUri().equals(uri);

                //System.out.println("Type id = "+typeId+" real name = "+fType.getName()+" T1="+t1+" T2="+t2);
                //if (t1 && t2) {
                /**
                 * GR:
                 * @HACK it seems not to be working, so I'm just comparing
                 * the prefixed name (don't should it be enough?)
                 */
                if (t1) {
                    return fType;
                }
            }
        }

        return null;
    }

    /**
     * Retrieve map of FeatureTypeInfo by prefix:typeName.
     *
     * <p>
     * Returns all the featuretype information objects
     * </p>
     *
     * @return Map of FetureTypeInfo by prefix:typeName
     */
    public Map getFeatureTypeInfos() {
        return Collections.unmodifiableMap(featureTypes);
    }

    //TODO: detect if a user put a full url, instead of just one to be resolved, and
    //use that instead.
    public Style loadStyle(String fileName, String base)
        throws IOException {
        return loadStyle(new File(base + fileName));
    }

    /**
     * Load GeoTools2 Style from a fileName
     *
     * @param fileName DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     *
     * @throws IOException DOCUMENT ME!
     */
    public Style loadStyle(File fileName) throws IOException {
        SLDParser stylereader = new SLDParser(styleFactory, fileName);

        return stylereader.readXML()[0];
    }

    /**
     * tests whether a given file is a file containing type information.
     *
     * @param testFile the file to test.
     *
     * @return <tt>true</tt> if the file has type info.
     */
    private static boolean isInfoFile(File testFile) {
        String testName = testFile.getAbsolutePath();
        int start = testName.length() - INFO_FILE.length();
        int end = testName.length();

        return testName.substring(start, end).equals(INFO_FILE);
    }

    /**
     * The number of connections currently held.
     *
     * <p>
     * We will need to modify DataStore to provide access to the current count
     * of its connection pool (if appropriate). Right now we are asumming a
     * one DataStore equals One "Connection".
     * </p>
     *
     * <p>
     * This is a good compromize since I just want to indicate the amount of
     * resources currently tied up by GeoServer.
     * </p>
     *
     * @return Number of available connections.
     */
    public int getConnectionCount() {
        int count = 0;

        for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
            DataStoreInfo meta = (DataStoreInfo) i.next();

            if (!meta.isEnabled()) {
                continue; // disabled
            }

            DataStore dataStore;

            try {
                dataStore = meta.getDataStore();
            } catch (Throwable notAvailable) {
                continue; // not available
            }

            // TODO: All DataStore to indicate number of connections
            count += 1;
        }

        return count;
    }

    /**
     * Count locks currently held.
     *
     * <p>
     * Not sure if this should be the number of features locked, or the number
     * of FeatureLocks in existence (a FeatureLock may lock several features.
     * </p>
     *
     * @return number of locks currently held
     */
    public int getLockCount() {
        int count = 0;

        for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
            DataStoreInfo meta = (DataStoreInfo) i.next();

            if (!meta.isEnabled()) {
                continue; // disabled
            }

            DataStore dataStore;

            try {
                dataStore = meta.getDataStore();
            } catch (IllegalStateException notAvailable) {
                continue; // not available
            } catch (Throwable huh) {
                continue; // not even working
            }

            LockingManager lockingManager = dataStore.getLockingManager();

            if (lockingManager == null) {
                continue; // locks not supported
            }

            // TODO: implement LockingManger.getLockSet()
            // count += lockingManager.getLockSet();            
        }

        return count;
    }

    /**
     * Release all feature locks currently held.
     *
     * <p>
     * This is the implementation for the Admin "free lock" action, transaction
     * locks are not released.
     * </p>
     *
     * @return Number of locks released
     */
    public int lockReleaseAll() {
        int count = 0;

        for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
            DataStoreInfo meta = (DataStoreInfo) i.next();

            if (!meta.isEnabled()) {
                continue; // disabled
            }

            DataStore dataStore;

            try {
                dataStore = meta.getDataStore();
            } catch (IllegalStateException notAvailable) {
                continue; // not available
            } catch (Throwable huh) {
                continue; // not even working
            }

            LockingManager lockingManager = dataStore.getLockingManager();

            if (lockingManager == null) {
                continue; // locks not supported
            }

            // TODO: implement LockingManger.releaseAll()
            //count += lockingManager.releaseAll();           
        }

        return count;
    }

    /**
     * Release lock by authorization
     *
     * @param lockID
     */
    public void lockRelease(String lockID) {
        boolean refresh = false;

        for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
            DataStoreInfo meta = (DataStoreInfo) i.next();

            if (!meta.isEnabled()) {
                continue; // disabled
            }

            DataStore dataStore;

            try {
                dataStore = meta.getDataStore();
            } catch (IllegalStateException notAvailable) {
                continue; // not available
            }

            LockingManager lockingManager = dataStore.getLockingManager();

            if (lockingManager == null) {
                continue; // locks not supported
            }

            Transaction t = new DefaultTransaction("Refresh "
                    + meta.getNameSpace());

            try {
                t.addAuthorization(lockID);

                if (lockingManager.release(lockID, t)) {
                    refresh = true;
                }
            } catch (IOException e) {
                LOGGER.log(Level.WARNING, e.getMessage(), e);
            } finally {
                try {
                    t.close();
                } catch (IOException closeException) {
                    LOGGER.log(Level.FINEST, closeException.getMessage(),
                        closeException);
                }
            }
        }

        if (!refresh) {
            // throw exception? or ignore...
        }
    }

    /**
     * Refresh lock by authorization
     *
     * <p>
     * Should use your own transaction?
     * </p>
     *
     * @param lockID
     */
    public void lockRefresh(String lockID) {
        boolean refresh = false;

        for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
            DataStoreInfo meta = (DataStoreInfo) i.next();

            if (!meta.isEnabled()) {
                continue; // disabled
            }

            DataStore dataStore;

            try {
                dataStore = meta.getDataStore();
            } catch (IllegalStateException notAvailable) {
                continue; // not available
            }

            LockingManager lockingManager = dataStore.getLockingManager();

            if (lockingManager == null) {
                continue; // locks not supported
            }

            Transaction t = new DefaultTransaction("Refresh "
                    + meta.getNameSpace());

            try {
                t.addAuthorization(lockID);

                if (lockingManager.refresh(lockID, t)) {
                    refresh = true;
                }
            } catch (IOException e) {
                LOGGER.log(Level.WARNING, e.getMessage(), e);
            } finally {
                try {
                    t.close();
                } catch (IOException closeException) {
                    LOGGER.log(Level.FINEST, closeException.getMessage(),
                        closeException);
                }
            }
        }

        if (!refresh) {
            // throw exception? or ignore...
        }
    }

    /**
     * Implement lockRefresh.
     *
     * @param lockID
     * @param t
     *
     * @return true if lock was found and refreshed
     *
     * @throws IOException
     *
     * @see org.geotools.data.Data#lockRefresh(java.lang.String,
     *      org.geotools.data.Transaction)
     */
    public boolean lockRefresh(String lockID, Transaction t)
        throws IOException {
        boolean refresh = false;

        for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
            DataStoreInfo meta = (DataStoreInfo) i.next();

            if (!meta.isEnabled()) {
                continue; // disabled
            }

            DataStore dataStore;

            try {
                dataStore = meta.getDataStore();
            } catch (IllegalStateException notAvailable) {
                continue; // not available
            }

            LockingManager lockingManager = dataStore.getLockingManager();

            if (lockingManager == null) {
                continue; // locks not supported
            }

            if (lockingManager.refresh(lockID, t)) {
                refresh = true;
            }
        }

        return refresh;
    }

    /**
     * Implement lockRelease.
     *
     * @param lockID
     * @param t
     *
     * @return true if the lock was found and released
     *
     * @throws IOException
     *
     * @see org.geotools.data.Data#lockRelease(java.lang.String,
     *      org.geotools.data.Transaction)
     */
    public boolean lockRelease(String lockID, Transaction t)
        throws IOException {
        boolean release = false;

        for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
            DataStoreInfo meta = (DataStoreInfo) i.next();

            if (!meta.isEnabled()) {
                continue; // disabled
            }

            DataStore dataStore;

            try {
                dataStore = meta.getDataStore();
            } catch (IllegalStateException notAvailable) {
                continue; // not available
            }

            LockingManager lockingManager = dataStore.getLockingManager();

            if (lockingManager == null) {
                continue; // locks not supported
            }

            if (lockingManager.release(lockID, t)) {
                release = true;
            }
        }

        return release;
    }

    /**
     * Implement lockExists.
     *
     * @param lockID
     *
     * @return true if lockID exists
     *
     * @see org.geotools.data.Data#lockExists(java.lang.String)
     */
    public boolean lockExists(String lockID) {
        for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
            DataStoreInfo meta = (DataStoreInfo) i.next();

            if (!meta.isEnabled()) {
                continue; // disabled
            }

            DataStore dataStore;

            try {
                dataStore = meta.getDataStore();
            } catch (IllegalStateException notAvailable) {
                continue; // not available
            }

            LockingManager lockingManager = dataStore.getLockingManager();

            if (lockingManager == null) {
                continue; // locks not supported
            }

            if (lockingManager.exists(lockID)) {
                return true;
            }
        }

        return false;
    }

    //
    // GeoTools2 Catalog API
    //

    /**
     * Set of available Namespace prefixes.
     *
     * @return Set of namespace Prefixes
     *
     * @see org.geotools.data.Catalog#getPrefixes()
     */
    public Set getPrefixes() {
        return Collections.unmodifiableSet(nameSpaces.keySet());
    }

    /**
     * Prefix of the defaultNamespace.
     *
     * @return prefix of the default namespace
     *
     * @see org.geotools.data.Catalog#getDefaultPrefix()
     */
    public String getDefaultPrefix() {
        return defaultNameSpace.getPrefix();
    }

    /**
     * Implement getNamespace.
     *
     * <p>
     * Description ...
     * </p>
     *
     * @param prefix
     *
     * @return
     *
     * @see org.geotools.data.Catalog#getNamespace(java.lang.String)
     */
    public NameSpaceInfo getNamespaceMetaData(String prefix) {
        return getNameSpace(prefix);
    }

    /**
     * Register a DataStore with this Catalog.
     *
     * <p>
     * This is part of the public CatalogAPI, the fact that we don't want to
     * support it here may be gounds for it's removal.
     * </p>
     *
     * <p>
     * GeoSever and the global package would really like to have
     * <b>complete</b> control over the DataStores in use by the application.
     * It recognize that this may not always be possible. As GeoServer is
     * extend with additional Modules (such as config) that wish to locate and
     * talk to DataStores independently of GeoServer the best we can do is ask
     * them to register with the this Catalog in global.
     * </p>
     *
     * <p>
     * This reveals what may be a deisgn flaw in GeoTools2 DataStore. We have
     * know way of knowing if the dataStore has already been placed into our
     * care as DataStores are not good at identifying themselves. To
     * complicate matters most keep a static connectionPool around in their
     * Factory - it could be that the Factories are supposed to be smart
     * enough to prevent duplication.
     * </p>
     *
     * @param dataStore
     *
     * @throws IOException
     *
     * @see org.geotools.data.Catalog#registerDataStore(org.geotools.data.DataStore)
     */
    public void registerDataStore(DataStore dataStore)
        throws IOException {
    }

    /**
     * Convience method for Accessing FeatureSource by prefix:typeName.
     *
     * <p>
     * This method is part of the public Catalog API. It allows the Validation
     * framework to be writen using only public Geotools2 interfaces.
     * </p>
     *
     * @param prefix Namespace prefix in which the FeatureType available
     * @param typeName typeNamed used to identify FeatureType
     *
     * @return
     *
     * @throws IOException DOCUMENT ME!
     *
     * @see org.geotools.data.Catalog#getFeatureSource(java.lang.String,
     *      java.lang.String)
     */
    public FeatureSource getFeatureSource(String prefix, String typeName)
        throws IOException {
        if ((prefix == null) || (prefix == "")) {
            prefix = defaultNameSpace.getPrefix();
        }

        NameSpaceInfo namespace = getNamespaceMetaData(prefix);
        FeatureTypeInfo featureType = namespace.getFeatureTypeInfo(typeName);
        DataStoreInfo dataStore = featureType.getDataStoreMetaData();

        return dataStore.getDataStore().getFeatureSource(typeName);
    }

    /**
     * Returns the baseDir for use with relative paths.
     *
     * @return Returns the baseDir.
     */
    public File getBaseDir() {
        return baseDir;
    }
}
TOP

Related Classes of org.vfny.geoserver.global.Data

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.