/* * #%L * ACS AEM Commons Bundle * %% * Copyright (C) 2015 Adobe * %% * 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. * #L% */ package com.adobe.acs.commons.httpcache.store.mem.impl; import com.adobe.acs.commons.httpcache.exception.HttpCacheDataStreamException; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import org.apache.commons.io.IOUtils; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; /** * Value for cache item in mem store. */ class MemCachePersistenceObject { /** Response status **/ private int status; /** Response character encoding */ private String charEncoding; /** Response content type */ private String contentType; /** Response headers */ Multimap<String, String> headers; /** Byte array to hold the data from the stream */ private byte[] bytes; AtomicInteger count = new AtomicInteger(0); /** * Create <code>MemCachePersistenceObject</code>. Use <code>buildForCaching</code> method to initialize parameters. */ MemCachePersistenceObject() { } /** * Construct a Mem cache value suitable for caching. This constructor takes deep copy of parameters making the * object suitable for caching avoiding any memory leaks. * * @param charEncoding * @param contentType * @param headers * @param dataInputStream * @throws HttpCacheDataStreamException */ public MemCachePersistenceObject buildForCaching(int status, String charEncoding, String contentType, Map<String, List<String>> headers, InputStream dataInputStream) throws HttpCacheDataStreamException { this.status = status; this.charEncoding = charEncoding; this.contentType = contentType; // Iterate headers and take a copy. this.headers = HashMultimap.create(); for (Map.Entry<String, List<String>> entry : headers.entrySet()) { for (String value : entry.getValue()) { if (!"Sling-Tracer-Protocol-Version".equals(entry.getKey()) && !"Sling-Tracer-Request-Id".equals(entry.getKey())) { // Do NOT cache Sling Tracer headers as this makes debugging difficult and confusing! this.headers.put(entry.getKey(), value); } } } // Read input stream and place it in a byte array. try { this.bytes = IOUtils.toByteArray(dataInputStream); } catch (IOException e) { throw new HttpCacheDataStreamException("Unable to get byte array out of stream", e); } return this; } /** * Get response status * @return the status code */ public int getStatus() { return status; } /** * Get char encoding. * * @return */ public String getCharEncoding() { return charEncoding; } /** * Get content type * * @return */ public String getContentType() { return contentType; } /** * Get the header in multimap format. * * @return Returned in <code>Map<String, List<String>></code> format. */ public Map<String, List<String>> getHeaders() { Map<String, List<String>> map = new HashMap<String, List<String>>(); // Convert com.google.common.collect.AbstractMapBasedMultimap$WrappedSet to List<String> value to avoid cast // exception for (Map.Entry<String, Collection<String>> entry : Multimaps.asMap(headers).entrySet()) { map.put(entry.getKey(), new ArrayList<String>(entry.getValue())); } return map; } /** * Get the data byte array * * @return */ public byte[] getBytes() { return bytes; } /** * Increments the hit for this cache entry. */ public void incrementHitCount() { count.incrementAndGet(); } /** * @return the number of times this cache entry has been requested */ public int getHitCount() { return count.get(); } }