diff --git a/arch/emailparser.ldb b/arch/emailparser.ldb deleted file mode 100644 index f540bd2..0000000 Binary files a/arch/emailparser.ldb and /dev/null differ diff --git a/src/main/java/com/fruitfactory/controllers/OFEmailController.java b/src/main/java/com/fruitfactory/controllers/OFEmailController.java index 986f482..327bfd4 100644 --- a/src/main/java/com/fruitfactory/controllers/OFEmailController.java +++ b/src/main/java/com/fruitfactory/controllers/OFEmailController.java @@ -1,5 +1,8 @@ package com.fruitfactory.controllers; +import com.fruitfactory.infrastructure.OFItemsReader; +import com.fruitfactory.interfaces.IOFItemsReader; +import com.fruitfactory.models.OFItemsContainer; import com.fruitfactory.models.response.OFEmailResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; @@ -13,11 +16,20 @@ @RequestMapping(value = "/email") public class OFEmailController { + private final IOFItemsReader reader = new OFItemsReader(); + + public OFEmailController() { + } @RequestMapping(value = "/items",method = RequestMethod.POST) public OFEmailResponse putEmailContainer(@RequestBody String body){ OFEmailResponse response = new OFEmailResponse(false,""); try { + OFItemsContainer container = reader.parseContainer(body); + + + + response.setStatus(true); }catch(Exception ex){ response.setMessage(ex.getMessage()); diff --git a/src/main/java/com/fruitfactory/infrastructure/OFConversationIndexData.java b/src/main/java/com/fruitfactory/infrastructure/OFConversationIndexData.java new file mode 100644 index 0000000..669728e --- /dev/null +++ b/src/main/java/com/fruitfactory/infrastructure/OFConversationIndexData.java @@ -0,0 +1,109 @@ +package com.fruitfactory.infrastructure; + +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Date; +import java.util.UUID; + +/** + * Created by Yariki on 2/1/2017. + */ +public class OFConversationIndexData { + + private static final int RESERVED_INDEX = 0; + private static final int CONVERSSATION_INDEX_OFFSET = 6; + private static final int CONVERSATION_INDEX_GUID_LENGHT = 16; + private static final int CONVERSATION_INDEX_LEGHT = CONVERSSATION_INDEX_OFFSET + CONVERSATION_INDEX_GUID_LENGHT; + private static final int CONVERSATION_INDEX_STRING_LENGHT = CONVERSATION_INDEX_LEGHT * 2; + private static final int CONVERSATION_RESPONSE_LEVEL_LENGHT = 5; + + private byte[] data; + private String hex_string; + + public OFConversationIndexData(byte[] data) { + this.data = data; + init(this.data); + } + + public byte getReservedValue() { + return data[RESERVED_INDEX]; + } + + public UUID getConversationUUID(String conversationTopic, boolean conversationIndexTracking) throws NoSuchAlgorithmException { + boolean useTopic = true; + UUID uuId = null; + //TODO: get raw id without any changes (according subject etc) + if (data != null && data.length >= CONVERSATION_INDEX_LEGHT && getReservedValue() == 0x01) { + byte[] uuidArray = getConversationIndexUuidArray(); + uuId = UUID.nameUUIDFromBytes(uuidArray); + useTopic = false; + } + return uuId; + } + + public boolean isDataEmpty(){ + return data == null; + } + + public byte[] getConversationIndexUuidArray() { + byte[] uuidArray = Arrays.copyOfRange(data, CONVERSSATION_INDEX_OFFSET, + CONVERSATION_INDEX_GUID_LENGHT); + return uuidArray; + } + + public Date getConversationFileTime() { + Date date = null; + byte[] filetimeArr = Arrays.copyOfRange(data, 0, CONVERSSATION_INDEX_OFFSET); + String hex_str = javax.xml.bind.DatatypeConverter.printHexBinary(filetimeArr) + "0000"; + long mil = Long.parseLong(hex_str, 16); + date = convertFILETIMEToDate(mil); + return date; + } + + private static Date convertFILETIMEToDate(long filetime) { + // Filetime Epoch is JAN 01 1601 + // java date Epoch is January 1, 1970 + // so take the number and subtract java Epoch: + long javaTime = filetime - 0x19db1ded53e8000L; + + // convert UNITS from (100 nano-seconds) to (milliseconds) + javaTime /= 10000; + + // Date(long date) + // Allocates a Date object and initializes it to represent + // the specified number of milliseconds since the standard base + // time known as "the epoch", namely January 1, 1970, 00:00:00 GMT. + Date theDate = new Date(javaTime); + + return theDate; + } + + public String getHexString() { + return hex_string; + } + + public int getConversationIndex() { + int difference = hex_string.length() - CONVERSATION_INDEX_STRING_LENGHT; + if (difference > 0) { + return (difference / (CONVERSATION_RESPONSE_LEVEL_LENGHT * 2)) + 1; + } + return 0; + } + + public String getOutlookConversationId() { + if (hex_string.length() < CONVERSATION_INDEX_STRING_LENGHT) { + return ""; + } + String temp = hex_string.substring(CONVERSSATION_INDEX_OFFSET * 2, CONVERSATION_INDEX_STRING_LENGHT); + return temp; + } + + private void init(byte[] buffer) { + if (buffer == null || buffer.length == 0) { + return; + } + hex_string = javax.xml.bind.DatatypeConverter.printHexBinary(buffer); + } + + +} diff --git a/src/main/java/com/fruitfactory/infrastructure/OFDataParse.java b/src/main/java/com/fruitfactory/infrastructure/OFDataParse.java new file mode 100644 index 0000000..93deb02 --- /dev/null +++ b/src/main/java/com/fruitfactory/infrastructure/OFDataParse.java @@ -0,0 +1,103 @@ +package com.fruitfactory.infrastructure; + +import com.fasterxml.jackson.databind.deser.Deserializers; +import com.fruitfactory.infrastructure.core.OFDataProcess; +import com.fruitfactory.interfaces.IOFDataRepositoryPipe; +import com.fruitfactory.models.OFAttachment; +import com.fruitfactory.models.OFEmail; +import com.fruitfactory.models.OFItemsContainer; +import com.sun.xml.internal.messaging.saaj.util.ByteInputStream; +import org.apache.tika.Tika; +import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; +import org.apache.tika.metadata.Metadata; + +/** + * Created by Yariki on 2/1/2017. + */ +public class OFDataParse extends OFDataProcess { + + private final IOFDataRepositoryPipe dataTarget; + + private final Tika tika = new Tika(); + + public OFDataParse(IOFDataRepositoryPipe dataSource, IOFDataRepositoryPipe dataTarget, String name) { + super(dataSource, name); + this.dataTarget = dataTarget; + } + + @Override + protected void processData(OFItemsContainer container) { + try { + processEmail(container); + processAttachments(container); + dataTarget.pushData(container); + }catch (Exception ex){ + + } + } + + private void processAttachments(OFItemsContainer container) { + if(container.getAttachments() == null || container.getAttachments().isEmpty()){ + return; + } + try { + for(OFAttachment attachment : container.getAttachments()){ + processAttachment(attachment); + } + }catch (Exception ex){ + + } + } + + private void processAttachment(OFAttachment attachment) { + if(attachment.getContent() == null){ + return; + } + try{ + String parsedContent = ""; + byte[] byteBuffer = Base64.decode(attachment.getContent()); + parsedContent = tika.parseToString(new ByteInputStream(byteBuffer,byteBuffer.length), new Metadata()); + attachment.setContent(parsedContent); + }catch (Exception ex){ + + } + } + + private void processEmail(OFItemsContainer container){ + if(container.getEmail() == null){ + return; + } + OFEmail email = container.getEmail(); + try { + OFConversationIndexData indexData = new OFConversationIndexData(email.getConversationindex().getBytes()) ; + email.setConversationindex(Integer.toString(indexData.getConversationIndex())); + email.setOutlookconversationid(indexData.getOutlookConversationId()); + String body = null; + String htmlBody = null; + try { + body = new String(Base64.decode(email.getContent())); + }catch (Exception ex){ + + } + try { + htmlBody = new String(Base64.decode(email.getHtmlcontent())); + }catch(Exception ex){ + + } + String analyzedContent = null; + + if(body != null && !body.isEmpty()){ + byte[] bytes = body.getBytes(); + analyzedContent = tika.parseToString(new ByteInputStream(bytes,bytes.length),new Metadata()); + } else if(htmlBody != null && !htmlBody.isEmpty()){ + byte[] bytes = htmlBody.getBytes(); + analyzedContent = tika.parseToString(new ByteInputStream(bytes,bytes.length),new Metadata()); + } + email.setAnalyzedcontent(analyzedContent); + + }catch (Exception ex){ + + } + } + +} diff --git a/src/main/java/com/fruitfactory/infrastructure/OFDateRepositoryPipe.java b/src/main/java/com/fruitfactory/infrastructure/OFDateRepositoryPipe.java new file mode 100644 index 0000000..6fdf981 --- /dev/null +++ b/src/main/java/com/fruitfactory/infrastructure/OFDateRepositoryPipe.java @@ -0,0 +1,52 @@ +package com.fruitfactory.infrastructure; + +import com.fruitfactory.interfaces.IOFDataRepositoryPipe; +import com.fruitfactory.models.OFItemsContainer; + +import java.util.concurrent.LinkedBlockingQueue; + +/** + * Created by Yariki on 1/29/2017. + */ +public class OFDateRepositoryPipe implements IOFDataRepositoryPipe { + + private LinkedBlockingQueue dataContainer; + private final Object syncObject = new Object(); + private volatile boolean available = false; + + public OFDateRepositoryPipe() { + dataContainer = new LinkedBlockingQueue<>(); + } + + @Override + public synchronized void pushData(OFItemsContainer container) { + try{ + dataContainer.put(container); + available = true; + syncObject.notifyAll(); + }catch(InterruptedException ie){ + + }catch (Exception ex){ + + } + } + + @Override + public synchronized void stopNotify() { + syncObject.notifyAll(); + } + + @Override + public synchronized OFItemsContainer popData() { + if(!available){ + try { + syncObject.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + OFItemsContainer container = dataContainer.poll(); + available = !dataContainer.isEmpty(); + return container; + } +} diff --git a/src/main/java/com/fruitfactory/infrastructure/OFItemsReader.java b/src/main/java/com/fruitfactory/infrastructure/OFItemsReader.java new file mode 100644 index 0000000..76547d5 --- /dev/null +++ b/src/main/java/com/fruitfactory/infrastructure/OFItemsReader.java @@ -0,0 +1,23 @@ +package com.fruitfactory.infrastructure; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.fruitfactory.interfaces.IOFItemsReader; +import com.fruitfactory.models.OFItemsContainer; + +/** + * Created by Yariki on 1/29/2017. + */ +public class OFItemsReader implements IOFItemsReader { + + public OFItemsReader() { + + } + + @Override + public OFItemsContainer parseContainer(String body) { + Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").create(); + OFItemsContainer container = gson.fromJson(body,OFItemsContainer.class); + return container; + } +} diff --git a/src/main/java/com/fruitfactory/infrastructure/core/OFDataProcess.java b/src/main/java/com/fruitfactory/infrastructure/core/OFDataProcess.java new file mode 100644 index 0000000..02fed2b --- /dev/null +++ b/src/main/java/com/fruitfactory/infrastructure/core/OFDataProcess.java @@ -0,0 +1,40 @@ +package com.fruitfactory.infrastructure.core; + +import com.fruitfactory.interfaces.IOFDataProcessThread; +import com.fruitfactory.interfaces.IOFDataRepositoryPipe; +import com.fruitfactory.models.OFItemsContainer; + +/** + * Created by Yariki on 2/1/2017. + */ +public abstract class OFDataProcess extends Thread implements IOFDataProcessThread{ + + private final IOFDataRepositoryPipe dataSource; + private volatile boolean stop = false; + + public OFDataProcess(IOFDataRepositoryPipe dataSource, String name) { + super(name); + this.dataSource = dataSource; + } + + @Override + public synchronized void run() { + while (!stop){ + OFItemsContainer container = null; + try { + container = dataSource.popData(); + processData(container); + }catch(Exception ex){ + + } + } + } + + protected abstract void processData(OFItemsContainer container); + + @Override + public void close() { + dataSource.stopNotify(); + stop = true; + } +} diff --git a/src/main/java/com/fruitfactory/interfaces/IOFDataProcessThread.java b/src/main/java/com/fruitfactory/interfaces/IOFDataProcessThread.java new file mode 100644 index 0000000..23d6255 --- /dev/null +++ b/src/main/java/com/fruitfactory/interfaces/IOFDataProcessThread.java @@ -0,0 +1,11 @@ +package com.fruitfactory.interfaces; + +/** + * Created by Yariki on 1/29/2017. + */ +public interface IOFDataProcessThread { + + void start(); + + void close(); +} diff --git a/src/main/java/com/fruitfactory/interfaces/IOFDataRepositoryPipe.java b/src/main/java/com/fruitfactory/interfaces/IOFDataRepositoryPipe.java new file mode 100644 index 0000000..88c669c --- /dev/null +++ b/src/main/java/com/fruitfactory/interfaces/IOFDataRepositoryPipe.java @@ -0,0 +1,16 @@ +package com.fruitfactory.interfaces; + +import com.fruitfactory.models.OFItemsContainer; + +/** + * Created by Yariki on 1/29/2017. + */ +public interface IOFDataRepositoryPipe { + + void pushData(OFItemsContainer container) throws InterruptedException; + + OFItemsContainer popData(); + + void stopNotify(); + +} diff --git a/src/main/java/com/fruitfactory/interfaces/IOFItemsReader.java b/src/main/java/com/fruitfactory/interfaces/IOFItemsReader.java new file mode 100644 index 0000000..d680970 --- /dev/null +++ b/src/main/java/com/fruitfactory/interfaces/IOFItemsReader.java @@ -0,0 +1,12 @@ +package com.fruitfactory.interfaces; + +import com.fruitfactory.models.OFItemsContainer; + +/** + * Created by Yariki on 1/29/2017. + */ +public interface IOFItemsReader { + + OFItemsContainer parseContainer(String body); + +} diff --git a/src/main/java/com/fruitfactory/models/OFEmail.java b/src/main/java/com/fruitfactory/models/OFEmail.java index 485fe8b..c6b8757 100644 --- a/src/main/java/com/fruitfactory/models/OFEmail.java +++ b/src/main/java/com/fruitfactory/models/OFEmail.java @@ -276,4 +276,5 @@ public void setStoreid(String storeid) { this.storeid = storeid; } + }