View Javadoc
1   /*
2    * Copyright 2016 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.openehealth.ipf.platform.camel.ihe.mllp.core;
17  
18  import lombok.experimental.Delegate;
19  import org.apache.camel.component.mina2.Mina2Producer;
20  import org.apache.camel.impl.DefaultProducer;
21  import org.apache.mina.core.service.IoConnector;
22  import org.apache.mina.core.session.IoSession;
23  import org.slf4j.Logger;
24  import org.slf4j.LoggerFactory;
25  
26  import java.lang.reflect.Field;
27  import java.lang.reflect.InvocationTargetException;
28  import java.lang.reflect.Method;
29  
30  /**
31   * MllpProducer wraps a Mina2Producer for having a hook to shutdown some Mina
32   * resources when the consumer is closing
33   */
34  public class MllpProducer extends DefaultProducer {
35  
36      private static final Logger LOG = LoggerFactory.getLogger(MllpProducer.class);
37  
38      // The reason for this interface is to convince the Delegate annotation to *not* delegate
39      // the stop method. Weird API, really.
40      private interface DoStop {
41          @SuppressWarnings("unused")
42          void stop() throws Exception;
43      }
44  
45      @Delegate(excludes = DoStop.class)
46      private final Mina2Producer producer;
47  
48      MllpProducer(Mina2Producer producer) {
49          // Everything will be delegated
50          super(producer.getEndpoint());
51          this.producer = producer;
52      }
53  
54      @Override
55      public void stop() throws Exception {
56          super.stop();
57      }
58  
59      /**
60       * Hack to circumvent accessing private members of the super class with the effect that
61       * disposing the connector does NOT wait indefinitely.
62       * @throws Exception
63       */
64      @Override
65      protected void doStop() throws Exception {
66          IoSession session = getField(producer, IoSession.class, "session");
67          if (session != null) {
68              invoke(producer, "closeSessionIfNeededAndAwaitCloseInHandler", IoSession.class, session);
69          }
70          IoConnector connector = getField(producer, IoConnector.class, "connector");
71          // Do NOT wait indefinitely
72          connector.dispose(false);
73          super.doStop();
74      }
75  
76      private static <T> T getField(Object target, Class<T> clazz, String name) throws NoSuchFieldException, IllegalAccessException {
77          Field field = target.getClass().getDeclaredField(name);
78          field.setAccessible(true);
79          return (T) field.get(target);
80      }
81  
82      private static <T> void invoke(Object target, String name, Class<T> clazz, T arg) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
83          Method method = target.getClass().getDeclaredMethod(name, clazz);
84          method.setAccessible(true);
85          method.invoke(target, arg);
86      }
87  }