/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.io.rest.sse.internal.util;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import javax.servlet.ServletRequest;
import javax.ws.rs.core.MediaType;
import org.apache.commons.lang.StringUtils;
import org.eclipse.smarthome.core.events.Event;
import org.eclipse.smarthome.io.rest.sse.beans.EventBean;
import org.glassfish.jersey.media.sse.OutboundEvent;
/**
* Utility class containing helper methods for the SSE implementation.
*
* @author Ivan Iliev - Initial Contribution and API
* @author Dennis Nobel - Changed EventBean
*/
public class SseUtil {
static final String TOPIC_VALIDATE_PATTERN = "(\\w*\\*?\\/?,?\\s*)*";
static {
boolean servlet3 = false;
try {
servlet3 = ServletRequest.class.getMethod("startAsync") != null;
} catch (Exception e) {
} finally {
SERVLET3_SUPPORT = servlet3;
}
}
/**
* True if the {@link ServletRequest} class has a "startAsync" method,
* otherwise false.
*/
public static final boolean SERVLET3_SUPPORT;
/**
* Creates a new {@link OutboundEvent} object containing an {@link EventBean} created for the given Eclipse
* SmartHome {@link Event}.
*
* @param event the event
*
* @return a new OutboundEvent
*/
public static OutboundEvent buildEvent(Event event) {
EventBean eventBean = new EventBean();
eventBean.topic = event.getTopic();
eventBean.type = event.getType();
eventBean.payload = event.getPayload();
OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();
OutboundEvent outboundEvent = eventBuilder.name("message").mediaType(MediaType.APPLICATION_JSON_TYPE)
.data(eventBean).build();
return outboundEvent;
}
/**
* Used to mark our current thread(request processing) that SSE blocking
* should be enabled.
*/
private static ThreadLocal<Boolean> blockingSseEnabled = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return false;
}
};
/**
* Returns true if the current thread is processing an SSE request that
* should block.
*
* @return
*/
public static boolean shouldAsyncBlock() {
return blockingSseEnabled.get().booleanValue();
}
/**
* Marks the current thread as processing a blocking sse request.
*/
public static void enableBlockingSse() {
blockingSseEnabled.set(true);
}
/**
* Validates the given topicFilter
*
* @param topicFilter
* @return true if the given input filter is empty or a valid topic filter string
*
*/
public static boolean isValidTopicFilter(String topicFilter) {
return StringUtils.isEmpty(topicFilter) || topicFilter.matches(TOPIC_VALIDATE_PATTERN);
}
/**
* Splits the given topicFilter at any commas (",") and for each token replaces any wildcards(*) with the regex
* pattern (.*)
*
* @param topicFilter
* @return
*/
public static List<String> convertToRegex(String topicFilter) {
List<String> filters = new ArrayList<String>();
if (StringUtils.isEmpty(topicFilter)) {
filters.add(".*");
} else {
StringTokenizer tokenizer = new StringTokenizer(topicFilter, ",");
while (tokenizer.hasMoreElements()) {
String regex = tokenizer.nextToken().trim().replace("*", ".*") + ".*";
filters.add(regex);
}
}
return filters;
}
}