| /* |
| * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // - rbarkhouse - 23 April 2012 - 2.4 - Initial implementation |
| package org.eclipse.persistence.testing.jaxb.cycle; |
| |
| import java.io.ByteArrayOutputStream; |
| |
| import jakarta.xml.bind.Marshaller; |
| |
| import org.eclipse.persistence.exceptions.XMLMarshalException; |
| import org.eclipse.persistence.testing.jaxb.JAXBWithJSONTestCases; |
| |
| public class CycleRecoverableTestCases extends JAXBWithJSONTestCases { |
| |
| private final static String XML_RESOURCE = "org/eclipse/persistence/testing/jaxb/cycle/cycle.xml"; |
| private final static String JSON_RESOURCE = "org/eclipse/persistence/testing/jaxb/cycle/cycle.json"; |
| |
| public CycleRecoverableTestCases(String name) throws Exception { |
| super(name); |
| |
| setControlDocument(XML_RESOURCE); |
| setControlJSON(JSON_RESOURCE); |
| setClasses(new Class[] { Company.class, EmployeePointer.class }); |
| } |
| |
| @Override |
| public boolean isUnmarshalTest() { |
| return false; |
| } |
| |
| public void testEqualsUsingEqualsMethod() throws Exception { |
| Marshaller m = getJAXBMarshaller(); |
| |
| // Use equals() method for object comparison. |
| // Email's equals() always returns false, so Cycle cannot be detected. |
| // Expecting StackOverflowError. |
| m.setProperty("org.glassfish.jaxb.objectIdentitityCycleDetection", false); |
| |
| Email em1 = new Email(); em1.user = "me"; em1.domain = "here.com"; |
| Email em2 = new Email(); em2.user = "myself"; em2.domain = "overthere.co.uk"; |
| em1.forward = em2; em2.forward = em1; |
| |
| Throwable expectedException = null; |
| try { |
| m.marshal(em1, new ByteArrayOutputStream()); |
| } catch (Throwable ex) { |
| expectedException = ex; |
| } |
| |
| assertNotNull("No exception caught as expected.", expectedException); |
| assertEquals("Incorrect exception caught.", StackOverflowError.class, expectedException.getClass()); |
| |
| m.setProperty("org.glassfish.jaxb.objectIdentitityCycleDetection", true); |
| } |
| |
| public void testUnhandledCycle() throws Exception { |
| Company c = (Company) getControlObject(); |
| |
| Employee e = new Employee(); |
| e.id = 40; |
| e.name = "Fred Flintstone"; |
| ContactInfo info = new ContactInfo(); |
| Email em = new Email(); |
| em.user = "bcfred"; |
| em.domain = "slate.com"; |
| info.email = em; |
| |
| // Introduce unhandled cycle |
| em.parentInfo = info; |
| |
| e.contactInfos.add(info); |
| c.employees.add(e); |
| |
| // jakarta.xml.bind.MarshalException |
| // -> XMLMarshalException: An error occurred marshalling the object |
| // -> XMLMarshalException: A cycle is detected in the object graph. |
| XMLMarshalException expectedException = null; |
| try { |
| Marshaller m = getJAXBContext().createMarshaller(); |
| //m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); |
| //m.setProperty(JAXBMarshaller.MEDIA_TYPE, "application/json"); |
| //m.marshal(c, System.out); |
| m.marshal(c, new ByteArrayOutputStream()); |
| } catch (Exception ex) { |
| expectedException = (XMLMarshalException) ex.getCause(); |
| } |
| |
| assertNotNull("No exception caught as expected.", expectedException); |
| XMLMarshalException xmlMarshalException = expectedException; |
| assertEquals("Incorrect exception code.", xmlMarshalException.getErrorCode(), XMLMarshalException.OBJECT_CYCLE_DETECTED); |
| } |
| |
| @Override |
| protected Object getControlObject() { |
| Company c = new Company(); |
| c.name = "ACME Incorporated"; |
| |
| Employee e1 = new Employee(); |
| e1.id = 789; |
| e1.name = "Bob Smith"; |
| |
| Employee e2 = new Employee(); |
| e2.id = 1234; |
| e2.name = "Jane Doe"; |
| |
| ContactInfo info1 = new ContactInfo(); |
| Address a1 = new Address(); |
| a1.addressString = "123 Main St."; |
| info1.address = a1; |
| PhoneNumber p1 = new PhoneNumber(); |
| p1.number = 5551212; |
| info1.phoneNumber = p1; |
| e1.contactInfos.add(info1); |
| |
| ContactInfo info2 = new ContactInfo(); |
| Address a2 = new Address(); |
| a2.addressString = "727 Water St."; |
| info2.address = a2; |
| PhoneNumber p2 = new PhoneNumber(); |
| p2.number = 5551655; |
| info2.phoneNumber = p2; |
| e1.contactInfos.add(info2); |
| |
| ContactInfo info3 = new ContactInfo(); |
| Address a3 = new Address(); |
| a3.addressString = "711 Maple Ave."; |
| info3.address = a3; |
| PhoneNumber p3 = new PhoneNumber(); |
| p3.number = 5559876; |
| info3.phoneNumber = p3; |
| Email em3 = new Email(); |
| em3.user = "Jane.Doe"; |
| em3.domain = "oracle.com"; |
| info3.email = em3; |
| e2.contactInfos.add(info3); |
| |
| // Introduce object-cycles, which will be handled by |
| // Employee.onCycleDetected |
| p2.owningEmployee = e1; |
| p3.owningEmployee = e2; |
| |
| c.employees.add(e1); |
| c.employees.add(e2); |
| |
| return c; |
| } |
| |
| } |