org.syncope.console.pages.ConnectorModalPage.java Source code

Java tutorial

Introduction

Here is the source code for org.syncope.console.pages.ConnectorModalPage.java

Source

/*
 * 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.syncope.console.pages;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import org.apache.commons.lang.StringUtils;
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.ChoiceRenderer;
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.springframework.util.ClassUtils;
import org.syncope.client.to.ConnBundleTO;
import org.syncope.client.to.ConnInstanceTO;
import org.syncope.client.validation.SyncopeClientCompositeErrorException;
import org.syncope.console.rest.ConnectorRestClient;
import org.syncope.console.wicket.markup.html.form.AjaxCheckBoxPanel;
import org.syncope.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
import org.syncope.console.wicket.markup.html.form.AjaxNumberFieldPanel;
import org.syncope.console.wicket.markup.html.form.AjaxPasswordFieldPanel;
import org.syncope.console.wicket.markup.html.form.AjaxTextFieldPanel;
import org.syncope.console.wicket.markup.html.form.FieldPanel;
import org.syncope.console.wicket.markup.html.form.MultiValueSelectorPanel;
import org.syncope.types.ConnConfPropSchema;
import org.syncope.types.ConnConfProperty;
import org.syncope.types.ConnectorCapability;

/**
 * Modal window with Connector form.
 */
public class ConnectorModalPage extends BaseModalPage {

    private static final long serialVersionUID = -2025535531121434050L;

    // GuardedString is not in classpath
    private static final String GUARDED_STRING = "org.identityconnectors.common.security.GuardedString";

    // GuardedByteArray is not in classpath
    private static final String GUARDED_BYTE_ARRAY = "org.identityconnectors.common.security.GuardedByteArray";

    private static final List<Class> NUMBER = Arrays.asList(new Class[] { Integer.class, Double.class, Long.class,
            Float.class, Number.class, Integer.TYPE, Long.TYPE, Double.TYPE, Float.TYPE });

    @SpringBean
    private ConnectorRestClient restClient;

    private CheckBoxMultipleChoice capabilitiesPalette;

    private WebMarkupContainer propertiesContainer;

    private List<ConnectorCapability> selectedCapabilities;

    private ConnBundleTO bundleTO;

    private List<ConnConfProperty> properties;

    public ConnectorModalPage(final PageReference callerPageRef, final ModalWindow window,
            final ConnInstanceTO connectorTO) {

        super();

        selectedCapabilities = new ArrayList(connectorTO.getId() == 0 ? EnumSet.noneOf(ConnectorCapability.class)
                : connectorTO.getCapabilities());

        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());
            }
        };

        final IModel<List<ConnBundleTO>> bundles = new LoadableDetachableModel<List<ConnBundleTO>>() {

            private static final long serialVersionUID = 5275935387613157437L;

            @Override
            protected List<ConnBundleTO> load() {
                return restClient.getAllBundles();
            }
        };

        bundleTO = getSelectedBundleTO(bundles.getObject(), connectorTO);
        properties = getProperties(bundleTO, connectorTO);

        final AjaxTextFieldPanel connectorName = new AjaxTextFieldPanel("connectorName", "connector name",
                new PropertyModel<String>(connectorTO, "connectorName"), false);

        connectorName.setOutputMarkupId(true);
        connectorName.setEnabled(false);

        final AjaxTextFieldPanel displayName = new AjaxTextFieldPanel("displayName", "display name",
                new PropertyModel<String>(connectorTO, "displayName"), false);

        displayName.setOutputMarkupId(true);
        displayName.addRequiredLabel();

        final AjaxTextFieldPanel version = new AjaxTextFieldPanel("version", "version",
                new PropertyModel<String>(connectorTO, "version"), false);

        displayName.setOutputMarkupId(true);
        version.setEnabled(false);

        final AjaxDropDownChoicePanel<ConnBundleTO> bundle = new AjaxDropDownChoicePanel<ConnBundleTO>("bundle",
                "bundle", new Model<ConnBundleTO>(bundleTO), false);

        bundle.setStyleShet("long_dynamicsize");

        bundle.setChoices(bundles.getObject());

        bundle.setChoiceRenderer(new ChoiceRenderer<ConnBundleTO>() {

            private static final long serialVersionUID = -1945543182376191187L;

            @Override
            public Object getDisplayValue(final ConnBundleTO object) {
                return object.getBundleName() + " " + object.getVersion();
            }

            @Override
            public String getIdValue(final ConnBundleTO object, final int index) {
                // idValue must include version as well in order to cope
                // with multiple version of the same bundle.
                return object.getBundleName() + "#" + object.getVersion();
            }
        });

        ((DropDownChoice) bundle.getField()).setNullValid(true);
        bundle.setRequired(true);

        bundle.getField().add(new AjaxFormComponentUpdatingBehavior("onchange") {

            private static final long serialVersionUID = -1107858522700306810L;

            @Override
            protected void onUpdate(final AjaxRequestTarget target) {
                //reset all informations stored in connectorTO
                connectorTO.setConfiguration(new HashSet<ConnConfProperty>());

                ((DropDownChoice) bundle.getField()).setNullValid(false);
                target.add(bundle.getField());

                target.add(connectorName);
                target.add(version);

                target.add(propertiesContainer);
            }
        });

        bundle.getField().setModel(new IModel<ConnBundleTO>() {

            private static final long serialVersionUID = -3736598995576061229L;

            @Override
            public ConnBundleTO getObject() {
                return bundleTO;
            }

            @Override
            public void setObject(final ConnBundleTO object) {
                if (object != null && connectorTO != null) {
                    connectorTO.setBundleName(object.getBundleName());
                    connectorTO.setVersion(object.getVersion());
                    connectorTO.setConnectorName(object.getConnectorName());
                    properties = getProperties(object, connectorTO);
                    bundleTO = object;
                }
            }

            @Override
            public void detach() {
            }
        });

        bundle.addRequiredLabel();
        bundle.setEnabled(connectorTO.getId() == 0);

        final ListView<ConnConfProperty> view = new ListView<ConnConfProperty>("connectorProperties",
                new PropertyModel(this, "properties")) {

            private static final long serialVersionUID = 9101744072914090143L;

            @Override
            protected void populateItem(final ListItem<ConnConfProperty> item) {
                final ConnConfProperty property = item.getModelObject();

                final Label label = new Label("connPropAttrSchema",
                        property.getSchema().getDisplayName() == null
                                || property.getSchema().getDisplayName().isEmpty() ? property.getSchema().getName()
                                        : property.getSchema().getDisplayName());

                item.add(label);

                final FieldPanel field;

                boolean required = false;

                boolean isArray = false;

                if (GUARDED_STRING.equalsIgnoreCase(property.getSchema().getType())
                        || GUARDED_BYTE_ARRAY.equalsIgnoreCase(property.getSchema().getType())) {

                    field = new AjaxPasswordFieldPanel("panel", label.getDefaultModelObjectAsString(), new Model(),
                            true);

                    ((PasswordTextField) field.getField()).setResetPassword(false);

                    required = property.getSchema().isRequired();

                } else {
                    Class propertySchemaClass;

                    try {
                        propertySchemaClass = ClassUtils.forName(property.getSchema().getType(),
                                ClassUtils.getDefaultClassLoader());
                    } catch (Exception e) {
                        LOG.error("Error parsing attribute type", e);
                        propertySchemaClass = String.class;
                    }

                    if (NUMBER.contains(propertySchemaClass)) {
                        field = new AjaxNumberFieldPanel("panel", label.getDefaultModelObjectAsString(),
                                new Model(), ClassUtils.resolvePrimitiveIfNecessary(propertySchemaClass), true);

                        required = property.getSchema().isRequired();
                    } else if (Boolean.class.equals(propertySchemaClass)
                            || boolean.class.equals(propertySchemaClass)) {
                        field = new AjaxCheckBoxPanel("panel", label.getDefaultModelObjectAsString(), new Model(),
                                true);
                    } else {

                        field = new AjaxTextFieldPanel("panel", label.getDefaultModelObjectAsString(), new Model(),
                                true);

                        required = property.getSchema().isRequired();
                    }

                    if (String[].class.equals(propertySchemaClass)) {
                        isArray = true;
                    }
                }

                field.setTitle(property.getSchema().getHelpMessage());

                if (isArray) {
                    field.removeRequiredLabel();

                    if (property.getValues().isEmpty()) {
                        property.getValues().add(null);
                    }

                    item.add(new MultiValueSelectorPanel<String>("panel",
                            new PropertyModel<List<String>>(property, "values"), String.class, field));
                } else {
                    if (required) {
                        field.addRequiredLabel();
                    }

                    field.setNewModel(property.getValues());
                    item.add(field);
                }

                final AjaxCheckBoxPanel overridable = new AjaxCheckBoxPanel("connPropAttrOverridable",
                        "connPropAttrOverridable", new PropertyModel(property, "overridable"), true);

                item.add(overridable);
                connectorTO.getConfiguration().add(property);
            }
        };

        final Form connectorForm = new Form("form");
        connectorForm.setModel(new CompoundPropertyModel(connectorTO));

        final Form connectorPropForm = new Form("connectorPropForm");
        connectorPropForm.setModel(new CompoundPropertyModel(connectorTO));
        connectorPropForm.setOutputMarkupId(true);

        propertiesContainer = new WebMarkupContainer("container");
        propertiesContainer.setOutputMarkupId(true);
        propertiesContainer.add(connectorPropForm);

        connectorForm.add(propertiesContainer);
        connectorPropForm.add(view);

        final AjaxLink check = new IndicatingAjaxLink("check", new ResourceModel("check")) {

            private static final long serialVersionUID = -7978723352517770644L;

            @Override
            public void onClick(final AjaxRequestTarget target) {

                connectorTO.setBundleName(bundleTO.getBundleName());
                connectorTO.setVersion(bundleTO.getVersion());

                if (restClient.check(connectorTO).booleanValue()) {
                    info(getString("success_connection"));
                } else {
                    error(getString("error_connection"));
                }

                target.add(feedbackPanel);
            }
        };

        connectorPropForm.add(check);

        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.getDefaultModelObject();

                conn.setBundleName(bundleTO.getBundleName());

                // Set the model object's capabilites to
                // capabilitiesPalette's converted Set
                if (!selectedCapabilities.isEmpty()) {
                    // exception if selectedCapabilities is empy
                    conn.setCapabilities(EnumSet.copyOf(selectedCapabilities));
                } else {
                    conn.setCapabilities(EnumSet.noneOf(ConnectorCapability.class));
                }
                try {
                    if (connectorTO.getId() == 0) {
                        restClient.create(conn);
                    } else {
                        restClient.update(conn);
                    }

                    ((Resources) callerPageRef.getPage()).setModalResult(true);
                    window.close(target);
                } catch (SyncopeClientCompositeErrorException e) {
                    error(getString("error") + ":" + e.getMessage());
                    target.add(feedbackPanel);
                    ((Resources) callerPageRef.getPage()).setModalResult(false);
                    LOG.error("While creating or updating connector {}", conn);
                }
            }

            @Override
            protected void onError(final AjaxRequestTarget target, final Form form) {

                target.add(feedbackPanel);
            }
        };

        String roles = connectorTO.getId() == 0 ? xmlRolesReader.getAllAllowedRoles("Connectors", "create")
                : xmlRolesReader.getAllAllowedRoles("Connectors", "update");

        MetaDataRoleAuthorizationStrategy.authorize(submit, ENABLE, roles);

        connectorForm.add(connectorName);
        connectorForm.add(displayName);
        connectorForm.add(bundle);
        connectorForm.add(version);

        capabilitiesPalette = new CheckBoxMultipleChoice("capabilitiesPalette",
                new PropertyModel(this, "selectedCapabilities"), capabilities);
        connectorForm.add(capabilitiesPalette);

        connectorForm.add(submit);

        add(connectorForm);
    }

    private ConnBundleTO getSelectedBundleTO(final List<ConnBundleTO> bundles, final ConnInstanceTO connTO) {
        // -------------------------------------
        // Manage bundle and connector beans
        // -------------------------------------

        if (connTO != null && StringUtils.isNotBlank(connTO.getBundleName())
                && StringUtils.isNotBlank(connTO.getVersion())) {

            for (ConnBundleTO to : bundles) {
                if (to.getVersion().equals(connTO.getVersion())
                        && to.getBundleName().equals(connTO.getBundleName())) {

                    connTO.setConnectorName(to.getConnectorName());
                    connTO.setVersion(to.getVersion());

                    return to;
                }
            }
        }

        return null;
    }

    private List<ConnConfProperty> getProperties(final ConnBundleTO bundleTO, final ConnInstanceTO connTO) {

        // -------------------------------------
        // Manage bundle properties
        // -------------------------------------
        final List<ConnConfProperty> props = new ArrayList<ConnConfProperty>();

        if (connTO.getId() == 0 && bundleTO != null) {
            for (ConnConfPropSchema key : bundleTO.getProperties()) {
                final ConnConfProperty propertyTO = new ConnConfProperty();
                propertyTO.setSchema(key);
                props.add(propertyTO);
            }
        } else {
            props.addAll(connTO.getConfiguration());
        }
        // -------------------------------------

        return props;
    }
}