/*
 * Copyright 2012-2017 the original author or authors.
 *
 * 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 org.springframework.boot.test.json;

import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.test.context.MergedContextConfiguration;

/**
 * A {@link ContextCustomizerFactory} that produces a {@link ContextCustomizer} that warns
 * the user when multiple occurrences of {@code JSONObject} are found on the class path.
 *
 * @author Andy Wilkinson
 */
class DuplicateJsonObjectContextCustomizerFactory implements ContextCustomizerFactory {

	@Override
	public ContextCustomizer createContextCustomizer(Class<?> testClass,
			List<ContextConfigurationAttributes> configAttributes) {
		return new DuplicateJsonObjectContextCustomizer();
	}

	private static class DuplicateJsonObjectContextCustomizer
			implements ContextCustomizer {

		private final Log logger = LogFactory
				.getLog(DuplicateJsonObjectContextCustomizer.class);

		@Override
		public void customizeContext(ConfigurableApplicationContext context,
				MergedContextConfiguration mergedConfig) {
			List<URL> jsonObjects = findJsonObjects();
			if (jsonObjects.size() > 1) {
				logDuplicateJsonObjectsWarning(jsonObjects);
			}
		}

		private List<URL> findJsonObjects() {
			List<URL> jsonObjects = new ArrayList<URL>();
			try {
				Enumeration<URL> resources = getClass().getClassLoader()
						.getResources("org/json/JSONObject.class");
				while (resources.hasMoreElements()) {
					jsonObjects.add(resources.nextElement());
				}
			}
			catch (Exception ex) {
				// Continue
			}
			return jsonObjects;
		}

		private void logDuplicateJsonObjectsWarning(List<URL> jsonObjects) {
			StringBuilder message = new StringBuilder("\n\nFound multiple occurrences of"
					+ " org.json.JSONObject on the class path:\n\n");
			for (URL jsonObject : jsonObjects) {
				message.append("\t" + jsonObject + "\n");
			}
			message.append("\nYou may wish to exclude one of them to ensure"
					+ " predictable runtime behaviour\n");
			this.logger.warn(message);
		}

		@Override
		public int hashCode() {
			return getClass().hashCode();
		}

		@Override
		public boolean equals(Object obj) {
			if (obj == null || obj.getClass() != getClass()) {
				return false;
			}
			return true;
		}

	}

}

@@ -2650,12 +2650,26 @@
 der(
-%22%5Cn%5C
+String.format(%22%25n%25
 nFou
@@ -2747,14 +2747,15 @@
 ath:
-%5Cn%5C
+%25n%25
 n%22)
+)
 ;%0A%09%09
@@ -2815,14 +2815,31 @@
 end(
-%22%5Ct%22 +
+String.format(%22%5Ct%25s%25n%22,
  jso
@@ -2849,15 +2849,9 @@
 ject
- + %22%5Cn%22
+)
 );%0A%09
@@ -2872,18 +2872,32 @@
 .append(
-%22%5C
+String.format(%22%25
 nYou may
@@ -2976,14 +2976,14 @@
 avio
-ur%5C
+r%25
 n%22)
+)
 ;%0A%09%09

Use the platform-specific line separator