package org.orienteer.camel.component;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.camel.CamelContext;
import org.apache.camel.ServiceStatus;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.model.RouteDefinition;
import org.apache.camel.model.RoutesDefinition;
import org.apache.wicket.Application;
import org.apache.wicket.Component;
import org.apache.wicket.MetaDataKey;
import org.apache.wicket.authorization.UnauthorizedActionException;
import org.orienteer.camel.behavior.OIntegrationConfigStopBehavior;
import org.orienteer.camel.tasks.CamelEventHandler;
import org.orienteer.camel.tasks.OCamelTaskSessionCallback;
import org.orienteer.core.component.BootstrapType;
import org.orienteer.core.component.FAIconType;
import org.orienteer.core.method.ClassOMethod;
import org.orienteer.core.method.IMethodEnvironmentData;
import org.orienteer.core.method.OFilter;
import org.orienteer.core.method.filters.PlaceFilter;
import org.orienteer.core.method.filters.WidgetTypeFilter;
import org.orienteer.core.tasks.OTask;
import org.orienteer.core.tasks.OTaskSessionRuntime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.orientechnologies.orient.core.record.impl.ODocument;
import ru.ydn.wicket.wicketorientdb.IOrientDbSettings;
import ru.ydn.wicket.wicketorientdb.OrientDbWebApplication;
import ru.ydn.wicket.wicketorientdb.OrientDbWebSession;
/**
* Wrapper for OIntegrationConfig ODocuments
*
*/
public class OIntegrationConfig extends OTask {
private static final Logger LOG = LoggerFactory.getLogger(OIntegrationConfig.class);
private static final long serialVersionUID = 1L;
public static final String TASK_CLASS = "OIntegrationConfig";
public static final MetaDataKey<Map<String,CamelContext>> INTEGRATION_SESSIONS_KEY = new MetaDataKey<Map<String,CamelContext>>()
{
private static final long serialVersionUID = 1L;
};
/////////////////////////////////////////////////////////////////////////////////////////////////////
@ClassOMethod(
order=10,bootstrap=BootstrapType.SUCCESS,icon = FAIconType.play,
filters={
@OFilter(fClass = PlaceFilter.class, fData = "STRUCTURE_TABLE"),
@OFilter(fClass = WidgetTypeFilter.class, fData = "parameters"),
// @OFilter(fClass = PlaceFilter.class, fData = "STRUCTURE_TABLE|DATA_TABLE"),
}
)
public void start(IMethodEnvironmentData data){
final CamelContext context = getOrMakeContextByRid(getDocument().getIdentity().toString(),data.getCurrentWidget());
new Thread(new Runnable() {
@Override
public void run() {
try {
if (context.getStatus().isSuspended()){
context.resume();
//target.add(CamelWidget.this.form);
}else if (!context.getStatus().isStarted()){
clearContext(context);
String script = getDocument().field("script");
RoutesDefinition routes = context.loadRoutesDefinition(new ByteArrayInputStream( script.getBytes()));
context.addRouteDefinitions(routes.getRoutes());
context.start();
}
} catch (Exception e) {
LOG.error("Cannot start or resume Camel Context",e);
}
}
}).start();
waitingRefresh(context);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
@ClassOMethod(
order = 30,bootstrap=BootstrapType.DANGER,icon = FAIconType.stop,
filters={@OFilter(fClass = PlaceFilter.class, fData = "STRUCTURE_TABLE"),
@OFilter(fClass = WidgetTypeFilter.class, fData = "parameters"),
},
behaviors={OIntegrationConfigStopBehavior.class}
)
public void stop(IMethodEnvironmentData data){
CamelContext context = getOrMakeContextByRid(getDocument().getIdentity().toString(),data.getCurrentWidget());
try {
context.stop();
} catch (Exception e) {
LOG.error("Cannot stop Camel Context",e);
}
waitingRefresh(context);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
@ClassOMethod(
order = 20,bootstrap=BootstrapType.WARNING,icon = FAIconType.pause,
filters={
@OFilter(fClass = PlaceFilter.class, fData = "STRUCTURE_TABLE"),
@OFilter(fClass = WidgetTypeFilter.class, fData = "parameters"),
},
behaviors={OIntegrationConfigStopBehavior.class}
)
public void suspend(IMethodEnvironmentData data){
final CamelContext context = getOrMakeContext(data.getCurrentWidget());
new Thread(new Runnable() {
@Override
public void run() {
try {
ServiceStatus status = context.getStatus();
if (status.isSuspended()){
context.start();
}else if(status.isStarted()){
context.suspend();
}
} catch (Exception e) {
LOG.error("Cannot start or suspend Camel Context",e);
}
}
}).start();
waitingRefresh(context);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
public OIntegrationConfig(ODocument doc) {
super(doc);
}
public CamelContext getOrMakeContextByRid(String rid,Component component){
CamelContext context;
Map<String,CamelContext> contextMap = Application.get().getMetaData(INTEGRATION_SESSIONS_KEY);
if (contextMap.containsKey(rid)){
context = contextMap.get(rid);
}else{
IOrientDbSettings dbSettings = OrientDbWebApplication.get().getOrientDbSettings();
OrientDbWebSession session = OrientDbWebSession.get();
if (session.getUsername()==null){
throw new UnauthorizedActionException(component, Component.RENDER);
}
context = new DefaultCamelContext();
Map<String, String> properties = context.getProperties();
properties.put(OrientDBComponent.DB_URL, dbSettings.getDBUrl());
properties.put(OrientDBComponent.DB_USERNAME, session.getUsername());
properties.put(OrientDBComponent.DB_PASSWORD, session.getPassword());
context.setProperties(properties);
context.getManagementStrategy().addEventNotifier(new CamelEventHandler(new OCamelTaskSessionCallback(context),this,context));
contextMap.put(rid, context);
}
return context;
}
public void clearContext(CamelContext context) throws Exception{
List<RouteDefinition> definitions = context.getRouteDefinitions();
if (!definitions.isEmpty()){
context.removeRouteDefinitions(new ArrayList<RouteDefinition>(definitions));
}
}
public CamelContext getOrMakeContext(Component component){
return getOrMakeContextByRid(getDocument().getIdentity().toString(),component);
}
// wait for context status refresh
private void waitingRefresh(CamelContext context){
ServiceStatus oldStatus = context.getStatus();
try {
for(int i =0 ;i<10;i++){
Thread.sleep(100);
if (!oldStatus.equals(context.getStatus())){
return ;
}
}
} catch (InterruptedException e) {
// silently escape
}
}
@Override
public OTaskSessionRuntime startNewSession() {
throw new RuntimeException("Cannot start new Camel session outside CamelEventHandler");
}
}