/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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.wso2.carbon.event.output.adapter.ui;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jaggeryjs.hostobjects.web.WebSocketHostObject;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.databridge.commons.Attribute;
import org.wso2.carbon.databridge.commons.StreamDefinition;
import org.wso2.carbon.event.output.adapter.ui.internal.ds.UIEventAdaptorServiceInternalValueHolder;
import org.wso2.carbon.event.stream.core.exception.EventStreamConfigurationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Jaggery Websocket server calls this helper to subscribe/unsubscribe Websocket clients.
*/
public class JaggeryWebSocketHelper {
private static final Log log = LogFactory.getLog(JaggeryWebSocketHelper.class);
private static final String FILTER_PROP_NAME = "name";
private static final String FILTER_PROP_VALUE = "value";
private static final String CORRELATATION = "correlation_";
private static final String META = "meta_";
private static final String NULL = "null";
public static void subscribeWebSocket(String streamName, String streamVersion, String filterProps, String username,
String sessionId, int tenantId, Object webSocketHostObject) {
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId);
StreamDefinition streamDefinition = UIEventAdaptorServiceInternalValueHolder.getEventStreamService().
getStreamDefinition(streamName, streamVersion);
if (!filterProps.equalsIgnoreCase(NULL)) {
UIEventAdaptorServiceInternalValueHolder.getUIOutputCallbackRegisterServiceImpl().
subscribeWebsocket(streamName, streamVersion, new JaggerySessionHolder(sessionId,
getFilterProps(streamDefinition, new JSONArray(filterProps)), username, tenantId, (WebSocketHostObject) webSocketHostObject));
} else {
UIEventAdaptorServiceInternalValueHolder.getUIOutputCallbackRegisterServiceImpl().
subscribeWebsocket(streamName, streamVersion, new JaggerySessionHolder(sessionId,
getFilterProps(streamDefinition, null), username, tenantId, (WebSocketHostObject) webSocketHostObject));
}
} catch (JSONException | EventStreamConfigurationException e) {
log.error(e.getMessage(), e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
private static Map<Integer, String> getFilterProps(StreamDefinition streamDefinition, JSONArray filterPropsJson) throws JSONException {
Map<Integer, String> filterProps = new HashMap<>();
if (filterPropsJson != null) {
int metaDataOffset = 1;
int correlationDataOffset = metaDataOffset;
if (streamDefinition.getMetaData() != null) {
correlationDataOffset = correlationDataOffset + streamDefinition.getMetaData().size();
}
int payloadDataOffset = correlationDataOffset;
if (streamDefinition.getCorrelationData() != null) {
payloadDataOffset = payloadDataOffset + streamDefinition.getCorrelationData().size();
}
for (int i = 0; i < filterPropsJson.length(); i++) {
JSONObject aFilter = (JSONObject) filterPropsJson.get(i);
String filterName = (String) aFilter.get(FILTER_PROP_NAME);
String filterValue = (String) aFilter.get(FILTER_PROP_VALUE);
if (filterName != null && !filterName.trim().isEmpty() && filterValue != null && !filterValue.trim().isEmpty()) {
int index = -1;
if (filterName.startsWith(META)) {
filterName = filterName.replace(META, "");
index = getIndexOf(streamDefinition.getMetaData(), filterName);
if (index != -1) {
filterProps.put(metaDataOffset + index, filterValue);
} else {
log.warn("Filter property - " + filterName + " doesn't exists in the stream - "
+ streamDefinition.getStreamId() + ", hence ignoring the filter property");
}
} else if (filterName.startsWith(CORRELATATION)) {
filterName = filterName.replace(CORRELATATION, "");
index = getIndexOf(streamDefinition.getCorrelationData(), filterName);
if (index != -1) {
filterProps.put(correlationDataOffset + index, filterValue);
} else {
log.warn("Filter property - " + filterName + " doesn't exists in the stream - "
+ streamDefinition.getStreamId() + ", hence ignoring the filter property");
}
} else {
index = getIndexOf(streamDefinition.getPayloadData(), filterName);
if (index != -1) {
filterProps.put(payloadDataOffset + index, filterValue);
} else {
log.warn("Filter property - " + filterName + " doesn't exists in the stream - "
+ streamDefinition.getStreamId() + ", hence ignoring the filter property");
}
}
}
}
}
return filterProps;
}
private static int getIndexOf(List<Attribute> streamAttributes, String attributeName) {
if (streamAttributes != null) {
for (int i = 0; i < streamAttributes.size(); i++) {
if (streamAttributes.get(i).getName().equalsIgnoreCase(attributeName)) {
return i;
}
}
return -1;
} else {
return -1;
}
}
public static void unsubscribeWebsocket(String streamName, String streamVersion, String sessionId, int tenantId) {
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId);
UIEventAdaptorServiceInternalValueHolder.getUIOutputCallbackRegisterServiceImpl().
unsubscribeWebsocket(streamName, streamVersion, sessionId);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}