001/**
002 * Copyright (C) 2006-2022 Talend Inc. - www.talend.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.talend.sdk.component.server.service.jcache;
017
018import java.lang.annotation.Annotation;
019import java.util.Arrays;
020import java.util.UUID;
021import java.util.stream.Stream;
022
023import javax.cache.annotation.CacheInvocationParameter;
024import javax.cache.annotation.CacheKeyGenerator;
025import javax.cache.annotation.CacheKeyInvocationContext;
026import javax.cache.annotation.GeneratedCacheKey;
027import javax.enterprise.context.ApplicationScoped;
028import javax.inject.Inject;
029import javax.ws.rs.core.Context;
030import javax.ws.rs.core.HttpHeaders;
031import javax.ws.rs.core.Request;
032import javax.ws.rs.core.UriInfo;
033
034import lombok.extern.slf4j.Slf4j;
035
036@Slf4j
037@ApplicationScoped
038public class FrontCacheKeyGenerator implements CacheKeyGenerator {
039
040    @Inject
041    @Context
042    private Request request;
043
044    @Inject
045    @Context
046    private UriInfo uriInfo;
047
048    @Inject
049    @Context
050    private HttpHeaders headers;
051
052    @Override
053    public GeneratedCacheKey
054            generateCacheKey(final CacheKeyInvocationContext<? extends Annotation> cacheKeyInvocationContext) {
055        return new GeneratedCacheKeyImpl(Stream
056                .concat(Stream.of(cacheKeyInvocationContext.getKeyParameters()).map(CacheInvocationParameter::getValue),
057                        getContextualKeys())
058                .toArray(Object[]::new));
059    }
060
061    private Stream<Object> getContextualKeys() {
062        try {
063            return Stream
064                    .of(uriInfo.getPath(), uriInfo.getQueryParameters(), headers.getLanguage(),
065                            headers.getHeaderString(HttpHeaders.ACCEPT),
066                            headers.getHeaderString(HttpHeaders.ACCEPT_ENCODING));
067        } catch (Exception e) {
068            log.debug("[getContextualKeys] context not applicable: {}", e.getMessage());
069            return Stream.of(UUID.randomUUID());
070        }
071    }
072
073    private static class GeneratedCacheKeyImpl implements GeneratedCacheKey {
074
075        private final Object[] params;
076
077        private final int hash;
078
079        private GeneratedCacheKeyImpl(final Object[] parameters) {
080            params = parameters;
081            hash = Arrays.deepHashCode(parameters);
082        }
083
084        @Override
085        public boolean equals(final Object o) {
086            if (this == o) {
087                return true;
088            }
089            if (o == null || getClass() != o.getClass()) {
090                return false;
091            }
092            final GeneratedCacheKeyImpl that = GeneratedCacheKeyImpl.class.cast(o);
093            return Arrays.deepEquals(params, that.params);
094
095        }
096
097        @Override
098        public int hashCode() {
099            return hash;
100        }
101    }
102}