0001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
0002: * This code is licensed under the GPL 2.0 license, availible at the root
0003: * application directory.
0004: */
0005: package org.vfny.geoserver.global;
0006:
0007: import java.io.File;
0008: import java.io.IOException;
0009: import java.util.ArrayList;
0010: import java.util.Arrays;
0011: import java.util.Collections;
0012: import java.util.Comparator;
0013: import java.util.HashMap;
0014: import java.util.HashSet;
0015: import java.util.Iterator;
0016: import java.util.List;
0017: import java.util.Map;
0018: import java.util.NoSuchElementException;
0019: import java.util.Set;
0020: import java.util.logging.Level;
0021:
0022: import javax.xml.namespace.QName;
0023:
0024: import org.geotools.data.DataStore;
0025: import org.geotools.data.DefaultTransaction;
0026: import org.geotools.data.FeatureSource;
0027: import org.geotools.data.LockingManager;
0028: import org.geotools.data.Transaction;
0029: import org.geotools.feature.AttributeType;
0030: import org.geotools.feature.FeatureType;
0031: import org.geotools.styling.SLDParser;
0032: import org.geotools.styling.Style;
0033: import org.geotools.styling.StyleFactory;
0034: import org.geotools.styling.StyleFactoryFinder;
0035: import org.vfny.geoserver.global.dto.AttributeTypeInfoDTO;
0036: import org.vfny.geoserver.global.dto.CoverageInfoDTO;
0037: import org.vfny.geoserver.global.dto.CoverageStoreInfoDTO;
0038: import org.vfny.geoserver.global.dto.DataDTO;
0039: import org.vfny.geoserver.global.dto.DataStoreInfoDTO;
0040: import org.vfny.geoserver.global.dto.DataTransferObjectFactory;
0041: import org.vfny.geoserver.global.dto.FeatureTypeInfoDTO;
0042: import org.vfny.geoserver.global.dto.NameSpaceInfoDTO;
0043: import org.vfny.geoserver.global.dto.StyleDTO;
0044:
0045: /**
0046: * This class stores all the information that a catalog would (and CatalogConfig
0047: * used to).
0048: * <p>
0049: * All public methods besides constructors and stuff used for dependency injection
0050: * setters is synchronized to avoid response failures during the Geoserver reconfiguration
0051: * process (basically, each time you apply a new configuration set on the user interface).
0052: * </p>
0053: * <p>
0054: * A quick benchar did not show significant scalability loss. If one is to be encountered,
0055: * a more complex Reader/Write synchronization will be used, based on the java 5 concurrency
0056: * classes or their backport for java 1.4
0057: * </p>
0058: *
0059: * @author Gabriel Roldan, Axios Engineering
0060: * @author Chris Holmes
0061: * @author dzwiers
0062: * @author $Author: Alessio Fabiani (alessio.fabiani@gmail.com) $ (last
0063: * modification)
0064: * @author $Author: Simone Giannecchini (simboss1@gmail.com) $ (last
0065: * modification)
0066: * @version $Id: Data.java 8418 2008-02-18 14:47:17Z aaime $
0067: */
0068: public class Data extends GlobalLayerSupertype /* implements Repository */{
0069: public static final String WEB_CONTAINER_KEY = "DATA";
0070: public static final Integer TYPE_VECTOR = new Integer(0);
0071: public static final Integer TYPE_RASTER = new Integer(1);
0072:
0073: /** Default name of feature type information */
0074: private static final String INFO_FILE = "info.xml";
0075:
0076: /** used to create styles */
0077: private static StyleFactory styleFactory = StyleFactoryFinder
0078: .createStyleFactory();
0079:
0080: /** used to cache layer names and types **/
0081: private volatile Map layerNames = new HashMap();
0082:
0083: /** holds the mappings between prefixes and NameSpaceInfo objects */
0084: private Map nameSpaces;
0085:
0086: /** NameSpaceInfo */
0087: private NameSpaceInfo defaultNameSpace;
0088:
0089: /** Mapping of DataStoreInfo by dataStoreId */
0090: private Map dataStores;
0091:
0092: /**
0093: * Mapping of CoverageStoreInfo by formatId
0094: *
0095: * @uml.property name="formats"
0096: * @uml.associationEnd elementType="org.vfny.geoserver.global.dto.FeatureTypeInfoDTO"
0097: * qualifier="next:java.lang.String
0098: * org.vfny.geoserver.global.CoverageStoreInfo"
0099: * multiplicity= "(0 -1)" ordering="ordered"
0100: */
0101: private Map formats;
0102:
0103: /**
0104: * holds the mapping of Styles and style names
0105: *
0106: * @uml.property name="styles"
0107: * @uml.associationEnd elementType="org.vfny.geoserver.global.dto.FeatureTypeInfoDTO"
0108: * qualifier="id:java.lang.String
0109: * org.geotools.styling.Style" multiplicity="(0 -1) "
0110: * ordering="ordered"
0111: */
0112: private Map styles;
0113:
0114: /**
0115: *
0116: * @uml.property name="stFiles"
0117: * @uml.associationEnd qualifier="id:java.lang.String java.io.File"
0118: * multiplicity="(0 1)"
0119: */
0120: private Map stFiles;
0121:
0122: /**
0123: * Map of <code>FeatureTypeInfo</code>'s stored by full qualified name
0124: * (NameSpaceInfo prefix + PREFIX_DELIMITER + typeName)
0125: *
0126: * @uml.property name="featureTypes"
0127: * @uml.associationEnd inverse="data:org.vfny.geoserver.global.FeatureTypeInfo"
0128: * qualifier= "name:java.lang.String
0129: * org.vfny.geoserver.global.FeatureTypeInfo"
0130: * multiplicity= "(0 1)"
0131: */
0132: private Map featureTypes;
0133:
0134: /**
0135: *
0136: * @uml.property name="coverages"
0137: * @uml.associationEnd inverse="data:org.vfny.geoserver.global.CoverageInfo"
0138: * qualifier= "next:java.lang.String
0139: * org.vfny.geoserver.global.CoverageInfo"
0140: * multiplicity="(0 1)"
0141: */
0142: private Map coverages;
0143:
0144: /**
0145: * Base directory for use with file based relative paths
0146: *
0147: * @uml.property name="baseDir" multiplicity="(0 1)"
0148: */
0149: private File baseDir;
0150:
0151: /**
0152: * Data constructor.
0153: *
0154: * <p>
0155: * Creates a Data object from the data provided.
0156: * </p>
0157: *
0158: * @uml.property name="gs"
0159: * @uml.associationEnd multiplicity="(1 1)"
0160: */
0161: private GeoServer gs;
0162:
0163: /**
0164: * map of all featureTypeDTO -> load status (Boolean.True, Boolean.False,
0165: * Exception) Boolean.True when feature was loaded. Boolean.False when
0166: * something was disabled. Exception the error.
0167: *
0168: * @uml.property name="errors"
0169: * @uml.associationEnd qualifier="featureTypeDTO:org.vfny.geoserver.global.dto.FeatureTypeInfoDTO
0170: * org.vfny.geoserver.global.ConfigurationException"
0171: * multiplicity="(0 1)"
0172: */
0173: private Map errors;
0174:
0175: public Data(DataDTO config, File dir, GeoServer g)
0176: throws ConfigurationException {
0177: baseDir = dir;
0178: load(config);
0179: gs = g;
0180: }
0181:
0182: public Data(File dir, GeoServer g) throws ConfigurationException {
0183: baseDir = dir;
0184: gs = g;
0185: }
0186:
0187: public Data(Config config, GeoServer g)
0188: throws ConfigurationException {
0189: this (config.getData(), config.dataDirectory(), g);
0190: }
0191:
0192: public GeoServer getGeoServer() {
0193: return gs;
0194: }
0195:
0196: public void setDataDirectory(File dataDirectory) {
0197: this .baseDir = dataDirectory;
0198: }
0199:
0200: public File getDataDirectory() {
0201: return baseDir;
0202: }
0203:
0204: /*
0205: * Places the data in this container and innitializes it. Complex tests are
0206: * performed to detect existing datasources, while the remainder only
0207: * include simplistic id checks.
0208: *
0209: * @param config
0210: *
0211: * @throws NullPointerException
0212: */
0213: public synchronized void load(DataDTO config) {
0214: if (config == null) {
0215: throw new NullPointerException(
0216: "Non null DataDTO required for load");
0217: }
0218:
0219: // Step 0: dispose datastore and readers as needed
0220: if (dataStores != null)
0221: for (Iterator it = dataStores.values().iterator(); it
0222: .hasNext();) {
0223: DataStoreInfo ds = (DataStoreInfo) it.next();
0224: ds.dispose();
0225: }
0226:
0227: // Step 1: load formats, dataStores and Namespaces
0228: formats = loadFormats(config);
0229: dataStores = loadDataStores(config);
0230: nameSpaces = loadNamespaces(config);
0231: defaultNameSpace = (NameSpaceInfo) nameSpaces.get(config
0232: .getDefaultNameSpacePrefix());
0233:
0234: // Step 2: set up styles
0235: styles = loadStyles(config);
0236:
0237: // Step 3: load featureTypes
0238: layerNames.clear();
0239: featureTypes = loadFeatureTypes(config);
0240: coverages = loadCoverages(config);
0241: }
0242:
0243: public synchronized Set getDataStores() {
0244: return new HashSet(dataStores.values());
0245: }
0246:
0247: public synchronized Set getFormats() {
0248: return new HashSet(formats.values());
0249: }
0250:
0251: private final Map loadFormats(DataDTO dto) {
0252: if ((dto == null) || (dto.getFormats() == null)) {
0253: return Collections.EMPTY_MAP; // we *are* allowed no datasets
0254: }
0255:
0256: Map map = new HashMap();
0257:
0258: for (Iterator i = dto.getFormats().values().iterator(); i
0259: .hasNext();) {
0260: CoverageStoreInfoDTO formatDTO = (CoverageStoreInfoDTO) i
0261: .next();
0262: String id = formatDTO.getId();
0263:
0264: CoverageStoreInfo formatInfo = new CoverageStoreInfo(
0265: formatDTO, this );
0266: map.put(id, formatInfo);
0267:
0268: if (formatDTO.isEnabled()) {
0269: if (LOGGER.isLoggable(Level.FINE)) {
0270: LOGGER.fine(new StringBuffer("Register Format '")
0271: .append(id).append("'").toString());
0272: }
0273: } else {
0274: if (LOGGER.isLoggable(Level.FINE)) {
0275: LOGGER.fine(new StringBuffer(
0276: "Did not Register Format '").append(id)
0277: .append("' as it was not enabled")
0278: .toString());
0279: }
0280: }
0281: }
0282:
0283: return map;
0284: }
0285:
0286: /**
0287: * Configure a map of DataStoreInfo by dataStoreId.
0288: *
0289: * <p>
0290: * This method is order dependent and should be called by load( DataDTO ).
0291: * This method may have to be smarter in the face of reloads.
0292: * </p>
0293: *
0294: * <p>
0295: * Note that any disabled DTO will not be added to the map.
0296: * </p>
0297: *
0298: * <p>
0299: * This method is just to make laod( DataDTO ) readable, making it private
0300: * final will help
0301: * </p>
0302: *
0303: * @param dto
0304: *
0305: * @return DOCUMENT ME!
0306: *
0307: * @throws NullPointerException
0308: * DOCUMENT ME!
0309: */
0310: private final Map loadDataStores(DataDTO dto) {
0311: if ((dto == null) || (dto.getDataStores() == null)) {
0312: return Collections.EMPTY_MAP; // we *are* allowed no datasets
0313: }
0314:
0315: Map map = new HashMap(dto.getDataStores().size());
0316: DataStoreInfoDTO dataStoreDTO;
0317: String id;
0318: DataStoreInfo dataStoreInfo;
0319:
0320: for (Iterator i = dto.getDataStores().values().iterator(); i
0321: .hasNext();) {
0322: dataStoreDTO = (DataStoreInfoDTO) i.next();
0323: id = dataStoreDTO.getId();
0324: dataStoreInfo = new DataStoreInfo(dataStoreDTO, this );
0325: map.put(id, dataStoreInfo);
0326:
0327: if (dataStoreDTO.isEnabled()) {
0328: if (LOGGER.isLoggable(Level.FINE)) {
0329: LOGGER
0330: .fine(new StringBuffer(
0331: "Register DataStore '").append(id)
0332: .append("'").toString());
0333: }
0334: } else {
0335: if (LOGGER.isLoggable(Level.FINE)) {
0336: LOGGER.fine(new StringBuffer(
0337: "Did not Register DataStore '").append(id)
0338: .append("' as it was not enabled")
0339: .toString());
0340: }
0341: }
0342: }
0343:
0344: return map;
0345: }
0346:
0347: /**
0348: * Configure a map of NamespaceInfo by prefix.
0349: *
0350: * <p>
0351: * This method is order dependent and should be called by load( DataDTO ).
0352: * This method may have to be smarter in the face of reloads.
0353: * </p>
0354: *
0355: * <p>
0356: * This method is just to make laod( DataDTO ) readable, making it private
0357: * final will help
0358: * </p>
0359: *
0360: * @param dto
0361: *
0362: * @return DOCUMENT ME!
0363: *
0364: * @throws NullPointerException
0365: * DOCUMENT ME!
0366: */
0367: private final Map loadNamespaces(DataDTO dto) {
0368: if ((dto == null) || (dto.getNameSpaces() == null)) {
0369: return Collections.EMPTY_MAP; // we *are* allowed no datasets
0370: }
0371:
0372: Map map = new HashMap(dto.getNameSpaces().size());
0373: NameSpaceInfoDTO namespaceDto;
0374: String prefix;
0375: NameSpaceInfo namespaceInfo;
0376:
0377: for (Iterator i = dto.getNameSpaces().values().iterator(); i
0378: .hasNext();) {
0379: namespaceDto = (NameSpaceInfoDTO) i.next();
0380: prefix = namespaceDto.getPrefix();
0381: namespaceInfo = new NameSpaceInfo(this , namespaceDto);
0382: map.put(prefix, namespaceInfo);
0383: }
0384:
0385: return map;
0386: }
0387:
0388: private final Map loadCoverages(DataDTO dto) {
0389: if ((dto == null) || (dto.getCoverages() == null)) {
0390: return Collections.EMPTY_MAP; // we *are* allowed no datasets
0391: }
0392:
0393: Map map = new HashMap(dto.getCoverages().size());
0394: CoverageInfoDTO coverageDTO;
0395: String id;
0396: CoverageInfo coverageInfo;
0397:
0398: for (Iterator i = dto.getCoverages().values().iterator(); i
0399: .hasNext();) {
0400: coverageDTO = (CoverageInfoDTO) i.next();
0401: id = coverageDTO.getName();
0402:
0403: try {
0404: coverageInfo = new CoverageInfo(coverageDTO, this );
0405: } catch (ConfigurationException e) {
0406: coverageInfo = null;
0407: }
0408:
0409: map.put(id, coverageInfo);
0410: // set layer name, type raster (1)
0411: layerNames.put(id, TYPE_RASTER);
0412:
0413: if ((dto.getFormats() != null)
0414: && (dto.getFormats().get(coverageDTO.getFormatId()) != null)) {
0415: if (LOGGER.isLoggable(Level.FINE)) {
0416: LOGGER.fine(new StringBuffer("Register Coverage '")
0417: .append(id).append("'").toString());
0418: }
0419: } else {
0420: if (LOGGER.isLoggable(Level.FINE)) {
0421: LOGGER.fine(new StringBuffer(
0422: "Did not Register Coverage '").append(id)
0423: .append("' as didn't exist a valid Format")
0424: .toString());
0425: }
0426: }
0427: }
0428:
0429: return map;
0430: }
0431:
0432: /**
0433: * Configure a map of FeatureTypeInfo by prefix:typeName.
0434: *
0435: * <p>
0436: * Note that this map uses namespace prefix (not datastore ID like the the
0437: * configuration system). That is because this is the actual runtime, in
0438: * which we access FeatureTypes by namespace. The configuration system uses
0439: * dataStoreId which is assumed to be more stable across changes (one can
0440: * reassing a FeatureType to a different namespace, but not a different
0441: * dataStore).
0442: * </p>
0443: *
0444: * <p>
0445: * Note loadDataStores() and loadNamespaces() must be called prior to using
0446: * this function!
0447: * </p>
0448: *
0449: * @param dto
0450: * configDTO
0451: *
0452: * @return
0453: *
0454: * @throws NullPointerException
0455: * DOCUMENT ME!
0456: */
0457: private final Map loadFeatureTypes(DataDTO dto) {
0458: errors = new HashMap();
0459: featureTypes = new HashMap(); // to fix lazy loading
0460:
0461: if ((dto == null) || (dto.getFeaturesTypes() == null)) {
0462: errors = null;
0463:
0464: return Collections.EMPTY_MAP; // we *are* allowed no datasets
0465: }
0466:
0467: Map map = new HashMap(dto.getFeaturesTypes().size());
0468: FeatureTypeInfoDTO featureTypeDTO;
0469: String key;
0470: DataStoreInfo dataStoreInfo;
0471: String dataStoreId;
0472: String typeName;
0473: Style s;
0474:
0475: //let's sort the featuretypes first, and give some good loading messages as we go along.
0476: FeatureTypeInfoDTO[] ftypes = (FeatureTypeInfoDTO[]) dto
0477: .getFeaturesTypes().values().toArray(
0478: new FeatureTypeInfoDTO[dto.getFeaturesTypes()
0479: .size()]);
0480: Arrays.sort(ftypes, new Comparator() {
0481: public int compare(Object arg0, Object arg1) {
0482: FeatureTypeInfoDTO a0 = (FeatureTypeInfoDTO) arg0;
0483: FeatureTypeInfoDTO a1 = (FeatureTypeInfoDTO) arg1;
0484: return a0.getKey().compareToIgnoreCase(a1.getKey());
0485: }
0486: });
0487:
0488: int curLayerNum = 0;
0489: final int totalLayers = ftypes.length;
0490:
0491: SCHEMA: for (Iterator i = Arrays.asList(ftypes).iterator(); i
0492: .hasNext();) {
0493: curLayerNum++;
0494: featureTypeDTO = (FeatureTypeInfoDTO) i.next();
0495:
0496: if (featureTypeDTO == null) {
0497: if (LOGGER.isLoggable(Level.WARNING)) {
0498: LOGGER.warning(new StringBuffer(
0499: "Ignore null FeatureTypeInfo DTO!")
0500: .toString());
0501: }
0502:
0503: continue;
0504: }
0505:
0506: key = featureTypeDTO.getKey(); // dataStoreId:typeName
0507:
0508: LOGGER.info("Loading feature type '" + key + "' (layer "
0509: + curLayerNum + "/" + totalLayers + ")");
0510:
0511: if (LOGGER.isLoggable(Level.FINER)) {
0512: LOGGER.finer(new StringBuffer("FeatureType ").append(
0513: key).append(": loading feature type info dto:")
0514: .append(featureTypeDTO).toString());
0515: }
0516:
0517: dataStoreId = featureTypeDTO.getDataStoreId();
0518:
0519: if (LOGGER.isLoggable(Level.FINEST)) {
0520: LOGGER.finest(new StringBuffer("FeatureType ").append(
0521: key).append(" looking up :")
0522: .append(dataStoreId).toString());
0523: }
0524:
0525: dataStoreInfo = (DataStoreInfo) dataStores.get(dataStoreId);
0526:
0527: if (dataStoreInfo == null) {
0528: if (LOGGER.isLoggable(Level.SEVERE)) {
0529: LOGGER.severe(new StringBuffer("FeatureTypeInfo ")
0530: .append(key).append(
0531: " could not be used - DataStore ")
0532: .append(dataStoreId).append(
0533: " is not defined!").toString());
0534: }
0535:
0536: DataStoreInfoDTO tmp = (DataStoreInfoDTO) dto
0537: .getDataStores().get(dataStoreId);
0538:
0539: if ((tmp != null) && (!tmp.isEnabled())) {
0540: errors.put(featureTypeDTO, Boolean.FALSE);
0541: } else {
0542: errors
0543: .put(
0544: featureTypeDTO,
0545: new ConfigurationException(
0546: "FeatureTypeInfo "
0547: + key
0548: + " could not be used - DataStore "
0549: + dataStoreId
0550: + " is not defined!"));
0551: }
0552:
0553: continue;
0554: } else {
0555: if (LOGGER.isLoggable(Level.FINEST)) {
0556: LOGGER.finest(new StringBuffer(key).append(
0557: " datastore found :").append(dataStoreInfo)
0558: .toString());
0559: }
0560: }
0561:
0562: s = getStyle(featureTypeDTO.getDefaultStyle());
0563:
0564: if (s == null) {
0565: if (LOGGER.isLoggable(Level.SEVERE)) {
0566: LOGGER.severe(new StringBuffer("FeatureTypeInfo ")
0567: .append(key).append(" ignored - Style '")
0568: .append(featureTypeDTO.getDefaultStyle())
0569: .append("' not found!").toString());
0570: }
0571:
0572: errors.put(featureTypeDTO, new ConfigurationException(
0573: "FeatureTypeInfo " + key + " ignored - Style '"
0574: + featureTypeDTO.getDefaultStyle()
0575: + "' not found!"));
0576:
0577: continue SCHEMA;
0578: }
0579:
0580: // Check attributes configured correctly against schema
0581: typeName = featureTypeDTO.getName();
0582:
0583: try {
0584: DataStore dataStore = dataStoreInfo.getDataStore();
0585: FeatureType featureType = dataStore.getSchema(typeName);
0586:
0587: Set attributeNames = new HashSet();
0588: Set ATTRIBUTENames = new HashSet();
0589:
0590: // as far as I can tell an emtpy list indicates that no
0591: // schema.xml file was found. I may be approaching this
0592: // all wrong, is this logic contained elsewhere?
0593: // CH: Yeah, this shit was super messed up. It was causing null
0594: // pointer
0595: // exceptions, and then it created this createAttrDTO flag that
0596: // wasn't
0597: // then used by anyone. So I fixed the null and made it so it
0598: // creates
0599: // AttributeTypeInfoDTO's (once again, I hate these) from the
0600: // FeatureType
0601: // of the real datastore.
0602: // boolean createAttrDTO =
0603: // (featureTypeDTO.getSchemaAttributes().size() == 0);
0604: if (LOGGER.isLoggable(Level.FINE)) {
0605: LOGGER.fine(new StringBuffer("locading datastore ")
0606: .append(typeName).toString());
0607: }
0608:
0609: boolean createAttrDTO;
0610:
0611: if (featureTypeDTO.getSchemaAttributes() == null) {
0612: createAttrDTO = true;
0613: } else {
0614: createAttrDTO = featureTypeDTO
0615: .getSchemaAttributes().size() == 0;
0616: }
0617:
0618: if (createAttrDTO) {
0619: List attributeDTOs = createAttrDTOsFromSchema(featureType);
0620: featureTypeDTO.setSchemaAttributes(attributeDTOs);
0621:
0622: if (LOGGER.isLoggable(Level.FINER)) {
0623: LOGGER
0624: .finer(new StringBuffer(
0625: "No schema found, setting featureTypeDTO with ")
0626: .append(attributeDTOs)
0627: .toString());
0628: }
0629: } else {
0630: for (int index = 0; index < featureType
0631: .getAttributeCount(); index++) {
0632: AttributeType attrib = featureType
0633: .getAttributeType(index);
0634: attributeNames.add(attrib.getName());
0635: ATTRIBUTENames.add(attrib.getName()
0636: .toUpperCase());
0637: }
0638:
0639: if (featureTypeDTO.getSchemaAttributes() != null) {
0640: for (Iterator a = featureTypeDTO
0641: .getSchemaAttributes().iterator(); a
0642: .hasNext();) {
0643: AttributeTypeInfoDTO attribDTO = (AttributeTypeInfoDTO) a
0644: .next();
0645: String attributeName = attribDTO.getName();
0646:
0647: if (!attributeNames.contains(attributeName)) {
0648: if (ATTRIBUTENames
0649: .contains(attributeName
0650: .toUpperCase())) {
0651: if (LOGGER.isLoggable(Level.SEVERE)) {
0652: LOGGER
0653: .severe(new StringBuffer(
0654: "FeatureTypeInfo ")
0655: .append(key)
0656: .append(
0657: " ignored - attribute '")
0658: .append(
0659: attributeName)
0660: .append(
0661: "' not found - please check captialization")
0662: .toString());
0663: }
0664: } else {
0665: if (LOGGER.isLoggable(Level.SEVERE)) {
0666: LOGGER
0667: .severe(new StringBuffer(
0668: "FeatureTypeInfo ")
0669: .append(key)
0670: .append(
0671: " ignored - attribute '")
0672: .append(
0673: attributeName)
0674: .append(
0675: "' not found!")
0676: .toString());
0677: }
0678:
0679: String names = "";
0680: Iterator x = attributeNames
0681: .iterator();
0682:
0683: if (x.hasNext()) {
0684: names = x.next().toString();
0685: }
0686:
0687: while (x.hasNext())
0688: names = ":::"
0689: + x.next().toString();
0690:
0691: if (LOGGER.isLoggable(Level.SEVERE)) {
0692: LOGGER
0693: .severe(new StringBuffer(
0694: "Valid attribute names include :::")
0695: .append(names)
0696: .toString());
0697: }
0698: }
0699:
0700: errors
0701: .put(
0702: featureTypeDTO,
0703: new ConfigurationException(
0704: new StringBuffer(
0705: "FeatureTypeInfo ")
0706: .append(
0707: key)
0708: .append(
0709: " could not be used - DataStore ")
0710: .append(
0711: dataStoreId)
0712: .append(
0713: " is not defined!")
0714: .toString()));
0715:
0716: continue SCHEMA;
0717: }
0718: }
0719: }
0720: }
0721: } catch (IllegalStateException illegalState) {
0722: if (LOGGER.isLoggable(Level.SEVERE)) {
0723: LOGGER.severe(new StringBuffer("FeatureTypeInfo ")
0724: .append(key).append(
0725: " ignored - as DataStore ").append(
0726: dataStoreId)
0727: .append(" is disabled!").toString());
0728: }
0729:
0730: errors.put(featureTypeDTO, Boolean.FALSE);
0731:
0732: continue;
0733: } catch (IOException ioException) {
0734: if (LOGGER.isLoggable(Level.SEVERE)) {
0735: LOGGER.log(Level.SEVERE, new StringBuffer(
0736: "FeatureTypeInfo ").append(key).append(
0737: " ignored - as DataStore ").append(
0738: dataStoreId).append(" is unavailable:")
0739: .append(ioException).toString());
0740: }
0741:
0742: if (LOGGER.isLoggable(Level.FINE)) {
0743: LOGGER.log(Level.FINE, new StringBuffer(key)
0744: .append(" unavailable").toString(),
0745: ioException);
0746: }
0747:
0748: errors.put(featureTypeDTO, ioException);
0749:
0750: continue;
0751: } catch (NoSuchElementException nse) {
0752: if (LOGGER.isLoggable(Level.SEVERE)) {
0753: LOGGER.log(Level.SEVERE, new StringBuffer(
0754: "FeatureTypeInfo ").append(key).append(
0755: " ignored - as DataStore ").append(
0756: dataStoreId).append(
0757: " can't find FeatureType '" + typeName
0758: + "'. Error was:\n").append(nse)
0759: .toString());
0760: }
0761:
0762: if (LOGGER.isLoggable(Level.FINE)) {
0763: LOGGER
0764: .log(Level.FINE, typeName + " not found",
0765: nse);
0766: }
0767:
0768: continue;
0769: } catch (Throwable unExpected) {
0770: if (LOGGER.isLoggable(Level.SEVERE)) {
0771: LOGGER.log(Level.SEVERE, new StringBuffer(
0772: "FeatureTypeInfo ").append(key).append(
0773: " ignored - as DataStore ").append(
0774: dataStoreId).append(" is broken:").append(
0775: unExpected).toString());
0776: }
0777:
0778: if (LOGGER.isLoggable(Level.FINE)) {
0779: LOGGER.log(Level.FINE, new StringBuffer(key)
0780: .append(" unavailable").toString(),
0781: unExpected);
0782: }
0783:
0784: errors.put(featureTypeDTO, unExpected);
0785:
0786: continue;
0787: }
0788:
0789: String prefix = dataStoreInfo.getNamesSpacePrefix();
0790:
0791: if (LOGGER.isLoggable(Level.FINEST)) {
0792: LOGGER.finest(new StringBuffer("FeatureType ").append(
0793: key).append(" creating FeatureTypeInfo for ")
0794: .append(prefix).append(":").append(typeName)
0795: .toString());
0796: }
0797:
0798: FeatureTypeInfo featureTypeInfo = null;
0799:
0800: try {
0801: featureTypeInfo = new FeatureTypeInfo(featureTypeDTO,
0802: this );
0803: } catch (ConfigurationException configException) {
0804: if (LOGGER.isLoggable(Level.SEVERE)) {
0805: LOGGER.log(Level.SEVERE, new StringBuffer(
0806: "FeatureTypeInfo ").append(key).append(
0807: " ignored - configuration problem:")
0808: .append(configException).toString());
0809: }
0810:
0811: if (LOGGER.isLoggable(Level.FINEST)) {
0812: LOGGER.log(Level.FINEST, new StringBuffer(key)
0813: .append(" unavailable").toString(),
0814: configException);
0815: }
0816:
0817: errors.put(featureTypeDTO, configException);
0818:
0819: continue;
0820: }
0821:
0822: String key2;
0823: if (featureTypeDTO.getAlias() == null)
0824: key2 = prefix + ":" + typeName;
0825: else
0826: key2 = prefix + ":" + featureTypeDTO.getAlias();
0827:
0828: if (map.containsKey(key2)) {
0829: if (LOGGER.isLoggable(Level.SEVERE)) {
0830: LOGGER
0831: .severe(new StringBuffer(
0832: "FeatureTypeInfo '")
0833: .append(key2)
0834: .append(
0835: "' already defined - you must have duplicate defined?")
0836: .toString());
0837: }
0838:
0839: errors
0840: .put(
0841: featureTypeDTO,
0842: new ConfigurationException(
0843: "FeatureTypeInfo '"
0844: + key2
0845: + "' already defined - you must have duplicate defined?"));
0846: } else {
0847: if (LOGGER.isLoggable(Level.FINEST)) {
0848: LOGGER.finest(new StringBuffer("FeatureTypeInfo ")
0849: .append(key2)
0850: .append(" has been created...").toString());
0851: }
0852:
0853: map.put(key2, featureTypeInfo);
0854: // set layer name, type vector (0)
0855: layerNames.put(key2, TYPE_VECTOR);
0856:
0857: if (LOGGER.isLoggable(Level.FINEST)) {
0858: LOGGER.finest(new StringBuffer("FeatureTypeInfo '")
0859: .append(key2).append("' is registered:")
0860: .append(dataStoreInfo).toString());
0861: }
0862:
0863: errors.put(featureTypeDTO, Boolean.TRUE);
0864: }
0865: }
0866:
0867: return map;
0868: }
0869:
0870: private List createAttrDTOsFromSchema(FeatureType featureType) {
0871: List attrList = DataTransferObjectFactory
0872: .generateAttributes(featureType);
0873:
0874: /*
0875: * new ArrayList(featureType.getAttributeCount()); for (int index = 0;
0876: * index < featureType.getAttributeCount(); index++) { AttributeType
0877: * attrib = featureType.getAttributeType(index); attrList.add(new
0878: * AttributeTypeInfoDTO(attrib)); }
0879: */
0880: return attrList;
0881: }
0882:
0883: /**
0884: * Generate map of geotools2 Styles by id.
0885: *
0886: * <p>
0887: * The filename specified by the StyleDTO will be used to generate the
0888: * resulting Styles.
0889: * </p>
0890: *
0891: * @param dto
0892: * requested configuration
0893: *
0894: * @return Map of Style by id
0895: *
0896: * @throws NullPointerException
0897: * If the style could not be loaded from the filename
0898: *
0899: * @see Data.loadStyle() for more information
0900: */
0901: private final Map loadStyles(DataDTO dto) {
0902: Map map = new HashMap();
0903: stFiles = new HashMap();
0904:
0905: if ((dto == null) || (dto.getStyles() == null)) {
0906: return Collections.EMPTY_MAP; // we *are* allowed no datasets
0907: }
0908:
0909: for (Iterator i = dto.getStyles().values().iterator(); i
0910: .hasNext();) {
0911: StyleDTO styleDTO = (StyleDTO) i.next();
0912: String id = styleDTO.getId();
0913: Style style;
0914:
0915: try {
0916: style = loadStyle(styleDTO.getFilename());
0917: // HACK: due to our crappy weird id shit we rename the style's
0918: // specified
0919: // name with the id we (and our clients) refer to the style as.
0920: // Should redo style management to not make use of our weird
0921: // ids, just
0922: // use the style's name out of the styles directory.
0923: style.setName(id);
0924: } catch (Exception ioException) { // was IOException
0925:
0926: if (LOGGER.isLoggable(Level.SEVERE)) {
0927: LOGGER.log(Level.SEVERE, new StringBuffer(
0928: "Could not load style ").append(id)
0929: .toString(), ioException);
0930: }
0931:
0932: continue;
0933: }
0934:
0935: stFiles.put(id, styleDTO.getFilename());
0936: map.put(id, style);
0937: }
0938:
0939: if (LOGGER.isLoggable(Level.FINER)) {
0940: LOGGER.finer(new StringBuffer("returning styles ").append(
0941: map).append("\n and set map ").append(stFiles)
0942: .toString());
0943: }
0944:
0945: return map;
0946: }
0947:
0948: /**
0949: * Status output
0950: *
0951: * @param title
0952: * DOCUMENT ME!
0953: * @param status
0954: * DOCUMENT ME!
0955: */
0956: static final void outputStatus(String title, Map status) {
0957: if (LOGGER.isLoggable(Level.INFO)) {
0958: LOGGER.info(title);
0959: }
0960:
0961: for (Iterator i = status.entrySet().iterator(); i.hasNext();) {
0962: Map.Entry entry = (Map.Entry) i.next();
0963: String key = (String) entry.getKey();
0964: Object value = entry.getValue();
0965:
0966: if (value == Boolean.TRUE) {
0967: if (LOGGER.isLoggable(Level.FINE)) {
0968: LOGGER.fine(new StringBuffer(key).append(": ready")
0969: .toString());
0970: }
0971: } else if (value instanceof Throwable) {
0972: Throwable t = (Throwable) value;
0973:
0974: if (LOGGER.isLoggable(Level.SEVERE)) {
0975: LOGGER.log(Level.SEVERE, new StringBuffer(key)
0976: .append(" not ready").toString(), t);
0977: }
0978: } else {
0979: if (LOGGER.isLoggable(Level.WARNING)) {
0980: LOGGER.warning(new StringBuffer(key).append(": '")
0981: .append(value).append("'").toString());
0982: }
0983: }
0984: }
0985: }
0986:
0987: /**
0988: * Dynamically tries to connect to every DataStore!
0989: *
0990: * <p>
0991: * Returns a map of Exception by dataStoreId:typeName. If by some marvel the
0992: * we could connect to a FeatureSource we will record Boolean.TRUE.
0993: * </p>
0994: *
0995: * @return Map of Exception by dataStoreId:typeName
0996: */
0997: public synchronized Map statusDataStores() {
0998: Map m = new HashMap();
0999: Iterator i = errors.entrySet().iterator();
1000:
1001: while (i.hasNext()) {
1002: Map.Entry e = (Map.Entry) i.next();
1003: FeatureTypeInfoDTO ftdto = (FeatureTypeInfoDTO) e.getKey();
1004: m.put(ftdto.getDataStoreId() + ":" + ftdto.getName(), e
1005: .getValue());
1006: }
1007:
1008: return m;
1009: }
1010:
1011: /**
1012: * Dynamically tries to connect to every Namespace!
1013: *
1014: * <p>
1015: * Returns a map of Exception by prefix:typeName. If by some marvel the we
1016: * could connect to a FeatureSource we will record Boolean.TRUE.
1017: * </p>
1018: *
1019: * @return Map of Exception by prefix:typeName
1020: */
1021: public synchronized Map statusNamespaces() {
1022: Map m = new HashMap();
1023: Iterator i = errors.entrySet().iterator();
1024:
1025: while (i.hasNext()) {
1026: Map.Entry e = (Map.Entry) i.next();
1027: FeatureTypeInfoDTO ftdto = (FeatureTypeInfoDTO) e.getKey();
1028: DataStoreInfo dsdto = (DataStoreInfo) dataStores.get(ftdto
1029: .getDataStoreId());
1030:
1031: if (dsdto != null) {
1032: m.put(dsdto.getNamesSpacePrefix() + ":"
1033: + ftdto.getName(), e.getValue());
1034: }
1035: }
1036:
1037: return m;
1038: }
1039:
1040: /**
1041: * toDTO purpose.
1042: *
1043: * <p>
1044: * This method is package visible only, and returns a reference to the
1045: * GeoServerDTO. This method is unsafe, and should only be used with extreme
1046: * caution.
1047: * </p>
1048: *
1049: * @return DataDTO the generated object
1050: */
1051: public synchronized Object toDTO() {
1052: DataDTO dto = new DataDTO();
1053:
1054: HashMap tmp;
1055: Iterator i;
1056: tmp = new HashMap();
1057: i = nameSpaces.keySet().iterator();
1058:
1059: while (i.hasNext()) {
1060: NameSpaceInfo nsi = (NameSpaceInfo) nameSpaces
1061: .get(i.next());
1062: tmp.put(nsi.getPrefix(), nsi.toDTO());
1063: }
1064:
1065: dto.setNameSpaces(tmp);
1066:
1067: if (defaultNameSpace != null) {
1068: dto.setDefaultNameSpacePrefix(defaultNameSpace.getPrefix());
1069: }
1070:
1071: tmp = new HashMap();
1072: i = styles.keySet().iterator();
1073:
1074: while (i.hasNext()) {
1075: String id = (String) i.next();
1076: Style st = (Style) styles.get(id);
1077: StyleDTO sdto = new StyleDTO();
1078: sdto.setDefault(st.isDefault());
1079: sdto.setFilename((File) stFiles.get(id));
1080: sdto.setId(id);
1081: tmp.put(id, sdto);
1082: }
1083:
1084: if (LOGGER.isLoggable(Level.FINER)) {
1085: LOGGER.finer(new StringBuffer("setting styles to: ")
1086: .append(tmp).toString());
1087: }
1088:
1089: dto.setStyles(tmp);
1090:
1091: tmp = new HashMap();
1092: i = formats.keySet().iterator();
1093:
1094: while (i.hasNext()) {
1095: CoverageStoreInfo fmi = (CoverageStoreInfo) formats.get(i
1096: .next());
1097: tmp.put(fmi.getId(), fmi.toDTO());
1098: }
1099:
1100: dto.setFormats(tmp);
1101:
1102: tmp = new HashMap();
1103: i = dataStores.keySet().iterator();
1104:
1105: while (i.hasNext()) {
1106: DataStoreInfo dsi = (DataStoreInfo) dataStores
1107: .get(i.next());
1108: tmp.put(dsi.getId(), dsi.toDTO());
1109: }
1110:
1111: dto.setDataStores(tmp);
1112:
1113: tmp = new HashMap();
1114: i = errors.keySet().iterator();
1115:
1116: while (i.hasNext()) {
1117: FeatureTypeInfoDTO fti = (FeatureTypeInfoDTO) i.next();
1118: tmp.put(fti.getKey(), fti.clone()); // DJB: changed to getKey() from
1119: // getName() which was NOT
1120: // unique!
1121: }
1122:
1123: dto.setFeaturesTypes(tmp);
1124:
1125: tmp = new HashMap();
1126: i = coverages.keySet().iterator();
1127:
1128: while (i.hasNext()) {
1129: CoverageInfo cvi = (CoverageInfo) coverages.get(i.next());
1130: tmp.put(cvi.getName(), cvi.toDTO());
1131: }
1132:
1133: dto.setCoverages(tmp);
1134:
1135: return dto;
1136: }
1137:
1138: /**
1139: * Locate a DataStoreInfo by its id attribute.
1140: *
1141: * @param id
1142: * the DataStoreInfo id looked for
1143: *
1144: * @return the DataStoreInfo with id attribute equals to <code>id</code>
1145: * or null if there no exists
1146: */
1147: public synchronized DataStoreInfo getDataStoreInfo(String id) {
1148: DataStoreInfo dsi = (DataStoreInfo) dataStores.get(id);
1149:
1150: if ((dsi != null) && dsi.isEnabled()) {
1151: return dsi;
1152: }
1153:
1154: return null;
1155: }
1156:
1157: /**
1158: * Locate a CoverageStoreInfo by its id attribute.
1159: *
1160: * @param id
1161: * the CoverageStoreInfo id looked for
1162: *
1163: * @return the CoverageStoreInfo with id attribute equals to <code>id</code>
1164: * or null if there no exists
1165: */
1166: public synchronized CoverageStoreInfo getFormatInfo(String id) {
1167: CoverageStoreInfo dfi = (CoverageStoreInfo) formats.get(id);
1168:
1169: if ((dfi != null) && dfi.isEnabled()) {
1170: return dfi;
1171: }
1172:
1173: return null;
1174: }
1175:
1176: /**
1177: * getNameSpaces purpose.
1178: *
1179: * <p>
1180: * List of all relevant namespaces
1181: * </p>
1182: *
1183: * @return NameSpaceInfo[]
1184: */
1185: public synchronized NameSpaceInfo[] getNameSpaces() {
1186: NameSpaceInfo[] ns = new NameSpaceInfo[nameSpaces.values()
1187: .size()];
1188:
1189: return (NameSpaceInfo[]) new ArrayList(nameSpaces.values())
1190: .toArray(ns);
1191: }
1192:
1193: /**
1194: * getNameSpace purpose.
1195: *
1196: * <p>
1197: * The NameSpaceInfo from the specified prefix
1198: * </p>
1199: *
1200: * @param prefix
1201: *
1202: * @return NameSpaceInfo resulting from the specified prefix
1203: */
1204: public synchronized NameSpaceInfo getNameSpace(String prefix) {
1205: NameSpaceInfo retNS = (NameSpaceInfo) nameSpaces.get(prefix);
1206:
1207: return retNS;
1208: }
1209:
1210: /**
1211: * Returns the NamespaceINfo object corresponding to a particular
1212: * namespace uri.
1213: * <p>
1214: * If a namespace info object could not be found with mathces <param>uri</param>
1215: * then <code>null</code> is returned.
1216: * </p>
1217: *
1218: * @param uri A namespace uri, non-null
1219: *
1220: * @return NameSpaceInfo resulting from the specified uri.
1221: */
1222: public synchronized NameSpaceInfo getNameSpaceFromURI(String uri) {
1223: for (Iterator i = nameSpaces.values().iterator(); i.hasNext();) {
1224: NameSpaceInfo nsInfo = (NameSpaceInfo) i.next();
1225:
1226: if (nsInfo.getURI().equals(uri)) {
1227: return nsInfo;
1228: }
1229: }
1230:
1231: return null;
1232: }
1233:
1234: /**
1235: * getDefaultNameSpace purpose.
1236: *
1237: * <p>
1238: * Returns the default NameSpaceInfo for this Data object.
1239: * </p>
1240: *
1241: * @return NameSpaceInfo the default name space
1242: *
1243: * @uml.property name="defaultNameSpace"
1244: */
1245: public synchronized NameSpaceInfo getDefaultNameSpace() {
1246: return defaultNameSpace;
1247: }
1248:
1249: /**
1250: * getStyles purpose.
1251: *
1252: * <p>
1253: * A reference to the map of styles
1254: * </p>
1255: *
1256: * @return Map A map containing the Styles.
1257: *
1258: * @uml.property name="styles"
1259: */
1260: public synchronized Map getStyles() {
1261: return this .styles;
1262: }
1263:
1264: public synchronized Style getStyle(String id) {
1265: return (Style) styles.get(id);
1266: }
1267:
1268: /**
1269: * Locate FeatureTypeInfo by name
1270: *
1271: * <p>
1272: * The following searchness is used::
1273: *
1274: * <ul>
1275: * <li> search prefix:typeName for direct match with name </li>
1276: * <li> search prefix:typeName for match with defaultnamespaceprefix:name
1277: * </li>
1278: * <li> linear search of typeName for direct match </li>
1279: * </ul>
1280: * </p>
1281: *
1282: * <p>
1283: * Yes this is the magic method used by TransasctionResponse. If you
1284: * wondered what it was doing - this is it.
1285: * </p>
1286: *
1287: * @param name
1288: * String The FeatureTypeInfo Name
1289: *
1290: * @return FeatureTypeInfo
1291: *
1292: * @throws NoSuchElementException
1293: */
1294: public synchronized FeatureTypeInfo getFeatureTypeInfo(String name)
1295: throws NoSuchElementException {
1296: if (LOGGER.isLoggable(Level.FINE)) {
1297: LOGGER.fine(new StringBuffer("getting type ").append(name)
1298: .toString());
1299: }
1300:
1301: FeatureTypeInfo found = null;
1302:
1303: found = (FeatureTypeInfo) featureTypes.get(name);
1304:
1305: if (found != null) {
1306: return found;
1307: }
1308:
1309: String defaultPrefix = defaultNameSpace.getPrefix();
1310: found = (FeatureTypeInfo) featureTypes.get(defaultPrefix + ":"
1311: + name);
1312:
1313: if (found != null) {
1314: return found;
1315: }
1316:
1317: for (Iterator i = featureTypes.values().iterator(); i.hasNext();) {
1318: FeatureTypeInfo fto = (FeatureTypeInfo) i.next();
1319:
1320: if ((name != null) && name.equals(fto.getName())) {
1321: found = fto;
1322: }
1323: }
1324:
1325: if (found != null) {
1326: return found;
1327: }
1328:
1329: throw new NoSuchElementException(
1330: "Could not locate FeatureTypeConfig '" + name + "'");
1331: }
1332:
1333: /**
1334: * Gets a FeatureTypeINfo from a qualified name.
1335: * <p>
1336: * This method calls through to {@link #getFeatureTypeInfo(String, String)}.
1337: * </p>
1338: * @param name The qualified name of the feature type.
1339: */
1340: public FeatureTypeInfo getFeatureTypeInfo(QName name) {
1341: return getFeatureTypeInfo(name.getLocalPart(), name
1342: .getNamespaceURI());
1343: }
1344:
1345: /**
1346: * Gets a FeatureTypeInfo from a local type name (ie unprefixed), and a uri.
1347: *
1348: * <p>
1349: * This method is slow, use getFeatureType(String typeName), where possible.
1350: * For not he only user should be TransactionFeatureHandler.
1351: * </p>
1352: *
1353: * <p>
1354: * TODO: Jody here - David is this still correct?
1355: * </p>
1356: *
1357: * @param typename
1358: * Name NameSpaceInfo name
1359: * @param uri
1360: * NameSpaceInfo uri
1361: *
1362: * @return FeatureTypeInfo
1363: */
1364: public synchronized FeatureTypeInfo getFeatureTypeInfo(
1365: String typename, String uri) {
1366: // For some reason I don't understand GR patched this to remove the namespace
1367: // test, but this breaks if there are multiple feature types with the same
1368: // name in different namespaces. Now, to stay on the safe side, I will lookup
1369: // first based on both name and namespace, and return a pure name matcher only
1370: // if a full name + namespace match was not found
1371:
1372: // This will be returned if we matched only the name but not the namespace
1373: FeatureTypeInfo fallback = null;
1374: for (Iterator it = featureTypes.values().iterator(); it
1375: .hasNext();) {
1376: FeatureTypeInfo fType = (FeatureTypeInfo) it.next();
1377:
1378: if (fType.isEnabled()) {
1379: String typeId = fType.getNameSpace().getPrefix() + ":"
1380: + typename;
1381: boolean t1 = fType.getName().equals(typeId);
1382: boolean t2 = fType.getNameSpace().getUri().equals(uri);
1383:
1384: /**
1385: * GR:
1386: *
1387: * @HACK it seems not to be working, so I'm just comparing the
1388: * prefixed name (don't should it be enough?)
1389: */
1390: if (t1 && t2) {
1391: return fType;
1392: } else if (t1) {
1393: fallback = fType;
1394: }
1395: }
1396: }
1397:
1398: return fallback;
1399: }
1400:
1401: public synchronized CoverageInfo getCoverageInfo(String name)
1402: throws NoSuchElementException {
1403: LOGGER.fine("getting coverage " + name);
1404:
1405: CoverageInfo found = null;
1406:
1407: found = (CoverageInfo) coverages.get(name);
1408:
1409: if (found != null) {
1410: return found;
1411: }
1412:
1413: String defaultPrefix = defaultNameSpace.getPrefix();
1414: found = (CoverageInfo) coverages
1415: .get(defaultPrefix + ":" + name);
1416:
1417: if (found != null) {
1418: return found;
1419: }
1420:
1421: for (Iterator i = coverages.values().iterator(); i.hasNext();) {
1422: CoverageInfo cvo = (CoverageInfo) i.next();
1423:
1424: if ((name != null) && name.equals(cvo.getName())) {
1425: found = cvo;
1426: }
1427: }
1428:
1429: if (found != null) {
1430: return found;
1431: }
1432:
1433: throw new NoSuchElementException(
1434: "Could not locate CoverageConfig '" + name + "'");
1435: }
1436:
1437: public synchronized CoverageInfo getCoverageInfo(String name,
1438: String uri) {
1439: for (Iterator it = coverages.values().iterator(); it.hasNext();) {
1440: CoverageInfo cvo = (CoverageInfo) it.next();
1441:
1442: if (cvo.isEnabled()) {
1443: String cvId = cvo.getNameSpace().getPrefix() + ":"
1444: + name;
1445: boolean t1 = cvo.getName().equals(cvId);
1446: boolean t2 = cvo.getNameSpace().getUri().equals(uri);
1447:
1448: if (t1) {
1449: return cvo;
1450: }
1451: }
1452: }
1453:
1454: return null;
1455: }
1456:
1457: /**
1458: * Returns the map layer info for the specified layer, or null if the layer
1459: * is not known
1460: * @param layerName
1461: * @return
1462: */
1463: public MapLayerInfo getMapLayerInfo(String layerName) {
1464: Integer layerType = getLayerType(layerName);
1465: if (layerType == TYPE_VECTOR)
1466: return new MapLayerInfo(getFeatureTypeInfo(layerName));
1467: else if (layerType == TYPE_RASTER)
1468: return new MapLayerInfo(getCoverageInfo(layerName));
1469: else
1470: return null;
1471: }
1472:
1473: /**
1474: * Retrieve map of FeatureTypeInfo by prefix:typeName.
1475: *
1476: * <p>
1477: * Returns all the featuretype information objects
1478: * </p>
1479: *
1480: * @return Map of FetureTypeInfo by prefix:typeName
1481: */
1482: public synchronized Map getFeatureTypeInfos() {
1483: return Collections.unmodifiableMap(featureTypes);
1484: }
1485:
1486: public synchronized Map getCoverageInfos() {
1487: return Collections.unmodifiableMap(coverages);
1488: }
1489:
1490: // TODO: detect if a user put a full url, instead of just one to be
1491: // resolved, and
1492: // use that instead.
1493: public Style loadStyle(String fileName, String base)
1494: throws IOException {
1495: return loadStyle(new File(base + fileName));
1496: }
1497:
1498: /**
1499: * Load GeoTools2 Style from a fileName
1500: *
1501: * @param fileName
1502: * DOCUMENT ME!
1503: *
1504: * @return DOCUMENT ME!
1505: *
1506: * @throws IOException
1507: * DOCUMENT ME!
1508: */
1509: public Style loadStyle(File fileName) throws IOException {
1510: SLDParser stylereader = new SLDParser(styleFactory, fileName);
1511:
1512: return stylereader.readXML()[0];
1513: }
1514:
1515: /**
1516: * tests whether a given file is a file containing type information.
1517: *
1518: * @param testFile
1519: * the file to test.
1520: *
1521: * @return <tt>true</tt> if the file has type info.
1522: */
1523: private static boolean isInfoFile(File testFile) {
1524: String testName = testFile.getAbsolutePath();
1525: int start = testName.length() - INFO_FILE.length();
1526: int end = testName.length();
1527:
1528: return testName.substring(start, end).equals(INFO_FILE);
1529: }
1530:
1531: /**
1532: * The number of connections currently held.
1533: *
1534: * <p>
1535: * We will need to modify DataStore to provide access to the current count
1536: * of its connection pool (if appropriate). Right now we are asumming a one
1537: * DataStore equals One "Connection".
1538: * </p>
1539: *
1540: * <p>
1541: * This is a good compromize since I just want to indicate the amount of
1542: * resources currently tied up by GeoServer.
1543: * </p>
1544: *
1545: * @return Number of available connections.
1546: */
1547: public synchronized int getConnectionCount() {
1548: int count = 0;
1549: DataStoreInfo meta;
1550: DataStore dataStore;
1551:
1552: for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
1553: meta = (DataStoreInfo) i.next();
1554:
1555: if (!meta.isEnabled()) {
1556: continue; // disabled
1557: }
1558:
1559: try {
1560: dataStore = meta.getDataStore();
1561: } catch (Throwable notAvailable) {
1562: continue; // not available
1563: }
1564:
1565: // TODO: All DataStore to indicate number of connections
1566: count += 1;
1567: }
1568:
1569: return count;
1570: }
1571:
1572: /**
1573: * Count locks currently held.
1574: *
1575: * <p>
1576: * Not sure if this should be the number of features locked, or the number
1577: * of FeatureLocks in existence (a FeatureLock may lock several features.
1578: * </p>
1579: *
1580: * @return number of locks currently held
1581: */
1582: public synchronized int getLockCount() {
1583: int count = 0;
1584: DataStore dataStore;
1585: ;
1586:
1587: LockingManager lockingManager;
1588:
1589: for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
1590: DataStoreInfo meta = (DataStoreInfo) i.next();
1591:
1592: if (!meta.isEnabled()) {
1593: continue; // disabled
1594: }
1595:
1596: try {
1597: dataStore = meta.getDataStore();
1598: } catch (IllegalStateException notAvailable) {
1599: continue; // not available
1600: } catch (Throwable huh) {
1601: continue; // not even working
1602: }
1603:
1604: lockingManager = dataStore.getLockingManager();
1605:
1606: if (lockingManager == null) {
1607: continue; // locks not supported
1608: }
1609:
1610: // TODO: implement LockingManger.getLockSet()
1611: // count += lockingManager.getLockSet();
1612: }
1613:
1614: return count;
1615: }
1616:
1617: /**
1618: * Release all feature locks currently held.
1619: *
1620: * <p>
1621: * This is the implementation for the Admin "free lock" action, transaction
1622: * locks are not released.
1623: * </p>
1624: *
1625: * @return Number of locks released
1626: */
1627: public synchronized int lockReleaseAll() {
1628: int count = 0;
1629:
1630: for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
1631: DataStoreInfo meta = (DataStoreInfo) i.next();
1632:
1633: if (!meta.isEnabled()) {
1634: continue; // disabled
1635: }
1636:
1637: DataStore dataStore;
1638:
1639: try {
1640: dataStore = meta.getDataStore();
1641: } catch (IllegalStateException notAvailable) {
1642: continue; // not available
1643: } catch (Throwable huh) {
1644: continue; // not even working
1645: }
1646:
1647: LockingManager lockingManager = dataStore
1648: .getLockingManager();
1649:
1650: if (lockingManager == null) {
1651: continue; // locks not supported
1652: }
1653:
1654: // TODO: implement LockingManger.releaseAll()
1655: // count += lockingManager.releaseAll();
1656: }
1657:
1658: return count;
1659: }
1660:
1661: /**
1662: * Release lock by authorization
1663: *
1664: * @param lockID
1665: */
1666: public synchronized void lockRelease(String lockID) {
1667: boolean refresh = false;
1668:
1669: for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
1670: DataStoreInfo meta = (DataStoreInfo) i.next();
1671:
1672: if (!meta.isEnabled()) {
1673: continue; // disabled
1674: }
1675:
1676: DataStore dataStore;
1677:
1678: try {
1679: dataStore = meta.getDataStore();
1680: } catch (IllegalStateException notAvailable) {
1681: continue; // not available
1682: }
1683:
1684: LockingManager lockingManager = dataStore
1685: .getLockingManager();
1686:
1687: if (lockingManager == null) {
1688: continue; // locks not supported
1689: }
1690:
1691: Transaction t = new DefaultTransaction("Refresh "
1692: + meta.getNameSpace());
1693:
1694: try {
1695: t.addAuthorization(lockID);
1696:
1697: if (lockingManager.release(lockID, t)) {
1698: refresh = true;
1699: }
1700: } catch (IOException e) {
1701: if (LOGGER.isLoggable(Level.WARNING)) {
1702: LOGGER.log(Level.WARNING, e.getMessage(), e);
1703: }
1704: } finally {
1705: try {
1706: t.close();
1707: } catch (IOException closeException) {
1708: if (LOGGER.isLoggable(Level.FINEST)) {
1709: LOGGER.log(Level.FINEST, closeException
1710: .getMessage(), closeException);
1711: }
1712: }
1713: }
1714: }
1715:
1716: if (!refresh) {
1717: // throw exception? or ignore...
1718: }
1719: }
1720:
1721: /**
1722: * Refresh lock by authorization
1723: *
1724: * <p>
1725: * Should use your own transaction?
1726: * </p>
1727: *
1728: * @param lockID
1729: */
1730: public synchronized void lockRefresh(String lockID) {
1731: boolean refresh = false;
1732:
1733: for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
1734: DataStoreInfo meta = (DataStoreInfo) i.next();
1735:
1736: if (!meta.isEnabled()) {
1737: continue; // disabled
1738: }
1739:
1740: DataStore dataStore;
1741:
1742: try {
1743: dataStore = meta.getDataStore();
1744: } catch (IllegalStateException notAvailable) {
1745: continue; // not available
1746: }
1747:
1748: LockingManager lockingManager = dataStore
1749: .getLockingManager();
1750:
1751: if (lockingManager == null) {
1752: continue; // locks not supported
1753: }
1754:
1755: Transaction t = new DefaultTransaction("Refresh "
1756: + meta.getNameSpace());
1757:
1758: try {
1759: t.addAuthorization(lockID);
1760:
1761: if (lockingManager.refresh(lockID, t)) {
1762: refresh = true;
1763: }
1764: } catch (IOException e) {
1765: if (LOGGER.isLoggable(Level.WARNING)) {
1766: LOGGER.log(Level.WARNING, e.getMessage(), e);
1767: }
1768: } finally {
1769: try {
1770: t.close();
1771: } catch (IOException closeException) {
1772: if (LOGGER.isLoggable(Level.FINEST)) {
1773: LOGGER.log(Level.FINEST, closeException
1774: .getMessage(), closeException);
1775: }
1776: }
1777: }
1778: }
1779:
1780: if (!refresh) {
1781: // throw exception? or ignore...
1782: }
1783: }
1784:
1785: /**
1786: * Implement lockRefresh.
1787: *
1788: * @param lockID
1789: * @param t
1790: *
1791: * @return true if lock was found and refreshed
1792: *
1793: * @throws IOException
1794: *
1795: * @see org.geotools.data.Data#lockRefresh(java.lang.String,
1796: * org.geotools.data.Transaction)
1797: */
1798: public synchronized boolean lockRefresh(String lockID, Transaction t)
1799: throws IOException {
1800: boolean refresh = false;
1801:
1802: for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
1803: DataStoreInfo meta = (DataStoreInfo) i.next();
1804:
1805: if (!meta.isEnabled()) {
1806: continue; // disabled
1807: }
1808:
1809: DataStore dataStore;
1810:
1811: try {
1812: dataStore = meta.getDataStore();
1813: } catch (IllegalStateException notAvailable) {
1814: continue; // not available
1815: }
1816:
1817: LockingManager lockingManager = dataStore
1818: .getLockingManager();
1819:
1820: if (lockingManager == null) {
1821: continue; // locks not supported
1822: }
1823:
1824: if (lockingManager.refresh(lockID, t)) {
1825: refresh = true;
1826: }
1827: }
1828:
1829: return refresh;
1830: }
1831:
1832: /**
1833: * Implement lockRelease.
1834: *
1835: * @param lockID
1836: * @param t
1837: *
1838: * @return true if the lock was found and released
1839: *
1840: * @throws IOException
1841: *
1842: * @see org.geotools.data.Data#lockRelease(java.lang.String,
1843: * org.geotools.data.Transaction)
1844: */
1845: public synchronized boolean lockRelease(String lockID, Transaction t)
1846: throws IOException {
1847: boolean release = false;
1848:
1849: for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
1850: DataStoreInfo meta = (DataStoreInfo) i.next();
1851:
1852: if (!meta.isEnabled()) {
1853: continue; // disabled
1854: }
1855:
1856: DataStore dataStore;
1857:
1858: try {
1859: dataStore = meta.getDataStore();
1860: } catch (IllegalStateException notAvailable) {
1861: continue; // not available
1862: }
1863:
1864: LockingManager lockingManager = dataStore
1865: .getLockingManager();
1866:
1867: if (lockingManager == null) {
1868: continue; // locks not supported
1869: }
1870:
1871: if (lockingManager.release(lockID, t)) {
1872: release = true;
1873: }
1874: }
1875:
1876: return release;
1877: }
1878:
1879: /**
1880: * Implement lockExists.
1881: *
1882: * @param lockID
1883: *
1884: * @return true if lockID exists
1885: *
1886: * @see org.geotools.data.Data#lockExists(java.lang.String)
1887: */
1888: public synchronized boolean lockExists(String lockID) {
1889: for (Iterator i = dataStores.values().iterator(); i.hasNext();) {
1890: DataStoreInfo meta = (DataStoreInfo) i.next();
1891:
1892: if (!meta.isEnabled()) {
1893: continue; // disabled
1894: }
1895:
1896: DataStore dataStore;
1897:
1898: try {
1899: dataStore = meta.getDataStore();
1900: } catch (IllegalStateException notAvailable) {
1901: continue; // not available
1902: }
1903:
1904: LockingManager lockingManager = dataStore
1905: .getLockingManager();
1906:
1907: if (lockingManager == null) {
1908: continue; // locks not supported
1909: }
1910:
1911: if (lockingManager.exists(lockID)) {
1912: return true;
1913: }
1914: }
1915:
1916: return false;
1917: }
1918:
1919: //
1920: // GeoTools2 Catalog API
1921: //
1922:
1923: /**
1924: * Set of available Namespace prefixes.
1925: *
1926: * @return Set of namespace Prefixes
1927: *
1928: * @see org.geotools.data.Catalog#getPrefixes()
1929: */
1930: public synchronized Set getPrefixes() {
1931: return Collections.unmodifiableSet(nameSpaces.keySet());
1932: }
1933:
1934: /**
1935: * Prefix of the defaultNamespace.
1936: *
1937: * @return prefix of the default namespace
1938: *
1939: * @see org.geotools.data.Catalog#getDefaultPrefix()
1940: */
1941: public synchronized String getDefaultPrefix() {
1942: return defaultNameSpace.getPrefix();
1943: }
1944:
1945: /**
1946: * Implement getNamespace.
1947: *
1948: * <p>
1949: * Description ...
1950: * </p>
1951: *
1952: * @param prefix
1953: *
1954: * @return
1955: *
1956: * @see org.geotools.data.Catalog#getNamespace(java.lang.String)
1957: */
1958: public synchronized NameSpaceInfo getNamespaceMetaData(String prefix) {
1959: return getNameSpace(prefix);
1960: }
1961:
1962: /**
1963: * Register a DataStore with this Catalog.
1964: *
1965: * <p>
1966: * This is part of the public CatalogAPI, the fact that we don't want to
1967: * support it here may be gounds for it's removal.
1968: * </p>
1969: *
1970: * <p>
1971: * GeoSever and the global package would really like to have <b>complete</b>
1972: * control over the DataStores in use by the application. It recognize that
1973: * this may not always be possible. As GeoServer is extend with additional
1974: * Modules (such as config) that wish to locate and talk to DataStores
1975: * independently of GeoServer the best we can do is ask them to register
1976: * with the this Catalog in global.
1977: * </p>
1978: *
1979: * <p>
1980: * This reveals what may be a deisgn flaw in GeoTools2 DataStore. We have
1981: * know way of knowing if the dataStore has already been placed into our
1982: * care as DataStores are not good at identifying themselves. To complicate
1983: * matters most keep a static connectionPool around in their GDSFactory - it
1984: * could be that the Factories are supposed to be smart enough to prevent
1985: * duplication.
1986: * </p>
1987: *
1988: * @param dataStore
1989: *
1990: * @throws IOException
1991: *
1992: * @see org.geotools.data.Catalog#registerDataStore(org.geotools.data.DataStore)
1993: */
1994: public synchronized void registerDataStore(DataStore dataStore)
1995: throws IOException {
1996: }
1997:
1998: /**
1999: * Convience method for Accessing FeatureSource by prefix:typeName.
2000: *
2001: * <p>
2002: * This method is part of the public Catalog API. It allows the Validation
2003: * framework to be writen using only public Geotools2 interfaces.
2004: * </p>
2005: *
2006: * @param prefix
2007: * Namespace prefix in which the FeatureType available
2008: * @param typeName
2009: * typeNamed used to identify FeatureType
2010: *
2011: * @return
2012: *
2013: * @throws IOException
2014: * DOCUMENT ME!
2015: *
2016: * @see org.geotools.data.Catalog#getFeatureSource(java.lang.String,
2017: * java.lang.String)
2018: */
2019: public synchronized FeatureSource getFeatureSource(String prefix,
2020: String typeName) throws IOException {
2021: if ((prefix == null) || (prefix == "")) {
2022: prefix = defaultNameSpace.getPrefix();
2023: }
2024:
2025: NameSpaceInfo namespace = getNamespaceMetaData(prefix);
2026: FeatureTypeInfo featureType = namespace
2027: .getFeatureTypeInfo(typeName);
2028: DataStoreInfo dataStore = featureType.getDataStoreMetaData();
2029:
2030: return dataStore.getDataStore().getFeatureSource(typeName);
2031: }
2032:
2033: /**
2034: * Returns the baseDir for use with relative paths.
2035: *
2036: * @return Returns the baseDir.
2037: *
2038: * @uml.property name="baseDir"
2039: */
2040: public File getBaseDir() {
2041: return baseDir;
2042: }
2043:
2044: /**
2045: * Given a layer name will return its type, or null if the layer is not there
2046: * @param layerName the layer name, either fully qualified (namespace:name) or
2047: * just the name if the layers happens to be in the default namespace
2048: * @return the layer type (see {@link #TYPE_VECTOR} and {@link #TYPE_RASTER})
2049: */
2050: public Integer getLayerType(final String layerName) {
2051: Integer layerType = (Integer) layerNames.get(layerName);
2052:
2053: if (layerType != null) {
2054: return layerType;
2055: }
2056:
2057: // vector layers are namespace prefixed, coverages are not
2058: if (layerName.indexOf(":") == -1) {
2059: final String prefixedName = defaultNameSpace.getPrefix()
2060: + ":" + layerName;
2061:
2062: return (Integer) layerNames.get(prefixedName);
2063: } else {
2064: final String strippedName = layerName.substring(layerName
2065: .indexOf(":") + 1, layerName.length());
2066:
2067: return (Integer) layerNames.get(strippedName);
2068: }
2069: }
2070:
2071: /**
2072: * Returns an unmodifiable set of known layer names (feature type and coverages)
2073: * @return
2074: */
2075: public Set getLayerNames() {
2076: return Collections.unmodifiableSet(layerNames.keySet());
2077: }
2078: }
|