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.console.pages; 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.common.SyncopeClientException; import org.apache.syncope.common.to.ConnBundleTO; import org.apache.syncope.common.to.ConnInstanceTO; import org.apache.syncope.common.to.ConnPoolConfTO; import org.apache.syncope.common.types.ConnConfPropSchema; import org.apache.syncope.common.types.ConnConfProperty; import org.apache.syncope.common.types.ConnectorCapability; import org.apache.syncope.console.commons.Constants; import org.apache.syncope.console.markup.html.list.AltListView; import org.apache.syncope.console.rest.ConnectorRestClient; import org.apache.syncope.console.wicket.markup.html.form.AjaxCheckBoxPanel; import org.apache.syncope.console.wicket.markup.html.form.AjaxDropDownChoicePanel; import org.apache.syncope.console.wicket.markup.html.form.AjaxPasswordFieldPanel; import org.apache.syncope.console.wicket.markup.html.form.AjaxTextFieldPanel; import org.apache.syncope.console.wicket.markup.html.form.FieldPanel; import org.apache.syncope.console.wicket.markup.html.form.MultiFieldPanel; import org.apache.syncope.console.wicket.markup.html.form.SpinnerFieldPanel; import org.apache.wicket.PageReference; 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.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.IndicatingAjaxLink; 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.form.PasswordTextField; 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.LoadableDetachableModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.model.ResourceModel; import org.apache.wicket.spring.injection.annot.SpringBean; import org.apache.wicket.validation.validator.RangeValidator; import org.springframework.util.ClassUtils; /** * Modal window with Connector form. */ public class ConnectorModalPage extends BaseModalPage { private static final long serialVersionUID = -2025535531121434050L; @SpringBean private ConnectorRestClient restClient; 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 ConnectorModalPage(final PageReference pageRef, final ModalWindow window, final ConnInstanceTO connInstanceTO) { super(); // general data setup selectedCapabilities = new ArrayList<ConnectorCapability>( connInstanceTO.getId() == 0 ? EnumSet.noneOf(ConnectorCapability.class) : connInstanceTO.getCapabilities()); mapConnBundleTOs = new HashMap<String, Map<String, Map<String, ConnBundleTO>>>(); for (ConnBundleTO connBundleTO : restClient.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<ConnInstanceTO>(FORM); connectorForm.setModel(new CompoundPropertyModel<ConnInstanceTO>(connInstanceTO)); connectorForm.setOutputMarkupId(true); add(connectorForm); propertiesContainer = new WebMarkupContainer("container"); propertiesContainer.setOutputMarkupId(true); connectorForm.add(propertiesContainer); final Form<ConnInstanceTO> connectorPropForm = new Form<ConnInstanceTO>("connectorPropForm"); connectorPropForm.setModel(new CompoundPropertyModel<ConnInstanceTO>(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<String>("location", "location", new Model<String>(bundleTO == null ? null : bundleTO.getLocation())); ((DropDownChoice<String>) location.getField()).setNullValid(true); location.setStyleSheet("long_dynamicsize"); location.setChoices(new ArrayList<String>(mapConnBundleTOs.keySet())); location.setRequired(true); location.addRequiredLabel(); location.setOutputMarkupId(true); location.setEnabled(connInstanceTO.getId() == 0); location.getField().setOutputMarkupId(true); connectorForm.add(location); final AjaxDropDownChoicePanel<String> connectorName = new AjaxDropDownChoicePanel<String>("connectorName", "connectorName", new Model<String>(bundleTO == null ? null : bundleTO.getBundleName())); ((DropDownChoice<String>) connectorName.getField()).setNullValid(true); connectorName.setStyleSheet("long_dynamicsize"); connectorName.setChoices(bundleTO == null ? new ArrayList<String>() : new ArrayList<String>(mapConnBundleTOs.get(connInstanceTO.getLocation()).keySet())); connectorName.setRequired(true); connectorName.addRequiredLabel(); connectorName.setEnabled(connInstanceTO.getLocation() != null); connectorName.setOutputMarkupId(true); connectorName.setEnabled(connInstanceTO.getId() == 0); connectorName.getField().setOutputMarkupId(true); connectorForm.add(connectorName); final AjaxDropDownChoicePanel<String> version = new AjaxDropDownChoicePanel<String>("version", "version", new Model<String>(bundleTO == null ? null : bundleTO.getVersion())); version.setStyleSheet("long_dynamicsize"); version.setChoices(bundleTO == null ? new ArrayList<String>() : new ArrayList<String>(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<Integer>("connRequestTimeout", "connRequestTimeout", Integer.class, new PropertyModel<Integer>(connInstanceTO, "connRequestTimeout"), 0, null); connRequestTimeout.getField().add(new RangeValidator<Integer>(0, Integer.MAX_VALUE)); connectorForm.add(connRequestTimeout); if (connInstanceTO.getPoolConf() == null) { connInstanceTO.setPoolConf(new ConnPoolConfTO()); } final SpinnerFieldPanel<Integer> poolMaxObjects = new SpinnerFieldPanel<Integer>("poolMaxObjects", "poolMaxObjects", Integer.class, new PropertyModel<Integer>(connInstanceTO.getPoolConf(), "maxObjects"), 0, null); poolMaxObjects.getField().add(new RangeValidator<Integer>(0, Integer.MAX_VALUE)); connectorForm.add(poolMaxObjects); final SpinnerFieldPanel<Integer> poolMinIdle = new SpinnerFieldPanel<Integer>("poolMinIdle", "poolMinIdle", Integer.class, new PropertyModel<Integer>(connInstanceTO.getPoolConf(), "minIdle"), 0, null); poolMinIdle.getField().add(new RangeValidator<Integer>(0, Integer.MAX_VALUE)); connectorForm.add(poolMinIdle); final SpinnerFieldPanel<Integer> poolMaxIdle = new SpinnerFieldPanel<Integer>("poolMaxIdle", "poolMaxIdle", Integer.class, new PropertyModel<Integer>(connInstanceTO.getPoolConf(), "maxIdle"), 0, null); poolMaxIdle.getField().add(new RangeValidator<Integer>(0, Integer.MAX_VALUE)); connectorForm.add(poolMaxIdle); final SpinnerFieldPanel<Long> poolMaxWait = new SpinnerFieldPanel<Long>("poolMaxWait", "poolMaxWait", Long.class, new PropertyModel<Long>(connInstanceTO.getPoolConf(), "maxWait"), 0L, null); poolMaxWait.getField().add(new RangeValidator<Long>(0L, Long.MAX_VALUE)); connectorForm.add(poolMaxWait); final SpinnerFieldPanel<Long> poolMinEvictableIdleTime = new SpinnerFieldPanel<Long>( "poolMinEvictableIdleTime", "poolMinEvictableIdleTime", Long.class, new PropertyModel<Long>(connInstanceTO.getPoolConf(), "minEvictableIdleTimeMillis"), 0L, null); poolMinEvictableIdleTime.getField().add(new RangeValidator<Long>(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<String>(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<String>(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 AltListView<ConnConfProperty>("connectorProperties", new PropertyModel<List<ConnConfProperty>>(this, "properties")) { private static final long serialVersionUID = 9101744072914090143L; @Override @SuppressWarnings({ "unchecked", "rawtypes" }) protected void populateItem(final ListItem<ConnConfProperty> item) { final ConnConfProperty property = item.getModelObject(); final Label label = new Label("connPropAttrSchema", StringUtils.isBlank(property.getSchema().getDisplayName()) ? property.getSchema().getName() : property.getSchema().getDisplayName()); item.add(label); final FieldPanel field; boolean required = false; boolean isArray = false; if (property.getSchema().isConfidential() || Constants.GUARDED_STRING.equalsIgnoreCase(property.getSchema().getType()) || Constants.GUARDED_BYTE_ARRAY.equalsIgnoreCase(property.getSchema().getType())) { field = new AjaxPasswordFieldPanel("panel", label.getDefaultModelObjectAsString(), new Model<String>()); ((PasswordTextField) field.getField()).setResetPassword(false); required = property.getSchema().isRequired(); } else { Class<?> propertySchemaClass; try { propertySchemaClass = ClassUtils.forName(property.getSchema().getType(), ClassUtils.getDefaultClassLoader()); if (ClassUtils.isPrimitiveOrWrapper(propertySchemaClass)) { propertySchemaClass = org.apache.commons.lang3.ClassUtils .primitiveToWrapper(propertySchemaClass); } } catch (Exception e) { LOG.error("Error parsing attribute type", e); propertySchemaClass = String.class; } if (ClassUtils.isAssignable(Number.class, propertySchemaClass)) { field = new SpinnerFieldPanel<Number>("panel", label.getDefaultModelObjectAsString(), (Class<Number>) propertySchemaClass, new Model<Number>(), null, null); required = property.getSchema().isRequired(); } else if (ClassUtils.isAssignable(Boolean.class, propertySchemaClass)) { field = new AjaxCheckBoxPanel("panel", label.getDefaultModelObjectAsString(), new Model<Boolean>()); } else { field = new AjaxTextFieldPanel("panel", label.getDefaultModelObjectAsString(), new Model<String>()); required = property.getSchema().isRequired(); } if (propertySchemaClass.isArray()) { isArray = true; } } field.setTitle(property.getSchema().getHelpMessage()); if (required) { field.addRequiredLabel(); } if (isArray) { if (property.getValues().isEmpty()) { property.getValues().add(null); } item.add(new MultiFieldPanel<String>("panel", new PropertyModel<List<String>>(property, "values"), field)); } else { field.setNewModel(property.getValues()); item.add(field); } final AjaxCheckBoxPanel overridable = new AjaxCheckBoxPanel("connPropAttrOverridable", "connPropAttrOverridable", new PropertyModel<Boolean>(property, "overridable")); item.add(overridable); connInstanceTO.getConfiguration().add(property); } }; connPropView.setOutputMarkupId(true); connectorPropForm.add(connPropView); final AjaxLink<String> check = new IndicatingAjaxLink<String>("check", new ResourceModel("check")) { private static final long serialVersionUID = -7978723352517770644L; @Override public void onClick(final AjaxRequestTarget target) { connInstanceTO.setBundleName(bundleTO.getBundleName()); connInstanceTO.setVersion(bundleTO.getVersion()); connInstanceTO.setConnectorName(bundleTO.getConnectorName()); if (restClient.check(connInstanceTO)) { 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<ConnectorCapability>( "capabilitiesPalette", new PropertyModel<List<ConnectorCapability>>(this, "selectedCapabilities"), capabilities); connectorForm.add(capabilitiesPalette); // form - submit / cancel buttons final AjaxButton submit = new IndicatingAjaxButton(APPLY, new Model<String>(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() .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.getId() == 0) { restClient.create(conn); } else { restClient.update(conn); } ((Resources) pageRef.getPage()).setModalResult(true); window.close(target); } catch (SyncopeClientException e) { error(getString(Constants.ERROR) + ": " + e.getMessage()); feedbackPanel.refresh(target); ((Resources) 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 roles = connInstanceTO.getId() == 0 ? xmlRolesReader.getAllAllowedRoles("Connectors", "create") : xmlRolesReader.getAllAllowedRoles("Connectors", "update"); MetaDataRoleAuthorizationStrategy.authorize(submit, ENABLE, roles); 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<ConnConfProperty>(); if (bundleTO != null) { for (ConnConfPropSchema key : bundleTO.getProperties()) { final ConnConfProperty property = new ConnConfProperty(); property.setSchema(key); if (connInstanceTO.getId() != 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; } }