View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, and individual contributors by the @author
5      tags. See the COPYRIGHT.txt in the distribution for a full listing of
6      individual contributors.
7   
8      All GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package openr66.protocol.localhandler;
22  
23  import static openr66.context.R66FiniteDualStates.ERROR;
24  
25  import goldengate.common.logging.GgInternalLogger;
26  import goldengate.common.logging.GgInternalLoggerFactory;
27  import openr66.context.ErrorCode;
28  import openr66.context.R66Result;
29  import openr66.protocol.configuration.Configuration;
30  import openr66.protocol.exception.OpenR66Exception;
31  import openr66.protocol.exception.OpenR66ExceptionTrappedFactory;
32  import openr66.protocol.exception.OpenR66ProtocolBusinessNoWriteBackException;
33  import openr66.protocol.exception.OpenR66ProtocolNetworkException;
34  import openr66.protocol.exception.OpenR66ProtocolNoConnectionException;
35  import openr66.protocol.exception.OpenR66ProtocolShutdownException;
36  import openr66.protocol.exception.OpenR66ProtocolSystemException;
37  import openr66.protocol.localhandler.packet.AbstractLocalPacket;
38  import openr66.protocol.localhandler.packet.ErrorPacket;
39  import openr66.protocol.localhandler.packet.LocalPacketFactory;
40  import openr66.protocol.utils.ChannelCloseTimer;
41  import openr66.protocol.utils.ChannelUtils;
42  
43  import org.jboss.netty.channel.Channel;
44  import org.jboss.netty.channel.ChannelHandlerContext;
45  import org.jboss.netty.channel.ChannelStateEvent;
46  import org.jboss.netty.channel.Channels;
47  import org.jboss.netty.channel.ExceptionEvent;
48  import org.jboss.netty.channel.MessageEvent;
49  import org.jboss.netty.channel.SimpleChannelHandler;
50  
51  /**
52   * @author frederic bregier
53   */
54  public class LocalClientHandler extends SimpleChannelHandler {
55      /**
56       * Internal Logger
57       */
58      private static final GgInternalLogger logger = GgInternalLoggerFactory
59              .getLogger(LocalClientHandler.class);
60  
61      /**
62       * Local Channel Reference
63       */
64      private volatile LocalChannelReference localChannelReference = null;
65  
66      /*
67       * (non-Javadoc)
68       *
69       * @see
70       * org.jboss.netty.channel.SimpleChannelHandler#channelClosed(org.jboss.
71       * netty.channel.ChannelHandlerContext,
72       * org.jboss.netty.channel.ChannelStateEvent)
73       */
74      @Override
75      public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
76              throws Exception {
77          logger.debug("Local Client Channel Closed: {}", e.getChannel().getId());
78      }
79  
80      /*
81       * (non-Javadoc)
82       *
83       * @see
84       * org.jboss.netty.channel.SimpleChannelHandler#channelConnected(org.jboss
85       * .netty.channel.ChannelHandlerContext,
86       * org.jboss.netty.channel.ChannelStateEvent)
87       */
88      @Override
89      public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
90              throws Exception {
91          logger
92                  .debug("Local Client Channel Connected: " +
93                          e.getChannel().getId());
94      }
95      /**
96       * Initiate the LocalChannelReference
97       * @param channel
98       * @throws InterruptedException
99       * @throws OpenR66ProtocolNetworkException
100      */
101     private void initLocalClientHandler(Channel channel)
102             throws InterruptedException, OpenR66ProtocolNetworkException {
103         int i = 0;
104         if (localChannelReference == null) {
105             for (i = 0; i < Configuration.RETRYNB; i ++) {
106                 localChannelReference = Configuration.configuration
107                         .getLocalTransaction().getFromId(channel.getId());
108                 if (localChannelReference != null) {
109                     return;
110                 }
111                 Thread.sleep(Configuration.RETRYINMS);
112             }
113             logger.warn("Cannot find local connection");
114         }
115     }
116 
117     /*
118      * (non-Javadoc)
119      *
120      * @see
121      * org.jboss.netty.channel.SimpleChannelHandler#messageReceived(org.jboss
122      * .netty.channel.ChannelHandlerContext,
123      * org.jboss.netty.channel.MessageEvent)
124      */
125     @Override
126     public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
127             throws Exception {
128         if (localChannelReference == null) {
129             initLocalClientHandler(e.getChannel());
130         }
131         // only Startup Packet should arrived here !
132         final AbstractLocalPacket packet = (AbstractLocalPacket) e.getMessage();
133         if (packet.getType() != LocalPacketFactory.STARTUPPACKET) {
134             logger.error("Local Client Channel Recv wrong packet: " +
135                     e.getChannel().getId() + " : " + packet.toString());
136             throw new OpenR66ProtocolSystemException("Should not be here");
137         }
138         logger.debug("LocalClientHandler initialized: " +
139                 (localChannelReference != null));
140     }
141 
142     /*
143      * (non-Javadoc)
144      *
145      * @see
146      * org.jboss.netty.channel.SimpleChannelHandler#exceptionCaught(org.jboss
147      * .netty.channel.ChannelHandlerContext,
148      * org.jboss.netty.channel.ExceptionEvent)
149      */
150     @Override
151     public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
152             throws Exception {
153         // informs network of the problem
154         logger.debug(
155                 "Local Client Channel Exception: {}",e.getChannel().getId(), e
156                         .getCause());
157         if (localChannelReference == null) {
158             initLocalClientHandler(e.getChannel());
159         }
160         if (localChannelReference != null) {
161             OpenR66Exception exception = OpenR66ExceptionTrappedFactory
162                     .getExceptionFromTrappedException(e.getChannel(), e);
163             localChannelReference.sessionNewState(ERROR);
164             if (exception != null) {
165                 if (exception instanceof OpenR66ProtocolShutdownException) {
166                     Thread thread = new Thread(new ChannelUtils(), "R66 Shutdown Thread");
167                     thread.setDaemon(true);
168                     thread.start();
169                     logger.debug("Will close channel");
170                     Channels.close(e.getChannel());
171                     return;
172                 } else if (exception instanceof OpenR66ProtocolBusinessNoWriteBackException) {
173                     logger.error("Will close channel", exception);
174                     Channels.close(e.getChannel());
175                     return;
176                 } else if (exception instanceof OpenR66ProtocolNoConnectionException) {
177                     logger.error("Will close channel", exception);
178                     Channels.close(e.getChannel());
179                     return;
180                 }
181                 final ErrorPacket errorPacket = new ErrorPacket(exception
182                         .getMessage(),
183                         ErrorCode.RemoteError.getCode(), ErrorPacket.FORWARDCLOSECODE);
184                 ChannelUtils.writeAbstractLocalPacket(localChannelReference, errorPacket, true);
185                 if (!localChannelReference.getFutureRequest().isDone()) {
186                     localChannelReference.invalidateRequest(new R66Result(
187                             exception, localChannelReference.getSession(), true, ErrorCode.Internal, null));
188                 }
189             } else {
190                 // Nothing to do
191                 return;
192             }
193         }
194         logger.debug("Will close channel");
195         ChannelCloseTimer.closeFutureChannel(e.getChannel());
196     }
197 
198 }