// Path: src/main/java/com/thoughtworks/go/strongauth/authentication/PrincipalDetail.java
// @Value
// public class PrincipalDetail {
//     private final String username;
//     private final String passwordHash;
//     private final String salt;
//     private final String hashConfiguration;
// }
// 
// Path: src/main/java/com/thoughtworks/go/strongauth/authentication/PrincipalDetailSource.java
// public interface PrincipalDetailSource {
//     Optional<PrincipalDetail> byUsername(String username);
// }
// 
// Path: src/main/java/com/thoughtworks/go/strongauth/util/Constants.java
// public class Constants {
//     public static final String PLUGIN_ID = "strongauth";
// }
// 
// Path: src/main/java/com/thoughtworks/go/strongauth/util/InputStreamSource.java
// public interface InputStreamSource {
// 
//     void addChangeListener(SourceChangeListener sourceChangeListener);
// 
//     InputStream inputStream() throws IOException;
// }
// 
// Path: src/main/java/com/thoughtworks/go/strongauth/util/io/SourceChangeEvent.java
// @Value
// public class SourceChangeEvent {
// 
//     private InputStream inputStream;
//     private String description;
// 
// }
// 
// Path: src/main/java/com/thoughtworks/go/strongauth/util/io/SourceChangeListener.java
// public interface SourceChangeListener {
//     void sourceChanged(final SourceChangeEvent event);
// }


import com.google.common.base.Optional;
import com.thoughtworks.go.plugin.api.logging.Logger;
import com.thoughtworks.go.strongauth.authentication.PrincipalDetail;
import com.thoughtworks.go.strongauth.authentication.PrincipalDetailSource;
import com.thoughtworks.go.strongauth.util.Constants;
import com.thoughtworks.go.strongauth.util.InputStreamSource;
import com.thoughtworks.go.strongauth.util.io.SourceChangeEvent;
import com.thoughtworks.go.strongauth.util.io.SourceChangeListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.String.format;
import static org.apache.commons.io.IOUtils.toBufferedReader;
package com.thoughtworks.go.strongauth.authentication.principalDetailSources;




public class ConfigurableUserPrincipalDetailSource implements PrincipalDetailSource {
    private final Map<String, PrincipalDetail> principalDetails = new HashMap<>();
    public static final Pattern DETAIL_PATTERN = Pattern.compile("^([^:]+):([^:]+):([^:]*):([^:]+)$");

    private static final Logger LOGGER = Logger.getLoggerFor(ConfigurableUserPrincipalDetailSource.class);
    public final String pluginId = Constants.PLUGIN_ID;

    public ConfigurableUserPrincipalDetailSource(InputStreamSource passwordSource) {
        try {
            loadSource(passwordSource.inputStream());
        } catch (IOException e) {
            LOGGER.warn("Missing password file. No credentials loaded.");
        }

        passwordSource.addChangeListener(new SourceChangeListener() {
            @Override
// Path: src/main/java/com/thoughtworks/go/strongauth/authentication/PrincipalDetail.java
// @Value
// public class PrincipalDetail {
//     private final String username;
//     private final String passwordHash;
//     private final String salt;
//     private final String hashConfiguration;
// }
// 
// Path: src/main/java/com/thoughtworks/go/strongauth/authentication/PrincipalDetailSource.java
// public interface PrincipalDetailSource {
//     Optional<PrincipalDetail> byUsername(String username);
// }
// 
// Path: src/main/java/com/thoughtworks/go/strongauth/util/Constants.java
// public class Constants {
//     public static final String PLUGIN_ID = "strongauth";
// }
// 
// Path: src/main/java/com/thoughtworks/go/strongauth/util/InputStreamSource.java
// public interface InputStreamSource {
// 
//     void addChangeListener(SourceChangeListener sourceChangeListener);
// 
//     InputStream inputStream() throws IOException;
// }
// 
// Path: src/main/java/com/thoughtworks/go/strongauth/util/io/SourceChangeEvent.java
// @Value
// public class SourceChangeEvent {
// 
//     private InputStream inputStream;
//     private String description;
// 
// }
// 
// Path: src/main/java/com/thoughtworks/go/strongauth/util/io/SourceChangeListener.java
// public interface SourceChangeListener {
//     void sourceChanged(final SourceChangeEvent event);
// }


// Path: src/main/java/com/thoughtworks/go/strongauth/authentication/principalDetailSources/ConfigurableUserPrincipalDetailSource.java
import com.google.common.base.Optional;
import com.thoughtworks.go.plugin.api.logging.Logger;
import com.thoughtworks.go.strongauth.authentication.PrincipalDetail;
import com.thoughtworks.go.strongauth.authentication.PrincipalDetailSource;
import com.thoughtworks.go.strongauth.util.Constants;
import com.thoughtworks.go.strongauth.util.InputStreamSource;
import com.thoughtworks.go.strongauth.util.io.SourceChangeEvent;
import com.thoughtworks.go.strongauth.util.io.SourceChangeListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.String.format;
import static org.apache.commons.io.IOUtils.toBufferedReader;

package com.thoughtworks.go.strongauth.authentication.principalDetailSources;




public class ConfigurableUserPrincipalDetailSource implements PrincipalDetailSource {
    private final Map<String, PrincipalDetail> principalDetails = new HashMap<>();
    public static final Pattern DETAIL_PATTERN = Pattern.compile("^([^:]+):([^:]+):([^:]*):([^:]+)$");

    private static final Logger LOGGER = Logger.getLoggerFor(ConfigurableUserPrincipalDetailSource.class);
    public final String pluginId = Constants.PLUGIN_ID;

    public ConfigurableUserPrincipalDetailSource(InputStreamSource passwordSource) {
        try {
            loadSource(passwordSource.inputStream());
        } catch (IOException e) {
            LOGGER.warn("Missing password file. No credentials loaded.");
        }

        passwordSource.addChangeListener(new SourceChangeListener() {
            @Override
            public void sourceChanged(SourceChangeEvent event) {