diff --git a/converters/src/main/java/org/dukecon/server/convert/DoagSpeakerImageService.groovy b/converters/src/main/java/org/dukecon/server/convert/DoagSpeakerImageService.groovy new file mode 100644 index 00000000..dcf80d1f --- /dev/null +++ b/converters/src/main/java/org/dukecon/server/convert/DoagSpeakerImageService.groovy @@ -0,0 +1,67 @@ +package org.dukecon.server.convert + +import groovy.util.logging.Slf4j +import org.dukecon.adapter.ResourceWrapper +import org.dukecon.server.conference.SpeakerImageService + +import java.security.MessageDigest + +@Slf4j +class DoagSpeakerImageService implements SpeakerImageService { + + private final String path + + DoagSpeakerImageService(String path) { + this.path = path + } + + String addImage(byte[] content, String filename = null) { + return this.addImage(Base64.encoder.encodeToString(content), filename) + } + + String addImage(String contentBase64, String filename = null) { + log.trace("Adding speaker image from '{}')", filename ? "file >${filename}<" : "Image Data: >${contentBase64?.substring(0, 10)}<") + + String md5Hash = md5(contentBase64) + + //create image resource + def final image = new ImageWithName("${md5Hash}.${fileEnding(contentBase64)}", Base64.decoder.decode(contentBase64)) + + //write image resource to file + def pathInFilesystem = new File(this.path) + if(!pathInFilesystem.exists()) + pathInFilesystem.mkdir() + image.writeToDisk(this.path) + + return md5Hash + } + + @Override + SpeakerImageService.ImageWithName getImage(String md5Hash) { + throw new IllegalStateException("should not be called from converter") + } + + private md5(String s) { + MessageDigest digest = MessageDigest.getInstance("MD5") + digest.update(s.bytes); + new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0') + } + + private fileEnding(String content) { + switch (content) { + case ~/^iVBO.*/: + return 'png' + case ~/^R0.*/: + return 'gif' + case ~$/^/9j/*/$: + default: + return 'jpg' + } + } + + @Override + Map getImages() { + throw new IllegalStateException("should not be called from converter") + } +} + diff --git a/converters/src/main/java/org/dukecon/server/convert/DummySpeakerImageService.groovy b/converters/src/main/java/org/dukecon/server/convert/DummySpeakerImageService.groovy index 3f379c29..e69de29b 100644 --- a/converters/src/main/java/org/dukecon/server/convert/DummySpeakerImageService.groovy +++ b/converters/src/main/java/org/dukecon/server/convert/DummySpeakerImageService.groovy @@ -1,40 +0,0 @@ -package org.dukecon.server.convert - -import org.dukecon.server.conference.SpeakerImageService - -/** - * Will be obsolete as soon as conference provider will be disabled in dukecon_server implementation. This interface and - * its references can be removed when speaker images will be saved as static files. - */ -@Deprecated -class DummySpeakerImageService implements SpeakerImageService { - @Override - Map getImages() { - return null - } - - @Override - String addImage(byte ... content) { - return null - } - - @Override - String addImage(byte[] content, String filename) { - return null - } - - @Override - String addImage(String contentBase64) { - return null - } - - @Override - String addImage(String contentBase64, String filename) { - return null - } - - @Override - ImageWithName getImage(String md5Hash) { - return null - } -} diff --git a/converters/src/main/java/org/dukecon/server/convert/GenerateDukecon.groovy b/converters/src/main/java/org/dukecon/server/convert/GenerateDukecon.groovy index 9bf31f27..06e89800 100644 --- a/converters/src/main/java/org/dukecon/server/convert/GenerateDukecon.groovy +++ b/converters/src/main/java/org/dukecon/server/convert/GenerateDukecon.groovy @@ -47,7 +47,7 @@ class GenerateDukecon { ConferenceDataExtractor conferenceDataExtractor = conferenceDataExtractorClass.getConstructor(ConferencesConfiguration.Conference.class, RawDataMapper.class, SpeakerImageService.class) - .newInstance(conferenceConfig, rawDataMapper, new DummySpeakerImageService()) + .newInstance(conferenceConfig, rawDataMapper, new DoagSpeakerImageService('images')) Conference conference = conferenceDataExtractor.conference ObjectMapper objectMapper = new ObjectMapper() String conferenceStartDirectoryName = "htdocs/rest/${conferenceConfig.conference}/${conferenceConfig.year}/rest" @@ -69,6 +69,7 @@ class GenerateDukecon { stylesCssFile.getParentFile().mkdirs() stylesCssFile.write(stylesCssResource.getContent()) log.info("Created {}", stylesCssFile.absolutePath) + } } diff --git a/converters/src/test/resources/conferences-javaland.yml b/converters/src/test/resources/conferences-javaland.yml index 90fa871b..77a9b83d 100644 --- a/converters/src/test/resources/conferences-javaland.yml +++ b/converters/src/test/resources/conferences-javaland.yml @@ -6,9 +6,9 @@ conference: javaland year: 2019 talksUri: - eventsData: 'javaland2019/eventsData.json' - speakersData: 'javaland2019/speakersData.json' - additionalData: 'javaland2019/additionalData.json' + eventsData: 'file:javaland2019/eventsData.json' + speakersData: 'file:javaland2019/speakersData.json' + additionalData: 'file:javaland2019/additionalData.json' backupUri: javaland-2019-backup.raw url: 'http://${conference}.dukecon.org/${year}' homeUrl: 'http://www.javaland.eu' diff --git a/repositories/src/main/java/org/dukecon/server/conference/SpeakerImageService.groovy b/repositories/src/main/java/org/dukecon/server/conference/SpeakerImageService.groovy index 2d55bd31..97eaa568 100644 --- a/repositories/src/main/java/org/dukecon/server/conference/SpeakerImageService.groovy +++ b/repositories/src/main/java/org/dukecon/server/conference/SpeakerImageService.groovy @@ -1,5 +1,6 @@ package org.dukecon.server.conference +import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream import org.springframework.stereotype.Service /** @@ -15,6 +16,21 @@ interface SpeakerImageService { this.filename = filename this.content = content } + + void writeToDisk(String path) { + FileOutputStream outputStream + String fileWithPath = path + File.separator + this.filename + try { + outputStream = new FileOutputStream(fileWithPath) + outputStream.write(this.content) + outputStream.flush() + } catch(Exception e) { + throw new RuntimeException("could not write file: $fileWithPath ", e) + } finally { + if(outputStream) + outputStream.close() + } + } } Map getImages() @@ -23,4 +39,4 @@ interface SpeakerImageService { String addImage(String contentBase64) String addImage(String contentBase64, String filename) ImageWithName getImage(String md5Hash) -} \ No newline at end of file +}