Exemplo n.º 1
0
 /**
  * Method createMetaContents.
  *
  * @param message
  * @return
  */
 private String createMetaContents(IMessageContext message) {
   Envelope envelope = message.getEnvelope();
   Partition partition = message.getPartition();
   StringBuffer buf = new StringBuffer(200);
   buf.append("Subject: ").append(envelope.getSubject()).append(MetaMessageWriterStage.NEW_LINE);
   Date sentDate = envelope.getSentDate();
   if (sentDate != null) {
     buf.append("Date: ")
         .append(MetaMessageWriterStage.s_rfc822DateFormat.format(sentDate))
         .append(MetaMessageWriterStage.NEW_LINE);
   }
   // If there is a header based sender that was found by the vault box, then use it.
   // The header based sender is usually in a nicer format "Bob Smith" <*****@*****.**>
   // instead of just the email address of the sender [email protected]
   String from;
   if (envelope.getHeaderBasedSender() != null && envelope.getHeaderBasedSender().length() > 3) {
     from = envelope.getHeaderBasedSender();
   } else {
     from = envelope.getSender();
   }
   if (from != null) {
     buf.append("From: ").append(from).append(MetaMessageWriterStage.NEW_LINE);
   }
   buf.append("Message-ID: ");
   buf.append(envelope.getSize());
   buf.append("__");
   buf.append("&mid=");
   buf.append(message.getInternalId());
   buf.append("&svr=");
   buf.append(partition.getServer());
   buf.append("&p=");
   buf.append(partition.getId());
   buf.append(MetaMessageWriterStage.NEW_LINE);
   return buf.toString();
 }
Exemplo n.º 2
0
  /**
   * Validates that the stage properly identifies when a message should be restored
   *
   * @throws Exception on error
   */
  @Test
  public void testRestoreMissingMessage() throws Exception {
    List<IMessageContext> msgs = new ArrayList<IMessageContext>();
    IMessageContext msg = EasyMock.createStrictMock(IMessageContext.class);
    msgs.add(msg);

    // isUpdate & does not need restorage == don't store!
    EasyMock.expect(msg.shouldReplaceStorage()).andReturn(false);
    EasyMock.expect(msg.isUpdate()).andReturn(true);
    EasyMock.replay(msg);
    List<IMessageContext> needsStorage = Itertools.filter(PartitionStoreStage.NEEDS_STORAGE, msgs);
    assertTrue(needsStorage.isEmpty());
    EasyMock.verify(msg);
    EasyMock.reset(msg);

    // should replace storage will bypass the other tests
    EasyMock.expect(msg.shouldReplaceStorage()).andReturn(true);
    EasyMock.replay(msg);
    needsStorage = Itertools.filter(PartitionStoreStage.NEEDS_STORAGE, msgs);
    assertEquals(1, needsStorage.size());
    EasyMock.verify(msg);
    EasyMock.reset(msg);

    // !isUpdate & no filepath & does not need restorage == store!
    EasyMock.expect(msg.shouldReplaceStorage()).andReturn(false);
    EasyMock.expect(msg.isUpdate()).andReturn(false);
    EasyMock.expect(msg.getStoreFileSubPath()).andReturn(null);
    EasyMock.replay(msg);
    needsStorage = Itertools.filter(PartitionStoreStage.NEEDS_STORAGE, msgs);
    assertEquals(1, needsStorage.size());
    EasyMock.verify(msg);
    EasyMock.reset(msg);
  }
Exemplo n.º 3
0
  protected void failMessage(IMessageContext message, Exception ex) {
    if (ex != null) {
      MessageProcessError mpe = new MessageProcessError(ex, getName());
      message.addError(mpe);
    }

    m_importer.audit(message, getName(), null, ex);
    m_importer.importFailed(message, ex);
  }
Exemplo n.º 4
0
 /**
  * Method writeMetaFiles. This uses the MailStoreFileManger API to store files remotely.
  *
  * @param message
  */
 private boolean writeMetaFiles(IMessageContext message) {
   String metaContents = createMetaContents(message);
   String metaFileName = new File(message.getStoreFileSubPath()).getName();
   Collection<MailStoreFileManager.MetaMessageDescriptor> msgs =
       new ArrayList<MailStoreFileManager.MetaMessageDescriptor>();
   if (!CollectionsUtils.isNullOrEmpty(message.getResolvedRecipients())) {
     for (ReplicatedRecipient rr : message.getResolvedRecipients()) {
       msgs.add(
           new MailStoreFileManager.MetaMessageDescriptor(
               message.getInternalId(),
               rr.getMaildir(),
               metaFileName,
               message.getEnvelope().getSentDate(),
               message.getEnvelope().getReceivedDate(),
               false,
               rr.getState().toInt()));
     }
   }
   if (message.getResolvedSender() != null) {
     ReplicatedRecipient rr = message.getResolvedSender();
     msgs.add(
         new MailStoreFileManager.MetaMessageDescriptor(
             message.getInternalId(),
             rr.getMaildir(),
             metaFileName,
             message.getEnvelope().getSentDate(),
             message.getEnvelope().getReceivedDate(),
             true,
             rr.getState().toInt()));
   }
   IMailStoreFileManager imsfm = ManagementContainer.getInstance().getMailStoreFileManager();
   if (imsfm.storeMetaMessage(msgs, metaContents)) {
     m_importer.audit(message, getName(), metaFileName);
     return true;
   } else {
     m_importer.getStatComponent().addToValue(STAT_META_STORE_FAILURES, 1);
     m_importer.consumerImportFailed(message, true);
     return false;
   }
 }
Exemplo n.º 5
0
  @Override
  protected boolean processMessage(IMessageContext message) throws CapabilitiesLoadException {
    Capabilities caps = message.getCustomer().getCapabilities();
    if (caps == null) throw new CapabilitiesLoadException();
    Capabilities.ActiveMailboxSupport amSupportCap =
        caps.getEnumCapability(
            Capabilities.CAP_ACTIVEMAILBOX_SUPPORT, Capabilities.ActiveMailboxSupport.NONE);
    boolean useNFS =
        ManagementContainer.getInstance()
            .getConfiguration()
            .getBooleanProperty(CONFIG_USE_NFS, DEFAULT_USE_NFS);

    if (amSupportCap == Capabilities.ActiveMailboxSupport.AM_CUSTOMER_ENCRYPTION
        || message.getEnvelope().isCustomerEncrypted()) {
      if (!useNFS) {
        return writeMetaFiles(message);
      } else {
        // Direct nfs usage; doesn't occur in production (mmfs is used instead)
        boolean success = true;
        String metaContents = createMetaContents(message);
        String metaFileName = new File(message.getStoreFileSubPath()).getName();
        if (!CollectionsUtils.isNullOrEmpty(message.getResolvedRecipients())) {
          for (Iterator<ReplicatedRecipient> it = message.getResolvedRecipients().iterator();
              it.hasNext(); ) {
            ReplicatedRecipient rr = it.next();
            if (!writeMetaFile(rr, message, false, metaFileName, metaContents)) {
              success = false;
            }
          }
        }
        if (message.getResolvedSender() != null) {
          if (!writeMetaFile(
              message.getResolvedSender(), message, true, metaFileName, metaContents)) {
            success = false;
          }
        }
        if (!success) {
          m_importer.getStatComponent().addToValue(STAT_META_STORE_FAILURES, 1);
          m_importer.consumerImportFailed(message, true);
          return false;
        }
      }
    }
    return true;
  }
Exemplo n.º 6
0
  /**
   * Method writeMetaFile. This uses NFS to store files remotely. Not used in production, mmfs is
   * used instead.
   *
   * @param recpt
   * @param message
   * @param isSender
   * @param metaFileName
   * @param metaContents
   */
  private boolean writeMetaFile(
      ReplicatedRecipient recpt,
      IMessageContext message,
      boolean isSender,
      String metaFileName,
      String metaContents) {
    Envelope env = message.getEnvelope();
    ActiveMailboxFolder folder =
        ActiveMailboxFolder.getFolder(recpt.getMaildir(), env.getSentDate(), isSender);
    folder.initialize();
    File metaMsgDir;
    CustomerState userState = recpt.getState();
    if (userState == CustomerState.ACTIVE || userState == CustomerState.TEST) {
      metaMsgDir = folder.getMeta();
    } else {
      metaMsgDir = folder.getCur();
    }
    if (!metaMsgDir.exists()) {
      m_importer.auditError(
          message, getName(), metaMsgDir + " doesn't exist while trying to create meta-file");
    }
    File metaMsgFile = new File(metaMsgDir, metaFileName);

    BufferedWriter out = null;
    try {
      try {
        out = new BufferedWriter(new FileWriter(metaMsgFile));
        out.write(metaContents);
      } finally {
        if (out != null) out.close();
      }
      // preserve arrival timestamp
      metaMsgFile.setLastModified(env.getReceivedDate().getTime());
      m_importer.audit(message, getName(), metaMsgFile.getAbsolutePath());
    } catch (IOException ex) {
      m_logger.error("Error creating file " + metaMsgFile.getPath(), ex);
      return false;
    }
    return true;
  }
Exemplo n.º 7
0
  private List<IMessageContext> generateMockMessageContext(int start, int count, Customer cust)
      throws Exception {
    final String indexFilePrefix = "INDEX";
    final String contentFilePrefix = "CONTENT";
    int time = (int) new Date().getTime();

    List<IMessageContext> arr = new ArrayList<IMessageContext>();
    for (int x = 0; x < count; x++) {
      File indexFile = new File(m_tmpDir, indexFilePrefix + x + ".ftp");
      File contentFile = new File(m_tmpDir, contentFilePrefix + x + ".ftp");
      if (!indexFile.exists()) {
        assertTrue("Failed to create index file.", indexFile.createNewFile());
      }
      if (!contentFile.exists()) {
        assertTrue("Failed to create content file.", contentFile.createNewFile());
      }

      IMessageContext mock = new MessageContext(indexFile, contentFile);
      Envelope lope = new Envelope();
      lope.setMessageID("booga" + x + new Date().getTime());
      lope.setReceivedDate(new Date());
      lope.setSentDate(new Date());
      lope.setSize(10);
      lope.setCompressedSize(5);
      lope.setSubject("Test");
      lope.setRecipients("bleh");
      lope.setSftpTimeMS(100);
      lope.setSender("test2");
      mock.setEnvelope(lope);
      mock.setResolvedRecipients(new ArrayList<ReplicatedRecipient>());
      mock.setCustomer(cust);
      mock.setPartition(m_part);
      mock.setInternalId(start + 1 + x);
      arr.add(mock);
    }
    return arr;
  }
Exemplo n.º 8
0
  @Test
  public void testFailureTracking() throws Exception {
    final IPartitionProxy partitionProxy = createNiceMock(IPartitionProxy.class);
    final IPartitionProxy partitionProxy2 = createNiceMock(IPartitionProxy.class);
    long msgId = 2L;
    IFailureTrackingManager failMgr = ManagementContainer.getInstance().getFailureTrackingManager();
    StorageImporter importer = new MockStorageImporter();
    Customer customer = TestUtils.createTestCustomer();
    try {
      PartitionStoreStage stage = new PartitionStoreStage(importer);
      Pipeline pipeline =
          PipelineBuilder.start(
                  ManagementContainer.getInstance().getConfiguration(),
                  MessageImporter.PIPELINE_CONFIG_SECTION)
              .singleton("store-stage", stage)
              .get();
      File envelopeFile =
          File.createTempFile(
              "PartitionStoreTest", "test", ManagementContainer.getInstance().getNfsRoot());
      IMessageContext msgCtx = new MessageContext(envelopeFile, null);
      msgCtx.setCustomer(customer);
      msgCtx.setIndexMessage(true);
      msgCtx.setInternalId(msgId);
      msgCtx.setPartition(m_part);
      msgCtx.setPartitionID(m_part.getId());
      Collection<IMessageContext> msgs = Collections.singletonList(msgCtx);
      Collection<IMessageContext> emptyResult = Collections.emptyList();

      expect(partitionProxy.storeMessages(msgs)).andReturn(emptyResult).anyTimes();
      replay(partitionProxy);

      PartitionManager pm =
          new PartitionManager(
              ManagementContainer.getInstance().getPool(ManagementContainer.AM_POOL_NAME)) {
            @Override
            public IPartitionProxy getContentProxy(int id) {
              return partitionProxy;
            }
          };
      PartitionManagerTest.preparePartitionManager(pm);
      stage.setPartitionManager(pm);

      FailureRecord failureRecord =
          FailureTrackingHelper.buildFailureRecord(msgCtx, FailureCategory.STORAGE, null, null);
      failureRecord.setStoredOnPartition(false);
      failMgr.insertMessageFailure(failureRecord);
      msgCtx.setInternalFailureId(msgId);
      pipeline.process(
          new Pair<Partition, List<IMessageContext>>(m_part, Collections.singletonList(msgCtx)));
      failureRecord = failMgr.getFailureRecord(msgId);
      assertTrue("Should find stored on partition to be true", failureRecord.isStoredOnPartition());
      Map<String, String> props = msgCtx.readEnvelope();
      assertTrue(
          "envelope should contain failure ID",
          props.containsKey(ParseEnvelopeStage.INTERNAL_MESSAGE_FAILURE_ID));
      assertEquals(
          "message ID in envelope should match permanent ID",
          String.valueOf(msgId),
          props.get(ParseEnvelopeStage.INTERNAL_MESSAGE_FAILURE_ID));

      // confirm that transient ID gets set back to real ID of message
      // remove the existing failure record
      failMgr.removeFailure(msgId);
      // change the ID
      msgCtx.setInternalFailureId(msgId + 1);
      msgCtx.setInternalId(msgId + 1);
      // insert the new failure record
      failureRecord =
          FailureTrackingHelper.buildFailureRecord(msgCtx, FailureCategory.STORAGE, null, null);
      failMgr.insertMessageFailure(failureRecord);
      // old record should be gone
      failureRecord = failMgr.getFailureRecord(msgId);
      assertNull("Should no longer find the failure record with permanent ID", failureRecord);
      // check that the new record can be fetched
      failureRecord = failMgr.getFailureRecord(msgId + 1);
      assertNotNull("Should find transient ID failure record", failureRecord);
      msgCtx.appendToEnvelope(ParseEnvelopeStage.INTERNAL_MESSAGE_FAILURE_ID, msgId + 1);
      props = msgCtx.readEnvelope();
      assertTrue(
          "envelope should contain failure ID",
          props.containsKey(ParseEnvelopeStage.INTERNAL_MESSAGE_FAILURE_ID));
      assertEquals(
          "message ID in envelope should match permanent ID",
          String.valueOf(msgId + 1),
          props.get(ParseEnvelopeStage.INTERNAL_MESSAGE_FAILURE_ID));

      // now assign back the permanent ID and process through the pipeline
      msgCtx.setInternalId(msgId);
      pipeline.process(
          new Pair<Partition, List<IMessageContext>>(m_part, Collections.singletonList(msgCtx)));

      failureRecord = failMgr.getFailureRecord(msgId + 1);
      assertNull("Should not find any record based on transient message ID", failureRecord);
      failureRecord = failMgr.getFailureRecord(msgId);
      assertNotNull("Should find failure record for permanent ID", failureRecord);
      assertTrue("Should find stored on partition to be true", failureRecord.isStoredOnPartition());
      // envelope should now reflect permanent ID
      props = msgCtx.readEnvelope();
      assertTrue(
          "envelope should contain failure ID",
          props.containsKey(ParseEnvelopeStage.INTERNAL_MESSAGE_FAILURE_ID));
      assertEquals(
          "message ID in envelope should match permanent ID",
          String.valueOf(msgId),
          props.get(ParseEnvelopeStage.INTERNAL_MESSAGE_FAILURE_ID));

      // confirm that state does not change on failure
      // force an exception on any call to storeMessages
      pm =
          new PartitionManager(
              ManagementContainer.getInstance().getPool(ManagementContainer.AM_POOL_NAME)) {
            @Override
            public IPartitionProxy getContentProxy(int id) {
              return partitionProxy2;
            }
          };
      PartitionManagerTest.preparePartitionManager(pm);
      stage.setPartitionManager(pm);

      expect(partitionProxy2.storeMessages(msgs))
          .andThrow(new IPartitionProxy.ServiceNotAvailableException(new Exception()))
          .anyTimes();
      replay(partitionProxy2);
      failureRecord.setStoredOnPartition(false);
      failMgr.insertMessageFailure(failureRecord);
      pipeline.process(
          new Pair<Partition, List<IMessageContext>>(m_part, Collections.singletonList(msgCtx)));
      failureRecord = failMgr.getFailureRecord(msgId);
      assertNotNull("Should find the failure record for message", failureRecord);
      assertFalse(
          "Should find stored on partition to be true", failureRecord.isStoredOnPartition());
    } finally {
      importer.stop();
      TestUtils.quietDeleteCustomer(customer);
    }
  }