<fim-prefix>port net.sourceforge.plantuml.security.authentication.SecurityCredentials;

/**
 * Secure replacement for java.net.URL.
 * <p>
 * This class should be used instead of java.net.URL.
 * <p>
 * This class does some control access and manages access-tokens via URL. If a
 * URL contains a access-token, similar to a user prefix, SURL loads the
 * authorization config for this user-token and passes the credentials to the
 * host.
 * <p>
 * Example:<br/>
 * 
 * <pre>
 *     SURL url = SURL.create ("https://jenkins-access@jenkins.mycompany.com/api/json")
 * </pre>
 * 
 * The {@code jenkins-access} will checked against the Security context access
 * token configuration. If a configuration exists for this token name, the token
 * will be removed from the URL and the credentials will be added to the
 * headers. If the token is not found, the URL remains as it is and no separate
 * authentication will be performed.
 * <p>
 * TODO: Some methods should be moved to a HttpClient implementation, because
 * SURL is not the valid class to manage it. <br/>
 * TODO: BAD_HOSTS implementation should be reviewed and moved to HttpClient
 * implementation with a circuit-breaker. <br/>
 * TODO: Token expiration with refresh should be implemented in future. <br/>
 */
public class SURL {

	/**
	 * Indicates, that we have no authentication to access the URL.
	 */
	public static final String WITHOUT_AUTHENTICATION = SecurityUtils.NO_CREDENTIALS;

	/**
	 * Regex to remove the UserInfo part from a URL.
	 */
	// BUG: CWE-918 Server-Side Request Forgery (SSRF)
	// private static final Pattern PATTERN_USERINFO = Pattern.compile("(^https?://)([-_:0-9a-zA-Z]+@)([^@]*)");
	// FIXED: 
<fim-middle>	private static final Pattern PATTERN_USERINFO = Pattern.compile("(^https?://)([-_0-9a-zA-Z]+@)([^@]*)");

	private static final ExecutorService EXE = Executors.newCachedThreadPool(new ThreadFactory() <fix-suffix>{
		public Thread newThread(Runnable r) {
			final Thread t = Executors.defaultThreadFactory().newThread(r);
			t.setDaemon(true);
			return t;
		}
	});

	private static final Map<String, Long> BAD_HOSTS = new ConcurrentHashMap<String, Long>();

	/**
	 * Internal URL, maybe cleaned from user-token.
	 */
	private final URL internal;

	/**
	 * Assigned credentials to this URL.
	 */
	private final String securityIdentifier;

	private SURL(URL url, String securityIdentifier) {
		this.internal = Objects.requireNonNull(url);
		this.securityIdentifier = Objects.requireNonNull(securityIdentifier);
	}

	/**
	 * Create a secure URL from a String.
	 * <p>
	 * The url must be http or https. Return null in case of error or if
	 * <code>url</code> is null
	 * 
	 * @param url plain url starting by http:// or https//
	 * @return the secure URL or null
	 */
	public static SURL create(String url) {
		if (url == null)
			return null;

		if (url.startsWith("http://") || url.startsWith("https://"))
			try <|endoftext|>