diff --git a/src/extension/restconfig/src/main/java/org/geoserver/catalog/rest/CoverageStoreFileResource.java b/src/extension/restconfig/src/main/java/org/geoserver/catalog/rest/CoverageStoreFileResource.java
index 9c2c461..eb3deec 100644
--- a/src/extension/restconfig/src/main/java/org/geoserver/catalog/rest/CoverageStoreFileResource.java
+++ b/src/extension/restconfig/src/main/java/org/geoserver/catalog/rest/CoverageStoreFileResource.java
@@ -198,6 +198,12 @@ public class CoverageStoreFileResource extends StoreFileResource {
                 }
                 */
 
+                try {
+                    catalog.validate(layerInfo, true);
+                } catch (Exception e) {
+                    layerInfo.setEnabled(false);
+                }
+
                 catalog.add(layerInfo);
             }
             else {
diff --git a/src/extension/restconfig/src/main/java/org/geoserver/catalog/rest/DataStoreFileResource.java b/src/extension/restconfig/src/main/java/org/geoserver/catalog/rest/DataStoreFileResource.java
index edaa54f..cf45c47 100644
--- a/src/extension/restconfig/src/main/java/org/geoserver/catalog/rest/DataStoreFileResource.java
+++ b/src/extension/restconfig/src/main/java/org/geoserver/catalog/rest/DataStoreFileResource.java
@@ -21,6 +21,7 @@ import org.geoserver.catalog.Catalog;
 import org.geoserver.catalog.CatalogBuilder;
 import org.geoserver.catalog.DataStoreInfo;
 import org.geoserver.catalog.FeatureTypeInfo;
+import org.geoserver.catalog.LayerInfo;
 import org.geoserver.catalog.NamespaceInfo;
 import org.geoserver.rest.RestletException;
 import org.geoserver.rest.format.StreamDataFormat;
@@ -229,8 +230,15 @@ public class DataStoreFileResource extends StoreFileResource {
                     catalog.add( ftinfo );
                     
                     //add a layer for the feature type as well
-                    catalog.add(builder.buildLayer(ftinfo));
-                   
+                    LayerInfo layer = builder.buildLayer(ftinfo);
+
+                    try { 
+                        catalog.validate(layer, true);
+                    } catch (Exception e) {
+                        layer.setEnabled(false);
+                    }
+
+                    catalog.add(layer);
                 }
                 else {
                     catalog.save( ftinfo );
diff --git a/src/main/src/main/java/org/geoserver/catalog/Catalog.java b/src/main/src/main/java/org/geoserver/catalog/Catalog.java
index b30b124..40467d2 100644
--- a/src/main/src/main/java/org/geoserver/catalog/Catalog.java
+++ b/src/main/src/main/java/org/geoserver/catalog/Catalog.java
@@ -151,6 +151,17 @@ public interface Catalog extends CatalogInfo {
     void add(StoreInfo store);
 
     /**
+     * Validate a store.
+     *
+     * @param store the StoreInfo to be validated
+     * @param isNew a boolean; if true then an existing store with the same
+     *     name and workspace will cause a validation error.
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(StoreInfo store, boolean isNew);
+
+    /**
      * Removes an existing store.
      */
     void remove(StoreInfo store);
@@ -606,6 +617,17 @@ public interface Catalog extends CatalogInfo {
     void add(ResourceInfo resource);
 
     /**
+     * Validate a resource.
+     *
+     * @param resource the ResourceInfo to be validated
+     * @param isNew a boolean; if true then an existing resource with the same
+     *     name and store will cause a validation error.
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(ResourceInfo resource, boolean isNew);
+
+    /**
      * Removes an existing resource.
      */
     void remove(ResourceInfo resource);
@@ -1033,6 +1055,17 @@ public interface Catalog extends CatalogInfo {
     void add(LayerInfo layer);
 
     /**
+     * Validate a layer.
+     *
+     * @param layer the LayerInfo to be validated
+     * @param isNew a boolean; if true then an existing layer with the same
+     *     name will cause a validation error.
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(LayerInfo layer, boolean isNew);
+
+    /**
      * Removes an existing layer.
      */
     void remove(LayerInfo layer);
@@ -1160,6 +1193,17 @@ public interface Catalog extends CatalogInfo {
      * Adds a layer group to the catalog.
      */
     void add(LayerGroupInfo layerGroup);
+
+    /**
+     * Validate a layergroup.
+     *
+     * @param layerGroup the LayerGroupInfo to be validated
+     * @param isNew a boolean; if true then an existing layergroup with the same
+     *     name will cause a validation error.
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(LayerGroupInfo layerGroup, boolean isNew);
     
     /**
      * Removes a layer group from the catalog.
@@ -1208,6 +1252,17 @@ public interface Catalog extends CatalogInfo {
     void add(StyleInfo style);
 
     /**
+     * Validate a style.
+     *
+     * @param style the StyleInfo to be validated
+     * @param isNew a boolean; if true then an existing style with the same
+     *     name will cause a validation error.
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(StyleInfo style, boolean isNew);
+
+    /**
      * Removes a style.
      */
     void remove(StyleInfo style);
@@ -1261,6 +1316,17 @@ public interface Catalog extends CatalogInfo {
     void add(NamespaceInfo namespace);
 
     /**
+     * Validate a namespace.
+     *
+     * @param namespace the NamespaceInfo to be validated
+     * @param isNew a boolean; if true then an existing namespace with the same
+     *     prefix will cause a validation error.
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(NamespaceInfo namespace, boolean isNew);
+
+    /**
      * Removes an existing namespace.
      */
     void remove(NamespaceInfo namespace);
@@ -1335,6 +1401,17 @@ public interface Catalog extends CatalogInfo {
     void add(WorkspaceInfo workspace);
     
     /**
+     * Validate a workspace.
+     *
+     * @param workspace the WorkspaceInfo to be validated
+     * @param isNew a boolean; if true then an existing workspace with the same
+     *     name will cause a validation error.
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(WorkspaceInfo workspace, boolean isNew);
+
+    /**
      * Removes an existing workspace.
      */
     void remove(WorkspaceInfo workspace);
diff --git a/src/main/src/main/java/org/geoserver/catalog/InfoValidator.java b/src/main/src/main/java/org/geoserver/catalog/InfoValidator.java
new file mode 100644
index 0000000..9ad7d92
--- /dev/null
+++ b/src/main/src/main/java/org/geoserver/catalog/InfoValidator.java
@@ -0,0 +1,90 @@
+/* Copyright (c) 2001 - 2008 TOPP - www.openplans.org. All rights reserved.
+ * This code is licensed under the GPL 2.0 license, available at the root
+ * application directory.
+ */
+package org.geoserver.catalog;
+
+/**
+ * Extension point for validation rules for catalog objects.
+ * 
+ * @author David Winslow, OpenGeo
+ *
+ */
+public interface InfoValidator {
+    /**
+     * Validate a resource.
+     *
+     * @param store the Resourceinfo to be validated
+     * @param isNew a boolean; if true then the resource is not expected to
+     *     already exist in the catalog.
+     *
+     * @throws RuntimeError if validation fails
+     */
+    void validate(ResourceInfo resource, boolean isNew);
+
+    /**
+     * Validate a store.
+     *
+     * @param store the StoreInfo to be validated
+     * @param isNew a boolean; if true then the store is not expected to
+     *     already exist in the catalog.
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(StoreInfo store, boolean isNew);
+
+    /**
+     * Validate a workspace.
+     *
+     * @param store the WorkspaceInfo to be validated
+     * @param isNew a boolean; if true then the workspace is not expected to
+     *     already exist in the catalog.
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(WorkspaceInfo workspace, boolean isNew);
+
+    /**
+     * Validate a layer.
+     *
+     * @param layer the LayerInfo to be validated
+     * @param isNew a boolean; if true then the layer is not expected to
+     *     already exist in the catalog.
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(LayerInfo layer, boolean isNew);
+
+    /**
+     * Validate a style.
+     *
+     * @param style the StyleInfo to be validated
+     * @param isNew a boolean; if true then the style is not expected to
+     *     already exist in the catalog.
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(StyleInfo style, boolean isNew);
+
+    /**
+     * Validate a layergroup.
+     *
+     * @param layerGroup the LayerGroupInfo to be validated
+     * @param isNew a boolean; if true then the layergroup is not expected to
+     *     already exist in the catalog.
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(LayerGroupInfo layerGroup, boolean isNew);
+
+    /**
+     * Validate a namespace.
+     *
+     * @param namespace the NamespaceInfo to be validated
+     * @param isNew a boolean; if true then the layer is not expected to
+     *     already exist in the catalog
+     * 
+     * @throws RuntimeError if validation fails
+     */
+    void validate(NamespaceInfo namespace, boolean isNew);
+}
diff --git a/src/main/src/main/java/org/geoserver/catalog/impl/AbstractInfoValidator.java b/src/main/src/main/java/org/geoserver/catalog/impl/AbstractInfoValidator.java
new file mode 100644
index 0000000..a072ccb
--- /dev/null
+++ b/src/main/src/main/java/org/geoserver/catalog/impl/AbstractInfoValidator.java
@@ -0,0 +1,46 @@
+/* Copyright (c) 2001 - 2008 TOPP - www.openplans.org. All rights reserved.
+ * This code is licensed under the GPL 2.0 license, available at the root
+ * application directory.
+ */
+package org.geoserver.catalog.impl;
+
+import org.geoserver.catalog.InfoValidator;
+import org.geoserver.catalog.LayerGroupInfo;
+import org.geoserver.catalog.LayerInfo;
+import org.geoserver.catalog.NamespaceInfo;
+import org.geoserver.catalog.ResourceInfo;
+import org.geoserver.catalog.StoreInfo;
+import org.geoserver.catalog.StyleInfo;
+import org.geoserver.catalog.WorkspaceInfo;
+
+/**
+ * A convenience implementation of InfoValidator with all methods implemented
+ * as a no-op.  You can override individual methods without having to provide
+ * your own stubs.
+ * 
+ * @author David Winslow, OpenGeo
+ *
+ */
+public abstract class AbstractInfoValidator implements InfoValidator {
+
+    public void validate(ResourceInfo resource, boolean isNew) {
+    }
+
+    public void validate(StoreInfo store, boolean isNew) {
+    }
+
+    public void validate(WorkspaceInfo workspace, boolean isNew) {
+    }
+
+    public void validate(LayerInfo layer, boolean isNew) {
+    }
+
+    public void validate(StyleInfo style, boolean isNew) {
+    }
+
+    public void validate(LayerGroupInfo layerGroup, boolean isNew) {
+    }
+
+    public void validate(NamespaceInfo namespace, boolean isNew) {
+    }
+}
diff --git a/src/main/src/main/java/org/geoserver/catalog/impl/CatalogImpl.java b/src/main/src/main/java/org/geoserver/catalog/impl/CatalogImpl.java
index d2492d8..53a1173 100644
--- a/src/main/src/main/java/org/geoserver/catalog/impl/CatalogImpl.java
+++ b/src/main/src/main/java/org/geoserver/catalog/impl/CatalogImpl.java
@@ -30,6 +30,7 @@ import org.geoserver.catalog.CoverageInfo;
 import org.geoserver.catalog.CoverageStoreInfo;
 import org.geoserver.catalog.DataStoreInfo;
 import org.geoserver.catalog.FeatureTypeInfo;
+import org.geoserver.catalog.InfoValidator;
 import org.geoserver.catalog.LayerGroupInfo;
 import org.geoserver.catalog.LayerInfo;
 import org.geoserver.catalog.MapInfo;
@@ -53,6 +54,7 @@ import org.geoserver.catalog.event.impl.CatalogPostModifyEventImpl;
 import org.geoserver.catalog.event.impl.CatalogRemoveEventImpl;
 import org.geoserver.ows.util.ClassProperties;
 import org.geoserver.ows.util.OwsUtils;
+import org.geoserver.platform.GeoServerExtensions;
 import org.geoserver.platform.GeoServerResourceLoader;
 import org.geotools.util.logging.Logging;
 import org.opengis.feature.type.Name;
@@ -98,6 +100,10 @@ public class CatalogImpl implements Catalog {
     public CatalogFacade getFacade() {
         return facade;
     }
+
+    public Iterable<InfoValidator> getValidators() {
+        return GeoServerExtensions.extensions(InfoValidator.class);
+    }
     
     public void setFacade(CatalogFacade facade) {
         this.facade = facade;
@@ -120,7 +126,7 @@ public class CatalogImpl implements Catalog {
         }
 
         validate(store, true);
-        
+
         //TODO: remove synchronized block, need transactions
         synchronized (facade) {
             facade.add(resolve(store));
@@ -133,7 +139,7 @@ public class CatalogImpl implements Catalog {
         added(store);
     }
 
-    void validate(StoreInfo store, boolean isNew) {
+    public void validate(StoreInfo store, boolean isNew) {
         if ( isNull(store.getName()) ) {
             throw new IllegalArgumentException( "Store name must not be null");
         }
@@ -147,6 +153,10 @@ public class CatalogImpl implements Catalog {
             String msg = "Store '"+ store.getName() +"' already exists in workspace '"+workspace.getName()+"'";
             throw new IllegalArgumentException( msg );
         }    
+
+        for (InfoValidator constraint : getValidators()) {
+            constraint.validate(store, isNew);
+        }
     }
     
     public void remove(StoreInfo store) {
@@ -350,7 +360,7 @@ public class CatalogImpl implements Catalog {
         added(resource);
     }
 
-    void validate(ResourceInfo resource, boolean isNew) {
+    public void validate(ResourceInfo resource, boolean isNew) {
         if ( isNull(resource.getName()) ) {
             throw new NullPointerException( "Resource name must not be null");
         }
@@ -378,6 +388,9 @@ public class CatalogImpl implements Catalog {
             throw new IllegalArgumentException( msg );
         }
         
+        for (InfoValidator constraint : getValidators()) {
+            constraint.validate(resource, isNew);
+        }
     }
     
     public void remove(ResourceInfo resource) {
@@ -602,7 +615,7 @@ public class CatalogImpl implements Catalog {
         added(layer);
     }
 
-    void validate( LayerInfo layer, boolean isNew) {
+    public void validate( LayerInfo layer, boolean isNew) {
         // TODO: bring back when the layer/publishing split is in act
 //        if ( isNull(layer.getName()) ) {
 //            throw new NullPointerException( "Layer name must not be null" );
@@ -625,6 +638,10 @@ public class CatalogImpl implements Catalog {
         //if ( layer.getDefaultStyle() == null ){
         //    throw new NullPointerException( "Layer default style must not be null" );
         //}
+
+        for (InfoValidator constraint : getValidators()) {
+            constraint.validate(layer, isNew);
+        }
     }
    
     public void remove(LayerInfo layer) {
@@ -731,7 +748,7 @@ public class CatalogImpl implements Catalog {
         added( layerGroup );
     }
     
-    void validate( LayerGroupInfo layerGroup, boolean isNew ) {
+    public void validate( LayerGroupInfo layerGroup, boolean isNew ) {
         if( isNull(layerGroup.getName()) ) {
             throw new NullPointerException( "Layer group name must not be null");
         }
@@ -749,6 +766,10 @@ public class CatalogImpl implements Catalog {
                 !(layerGroup.getStyles().size() == layerGroup.getLayers().size()) ) {
             throw new IllegalArgumentException( "Layer group has different number of styles than layers");
         }
+
+        for (InfoValidator constraint : getValidators()) {
+            constraint.validate(layerGroup, isNew);
+        }
     }
     
     public void remove(LayerGroupInfo layerGroup) {
@@ -834,7 +855,7 @@ public class CatalogImpl implements Catalog {
         added(namespace);
     }
 
-    void validate(NamespaceInfo namespace, boolean isNew) {
+    public void validate(NamespaceInfo namespace, boolean isNew) {
         if ( isNull(namespace.getPrefix()) ) {
             throw new NullPointerException( "Namespace prefix must not be null");
         }
@@ -863,6 +884,10 @@ public class CatalogImpl implements Catalog {
             throw new IllegalArgumentException("Invalid URI syntax for '" + namespace.getURI() 
                     + "' in namespace '" + namespace.getPrefix() + "'");
         }
+
+        for (InfoValidator constraint : getValidators()) {
+            constraint.validate(namespace, isNew);
+        }
     }
     
     public void remove(NamespaceInfo namespace) {
@@ -916,7 +941,7 @@ public class CatalogImpl implements Catalog {
         added( workspace );
     }
     
-    void validate(WorkspaceInfo workspace, boolean isNew) {
+    public void validate(WorkspaceInfo workspace, boolean isNew) {
         if ( isNull(workspace.getName()) ) {
             throw new NullPointerException( "workspace name must not be null");
         }
@@ -930,6 +955,9 @@ public class CatalogImpl implements Catalog {
             throw new IllegalArgumentException( "Workspace named '"+ workspace.getName() +"' already exists.");
         }
         
+        for (InfoValidator constraint : getValidators()) {
+            constraint.validate(workspace, isNew);
+        }
     }
     
     public void remove(WorkspaceInfo workspace) {
@@ -1021,7 +1049,7 @@ public class CatalogImpl implements Catalog {
         added(style);
     }
 
-    void validate( StyleInfo style, boolean isNew ) {
+    public void validate( StyleInfo style, boolean isNew ) {
         if ( isNull(style.getName()) ) {
             throw new NullPointerException( "Style name must not be null");
         }
@@ -1033,6 +1061,10 @@ public class CatalogImpl implements Catalog {
         if ( existing != null && !existing.getId().equals( style.getId() )) {
             throw new IllegalArgumentException( "Style named '" +  style.getName() +"' already exists.");
         }
+
+        for (InfoValidator constraint : getValidators()) {
+            constraint.validate(style, isNew);
+        }
     }
     
     public void remove(StyleInfo style) {
diff --git a/src/main/src/main/java/org/geoserver/catalog/impl/LayerInfoImpl.java b/src/main/src/main/java/org/geoserver/catalog/impl/LayerInfoImpl.java
index 317aa9d..012af9f 100644
--- a/src/main/src/main/java/org/geoserver/catalog/impl/LayerInfoImpl.java
+++ b/src/main/src/main/java/org/geoserver/catalog/impl/LayerInfoImpl.java
@@ -11,11 +11,14 @@ import java.util.logging.Logger;
 
 import org.geoserver.catalog.AttributionInfo;
 import org.geoserver.catalog.CatalogVisitor;
+import org.geoserver.catalog.CoverageInfo;
+import org.geoserver.catalog.FeatureTypeInfo;
 import org.geoserver.catalog.LayerInfo;
 import org.geoserver.catalog.LegendInfo;
 import org.geoserver.catalog.MetadataMap;
 import org.geoserver.catalog.ResourceInfo;
 import org.geoserver.catalog.StyleInfo;
+import org.geotools.factory.GeoTools;
 import org.geotools.util.logging.Logging;
 
 public class LayerInfoImpl implements LayerInfo {
diff --git a/src/main/src/main/java/org/geoserver/security/SecureCatalogImpl.java b/src/main/src/main/java/org/geoserver/security/SecureCatalogImpl.java
index 074fe7e..38dda6f 100644
--- a/src/main/src/main/java/org/geoserver/security/SecureCatalogImpl.java
+++ b/src/main/src/main/java/org/geoserver/security/SecureCatalogImpl.java
@@ -850,6 +850,10 @@ public class SecureCatalogImpl extends AbstractDecorator<Catalog> implements Cat
         delegate.add(unwrap(layerGroup));
     }
 
+    public void validate(LayerGroupInfo layerGroup, boolean isNew) {
+        delegate.validate(unwrap(layerGroup), isNew);
+    }
+
     public LayerGroupInfo detach(LayerGroupInfo layerGroup) {
         return delegate.detach(layerGroup);
     }
@@ -858,6 +862,10 @@ public class SecureCatalogImpl extends AbstractDecorator<Catalog> implements Cat
         delegate.add(unwrap(layer));
     }
 
+    public void validate(LayerInfo layer, boolean isNew) {
+        delegate.validate(unwrap(layer), isNew);
+    }
+
     public LayerInfo detach(LayerInfo layer) {
         return delegate.detach(layer);
     }
@@ -874,6 +882,10 @@ public class SecureCatalogImpl extends AbstractDecorator<Catalog> implements Cat
         delegate.add(namespace);
     }
 
+    public void validate(NamespaceInfo namespace, boolean isNew) {
+        delegate.validate(namespace, isNew);
+    }
+
     public NamespaceInfo detach(NamespaceInfo namespace) {
         return delegate.detach(namespace);
     }
@@ -882,6 +894,10 @@ public class SecureCatalogImpl extends AbstractDecorator<Catalog> implements Cat
         delegate.add(unwrap(resource));
     }
 
+    public void validate(ResourceInfo resource, boolean isNew) {
+        delegate.validate(unwrap(resource), isNew);
+    }
+
     public <T extends ResourceInfo> T detach(T resource) {
         return delegate.detach(resource);
     }
@@ -889,6 +905,11 @@ public class SecureCatalogImpl extends AbstractDecorator<Catalog> implements Cat
     public void add(StoreInfo store) {
         delegate.add(unwrap(store));
     }
+
+    public void validate(StoreInfo store, boolean isNew) {
+        delegate.validate(unwrap(store), isNew);
+    }
+
     
     public <T extends StoreInfo> T detach(T store) {
         return delegate.detach(store);
@@ -898,6 +919,10 @@ public class SecureCatalogImpl extends AbstractDecorator<Catalog> implements Cat
         delegate.add(style);
     }
 
+    public void validate(StyleInfo style, boolean isNew) {
+        delegate.validate(style, isNew);
+    }
+
     public StyleInfo detach(StyleInfo style) {
         return delegate.detach(style);
     }
@@ -906,6 +931,10 @@ public class SecureCatalogImpl extends AbstractDecorator<Catalog> implements Cat
         delegate.add(workspace);
     }
 
+    public void validate(WorkspaceInfo workspace, boolean isNew) {
+        delegate.validate(workspace, isNew);
+    }
+
     public WorkspaceInfo detach(WorkspaceInfo workspace) {
         return delegate.detach(workspace);
     }
diff --git a/src/main/src/main/java/org/geoserver/security/decorators/DecoratingLayerInfo.java b/src/main/src/main/java/org/geoserver/security/decorators/DecoratingLayerInfo.java
index 189c73d..f59df98 100644
--- a/src/main/src/main/java/org/geoserver/security/decorators/DecoratingLayerInfo.java
+++ b/src/main/src/main/java/org/geoserver/security/decorators/DecoratingLayerInfo.java
@@ -106,6 +106,11 @@ public class DecoratingLayerInfo extends AbstractDecorator<LayerInfo> implements
     public void accept(CatalogVisitor visitor) {
         delegate.accept(visitor);
     }
+
+    @Override
+    public boolean willBreakGetCaps() {
+        return delegate.willBreakGetCaps();
+    }
     
     @Override
     public String toString() {
diff --git a/src/wms/src/main/java/applicationContext.xml b/src/wms/src/main/java/applicationContext.xml
index 035a50e..e9c021e 100644
--- a/src/wms/src/main/java/applicationContext.xml
+++ b/src/wms/src/main/java/applicationContext.xml
@@ -561,4 +561,8 @@
     <bean id="wmsLifecycleHandler" class="org.geoserver.wms.WMSLifecycleHandler">
       <constructor-arg index="0" ref="dataDirectory"/>
     </bean>
+      
+    <bean id="wmsCatalogValidator" class="org.geoserver.wms.WMSValidator">
+      <constructor-arg ref="catalog"/>
+    </bean>
 </beans>
diff --git a/src/wms/src/main/java/org/geoserver/wms/WMSValidator.java b/src/wms/src/main/java/org/geoserver/wms/WMSValidator.java
new file mode 100644
index 0000000..3e81fb4
--- /dev/null
+++ b/src/wms/src/main/java/org/geoserver/wms/WMSValidator.java
@@ -0,0 +1,53 @@
+/* Copyright (c) 2010 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.geoserver.wms;
+
+import java.util.List;
+
+import org.geoserver.catalog.LayerInfo;
+import org.geoserver.catalog.impl.AbstractInfoValidator;
+
+/**
+ * Configuration validator for Web Map Service.
+ * 
+ * @author David Winslow, OpenGeo
+ */
+public class WMSValidator extends AbstractInfoValidator {
+    public void validate(LayerInfo lyr, boolean isNew) {
+        if (
+            lyr.resource == null ||
+            lyr.resource.getNamespace() == null ||
+            lyr.resource.getTitle() == null ||
+            lyr.resource.getAbstract() == null ||
+            lyr.resource.getSRS() == null ||
+            lyr.resource.getLatLonBoundingBox() == null
+        ) return true;
+      
+        // Resource-dependent checks
+        if (lyr.getType() == Type.RASTER) {
+            if (!(lyr.resource instanceof CoverageInfo)) return true;
+            CoverageInfo cvinfo = (CoverageInfo) lyr.resource;
+            try {
+                cvinfo.getCatalog().getResourcePool().getGridCoverageReader(
+                    cvinfo.getStore(),
+                    GeoTools.getDefaultHints()
+                );
+            } catch (Throwable t) {
+                return true;
+            }
+        } else if (lyr.getType() == Type.VECTOR) {
+            if (!(lyr.resource instanceof FeatureTypeInfo)) return true;
+            FeatureTypeInfo ftinfo = (FeatureTypeInfo) lyr.resource;
+        } else return true;
+
+        // Style-dependent checks
+        if (
+            lyr.getDefaultStyle() == null ||
+            lyr.getStyles().contains(null)
+        ) return true;
+
+        return false;
+    }
+}
