All Downloads are FREE. Search and download functionalities are using the official Maven repository.

play.mvc.Scope Maven / Gradle / Ivy

There is a newer version: 2.6.3
Show newest version
package play.mvc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.Play;
import play.data.parsing.DataParser;
import play.data.parsing.DataParsers;
import play.data.parsing.UrlEncodedParser;
import play.i18n.Messages;
import play.libs.Codec;
import play.libs.Signer;
import play.utils.Utils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.ByteArrayInputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.*;

import static java.lang.String.join;
import static java.util.Arrays.asList;

/**
 * All application Scopes
 */
public class Scope {
    private static final Logger logger = LoggerFactory.getLogger(Scope.class);

    public static final String COOKIE_PREFIX = Play.configuration.getProperty("application.session.cookie", "PLAY");
    public static final boolean COOKIE_SECURE = "true".equals(Play.configuration.getProperty("application.session.secure", "false").toLowerCase());
    public static final String COOKIE_EXPIRATION_SETTING = "application.session.maxAge";
    public static final boolean SESSION_HTTPONLY = "true".equals(Play.configuration.getProperty("application.session.httpOnly", "false").toLowerCase());

    /**
     * Flash scope
     */
    public static class Flash {
        final Set used = new HashSet<>();
        final Map data;
        final Map out = new HashMap<>();

        public Flash() {
            this(new HashMap<>(2));
        }

        Flash(Map data) {
            this.data = data;
        }

        public void put(@Nonnull String key, @Nullable String value) {
            validateKey(key);
            data.put(key, value);
            out.put(key, value);
        }

        public void put(@Nonnull String key, @Nullable Integer value) {
            put(key, value == null ? null : value.toString());
        }

        public void put(@Nonnull String key, @Nullable Long value) {
            put(key, value == null ? null : value.toString());
        }

        public void put(@Nonnull String key, @Nullable Boolean value) {
            put(key, value == null ? null : value.toString());
        }

        public void put(@Nonnull String key, @Nullable BigDecimal value) {
            put(key, value == null ? null : value.toPlainString());
        }

        public void put(@Nonnull String key, @Nonnull Enum value) {
            put(key, value.name());
        }

        public void now(@Nonnull String key, @Nonnull  String value) {
            validateKey(key);
            data.put(key, value);
        }

        private void validateKey(@Nonnull String key) {
            if (key.contains(":")) {
                throw new IllegalArgumentException("Character ':' is invalid in a flash key.");
            }
        }

        public void error(@Nonnull String value, Object... args) {
            put("error", Messages.get(value, args));
        }

        public void success(@Nonnull String value, Object... args) {
            put("success", Messages.get(value, args));
        }

        public void discard(@Nonnull String key) {
            out.remove(key);
        }

        public void discard() {
            out.clear();
        }

        public void keep(@Nonnull String key) {
            if (data.containsKey(key)) {
                out.put(key, data.get(key));
            }
        }

        public void keep() {
            out.putAll(data);
        }

        @Nullable
        public String get(@Nonnull String key) {
            used.add(key);
            return data.get(key);
        }

        public boolean remove(@Nonnull String key) {
            return data.remove(key) != null;
        }

        public void clear() {
            data.clear();
        }

        public boolean contains(@Nonnull String key) {
            used.add(key);
            return data.containsKey(key);
        }

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

    /**
     * Session scope
     */
    public static class Session {

        private static final String AT_KEY = "___AT";
        private static final String ID_KEY = "___ID";
        protected static final String TS_KEY = "___TS";
        private static final String UA_KEY = "___UA";
        private static final Signer signer = new Signer("auth-token");

        private String id;
        Map data = new HashMap<>();
        boolean changed;

        public Session() {
        }

        protected Session(String id) {
            this.id = id;
        }

        @Nonnull
        public String getId() {
            if (id == null) {
                id = data.get(ID_KEY);
                if (id == null) {
                    id = Codec.ulid();
                    data.put(ID_KEY, id);
                }
            }
            return id;
        }

        @Nonnull
        public Map all() {
            return data;
        }

        @Nonnull
        public String getAuthenticityToken() {
            if (!data.containsKey(AT_KEY)) {
                this.put(AT_KEY, signer.sign(Codec.UUID()));
            }
            return data.get(AT_KEY);
        }

        void change() {
            changed = true;
        }

        public void put(@Nonnull String key, @Nullable String value) {
            if (key.contains(":")) {
                throw new IllegalArgumentException("Character ':' is invalid in a session key.");
            }
            change();
            if (value == null) {
                data.remove(key);
            } else {
                data.put(key, value);
            }
        }

        public void put(@Nonnull String key, @Nullable Object value) {
            change();
            if (value == null) {
                put(key, (String) null);
            } else {
                put(key, value.toString());
            }
        }

        @Nullable
        public String get(@Nonnull String key) {
            return data.get(key);
        }

        public boolean remove(@Nonnull String key) {
            change();
            return data.remove(key) != null;
        }

        public void remove(@Nonnull String... keys) {
            for (String key : keys) {
                remove(key);
            }
        }

        public void clear() {
            String timeStamp = data.get(TS_KEY);
            change();
            data.clear();
            put(TS_KEY, timeStamp);
        }

        /**
         * Returns true if the session is empty, e.g. does not contain anything else than the timestamp
         * 
         * @return true if the session is empty, otherwise false
         */
        public boolean isEmpty() {
            for (String key : data.keySet()) {
                if (!TS_KEY.equals(key) && !UA_KEY.equals(key) && !ID_KEY.equals(key)) {
                    return false;
                }
            }
            return true;
        }

        public boolean contains(@Nonnull String key) {
            return data.containsKey(key);
        }

        @Nullable
        public String getUserAgent() {
            return get(UA_KEY);
        }

        public void setUserAgent(@Nonnull String userAgent) {
            put(UA_KEY, userAgent);
        }

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

    /**
     * HTTP params
     */
    public static class Params {
        public Params(@Nonnull Http.Request request) {
            this.request = request;
        }

        private final Http.Request request;
        private boolean requestIsParsed;
        private final Map data = new LinkedHashMap<>();

        boolean rootParamsNodeIsGenerated;

        public void checkAndParse() {
            if (requestIsParsed) return;

            __mergeWith(request.routeArgs);

            if (request.querystring != null) {
                _mergeWith(UrlEncodedParser.parseQueryString(new ByteArrayInputStream(request.querystring.getBytes(request.encoding)), request.encoding));
            }
            String contentType = request.contentType;
            if (contentType != null) {
                DataParser dataParser = DataParsers.forContentType(contentType);
                if (dataParser != null) {
                    _mergeWith(dataParser.parse(request));
                }
            }
            requestIsParsed = true;
        }

        public void put(@Nonnull String key, @Nullable String value) {
            checkAndParse();
            data.put(key, new String[] { value });
            // make sure rootsParamsNode is regenerated if needed
            rootParamsNodeIsGenerated = false;
        }

        public void put(@Nonnull String key, @Nonnull String[] values) {
            checkAndParse();
            data.put(key, values);
            // make sure rootsParamsNode is regenerated if needed
            rootParamsNodeIsGenerated = false;
        }

        public void remove(@Nonnull String key) {
            checkAndParse();
            data.remove(key);
            // make sure rootsParamsNode is regenerated if needed
            rootParamsNodeIsGenerated = false;
        }

        @Nullable
        public String get(@Nonnull String key) {
            checkAndParse();
            if (data.containsKey(key)) {
                return data.get(key)[0];
            }
            return null;
        }

        public boolean contains(@Nonnull String key) {
            checkAndParse();
            return data.containsKey(key);
        }

        public boolean containsFiles() {
            checkAndParse();
            return request.args.containsKey("__UPLOADS");
        }

        @Nullable
        public String[] getAll(@Nonnull String key) {
            checkAndParse();
            return data.get(key);
        }

        @Nonnull
        public Map all() {
            checkAndParse();
            return data;
        }

        @Nonnull
        public Map allSimple() {
            checkAndParse();
            Map result = new HashMap<>();
            for (Map.Entry entry : data.entrySet()) {
                result.put(entry.getKey(), entry.getValue()[0]);
            }
            return result;
        }

        private void _mergeWith(@Nonnull Map map) {
            for (Map.Entry entry : map.entrySet()) {
                Utils.Maps.mergeValueInMap(data, entry.getKey(), entry.getValue());
            }
        }

        private void __mergeWith(@Nonnull Map map) {
            for (Map.Entry entry : map.entrySet()) {
                Utils.Maps.mergeValueInMap(data, entry.getKey(), entry.getValue());
            }
        }

        @Nonnull
        public String urlEncode(@Nonnull Http.Response response) {
            checkAndParse();
            Charset encoding = response.encoding;
            StringBuilder ue = new StringBuilder();
            for (Map.Entry entry : data.entrySet()) {
                if ("body".equals(entry.getKey())) {
                    continue;
                }
                String[] values = entry.getValue();
                for (String value : values) {
                    try {
                        ue.append(URLEncoder.encode(entry.getKey(), encoding)).append("=").append(URLEncoder.encode(value, encoding)).append("&");
                    } catch (Exception e) {
                        logger.error("Error (encoding ?)", e);
                    }
                }
            }
            return ue.toString();
        }

        public void flash(@Nonnull Flash flash, @Nonnull String... params) {
            Collection keys = params.length == 0 ? all().keySet() : asList(params);
            for (String key : keys) {
                flash.put(key, join(",", data.get(key)));
            }
        }

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

    /**
     * Render args (used in template rendering)
     */
    public static class RenderArgs {

        public final Map data = new HashMap<>(); // ThreadLocal access

        @Deprecated
        public static final ThreadLocal current = new ThreadLocal<>();

        @Deprecated
        @Nonnull
        public static RenderArgs current() {
            return current.get();
        }

        public static void removeCurrent() {
            current.remove();
        }

        public void put(@Nonnull String key, @Nullable Object arg) {
            this.data.put(key, arg);
        }

        @Nullable
        public Object get(@Nonnull String key) {
            return data.get(key);
        }

        @Nullable @SuppressWarnings("unchecked")
        public  T get(String key, Class clazz) {
            return (T) this.get(key);
        }

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy