/* (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.security.web; import java.util.ArrayList; import java.util.List; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.ajax.AjaxRequestTarget; 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.Form; import org.apache.wicket.markup.html.form.SubmitLink; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.CompoundPropertyModel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.geoserver.security.GeoServerSecurityService; import org.geoserver.security.config.SecurityNamedServiceConfig; import org.geoserver.web.GeoServerApplication; /** * New page for specific class of named security service. * <p> * Most of the work is delegated to {@link SecurityNamedServicePanelInfo} and * {@link SecurityNamedServicePanel}. * </p> * * @author Justin Deoliveira, OpenGeo * */ public class SecurityNamedServiceNewPage <S extends GeoServerSecurityService, T extends SecurityNamedServiceConfig> extends SecurityNamedServicePage<T> { Form form; WebMarkupContainer panelContainer; public SecurityNamedServiceNewPage(Class<S> serviceClass) { //keys that allow us to dynamically set the page title and description based on // type of service class / extension point add(new Label("title1", createTitleModel(serviceClass).getString())); add(new Label("title2", createTitleModel(serviceClass).getString())); List<SecurityNamedServicePanelInfo> panelInfos = lookupPanelInfos(serviceClass); AjaxLinkGroup<SecurityNamedServicePanelInfo> serviceLinks = new AjaxLinkGroup<SecurityNamedServicePanelInfo>("services", panelInfos) { @Override protected void populateItem(ListItem<SecurityNamedServicePanelInfo> item) { SecurityNamedServicePanelInfo panelInfo = item.getModelObject(); item.add(newLink("link", item.getModel()).add( new Label("title", createShortTitleModel(panelInfo))).setEnabled(item.getIndex() > 0)); item.add(new Label("description", createDescriptionModel(panelInfo))); } @Override protected void onClick(AjaxLink<SecurityNamedServicePanelInfo> link, AjaxRequestTarget target) { updatePanel(link.getModelObject(), target); } }; add(new WebMarkupContainer("servicesContainer").add(serviceLinks).setOutputMarkupId(true)); add(form = new Form<T>("form")); //add a container for the actual panel, since we will dynamically update it form.add(panelContainer = new WebMarkupContainer("panel")); panelContainer.setOutputMarkupId(true); form.add(new SubmitLink("save", form) { @Override public void onSubmit() { handleSubmit(getForm()); } }); form.add(new Link("cancel") { @Override public void onClick() { doReturn(); } }); updatePanel(panelInfos.get(0), null); } void updatePanel(SecurityNamedServicePanelInfo panelInfo, AjaxRequestTarget target) { //create a new config object T config = null; try { config = (T) panelInfo.getServiceConfigClass().newInstance(); } catch (Exception e) { throw new WicketRuntimeException( "Unable to create config class: " + panelInfo.getServiceConfigClass(), e); } config.setClassName(panelInfo.getServiceClass().getCanonicalName()); //update the form model form.setModel(new CompoundPropertyModel<T>(config)); //create the new panel panel = createPanel("content", panelInfo, new Model(config)); //remove the old panel if it is there if (panelContainer.get("content") != null) { panelContainer.remove("content"); } panelContainer.add(panel); if (target != null) { target.add(panelContainer); } } List<SecurityNamedServicePanelInfo> lookupPanelInfos(Class<S> serviceClass) { List<SecurityNamedServicePanelInfo> panelInfos = new ArrayList(); for (SecurityNamedServicePanelInfo pageInfo : GeoServerApplication.get().getBeansOfType(SecurityNamedServicePanelInfo.class)) { if (serviceClass.isAssignableFrom(pageInfo.getServiceClass())) { panelInfos.add(pageInfo); } } if (panelInfos.isEmpty()) { throw new RuntimeException("Unable to find panel info for service class: " + serviceClass); } return panelInfos; } static abstract class AjaxLinkGroup<T> extends ListView<T> { public AjaxLinkGroup(String id, List<T> list) { super(id, list); } public AjaxLinkGroup(String id) { super(id); } void init() { setOutputMarkupId(true); } protected AjaxLink<T> newLink(String id, IModel<T> model) { return (AjaxLink<T>) new AjaxLink<T>(id, model) { @Override public void onClick(final AjaxRequestTarget target) { //set all links enabled AjaxLinkGroup.this.visitChildren(AjaxLink.class, (component, visit) -> { component.setEnabled(true); target.add(component); visit.dontGoDeeper(); }); //set this link disabled setEnabled(false); //update //target.add(AjaxLinkGroup.this.getParent()); target.add(this); AjaxLinkGroup.this.onClick(this, target); } }.setOutputMarkupId(true); } protected abstract void onClick(AjaxLink<T> link, AjaxRequestTarget target); } }