/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.web.data.layer; import java.io.IOException; import java.util.logging.Level; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.image.Image; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.request.resource.PackageResourceReference; import org.geoserver.catalog.Catalog; import org.geoserver.catalog.CatalogBuilder; import org.geoserver.catalog.CoverageInfo; import org.geoserver.catalog.CoverageStoreInfo; import org.geoserver.catalog.DataStoreInfo; import org.geoserver.catalog.FeatureTypeInfo; import org.geoserver.catalog.LayerInfo; import org.geoserver.catalog.ResourceInfo; import org.geoserver.catalog.StoreInfo; import org.geoserver.catalog.WMSLayerInfo; import org.geoserver.catalog.WMSStoreInfo; import org.geoserver.web.CatalogIconFactory; import org.geoserver.web.ComponentAuthorizer; import org.geoserver.web.GeoServerSecuredPage; import org.geoserver.web.data.importer.WMSLayerImporterPage; import org.geoserver.web.data.resource.ResourceConfigurationPage; import org.geoserver.web.data.store.StoreListChoiceRenderer; import org.geoserver.web.data.store.StoreListModel; import org.geoserver.web.wicket.GeoServerDataProvider.Property; import org.geoserver.web.wicket.GeoServerTablePanel; import org.geoserver.web.wicket.ParamResourceModel; import org.geoserver.web.wicket.SimpleAjaxLink; import org.geotools.data.DataAccess; import org.geotools.data.DataStore; import org.geotools.data.wfs.WFSDataStore; import org.geotools.data.wms.WebMapServer; import org.geotools.jdbc.JDBCDataStore; /** * A page listing the resources contained in a store, and whose links will bring * the user to a new resource configuration page * * @author Andrea Aime - OpenGeo */ @SuppressWarnings("serial") public class NewLayerPage extends GeoServerSecuredPage { String storeId; private NewLayerPageProvider provider; private GeoServerTablePanel<Resource> layers; private WebMarkupContainer selectLayersContainer; private WebMarkupContainer selectLayers; private Label storeName; private WebMarkupContainer createTypeContainer; private WebMarkupContainer createSQLViewContainer; private WebMarkupContainer createCoverageViewContainer; private WebMarkupContainer createCascadedWFSStoredQueryContainer; private WebMarkupContainer createWMSLayerImportContainer; public NewLayerPage() { this(null); } public NewLayerPage(String storeId) { this.storeId = storeId; // the store selector, used when no store is initially known Form<?> selector = new Form<Void>("selector"); selector.add(storesDropDown()); selector.setVisible(storeId == null); add(selector); // the layer choosing block // visible when in any way a store has been chosen selectLayersContainer = new WebMarkupContainer("selectLayersContainer"); selectLayersContainer.setOutputMarkupId(true); add(selectLayersContainer); selectLayers = new WebMarkupContainer("selectLayers"); selectLayers.setVisible(storeId != null); selectLayersContainer.add(selectLayers); selectLayers.add(storeName = new Label("storeName", new Model<String>())); if(storeId != null) { StoreInfo store = getCatalog().getStore(storeId, StoreInfo.class); storeName.setDefaultModelObject(store.getName()); } provider = new NewLayerPageProvider(); provider.setStoreId(storeId); provider.setShowPublished(true); layers = new GeoServerTablePanel<Resource>("layers", provider) { @Override protected Component getComponentForProperty(String id, IModel<Resource> itemModel, Property<Resource> property) { if (property == NewLayerPageProvider.NAME) { return new Label(id, property.getModel(itemModel)); } else if (property == NewLayerPageProvider.PUBLISHED) { final Resource resource = itemModel.getObject(); final CatalogIconFactory icons = CatalogIconFactory.get(); if(resource.isPublished()) { PackageResourceReference icon = icons.getEnabledIcon(); Fragment f = new Fragment(id, "iconFragment", selectLayers); f.add(new Image("layerIcon", icon)); return f; } else { return new Label(id); } } else if(property == NewLayerPageProvider.ACTION) { final Resource resource = itemModel.getObject(); if(resource.isPublished()) { return resourceChooserLink(id, itemModel, new ParamResourceModel("publishAgain", this)); } else { return resourceChooserLink(id, itemModel, new ParamResourceModel("publish", this)); } } else { throw new IllegalArgumentException( "Don't know of property " + property.getName()); } } }; layers.setFilterVisible(true); selectLayers.add(layers); createTypeContainer = new WebMarkupContainer("createTypeContainer"); createTypeContainer.setVisible(false); createTypeContainer.add(newFeatureTypeLink()); selectLayersContainer.add(createTypeContainer); createSQLViewContainer = new WebMarkupContainer("createSQLViewContainer"); createSQLViewContainer.setVisible(false); createSQLViewContainer.add(newSQLViewLink()); selectLayersContainer.add(createSQLViewContainer); createCoverageViewContainer = new WebMarkupContainer("createCoverageViewContainer"); createCoverageViewContainer.setVisible(false); createCoverageViewContainer.add(newCoverageViewLink()); selectLayersContainer.add(createCoverageViewContainer); createCascadedWFSStoredQueryContainer = new WebMarkupContainer("createCascadedWFSStoredQueryContainer"); createCascadedWFSStoredQueryContainer.setVisible(false); createCascadedWFSStoredQueryContainer.add(newCascadedWFSStoredQueryLink()); selectLayersContainer.add(createCascadedWFSStoredQueryContainer); createWMSLayerImportContainer = new WebMarkupContainer("createWMSLayerImportContainer"); createWMSLayerImportContainer.setVisible(false); createWMSLayerImportContainer.add(newWMSImportLink()); selectLayersContainer.add(createWMSLayerImportContainer); // case where the store is selected, or we have just created new one if(storeId != null) { StoreInfo store = getCatalog().getStore(storeId, StoreInfo.class); updateSpecialFunctionPanels(store); } } Component newFeatureTypeLink() { return new AjaxLink<Void>("createFeatureType") { @Override public void onClick(AjaxRequestTarget target) { DataStoreInfo ds = getCatalog().getStore(storeId, DataStoreInfo.class); PageParameters pp = new PageParameters().add("wsName", ds.getWorkspace().getName()).add("storeName", ds.getName()); setResponsePage(NewFeatureTypePage.class, pp); } }; } Component newSQLViewLink() { return new AjaxLink<Void>("createSQLView") { @Override public void onClick(AjaxRequestTarget target) { DataStoreInfo ds = getCatalog().getStore(storeId, DataStoreInfo.class); PageParameters pp = new PageParameters().add("wsName", ds.getWorkspace().getName()).add("storeName", ds.getName()); setResponsePage(SQLViewNewPage.class, pp); } }; } Component newCoverageViewLink() { return new AjaxLink<Void>("createCoverageView") { @Override public void onClick(AjaxRequestTarget target) { CoverageStoreInfo cs = getCatalog().getStore(storeId, CoverageStoreInfo.class); PageParameters pp = new PageParameters().add("wsName", cs.getWorkspace().getName()).add("storeName", cs.getName()); setResponsePage(CoverageViewNewPage.class, pp); } }; } Component newCascadedWFSStoredQueryLink() { return new AjaxLink<Void>("createCascadedWFSStoredQuery") { @Override public void onClick(AjaxRequestTarget target) { DataStoreInfo ds = getCatalog().getStore(storeId, DataStoreInfo.class); PageParameters pp = new PageParameters().add("wsName", ds.getWorkspace().getName()).add("storeName", ds.getName()); setResponsePage(CascadedWFSStoredQueryNewPage.class, pp); } }; } Component newWMSImportLink() { return new AjaxLink<Void>("createWMSImport") { @Override public void onClick(AjaxRequestTarget target) { PageParameters pp = new PageParameters().add("storeId", storeId); setResponsePage(WMSLayerImporterPage.class, pp); } }; } private DropDownChoice<StoreInfo> storesDropDown() { final DropDownChoice<StoreInfo> stores = new DropDownChoice<>("storesDropDown", new Model<StoreInfo>(), new StoreListModel(), new StoreListChoiceRenderer()); stores.setOutputMarkupId(true); stores.add(new AjaxFormComponentUpdatingBehavior("change") { @Override protected void onUpdate(AjaxRequestTarget target) { if (stores.getModelObject() != null) { StoreInfo store = (StoreInfo) stores.getModelObject(); NewLayerPage.this.storeId = store.getId(); provider.setStoreId(store.getId()); storeName.setDefaultModelObject(store.getName()); selectLayers.setVisible(true); // make sure we can actually list the contents, it may happen // the store is actually unreachable, in that case we // want to display an error message try { provider.getItems(); } catch(Exception e) { LOGGER.log(Level.SEVERE, "Error retrieving layers for the specified store", e); error(e.getMessage()); selectLayers.setVisible(false); } updateSpecialFunctionPanels(store); } else { selectLayers.setVisible(false); createTypeContainer.setVisible(false); } target.add(selectLayersContainer); target.add(feedbackPanel); } }); return stores; } SimpleAjaxLink<Resource> resourceChooserLink(String id, IModel<Resource> itemModel, IModel<String> label) { return new SimpleAjaxLink<Resource>(id, itemModel, label) { @Override protected void onClick(AjaxRequestTarget target) { Resource resource = (Resource) getDefaultModelObject(); setResponsePage(new ResourceConfigurationPage( buildLayerInfo(resource), true)); } }; } void updateSpecialFunctionPanels(StoreInfo store) { // at the moment just assume every store can create types try { createTypeContainer.setVisible(store instanceof DataStoreInfo && ((DataStoreInfo)store).getDataStore(null) instanceof DataStore); } catch (IOException e) { LOGGER.log(Level.FINEST, e.getMessage()); } // reset to default first, to avoid the container being displayed if store is not a // DataStoreInfo createSQLViewContainer.setVisible(false); createCascadedWFSStoredQueryContainer.setVisible(false); if (store instanceof DataStoreInfo) { try { DataAccess<?,?> da = ((DataStoreInfo) store).getDataStore(null); createSQLViewContainer.setVisible(da instanceof JDBCDataStore); if (da instanceof WFSDataStore) { createCascadedWFSStoredQueryContainer.setVisible(((WFSDataStore)da).supportsStoredQueries()); } } catch (IOException e) { LOGGER.log(Level.FINEST, e.getMessage()); } } createCoverageViewContainer.setVisible(false); if (store instanceof CoverageStoreInfo) { createCoverageViewContainer.setVisible(true); } // reset to default first, to avoid the container being displayed if store is not a // WMSStoreInfo createWMSLayerImportContainer.setVisible(false); if (store instanceof WMSStoreInfo) { try { WebMapServer wms = ((WMSStoreInfo) store).getWebMapServer(null); createWMSLayerImportContainer.setVisible(wms != null); } catch (IOException e) { LOGGER.log(Level.FINEST, e.getMessage()); } } } /** * Turns a resource name into a full {@link ResourceInfo} * * @param resource * */ LayerInfo buildLayerInfo(Resource resource) { Catalog catalog = getCatalog(); StoreInfo store = catalog.getStore(getSelectedStoreId(), StoreInfo.class); StoreInfo expandedStore = null; if(store instanceof DataStoreInfo) { DataStoreInfo dstore = (DataStoreInfo) store; expandedStore = getCatalog().getResourcePool().clone(dstore, true); } else if(store instanceof CoverageStoreInfo) { CoverageStoreInfo cstore = (CoverageStoreInfo) store; expandedStore = getCatalog().getResourcePool().clone(cstore, true); } else if(store instanceof WMSStoreInfo) { WMSStoreInfo wmsInfo = (WMSStoreInfo) store; expandedStore = getCatalog().getResourcePool().clone(wmsInfo, true); } // try to build from coverage store or data store try { CatalogBuilder builder = new CatalogBuilder(catalog); builder.setStore(expandedStore); if (expandedStore instanceof CoverageStoreInfo) { CoverageInfo ci = builder.buildCoverage(resource.getName().getLocalPart()); return builder.buildLayer(ci); } else if (expandedStore instanceof DataStoreInfo) { FeatureTypeInfo fti = builder.buildFeatureType(resource.getName()); return builder.buildLayer(fti); } else if (expandedStore instanceof WMSStoreInfo) { WMSLayerInfo wli = builder.buildWMSLayer(resource.getLocalName()); return builder.buildLayer(wli); } } catch (Exception e) { throw new RuntimeException( "Error occurred while building the resources for the configuration page", e); } // handle the case in which the store was not found anymore, or was not // of the expected type if (expandedStore == null) throw new IllegalArgumentException( "Store is missing from configuration!"); else throw new IllegalArgumentException( "Don't know how to deal with this store " + expandedStore); } /** * Returns the storeId provided during construction, or the one pointed * by the drop down if none was provided during construction * */ String getSelectedStoreId() { // the provider is always up to date return provider.getStoreId(); } @Override protected ComponentAuthorizer getPageAuthorizer() { return ComponentAuthorizer.WORKSPACE_ADMIN; } }