/* * Copyright (c) 2010-2014 Evolveum * * Licensed 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 com.evolveum.midpoint.testing.model.client.sample; import com.evolveum.midpoint.model.client.ModelClientUtil; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.GetOperationOptionsType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectDeltaListType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectDeltaOperationListType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectListType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectSelectorType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.RetrieveOptionType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.SelectorQualifiedGetOptionType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.SelectorQualifiedGetOptionsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ModelExecuteOptionsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectDeltaOperationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAttributesType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemObjectsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import com.evolveum.midpoint.xml.ns._public.common.fault_3.FaultMessage; import com.evolveum.midpoint.xml.ns._public.model.model_3.ModelPortType; import com.evolveum.midpoint.xml.ns._public.model.model_3.ModelService; import com.evolveum.prism.xml.ns._public.query_3.OrderDirectionType; import com.evolveum.prism.xml.ns._public.query_3.PagingType; import com.evolveum.prism.xml.ns._public.query_3.QueryType; import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType; import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType; import com.evolveum.prism.xml.ns._public.types_3.ItemDeltaType; import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; import com.evolveum.prism.xml.ns._public.types_3.ModificationTypeType; import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.Validate; import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.transport.http.HTTPConduit; import org.apache.cxf.transports.http.configuration.HTTPClientPolicy; import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor; import org.apache.wss4j.dom.WSConstants; import org.apache.wss4j.dom.handler.WSHandlerConstants; import org.testng.AssertJUnit; import org.testng.annotations.BeforeClass; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.SAXException; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.namespace.QName; import javax.xml.ws.BindingProvider; import javax.xml.ws.Holder; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Common functionality for connector-related tests. * * @author mederly */ public class AbstractTestForExchangeConnector { // Configuration public static final String ADM_USERNAME = "administrator"; public static final String ADM_PASSWORD = "5ecr3t"; public static final String DEFAULT_ENDPOINT_URL = "http://localhost.:8080/midpoint/model/model-3"; // Object OIDs // Other public static final String NS_RI = "http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"; public static final String NS_ICFS = "http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"; public static final QName OC_ACCOUNT = new QName(NS_RI, "AccountObjectClass"); public static final QName OC_ACCEPTED_DOMAIN = new QName(NS_RI, "CustomAcceptedDomainObjectClass"); public static final QName OC_GLOBAL_ADDRESS_LIST = new QName(NS_RI, "CustomGlobalAddressListObjectClass"); public static final QName OC_ADDRESS_LIST = new QName(NS_RI, "CustomAddressListObjectClass"); public static final QName OC_OFFLINE_ADDRESS_BOOK = new QName(NS_RI, "CustomOfflineAddressBookObjectClass"); public static final QName OC_ADDRESS_BOOK_POLICY = new QName(NS_RI, "CustomAddressBookPolicyObjectClass"); public static final QName OC_DISTRIBUTION_GROUP = new QName(NS_RI, "CustomDistributionGroupObjectClass"); public static final QName OC_EMAIL_ADDRESS_POLICY = new QName(NS_RI, "CustomEmailAddressPolicyObjectClass"); // objects created (to be cleaned up at the end) protected List<String> acceptedDomains = new ArrayList<>(); protected List<String> globalAddressLists = new ArrayList<>(); protected List<String> addressLists = new ArrayList<>(); protected List<String> offlineAddressBooks = new ArrayList<>(); protected List<String> addressBookPolicies = new ArrayList<>(); protected List<String> distributionGroups = new ArrayList<>(); protected List<String> emailAddressPolicies = new ArrayList<>(); protected List<OrgType> orgs = new ArrayList<>(); protected ModelPortType modelPort; protected ObjectDeltaOperationType lastOdo; // a hack to see last result // private String dn(String givenName, String sn) { // return "CN=" + givenName + " " + sn + "," + getContainer(); // } // // private String mail(String givenName, String sn) { // return sn.toLowerCase() + "@" + getMailDomain(); // } // // private String getContainer() { // return System.getProperty("container"); // } // protected String getResourceOid() { return System.getProperty("resourceOid"); } // // public String getMailDomain() { // return System.getProperty("mailDomain"); // } @BeforeClass public void initialize() throws Exception { modelPort = createModelPort(new String[0]); } // =============== AcceptedDomain =============== protected String createAndCheckAcceptedDomain(String name, String domainName, String domainType) throws Exception { System.out.println("Creating accepted domain " + name); String oid = createAcceptedDomain(name, domainName, domainType); System.out.println("Done; OID = " + oid); acceptedDomains.add(oid); return checkAcceptedDomain(name, domainName, domainType).getOid(); } protected String createAcceptedDomain(String name, String domainName, String domainType) throws FaultMessage { Document doc = ModelClientUtil.getDocumnent(); ShadowType shadow = new ShadowType(); shadow.setName(ModelClientUtil.createPolyStringType(name, doc)); shadow.setResourceRef(createObjectReferenceType(ResourceType.class, getResourceOid())); shadow.setObjectClass(OC_ACCEPTED_DOMAIN); shadow.setKind(ShadowKindType.GENERIC); shadow.setIntent("custom-accepted-domain"); ShadowAttributesType attributes = new ShadowAttributesType(); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_ICFS, "name"), name, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "DomainName"), domainName, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "DomainType"), domainType, doc)); shadow.setAttributes(attributes); return createShadow(shadow); } protected ShadowType checkAcceptedDomain(String name, String domainName, String domainType) throws Exception { System.out.println("Retrieving AcceptedDomain " + name); ShadowType shadowType = getShadowByName(getResourceOid(), OC_ACCEPTED_DOMAIN, name); AssertJUnit.assertNotNull("AcceptedDomain " + name + " was not found", shadowType); System.out.println("Done; shadow OID = " + shadowType.getOid()); dumpAttributes(shadowType); Map<String,Object> attrs = getAttributesAsMap(shadowType); assertAttributeExists(attrs, "uid"); assertAttributeEquals(attrs, "name", name); assertAttributeEquals(attrs, "DomainName", domainName); assertAttributeEquals(attrs, "DomainType", domainType); return shadowType; } // =============== GAL =============== protected String createAndCheckGlobalAddressList(String name, String valueToExpect) throws Exception { System.out.println("Creating GAL " + name); String oid = createGlobalAddressList(name, valueToExpect); System.out.println("Done; OID = " + oid); globalAddressLists.add(oid); return checkGlobalAddressList(name, galFilter(valueToExpect)).getOid(); } protected String galFilter(String valueToExpect) { return "((Alias -ne $null) -and (CustomAttribute1 -eq '" + valueToExpect + "'))"; } protected String createGlobalAddressList(String name, String valueToExpect) throws FaultMessage { Document doc = ModelClientUtil.getDocumnent(); ShadowType shadow = new ShadowType(); shadow.setName(ModelClientUtil.createPolyStringType(name, doc)); shadow.setResourceRef(createObjectReferenceType(ResourceType.class, getResourceOid())); shadow.setObjectClass(OC_GLOBAL_ADDRESS_LIST); shadow.setKind(ShadowKindType.GENERIC); shadow.setIntent("global-address-list"); ShadowAttributesType attributes = new ShadowAttributesType(); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_ICFS, "name"), name, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "RecipientFilter"), galFilter(valueToExpect), doc)); shadow.setAttributes(attributes); return createShadow(shadow); } protected ShadowType checkGlobalAddressList(String name, String recipientFilter) throws Exception { System.out.println("Retrieving GAL " + name); ShadowType shadowType = getShadowByName(getResourceOid(), OC_GLOBAL_ADDRESS_LIST, name); AssertJUnit.assertNotNull("GAL " + name + " was not found", shadowType); System.out.println("Done; shadow OID = " + shadowType.getOid()); dumpAttributes(shadowType); Map<String,Object> attrs = getAttributesAsMap(shadowType); assertAttributeExists(attrs, "uid"); assertAttributeEquals(attrs, "name", name); if (recipientFilter != null) { assertAttributeEquals(attrs, "RecipientFilter", recipientFilter); } return shadowType; } // =============== Address Lists =============== enum AddressListType { USERS("address-list-all-users", "((((Alias -ne $null) -and (CustomAttribute1 -eq '$$$'))) -and (ObjectCategory -like 'person'))"), GROUPS("address-list-all-groups", "((((Alias -ne $null) -and (CustomAttribute1 -eq '$$$'))) -and (ObjectCategory -like 'group'))"), CONTACTS("address-list-all-contacts", "((((Alias -ne $null) -and (CustomAttribute1 -eq '$$$'))) -and (((ObjectCategory -like 'person') -and (ObjectClass -eq 'contact'))))"), ROOMS("address-list-all-rooms", "((((Alias -ne $null) -and (CustomAttribute1 -eq '$$$'))) -and (((RecipientDisplayType -eq 'ConferenceRoomMailbox') -or (RecipientDisplayType -eq 'SyncedConferenceRoomMailbox'))))"); private String intent; private final String filterTemplate; AddressListType(String intent, String filterTemplate) { this.intent = intent; this.filterTemplate = filterTemplate; } public String createFilter(String valueToExpect) { return filterTemplate.replace("$$$", valueToExpect); } public String getIntent() { return intent; } } protected String createAndCheckAddressList(String name, String valueToExpect, AddressListType type) throws Exception { System.out.println("Creating AddressList " + name); String oid = createAddressList(name, valueToExpect, type); System.out.println("Done; OID = " + oid); addressLists.add(oid); return checkAddressList(name, type.createFilter(valueToExpect)).getOid(); } protected String createAddressList(String name, String valueToExpect, AddressListType type) throws FaultMessage { Document doc = ModelClientUtil.getDocumnent(); ShadowType shadow = new ShadowType(); shadow.setName(ModelClientUtil.createPolyStringType(name, doc)); shadow.setResourceRef(createObjectReferenceType(ResourceType.class, getResourceOid())); shadow.setObjectClass(OC_ADDRESS_LIST); shadow.setKind(ShadowKindType.GENERIC); shadow.setIntent(type.getIntent()); ShadowAttributesType attributes = new ShadowAttributesType(); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_ICFS, "name"), name, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "RecipientFilter"), type.createFilter(valueToExpect), doc)); shadow.setAttributes(attributes); return createShadow(shadow); } protected ShadowType checkAddressList(String name, String recipientFilter) throws Exception { System.out.println("Retrieving AddressList " + name); ShadowType shadowType = getShadowByName(getResourceOid(), OC_ADDRESS_LIST, name); AssertJUnit.assertNotNull("AddressList " + name + " was not found", shadowType); System.out.println("Done; shadow OID = " + shadowType.getOid()); dumpAttributes(shadowType); Map<String,Object> attrs = getAttributesAsMap(shadowType); assertAttributeExists(attrs, "uid"); assertAttributeEquals(attrs, "name", name); assertAttributeEquals(attrs, "RecipientFilter", recipientFilter); return shadowType; } // =============== OfflineAddressBook =============== protected String createAndCheckOfflineAddressBook(String name, String addressList, String tenantName) throws Exception { System.out.println("Creating OAB " + name); String oid = createOfflineAddressBook(name, addressList, tenantName); System.out.println("Done; OID = " + oid); offlineAddressBooks.add(oid); return checkOfflineAddressBook(name, addressList).getOid(); } protected String createOfflineAddressBook(String name, String addressList, String tenantName) throws FaultMessage { Document doc = ModelClientUtil.getDocumnent(); ShadowType shadow = new ShadowType(); shadow.setName(ModelClientUtil.createPolyStringType(name, doc)); shadow.setResourceRef(createObjectReferenceType(ResourceType.class, getResourceOid())); shadow.setObjectClass(OC_OFFLINE_ADDRESS_BOOK); shadow.setKind(ShadowKindType.GENERIC); shadow.setIntent("offline-address-book"); ShadowAttributesType attributes = new ShadowAttributesType(); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_ICFS, "name"), name, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "AddressLists"), addressList, doc)); //attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "_TenantName"), tenantName, doc)); shadow.setAttributes(attributes); return createShadow(shadow); } protected ShadowType checkOfflineAddressBook(String name, String addressList) throws Exception { System.out.println("Retrieving OAB " + name); ShadowType shadowType = getShadowByName(getResourceOid(), OC_OFFLINE_ADDRESS_BOOK, name); AssertJUnit.assertNotNull("OAB " + name + " was not found", shadowType); System.out.println("Done; shadow OID = " + shadowType.getOid()); dumpAttributes(shadowType); Map<String,Object> attrs = getAttributesAsMap(shadowType); assertAttributeExists(attrs, "uid"); assertAttributeEquals(attrs, "name", name); assertAttributeEquals(attrs, "AddressLists", "\\" + addressList); return shadowType; } // TODO checking access rights to download OAB // =============== AddressBookPolicy =============== protected String createAndCheckAddressBookPolicy(String name, Collection<String> addressLists, String gal, String oab, String rooms) throws Exception { System.out.println("Creating ABP " + name); String oid = createAddressBookPolicy(name, addressLists, gal, oab, rooms); System.out.println("Done; OID = " + oid); addressBookPolicies.add(oid); return checkAddressBookPolicy(name, addressLists, gal, oab, rooms).getOid(); } protected String createAddressBookPolicy(String name, Collection<String> addressLists, String gal, String oab, String rooms) throws FaultMessage { Document doc = ModelClientUtil.getDocumnent(); ShadowType shadow = new ShadowType(); shadow.setName(ModelClientUtil.createPolyStringType(name, doc)); shadow.setResourceRef(createObjectReferenceType(ResourceType.class, getResourceOid())); shadow.setObjectClass(OC_ADDRESS_BOOK_POLICY); shadow.setKind(ShadowKindType.GENERIC); shadow.setIntent("address-book-policy"); ShadowAttributesType attributes = new ShadowAttributesType(); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_ICFS, "name"), name, doc)); for (String addressList : addressLists) { attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "AddressLists"), addressList, doc)); } attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "GlobalAddressList"), gal, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "OfflineAddressBook"), oab, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "RoomList"), rooms, doc)); shadow.setAttributes(attributes); return createShadow(shadow); } protected ShadowType checkAddressBookPolicy(String name, Collection<String> addressLists, String gal, String oab, String rooms) throws Exception { System.out.println("Retrieving ABP " + name); ShadowType shadowType = getShadowByName(getResourceOid(), OC_ADDRESS_BOOK_POLICY, name); AssertJUnit.assertNotNull("ABP " + name + " was not found", shadowType); System.out.println("Done; shadow OID = " + shadowType.getOid()); dumpAttributes(shadowType); Map<String,Object> attrs = getAttributesAsMap(shadowType); assertAttributeExists(attrs, "uid"); assertAttributeEquals(attrs, "name", name); assertAttributeEquals(attrs, "AddressLists", new HashSet<>(addressLists)); assertAttributeEquals(attrs, "GlobalAddressList", gal); assertAttributeEquals(attrs, "OfflineAddressBook", oab); assertAttributeEquals(attrs, "RoomList", rooms); return shadowType; } // =============== DistributionGroup =============== protected String distributionGroupName(String name) { return "Mail-" + name + "@MailSecurity"; } protected String distributionGroupPrimaryAddress(String name) { return "Mail-" + name + "@MailSecurity"; } protected Collection<String> distributionGroupMembers(String name) { //return Arrays.asList("Mail-" + name + "@AllUsers"); return new ArrayList<>(); } protected String distributionGroupDisplayName(String name) { return "Mail-" + name + "@MailSecurity"; } protected String createAndCheckDistributionGroup(String name, String primaryAddress, Collection<String> members, String ou, String displayName, String valueForFilter) throws Exception { System.out.println("Creating DG " + name); String oid = createDistributionGroup(name, primaryAddress, members, ou, displayName, valueForFilter); System.out.println("Done; OID = " + oid); distributionGroups.add(oid); return checkDistributionGroup(name, primaryAddress, members, ou, displayName, valueForFilter).getOid(); } protected String createDistributionGroup(String name, String primaryAddress, Collection<String> members, String ou, String displayName, String valueForFilter) throws FaultMessage { Document doc = ModelClientUtil.getDocumnent(); ShadowType shadow = new ShadowType(); shadow.setName(ModelClientUtil.createPolyStringType(name, doc)); shadow.setResourceRef(createObjectReferenceType(ResourceType.class, getResourceOid())); shadow.setObjectClass(OC_DISTRIBUTION_GROUP); shadow.setKind(ShadowKindType.GENERIC); shadow.setIntent("distribution-group"); ShadowAttributesType attributes = new ShadowAttributesType(); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_ICFS, "name"), name, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "Type"), "Security", doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "PrimarySmtpAddress"), primaryAddress, doc)); for (String member : members) { attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "Members"), member, doc)); } attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "OrganizationalUnit"), ou, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "DisplayName"), displayName, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "HiddenFromAddressListsEnabled"), "true", doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "CustomAttribute1"), valueForFilter, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "BypassSecurityGroupManagerCheck"), "true", doc)); shadow.setAttributes(attributes); return createShadow(shadow); } protected ShadowType checkDistributionGroup(String name, String primaryAddress, Collection<String> members, String ou, String displayName, String valueForFilter) throws Exception { System.out.println("Retrieving DistributionGroup " + name); ShadowType shadowType = getShadowByName(getResourceOid(), OC_DISTRIBUTION_GROUP, name); AssertJUnit.assertNotNull("DistributionGroup " + name + " was not found", shadowType); System.out.println("Done; shadow OID = " + shadowType.getOid()); dumpAttributes(shadowType); Map<String,Object> attrs = getAttributesAsMap(shadowType); assertAttributeExists(attrs, "uid"); assertAttributeEquals(attrs, "name", name); assertAttributeEquals(attrs, "RecipientType", "MailUniversalSecurityGroup"); assertAttributeEquals(attrs, "PrimarySmtpAddress", primaryAddress); //Members cannot be retrieved in this way //assertAttributeEquals(attrs, "Members", members); assertAttributeEquals(attrs, "OrganizationalUnit", ou); assertAttributeEquals(attrs, "DisplayName", displayName); assertAttributeEquals(attrs, "HiddenFromAddressListsEnabled", "true"); assertAttributeEquals(attrs, "CustomAttribute1", valueForFilter); return shadowType; } // =============== Users =============== protected void cleanup() throws Exception { deleteShadows(distributionGroups, true); deleteShadows(emailAddressPolicies, true); deleteShadows(addressBookPolicies, true); deleteShadows(offlineAddressBooks, true); deleteShadows(addressLists, true); deleteShadows(globalAddressLists, true); deleteShadows(acceptedDomains, true); deleteObjects(OrgType.class, orgs, true); } protected void deleteShadows(List<String> oids, boolean ignoreFailures) throws FaultMessage { deleteObjectsByOids(ShadowType.class, oids, ignoreFailures); } protected void deleteShadow(String oid, boolean ignoreFailures) throws FaultMessage { deleteObject(ShadowType.class, oid, ignoreFailures); } protected void deleteShadowRaw(String oid, boolean ignoreFailures) throws FaultMessage { deleteObject(ShadowType.class, oid, ignoreFailures, createRaw()); } protected ModelExecuteOptionsType createRaw() { ModelExecuteOptionsType options = new ModelExecuteOptionsType(); options.setRaw(true); return options; } protected void deleteObjectsByOids(Class objectClass, List<String> oids, boolean ignoreFailures) throws FaultMessage { for (String oid : oids) { deleteObject(objectClass, oid, ignoreFailures); } } protected void deleteObjects(Class objectClass, List<? extends ObjectType> objects, boolean ignoreFailures) throws FaultMessage { for (ObjectType objectType : objects) { deleteObject(objectClass, objectType.getOid(), ignoreFailures); } } protected void deleteObject(Class objectClass, String oid, boolean ignoreFailures) throws FaultMessage { deleteObject(objectClass, oid, ignoreFailures, new ModelExecuteOptionsType()); } protected void deleteObject(Class objectClass, String oid, boolean ignoreFailures, ModelExecuteOptionsType executeOptionsType) throws FaultMessage { System.out.println("Deleting " + objectClass.getSimpleName() + " " + oid); ObjectDeltaType deltaType = new ObjectDeltaType(); deltaType.setObjectType(ModelClientUtil.getTypeQName(objectClass)); deltaType.setChangeType(ChangeTypeType.DELETE); deltaType.setOid(oid); ObjectDeltaListType deltaListType = new ObjectDeltaListType(); deltaListType.getDelta().add(deltaType); if (!ignoreFailures) { modelPort.executeChanges(deltaListType, executeOptionsType); } else { try { modelPort.executeChanges(deltaListType, executeOptionsType); } catch (Exception e) { System.err.println("Cannot remove " + oid + ": " + e.getMessage()); } } } protected void modifyShadow(String oid, String path, ModificationTypeType modType, Object value) throws Exception { modifyObject(ShadowType.class, oid, path, modType, value); } protected void modifyObject(Class objectType, String oid, String path, ModificationTypeType modType, Object value) throws Exception { modifyObject(objectType, oid, path, modType, value, null, true); } protected ObjectDeltaOperationType modifyObject(Class objectType, String oid, String path, ModificationTypeType modType, Object value, ModelExecuteOptionsType optionsType, boolean assertSuccess) throws Exception { System.out.println("Modifying " + objectType.getSimpleName() + " " + oid + " (path: " + path + ")"); ObjectDeltaType deltaType = new ObjectDeltaType(); deltaType.setObjectType(ModelClientUtil.getTypeQName(objectType)); deltaType.setChangeType(ChangeTypeType.MODIFY); deltaType.setOid(oid); if (path != null) { ItemDeltaType itemDelta = new ItemDeltaType(); itemDelta.setModificationType(modType); itemDelta.setPath(createNonDefaultItemPathType(path)); if (!(value instanceof Collection)) { itemDelta.getValue().add(value); } else { itemDelta.getValue().addAll((Collection) value); } deltaType.getItemDelta().add(itemDelta); } ObjectDeltaListType deltaListType = new ObjectDeltaListType(); deltaListType.getDelta().add(deltaType); ObjectDeltaOperationListType odolist = modelPort.executeChanges(deltaListType, optionsType); return assertExecuteChangesSuccess(odolist, deltaType, assertSuccess); } // values: path -> value or collection of values protected ObjectDeltaOperationType modifyObject(Class objectType, String oid, ModificationTypeType modType, Map<String,Object> values, ModelExecuteOptionsType optionsType, boolean assertSuccess) throws Exception { System.out.println("Modifying " + objectType.getSimpleName() + " " + oid + " (values: " + values + ")"); ObjectDeltaType deltaType = new ObjectDeltaType(); deltaType.setObjectType(ModelClientUtil.getTypeQName(objectType)); deltaType.setChangeType(ChangeTypeType.MODIFY); deltaType.setOid(oid); for (Map.Entry<String,Object> entry : values.entrySet()) { ItemDeltaType itemDelta = new ItemDeltaType(); itemDelta.setModificationType(modType); itemDelta.setPath(createNonDefaultItemPathType(entry.getKey())); if (!(entry.getValue() instanceof Collection)) { itemDelta.getValue().add(entry.getValue()); } else { itemDelta.getValue().addAll((Collection) (entry.getValue())); } deltaType.getItemDelta().add(itemDelta); } ObjectDeltaListType deltaListType = new ObjectDeltaListType(); deltaListType.getDelta().add(deltaType); ObjectDeltaOperationListType odolist = modelPort.executeChanges(deltaListType, optionsType); return assertExecuteChangesSuccess(odolist, deltaType, assertSuccess); } protected ObjectDeltaOperationType assertExecuteChangesSuccess(ObjectDeltaOperationListType odolist, ObjectDeltaType deltaType, boolean assertSuccess) { ObjectDeltaOperationType found = null; for (ObjectDeltaOperationType odo : odolist.getDeltaOperation()) { if (deltaType == null || deltaType.getOid().equals(odo.getObjectDelta().getOid())) { AssertJUnit.assertNotNull("Operation result is null", odo.getExecutionResult()); found = odo; if (odo.getExecutionResult().getStatus() != OperationResultStatusType.SUCCESS) { System.out.println("!!! Operation result is " + odo.getExecutionResult().getStatus()); System.out.println("!!! Message: " + odo.getExecutionResult().getMessage()); System.out.println("!!! Details:\n" + odo.getExecutionResult()); if (assertSuccess) { AssertJUnit.assertEquals("Unexpected operation result status", OperationResultStatusType.SUCCESS, odo.getExecutionResult().getStatus()); } } } } AssertJUnit.assertNotNull("ObjectDelta was not found in ObjectDeltaOperationList", found); return found; } protected void assertAttributeExists(Map<String, Object> attrs, String name) { AssertJUnit.assertTrue("Attribute " + name + " is missing", attrs.containsKey(name)); } protected ShadowType checkAccount(String givenName, String sn, String dn, String container) throws Exception { System.out.println("Retrieving " + sn + " account..."); ShadowType shadowType = getShadowByName(getResourceOid(), OC_ACCOUNT, dn); AssertJUnit.assertNotNull(sn + " was not found", shadowType); System.out.println("Done; shadow OID = " + shadowType.getOid()); dumpAttributes(shadowType); Map<String,Object> attrs = getAttributesAsMap(shadowType); assertAttributeExists(attrs, "uid"); assertAttributeEquals(attrs, "sAMAccountName", sn.toLowerCase()); assertAttributeEquals(attrs, "distinguishedName", dn); assertAttributeEquals(attrs, "givenName", givenName); assertAttributeEquals(attrs, "sn", sn); assertAttributeEquals(attrs, "passwordExpired", true); assertAttributeEquals(attrs, "PasswordNeverExpires", "false"); assertAttributeEquals(attrs, "ad_container", container); assertAttributeEquals(attrs, "objectClass", new HashSet(Arrays.asList("top", "person", "organizationalPerson", "user"))); return shadowType; } protected void assertAttributeEquals(Map<String, Object> attrs, String name, Object expectedValue) { Object realValue = attrs.get(name); AssertJUnit.assertEquals("Unexpected value of attribute " + name, expectedValue, realValue); } protected void assertAttributeContains(Map<String, Object> attrs, String name, Object expectedValue) { if (expectedValue instanceof Collection) { for (Object singleValue : (Collection) expectedValue) { assertAttributeContains(attrs, name, singleValue); } } else { Object realValue = attrs.get(name); Collection realCollection; if (realValue == null) { realCollection = new ArrayList(); } else if (!(realValue instanceof Collection)) { realCollection = Arrays.asList(realValue); } else { realCollection = (Collection) realValue; } if (!realCollection.contains(expectedValue)) { AssertJUnit.assertTrue("Attribute " + name + " was expected to contain " + expectedValue + " but it doesn't: " + realCollection, false); } } } protected void dumpAttributes(ShadowType shadowType) { ShadowAttributesType attributes = shadowType.getAttributes(); System.out.println("Attributes for " + shadowType.getObjectClass().getLocalPart() + " " + getOrig(shadowType.getName()) + " {" + attributes.getAny().size() + " entries):"); for (Object item : attributes.getAny()) { if (item instanceof Element) { Element e = (Element) item; System.out.println(" - " + e.getLocalName() + ": " + e.getTextContent()); } else if (item instanceof JAXBElement) { JAXBElement je = (JAXBElement) item; String typeInfo = je.getValue() instanceof String ? "" : (" (" + je.getValue().getClass().getSimpleName() + ")"); System.out.println(" - " + je.getName().getLocalPart() + ": " + je.getValue() + typeInfo); } else { System.out.println(" - " + item); } } } protected Map<String,Object> getAttributesAsMap(ShadowType shadowType) { Map<String,Object> rv = new HashMap<>(); ShadowAttributesType attributes = shadowType.getAttributes(); for (Object item : attributes.getAny()) { if (item instanceof Element) { Element e = (Element) item; put(rv, e.getLocalName(), e.getTextContent()); } else if (item instanceof JAXBElement) { JAXBElement je = (JAXBElement) item; put(rv, je.getName().getLocalPart(), je.getValue()); } else { // nothing to do here } } return rv; } protected void put(Map<String, Object> map, String name, Object value) { Object existing = map.get(name); if (existing == null) { map.put(name, value); } else if (!(existing instanceof Set)) { Set set = new HashSet(); set.add(existing); set.add(value); map.put(name, set); } else { ((Set) existing).add(value); } } // TODO move to ModelClientUtil public static String getOrig(PolyStringType polyStringType) { if (polyStringType == null) { return null; } StringBuilder sb = new StringBuilder(); for (Object o : polyStringType.getContent()) { if (o instanceof String) { sb.append(o); } else if (o instanceof Element) { Element e = (Element) o; if ("orig".equals(e.getLocalName())) { return e.getTextContent(); } } else if (o instanceof JAXBElement) { JAXBElement je = (JAXBElement) o; if ("orig".equals(je.getName().getLocalPart())) { return (String) je.getValue(); } } } return sb.toString(); } public static void dump(Collection<? extends ObjectType> objects) { System.out.println("Objects returned: " + objects.size()); for (ObjectType objectType : objects) { System.out.println(" - " + getOrig(objectType.getName()) + ": " + objectType); } } protected SystemConfigurationType getConfiguration() throws FaultMessage { Holder<ObjectType> objectHolder = new Holder<ObjectType>(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); modelPort.getObject(ModelClientUtil.getTypeQName(SystemConfigurationType.class), SystemObjectsType.SYSTEM_CONFIGURATION.value(), options, objectHolder, resultHolder); return (SystemConfigurationType) objectHolder.value; } protected Collection<ResourceType> listResources() throws SAXException, IOException, FaultMessage { SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); Holder<ObjectListType> objectListHolder = new Holder<ObjectListType>(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); modelPort.searchObjects(ModelClientUtil.getTypeQName(ResourceType.class), null, options, objectListHolder, resultHolder); ObjectListType objectList = objectListHolder.value; return (Collection) objectList.getObject(); } protected ResourceType getResource(String oid) throws SAXException, IOException, FaultMessage { return getObject(ResourceType.class, oid); } protected RoleType getRole(String oid) throws SAXException, IOException, FaultMessage { return getObject(RoleType.class, oid); } protected <T extends ObjectType> T getObject(Class<T> clazz, String oid) throws SAXException, IOException, FaultMessage { return getObject(clazz, oid, new SelectorQualifiedGetOptionsType()); } protected <T extends ObjectType> T getObjectNoFetch(Class<T> clazz, String oid) throws SAXException, IOException, FaultMessage { SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); SelectorQualifiedGetOptionType option = new SelectorQualifiedGetOptionType(); GetOperationOptionsType getOptions = new GetOperationOptionsType(); getOptions.setNoFetch(true); option.setOptions(getOptions); options.getOption().add(option); return getObject(clazz, oid, options); } protected <T extends ObjectType> T getObject(Class<T> clazz, String oid, SelectorQualifiedGetOptionsType options) throws SAXException, IOException, FaultMessage { Holder<ObjectType> objectHolder = new Holder<>(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); modelPort.getObject(ModelClientUtil.getTypeQName(clazz), oid, options, objectHolder, resultHolder); return (T) objectHolder.value; } protected Collection<UserType> listUsers() throws SAXException, IOException, FaultMessage { SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); Holder<ObjectListType> objectListHolder = new Holder<ObjectListType>(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); // let's say we want to get first 3 users, sorted alphabetically by user name QueryType queryType = new QueryType(); // holds search query + paging options PagingType pagingType = new PagingType(); pagingType.setMaxSize(3); pagingType.setOrderBy(ModelClientUtil.createItemPathType("name")); pagingType.setOrderDirection(OrderDirectionType.ASCENDING); queryType.setPaging(pagingType); modelPort.searchObjects(ModelClientUtil.getTypeQName(UserType.class), queryType, options, objectListHolder, resultHolder); ObjectListType objectList = objectListHolder.value; return (Collection) objectList.getObject(); } protected Collection<TaskType> listTasks() throws SAXException, IOException, FaultMessage { SelectorQualifiedGetOptionsType operationOptions = new SelectorQualifiedGetOptionsType(); // Let's say we want to retrieve tasks' next scheduled time (because this may be a costly operation if // JDBC based quartz scheduler is used, the fetching of this attribute has to be explicitly requested) SelectorQualifiedGetOptionType getNextScheduledTimeOption = new SelectorQualifiedGetOptionType(); // prepare a selector (described by path) + options (saying to retrieve that attribute) ObjectSelectorType selector = new ObjectSelectorType(); selector.setPath(ModelClientUtil.createItemPathType("nextRunStartTimestamp")); getNextScheduledTimeOption.setSelector(selector); GetOperationOptionsType selectorOptions = new GetOperationOptionsType(); selectorOptions.setRetrieve(RetrieveOptionType.INCLUDE); getNextScheduledTimeOption.setOptions(selectorOptions); // add newly created option to the list of operation options operationOptions.getOption().add(getNextScheduledTimeOption); Holder<ObjectListType> objectListHolder = new Holder<ObjectListType>(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); modelPort.searchObjects(ModelClientUtil.getTypeQName(TaskType.class), null, operationOptions, objectListHolder, resultHolder); ObjectListType objectList = objectListHolder.value; return (Collection) objectList.getObject(); } protected String createUserGuybrush(RoleType role) throws FaultMessage { Document doc = ModelClientUtil.getDocumnent(); UserType user = new UserType(); user.setName(ModelClientUtil.createPolyStringType("guybrush", doc)); user.setFullName(ModelClientUtil.createPolyStringType("Guybrush Threepwood", doc)); user.setGivenName(ModelClientUtil.createPolyStringType("Guybrush", doc)); user.setFamilyName(ModelClientUtil.createPolyStringType("Threepwood", doc)); user.setEmailAddress("guybrush@meleeisland.net"); user.getOrganization().add(ModelClientUtil.createPolyStringType("Pirate Brethren International", doc)); user.getOrganizationalUnit().add(ModelClientUtil.createPolyStringType("Pirate Wannabes", doc)); user.setCredentials(ModelClientUtil.createPasswordCredentials("IwannaBEaPIRATE")); if (role != null) { // create user with a role assignment AssignmentType roleAssignment = createRoleAssignment(role.getOid()); user.getAssignment().add(roleAssignment); } return createUser(user); } protected String createOrg(OrgType orgType) throws FaultMessage { ObjectDeltaType deltaType = new ObjectDeltaType(); deltaType.setObjectType(ModelClientUtil.getTypeQName(OrgType.class)); deltaType.setChangeType(ChangeTypeType.ADD); deltaType.setObjectToAdd(orgType); ObjectDeltaListType deltaListType = new ObjectDeltaListType(); deltaListType.getDelta().add(deltaType); ObjectDeltaOperationListType operationListType = modelPort.executeChanges(deltaListType, null); return ModelClientUtil.getOidFromDeltaOperationList(operationListType, deltaType); } protected String createAccount(String givenName, String sn, String name, String recipientType, String overrideMail, String samAccountName, String upn, Map<String,Object> additionalAttributes, boolean assertSuccess) throws FaultMessage { ShadowType user = prepareShadowType(givenName, sn, name, recipientType, overrideMail, samAccountName, upn, additionalAttributes); return createObject(ShadowType.class, user, null, assertSuccess); } protected String createAccount(String givenName, String sn, String name, String recipientType, String overrideMail, String samAccountName, String upn, boolean assertSuccess) throws FaultMessage { ShadowType user = prepareShadowType(givenName, sn, name, recipientType, overrideMail, samAccountName, upn, null); return createObject(ShadowType.class, user, null, assertSuccess); } protected String createAccount(String givenName, String sn, String name, String recipientType, String overrideMail) throws FaultMessage { ShadowType user = prepareShadowType(givenName, sn, name, recipientType, overrideMail, null, null, null); return createShadow(user); } protected ObjectDeltaOperationType createAccountOdo(String givenName, String sn, String name, String recipientType, String overrideMail) throws FaultMessage { ShadowType shadowType = prepareShadowType(givenName, sn, name, recipientType, overrideMail, null, null, null); ObjectDeltaType deltaType = new ObjectDeltaType(); deltaType.setObjectType(ModelClientUtil.getTypeQName(ShadowType.class)); deltaType.setChangeType(ChangeTypeType.ADD); deltaType.setObjectToAdd(shadowType); ObjectDeltaListType deltaListType = new ObjectDeltaListType(); deltaListType.getDelta().add(deltaType); ObjectDeltaOperationListType operationListType = modelPort.executeChanges(deltaListType, null); return ModelClientUtil.findInDeltaOperationList(operationListType, deltaType); } // additionalAttributes: e.g. "OfflineAddressBook" -> "OAB123" private ShadowType prepareShadowType(String givenName, String sn, String name, String recipientType, String overrideMail, String samAccountName, String upn, Map<String, Object> additionalAttributes) { if (samAccountName == null) { samAccountName = sn.toLowerCase(); } Document doc = ModelClientUtil.getDocumnent(); ShadowType user = new ShadowType(); user.setName(ModelClientUtil.createPolyStringType(name, doc)); user.setResourceRef(createObjectReferenceType(ResourceType.class, getResourceOid())); user.setObjectClass(OC_ACCOUNT); user.setKind(ShadowKindType.ACCOUNT); ShadowAttributesType attributes = new ShadowAttributesType(); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_ICFS, "name"), name, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "givenName"), givenName, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "sn"), sn, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "RecipientType"), recipientType, doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "sAMAccountName"), samAccountName, doc)); if (overrideMail != null) { attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "EmailAddressPolicyEnabled"), "true", doc)); attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "EmailAddresses"), overrideMail, doc)); } if (upn != null) { attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, "userPrincipalName"), upn, doc)); } if (additionalAttributes != null) { for (Map.Entry<String,Object> entry : additionalAttributes.entrySet()) { if (entry.getValue() instanceof Collection) { for (Object value : (Collection) entry.getValue()) { addAttribute(attributes, entry.getKey(), value, doc); } } else { addAttribute(attributes, entry.getKey(), entry.getValue(), doc); } } } user.setAttributes(attributes); return user; } private void addAttribute(ShadowAttributesType attributes, String name, Object value, Document doc) { if (value != null) { attributes.getAny().add(ModelClientUtil.createTextElement(new QName(NS_RI, name), value.toString(), doc)); } } protected ShadowType getShadowByName(String resourceOid, QName objectClass, String name) throws JAXBException, SAXException, IOException, FaultMessage { // WARNING: in a real case make sure that the username is properly escaped before putting it in XML SearchFilterType filter = ModelClientUtil.parseSearchFilterType( " <q:and xmlns:q='http://prism.evolveum.com/xml/ns/public/query-3' xmlns:c='http://midpoint.evolveum.com/xml/ns/public/common/common-3'>\n" + " <q:ref>\n" + " <q:path>resourceRef</q:path>\n" + " <q:value>\n" + " <oid>" + resourceOid + "</oid>\n" + " <type>ResourceType</type>\n" + " </q:value>\n" + " </q:ref>\n" + " <q:equal>\n" + " <q:path>objectClass</q:path>\n" + " <q:value xmlns:a=\"" + objectClass.getNamespaceURI() + "\">a:" + objectClass.getLocalPart() + "</q:value>\n" + " </q:equal>\n" + " <q:equal>\n" + " <q:path>attributes/name</q:path>\n" + " <q:value>" + name + "</q:value>\n" + " </q:equal>\n" + " </q:and>\n"); QueryType query = new QueryType(); query.setFilter(filter); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); Holder<ObjectListType> objectListHolder = new Holder<>(); Holder<OperationResultType> resultHolder = new Holder<>(); modelPort.searchObjects(ModelClientUtil.getTypeQName(ShadowType.class), query, options, objectListHolder, resultHolder); ObjectListType objectList = objectListHolder.value; List<ObjectType> objects = objectList.getObject(); if (objects.isEmpty()) { return null; } if (objects.size() == 1) { return (ShadowType) objects.get(0); } throw new IllegalStateException("Expected to find a single shadow with name '"+name+"' but found "+objects.size()+" ones instead"); } // TODO move to Util public static ObjectReferenceType createObjectReferenceType(Class<? extends ObjectType> typeClass, String oid) { ObjectReferenceType ort = new ObjectReferenceType(); ort.setOid(oid); ort.setType(ModelClientUtil.getTypeQName(typeClass)); return ort; } protected String createUserFromSystemResource(String resourcePath) throws FileNotFoundException, JAXBException, FaultMessage { UserType user = unmarshallResource(resourcePath); return createUser(user); } protected static <T> T unmarshallFile(File file) throws JAXBException, FileNotFoundException { JAXBContext jc = ModelClientUtil.instantiateJaxbContext(); Unmarshaller unmarshaller = jc.createUnmarshaller(); InputStream is = null; JAXBElement<T> element = null; try { is = new FileInputStream(file); element = (JAXBElement<T>) unmarshaller.unmarshal(is); } finally { if (is != null) { IOUtils.closeQuietly(is); } } if (element == null) { return null; } return element.getValue(); } protected static <T> T unmarshallResource(String path) throws JAXBException, FileNotFoundException { JAXBContext jc = ModelClientUtil.instantiateJaxbContext(); Unmarshaller unmarshaller = jc.createUnmarshaller(); InputStream is = null; JAXBElement<T> element = null; try { is = AbstractTestForExchangeConnector.class.getClassLoader().getResourceAsStream(path); if (is == null) { throw new FileNotFoundException("System resource "+path+" was not found"); } element = (JAXBElement<T>) unmarshaller.unmarshal(is); } finally { if (is != null) { IOUtils.closeQuietly(is); } } if (element == null) { return null; } return element.getValue(); } protected String createUser(UserType userType) throws FaultMessage { ObjectDeltaType deltaType = new ObjectDeltaType(); deltaType.setObjectType(ModelClientUtil.getTypeQName(UserType.class)); deltaType.setChangeType(ChangeTypeType.ADD); deltaType.setObjectToAdd(userType); ObjectDeltaListType deltaListType = new ObjectDeltaListType(); deltaListType.getDelta().add(deltaType); ObjectDeltaOperationListType operationListType = modelPort.executeChanges(deltaListType, null); String oid = ModelClientUtil.getOidFromDeltaOperationList(operationListType, deltaType); return oid; } protected String createShadow(ShadowType shadowType) throws FaultMessage { return createShadow(shadowType, null); } protected String createShadow(ShadowType shadowType, ModelExecuteOptionsType options) throws FaultMessage { return createObject(ShadowType.class, shadowType, options); } protected String createObject(Class clazz, ObjectType objectType, ModelExecuteOptionsType options) throws FaultMessage { return createObject(clazz, objectType, options, true); } protected String createObject(Class clazz, ObjectType objectType, ModelExecuteOptionsType options, boolean assertSuccess) throws FaultMessage { ObjectDeltaType deltaType = new ObjectDeltaType(); deltaType.setObjectType(ModelClientUtil.getTypeQName(clazz)); deltaType.setChangeType(ChangeTypeType.ADD); deltaType.setObjectToAdd(objectType); ObjectDeltaListType deltaListType = new ObjectDeltaListType(); deltaListType.getDelta().add(deltaType); ObjectDeltaOperationListType operationListType = modelPort.executeChanges(deltaListType, options); lastOdo = assertExecuteChangesSuccess(operationListType, null, assertSuccess); // Holder<OperationResultType> holder = new Holder<>(); // String oid = getOidFromDeltaOperationList(operationListType, deltaType, holder); // AssertJUnit.assertNotNull("No operation result from create shadow operation", holder.value); // if (holder.value != null && holder.value.getStatus() != OperationResultStatusType.SUCCESS) { // System.out.println("!!! Operation result is " + holder.value.getStatus() + ": " + holder.value); // AssertJUnit.assertEquals("Unexpected operation result status", OperationResultStatusType.SUCCESS, holder.value.getStatus()); // } return ModelClientUtil.getOidFromDeltaOperationList(operationListType, deltaType); } /** * Retrieves OID and OperationResult created by model Web Service from the returned list of ObjectDeltaOperations. * * @param operationListType result of the model web service executeChanges call * @param originalDelta original request used to find corresponding ObjectDeltaOperationType instance. Must be of ADD type. * @param operationResultHolder where the result will be put * @return OID if found * * PRELIMINARY IMPLEMENTATION. Currently the first returned ADD delta with the same object type as original delta is returned. * * TODO move to ModelClientUtil */ public static String getOidFromDeltaOperationList(ObjectDeltaOperationListType operationListType, ObjectDeltaType originalDelta, Holder<OperationResultType> operationResultTypeHolder) { Validate.notNull(operationListType); Validate.notNull(originalDelta); if (originalDelta.getChangeType() != ChangeTypeType.ADD) { throw new IllegalArgumentException("Original delta is not of ADD type"); } if (originalDelta.getObjectToAdd() == null) { throw new IllegalArgumentException("Original delta contains no object-to-be-added"); } for (ObjectDeltaOperationType operationType : operationListType.getDeltaOperation()) { ObjectDeltaType objectDeltaType = operationType.getObjectDelta(); if (objectDeltaType.getChangeType() == ChangeTypeType.ADD && objectDeltaType.getObjectToAdd() != null) { ObjectType objectAdded = (ObjectType) objectDeltaType.getObjectToAdd(); if (objectAdded.getClass().equals(originalDelta.getObjectToAdd().getClass())) { operationResultTypeHolder.value = operationType.getExecutionResult(); return objectAdded.getOid(); } } } return null; } protected void changeUserPassword(String oid, String newPassword) throws FaultMessage { ItemDeltaType passwordDelta = new ItemDeltaType(); passwordDelta.setModificationType(ModificationTypeType.REPLACE); passwordDelta.setPath(ModelClientUtil.createItemPathType("credentials/password/value")); passwordDelta.getValue().add(ModelClientUtil.createProtectedString(newPassword)); ObjectDeltaType deltaType = new ObjectDeltaType(); deltaType.setObjectType(ModelClientUtil.getTypeQName(UserType.class)); deltaType.setChangeType(ChangeTypeType.MODIFY); deltaType.setOid(oid); deltaType.getItemDelta().add(passwordDelta); ObjectDeltaListType deltaListType = new ObjectDeltaListType(); deltaListType.getDelta().add(deltaType); modelPort.executeChanges(deltaListType, null); } protected void changeUserGivenName(String oid, String newValue) throws FaultMessage { Document doc = ModelClientUtil.getDocumnent(); ObjectDeltaType userDelta = new ObjectDeltaType(); userDelta.setOid(oid); userDelta.setObjectType(ModelClientUtil.getTypeQName(UserType.class)); userDelta.setChangeType(ChangeTypeType.MODIFY); ItemDeltaType itemDelta = new ItemDeltaType(); itemDelta.setModificationType(ModificationTypeType.REPLACE); itemDelta.setPath(ModelClientUtil.createItemPathType("givenName")); itemDelta.getValue().add(ModelClientUtil.createPolyStringType(newValue, doc)); userDelta.getItemDelta().add(itemDelta); ObjectDeltaListType deltaList = new ObjectDeltaListType(); deltaList.getDelta().add(userDelta); modelPort.executeChanges(deltaList, null); } protected boolean assignRoles(Class clazz, String oid, String... roleOids) throws FaultMessage { return modifyRoleAssignment(clazz, oid, true, roleOids); } protected void unassignRoles(Class clazz, String oid, String... roleOids) throws FaultMessage { modifyRoleAssignment(clazz, oid, false, roleOids); } protected boolean modifyRoleAssignment(Class clazz, String oid, boolean isAdd, String... roleOids) throws FaultMessage { ItemDeltaType assignmentDelta = new ItemDeltaType(); if (isAdd) { assignmentDelta.setModificationType(ModificationTypeType.ADD); } else { assignmentDelta.setModificationType(ModificationTypeType.DELETE); } assignmentDelta.setPath(ModelClientUtil.createItemPathType("assignment")); for (String roleOid: roleOids) { AssertJUnit.assertNotNull("role OID is null", roleOid); assignmentDelta.getValue().add(createRoleAssignment(roleOid)); } ObjectDeltaType deltaType = new ObjectDeltaType(); deltaType.setObjectType(ModelClientUtil.getTypeQName(clazz)); deltaType.setChangeType(ChangeTypeType.MODIFY); deltaType.setOid(oid); deltaType.getItemDelta().add(assignmentDelta); ObjectDeltaListType deltaListType = new ObjectDeltaListType(); deltaListType.getDelta().add(deltaType); ObjectDeltaOperationListType objectDeltaOperationList = modelPort.executeChanges(deltaListType, null); Boolean success = null; for (ObjectDeltaOperationType objectDeltaOperation : objectDeltaOperationList.getDeltaOperation()) { if (oid.equals(objectDeltaOperation.getObjectDelta().getOid())) { if (!OperationResultStatusType.SUCCESS.equals(objectDeltaOperation.getExecutionResult().getStatus())) { System.out.println("*** Operation result = " + objectDeltaOperation.getExecutionResult().getStatus() + ": " + objectDeltaOperation.getExecutionResult().getMessage()); success = false; } else { if (success == null) { success = true; } } } } return Boolean.TRUE.equals(success); } protected AssignmentType createRoleAssignment(String roleOid) { AssignmentType roleAssignment = new AssignmentType(); ObjectReferenceType roleRef = new ObjectReferenceType(); roleRef.setOid(roleOid); roleRef.setType(ModelClientUtil.getTypeQName(RoleType.class)); roleAssignment.setTargetRef(roleRef); return roleAssignment; } protected UserType searchUserByName(String username) throws SAXException, IOException, FaultMessage, JAXBException { // WARNING: in a real case make sure that the username is properly escaped before putting it in XML SearchFilterType filter = ModelClientUtil.parseSearchFilterType( "<equal xmlns='http://prism.evolveum.com/xml/ns/public/query-3' xmlns:c='http://midpoint.evolveum.com/xml/ns/public/common/common-3' >" + "<path>c:name</path>" + "<value>" + username + "</value>" + "</equal>" ); QueryType query = new QueryType(); query.setFilter(filter); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); Holder<ObjectListType> objectListHolder = new Holder<ObjectListType>(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); modelPort.searchObjects(ModelClientUtil.getTypeQName(UserType.class), query, options, objectListHolder, resultHolder); ObjectListType objectList = objectListHolder.value; List<ObjectType> objects = objectList.getObject(); if (objects.isEmpty()) { return null; } if (objects.size() == 1) { return (UserType) objects.get(0); } throw new IllegalStateException("Expected to find a single user with username '"+username+"' but found "+objects.size()+" users instead"); } protected RoleType searchRoleByName(String roleName) throws SAXException, IOException, FaultMessage, JAXBException { // WARNING: in a real case make sure that the role name is properly escaped before putting it in XML SearchFilterType filter = ModelClientUtil.parseSearchFilterType( "<equal xmlns='http://prism.evolveum.com/xml/ns/public/query-3' xmlns:c='http://midpoint.evolveum.com/xml/ns/public/common/common-3' >" + "<path>c:name</path>" + "<value>" + roleName + "</value>" + "</equal>" ); QueryType query = new QueryType(); query.setFilter(filter); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); Holder<ObjectListType> objectListHolder = new Holder<ObjectListType>(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); modelPort.searchObjects(ModelClientUtil.getTypeQName(RoleType.class), query, options, objectListHolder, resultHolder); ObjectListType objectList = objectListHolder.value; List<ObjectType> objects = objectList.getObject(); if (objects.isEmpty()) { return null; } if (objects.size() == 1) { return (RoleType) objects.get(0); } throw new IllegalStateException("Expected to find a single role with name '"+roleName+"' but found "+objects.size()+" users instead"); } protected Collection<RoleType> listRequestableRoles() throws SAXException, IOException, FaultMessage, JAXBException { SearchFilterType filter = ModelClientUtil.parseSearchFilterType( "<equal xmlns='http://prism.evolveum.com/xml/ns/public/query-3' xmlns:c='http://midpoint.evolveum.com/xml/ns/public/common/common-3' >" + "<path>c:requestable</path>" + "<value>true</value>" + "</equal>" ); QueryType query = new QueryType(); query.setFilter(filter); SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); Holder<ObjectListType> objectListHolder = new Holder<ObjectListType>(); Holder<OperationResultType> resultHolder = new Holder<OperationResultType>(); modelPort.searchObjects(ModelClientUtil.getTypeQName(RoleType.class), query, options, objectListHolder, resultHolder); ObjectListType objectList = objectListHolder.value; return (Collection) objectList.getObject(); } protected void deleteUser(String oid) throws FaultMessage { ObjectDeltaType deltaType = new ObjectDeltaType(); deltaType.setObjectType(ModelClientUtil.getTypeQName(UserType.class)); deltaType.setChangeType(ChangeTypeType.DELETE); deltaType.setOid(oid); ObjectDeltaListType deltaListType = new ObjectDeltaListType(); deltaListType.getDelta().add(deltaType); ModelExecuteOptionsType executeOptionsType = new ModelExecuteOptionsType(); executeOptionsType.setRaw(true); modelPort.executeChanges(deltaListType, executeOptionsType); } protected void deleteTask(String oid) throws FaultMessage { ObjectDeltaType deltaType = new ObjectDeltaType(); deltaType.setObjectType(ModelClientUtil.getTypeQName(TaskType.class)); deltaType.setChangeType(ChangeTypeType.DELETE); deltaType.setOid(oid); ObjectDeltaListType deltaListType = new ObjectDeltaListType(); deltaListType.getDelta().add(deltaType); ModelExecuteOptionsType executeOptionsType = new ModelExecuteOptionsType(); executeOptionsType.setRaw(true); modelPort.executeChanges(deltaListType, executeOptionsType); } public ModelPortType createModelPort(String[] args) { String endpointUrl = DEFAULT_ENDPOINT_URL; if (args.length > 0) { endpointUrl = args[0]; } System.out.println("Endpoint URL: "+endpointUrl); // uncomment this if you want to use Fiddler or any other proxy // ProxySelector.setDefault(new MyProxySelector("127.0.0.1", 8888)); ModelService modelService = new ModelService(); ModelPortType modelPort = modelService.getModelPort(); BindingProvider bp = (BindingProvider)modelPort; Map<String, Object> requestContext = bp.getRequestContext(); requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointUrl); org.apache.cxf.endpoint.Client client = ClientProxy.getClient(modelPort); HTTPConduit http = (HTTPConduit) client.getConduit(); HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy(); httpClientPolicy.setReceiveTimeout(300000L); http.setClient(httpClientPolicy); org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint(); Map<String,Object> outProps = new HashMap<String,Object>(); outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); outProps.put(WSHandlerConstants.USER, ADM_USERNAME); outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST); outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordHandler.class.getName()); WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); cxfEndpoint.getOutInterceptors().add(wssOut); // enable the following to get client-side logging of outgoing requests and incoming responses //cxfEndpoint.getOutInterceptors().add(new LoggingOutInterceptor()); //cxfEndpoint.getInInterceptors().add(new LoggingInInterceptor()); return modelPort; } public static ItemPathType createNonDefaultItemPathType(String stringPath) { ItemPathType itemPathType = new ItemPathType(); itemPathType.setValue(stringPath); return itemPathType; } protected String getDebugName(ObjectType objectType) { return objectType.getClass().getSimpleName() + " " + getOrig(objectType.getName()) + " (" + objectType.getOid() + ")"; } }