/** * Copyright © 2014 Instituto Superior Técnico * * This file is part of FenixEdu CMS. * * FenixEdu CMS is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * FenixEdu CMS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with FenixEdu CMS. If not, see <http://www.gnu.org/licenses/>. */ package org.fenixedu.cms.domain; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import com.google.common.collect.ImmutableMap; import com.google.common.hash.Hashing; import com.google.common.io.ByteStreams; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonParser; public class CMSThemeFiles { private final Map<String, CMSThemeFile> files; private final String checksum; public CMSThemeFiles(Map<String, CMSThemeFile> files) { this.files = ImmutableMap.copyOf(files); this.checksum = computeChecksum(); } public CMSThemeFiles(byte[] bytes) { this.files = getMapFromStream(bytes); this.checksum = computeChecksum(); } private String computeChecksum() { StringBuilder builder = new StringBuilder(); this.files.values().forEach(file -> { builder.append(Hashing.sha256().hashBytes(file.getContent()).toString()); }); return Hashing.murmur3_128().hashString(builder, StandardCharsets.UTF_8).toString().substring(0, 16); } public CMSThemeFile getFileForPath(String path) { return files.get(path); } public Collection<CMSThemeFile> getFiles() { return files.values().stream().sorted(Comparator.comparing(CMSThemeFile::getFileName)).collect(Collectors.toList()); } public JsonArray toJson() { JsonArray array = new JsonArray(); for (CMSThemeFile file : files.values()) { array.add(file.toJson()); } return array; } public byte[] externalize() { try { ByteArrayOutputStream out = new ByteArrayOutputStream(); GZIPOutputStream stream = new GZIPOutputStream(out); stream.write(toJson().toString().getBytes(StandardCharsets.UTF_8)); stream.close(); return out.toByteArray(); } catch (IOException e) { throw new RuntimeException("Could not externalize CMSThemeFiles!", e); } } private Map<String, CMSThemeFile> getMapFromStream(byte[] bytes) { try { GZIPInputStream stream = new GZIPInputStream(new ByteArrayInputStream(bytes)); byte[] unzipped = ByteStreams.toByteArray(stream); String json = new String(unzipped, StandardCharsets.UTF_8); JsonArray array = new JsonParser().parse(json).getAsJsonArray(); ImmutableMap.Builder<String, CMSThemeFile> files = ImmutableMap.builder(); for (JsonElement file : array) { CMSThemeFile themeFile = new CMSThemeFile(file.getAsJsonObject()); files.put(themeFile.getFullPath(), themeFile); } return files.build(); } catch (IOException e) { throw new RuntimeException("Could not internalize CMSThemeFiles!", e); } } public CMSThemeFiles with(CMSThemeFile file) { Map<String, CMSThemeFile> files = new HashMap<String, CMSThemeFile>(this.files); files.put(file.getFullPath(), file); return new CMSThemeFiles(files); } public CMSThemeFiles without(String path) { Map<String, CMSThemeFile> files = new HashMap<String, CMSThemeFile>(this.files); files.remove(path); return new CMSThemeFiles(files); } public CMSThemeFiles without(String[] paths){ Map<String, CMSThemeFile> files = new HashMap<String, CMSThemeFile>(this.files); for(String path : paths){ files.remove(path); } return new CMSThemeFiles(files); } public long getTotalSize() { return files.values().stream().mapToLong(CMSThemeFile::getFileSize).sum(); } public boolean checksumMatches(CMSThemeFiles files) { return this.checksum.equals(files.checksum); } public String getChecksum() { return this.checksum; } }