/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play.db.jpa;

import com.typesafe.config.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.db.DBApi;
import play.inject.ApplicationLifecycle;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.persistence.*;

/** Default implementation of the JPA API. */
public class DefaultJPAApi implements JPAApi {

  private static final Logger logger = LoggerFactory.getLogger(DefaultJPAApi.class);

  private final JPAConfig jpaConfig;

  private final Map<String, EntityManagerFactory> emfs = new HashMap<>();

  private final JPAEntityManagerContext entityManagerContext;

  /** @deprecated Deprecated as of 2.7.0. Use {@link #DefaultJPAApi(JPAConfig)} instead. */
  @Deprecated
  public DefaultJPAApi(JPAConfig jpaConfig, JPAEntityManagerContext entityManagerContext) {
    this.jpaConfig = jpaConfig;
    this.entityManagerContext = entityManagerContext;
  }

  public DefaultJPAApi(JPAConfig jpaConfig) {
    this(jpaConfig, null);
  }

  @Singleton
  public static class JPAApiProvider implements Provider<JPAApi> {
    private final JPAApi jpaApi;

    /**
     * @deprecated Deprecated as of 2.7.0. Use {@link #JPAApiProvider(JPAConfig,
     *     ApplicationLifecycle, DBApi, Config)} instead.
     */
    @Inject
    @Deprecated
    public JPAApiProvider(
        JPAConfig jpaConfig,
        JPAEntityManagerContext context,
        ApplicationLifecycle lifecycle,
        DBApi dbApi,
        Config config) {
      // dependency on db api ensures that the databases are initialised
      jpaApi =
          new DefaultJPAApi(
              jpaConfig,
              config.getBoolean("play.jpa.allowJPAEntityManagerContext") ? context : null);
      lifecycle.addStopHook(
          () -> {
            jpaApi.shutdown();
            return CompletableFuture.completedFuture(null);
          });
      jpaApi.start();
    }

    public JPAApiProvider(
        JPAConfig jpaConfig, ApplicationLifecycle lifecycle, DBApi dbApi, Config config) {
      this(jpaConfig, null, lifecycle, dbApi, config);
    }

    @Override
    public JPAApi get() {
      return jpaApi;
    }
  }

  /** Initialise JPA entity manager factories. */
  public JPAApi start() {
    jpaConfig
        .persistenceUnits()
        .forEach(
            persistenceUnit ->
                emfs.put(
                    persistenceUnit.name,
                    Persistence.createEntityManagerFactory(persistenceUnit.unitName)));
    return this;
  }

  /**
   * Get a newly created EntityManager for the specified persistence unit name.
   *
   * @param name The persistence unit name
   */
  public EntityManager em(String name) {
    EntityManagerFactory emf = emfs.get(name);
    if (emf == null) {
      return null;
    }
    return emf.createEntityManager();
  }

  /**
   * Get the EntityManager for a particular persistence unit for this thread.
   *
   * @return EntityManager for the specified persistence unit name
   * @deprecated Deprecated as of 2.7.0. The EntityManager is supplied as lambda parameter instead
   *     when using {@link #withTransaction(Function)}
   */
  @Deprecated
  public EntityManager em() {
    if (entityManagerContext == null) {
      throw new RuntimeException(
          "EntityManager can't be acquired from a thread-local. You should instead use one of the JPAApi methods where the EntityManager is provided automatically.");
    }
    return entityManagerContext.em();
  }

  /**
   * Run a block of code with a newly created EntityManager for the default Persistence Unit.
   *
   * @param block Block of code to execute
   * @param <T> type of result
   * @return code execution result
   */
  public <T> T withTransaction(Function<EntityManager, T> block) {
    return withTransaction("default", block);
  }

  /**
   * Run a block of code with a newly created EntityManager for the default Persistence Unit.
   *
   * @param block Block of code to execute
   */
  public void withTransaction(Consumer<EntityManager> block) {
    withTransaction(
        em -> {
          block.accept(em);
          return null;
        });
  }

  /**
   * Run a block of code with a newly created EntityManager for the named Persistence Unit.
   *
   * @param name The persistence unit name
   * @param block Block of code to execute
   * @param <T> type of result
   * @return code execution result
   */
  public <T> T withTransaction(String name, Function<EntityManager, T> block) {
    return withTransaction(name, false, block);
  }

  /**
   * Run a block of code with a newly created EntityManager for the named Persistence Unit.
   *
   * @param name The persistence unit name
   * @param block Block of code to execute
   */
  public void withTransaction(String name, Consumer<EntityManager> block) {
    withTransaction(
        name,
        em -> {
          block.accept(em);
          return null;
        });
  }

  /**
   * Run a block of code with a newly created EntityManager for the named Persistence Unit.
   *
   * @param name The persistence unit name
   * @param readOnly Is the transaction read-only?
   * @param block Block of code to execute
   * @param <T> type of result
   * @return code execution result
   */
  public <T> T withTransaction(String name, boolean readOnly, Function<EntityManager, T> block) {
    EntityManager entityManager = null;
    EntityTransaction tx = null;

    try {
      entityManager = em(name);

      if (entityManager == null) {
        throw new RuntimeException("Could not create JPA entity manager for '" + name + "'");
      }

      if (entityManagerContext != null) {
        entityManagerContext.push(entityManager, true);
      }

      if (!readOnly) {
        tx = entityManager.getTransaction();
        tx.begin();
      }

      T result = block.apply(entityManager);

      if (tx != null) {
        if (tx.getRollbackOnly()) {
          tx.rollback();
        } else {
          tx.commit();
        }
      }

      return result;

    } catch (Throwable t) {
      if (tx != null) {
        try {
          if (tx.isActive()) {
            tx.rollback();
          }
        } catch (Exception e) {
          logger.error("Could not rollback transaction", e);
        }
      }
      throw t;
    } finally {
      if (entityManager != null) {
        if (entityManagerContext != null) {
          entityManagerContext.pop(true);
        }
        entityManager.close();
      }
    }
  }

  /**
   * Run a block of code with a newly created EntityManager for the named Persistence Unit.
   *
   * @param name The persistence unit name
   * @param readOnly Is the transaction read-only?
   * @param block Block of code to execute
   */
  public void withTransaction(String name, boolean readOnly, Consumer<EntityManager> block) {
    withTransaction(
        name,
        readOnly,
        em -> {
          block.accept(em);
          return null;
        });
  }

  /**
   * Run a block of code in a JPA transaction.
   *
   * @param block Block of code to execute
   * @deprecated Deprecated as of 2.7.0. Use {@link #withTransaction(Function)} instead.
   */
  @Deprecated
  public <T> T withTransaction(Supplier<T> block) {
    return withTransaction("default", false, block);
  }

  /**
   * Run a block of code in a JPA transaction.
   *
   * @param block Block of code to execute
   * @deprecated Deprecated as of 2.7.0. Use {@link #withTransaction(Consumer)} instead.
   */
  @Deprecated
  public void withTransaction(final Runnable block) {
    try {
      withTransaction(
          () -> {
            block.run();
            return null;
          });
    } catch (Throwable t) {
      throw new RuntimeException("JPA transaction failed", t);
    }
  }

  /**
   * Run a block of code in a JPA transaction.
   *
   * @param name The persistence unit name
   * @param readOnly Is the transaction read-only?
   * @param block Block of code to execute
   * @deprecated Deprecated as of 2.7.0. Use {@link #withTransaction(String, boolean, Function)}
   *     instead.
   */
  @Deprecated
  public <T> T withTransaction(String name, boolean readOnly, Supplier<T> block) {
    return withTransaction(
        name,
        readOnly,
        entityManager -> {
          return block.get();
        });
  }

  /** Close all entity manager factories. */
  public void shutdown() {
    emfs.values().forEach(EntityManagerFactory::close);
  }
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play.i18n;

import play.libs.Scala;
import play.mvc.Http;
import play.mvc.Result;
import scala.collection.immutable.Seq;
import scala.collection.mutable.Buffer;
import scala.compat.java8.OptionConverters;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

/** The messages API. */
@Singleton
public class MessagesApi {

  private final play.api.i18n.MessagesApi messages;

  @Inject
  public MessagesApi(play.api.i18n.MessagesApi messages) {
    this.messages = messages;
  }

  /** @return the Scala versions of the Messages API. */
  public play.api.i18n.MessagesApi asScala() {
    return messages;
  }

  /**
   * Converts the varargs to a scala buffer, takes care of wrapping varargs into a intermediate list
   * if necessary
   *
   * @param args the message arguments
   * @return scala type for message processing
   */
  private static Seq<Object> convertArgsToScalaBuffer(final Object... args) {
    return scala.collection.JavaConverters.asScalaBufferConverter(wrapArgsToListIfNeeded(args))
        .asScala()
        .toList();
  }

  /**
   * Wraps arguments passed into a list if necessary.
   *
   *
Returns the first value as is if it is the only argument and a subtype of `java.util.List`
   * Otherwise, it calls Arrays.asList on args
   *
   * @param args arguments as a List
   */
  @SafeVarargs
  private static <T> List<T> wrapArgsToListIfNeeded(final T... args) {
    List<T> out;
    if (args != null && args.length == 1 && args[0] instanceof List) {
      out = (List<T>) args[0];
    } else {
      out = Arrays.asList(args);
    }
    return out;
  }

  /**
   * Translates a message.
   *
   *
Uses `java.text.MessageFormat` internally to format the message.
   *
   * @param lang the message lang
   * @param key the message key
   * @param args the message arguments
   * @return the formatted message or a default rendering if the key wasn't defined
   */
  public String get(play.api.i18n.Lang lang, String key, Object... args) {
    Seq<Object> scalaArgs = convertArgsToScalaBuffer(args);
    return messages.apply(key, scalaArgs, lang);
  }

  /**
   * Translates the first defined message.
   *
   *
Uses `java.text.MessageFormat` internally to format the message.
   *
   * @param lang the message lang
   * @param keys the messages keys
   * @param args the message arguments
   * @return the formatted message or a default rendering if the key wasn't defined
   */
  public String get(play.api.i18n.Lang lang, List<String> keys, Object... args) {
    Buffer<String> keyArgs = scala.collection.JavaConverters.asScalaBufferConverter(keys).asScala();
    Seq<Object> scalaArgs = convertArgsToScalaBuffer(args);
    return messages.apply(keyArgs.toSeq(), scalaArgs, lang);
  }

  /**
   * Check if a message key is defined.
   *
   * @param lang the message lang
   * @param key the message key
   * @return a Boolean
   */
  public Boolean isDefinedAt(play.api.i18n.Lang lang, String key) {
    return messages.isDefinedAt(key, lang);
  }

  /**
   * Get a messages context appropriate for the given candidates.
   *
   *
Will select a language from the candidates, based on the languages available, and fallback
   * to the default language if none of the candidates are available.
   *
   * @param candidates the candidate languages
   * @return the most appropriate Messages instance given the candidate languages
   */
  public Messages preferred(Collection<Lang> candidates) {
    Seq<Lang> cs = Scala.asScala(candidates);
    play.api.i18n.Messages msgs = messages.preferred((Seq) cs);
    return new MessagesImpl(new Lang(msgs.lang()), this);
  }

  /**
   * Get a messages context appropriate for the given request.
   *
   *
Will select a language from the request, based on the languages available, and fallback to
   * the default language if none of the candidates are available.
   *
   * @param request the incoming request
   * @return the preferred messages context for the request
   */
  public Messages preferred(Http.RequestHeader request) {
    play.api.i18n.Messages msgs = messages.preferred(request);
    return new MessagesImpl(new Lang(msgs.lang()), this);
  }

  /**
   * Given a Result and a Lang, return a new Result with the lang cookie set to the given Lang.
   *
   * @param result the result where the lang will be set.
   * @param lang the lang to set on the result
   * @return a new result with the lang.
   */
  public Result setLang(Result result, Lang lang) {
    return messages.setLang(result.asScala(), lang).asJava();
  }

  /**
   * Given a Result, return a new Result with the lang cookie discarded.
   *
   * @param result the result to clear the lang.
   * @return a new result with a cleared lang.
   */
  public Result clearLang(Result result) {
    return messages.clearLang(result.asScala()).asJava();
  }

  public String langCookieName() {
    return messages.langCookieName();
  }

  public boolean langCookieSecure() {
    return messages.langCookieSecure();
  }

  public boolean langCookieHttpOnly() {
    return messages.langCookieHttpOnly();
  }

  public Optional<Http.Cookie.SameSite> langCookieSameSite() {
    return OptionConverters.toJava(messages.langCookieSameSite())
        .map(sameSite -> sameSite.asJava());
  }
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play.inject.guice;

import com.google.common.collect.ImmutableMap;
import com.google.inject.Module;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import play.Environment;
import play.Mode;
import play.api.inject.guice.GuiceableModule;
import play.inject.Injector;
import play.libs.Scala;

import java.io.File;
import java.util.Map;

/**
 * A builder for creating Guice-backed Play Injectors.
 *
 * @param <Self> the concrete type that is extending this class
 * @param <Delegate> a scala GuiceBuilder type.
 */
public abstract class GuiceBuilder<
    Self, Delegate extends play.api.inject.guice.GuiceBuilder<Delegate>> {

  protected Delegate delegate;

  protected GuiceBuilder(Delegate delegate) {
    this.delegate = delegate;
  }

  /**
   * Set the environment.
   *
   * @param env the environment to configure into this application
   * @return a copy of this builder with the new environment
   */
  public final Self in(Environment env) {
    return newBuilder(delegate.in(env.asScala()));
  }

  /**
   * Set the environment path.
   *
   * @param path the path to configure
   * @return a copy of this builder with the new path
   */
  public final Self in(File path) {
    return newBuilder(delegate.in(path));
  }

  /**
   * Set the environment mode.
   *
   * @param mode the mode to configure
   * @return a copy of this build configured with this mode
   */
  public final Self in(Mode mode) {
    return newBuilder(delegate.in(mode.asScala()));
  }

  /**
   * Set the environment class loader.
   *
   * @param classLoader the class loader to use
   * @return a copy of this builder configured with the class loader
   */
  public final Self in(ClassLoader classLoader) {
    return newBuilder(delegate.in(classLoader));
  }

  /**
   * Add additional configuration.
   *
   * @param conf the configuration to add
   * @return a copy of this builder configured with the supplied configuration
   */
  public final Self configure(Config conf) {
    return newBuilder(delegate.configure(new play.api.Configuration(conf)));
  }

  /**
   * Add additional configuration.
   *
   * @param conf the configuration to add
   * @return a copy of this builder configured with the supplied configuration
   */
  public final Self configure(Map<String, Object> conf) {
    return configure(ConfigFactory.parseMap(conf));
  }

  /**
   * Add additional configuration.
   *
   * @param key a configuration key to set
   * @param value the associated value for key
   * @return a copy of this builder configured with the key=value
   */
  public final Self configure(String key, Object value) {
    return configure(ImmutableMap.of(key, value));
  }

  /**
   * Add bindings from guiceable modules.
   *
   * @param modules the set of modules to bind
   * @return a copy of this builder configured with those modules
   */
  public final Self bindings(GuiceableModule... modules) {
    return newBuilder(delegate.bindings(Scala.varargs(modules)));
  }

  /**
   * Add bindings from Guice modules.
   *
   * @param modules the set of Guice modules whose bindings to apply
   * @return a copy of this builder configured with the provided bindings
   */
  public final Self bindings(Module... modules) {
    return bindings(Guiceable.modules(modules));
  }

  /**
   * Add bindings from Play modules.
   *
   * @param modules the set of Guice modules whose bindings to apply
   * @return a copy of this builder configured with the provided bindings
   */
  public final Self bindings(play.api.inject.Module... modules) {
    return bindings(Guiceable.modules(modules));
  }

  /**
   * Add Play bindings.
   *
   * @param bindings the set of play bindings to apply
   * @return a copy of this builder configured with the provided bindings
   */
  public final Self bindings(play.api.inject.Binding<?>... bindings) {
    return bindings(Guiceable.bindings(bindings));
  }

  /**
   * Override bindings using guiceable modules.
   *
   * @param modules the set of Guice modules whose bindings override some previously configured ones
   * @return a copy of this builder re-configured with the provided bindings
   */
  public final Self overrides(GuiceableModule... modules) {
    return newBuilder(delegate.overrides(Scala.varargs(modules)));
  }

  /**
   * Override bindings using Guice modules.
   *
   * @param modules the set of Guice modules whose bindings override some previously configured ones
   * @return a copy of this builder re-configured with the provided bindings
   */
  public final Self overrides(Module... modules) {
    return overrides(Guiceable.modules(modules));
  }

  /**
   * Override bindings using Play modules.
   *
   * @param modules the set of Play modules whose bindings override some previously configured ones
   * @return a copy of this builder re-configured with the provided bindings
   */
  public final Self overrides(play.api.inject.Module... modules) {
    return overrides(Guiceable.modules(modules));
  }

  /**
   * Override bindings using Play bindings.
   *
   * @param bindings a set of Play bindings that override some previously configured ones
   * @return a copy of this builder re-configured with the provided bindings
   */
  public final Self overrides(play.api.inject.Binding<?>... bindings) {
    return overrides(Guiceable.bindings(bindings));
  }

  /**
   * Disable modules by class.
   *
   * @param moduleClasses the module classes whose bindings should be disabled
   * @return a copy of this builder configured to ignore the provided module classes
   */
  public final Self disable(Class<?>... moduleClasses) {
    return newBuilder(delegate.disable(Scala.toSeq(moduleClasses)));
  }

  /**
   * Create a Guice module that can be used to inject an Application.
   *
   * @return the module
   */
  public Module applicationModule() {
    return delegate.applicationModule();
  }

  /**
   * Create a Play Injector backed by Guice using this configured builder.
   *
   * @return the injector
   */
  public Injector injector() {
    return delegate.injector().instanceOf(Injector.class);
  }

  protected abstract Self newBuilder(Delegate delegate);
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play.mvc;

import java.lang.reflect.AnnotatedElement;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletionStage;

import play.core.j.JavaContextComponents;
import play.libs.typedmap.TypedKey;
import play.mvc.Http.Context;
import play.mvc.Http.Request;

import javax.inject.Inject;

/** An action acts as decorator for the action method call. */
public abstract class Action<T> extends Results {

  private JavaContextComponents contextComponents;

  @Inject
  public void setContextComponents(JavaContextComponents contextComponents) {
    this.contextComponents = contextComponents;
  }

  /** The action configuration - typically the annotation used to decorate the action method. */
  public T configuration;

  /** Where an action was defined. */
  public AnnotatedElement annotatedElement;

  /**
   * The precursor action.
   *
   *
If this action was called in a chain then this will contain the value of the action that is
   * called before this action. If no action was called first, then this value will be null.
   */
  public Action<?> precursor;

  /**
   * The wrapped action.
   *
   *
If this action was called in a chain then this will contain the value of the action that is
   * called after this action. If there is no action left to be called, then this value will be
   * null.
   */
  public Action<?> delegate;

  private static final TypedKey<Map<String, Object>> CTX_ARGS =
      TypedKey.<Map<String, Object>>create("http-context-args");

  /**
   * Executes this action with the given HTTP context and returns the result.
   *
   * @param ctx the http context in which to execute this action
   * @return a promise to the action's result
   * @deprecated Since 2.7.0. Use {@link #call(Request)} instead. Please see the
   *     migration guide for more details.
   */
  @Deprecated // TODO: When you remove this method make call(Request) below abstract
  public CompletionStage<Result> call(Context ctx) {
    return call(
        ctx.args != null && !ctx.args.isEmpty()
            ? ctx.request().addAttr(CTX_ARGS, ctx.args)
            : ctx.request());
  }

  /**
   * Executes this action with the given HTTP request and returns the result.
   *
   * @param req the http request with which to execute this action
   * @return a promise to the action's result
   */
  public CompletionStage<Result> call(
      Request req) { // TODO: Make this method abstract after removing call(Context)
    return Context.safeCurrent()
        .map(
            threadLocalCtx -> {
              // A previous action did explicitly set a context onto the thread local (via
              // Http.Context.current.set(...))
              // Let's use that context so the user doesn't loose data he/she set onto that ctx
              // (args,...)
              Context newCtx = threadLocalCtx.withRequest(req.removeAttr(CTX_ARGS));
              Context.setCurrent(newCtx);
              return call(newCtx);
            })
        .orElseGet(
            () -> {
              // A previous action did not set a context explicitly, we simply create a new one to
              // pass on the request
              Context ctx = new Context(req.removeAttr(CTX_ARGS), contextComponents);
              ctx.args = req.attrs().getOptional(CTX_ARGS).orElse(new HashMap<>());
              return call(ctx);
            });
  }

  /** A simple action with no configuration. */
  public abstract static class Simple extends Action<Void> {}
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play;

import play.libs.Scala;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Optional;

import scala.compat.java8.OptionConverters;

/**
 * The environment for the application.
 *
 *
Captures concerns relating to the classloader and the filesystem for the application.
 */
@Singleton
public class Environment {
  private final play.api.Environment env;

  @Inject
  public Environment(play.api.Environment environment) {
    this.env = environment;
  }

  public Environment(File rootPath, ClassLoader classLoader, Mode mode) {
    this(new play.api.Environment(rootPath, classLoader, mode.asScala()));
  }

  public Environment(File rootPath, Mode mode) {
    this(rootPath, Environment.class.getClassLoader(), mode);
  }

  public Environment(File rootPath) {
    this(rootPath, Environment.class.getClassLoader(), Mode.TEST);
  }

  public Environment(Mode mode) {
    this(new File("."), Environment.class.getClassLoader(), mode);
  }

  /**
   * The root path that the application is deployed at.
   *
   * @return the path
   */
  public File rootPath() {
    return env.rootPath();
  }

  /**
   * The classloader that all application classes and resources can be loaded from.
   *
   * @return the class loader
   */
  public ClassLoader classLoader() {
    return env.classLoader();
  }

  /**
   * The mode of the application.
   *
   * @return the mode
   */
  public Mode mode() {
    return env.mode().asJava();
  }

  /**
   * Returns `true` if the application is `DEV` mode.
   *
   * @return `true` if the application is `DEV` mode.
   */
  public boolean isDev() {
    return mode().equals(Mode.DEV);
  }

  /**
   * Returns `true` if the application is `PROD` mode.
   *
   * @return `true` if the application is `PROD` mode.
   */
  public boolean isProd() {
    return mode().equals(Mode.PROD);
  }

  /**
   * Returns `true` if the application is `TEST` mode.
   *
   * @return `true` if the application is `TEST` mode.
   */
  public boolean isTest() {
    return mode().equals(Mode.TEST);
  }

  /**
   * Retrieves a file relative to the application root path.
   *
   * @param relativePath relative path of the file to fetch
   * @return a file instance - it is not guaranteed that the file exists
   */
  public File getFile(String relativePath) {
    return env.getFile(relativePath);
  }

  /**
   * Retrieves a file relative to the application root path. This method returns an Optional, using
   * empty if the file was not found.
   *
   * @param relativePath relative path of the file to fetch
   * @return an existing file
   */
  public Optional<File> getExistingFile(String relativePath) {
    return OptionConverters.toJava(env.getExistingFile(relativePath));
  }

  /**
   * Retrieves a resource from the classpath.
   *
   * @param relativePath relative path of the resource to fetch
   * @return URL to the resource (may be null)
   */
  public URL resource(String relativePath) {
    return Scala.orNull(env.resource(relativePath));
  }

  /**
   * Retrieves a resource stream from the classpath.
   *
   * @param relativePath relative path of the resource to fetch
   * @return InputStream to the resource (may be null)
   */
  public InputStream resourceAsStream(String relativePath) {
    return Scala.orNull(env.resourceAsStream(relativePath));
  }

  /**
   * A simple environment.
   *
   *
Uses the same classloader that the environment classloader is defined in, the current
   * working directory as the path and test mode.
   *
   * @return the environment
   */
  public static Environment simple() {
    return new Environment(new File("."), Environment.class.getClassLoader(), Mode.TEST);
  }

  /**
   * The underlying Scala API Environment object that this Environment wraps.
   *
   * @return the environment
   * @see play.api.Environment
   */
  public play.api.Environment asScala() {
    return env;
  }
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play.inject;

import scala.compat.java8.OptionConverters;

import java.lang.annotation.Annotation;
import java.util.Optional;

/**
 * A binding.
 *
 *
Bindings are used to bind classes, optionally qualified by a JSR-330 qualifier annotation, to
 * instances, providers or implementation classes.
 *
 *
Bindings may also specify a JSR-330 scope. If, and only if that scope is javax.inject.Singleton,
 * then the binding may declare itself to be eagerly instantiated. In which case, it should be
 * eagerly instantiated when Play starts up.
 *
 *
See the {@link Module} class for information on how to provide bindings.
 */
public final class Binding<T> {
  private final play.api.inject.Binding<T> underlying;

  /**
   * @param key The binding key.
   * @param target The binding target.
   * @param scope The JSR-330 scope.
   * @param eager Whether the binding should be eagerly instantiated.
   * @param source Where this object was bound. Used in error reporting.
   */
  public Binding(
      final BindingKey<T> key,
      final Optional<BindingTarget<T>> target,
      final Optional<Class<? extends Annotation>> scope,
      final Boolean eager,
      final Object source) {
    this(
        play.api.inject.Binding.apply(
            key.asScala(),
            OptionConverters.toScala(target.map(BindingTarget::asScala)),
            OptionConverters.toScala(scope),
            eager,
            source));
  }

  public Binding(final play.api.inject.Binding<T> underlying) {
    this.underlying = underlying;
  }

  public BindingKey<T> getKey() {
    return underlying.key().asJava();
  }

  public Optional<BindingTarget<T>> getTarget() {
    return OptionConverters.toJava(underlying.target()).map(play.api.inject.BindingTarget::asJava);
  }

  public Optional<Class<? extends Annotation>> getScope() {
    return OptionConverters.toJava(underlying.scope());
  }

  public Boolean getEager() {
    return underlying.eager();
  }

  public Object getSource() {
    return underlying.source();
  }

  /** Configure the scope for this binding. */
  public  Binding<T> in(final Class scope) {
    return underlying.in(scope).asJava();
  }

  /** Eagerly instantiate this binding when Play starts up. */
  public Binding<T> eagerly() {
    return underlying.eagerly().asJava();
  }

  @Override
  public String toString() {
    return underlying.toString();
  }

  public play.api.inject.Binding<T> asScala() {
    return underlying;
  }
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play.libs;

import java.util.*;
import java.util.concurrent.*;
import java.util.function.Supplier;

import scala.concurrent.ExecutionContext;

/** Defines a set of functional programming style helpers. */
public class F {

  /** A Function with 3 arguments. */
  public interface Function3 {
    R apply(A a, B b, C c) throws Throwable;
  }

  /** A Function with 4 arguments. */
  public interface Function4 {
    R apply(A a, B b, C c, D d) throws Throwable;
  }

  /**
   * Exception thrown when an operation times out. This class provides an unchecked alternative to
   * Java's TimeoutException.
   */
  public static class PromiseTimeoutException extends RuntimeException {
    public PromiseTimeoutException(String message) {
      super(message);
    }

    public PromiseTimeoutException(String message, Throwable cause) {
      super(message, cause);
    }
  }

  /** Represents a value of one of two possible types (a disjoint union) */
  public static class Either<L, R> {

    /** The left value. */
    public final Optional<L> left;

    /** The right value. */
    public final Optional<R> right;

    private Either(Optional<L> left, Optional<R> right) {
      this.left = left;
      this.right = right;
    }

    /**
     * Constructs a left side of the disjoint union, as opposed to the Right side.
     *
     * @param value The value of the left side
     * @param <L> the left type
     * @param <R> the right type
     * @return A left sided disjoint union
     */
    public static <L, R> Either<L, R> Left(L value) {
      return new Either<L, R>(Optional.of(value), Optional.<R>empty());
    }

    /**
     * Constructs a right side of the disjoint union, as opposed to the Left side.
     *
     * @param value The value of the right side
     * @param <L> the left type
     * @param <R> the right type
     * @return A right sided disjoint union
     */
    public static <L, R> Either<L, R> Right(R value) {
      return new Either<L, R>(Optional.<L>empty(), Optional.of(value));
    }

    @Override
    public String toString() {
      return "Either(left: " + this.left + ", right: " + this.right + ")";
    }
  }

  /** A pair - a tuple of the types A and B. */
  public static class Tuple {

    public final A _1;
    public final B _2;

    public Tuple(A _1, B _2) {
      this._1 = _1;
      this._2 = _2;
    }

    @Override
    public String toString() {
      return "Tuple2(_1: " + _1 + ", _2: " + _2 + ")";
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((_1 == null) ? 0 : _1.hashCode());
      result = prime * result + ((_2 == null) ? 0 : _2.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (obj == null) return false;
      if (!(obj instanceof Tuple)) return false;
      Tuple other = (Tuple) obj;
      if (_1 == null) {
        if (other._1 != null) return false;
      } else if (!_1.equals(other._1)) return false;
      if (_2 == null) {
        if (other._2 != null) return false;
      } else if (!_2.equals(other._2)) return false;
      return true;
    }
  }

  /**
   * Constructs a tuple of A,B
   *
   * @param a The a value
   * @param b The b value
   * @param  a's type
   * @param  b's type
   * @return The tuple
   */
  public static  Tuple Tuple(A a, B b) {
    return new Tuple(a, b);
  }

  /** A tuple of A,B,C */
  public static class Tuple3 {

    public final A _1;
    public final B _2;
    public final C _3;

    public Tuple3(A _1, B _2, C _3) {
      this._1 = _1;
      this._2 = _2;
      this._3 = _3;
    }

    @Override
    public String toString() {
      return "Tuple3(_1: " + _1 + ", _2: " + _2 + ", _3:" + _3 + ")";
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((_1 == null) ? 0 : _1.hashCode());
      result = prime * result + ((_2 == null) ? 0 : _2.hashCode());
      result = prime * result + ((_3 == null) ? 0 : _3.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (obj == null) return false;
      if (!(obj instanceof Tuple3)) return false;
      Tuple3 other = (Tuple3) obj;
      if (_1 == null) {
        if (other._1 != null) return false;
      } else if (!_1.equals(other._1)) return false;
      if (_2 == null) {
        if (other._2 != null) return false;
      } else if (!_2.equals(other._2)) return false;
      if (_3 == null) {
        if (other._3 != null) return false;
      } else if (!_3.equals(other._3)) return false;
      return true;
    }
  }

  /**
   * Constructs a tuple of A,B,C
   *
   * @param a The a value
   * @param b The b value
   * @param c The c value
   * @param  a's type
   * @param  b's type
   * @param <C> c's type
   * @return The tuple
   */
  public static  Tuple3 Tuple3(A a, B b, C c) {
    return new Tuple3(a, b, c);
  }

  /** A tuple of A,B,C,D */
  public static class Tuple4 {

    public final A _1;
    public final B _2;
    public final C _3;
    public final D _4;

    public Tuple4(A _1, B _2, C _3, D _4) {
      this._1 = _1;
      this._2 = _2;
      this._3 = _3;
      this._4 = _4;
    }

    @Override
    public String toString() {
      return "Tuple4(_1: " + _1 + ", _2: " + _2 + ", _3:" + _3 + ", _4:" + _4 + ")";
    }

    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((_1 == null) ? 0 : _1.hashCode());
      result = prime * result + ((_2 == null) ? 0 : _2.hashCode());
      result = prime * result + ((_3 == null) ? 0 : _3.hashCode());
      result = prime * result + ((_4 == null) ? 0 : _4.hashCode());
      return result;
    }

    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (obj == null) return false;
      if (!(obj instanceof Tuple4)) return false;
      Tuple4 other = (Tuple4) obj;
      if (_1 == null) {
        if (other._1 != null) return false;
      } else if (!_1.equals(other._1)) return false;
      if (_2 == null) {
        if (other._2 != null) return false;
      } else if (!_2.equals(other._2)) return false;
      if (_3 == null) {
        if (other._3 != null) return false;
      } else if (!_3.equals(other._3)) return false;
      if (_4 == null) {
        if (other._4 != null) return false;
      } else if (!_4.equals(other._4)) return false;
      return true;
    }
  }

  /**
   * Constructs a tuple of A,B,C,D
   *
   * @param a The a value
   * @param b The b value
   * @param c The c value
   * @param d The d value
   * @param  a's type
   * @param  b's type
   * @param <C> c's type
   * @param <D> d's type
   * @return The tuple
   */
  public static  Tuple4 Tuple4(A a, B b, C c, D d) {
    return new Tuple4(a, b, c, d);
  }

  /** A tuple of A,B,C,D,E */
  public static class Tuple5 {

    public final A _1;
    public final B _2;
    public final C _3;
    public final D _4;
    public final E _5;

    public Tuple5(A _1, B _2, C _3, D _4, E _5) {
      this._1 = _1;
      this._2 = _2;
      this._3 = _3;
      this._4 = _4;
      this._5 = _5;
    }

    @Override
    public String toString() {
      return "Tuple5(_1: " + _1 + ", _2: " + _2 + ", _3:" + _3 + ", _4:" + _4 + ", _5:" + _5 + ")";
    }

    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((_1 == null) ? 0 : _1.hashCode());
      result = prime * result + ((_2 == null) ? 0 : _2.hashCode());
      result = prime * result + ((_3 == null) ? 0 : _3.hashCode());
      result = prime * result + ((_4 == null) ? 0 : _4.hashCode());
      result = prime * result + ((_5 == null) ? 0 : _5.hashCode());
      return result;
    }

    public boolean equals(Object obj) {
      if (this == obj) return true;
      if (obj == null) return false;
      if (!(obj instanceof Tuple5)) return false;
      Tuple5 other = (Tuple5) obj;
      if (_1 == null) {
        if (other._1 != null) return false;
      } else if (!_1.equals(other._1)) return false;
      if (_2 == null) {
        if (other._2 != null) return false;
      } else if (!_2.equals(other._2)) return false;
      if (_3 == null) {
        if (other._3 != null) return false;
      } else if (!_3.equals(other._3)) return false;
      if (_4 == null) {
        if (other._4 != null) return false;
      } else if (!_4.equals(other._4)) return false;
      if (_5 == null) {
        if (other._5 != null) return false;
      } else if (!_5.equals(other._5)) return false;
      return true;
    }
  }

  /**
   * Constructs a tuple of A,B,C,D,E
   *
   * @param a The a value
   * @param b The b value
   * @param c The c value
   * @param d The d value
   * @param e The e value
   * @param  a's type
   * @param  b's type
   * @param <C> c's type
   * @param <D> d's type
   * @param <E> e's type
   * @return The tuple
   */
  public static  Tuple5 Tuple5(A a, B b, C c, D d, E e) {
    return new Tuple5(a, b, c, d, e);
  }

  /**
   * Converts the execution context to an executor, preparing it first.
   *
   * @param ec the execution context.
   * @return the Java Executor.
   */
  private static Executor toExecutor(ExecutionContext ec) {
    ExecutionContext prepared = ec.prepare();
    if (prepared instanceof Executor) {
      return (Executor) prepared;
    } else {
      return prepared::execute;
    }
  }

  public static class LazySupplier<T> implements Supplier<T> {

    private T value;

    private final Supplier<T> instantiator;

    private LazySupplier(Supplier<T> instantiator) {
      this.instantiator = instantiator;
    }

    @Override
    public T get() {
      if (this.value == null) {
        this.value = instantiator.get();
      }
      return this.value;
    }

    public static <T> Supplier<T> lazy(Supplier<T> creator) {
      return new LazySupplier<>(creator);
    }
  }
}


/*
 * Copyright 2016 The Netty Project
 *
 * The Netty Project licenses this file to you 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 play.core.cookie.encoding;

import java.text.ParsePosition;
import java.util.Date;

/**
 * A RFC6265 compliant cookie decoder to be used
 * client side.
 *
 *
It will store the way the raw value was wrapped in {@link Cookie#setWrap(boolean)} so it can
 * be eventually sent back to the Origin server as is.
 *
 * @see ClientCookieEncoder
 */
public final class ClientCookieDecoder extends CookieDecoder {

  /**
   * Strict encoder that validates that name and value chars are in the valid scope defined in
   * RFC6265
   */
  public static final ClientCookieDecoder STRICT = new ClientCookieDecoder(true);

  /** Lax instance that doesn't validate name and value */
  public static final ClientCookieDecoder LAX = new ClientCookieDecoder(false);

  private ClientCookieDecoder(boolean strict) {
    super(strict);
  }

  /**
   * Decodes the specified Set-Cookie HTTP header value into a {@link Cookie}.
   *
   * @param header the Set-Cookie header.
   * @return the decoded {@link Cookie}
   */
  public Cookie decode(String header) {
    if (header == null) {
      throw new NullPointerException("header");
    }
    final int headerLen = header.length();

    if (headerLen == 0) {
      return null;
    }

    CookieBuilder cookieBuilder = null;

    loop:
    for (int i = 0; ; ) {

      // Skip spaces and separators.
      for (; ; ) {
        if (i == headerLen) {
          break loop;
        }
        char c = header.charAt(i);
        if (c == ',') {
          // Having multiple cookies in a single Set-Cookie header is
          // deprecated, modern browsers only parse the first one
          break loop;

        } else if (c == '\t' || c == '\n' || c == 0x0b || c == '\f' || c == '\r' || c == ' '
            || c == ';') {
          i++;
          continue;
        }
        break;
      }

      int nameBegin = i;
      int nameEnd = i;
      int valueBegin = -1;
      int valueEnd = -1;

      if (i != headerLen) {
        keyValLoop:
        for (; ; ) {

          char curChar = header.charAt(i);
          if (curChar == ';') {
            // NAME; (no value till ';')
            nameEnd = i;
            valueBegin = valueEnd = -1;
            break keyValLoop;

          } else if (curChar == '=') {
            // NAME=VALUE
            nameEnd = i;
            i++;
            if (i == headerLen) {
              // NAME= (empty value, i.e. nothing after '=')
              valueBegin = valueEnd = 0;
              break keyValLoop;
            }

            valueBegin = i;
            // NAME=VALUE;
            int semiPos = header.indexOf(';', i);
            valueEnd = i = semiPos > 0 ? semiPos : headerLen;
            break keyValLoop;
          } else {
            i++;
          }

          if (i == headerLen) {
            // NAME (no value till the end of string)
            nameEnd = headerLen;
            valueBegin = valueEnd = -1;
            break;
          }
        }
      }

      if (valueEnd > 0 && header.charAt(valueEnd - 1) == ',') {
        // old multiple cookies separator, skipping it
        valueEnd--;
      }

      if (cookieBuilder == null) {
        // cookie name-value pair
        DefaultCookie cookie = initCookie(header, nameBegin, nameEnd, valueBegin, valueEnd);

        if (cookie == null) {
          return null;
        }

        cookieBuilder = new CookieBuilder(cookie);
      } else {
        // cookie attribute
        String attrValue = valueBegin == -1 ? null : header.substring(valueBegin, valueEnd);
        cookieBuilder.appendAttribute(header, nameBegin, nameEnd, attrValue);
      }
    }
    return cookieBuilder.cookie();
  }

  private static class CookieBuilder {

    private final DefaultCookie cookie;
    private String domain;
    private String path;
    private int maxAge = Integer.MIN_VALUE;
    private String expires;
    private boolean secure;
    private boolean httpOnly;
    private String sameSite;

    public CookieBuilder(DefaultCookie cookie) {
      this.cookie = cookie;
    }

    private int mergeMaxAgeAndExpire(int maxAge, String expires) {
      // max age has precedence over expires
      if (maxAge != Integer.MIN_VALUE) {
        return maxAge;
      } else if (expires != null) {
        Date expiresDate = HttpHeaderDateFormat.get().parse(expires, new ParsePosition(0));
        if (expiresDate != null) {
          long maxAgeMillis = expiresDate.getTime() - System.currentTimeMillis();
          return (int) (maxAgeMillis / 1000 + (maxAgeMillis % 1000 != 0 ? 1 : 0));
        }
      }
      return Integer.MIN_VALUE;
    }

    public Cookie cookie() {
      cookie.setDomain(domain);
      cookie.setPath(path);
      cookie.setMaxAge(mergeMaxAgeAndExpire(maxAge, expires));
      cookie.setSecure(secure);
      cookie.setHttpOnly(httpOnly);
      cookie.setSameSite(sameSite);
      return cookie;
    }

    /**
     * Parse and store a key-value pair. First one is considered to be the cookie name/value.
     * Unknown attribute names are silently discarded.
     *
     * @param header the HTTP header
     * @param keyStart where the key starts in the header
     * @param keyEnd where the key ends in the header
     * @param value the decoded value
     */
    public void appendAttribute(String header, int keyStart, int keyEnd, String value) {
      setCookieAttribute(header, keyStart, keyEnd, value);
    }

    private void setCookieAttribute(String header, int keyStart, int keyEnd, String value) {
      int length = keyEnd - keyStart;

      if (length == 4) {
        parse4(header, keyStart, value);
      } else if (length == 6) {
        parse6(header, keyStart, value);
      } else if (length == 7) {
        parse7(header, keyStart, value);
      } else if (length == 8) {
        parse8(header, keyStart, value);
      }
    }

    private void parse4(String header, int nameStart, String value) {
      if (header.regionMatches(true, nameStart, CookieHeaderNames.PATH, 0, 4)) {
        path = value;
      }
    }

    private void parse6(String header, int nameStart, String value) {
      if (header.regionMatches(true, nameStart, CookieHeaderNames.DOMAIN, 0, 5)) {
        domain = value.length() > 0 ? value : null;
      } else if (header.regionMatches(true, nameStart, CookieHeaderNames.SECURE, 0, 5)) {
        secure = true;
      }
    }

    private void setExpire(String value) {
      expires = value;
    }

    private void setMaxAge(String value) {
      try {
        maxAge = Math.max(Integer.valueOf(value), 0);
      } catch (NumberFormatException e1) {
        // ignore failure to parse -> treat as session cookie
      }
    }

    private void parse7(String header, int nameStart, String value) {
      if (header.regionMatches(true, nameStart, CookieHeaderNames.EXPIRES, 0, 7)) {
        setExpire(value);
      } else if (header.regionMatches(true, nameStart, CookieHeaderNames.MAX_AGE, 0, 7)) {
        setMaxAge(value);
      }
    }

    private void parse8(String header, int nameStart, String value) {
      if (header.regionMatches(true, nameStart, CookieHeaderNames.HTTPONLY, 0, 8)) {
        httpOnly = true;
      } else if (header.regionMatches(true, nameStart, CookieHeaderNames.SAMESITE, 0, 8)) {
        setSameSite(value);
      }
    }

    private void setSameSite(String value) {
      sameSite = value;
    }
  }
}


/**
 * Copyright (C) 2006 Google Inc.
 *
 *
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 play.inject;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.HashSet;

/**
 * Provides access to the calling line of code.
 * https://github.com/google/guice/blob/3.0/core/src/com/google/inject/internal/util/SourceProvider.java
 *
 * @author crazybob@google.com (Bob Lee)
 */
public final class SourceProvider {

  /** Indicates that the source is unknown. */
  public static final Object UNKNOWN_SOURCE = "[unknown source]";

  private final Set<String> classNamesToSkip;

  public static final SourceProvider DEFAULT_INSTANCE =
      new SourceProvider(Collections.singleton(SourceProvider.class.getName()));

  private SourceProvider(Collection<String> classesToSkip) {
    this.classNamesToSkip = Collections.unmodifiableSet(new HashSet<String>(classesToSkip));
  }

  /**
   * Returns a new instance that also skips {@code moreClassesToSkip}.
   *
   * @param moreClassesToSkip a list of classes to skip in from source provider.
   * @return the source provider skipping {@code moreClassesToSkip}.
   */
  public SourceProvider plusSkippedClasses(Class... moreClassesToSkip) {
    Set<String> toSkip = new HashSet<String>(classNamesToSkip);
    toSkip.addAll(asStrings(moreClassesToSkip));
    return new SourceProvider(toSkip);
  }

  /** Returns the class names as Strings */
  private static List<String> asStrings(Class... classes) {
    List<String> strings = new ArrayList<String>();
    for (Class c : classes) {
      strings.add(c.getName());
    }
    return strings;
  }

  /**
   * Returns the calling line of code. The selected line is the nearest to the top of the stack that
   * is not skipped.
   *
   * @return a stack trace element containing the caller.
   */
  public StackTraceElement get() {
    for (final StackTraceElement element : new Throwable().getStackTrace()) {
      String className = element.getClassName();
      if (!classNamesToSkip.contains(className)) {
        return element;
      }
    }
    throw new AssertionError();
  }
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play.db.jpa;

import com.google.common.collect.ImmutableSet;
import com.typesafe.config.Config;

import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import java.util.Map;
import java.util.Set;

/** Default JPA configuration. */
public class DefaultJPAConfig implements JPAConfig {

  private Set<JPAConfig.PersistenceUnit> persistenceUnits;

  public DefaultJPAConfig(Set<JPAConfig.PersistenceUnit> persistenceUnits) {
    this.persistenceUnits = persistenceUnits;
  }

  public DefaultJPAConfig(JPAConfig.PersistenceUnit... persistenceUnits) {
    this(ImmutableSet.copyOf(persistenceUnits));
  }

  @Override
  public Set<JPAConfig.PersistenceUnit> persistenceUnits() {
    return persistenceUnits;
  }

  @Singleton
  public static class JPAConfigProvider implements Provider<JPAConfig> {
    private final JPAConfig jpaConfig;

    @Inject
    public JPAConfigProvider(Config configuration) {
      String jpaKey = configuration.getString("play.jpa.config");

      ImmutableSet.Builder<JPAConfig.PersistenceUnit> persistenceUnits =
          new ImmutableSet.Builder<JPAConfig.PersistenceUnit>();

      if (configuration.hasPath(jpaKey)) {
        Config jpa = configuration.getConfig(jpaKey);
        jpa.entrySet()
            .forEach(
                entry -> {
                  String key = entry.getKey();
                  persistenceUnits.add(new JPAConfig.PersistenceUnit(key, jpa.getString(key)));
                });
      }

      jpaConfig = new DefaultJPAConfig(persistenceUnits.build());
    }

    @Override
    public JPAConfig get() {
      return jpaConfig;
    }
  }

  /**
   * Create a default JPA configuration with the given name and unit name.
   *
   * @param name the name for the entity manager factory
   * @param unitName the persistence unit name as used in `persistence.xml`
   * @return a default JPA configuration
   */
  public static JPAConfig of(String name, String unitName) {
    return new DefaultJPAConfig(new JPAConfig.PersistenceUnit(name, unitName));
  }

  /**
   * Create a default JPA configuration with the given names and unit names.
   *
   * @param n1 Name of the first entity manager factory
   * @param u1 Name of the first unit
   * @param n2 Name of the second entity manager factory
   * @param u2 Name of the second unit
   * @return a default JPA configuration with the provided persistence units.
   */
  public static JPAConfig of(String n1, String u1, String n2, String u2) {
    return new DefaultJPAConfig(
        new JPAConfig.PersistenceUnit(n1, u1), new JPAConfig.PersistenceUnit(n2, u2));
  }

  /**
   * Create a default JPA configuration with the given names and unit names.
   *
   * @param n1 Name of the first entity manager factory
   * @param u1 Name of the first unit
   * @param n2 Name of the second entity manager factory
   * @param u2 Name of the second unit
   * @param n3 Name of the third entity manager factory
   * @param u3 Name of the third unit
   * @return a default JPA configuration with the provided persistence units.
   */
  public static JPAConfig of(String n1, String u1, String n2, String u2, String n3, String u3) {
    return new DefaultJPAConfig(
        new JPAConfig.PersistenceUnit(n1, u1),
        new JPAConfig.PersistenceUnit(n2, u2),
        new JPAConfig.PersistenceUnit(n3, u3));
  }

  /**
   * Create a default JPA configuration from a map of names to unit names.
   *
   * @param map Map of entity manager factory names to unit names
   * @return a JPAConfig configured with the provided mapping
   */
  public static JPAConfig from(Map<String, String> map) {
    ImmutableSet.Builder<JPAConfig.PersistenceUnit> persistenceUnits =
        new ImmutableSet.Builder<JPAConfig.PersistenceUnit>();
    for (Map.Entry<String, String> entry : map.entrySet()) {
      persistenceUnits.add(new JPAConfig.PersistenceUnit(entry.getKey(), entry.getValue()));
    }
    return new DefaultJPAConfig(persistenceUnits.build());
  }
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play.libs;

import akka.NotUsed;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Source;
import akka.util.ByteString;
import akka.util.ByteStringBuilder;
import com.fasterxml.jackson.databind.JsonNode;
import play.twirl.api.utils.StringEscapeUtils;

import java.util.Arrays;

/**
 * Provides an easy way to use a Comet formatted output with Akka Streams.
 *
 *
There are two methods that can be used to convert strings and JSON, {@code Comet.string} and
 * {@code Comet.json}. These methods build on top of the base method, {@code Comet.flow}, which
 * takes a Flow of {@code akka.util.ByteString} and organizes it into Comet format.
 *
 *
{@literal
 *   public Result liveClock() {
 *        final DateTimeFormatter df = DateTimeFormatter.ofPattern("HH mm ss");
 *        final Source tickSource = Source.tick(Duration.Zero(), Duration.create(100, MILLISECONDS), "TICK");
 *        final Source eventSource = tickSource.map((tick) -> df.format(ZonedDateTime.now()));
 *
 *        final Source<ByteString, NotUsed> flow = eventSource.via(Comet.string("parent.clockChanged"));
 *        return ok().chunked(flow).as(Http.MimeTypes.HTML);
 *   }
 * }

 */
public abstract class Comet {

  private static ByteString initialChunk;

  static {
    char[] buffer = new char[1024 * 5];
    Arrays.fill(buffer, ' ');
    initialChunk = ByteString.fromString(new String(buffer) + "");
  }

  /**
   * Produces a Flow of escaped ByteString from a series of String elements. Calls out to Comet.flow
   * internally.
   *
   * @param callbackName the javascript callback method.
   * @return a flow of ByteString elements.
   */
  public static Flow<String, ByteString, NotUsed> string(String callbackName) {
    return Flow.of(String.class)
        .map(
            str -> {
              return ByteString.fromString("'" + StringEscapeUtils.escapeEcmaScript(str) + "'");
            })
        .via(flow(callbackName));
  }

  /**
   * Produces a flow of ByteString using `Json.stringify` from a Flow of JsonNode. Calls out to
   * Comet.flow internally.
   *
   * @param callbackName the javascript callback method.
   * @return a flow of ByteString elements.
   */
  public static Flow<JsonNode, ByteString, NotUsed> json(String callbackName) {
    return Flow.of(JsonNode.class)
        .map(
            json -> {
              return ByteString.fromString(Json.stringify(json));
            })
        .via(flow(callbackName));
  }

  /**
   * Produces a flow of ByteString with a prepended block and a script wrapper.
   *
   * @param callbackName the javascript callback method.
   * @return a flow of ByteString elements.
   */
  public static Flow<ByteString, ByteString, NotUsed> flow(String callbackName) {
    ByteString cb = ByteString.fromString(callbackName);
    return Flow.of(ByteString.class)
        .map(
            (msg) -> {
              return formatted(cb, msg);
            })
        .prepend(Source.single(initialChunk));
  }

  private static ByteString formatted(ByteString callbackName, ByteString javascriptMessage) {
    ByteStringBuilder b = new ByteStringBuilder();
    b.append(ByteString.fromString(""));
    return b.result();
  }
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play.mvc;

import java.util.concurrent.CompletionStage;
import java.util.function.Function;

import play.api.http.Status$;
import play.http.HttpErrorHandler;
import play.libs.F;
import play.libs.streams.Accumulator;
import play.core.j.JavaParsers;

import akka.util.ByteString;

/** Utilities for creating body parsers. */
public class BodyParsers {

  /**
   * Validate the content type of the passed in request using the given validator.
   *
   * <p>If the validator returns true, the passed in accumulator will be returned to parse the body,
   * otherwise an accumulator with a result created by the error handler will be returned.
   *
   * @param errorHandler The error handler used to create a bad request result if the content type
   *     is not valid.
   * @param request The request to validate.
   * @param errorMessage The error message to pass to the error handler if the content type is not
   *     valid.
   * @param validate The validation function.
   * @param parser The parser to use if the content type is valid.
   * @param <A> The type to be parsed by the parser
   * @return An accumulator to parse the body.
   */
  public static <A> Accumulator<ByteString, F.Either<Result, A>> validateContentType(
      HttpErrorHandler errorHandler,
      Http.RequestHeader request,
      String errorMessage,
      Function<String, Boolean> validate,
      Function<Http.RequestHeader, Accumulator<ByteString, F.Either<Result, A>>> parser) {
    if (request.contentType().map(validate).orElse(false)) {
      return parser.apply(request);
    } else {
      CompletionStage<Result> result =
          errorHandler.onClientError(
              request, Status$.MODULE$.UNSUPPORTED_MEDIA_TYPE(), errorMessage);
      return Accumulator.done(result.thenApply(F.Either::Left));
    }
  }

  static <A, B> Accumulator<ByteString, F.Either<Result, A>> delegate(
      play.api.mvc.BodyParser<B> delegate, Function<B, A> transform, Http.RequestHeader request) {
    Accumulator<ByteString, scala.util.Either<play.api.mvc.Result, B>> javaAccumulator =
        delegate.apply(request.asScala()).asJava();

    return javaAccumulator.map(
        result -> {
          if (result.isLeft()) {
            return F.Either.Left(result.left().get().asJava());
          } else {
            return F.Either.Right(transform.apply(result.right().get()));
          }
        },
        JavaParsers.trampoline());
  }
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play;

import org.slf4j.Marker;
import play.api.DefaultMarkerContext;

import java.util.function.Supplier;

/**
 * High level API for logging operations.
 *
 *
Example, logging with the default application logger:
 *
 *

 * Logger.info("Hello!");

 *
 * Example, logging with a custom logger:
 *
 *

 * Logger.of("my.logger").info("Hello!")

 *
 * Each of the logging methods is overloaded to be able to take an array of arguments. These are
 * formatted into the message String, replacing occurrences of '{}'. For example:
 *
 *

 * Logger.info("A {} request was received at {}", request.method(), request.uri());
 *

 *
 * This might print out:
 *
 *

 * A POST request was received at /api/items
 *

 *
 * This saves on the cost of String construction when logging is turned off.
 *
 *
This API is intended as a simple logging API to meet 99% percent of the most common logging
 * needs with minimal code overhead. For more complex needs, the underlying() methods may be used to
 * get the underlying SLF4J logger, or SLF4J may be used directly.
 */
public class Logger {

  /**
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated private static final ALogger logger = of("application");

  /**
   * Obtain a logger instance.
   *
   * @param name name of the logger
   * @return a logger
   */
  public static ALogger of(String name) {
    return new ALogger(play.api.Logger.apply(name));
  }

  /**
   * Obtain a logger instance.
   *
   * @param clazz a class whose name will be used as logger name
   * @return a logger
   */
  public static ALogger of(Class<?> clazz) {
    return new ALogger(play.api.Logger.apply(clazz));
  }

  /**
   * Get the underlying application SLF4J logger.
   *
   * @return the underlying logger
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static org.slf4j.Logger underlying() {
    return logger.underlying();
  }

  /**
   * Returns true if the logger instance enabled for the TRACE level?
   *
   * @return true if the logger instance enabled for the TRACE level?
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static boolean isTraceEnabled() {
    return logger.isTraceEnabled();
  }

  /**
   * Returns true if the logger instance enabled for the DEBUG level?
   *
   * @return true if the logger instance enabled for the DEBUG level?
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static boolean isDebugEnabled() {
    return logger.isDebugEnabled();
  }

  /**
   * Returns true if the logger instance enabled for the INFO level?
   *
   * @return true if the logger instance enabled for the INFO level?
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static boolean isInfoEnabled() {
    return logger.isInfoEnabled();
  }

  /**
   * Returns true if the logger instance enabled for the WARN level?
   *
   * @return true if the logger instance enabled for the WARN level?
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static boolean isWarnEnabled() {
    return logger.isWarnEnabled();
  }

  /**
   * Returns true if the logger instance enabled for the ERROR level?
   *
   * @return true if the logger instance enabled for the ERROR level?
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static boolean isErrorEnabled() {
    return logger.isWarnEnabled();
  }

  /**
   * Log a message with the TRACE level.
   *
   * @param message message to log
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void trace(String message) {
    logger.trace(message);
  }

  /**
   * Log a message with the TRACE level.
   *
   * @param msgSupplier Supplier that contains message to log
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void trace(Supplier<String> msgSupplier) {
    logger.trace(msgSupplier);
  }

  /**
   * Log a message with the TRACE level.
   *
   * @param message message to log
   * @param args The arguments to apply to the message String
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void trace(String message, Object... args) {
    logger.trace(message, args);
  }

  /**
   * Log a message with the TRACE level.
   *
   * @param message message to log
   * @param args Suppliers that contain arguments to apply to the message String
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void trace(String message, Supplier<?>... args) {
    logger.trace(message, args);
  }

  /**
   * Log a message with the TRACE level.
   *
   * @param message message to log
   * @param error associated exception
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void trace(String message, Throwable error) {
    logger.trace(message, error);
  }

  /**
   * Log a message with the DEBUG level.
   *
   * @param message message to log
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void debug(String message) {
    logger.debug(message);
  }

  /**
   * Log a message with the DEBUG level.
   *
   * @param msgSupplier Supplier that contains message to log
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void debug(Supplier<String> msgSupplier) {
    logger.debug(msgSupplier);
  }

  /**
   * Log a message with the DEBUG level.
   *
   * @param message message to log
   * @param args The arguments to apply to the message String
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void debug(String message, Object... args) {
    logger.debug(message, args);
  }

  /**
   * Log a message with the DEBUG level.
   *
   * @param message message to log
   * @param args Suppliers that contain arguments to apply to the message String
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void debug(String message, Supplier<?>... args) {
    logger.debug(message, args);
  }

  /**
   * Log a message with the DEBUG level.
   *
   * @param message message to log
   * @param error associated exception
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void debug(String message, Throwable error) {
    logger.debug(message, error);
  }

  /**
   * Log a message with the INFO level.
   *
   * @param message message to log
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void info(String message) {
    logger.info(message);
  }

  /**
   * Log a message with the INFO level.
   *
   * @param msgSupplier Supplier that contains message to log
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void info(Supplier<String> msgSupplier) {
    logger.info(msgSupplier);
  }

  /**
   * Log a message with the INFO level.
   *
   * @param message message to log
   * @param args The arguments to apply to the message string
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void info(String message, Object... args) {
    logger.info(message, args);
  }

  /**
   * Log a message with the INFO level.
   *
   * @param message message to log
   * @param args Suppliers that contain arguments to apply to the message String
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void info(String message, Supplier<?>... args) {
    logger.info(message, args);
  }

  /**
   * Log a message with the INFO level.
   *
   * @param message message to log
   * @param error associated exception
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void info(String message, Throwable error) {
    logger.info(message, error);
  }

  /**
   * Log a message with the WARN level.
   *
   * @param message message to log
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void warn(String message) {
    logger.warn(message);
  }

  /**
   * Log a message with the WARN level.
   *
   * @param msgSupplier Supplier that contains message to log
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void warn(Supplier<String> msgSupplier) {
    logger.warn(msgSupplier);
  }

  /**
   * Log a message with the WARN level.
   *
   * @param message message to log
   * @param args The arguments to apply to the message string
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void warn(String message, Object... args) {
    logger.warn(message, args);
  }

  /**
   * Log a message with the WARN level.
   *
   * @param message message to log
   * @param args Suppliers that contain arguments to apply to the message String
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void warn(String message, Supplier<?>... args) {
    logger.warn(message, args);
  }

  /**
   * Log a message with the WARN level.
   *
   * @param message message to log
   * @param error associated exception
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void warn(String message, Throwable error) {
    logger.warn(message, error);
  }

  /**
   * Log a message with the ERROR level.
   *
   * @param message message to log
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void error(String message) {
    logger.error(message);
  }

  /**
   * Log a message with the ERROR level.
   *
   * @param msgSupplier Supplier that contains message to log
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void error(Supplier<String> msgSupplier) {
    logger.error(msgSupplier);
  }

  /**
   * Log a message with the ERROR level.
   *
   * @param message message to log
   * @param args The arguments to apply to the message string
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void error(String message, Object... args) {
    logger.error(message, args);
  }

  /**
   * Log a message with the ERROR level.
   *
   * @param message message to log
   * @param args Suppliers that contain arguments to apply to the message String
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void error(String message, Supplier<?> args) {
    logger.error(message, args);
  }

  /**
   * Log a message with the ERROR level.
   *
   * @param message message to log
   * @param error associated exception
   * @deprecated Deprecated as of 2.7.0. Create an instance of {@link ALogger} via {@link
   *     #of(String)} / {@link #of(Class)} and use the same-named method. Or use SLF4J directly.
   */
  @Deprecated
  public static void error(String message, Throwable error) {
    logger.error(message, error);
  }

  /** Typical logger interface */
  public static class ALogger {

    private final play.api.MarkerContext noMarker = new play.api.DefaultMarkerContext(null);

    private final play.api.Logger logger;

    public ALogger(play.api.Logger logger) {
      this.logger = logger;
    }

    /**
     * Get the underlying SLF4J logger.
     *
     * @return the SLF4J logger
     */
    public org.slf4j.Logger underlying() {
      return logger.underlyingLogger();
    }

    /**
     * Returns true if the logger instance has TRACE level logging enabled.
     *
     * @return true if the logger instance has TRACE level logging enabled.
     */
    public boolean isTraceEnabled() {
      return logger.isTraceEnabled(noMarker);
    }

    /**
     * Similar to {@link #isTraceEnabled()} method except that the marker data is also taken into
     * account.
     *
     * @param marker The marker data to take into consideration
     * @return True if this Logger is enabled for the TRACE level, false otherwise.
     */
    public boolean isTraceEnabled(Marker marker) {
      return logger.isTraceEnabled(new DefaultMarkerContext(marker));
    }

    /**
     * Returns true if the logger instance has DEBUG level logging enabled.
     *
     * @return true if the logger instance has DEBUG level logging enabled.
     */
    public boolean isDebugEnabled() {
      return logger.isDebugEnabled(noMarker);
    }

    /**
     * Similar to {@link #isDebugEnabled()} method except that the marker data is also taken into
     * account.
     *
     * @param marker The marker data to take into consideration
     * @return True if this Logger is enabled for the DEBUG level, false otherwise.
     */
    public boolean isDebugEnabled(Marker marker) {
      return logger.isDebugEnabled(new DefaultMarkerContext(marker));
    }

    /**
     * Returns true if the logger instance has INFO level logging enabled.
     *
     * @return true if the logger instance has INFO level logging enabled.
     */
    public boolean isInfoEnabled() {
      return logger.isInfoEnabled(noMarker);
    }

    /**
     * Similar to {@link #isInfoEnabled()} method except that the marker data is also taken into
     * consideration.
     *
     * @param marker The marker data to take into consideration
     * @return true if this logger is warn enabled, false otherwise
     */
    public boolean isInfoEnabled(Marker marker) {
      return logger.isInfoEnabled(new DefaultMarkerContext(marker));
    }

    /**
     * Returns true if the logger instance has WARN level logging enabled.
     *
     * @return true if the logger instance has WARN level logging enabled.
     */
    public boolean isWarnEnabled() {
      return logger.isWarnEnabled(noMarker);
    }

    /**
     * Similar to {@link #isWarnEnabled()} method except that the marker data is also taken into
     * consideration.
     *
     * @param marker The marker data to take into consideration
     * @return True if this Logger is enabled for the WARN level, false otherwise.
     */
    public boolean isWarnEnabled(Marker marker) {
      return logger.isWarnEnabled(new DefaultMarkerContext(marker));
    }

    /**
     * Returns true if the logger instance has ERROR level logging enabled.
     *
     * @return true if the logger instance has ERROR level logging enabled.
     */
    public boolean isErrorEnabled() {
      return logger.isErrorEnabled(noMarker);
    }

    /**
     * Similar to {@link #isErrorEnabled()} method except that the marker data is also taken into
     * consideration.
     *
     * @param marker The marker data to take into consideration
     * @return True if this Logger is enabled for the ERROR level, false otherwise.
     */
    public boolean isErrorEnabled(Marker marker) {
      return logger.isErrorEnabled(new DefaultMarkerContext(marker));
    }

    /**
     * Converts array of Supplier<?> to array of results
     *
     * @param args suppliers we need to get results of
     * @return array of results represented as Object
     */
    private Object[] suppliersToObj(Supplier<?>... args) {

      final Object[] objArgs = new Object[args.length];
      for (int i = 0; i < args.length; i++) {
        objArgs[i] = args[i].get();
      }

      return objArgs;
    }

    /**
     * Logs a message with the TRACE level.
     *
     * @param message message to log
     */
    public void trace(String message) {
      logger.underlyingLogger().trace(message);
    }

    /**
     * Log a message with the TRACE level.
     *
     * @param msgSupplier Supplier that contains message to log
     */
    public void trace(Supplier<String> msgSupplier) {
      if (isTraceEnabled()) {
        trace(msgSupplier.get());
      }
    }

    /**
     * Logs a message with the TRACE level.
     *
     * @param marker the marker data specific to this log statement
     * @param message message to log
     */
    public void trace(Marker marker, String message) {
      logger.underlyingLogger().trace(marker, message);
    }

    /**
     * Logs a message with the TRACE level.
     *
     * @param message message to log
     * @param args The arguments to apply to the message string
     */
    public void trace(String message, Object... args) {
      logger.underlyingLogger().trace(message, args);
    }

    /**
     * Log a message with the TRACE level.
     *
     * @param message message to log
     * @param args Suppliers that contain arguments to apply to the message String
     */
    public void trace(String message, Supplier<?>... args) {
      if (isTraceEnabled()) {
        trace(message, suppliersToObj(args));
      }
    }

    /**
     * This method is similar to {@link #trace(String, Object...)} method except that the marker
     * data is also taken into consideration.
     *
     * @param marker the marker data specific to this log statement
     * @param message message to log
     * @param args The arguments to apply to the message string
     */
    public void trace(Marker marker, String message, Object... args) {
      logger.underlyingLogger().trace(marker, message, args);
    }

    /**
     * Logs a message with the TRACE level, with the given error.
     *
     * @param message message to log
     * @param error associated exception
     */
    public void trace(String message, Throwable error) {
      logger.underlyingLogger().trace(message, error);
    }

    /**
     * Logs a message with the TRACE level, with the given error.
     *
     * @param marker the marker data specific to this log statement
     * @param message message to log
     * @param error associated exception
     */
    public void trace(Marker marker, String message, Throwable error) {
      logger.underlyingLogger().trace(marker, message, error);
    }

    /**
     * Logs a message with the DEBUG level.
     *
     * @param message Message to log
     */
    public void debug(String message) {
      logger.underlyingLogger().debug(message);
    }

    /**
     * Log a message with the DEBUG level.
     *
     * @param msgSupplier Supplier that contains message to log
     */
    public void debug(Supplier<String> msgSupplier) {
      if (isDebugEnabled()) {
        debug(msgSupplier.get());
      }
    }

    /**
     * Logs a message with the DEBUG level.
     *
     * @param marker the marker data specific to this log statement
     * @param message Message to log
     */
    public void debug(Marker marker, String message) {
      logger.underlyingLogger().debug(marker, message);
    }

    /**
     * Logs a message with the DEBUG level.
     *
     * @param message Message to log
     * @param args The arguments to apply to the message string
     */
    public void debug(String message, Object... args) {
      logger.underlyingLogger().debug(message, args);
    }

    /**
     * Log a message with the DEBUG level.
     *
     * @param message message to log
     * @param args Suppliers that contain arguments to apply to the message String
     */
    public void debug(String message, Supplier<?>... args) {
      if (isDebugEnabled()) {
        debug(message, suppliersToObj(args));
      }
    }

    /**
     * Logs a message with the DEBUG level.
     *
     * @param marker the marker data specific to this log statement
     * @param message Message to log
     * @param args The arguments to apply to the message string
     */
    public void debug(Marker marker, String message, Object... args) {
      logger.underlyingLogger().debug(marker, message, args);
    }

    /**
     * Logs a message with the DEBUG level, with the given error.
     *
     * @param message Message to log
     * @param error associated exception
     */
    public void debug(String message, Throwable error) {
      logger.underlyingLogger().debug(message, error);
    }

    /**
     * Logs a message with the DEBUG level, with the given error.
     *
     * @param marker the marker data specific to this log statement
     * @param message Message to log
     * @param error associated exception
     */
    public void debug(Marker marker, String message, Throwable error) {
      logger.underlyingLogger().debug(marker, message, error);
    }

    /**
     * Logs a message with the INFO level.
     *
     * @param message message to log
     */
    public void info(String message) {
      logger.underlyingLogger().info(message);
    }

    /**
     * Log a message with the INFO level.
     *
     * @param msgSupplier Supplier that contains message to log
     */
    public void info(Supplier<String> msgSupplier) {
      if (isInfoEnabled()) {
        info(msgSupplier.get());
      }
    }

    /**
     * Logs a message with the INFO level.
     *
     * @param marker the marker data specific to this log statement
     * @param message message to log
     */
    public void info(Marker marker, String message) {
      logger.underlyingLogger().info(marker, message);
    }

    /**
     * Logs a message with the INFO level.
     *
     * @param message message to log
     * @param args The arguments to apply to the message string
     */
    public void info(String message, Object... args) {
      logger.underlyingLogger().info(message, args);
    }

    /**
     * Log a message with the INFO level.
     *
     * @param message message to log
     * @param args Suppliers that contain arguments to apply to the message String
     */
    public void info(String message, Supplier<?>... args) {
      if (isInfoEnabled()) {
        info(message, suppliersToObj(args));
      }
    }

    /**
     * Logs a message with the INFO level.
     *
     * @param marker the marker data specific to this log statement
     * @param message message to log
     * @param args The arguments to apply to the message string
     */
    public void info(Marker marker, String message, Object... args) {
      logger.underlyingLogger().info(marker, message, args);
    }

    /**
     * Logs a message with the INFO level, with the given error.
     *
     * @param message message to log
     * @param error associated exception
     */
    public void info(String message, Throwable error) {
      logger.underlyingLogger().info(message, error);
    }

    /**
     * Logs a message with the INFO level, with the given error.
     *
     * @param marker the marker data specific to this log statement
     * @param message message to log
     * @param error associated exception
     */
    public void info(Marker marker, String message, Throwable error) {
      logger.underlyingLogger().info(marker, message, error);
    }

    /**
     * Log a message with the WARN level.
     *
     * @param message message to log
     */
    public void warn(String message) {
      logger.underlyingLogger().warn(message);
    }

    /**
     * Log a message with the WARN level.
     *
     * @param msgSupplier Supplier that contains message to log
     */
    public void warn(Supplier<String> msgSupplier) {
      if (isWarnEnabled()) {
        warn(msgSupplier.get());
      }
    }

    /**
     * Log a message with the WARN level.
     *
     * @param marker the marker data specific to this log statement
     * @param message message to log
     */
    public void warn(Marker marker, String message) {
      logger.underlyingLogger().warn(marker, message);
    }

    /**
     * Log a message with the WARN level.
     *
     * @param message message to log
     * @param args The arguments to apply to the message string
     */
    public void warn(String message, Object... args) {
      logger.underlyingLogger().warn(message, args);
    }

    /**
     * Log a message with the WARN level.
     *
     * @param message message to log
     * @param args Suppliers that contain arguments to apply to the message String
     */
    public void warn(String message, Supplier<?>... args) {
      if (isWarnEnabled()) {
        warn(message, suppliersToObj(args));
      }
    }

    /**
     * Log a message with the WARN level.
     *
     * @param marker the marker data specific to this log statement
     * @param message message to log
     * @param args The arguments to apply to the message string
     */
    public void warn(Marker marker, String message, Object... args) {
      logger.underlyingLogger().warn(marker, message, args);
    }

    /**
     * Log a message with the WARN level, with the given error.
     *
     * @param message message to log
     * @param error associated exception
     */
    public void warn(String message, Throwable error) {
      logger.underlyingLogger().warn(message, error);
    }

    /**
     * Log a message with the WARN level, with the given error.
     *
     * @param marker the marker data specific to this log statement
     * @param message message to log
     * @param error associated exception
     */
    public void warn(Marker marker, String message, Throwable error) {
      logger.underlyingLogger().warn(marker, message, error);
    }

    /**
     * Log a message with the ERROR level.
     *
     * @param message message to log
     */
    public void error(String message) {
      logger.underlyingLogger().error(message);
    }

    /**
     * Log a message with the ERROR level.
     *
     * @param msgSupplier Supplier that contains message to log
     */
    public void error(Supplier<String> msgSupplier) {
      if (isErrorEnabled()) {
        error(msgSupplier.get());
      }
    }

    /**
     * Log a message with the ERROR level.
     *
     * @param marker the marker data specific to this log statement
     * @param message message to log
     */
    public void error(Marker marker, String message) {
      logger.underlyingLogger().error(marker, message);
    }

    /**
     * Log a message with the ERROR level.
     *
     * @param message message to log
     * @param args The arguments to apply to the message string
     */
    public void error(String message, Object... args) {
      logger.underlyingLogger().error(message, args);
    }

    /**
     * Log a message with the ERROR level.
     *
     * @param message message to log
     * @param args Suppliers that contain arguments to apply to the message String
     */
    public void error(String message, Supplier<?>... args) {
      if (isErrorEnabled()) {
        error(message, suppliersToObj(args));
      }
    }

    /**
     * Log a message with the ERROR level.
     *
     * @param marker the marker data specific to this log statement
     * @param message message to log
     * @param args The arguments to apply to the message string
     */
    public void error(Marker marker, String message, Object... args) {
      logger.underlyingLogger().error(marker, message, args);
    }

    /**
     * Log a message with the ERROR level, with the given error.
     *
     * @param message message to log
     * @param error associated exception
     */
    public void error(String message, Throwable error) {
      logger.underlyingLogger().error(message, error);
    }

    /**
     * Log a message with the ERROR level, with the given error.
     *
     * @param marker the marker data specific to this log statement
     * @param message message to log
     * @param error associated exception
     */
    public void error(Marker marker, String message, Throwable error) {
      logger.underlyingLogger().error(marker, message, error);
    }
  }
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play.data.validation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorFactory;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

/** ConstraintValidatorFactory to be used with compile-time Dependency Injection. */
public class MappedConstraintValidatorFactory implements ConstraintValidatorFactory {

  // This is a Map<Class, Supplier> so that we can have both
  // singletons and non-singletons validators.
  private final Map<Class<? extends ConstraintValidator>, Supplier<ConstraintValidator>>
      validators = new HashMap<>();

  /**
   * Adds validator as a singleton.
   *
   * @param key the constraint validator type
   * @param constraintValidator the constraint validator instance
   * @param <T> the type of constraint validator implementation
   * @return {@link MappedConstraintValidatorFactory} with the given constraint validator added.
   */
  public <T extends ConstraintValidator<?, ?>>
      MappedConstraintValidatorFactory addConstraintValidator(Class<T> key, T constraintValidator) {
    validators.put(key, () -> constraintValidator);
    return this;
  }

  /**
   * Adds validator as a non-singleton.
   *
   * @param key the constraint validator type
   * @param constraintValidator the constraint validator instance
   * @param <T> the type of constraint validator implementation
   * @return {@link MappedConstraintValidatorFactory} with the given constraint validator added.
   */
  public <T extends ConstraintValidator<?, ?>>
      MappedConstraintValidatorFactory addConstraintValidator(
          Class<T> key, Supplier<T> constraintValidator) {
    validators.put(key, constraintValidator::get);
    return this;
  }

  @Override
  @SuppressWarnings("unchecked")
  public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
    return (T) validators.computeIfAbsent(key, clazz -> () -> newInstance(clazz)).get();
  }

  @Override
  public void releaseInstance(ConstraintValidator<?, ?> instance) {
    validators.clear();
  }

  // This is a fallback to avoid that users needs to create every single
  // validator instance, which are usually very simple. We then create the
  // constraint validators automatically, even for compile-time dependency
  // injection, but we enable users to register their own instances if they
  // need to do so.
  private <T extends ConstraintValidator<?, ?>> T newInstance(Class<T> key) {
    try {
      return key.getDeclaredConstructor().newInstance();
    } catch (InstantiationException
        | RuntimeException
        | IllegalAccessException
        | NoSuchMethodException
        | InvocationTargetException ex) {
      throw new RuntimeException(ex);
    }
  }
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package javaguide.http.routing.controllers;

import play.mvc.Controller;
import play.mvc.Result;

public class Clients extends Controller {

  // #clients-show-action
  public Result show(Long id) {
    Client client = clientService.findById(id);
    return ok(views.html.Client.show(client));
  }
  // #clients-show-action

  public Result list() {
    return ok("all clients");
  }

  static class clientService {
    static Client findById(Long id) {
      return new Client(id);
    }
  }

  static class Client {
    Client(Long id) {
      this.id = id;
    }

    Long id;

    String show(Client client) {
      return "showing client " + client.id;
    }
  }

  static class views {
    static class html {
      static Client Client = new Client(0l);
    }
  }
}


/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package assets.controllers;

import play.mvc.*;

import java.io.File;

public class JavaRangeRequestController extends Controller {

  // #range-request
  public Result video(Http.Request request, Long videoId) {
    File videoFile = getVideoFile(videoId);
    return RangeResults.ofFile(request, videoFile);
  }
  // #range-request

  private File getVideoFile(Long videoId) {
    return new File("video.mp4");
  }
}