/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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.wso2.carbon.event.input.adapter.http;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException;
import org.wso2.carbon.event.input.adapter.core.exception.TestConnectionNotSupportedException;
import org.wso2.carbon.event.input.adapter.http.internal.ds.HTTPEventAdapterServiceValueHolder;
import org.wso2.carbon.event.input.adapter.http.internal.util.HTTPEventAdapterConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import javax.servlet.ServletException;
import java.util.Hashtable;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.*;
public final class HTTPEventAdapter implements InputEventAdapter {
private final InputEventAdapterConfiguration eventAdapterConfiguration;
private final Map<String, String> globalProperties;
private InputEventAdapterListener eventAdaptorListener;
private final String id = UUID.randomUUID().toString();
public static ExecutorService executorService;
private static final Log log = LogFactory.getLog(HTTPEventAdapter.class);
private boolean isConnected = false;
public HTTPEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
Map<String, String> globalProperties) {
this.eventAdapterConfiguration = eventAdapterConfiguration;
this.globalProperties = globalProperties;
}
@Override
public void init(InputEventAdapterListener eventAdaptorListener) throws InputEventAdapterException {
this.eventAdaptorListener = eventAdaptorListener;
//ThreadPoolExecutor will be assigned if it is null
if (executorService == null) {
int minThread;
int maxThread;
long defaultKeepAliveTime;
int jobQueueSize;
//If global properties are available those will be assigned else constant values will be assigned
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME) != null) {
minThread = Integer
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME));
} else {
minThread = HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE;
}
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME) != null) {
maxThread = Integer
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME));
} else {
maxThread = HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE;
}
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME) != null) {
defaultKeepAliveTime = Integer
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME));
} else {
defaultKeepAliveTime = HTTPEventAdapterConstants.DEFAULT_KEEP_ALIVE_TIME_IN_MILLS;
}
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME) != null) {
jobQueueSize = Integer
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME));
} else {
jobQueueSize = HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE;
}
RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
log.error("Exception while adding event to executor queue : " + e.getMessage(), e);
}
}
};
executorService = new ThreadPoolExecutor(minThread, maxThread, defaultKeepAliveTime, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(jobQueueSize), rejectedExecutionHandler);
}
}
@Override
public void testConnect() throws TestConnectionNotSupportedException {
throw new TestConnectionNotSupportedException("not-supported");
}
@Override
public void connect() {
registerDynamicEndpoint(eventAdapterConfiguration.getName());
isConnected = true;
}
@Override
public void disconnect() {
if (isConnected){
isConnected = false;
unregisterDynamicEndpoint(eventAdapterConfiguration.getName());
}
}
@Override
public void destroy() {
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof HTTPEventAdapter))
return false;
HTTPEventAdapter that = (HTTPEventAdapter) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean isEventDuplicatedInCluster() {
return false;
}
@Override
public boolean isPolling() {
return false;
}
private void registerDynamicEndpoint(String adapterName) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
String endpoint;
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + adapterName;
} else {
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + HTTPEventAdapterConstants.ENDPOINT_TENANT_KEY
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + tenantDomain
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + adapterName;
}
try {
String basicAuthEnabledValue = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants.BASIC_AUTH_ENABLED);
boolean isBasicAuthEnabled = true;
if(basicAuthEnabledValue != null){
isBasicAuthEnabled = Boolean.parseBoolean(basicAuthEnabledValue);
}
HttpService httpService = HTTPEventAdapterServiceValueHolder.getHTTPService();
if (httpService == null) {
throw new InputEventAdapterRuntimeException(
"HttpService not available, Error in registering endpoint " + endpoint);
}
httpService.registerServlet(endpoint, new HTTPMessageServlet(eventAdaptorListener, tenantId,
eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants.EXPOSED_TRANSPORTS),
isBasicAuthEnabled), new Hashtable(), httpService.createDefaultHttpContext());
} catch (ServletException | NamespaceException e) {
throw new InputEventAdapterRuntimeException("Error in registering endpoint " + endpoint, e);
}
}
private void unregisterDynamicEndpoint(String adapterName) {
HttpService httpService = HTTPEventAdapterServiceValueHolder.getHTTPService();
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String endpoint;
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + adapterName;
} else {
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + HTTPEventAdapterConstants.ENDPOINT_TENANT_KEY
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + tenantDomain
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + adapterName;
}
if (httpService != null) {
httpService.unregister(endpoint);
}
}
}