Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.syncope.client.console.panels; import static org.apache.wicket.Component.ENABLE; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.client.console.commons.Constants; import org.apache.syncope.client.console.pages.BasePage; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel; import org.apache.syncope.client.console.wicket.markup.html.form.SpinnerFieldPanel; import org.apache.syncope.client.console.wicket.markup.html.list.ConnConfPropertyListView; import org.apache.syncope.common.lib.SyncopeClientException; import org.apache.syncope.common.lib.to.ConnBundleTO; import org.apache.syncope.common.lib.to.ConnInstanceTO; import org.apache.syncope.common.lib.to.ConnPoolConfTO; import org.apache.syncope.common.lib.types.ConnConfPropSchema; import org.apache.syncope.common.lib.types.ConnConfProperty; import org.apache.syncope.common.lib.types.ConnectorCapability; import org.apache.syncope.common.lib.types.Entitlement; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.ajax.markup.html.form.AjaxButton; import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy; import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton; import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.CheckBoxMultipleChoice; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.Form; 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.LoadableDetachableModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.model.ResourceModel; import org.apache.wicket.validation.validator.RangeValidator; /** * Modal window with Connector form. */ public class ConnectorModal extends ModalContent { private static final long serialVersionUID = -2025535531121434050L; private final Map<String, Map<String, Map<String, ConnBundleTO>>> mapConnBundleTOs; private final List<ConnectorCapability> selectedCapabilities; private ConnBundleTO bundleTO; private List<ConnConfProperty> properties; private final WebMarkupContainer propertiesContainer; public ConnectorModal(final ModalWindow window, final PageReference pageRef, final ConnInstanceTO connInstanceTO) { super(window, pageRef); this.add(new Label("new", connInstanceTO.getKey() == 0 ? new ResourceModel("new") : new Model<>(StringUtils.EMPTY))); this.add(new Label("key", connInstanceTO.getKey() == 0 ? StringUtils.EMPTY : connInstanceTO.getKey())); // general data setup selectedCapabilities = new ArrayList<>( connInstanceTO.getKey() == 0 ? EnumSet.noneOf(ConnectorCapability.class) : connInstanceTO.getCapabilities()); mapConnBundleTOs = new HashMap<>(); for (ConnBundleTO connBundleTO : connectorRestClient.getAllBundles()) { // by location if (!mapConnBundleTOs.containsKey(connBundleTO.getLocation())) { mapConnBundleTOs.put(connBundleTO.getLocation(), new HashMap<String, Map<String, ConnBundleTO>>()); } final Map<String, Map<String, ConnBundleTO>> byLocation = mapConnBundleTOs .get(connBundleTO.getLocation()); // by name if (!byLocation.containsKey(connBundleTO.getBundleName())) { byLocation.put(connBundleTO.getBundleName(), new HashMap<String, ConnBundleTO>()); } final Map<String, ConnBundleTO> byName = byLocation.get(connBundleTO.getBundleName()); // by version if (!byName.containsKey(connBundleTO.getVersion())) { byName.put(connBundleTO.getVersion(), connBundleTO); } } bundleTO = getSelectedBundleTO(connInstanceTO); properties = fillProperties(bundleTO, connInstanceTO); // form - first tab final Form<ConnInstanceTO> connectorForm = new Form<>(FORM); connectorForm.setModel(new CompoundPropertyModel<>(connInstanceTO)); connectorForm.setOutputMarkupId(true); add(connectorForm); propertiesContainer = new WebMarkupContainer("container"); propertiesContainer.setOutputMarkupId(true); connectorForm.add(propertiesContainer); final Form<ConnInstanceTO> connectorPropForm = new Form<>("connectorPropForm"); connectorPropForm.setModel(new CompoundPropertyModel<>(connInstanceTO)); connectorPropForm.setOutputMarkupId(true); propertiesContainer.add(connectorPropForm); final AjaxTextFieldPanel displayName = new AjaxTextFieldPanel("displayName", "display name", new PropertyModel<String>(connInstanceTO, "displayName")); displayName.setOutputMarkupId(true); displayName.addRequiredLabel(); connectorForm.add(displayName); final AjaxDropDownChoicePanel<String> location = new AjaxDropDownChoicePanel<>("location", "location", new Model<>(bundleTO == null ? null : bundleTO.getLocation())); ((DropDownChoice<String>) location.getField()).setNullValid(true); location.setStyleSheet("long_dynamicsize"); location.setChoices(new ArrayList<>(mapConnBundleTOs.keySet())); location.setRequired(true); location.addRequiredLabel(); location.setOutputMarkupId(true); location.setEnabled(connInstanceTO.getKey() == 0); location.getField().setOutputMarkupId(true); connectorForm.add(location); final AjaxDropDownChoicePanel<String> connectorName = new AjaxDropDownChoicePanel<>("connectorName", "connectorName", new Model<>(bundleTO == null ? null : bundleTO.getBundleName())); ((DropDownChoice<String>) connectorName.getField()).setNullValid(true); connectorName.setStyleSheet("long_dynamicsize"); connectorName.setChoices(bundleTO == null ? new ArrayList<String>() : new ArrayList<>(mapConnBundleTOs.get(connInstanceTO.getLocation()).keySet())); connectorName.setRequired(true); connectorName.addRequiredLabel(); connectorName.setEnabled(connInstanceTO.getLocation() != null); connectorName.setOutputMarkupId(true); connectorName.setEnabled(connInstanceTO.getKey() == 0); connectorName.getField().setOutputMarkupId(true); connectorForm.add(connectorName); final AjaxDropDownChoicePanel<String> version = new AjaxDropDownChoicePanel<>("version", "version", new Model<>(bundleTO == null ? null : bundleTO.getVersion())); version.setStyleSheet("long_dynamicsize"); version.setChoices(bundleTO == null ? new ArrayList<String>() : new ArrayList<>(mapConnBundleTOs.get(connInstanceTO.getLocation()) .get(connInstanceTO.getBundleName()).keySet())); version.setRequired(true); version.addRequiredLabel(); version.setEnabled(connInstanceTO.getBundleName() != null); version.setOutputMarkupId(true); version.addRequiredLabel(); version.getField().setOutputMarkupId(true); connectorForm.add(version); final SpinnerFieldPanel<Integer> connRequestTimeout = new SpinnerFieldPanel<>("connRequestTimeout", "connRequestTimeout", Integer.class, new PropertyModel<Integer>(connInstanceTO, "connRequestTimeout"), 0, null); connRequestTimeout.getField().add(new RangeValidator<>(0, Integer.MAX_VALUE)); connectorForm.add(connRequestTimeout); if (connInstanceTO.getPoolConf() == null) { connInstanceTO.setPoolConf(new ConnPoolConfTO()); } final SpinnerFieldPanel<Integer> poolMaxObjects = new SpinnerFieldPanel<>("poolMaxObjects", "poolMaxObjects", Integer.class, new PropertyModel<Integer>(connInstanceTO.getPoolConf(), "maxObjects"), 0, null); poolMaxObjects.getField().add(new RangeValidator<>(0, Integer.MAX_VALUE)); connectorForm.add(poolMaxObjects); final SpinnerFieldPanel<Integer> poolMinIdle = new SpinnerFieldPanel<>("poolMinIdle", "poolMinIdle", Integer.class, new PropertyModel<Integer>(connInstanceTO.getPoolConf(), "minIdle"), 0, null); poolMinIdle.getField().add(new RangeValidator<>(0, Integer.MAX_VALUE)); connectorForm.add(poolMinIdle); final SpinnerFieldPanel<Integer> poolMaxIdle = new SpinnerFieldPanel<>("poolMaxIdle", "poolMaxIdle", Integer.class, new PropertyModel<Integer>(connInstanceTO.getPoolConf(), "maxIdle"), 0, null); poolMaxIdle.getField().add(new RangeValidator<>(0, Integer.MAX_VALUE)); connectorForm.add(poolMaxIdle); final SpinnerFieldPanel<Long> poolMaxWait = new SpinnerFieldPanel<>("poolMaxWait", "poolMaxWait", Long.class, new PropertyModel<Long>(connInstanceTO.getPoolConf(), "maxWait"), 0L, null); poolMaxWait.getField().add(new RangeValidator<>(0L, Long.MAX_VALUE)); connectorForm.add(poolMaxWait); final SpinnerFieldPanel<Long> poolMinEvictableIdleTime = new SpinnerFieldPanel<>("poolMinEvictableIdleTime", "poolMinEvictableIdleTime", Long.class, new PropertyModel<Long>(connInstanceTO.getPoolConf(), "minEvictableIdleTimeMillis"), 0L, null); poolMinEvictableIdleTime.getField().add(new RangeValidator<>(0L, Long.MAX_VALUE)); connectorForm.add(poolMinEvictableIdleTime); // form - first tab - onchange() location.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { private static final long serialVersionUID = -1107858522700306810L; @Override protected void onUpdate(final AjaxRequestTarget target) { ((DropDownChoice<String>) location.getField()).setNullValid(false); connInstanceTO.setLocation(location.getModelObject()); target.add(location); connectorName.setChoices(new ArrayList<>(mapConnBundleTOs.get(location.getModelObject()).keySet())); connectorName.setEnabled(true); connectorName.getField().setModelValue(null); target.add(connectorName); version.setChoices(new ArrayList<String>()); version.getField().setModelValue(null); version.setEnabled(false); target.add(version); properties.clear(); target.add(propertiesContainer); } }); connectorName.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { private static final long serialVersionUID = -1107858522700306810L; @Override protected void onUpdate(final AjaxRequestTarget target) { ((DropDownChoice<String>) connectorName.getField()).setNullValid(false); connInstanceTO.setBundleName(connectorName.getModelObject()); target.add(connectorName); List<String> versions = new ArrayList<>(mapConnBundleTOs.get(location.getModelObject()) .get(connectorName.getModelObject()).keySet()); version.setChoices(versions); version.setEnabled(true); if (versions.size() == 1) { selectVersion(target, connInstanceTO, version, versions.get(0)); version.getField().setModelObject(versions.get(0)); } else { version.getField().setModelValue(null); properties.clear(); target.add(propertiesContainer); } target.add(version); } }); version.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { private static final long serialVersionUID = -1107858522700306810L; @Override protected void onUpdate(final AjaxRequestTarget target) { selectVersion(target, connInstanceTO, version, version.getModelObject()); } }); // form - second tab (properties) final ListView<ConnConfProperty> connPropView = new ConnConfPropertyListView("connectorProperties", new PropertyModel<List<ConnConfProperty>>(this, "properties"), true, connInstanceTO.getConfiguration()); connPropView.setOutputMarkupId(true); connectorPropForm.add(connPropView); final AjaxButton check = new IndicatingAjaxButton("check", new ResourceModel("check")) { private static final long serialVersionUID = -7978723352517770644L; @Override public void onSubmit(final AjaxRequestTarget target, final Form<?> form) { final ConnInstanceTO conn = (ConnInstanceTO) form.getModelObject(); // ensure that connector bundle information is in sync conn.setBundleName(bundleTO.getBundleName()); conn.setVersion(bundleTO.getVersion()); conn.setConnectorName(bundleTO.getConnectorName()); if (connectorRestClient.check(conn)) { info(getString("success_connection")); } else { error(getString("error_connection")); } feedbackPanel.refresh(target); } }; connectorPropForm.add(check); // form - third tab (capabilities) final IModel<List<ConnectorCapability>> capabilities = new LoadableDetachableModel<List<ConnectorCapability>>() { private static final long serialVersionUID = 5275935387613157437L; @Override protected List<ConnectorCapability> load() { return Arrays.asList(ConnectorCapability.values()); } }; CheckBoxMultipleChoice<ConnectorCapability> capabilitiesPalette = new CheckBoxMultipleChoice<>( "capabilitiesPalette", new PropertyModel<List<ConnectorCapability>>(this, "selectedCapabilities"), capabilities); capabilitiesPalette.add(new AjaxFormChoiceComponentUpdatingBehavior() { private static final long serialVersionUID = -1107858522700306810L; @Override protected void onUpdate(final AjaxRequestTarget target) { } }); connectorForm.add(capabilitiesPalette); // form - submit / cancel buttons final AjaxButton submit = new IndicatingAjaxButton(APPLY, new Model<>(getString(SUBMIT))) { private static final long serialVersionUID = -958724007591692537L; @Override protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { final ConnInstanceTO conn = (ConnInstanceTO) form.getModelObject(); conn.setConnectorName(bundleTO.getConnectorName()); conn.setBundleName(bundleTO.getBundleName()); conn.setVersion(bundleTO.getVersion()); conn.getConfiguration().clear(); conn.getConfiguration().addAll(connPropView.getModelObject()); // Set the model object's capabilities to capabilitiesPalette's converted Set conn.getCapabilities().clear(); conn.getCapabilities() .addAll(selectedCapabilities.isEmpty() ? EnumSet.noneOf(ConnectorCapability.class) : EnumSet.copyOf(selectedCapabilities)); // Reset pool configuration if all fields are null if (conn.getPoolConf() != null && conn.getPoolConf().getMaxIdle() == null && conn.getPoolConf().getMaxObjects() == null && conn.getPoolConf().getMaxWait() == null && conn.getPoolConf().getMinEvictableIdleTimeMillis() == null && conn.getPoolConf().getMinIdle() == null) { conn.setPoolConf(null); } try { if (connInstanceTO.getKey() == 0) { connectorRestClient.create(conn); } else { connectorRestClient.update(conn); } ((BasePage) pageRef.getPage()).setModalResult(true); window.close(target); } catch (SyncopeClientException e) { error(getString(Constants.ERROR) + ": " + e.getMessage()); feedbackPanel.refresh(target); ((BasePage) pageRef.getPage()).setModalResult(false); LOG.error("While creating or updating connector {}", conn, e); } } @Override protected void onError(final AjaxRequestTarget target, final Form<?> form) { feedbackPanel.refresh(target); } }; String entitlements = connInstanceTO.getKey() == 0 ? Entitlement.CONNECTOR_CREATE : Entitlement.CONNECTOR_UPDATE; MetaDataRoleAuthorizationStrategy.authorize(submit, ENABLE, entitlements); connectorForm.add(submit); final IndicatingAjaxButton cancel = new IndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL)) { private static final long serialVersionUID = -958724007591692537L; @Override protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { window.close(target); } }; cancel.setDefaultFormProcessing(false); connectorForm.add(cancel); } private ConnBundleTO getSelectedBundleTO(final ConnInstanceTO connInstanceTO) { ConnBundleTO result = null; if (connInstanceTO != null && StringUtils.isNotBlank(connInstanceTO.getLocation()) && StringUtils.isNotBlank(connInstanceTO.getBundleName()) && StringUtils.isNotBlank(connInstanceTO.getVersion()) && mapConnBundleTOs.containsKey(connInstanceTO.getLocation())) { Map<String, Map<String, ConnBundleTO>> byLocation = mapConnBundleTOs.get(connInstanceTO.getLocation()); if (byLocation.containsKey(connInstanceTO.getBundleName())) { Map<String, ConnBundleTO> byName = byLocation.get(connInstanceTO.getBundleName()); if (byName.containsKey(connInstanceTO.getVersion())) { result = byName.get(connInstanceTO.getVersion()); } } } return result; } private List<ConnConfProperty> fillProperties(final ConnBundleTO bundleTO, final ConnInstanceTO connInstanceTO) { final List<ConnConfProperty> props = new ArrayList<>(); if (bundleTO != null) { for (ConnConfPropSchema key : bundleTO.getProperties()) { final ConnConfProperty property = new ConnConfProperty(); property.setSchema(key); if (connInstanceTO.getKey() != 0 && connInstanceTO.getConfigurationMap().containsKey(key.getName()) && connInstanceTO.getConfigurationMap().get(key.getName()).getValues() != null) { property.getValues() .addAll(connInstanceTO.getConfigurationMap().get(key.getName()).getValues()); property.setOverridable( connInstanceTO.getConfigurationMap().get(key.getName()).isOverridable()); } if (property.getValues().isEmpty() && !key.getDefaultValues().isEmpty()) { property.getValues().addAll(key.getDefaultValues()); } props.add(property); } } // re-order properties (implements Comparable) Collections.sort(props); return props; } private void selectVersion(final AjaxRequestTarget target, final ConnInstanceTO connInstanceTO, final AjaxDropDownChoicePanel<String> version, final String versionValue) { connInstanceTO.setVersion(versionValue); target.add(version); bundleTO = getSelectedBundleTO(connInstanceTO); properties = fillProperties(bundleTO, connInstanceTO); target.add(propertiesContainer); } public List<ConnConfProperty> getProperties() { return properties; } }