/*
* Copyright 2015 herd contributors
*
* 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.
*/
package org.finra.herd.service.helper;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.Map;
import com.amazonaws.services.s3.event.S3EventNotification;
import org.apache.commons.lang3.CharEncoding;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.config.JmsListenerEndpointRegistry;
import org.springframework.jms.listener.MessageListenerContainer;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.finra.herd.core.ApplicationContextHolder;
import org.finra.herd.core.helper.ConfigurationHelper;
import org.finra.herd.model.ObjectNotFoundException;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionKey;
import org.finra.herd.model.dto.BusinessObjectDefinitionSampleFileUpdateDto;
import org.finra.herd.model.dto.ConfigurationValue;
import org.finra.herd.service.BusinessObjectDefinitionService;
/**
* sample data jms message listener
*/
@Component
public class SampleDataJmsMessageListener
{
private static final Logger LOGGER = LoggerFactory.getLogger(SampleDataJmsMessageListener.class);
@Autowired
private ConfigurationHelper configurationHelper;
@Autowired
private BusinessObjectDefinitionService businessObjectDefinitionService;
/**
* Periodically check the configuration and apply the action to the storage policy processor JMS message listener service, if needed.
*/
@Scheduled(fixedDelay = 60000)
public void controlSampleDataJmsMessageListener()
{
try
{
// Get the configuration setting.
Boolean jmsMessageListenerEnabled =
Boolean.valueOf(configurationHelper.getProperty(ConfigurationValue.SAMPLE_DATA_JMS_LISTENER_ENABLED));
// Get the registry bean.
JmsListenerEndpointRegistry registry = ApplicationContextHolder.getApplicationContext()
.getBean("org.springframework.jms.config.internalJmsListenerEndpointRegistry", JmsListenerEndpointRegistry.class);
// Get the sample data JMS message listener container.
MessageListenerContainer jmsMessageListenerContainer =
registry.getListenerContainer(HerdJmsDestinationResolver.SQS_DESTINATION_SAMPLE_DATA_QUEUE);
// Get the current JMS message listener status and the configuration value.
LOGGER.debug("controlStoragePolicyProcessorJmsMessageListener(): {}={} jmsMessageListenerContainer.isRunning()={}",
ConfigurationValue.SAMPLE_DATA_JMS_LISTENER_ENABLED.getKey(), jmsMessageListenerEnabled, jmsMessageListenerContainer.isRunning());
// Apply the relative action if needed.
if (!jmsMessageListenerEnabled && jmsMessageListenerContainer.isRunning())
{
LOGGER.info("controlSampleDataJmsMessageListener(): Stopping the sample data JMS message listener ...");
jmsMessageListenerContainer.stop();
LOGGER.info("controlSampleDataJmsMessageListener(): Done");
}
else if (jmsMessageListenerEnabled && !jmsMessageListenerContainer.isRunning())
{
LOGGER.info("controlSampleDataJmsMessageListener(): Starting the sample data JMS message listener ...");
jmsMessageListenerContainer.start();
LOGGER.info("controlSampleDataJmsMessageListener(): Done");
}
}
catch (Exception e)
{
LOGGER.error("controlSampleDataJmsMessageListener(): Failed to control the sample data Jms message listener service.", e);
}
}
/**
* Processes a JMS message.
*
* @param payload the message payload
* @param allHeaders the JMS headers
*/
@JmsListener(id = HerdJmsDestinationResolver.SQS_DESTINATION_SAMPLE_DATA_QUEUE,
containerFactory = "jmsListenerContainerFactory",
destination = HerdJmsDestinationResolver.SQS_DESTINATION_SAMPLE_DATA_QUEUE)
public void processMessage(String payload, @Headers Map<Object, Object> allHeaders)
{
LOGGER.info("Message received from the JMS queue. jmsQueueName=\"{}\" jmsMessageHeaders=\"{}\" jmsMessagePayload={}",
HerdJmsDestinationResolver.SQS_DESTINATION_SAMPLE_DATA_QUEUE, allHeaders, payload);
try
{
// Process messages coming from S3 bucket.
S3EventNotification s3EventNotification = S3EventNotification.parseJson(payload);
String objectKey = URLDecoder.decode(s3EventNotification.getRecords().get(0).getS3().getObject().getKey(), CharEncoding.UTF_8);
long fileSize = s3EventNotification.getRecords().get(0).getS3().getObject().getSizeAsLong();
// parse the objectKey, it should be in the format of namespace/businessObjectDefinitionName/fileName
String[] objectKeyArrays = objectKey.split("/");
Assert.isTrue(objectKeyArrays.length == 3, String.format("S3 notification message %s is not in expected format", objectKey));
String namespace = objectKeyArrays[0];
String businessObjectDefinitionName = objectKeyArrays[1];
String fileName = objectKeyArrays[2];
String path = namespace + "/" + businessObjectDefinitionName + "/";
BusinessObjectDefinitionSampleFileUpdateDto businessObjectDefinitionSampleFileUpdateDto =
new BusinessObjectDefinitionSampleFileUpdateDto(path, fileName, fileSize);
String convertedNamespaece = convertS3KeyFormat(namespace);
String convertedBusinessObjectDefinitionName = convertS3KeyFormat(businessObjectDefinitionName);
BusinessObjectDefinitionKey businessObjectDefinitionKey =
new BusinessObjectDefinitionKey(convertedNamespaece, convertedBusinessObjectDefinitionName);
try
{
businessObjectDefinitionService.updateBusinessObjectDefinitionEntitySampleFile(businessObjectDefinitionKey,
businessObjectDefinitionSampleFileUpdateDto);
}
catch (ObjectNotFoundException ex)
{
LOGGER.info("Failed to find the business object definition, next try the original namespace and business oject defination name " + ex);
// if Business object definition is not found, use the original name space and bdef name
businessObjectDefinitionKey = new BusinessObjectDefinitionKey(namespace, businessObjectDefinitionName);
businessObjectDefinitionService.updateBusinessObjectDefinitionEntitySampleFile(businessObjectDefinitionKey,
businessObjectDefinitionSampleFileUpdateDto);
}
}
catch (RuntimeException | IOException e)
{
LOGGER.error("Failed to process message from the JMS queue. jmsQueueName=\"{}\" jmsMessagePayload={}",
HerdJmsDestinationResolver.SQS_DESTINATION_SAMPLE_DATA_QUEUE, payload, e);
}
}
/**
* Converts the specified string from the S3 key format. This implies converting dashes to underscores.
*
* @param string string in S3 format
*
* @return the regular string
*/
private String convertS3KeyFormat(String string)
{
return string.replace('-', '_');
}
}