Java tutorial
/* * Copyright (c) 2010-2013 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.repo.sql; import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.ReferenceDelta; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.prism.util.ValueSerializationUtil; import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.schema.*; import com.evolveum.midpoint.schema.processor.ResourceSchema; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ShadowUtil; import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.stat.Statistics; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.testng.AssertJUnit; import org.testng.annotations.Test; import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; import java.io.File; import java.util.*; /** * @author lazyman */ @ContextConfiguration(locations = { "../../../../../ctx-test.xml" }) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) public class AddGetObjectTest extends BaseSQLRepoTest { private static final Trace LOGGER = TraceManager.getTrace(AddGetObjectTest.class); @Test(enabled = false) public <T extends ObjectType> void perfTest() throws Exception { Statistics stats = getFactory().getStatistics(); stats.setStatisticsEnabled(true); final File OBJECTS_FILE = new File("./src/test/resources/10k-users.xml"); List<PrismObject<? extends Objectable>> elements = prismContext.parseObjects(OBJECTS_FILE); long previousCycle = 0; long time = System.currentTimeMillis(); for (int i = 0; i < elements.size(); i++) { if (i % 500 == 0) { LOGGER.info("Previous cycle time {}. Next cycle: {}", new Object[] { (System.currentTimeMillis() - time - previousCycle), i }); previousCycle = System.currentTimeMillis() - time; } PrismObject<T> object = (PrismObject<T>) elements.get(i); repositoryService.addObject(object, null, new OperationResult("add performance test")); } LOGGER.info("Time to add objects ({}): {}", new Object[] { elements.size(), (System.currentTimeMillis() - time) }); stats.logSummary(); } @Test public void addSameName() throws Exception { final File user = new File(FOLDER_BASIC, "objects-user.xml"); addGetCompare(user); try { // WHEN addGetCompare(user); assert false : "Unexpected success"; } catch (ObjectAlreadyExistsException e) { TestUtil.assertExceptionSanity(e); } } @Test public void addGetDSEESyncDoubleTest() throws Exception { final File OBJECTS_FILE = new File("./../../samples/dsee/odsee-localhost-advanced-sync.xml"); if (!OBJECTS_FILE.exists()) { LOGGER.warn("skipping addGetDSEESyncDoubleTest, file {} not found.", new Object[] { OBJECTS_FILE.getPath() }); return; } addGetCompare(OBJECTS_FILE); try { // WHEN addGetCompare(OBJECTS_FILE); assert false : "Unexpected success"; } catch (ObjectAlreadyExistsException e) { TestUtil.assertExceptionSanity(e); } } @Test public void simpleAddGetTest() throws Exception { LOGGER.info("===[ simpleAddGetTest ]==="); final File OBJECTS_FILE = new File(FOLDER_BASIC, "objects.xml"); addGetCompare(OBJECTS_FILE); } private void addGetCompare(File file) throws Exception { List<PrismObject<? extends Objectable>> elements = prismContext.parseObjects(file); List<String> oids = new ArrayList<String>(); OperationResult result = new OperationResult("Simple Add Get Test"); long time = System.currentTimeMillis(); for (int i = 0; i < elements.size(); i++) { PrismObject object = elements.get(i); LOGGER.info("Adding object {}, type {}", new Object[] { (i + 1), object.getCompileTimeClass().getSimpleName() }); oids.add(repositoryService.addObject(object, null, result)); } LOGGER.info("Time to add objects ({}): {}", new Object[] { elements.size(), (System.currentTimeMillis() - time), }); int count = 0; elements = prismContext.parseObjects(file); for (int i = 0; i < elements.size(); i++) { try { PrismObject object = elements.get(i); object.asObjectable().setOid(oids.get(i)); Class<? extends ObjectType> clazz = object.getCompileTimeClass(); Collection o = null; if (UserType.class.equals(clazz)) { o = SelectorOptions.createCollection(UserType.F_JPEG_PHOTO, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE)); } PrismObject<? extends ObjectType> newObject = repositoryService.getObject(clazz, oids.get(i), o, result); LOGGER.info("Old\n{}\nnew\n{}", new Object[] { object.debugDump(3), newObject.debugDump(3) }); checkContainersSize(newObject, object); System.out.println("OLD: " + object.findProperty(ObjectType.F_NAME).getValue()); System.out.println("NEW: " + newObject.findProperty(ObjectType.F_NAME).getValue()); ObjectDelta delta = object.diff(newObject); if (delta == null) { continue; } count += delta.getModifications().size(); if (delta.getModifications().size() > 0) { if (delta.getModifications().size() == 1) { ItemDelta d = (ItemDelta) delta.getModifications().iterator().next(); if (ShadowType.F_DEAD.equals(d.getElementName())) { count -= delta.getModifications().size(); continue; } } LOGGER.error(">>> {} Found {} changes for {}\n{}", new Object[] { (i + 1), delta.getModifications().size(), newObject.toString(), delta.debugDump(3) }); ItemDelta id = (ItemDelta) delta.getModifications().iterator().next(); if (id.isReplace()) { System.out.println(id.getValuesToReplace().iterator().next()); } LOGGER.error("{}", prismContext.serializeObjectToString(newObject, PrismContext.LANG_XML)); } } catch (Exception ex) { LOGGER.error("Exception occurred", ex); throw ex; } } AssertJUnit.assertEquals("Found changes during add/get test " + count, 0, count); } private Integer size(PrismContainerValue value) { if (value == null) { return null; } return value.getItems() != null ? value.getItems().size() : 0; } private void checkContainerValuesSize(QName parentName, PrismContainerValue newValue, PrismContainerValue oldValue) { LOGGER.info("Checking: " + parentName); AssertJUnit.assertEquals("Count doesn't match for '" + parentName + "'", size(oldValue), size(newValue)); List<QName> checked = new ArrayList<QName>(); for (Item item : (List<Item>) newValue.getItems()) { if (!(item instanceof PrismContainer)) { continue; } PrismContainer newContainer = (PrismContainer) item; PrismContainer oldContainer = oldValue.findContainer(newContainer.getElementName()); AssertJUnit.assertNotNull("Container '" + newContainer.getElementName() + "' doesn't exist.", oldContainer); checkContainersSize(newContainer, oldContainer); checked.add(oldContainer.getElementName()); } for (Item item : (List<Item>) oldValue.getItems()) { if (!(item instanceof PrismContainer) || checked.contains(item.getElementName())) { continue; } PrismContainer oldContainer = (PrismContainer) item; PrismContainer newContainer = newValue.findContainer(oldContainer.getElementName()); checkContainersSize(newContainer, oldContainer); } } private void checkContainersSize(PrismContainer newContainer, PrismContainer oldContainer) { LOGGER.info("checkContainersSize {} new {} old {}", new Object[] { newContainer.getElementName(), newContainer.size(), oldContainer.size() }); AssertJUnit.assertEquals(newContainer.size(), oldContainer.size()); List<Long> checked = new ArrayList<Long>(); List<PrismContainerValue> newValues = newContainer.getValues(); for (PrismContainerValue value : newValues) { PrismContainerValue oldValue = oldContainer.getValue(value.getId()); checkContainerValuesSize(newContainer.getElementName(), value, oldValue); checked.add(value.getId()); } List<PrismContainerValue> oldValues = oldContainer.getValues(); for (PrismContainerValue value : oldValues) { if (checked.contains(value.getId())) { continue; } PrismContainerValue newValue = newContainer.getValue(value.getId()); checkContainerValuesSize(newContainer.getElementName(), newValue, value); } } @Test public void addUserWithAssignmentExtension() throws Exception { LOGGER.info("===[ addUserWithAssignmentExtension ]==="); File file = new File(FOLDER_BASIC, "user-assignment-extension.xml"); List<PrismObject<? extends Objectable>> elements = prismContext.parseObjects(file); OperationResult result = new OperationResult("ADD"); String oid = repositoryService.addObject((PrismObject) elements.get(0), null, result); PrismObject<UserType> fileUser = (PrismObject<UserType>) prismContext.parseObjects(file).get(0); long id = 1; for (AssignmentType assignment : fileUser.asObjectable().getAssignment()) { assignment.setId(id); id++; } PrismObject<UserType> repoUser = repositoryService.getObject(UserType.class, oid, null, result); ObjectDelta<UserType> delta = fileUser.diff(repoUser); AssertJUnit.assertNotNull(delta); LOGGER.info("delta\n{}", new Object[] { delta.debugDump(3) }); AssertJUnit.assertTrue(delta.isEmpty()); } /** * Attempt to store full account in the repo and then get it out again. The * potential problem is that there are attributes that do not have a fixed * (static) definition. */ @Test public void addGetFullAccount() throws Exception { LOGGER.info("===[ addGetFullAccount ]==="); File file = new File(FOLDER_BASIC, "account-full.xml"); PrismObject<ShadowType> fileAccount = prismContext.parseObject(new File(FOLDER_BASIC, "account-full.xml")); // apply appropriate schema PrismObject<ResourceType> resource = prismContext .parseObject(new File(FOLDER_BASIC, "resource-opendj.xml")); ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); ShadowUtil.applyResourceSchema(fileAccount, resourceSchema); OperationResult result = new OperationResult("ADD"); String oid = repositoryService.addObject(fileAccount, null, result); PrismObject<ShadowType> repoAccount = repositoryService.getObject(ShadowType.class, oid, null, result); ObjectDelta<ShadowType> delta = fileAccount.diff(repoAccount); AssertJUnit.assertNotNull(delta); LOGGER.info("delta\n{}", new Object[] { delta.debugDump(3) }); AssertJUnit.assertTrue(delta.isEmpty()); ShadowType repoShadow = repoAccount.asObjectable(); AssertJUnit.assertNotNull(repoShadow.getSynchronizationSituation()); AssertJUnit.assertEquals(SynchronizationSituationType.LINKED, repoShadow.getSynchronizationSituation()); AssertJUnit.assertNotNull(repoShadow.getSynchronizationSituationDescription()); AssertJUnit.assertEquals(1, repoShadow.getSynchronizationSituationDescription().size()); AssertJUnit.assertEquals(SynchronizationSituationType.LINKED, repoShadow.getSynchronizationSituationDescription().get(0).getSituation()); AssertJUnit.assertEquals("syncChannel", repoShadow.getSynchronizationSituationDescription().get(0).getChannel()); } @Test public void addGetSystemConfigFile() throws Exception { LOGGER.info("===[ addGetPasswordPolicy ]==="); File file = new File(FOLDER_BASIC, "password-policy.xml"); PrismObject<ValuePolicyType> filePasswordPolicy = prismContext .parseObject(new File(FOLDER_BASIC, "password-policy.xml")); OperationResult result = new OperationResult("ADD"); String pwdPolicyOid = "00000000-0000-0000-0000-000000000003"; String oid = repositoryService.addObject(filePasswordPolicy, null, result); AssertJUnit.assertNotNull(oid); AssertJUnit.assertEquals(pwdPolicyOid, oid); PrismObject<ValuePolicyType> repoPasswordPolicy = repositoryService.getObject(ValuePolicyType.class, oid, null, result); AssertJUnit.assertNotNull(repoPasswordPolicy); String systemCongigOid = "00000000-0000-0000-0000-000000000001"; PrismObject<SystemConfigurationType> fileSystemConfig = prismContext .parseObject(new File(FOLDER_BASIC, "systemConfiguration.xml")); LOGGER.info("System config from file: {}", fileSystemConfig.debugDump()); oid = repositoryService.addObject(fileSystemConfig, null, result); AssertJUnit.assertNotNull(oid); AssertJUnit.assertEquals(systemCongigOid, oid); PrismObject<SystemConfigurationType> repoSystemConfig = repositoryService .getObject(SystemConfigurationType.class, systemCongigOid, null, result); // AssertJUnit.assertNotNull("global password policy null", repoSystemConfig.asObjectable().getGlobalPasswordPolicy()); LOGGER.info("System config from repo: {}", repoSystemConfig.debugDump()); AssertJUnit.assertNull("global password policy not null", repoSystemConfig.asObjectable().getGlobalPasswordPolicyRef()); ReferenceDelta refDelta = ReferenceDelta.createModificationAdd( SystemConfigurationType.F_GLOBAL_PASSWORD_POLICY_REF, repoSystemConfig.getDefinition(), PrismReferenceValue.createFromTarget(repoPasswordPolicy)); List<ReferenceDelta> refDeltas = new ArrayList<ReferenceDelta>(); refDeltas.add(refDelta); repositoryService.modifyObject(SystemConfigurationType.class, systemCongigOid, refDeltas, result); repoSystemConfig = repositoryService.getObject(SystemConfigurationType.class, systemCongigOid, null, result); LOGGER.info("system config after modify: {}", repoSystemConfig.debugDump()); AssertJUnit.assertNotNull("global password policy null", repoSystemConfig.asObjectable().getGlobalPasswordPolicyRef()); AssertJUnit.assertNull("default user template not null", repoSystemConfig.asObjectable().getDefaultUserTemplateRef()); } @Test public void addGetSyncDescription() throws Exception { PrismObjectDefinition accDef = prismContext.getSchemaRegistry() .findObjectDefinitionByCompileTimeClass(ShadowType.class); PrismObject<ShadowType> shadow = accDef.instantiate(); final Date TIME = new Date(); ShadowType shadowType = shadow.asObjectable(); shadowType.setName(new PolyStringType("sync desc test")); SynchronizationSituationDescriptionType desc = new SynchronizationSituationDescriptionType(); desc.setChannel("channel"); desc.setSituation(SynchronizationSituationType.LINKED); desc.setTimestamp(XMLGregorianCalendarType.asXMLGregorianCalendar(TIME)); shadowType.getSynchronizationSituationDescription().add(desc); OperationResult result = new OperationResult("sync desc test"); String oid = repositoryService.addObject(shadowType.asPrismObject(), null, result); shadow = repositoryService.getObject(ShadowType.class, oid, null, result); shadowType = shadow.asObjectable(); desc = shadowType.getSynchronizationSituationDescription().get(0); AssertJUnit.assertEquals("Times don't match", TIME, XMLGregorianCalendarType.asDate(desc.getTimestamp())); } /** * creates <iterationToken/> element in shadow */ @Test public void emtpyIterationToken() throws Exception { String token = testIterationToken(""); AssertJUnit.assertNotNull(token); AssertJUnit.assertTrue(token.equals("")); } /** * doesn't create <iterationToken/> element in shadow */ @Test public void nullIterationToken() throws Exception { String token = testIterationToken(null); AssertJUnit.assertNull(token); } /** * creates <iterationToken>some value</iterationToken> element in shadow */ @Test public void valueInIterationToken() throws Exception { String token = testIterationToken("foo"); AssertJUnit.assertNotNull(token); AssertJUnit.assertEquals(token, "foo"); } private String testIterationToken(String token) throws Exception { PrismObjectDefinition accDef = prismContext.getSchemaRegistry() .findObjectDefinitionByCompileTimeClass(ShadowType.class); PrismObject<ShadowType> shadow = accDef.instantiate(); ShadowType shadowType = shadow.asObjectable(); shadowType.setName(new PolyStringType("testIterationToken")); shadowType.setIterationToken(token); OperationResult result = new OperationResult("sync desc test"); final String oid = repositoryService.addObject(shadowType.asPrismObject(), null, result); shadow = repositoryService.getObject(ShadowType.class, oid, null, result); shadowType = shadow.asObjectable(); token = shadowType.getIterationToken(); repositoryService.deleteObject(ShadowType.class, oid, result); return token; } @Test(enabled = false) public void deltaOperationSerializationPerformanceTest() throws Exception { List<PrismObject<? extends Objectable>> elements = prismContext .parseObjects(new File(FOLDER_BASIC, "objects.xml")); //get user from objects.xml ObjectDelta delta = ObjectDelta.createAddDelta(elements.get(0)); final int COUNT = 10000; //first conversion option System.out.println(DeltaConvertor.toObjectDeltaTypeXml(delta)); //second conversion option System.out.println("\n" + toRepo(DeltaConvertor.toObjectDeltaType(delta), prismContext)); long time = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { String xml = DeltaConvertor.toObjectDeltaTypeXml(delta); } time = System.currentTimeMillis() - time; System.out.println(">>> " + time); time = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { ObjectDeltaType type = DeltaConvertor.toObjectDeltaType(delta); String xml = toRepo(type, prismContext); } time = System.currentTimeMillis() - time; System.out.println(">>> " + time); } private <T> String toRepo(T value, PrismContext prismContext) throws SchemaException, JAXBException { if (value == null) { return null; } // PrismDomProcessor domProcessor = prismContext.getPrismDomProcessor(); if (value instanceof Objectable) { return prismContext.serializeObjectToString(((Objectable) value).asPrismObject(), PrismContext.LANG_XML); } if (value instanceof Containerable) { // TODO: createFakeParentElement??? why we don't use the real // name??? return prismContext.serializeContainerValueToString(((Containerable) value).asPrismContainerValue(), QNameUtil.getNodeQName(RUtil.createFakeParentElement()), prismContext.LANG_XML); } return ValueSerializationUtil.serializeValue(value, new QName("fake"), prismContext, PrismContext.LANG_XML); } @Test public void test() throws Exception { OperationResult result = new OperationResult("asdf"); final List<PrismObject> objects = new ArrayList<PrismObject>(); ResultHandler<ObjectType> handler = new ResultHandler<ObjectType>() { @Override public boolean handle(PrismObject<ObjectType> object, OperationResult parentResult) { objects.add(object); return true; } }; repositoryService.searchObjectsIterative(ObjectType.class, null, handler, null, result); AssertJUnit.assertTrue(!objects.isEmpty()); } @Test private void addGetFullAccountShadow() throws Exception { LOGGER.info("===[ simpleAddAccountShadowTest ]==="); OperationResult result = new OperationResult("testAddAccountShadow"); File file = new File(FOLDER_BASIC, "account-accountTypeShadow.xml"); try { PrismObject<ShadowType> account = prismContext.parseObject(file); // apply appropriate schema PrismObject<ResourceType> resource = prismContext .parseObject(new File(FOLDER_BASIC, "resource-opendj.xml")); ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); ShadowUtil.applyResourceSchema(account, resourceSchema); repositoryService.addObject(account, null, result); PrismObject<ShadowType> afterAdd = repositoryService.getObject(ShadowType.class, account.getOid(), null, result); AssertJUnit.assertNotNull(afterAdd); } catch (Exception ex) { LOGGER.error("Exception occurred", ex); throw ex; } } @Test public void test100AddUserWithoutAssignmentIds() throws Exception { OperationResult result = new OperationResult("test100AddUserWithoutAssignmentIds"); PrismObject<UserType> user = PrismTestUtil.parseObject(new File(FOLDER_BASIC, "user-big.xml")); //remove ids from assignment values PrismContainer container = user.findContainer(UserType.F_ASSIGNMENT); for (PrismContainerValue value : (List<PrismContainerValue>) container.getValues()) { value.setId(null); } final String OID = repositoryService.addObject(user, null, result); result.computeStatusIfUnknown(); //get user user = repositoryService.getObject(UserType.class, OID, null, result); result.computeStatusIfUnknown(); container = user.findContainer(UserType.F_ASSIGNMENT); List<Short> xmlShorts = new ArrayList<>(); for (PrismContainerValue value : (List<PrismContainerValue>) container.getValues()) { AssertJUnit.assertNotNull(value.getId()); xmlShorts.add(value.getId().shortValue()); } Collections.sort(xmlShorts); Session session = open(); try { Query query = session.createSQLQuery("select id from m_assignment where owner_oid=:oid"); query.setString("oid", OID); List<Short> dbShorts = new ArrayList<>(); for (Number n : (List<Number>) query.list()) { dbShorts.add(n.shortValue()); } Collections.sort(dbShorts); LOGGER.info("assigments ids: expected {} db {}", Arrays.toString(xmlShorts.toArray()), Arrays.toString(dbShorts.toArray())); AssertJUnit.assertArrayEquals(xmlShorts.toArray(), dbShorts.toArray()); } finally { close(session); } } }