You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ha...@apache.org on 2010/09/28 23:27:00 UTC

svn commit: r1002361 [3/3] - in /camel/trunk/components/camel-quickfix: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/camel/ src/main/java/org/apache/camel/component/ src/main/java/org/apache/cam...

Added: camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorComponent.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorComponent.java?rev=1002361&view=auto
==============================================================================
--- camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorComponent.java (added)
+++ camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorComponent.java Tue Sep 28 21:26:58 2010
@@ -0,0 +1,160 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.camel.component.quickfixj.examples.trading;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+import org.apache.camel.Consumer;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.component.quickfixj.QuickfixjEventCategory;
+import org.apache.camel.component.quickfixj.converter.QuickfixjConverters;
+import org.apache.camel.impl.DefaultComponent;
+import org.apache.camel.impl.DefaultConsumer;
+import org.apache.camel.impl.DefaultEndpoint;
+import org.apache.camel.impl.DefaultProducer;
+import org.apache.camel.util.ExchangeHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import quickfix.Message;
+import quickfix.Message.Header;
+import quickfix.SessionID;
+import quickfix.field.SenderCompID;
+import quickfix.field.SenderLocationID;
+import quickfix.field.SenderSubID;
+import quickfix.field.TargetCompID;
+import quickfix.field.TargetLocationID;
+import quickfix.field.TargetSubID;
+
+/**
+ * Adapts the TradeExecutor for use as a Camel endpoint.
+ * 
+ * @see TradeExecutor
+ */
+public class TradeExecutorComponent extends DefaultComponent {
+    private static final Logger LOG = LoggerFactory.getLogger(TradeExecutorComponent.class);
+
+    private Map<String, TradeExecutorEndpoint> endpoints = new HashMap<String, TradeExecutorEndpoint>();
+    private final Executor executor;
+
+    public TradeExecutorComponent() {
+        this(Executors.newCachedThreadPool(new TradeExecutorThreadFactory()));
+    }
+    
+    private static class TradeExecutorThreadFactory implements ThreadFactory {
+        public Thread newThread(Runnable r) {
+            Thread thread = new Thread(r, "Trade Executor");
+            thread.setDaemon(true);
+            return thread;
+        }
+    }
+    
+    public TradeExecutorComponent(Executor executor) {
+        this.executor = executor;
+    }
+
+    @Override
+    protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+        synchronized (endpoints) {
+            Endpoint endpoint = endpoints.get(uri);
+            if (endpoint == null) {
+                endpoint = new TradeExecutorEndpoint(uri, new TradeExecutor());
+                endpoints.put(uri, (TradeExecutorEndpoint) endpoint);
+                LOG.info("Created trade executor: " + uri);
+            }
+            return endpoint;
+        }
+    }
+
+    private class TradeExecutorEndpoint extends DefaultEndpoint {
+        private final TradeExecutor tradeExecutor;
+        private List<Processor> processors = new CopyOnWriteArrayList<Processor>();
+        
+        public TradeExecutorEndpoint(String uri, TradeExecutor tradeExecutor) {
+            super(uri, TradeExecutorComponent.this.getCamelContext());
+            this.tradeExecutor = tradeExecutor;
+            tradeExecutor.addListener(new QuickfixjMessageListener() {
+                public void onMessage(SessionID sessionID, Message message) throws Exception {
+                    // Inject session ID into message so produce will know where to send it
+                    Header header = message.getHeader();
+                    setOptionalField(header, sessionID, SenderCompID.FIELD, sessionID.getTargetCompID());
+                    setOptionalField(header, sessionID, SenderSubID.FIELD, sessionID.getTargetSubID());
+                    setOptionalField(header, sessionID, SenderLocationID.FIELD, sessionID.getTargetLocationID());
+                    setOptionalField(header, sessionID, TargetCompID.FIELD, sessionID.getSenderCompID());
+                    setOptionalField(header, sessionID, TargetSubID.FIELD, sessionID.getSenderSubID());
+                    setOptionalField(header, sessionID, TargetLocationID.FIELD, sessionID.getSenderLocationID());
+                    
+                    Exchange exchange = QuickfixjConverters.toExchange(
+                        TradeExecutorEndpoint.this, sessionID, message, 
+                        QuickfixjEventCategory.AppMessageReceived);
+                    
+                    for (Processor processor : processors) {
+                        processor.process(exchange);
+                    }
+                }
+
+                private void setOptionalField(Header header, SessionID sessionID, int tag, String value) {
+                    if (value != null && value.length() > 0) {
+                        header.setString(tag, value);
+                    }
+                }
+            });
+        }
+
+        public Producer createProducer() throws Exception {
+            return new DefaultProducer(this) {
+                public void process(final Exchange exchange) throws Exception {
+                    executor.execute(new Runnable() {
+                        public void run() {
+                            try {
+                                tradeExecutor.execute(ExchangeHelper.getMandatoryInBody(exchange, Message.class));
+                            } catch (Exception e) {
+                                log.error("Error during trade execution", e);
+                            }
+                        }
+                    });
+                }
+            };
+        }
+
+        public Consumer createConsumer(Processor processor) throws Exception {
+            return new DefaultConsumer(this, processor) {
+                @Override
+                protected void doStart() throws Exception {
+                    processors.add(getProcessor());
+                }
+                
+                protected void doStop() throws Exception {
+                    processors.remove(getProcessor());                   
+                }
+            };
+        }
+
+        public boolean isSingleton() {
+            return false;
+        }        
+    }
+}

Added: camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorExample.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorExample.java?rev=1002361&view=auto
==============================================================================
--- camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorExample.java (added)
+++ camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorExample.java Tue Sep 28 21:26:58 2010
@@ -0,0 +1,140 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.camel.component.quickfixj.examples.trading;
+
+import java.util.Date;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Producer;
+import org.apache.camel.builder.PredicateBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.quickfixj.QuickfixjEndpoint;
+import org.apache.camel.component.quickfixj.QuickfixjEventCategory;
+import org.apache.camel.component.quickfixj.examples.transform.QuickfixjMessageJsonPrinter;
+import org.apache.camel.component.quickfixj.examples.util.CountDownLatchDecrementer;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import quickfix.field.ClOrdID;
+import quickfix.field.HandlInst;
+import quickfix.field.MsgType;
+import quickfix.field.OrdType;
+import quickfix.field.OrderQty;
+import quickfix.field.Price;
+import quickfix.field.Side;
+import quickfix.field.Symbol;
+import quickfix.field.TransactTime;
+import quickfix.fix42.NewOrderSingle;
+
+public class TradeExecutorExample {
+    private static final Logger LOG = LoggerFactory.getLogger(TradeExecutorExample.class);
+
+    public static void main(String[] args) throws Exception {
+        new TradeExecutorExample().sendMessage();
+    }
+    
+    public void sendMessage() throws Exception {        
+        DefaultCamelContext context = new DefaultCamelContext();
+        context.addComponent("trade-executor", new TradeExecutorComponent());
+        
+        final CountDownLatch logonLatch = new CountDownLatch(2);
+        final CountDownLatch executionReportLatch = new CountDownLatch(2);
+        
+        RouteBuilder routes = new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // Release latch when session logon events are received
+                // We expect four logon events (four sessions)
+                from("quickfixj:examples/inprocess.cfg").
+                    filter(header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.SessionLogon)).
+                    bean(new CountDownLatchDecrementer("logon", logonLatch));
+
+                from("quickfixj:examples/inprocess.cfg?sessionID=FIX.4.2:MARKET->TRADER").
+                    filter(header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AppMessageReceived)).
+                    to("trade-executor:market");
+
+                from("trade-executor:market").to("quickfixj:examples/inprocess.cfg");
+                
+                // Log app messages as JSON
+                from("quickfixj:examples/inprocess.cfg").
+                    filter(PredicateBuilder.or(
+                        header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AppMessageReceived),
+                        header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AppMessageSent))).
+                    bean(new QuickfixjMessageJsonPrinter());
+                
+                // Release latch when trader receives execution report
+                from("quickfixj:examples/inprocess.cfg?sessionID=FIX.4.2:TRADER->MARKET").
+                    filter(PredicateBuilder.and(
+                        header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AppMessageReceived),
+                        header(QuickfixjEndpoint.MESSAGE_TYPE_KEY).isEqualTo(MsgType.EXECUTION_REPORT))).
+                    bean(new CountDownLatchDecrementer("execution report", executionReportLatch));
+            }
+        };
+        
+        context.addRoutes(routes);
+        
+        LOG.info("Starting Camel context");
+        context.start();
+        
+        // This is not strictly necessary, but it prevents the need for session
+        // synchronization due to app messages being sent before being logged on
+        if (!logonLatch.await(5, TimeUnit.SECONDS)) {
+            throw new IllegalStateException("Logon did not complete");
+        }
+        
+        String gatewayUri = "quickfixj:examples/inprocess.cfg?sessionID=FIX.4.2:TRADER->MARKET";
+        Endpoint gatewayEndpoint = context.getEndpoint(gatewayUri);
+        Producer producer = gatewayEndpoint.createProducer();
+        
+        LOG.info("Sending order");
+        
+        NewOrderSingle order = createNewOrderMessage();
+        Exchange exchange = producer.createExchange(ExchangePattern.InOnly);
+        exchange.getIn().setBody(order);
+        producer.process(exchange);            
+
+        if (!executionReportLatch.await(5, TimeUnit.SECONDS)) {
+            throw new IllegalStateException("Did not receive execution reports");
+        }
+        
+        LOG.info("Message received, shutting down Camel context");
+        
+        context.stop();
+        
+        LOG.info("Order execution example complete");
+    }
+
+    private NewOrderSingle createNewOrderMessage() {
+        NewOrderSingle order = new NewOrderSingle(
+            new ClOrdID("CLIENT_ORDER_ID"), 
+            new HandlInst('1'), 
+            new Symbol("GOOG"), 
+            new Side(Side.BUY), 
+            new TransactTime(new Date()), 
+            new OrdType(OrdType.LIMIT));
+        
+        order.set(new OrderQty(10));
+        order.set(new Price(300.00));
+        
+        return order;
+    }
+}

Added: camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjEventJsonTransformer.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjEventJsonTransformer.java?rev=1002361&view=auto
==============================================================================
--- camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjEventJsonTransformer.java (added)
+++ camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjEventJsonTransformer.java Tue Sep 28 21:26:58 2010
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.camel.component.quickfixj.examples.transform;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.quickfixj.QuickfixjEndpoint;
+
+import quickfix.ConfigError;
+import quickfix.DataDictionary;
+import quickfix.Message;
+import quickfix.Session;
+import quickfix.SessionID;
+
+public class QuickfixjEventJsonTransformer {
+    private final QuickfixjMessageJsonTransformer renderer;
+    
+    public QuickfixjEventJsonTransformer() throws ConfigError {
+        renderer = new QuickfixjMessageJsonTransformer();
+    }
+    
+    public String transform(Exchange exchange) {
+        SessionID sessionID = (SessionID) exchange.getIn().getHeader(QuickfixjEndpoint.SESSION_ID_KEY);
+        Session session = Session.lookupSession(sessionID);
+        DataDictionary dataDictionary = session.getDataDictionary();
+        
+        if (dataDictionary == null) {
+            throw new IllegalStateException("No Data Dictionary. Exchange must reference an existing session");
+        }
+        
+        StringBuilder sb = new StringBuilder();
+        sb.append("\"event\": {\n");
+        
+        org.apache.camel.Message in = exchange.getIn();
+        for (String key : in.getHeaders().keySet()) {
+            sb.append("  \"").append(key).append("\": ").append(in.getHeader(key)).append(",\n");                
+        }
+        
+        sb.append(renderer.transform(in.getBody(Message.class), "  ", dataDictionary)).append("\n");
+        sb.append("}\n");
+        return sb.toString();
+    }
+}
\ No newline at end of file

Added: camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonPrinter.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonPrinter.java?rev=1002361&view=auto
==============================================================================
--- camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonPrinter.java (added)
+++ camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonPrinter.java Tue Sep 28 21:26:58 2010
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.camel.component.quickfixj.examples.transform;
+
+import org.apache.camel.Exchange;
+
+import quickfix.ConfigError;
+
+public class QuickfixjMessageJsonPrinter {
+    private QuickfixjEventJsonTransformer formatter;
+
+    public QuickfixjMessageJsonPrinter() throws ConfigError {
+        formatter = new QuickfixjEventJsonTransformer();
+    }
+    
+    public void print(Exchange exchange) {
+        System.out.println(formatter.transform(exchange));
+    }
+}
\ No newline at end of file

Added: camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonTransformer.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonTransformer.java?rev=1002361&view=auto
==============================================================================
--- camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonTransformer.java (added)
+++ camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonTransformer.java Tue Sep 28 21:26:58 2010
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.camel.component.quickfixj.examples.transform;
+
+import java.util.Iterator;
+
+import quickfix.DataDictionary;
+import quickfix.Field;
+import quickfix.FieldMap;
+import quickfix.FieldType;
+import quickfix.Group;
+import quickfix.Message;
+
+
+public class QuickfixjMessageJsonTransformer {
+    
+    public String transform(Message message, DataDictionary dataDictionary) {
+        return transform(message, "", dataDictionary);
+    }
+
+    public String transform(Message message, String indent, DataDictionary dd) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(indent).append("\"message\": ");
+        if (message == null) {
+            sb.append("null");
+        } else {
+            sb.append("{\n");
+            String contentIndent = indent + "  ";
+            
+            transform("header", message.getHeader(), sb, contentIndent, dd);
+            sb.append("\n");
+            
+            transform("body", message, sb, contentIndent, dd);
+            sb.append("\n");
+
+            transform("trailer", message.getTrailer(), sb, contentIndent, dd);
+            sb.append("\n");
+            
+            sb.append(indent).append("}");
+        }
+        return sb.toString();
+    }
+    
+    private void transform(String name, FieldMap fieldMap, StringBuilder sb, String indent, DataDictionary dd) {
+        sb.append(indent).append("\"").append(name).append("\": {\n");
+        int fieldCount = 0;
+        Iterator<Field<?>> fieldIterator = fieldMap.iterator();
+        while (fieldIterator.hasNext()) {
+            if (fieldCount > 0) {
+                sb.append(",\n");
+            }
+            Field<?> field = fieldIterator.next();
+            sb.append(indent).append("  \"").append(dd.getFieldName(field.getField())).append("\": ");
+            if (dd.hasFieldValue(field.getField())) {
+                int tag = field.getField();
+                sb.append("[ \"").append(field.getObject().toString()).append("\", \"").
+                append(dd.getValueName(tag, field.getObject().toString())).
+                append("\" ]");
+            } else {
+                FieldType fieldType = dd.getFieldTypeEnum(field.getField());
+                if (Number.class.isAssignableFrom(fieldType.getJavaType())) {
+                    sb.append(field.getObject());
+                } else {
+                    sb.append("\"").append(field.getObject().toString()).append("\"");
+                }
+            }
+            fieldCount++;
+        }
+        
+        sb.append("\n");
+        
+        Iterator<Integer> groupKeys = fieldMap.groupKeyIterator();
+        while (groupKeys.hasNext()) {
+            int groupTag = groupKeys.next();
+            for (Group group : fieldMap.getGroups(groupTag)) {
+                String groupName = dd.getFieldName(groupTag);
+                transform(groupName, group, sb, indent + "  ", dd);
+            }
+        }
+        
+        sb.append(indent).append("}").append("\n");
+    }
+}
\ No newline at end of file

Added: camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/util/CountDownLatchDecrementer.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/util/CountDownLatchDecrementer.java?rev=1002361&view=auto
==============================================================================
--- camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/util/CountDownLatchDecrementer.java (added)
+++ camel/trunk/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples/util/CountDownLatchDecrementer.java Tue Sep 28 21:26:58 2010
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.camel.component.quickfixj.examples.util;
+
+import java.util.concurrent.CountDownLatch;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Handler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CountDownLatchDecrementer {
+    private static final Logger LOG = LoggerFactory.getLogger(CountDownLatchDecrementer.class);
+
+    private String label;
+    private CountDownLatch latch;
+    
+    public CountDownLatchDecrementer(String label, CountDownLatch latch) {
+        this.label = label;
+        this.latch = latch;
+    }
+
+    @Handler
+    public void decrement(Exchange exchange) {
+        LOG.info("Decrementing latch count: " + label);
+        latch.countDown();
+    }
+}
\ No newline at end of file

Added: camel/trunk/components/camel-quickfix/src/test/resources/examples/gateway.cfg
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-quickfix/src/test/resources/examples/gateway.cfg?rev=1002361&view=auto
==============================================================================
--- camel/trunk/components/camel-quickfix/src/test/resources/examples/gateway.cfg (added)
+++ camel/trunk/components/camel-quickfix/src/test/resources/examples/gateway.cfg Tue Sep 28 21:26:58 2010
@@ -0,0 +1,42 @@
+#
+# Creates an initiators and acceptors that communicate within a 
+# VM (no external socket connections).
+#
+[default]
+SocketAcceptProtocol=VM_PIPE
+SocketAcceptPort=7001
+SocketConnectProtocol=VM_PIPE
+SocketConnectPort=7001
+
+#
+# Initiator for simulating trader #1
+#
+[session]
+ConnectionType=initiator
+BeginString=FIX.4.2
+SenderCompID=TRADER@1
+TargetCompID=GATEWAY
+
+#
+# Initiator for simulating trader #2
+#
+[session]
+ConnectionType=initiator
+BeginString=FIX.4.2
+SenderCompID=TRADER@2
+TargetCompID=GATEWAY
+
+#
+# Acceptor for simulating the routing gateway
+#
+[session]
+ConnectionType=acceptor
+BeginString=FIX.4.2
+SenderCompID=GATEWAY
+TargetCompID=TRADER@1
+
+[session]
+ConnectionType=acceptor
+BeginString=FIX.4.2
+SenderCompID=GATEWAY
+TargetCompID=TRADER@2

Added: camel/trunk/components/camel-quickfix/src/test/resources/examples/inprocess.cfg
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-quickfix/src/test/resources/examples/inprocess.cfg?rev=1002361&view=auto
==============================================================================
--- camel/trunk/components/camel-quickfix/src/test/resources/examples/inprocess.cfg (added)
+++ camel/trunk/components/camel-quickfix/src/test/resources/examples/inprocess.cfg Tue Sep 28 21:26:58 2010
@@ -0,0 +1,28 @@
+#
+# Creates an initiator and acceptor that communicate within a 
+# VM (no external socket connections).
+#
+[default]
+UseJmx=Y
+SocketAcceptProtocol=VM_PIPE
+SocketConnectProtocol=VM_PIPE
+
+#
+# Initiator for simulating a trader
+#
+[session]
+ConnectionType=initiator
+BeginString=FIX.4.2
+SenderCompID=TRADER
+TargetCompID=MARKET
+SocketConnectPort=7001
+
+#
+# Acceptor for simulating the market
+#
+[session]
+ConnectionType=acceptor
+BeginString=FIX.4.2
+SenderCompID=MARKET
+TargetCompID=TRADER
+SocketAcceptPort=7001
\ No newline at end of file

Added: camel/trunk/components/camel-quickfix/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-quickfix/src/test/resources/log4j.properties?rev=1002361&view=auto
==============================================================================
--- camel/trunk/components/camel-quickfix/src/test/resources/log4j.properties (added)
+++ camel/trunk/components/camel-quickfix/src/test/resources/log4j.properties Tue Sep 28 21:26:58 2010
@@ -0,0 +1,22 @@
+# Set root category priority to INFO and its only appender to CONSOLE.
+log4j.rootCategory=DEBUG, CONSOLE
+#log4j.rootCategory=CONSOLE, LOGFILE
+
+log4j.category.quickfix.mina.message=INFO
+log4j.category.org.apache.camel.management=INFO
+log4j.category.org.apache.camel.processor.FilterProcessor=INFO
+log4j.category.org.apache.camel.impl.converter=INFO
+
+# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.Threshold=DEBUG
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%d{HH:mm:ss.SSS} %p [%t] %c{1} - %m%n
+
+# LOGFILE is set to be a File appender using a PatternLayout.
+log4j.appender.LOGFILE=org.apache.log4j.FileAppender
+log4j.appender.LOGFILE.File=target/fixgw.log
+log4j.appender.LOGFILE.Append=true
+log4j.appender.LOGFILE.Threshold=DEBUG
+log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
+log4j.appender.LOGFILE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n