private void internalCheck()

in wicket-core/src/main/java/org/apache/wicket/core/util/objects/checker/CheckingObjectOutputStream.java [357:552]


	private void internalCheck(Object obj)
	{
		final Object original = obj;
		Class<?> cls = obj.getClass();
		nameStack.add(simpleName);
		traceStack.add(new TraceSlot(obj, fieldDescription));

		for (IObjectChecker checker : checkers)
		{
			IObjectChecker.Result result = checker.check(obj);
			if (result.status == IObjectChecker.Result.Status.FAILURE)
			{
				String prettyPrintMessage = toPrettyPrintedStack(Classes.name(cls));
				String exceptionMessage = result.reason + '\n' + prettyPrintMessage;
				throw new ObjectCheckException(exceptionMessage, result.cause);
			}
		}

		ObjectStreamClass desc;
		for (;;)
		{
			try
			{
				desc = (ObjectStreamClass)LOOKUP_METHOD.invoke(null, cls, Boolean.TRUE);
				Class<?> repCl;
				if (!(Boolean)HAS_WRITE_REPLACE_METHOD_METHOD.invoke(desc, (Object[])null) ||
						(obj = INVOKE_WRITE_REPLACE_METHOD.invoke(desc, obj)) == null ||
						(repCl = obj.getClass()) == cls)
				{
					break;
				}
				cls = repCl;
			}
			catch (IllegalAccessException | InvocationTargetException e)
			{
				throw new RuntimeException(e);
			}
		}

		if (cls.isPrimitive())
		{
			// skip
		}
		else if (cls.isArray())
		{
			checked.put(original, null);
			Class<?> ccl = cls.getComponentType();
			if (!(ccl.isPrimitive()))
			{
				Object[] objs = (Object[])obj;
				for (int i = 0; i < objs.length; i++)
				{
					if (!isKnownToBeSerializable(objs[i])) {
						CharSequence arrayPos = new StringBuilder(4).append('[').append(i).append(']');
						simpleName = arrayPos;
						fieldDescription += arrayPos;
						check(objs[i]);
					}
				}
			}
		}
		else if (obj instanceof Externalizable && (!Proxy.isProxyClass(cls)))
		{
			Externalizable extObj = (Externalizable)obj;
			try
			{
				extObj.writeExternal(new ObjectOutputAdaptor()
				{
					private int count = 0;

					@Override
					public void writeObject(Object streamObj) throws IOException
					{
						// Check for circular reference.
						if (checked.containsKey(streamObj))
						{
							return;
						}

						CharSequence arrayPos = new StringBuilder(10).append("[write:").append(count++).append(']');
						simpleName = arrayPos;
						fieldDescription += arrayPos;

						check(streamObj);
						
						checked.put(streamObj, null);
					}
				});
			}
			catch (Exception e)
			{
				if (e instanceof ObjectCheckException)
				{
					throw (ObjectCheckException)e;
				}
				log.warn("Error delegating to Externalizable. Path: {}", currentPath(), e);
			}
		}
		else
		{
			Method writeObjectMethod = null;
			if (writeObjectMethodMissing.contains(cls) == false)
			{
				try
				{
					writeObjectMethod = cls.getDeclaredMethod("writeObject", java.io.ObjectOutputStream.class);
				}
				catch (SecurityException | NoSuchMethodException e)
				{
					// we can't access / set accessible to true
					writeObjectMethodMissing.add(cls);
				}
			}

			if (writeObjectMethod != null)
			{
				class InterceptingObjectOutputStream extends ObjectOutputStream
				{
					private int counter;

					InterceptingObjectOutputStream() throws IOException
					{
						super(DUMMY_OUTPUT_STREAM);
						enableReplaceObject(true);
					}

					@Override
					protected Object replaceObject(Object streamObj) throws IOException
					{
						if (streamObj == original)
						{
							return streamObj;
						}

						counter++;
						// Check for circular reference.
						if (checked.containsKey(streamObj))
						{
							return null;
						}

						CharSequence arrayPos = new StringBuilder(10).append("[write:").append(counter).append(']');
						simpleName = arrayPos;
						fieldDescription += arrayPos;
						check(streamObj);
						checked.put(streamObj, null);
						return streamObj;
					}
				}
				try
				{
					InterceptingObjectOutputStream ioos = new InterceptingObjectOutputStream();
					ioos.writeObject(obj);
				}
				catch (Exception e)
				{
					if (e instanceof ObjectCheckException)
					{
						throw (ObjectCheckException)e;
					}
					log.warn("error delegating to writeObject : {}, path: {}", e.getMessage(), currentPath());
				}
			}
			else
			{
				Object[] slots;
				try
				{
					slots = (Object[])GET_CLASS_DATA_LAYOUT_METHOD.invoke(desc, (Object[])null);
				}
				catch (Exception e)
				{
					throw new RuntimeException(e);
				}
				for (Object slot : slots)
				{
					ObjectStreamClass slotDesc;
					try
					{
						Field descField = slot.getClass().getDeclaredField("desc");
						descField.setAccessible(true);
						slotDesc = (ObjectStreamClass)descField.get(slot);
					}
					catch (Exception e)
					{
						throw new RuntimeException(e);
					}
					checked.put(original, null);
					checkFields(obj, slotDesc);
				}
			}
		}

		traceStack.removeLast();
		nameStack.removeLast();
	}