001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.component.mina;
018    
019    import java.nio.charset.CharacterCodingException;
020    import java.nio.charset.Charset;
021    import java.nio.charset.CharsetEncoder;
022    
023    import org.apache.camel.CamelContext;
024    import org.apache.camel.NoTypeConversionAvailableException;
025    import org.apache.mina.common.ByteBuffer;
026    import org.apache.mina.common.IoSession;
027    import org.apache.mina.filter.codec.ProtocolCodecFactory;
028    import org.apache.mina.filter.codec.ProtocolDecoder;
029    import org.apache.mina.filter.codec.ProtocolDecoderOutput;
030    import org.apache.mina.filter.codec.ProtocolEncoder;
031    import org.apache.mina.filter.codec.ProtocolEncoderOutput;
032    
033    /**
034     * @version $Revision: 3039 $
035     */
036    public class MinaUdpProtocolCodecFactory implements ProtocolCodecFactory {
037    
038        private final Charset charset;
039        private final CamelContext context;
040    
041        public MinaUdpProtocolCodecFactory(CamelContext context, Charset charset) {
042            this.context = context;
043            this.charset = charset;
044        }
045    
046        public ProtocolEncoder getEncoder() throws Exception {
047            return new ProtocolEncoder() {
048                private CharsetEncoder encoder;
049    
050                public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
051                    if (encoder == null) {
052                        encoder = charset.newEncoder();
053                    }
054                    ByteBuffer buf = toByteBuffer(message, encoder);
055                    buf.flip();
056                    out.write(buf);
057                }
058    
059                public void dispose(IoSession session) throws Exception {
060                    // do nothing
061                }
062            };
063        }
064    
065        public ProtocolDecoder getDecoder() throws Exception {
066            return new ProtocolDecoder() {
067                public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
068                    // convert to bytes to write, we can not pass in the byte buffer as it could be sent to
069                    // multiple mina sessions so we must convert it to bytes
070                    byte[] bytes = context.getTypeConverter().convertTo(byte[].class, in);
071                    out.write(bytes);
072                }
073    
074                public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception {
075                    // do nothing
076                }
077    
078                public void dispose(IoSession session) throws Exception {
079                    // do nothing
080                }
081            };
082        }
083    
084        private ByteBuffer toByteBuffer(Object message, CharsetEncoder encoder)
085            throws CharacterCodingException, NoTypeConversionAvailableException {
086            String value = context.getTypeConverter().convertTo(String.class, message);
087            if (value != null) {
088                ByteBuffer answer = ByteBuffer.allocate(value.length()).setAutoExpand(false);
089                answer.putString(value, encoder);
090                return answer;
091            }
092    
093            // failback to use a byte buffer converter
094            return context.getTypeConverter().mandatoryConvertTo(ByteBuffer.class, message);
095        }
096    
097    }