/*
 * Copyright 2018 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.cloud.config.server.support;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jgit.errors.UnsupportedCredentialItem;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.transport.CredentialItem;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.URIish;

/**
 * A {@link CredentialsProvider} that will ignore any SSL validation errors that occur.
 * This is primarily intended as a convenience for testing scenarios where self-signed
 * certificates are being used.
 *
 * This class can be used as a decorator for another CredentialsProvider, adding SSL
 * validation skipping behaviour to a repository that also requires authentication, for
 * example.
 *
 * @author Gareth Clay
 */
public class GitSkipSslValidationCredentialsProvider extends CredentialsProvider {

	private final CredentialsProvider delegate;

	public GitSkipSslValidationCredentialsProvider(CredentialsProvider delegate) {
		this.delegate = delegate;
	}

	/**
	 * This provider can handle uris like https://github.com/org/repo
	 */
	public static boolean canHandle(String uri) {
		return uri != null && uri.toLowerCase().startsWith("https://");
	}

	@Override
	public boolean isInteractive() {
		return (delegate != null) && delegate.isInteractive();
	}

	@Override
	public boolean supports(CredentialItem... items) {
		List<CredentialItem> unprocessedItems = new ArrayList<>();

		for (CredentialItem item : items) {
			if (item instanceof CredentialItem.InformationalMessage
					&& item.getPromptText() != null && item.getPromptText()
							.contains(JGitText.get().sslFailureTrustExplanation))
				continue;

			if (item instanceof CredentialItem.YesNoType && item.getPromptText() != null
					&& (item.getPromptText().equals(JGitText.get().sslTrustNow)
							|| item.getPromptText()
									.startsWith(stripFormattingPlaceholders(
											JGitText.get().sslTrustForRepo))
							|| item.getPromptText()
									.equals(JGitText.get().sslTrustAlways)))
				continue;

			unprocessedItems.add(item);
		}

		return unprocessedItems.isEmpty() || (delegate != null
				&& delegate.supports(unprocessedItems.toArray(new CredentialItem[0])));
	}

	@Override
	public boolean get(URIish uri, CredentialItem... items)
			throws UnsupportedCredentialItem {
		List<CredentialItem> unprocessedItems = new ArrayList<>();

		for (CredentialItem item : items) {
			if (item instanceof CredentialItem.YesNoType) {
				CredentialItem.YesNoType yesNoItem = (CredentialItem.YesNoType) item;
				String prompt = yesNoItem.getPromptText();
				if (prompt == null) {
					unprocessedItems.add(item);
				}
				else if (prompt.equals(JGitText.get().sslTrustNow) || prompt.startsWith(
						stripFormattingPlaceholders(JGitText.get().sslTrustForRepo))) {
					yesNoItem.setValue(true);
				}
				else if (prompt.equals(JGitText.get().sslTrustAlways)) {
					yesNoItem.setValue(false);
				}
				else {
					unprocessedItems.add(item);
				}
			}
			else if (!item.getPromptText()
					.contains(JGitText.get().sslFailureTrustExplanation)) {
				unprocessedItems.add(item);
			}
		}

		if (unprocessedItems.isEmpty()) {
			return true;
		}
		if (delegate != null) {
			return delegate.get(uri, unprocessedItems.toArray(new CredentialItem[0]));
		}
		throw new UnsupportedCredentialItem(uri,
				unprocessedItems.size() + " credential items not supported");
	}

	@Override
	public void reset(URIish uri) {
		if (delegate != null) {
			delegate.reset(uri);
		}
	}

	private static String stripFormattingPlaceholders(String string) {
		return string.replaceAll("\\s*\\{\\d}\\s*", "");
	}
}

@@ -717,16 +717,48 @@
 il.List;
+%0Aimport java.util.regex.Pattern;
 %0A%0Aimport
@@ -1513,16 +1513,112 @@
 ider %7B%0A%0A
+%09private static final Pattern FORMAT_PLACEHOLDER_PATTERN = Pattern.compile(%22%5C%5Cs*%5C%5C%7B%5C%5Cd%7D%5C%5Cs*%22);%0A%0A
 %09private
@@ -4339,22 +4339,58 @@
 %09return 
+FORMAT_PLACEHOLDER_PATTERN.matcher(
 string
+)
 .replace
@@ -4397,27 +4397,8 @@
 All(
-%22%5C%5Cs*%5C%5C%7B%5C%5Cd%7D%5C%5Cs*%22, 
 %22%22);

Refactor String#replaceAll (#1146)