/*
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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 2.1 of
* the License, or (at your option) any later version.
*
* This software 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 this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.capedwarf.tasks;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.jms.BytesMessage;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import com.google.appengine.api.NamespaceManager;
import com.google.appengine.api.taskqueue.TaskOptions;
import org.jboss.capedwarf.common.jms.MessageCreator;
import org.jboss.capedwarf.shared.jms.MessageConstants;
import org.jboss.capedwarf.shared.jms.ServletRequestCreator;
import org.jboss.capedwarf.shared.reflection.ReflectionUtils;
/**
* Tasks message creator.
*
* @author <a href="mailto:ales.justin@jboss.org">Ales Justin</a>
* @author <a href="mailto:mluksa@redhat.com">Marko Luksa</a>
*/
public class TasksMessageCreator implements MessageCreator {
public static final String QUEUE_NAME_HEADER = "X-AppEngine-QueueName";
public static final String TASK_NAME_HEADER = "X-AppEngine-TaskName";
public static final String TASK_RETRY_COUNT = "X-AppEngine-TaskRetryCount";
public static final String TASK_EXECUTION_COUNT = "X-AppEngine-TaskExecutionCount";
public static final String TASK_ETA = "X-AppEngine-TaskETA";
public static final String FAIL_FAST = "X-AppEngine-FailFast";
public static final String CURRENT_NAMESPACE = "X-AppEngine-Current-Namespace";
public static final String HDR_SCHEDULED_DELIVERY_TIME = "_HQ_SCHED_DELIVERY";
public static final String QUEUE_NAME_KEY = "__CD__QueueName__";
public static final String TASK_NAME_KEY = "__CD__TaskName__";
private final String queueName;
private final TaskOptionsHelper taskOptions;
public TasksMessageCreator(String queueName, TaskOptions taskOptions) {
if (queueName == null)
throw new IllegalArgumentException("Null queue name");
if (taskOptions == null)
throw new IllegalArgumentException("Null task options");
this.queueName = queueName;
this.taskOptions = new TaskOptionsHelper(taskOptions);
}
public Message createMessage(Session session) throws Exception {
byte[] payload = taskOptions.getPayload();
if (payload != null && payload.length > 0) {
BytesMessage bytesMessage = session.createBytesMessage();
bytesMessage.writeBytes(payload);
enhanceMessage(bytesMessage);
return bytesMessage;
} else {
return null;
}
}
public void enhanceMessage(Message message) throws Exception {
addMethod(message);
addHeaders(message);
addParameters(message);
message.setStringProperty(QUEUE_NAME_KEY, queueName);
setIfNotNull(message, TASK_NAME_KEY, taskOptions.getTaskName());
message.setIntProperty(MessageConstants.MAX_ATTEMPTS, taskOptions.getTaskRetryLimit() == null ? -1 : taskOptions.getTaskRetryLimit());
Long etaMillis = taskOptions.getCalculatedEtaMillis();
if (etaMillis != null) {
message.setLongProperty(HDR_SCHEDULED_DELIVERY_TIME, etaMillis);
}
}
private void addMethod(Message message) throws JMSException {
message.setStringProperty(TasksServletRequestCreator.METHOD, taskOptions.getMethod().name());
}
@SuppressWarnings("unchecked")
private void addParameters(Message message) throws JMSException {
List<Object> params = taskOptions.getParams();
if (params != null && params.size() > 0) {
Map<String, String> map = new HashMap<String, String>();
for (Object param : params) {
String key = (String) ReflectionUtils.invokeInstanceMethod(param, "getURLEncodedName");
String value = (String) ReflectionUtils.invokeInstanceMethod(param, "getURLEncodedValue");
String values = map.get(key);
if (values == null) {
values = value;
} else {
values = values + TasksServletRequestCreator.DELIMITER + value;
}
map.put(key, values);
}
TasksServletRequestCreator.put(message, TasksServletRequestCreator.PARAMS, map);
}
}
@SuppressWarnings("unchecked")
private void addHeaders(Message message) throws JMSException {
Map<String, List<String>> headers = taskOptions.getHeaders();
Map<String, String> map = new HashMap<String, String>();
if (headers != null && headers.size() > 0) {
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
StringBuilder builder = new StringBuilder();
List<String> list = entry.getValue();
if (list.isEmpty() == false) {
builder.append(list.get(0));
for (int i = 1; i < list.size(); i++) {
builder.append(TasksServletRequestCreator.DELIMITER).append(list.get(i));
}
}
if (builder.length() > 0) {
String key = entry.getKey();
map.put(key, builder.toString());
}
}
}
map.put(QUEUE_NAME_HEADER, queueName);
putIfNotNull(map, TASK_NAME_HEADER, taskOptions.getTaskName());
putIfNotNull(map, TASK_ETA, taskOptions.getEtaMillis());
map.put(FAIL_FAST, Boolean.FALSE.toString()); // TODO?
if (map.containsKey(CURRENT_NAMESPACE) == false) {
String namespace = getCurrentNamespace();
map.put(CURRENT_NAMESPACE, namespace == null ? "" : namespace);
}
TasksServletRequestCreator.put(message, TasksServletRequestCreator.HEADERS, map);
}
protected String getCurrentNamespace() {
return NamespaceManager.get();
}
public String getPath() {
return taskOptions.getUrl() == null ? getDefaultUrl() : taskOptions.getUrl();
}
private String getDefaultUrl() {
return "/_ah/queue/" + queueName;
}
public Class<? extends ServletRequestCreator> getServletRequestCreator() {
return TasksServletRequestCreator.class;
}
private static void setIfNotNull(Message msg, String key, Object value) throws JMSException {
if (value != null) {
msg.setStringProperty(key, value.toString());
}
}
private static void putIfNotNull(Map<String, String> map, String key, Object value) {
if (value != null) {
map.put(key, value.toString());
}
}
}