001/**
002 * Copyright (C) 2006-2025 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.stream.Stream;
021
022import javax.cache.annotation.CacheInvocationParameter;
023import javax.cache.annotation.CacheKeyGenerator;
024import javax.cache.annotation.CacheKeyInvocationContext;
025import javax.cache.annotation.GeneratedCacheKey;
026import javax.enterprise.context.ApplicationScoped;
027import javax.inject.Inject;
028import javax.ws.rs.core.Context;
029import javax.ws.rs.core.HttpHeaders;
030import javax.ws.rs.core.Request;
031import javax.ws.rs.core.UriInfo;
032
033import lombok.extern.slf4j.Slf4j;
034
035@Slf4j
036@ApplicationScoped
037public class FrontCacheKeyGenerator implements CacheKeyGenerator {
038
039    @Inject
040    @Context
041    private Request request;
042
043    @Inject
044    @Context
045    private UriInfo uriInfo;
046
047    @Inject
048    @Context
049    private HttpHeaders headers;
050
051    @Override
052    public GeneratedCacheKey
053            generateCacheKey(final CacheKeyInvocationContext<? extends Annotation> cacheKeyInvocationContext) {
054        return new GeneratedCacheKeyImpl(Stream
055                .concat(Stream.of(cacheKeyInvocationContext.getKeyParameters()).map(CacheInvocationParameter::getValue),
056                        getContextualKeys())
057                .toArray(Object[]::new));
058    }
059
060    private Stream<Object> getContextualKeys() {
061        try {
062            return Stream
063                    .of(uriInfo.getPath(), uriInfo.getQueryParameters(), headers.getLanguage(),
064                            headers.getHeaderString(HttpHeaders.ACCEPT),
065                            headers.getHeaderString(HttpHeaders.ACCEPT_ENCODING));
066        } catch (Exception e) {
067            log.debug("[getContextualKeys] context not applicable: {}", e.getMessage());
068            return Stream.empty();
069        }
070    }
071
072    private static class GeneratedCacheKeyImpl implements GeneratedCacheKey {
073
074        private final Object[] params;
075
076        private final int hash;
077
078        private GeneratedCacheKeyImpl(final Object[] parameters) {
079            params = parameters;
080            hash = Arrays.deepHashCode(parameters);
081        }
082
083        @Override
084        public boolean equals(final Object o) {
085            if (this == o) {
086                return true;
087            }
088            if (o == null || getClass() != o.getClass()) {
089                return false;
090            }
091            final GeneratedCacheKeyImpl that = GeneratedCacheKeyImpl.class.cast(o);
092            return Arrays.deepEquals(params, that.params);
093
094        }
095
096        @Override
097        public int hashCode() {
098            return hash;
099        }
100    }
101}