View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.filter.codec.textline;
21  
22  import java.nio.charset.Charset;
23  import java.nio.charset.CharsetEncoder;
24  
25  import org.apache.mina.core.buffer.IoBuffer;
26  import org.apache.mina.core.session.AttributeKey;
27  import org.apache.mina.core.session.IoSession;
28  import org.apache.mina.filter.codec.ProtocolEncoder;
29  import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
30  import org.apache.mina.filter.codec.ProtocolEncoderOutput;
31  
32  /**
33   * A {@link ProtocolEncoder} which encodes a string into a text line
34   * which ends with the delimiter.
35   *
36   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
37   */
38  public class TextLineEncoder extends ProtocolEncoderAdapter {
39      private static final AttributeKey ENCODER = new AttributeKey(TextLineEncoder.class, "encoder");
40  
41      private final Charset charset;
42  
43      private final LineDelimiter delimiter;
44  
45      private int maxLineLength = Integer.MAX_VALUE;
46  
47      /**
48       * Creates a new instance with the current default {@link Charset}
49       * and {@link LineDelimiter#UNIX} delimiter.
50       */
51      public TextLineEncoder() {
52          this(Charset.defaultCharset(), LineDelimiter.UNIX);
53      }
54  
55      /**
56       * Creates a new instance with the current default {@link Charset}
57       * and the specified <tt>delimiter</tt>.
58       * 
59       * @param delimiter The line delimiter to use
60       */
61      public TextLineEncoder(String delimiter) {
62          this(new LineDelimiter(delimiter));
63      }
64  
65      /**
66       * Creates a new instance with the current default {@link Charset}
67       * and the specified <tt>delimiter</tt>.
68       * 
69       * @param delimiter The line delimiter to use
70       */
71      public TextLineEncoder(LineDelimiter delimiter) {
72          this(Charset.defaultCharset(), delimiter);
73      }
74  
75      /**
76       * Creates a new instance with the specified <tt>charset</tt>
77       * and {@link LineDelimiter#UNIX} delimiter.
78       * 
79       * @param charset The {@link Charset} to use
80       */
81      public TextLineEncoder(Charset charset) {
82          this(charset, LineDelimiter.UNIX);
83      }
84  
85      /**
86       * Creates a new instance with the specified <tt>charset</tt>
87       * and the specified <tt>delimiter</tt>.
88       * 
89       * @param charset The {@link Charset} to use
90       * @param delimiter The line delimiter to use
91       */
92      public TextLineEncoder(Charset charset, String delimiter) {
93          this(charset, new LineDelimiter(delimiter));
94      }
95  
96      /**
97       * Creates a new instance with the specified <tt>charset</tt>
98       * and the specified <tt>delimiter</tt>.
99       * 
100      * @param charset The {@link Charset} to use
101      * @param delimiter The line delimiter to use
102      */
103     public TextLineEncoder(Charset charset, LineDelimiter delimiter) {
104         if (charset == null) {
105             throw new IllegalArgumentException("charset");
106         }
107         if (delimiter == null) {
108             throw new IllegalArgumentException("delimiter");
109         }
110         if (LineDelimiter.AUTO.equals(delimiter)) {
111             throw new IllegalArgumentException("AUTO delimiter is not allowed for encoder.");
112         }
113 
114         this.charset = charset;
115         this.delimiter = delimiter;
116     }
117 
118     /**
119      * @return the allowed maximum size of the encoded line.
120      * If the size of the encoded line exceeds this value, the encoder
121      * will throw a {@link IllegalArgumentException}.  The default value
122      * is {@link Integer#MAX_VALUE}.
123      */
124     public int getMaxLineLength() {
125         return maxLineLength;
126     }
127 
128     /**
129      * Sets the allowed maximum size of the encoded line.
130      * If the size of the encoded line exceeds this value, the encoder
131      * will throw a {@link IllegalArgumentException}.  The default value
132      * is {@link Integer#MAX_VALUE}.
133      * 
134      * @param maxLineLength The maximum line length
135      */
136     public void setMaxLineLength(int maxLineLength) {
137         if (maxLineLength <= 0) {
138             throw new IllegalArgumentException("maxLineLength: " + maxLineLength);
139         }
140 
141         this.maxLineLength = maxLineLength;
142     }
143 
144     /**
145      * {@inheritDoc}
146      */
147     @Override
148     public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
149         CharsetEncoder encoder = (CharsetEncoder) session.getAttribute(ENCODER);
150 
151         if (encoder == null) {
152             encoder = charset.newEncoder();
153             session.setAttribute(ENCODER, encoder);
154         }
155 
156         String value = message == null ? "" : message.toString();
157         IoBuffer buf = IoBuffer.allocate(value.length()).setAutoExpand(true);
158         buf.putString(value, encoder);
159 
160         if (buf.position() > maxLineLength) {
161             throw new IllegalArgumentException("Line length: " + buf.position());
162         }
163 
164         buf.putString(delimiter.getValue(), encoder);
165         buf.flip();
166         out.write(buf);
167     }
168 
169     /**
170      * Dispose the encoder
171      * 
172      * @throws Exception If the dispose failed
173      */
174     public void dispose() throws Exception {
175         // Do nothing
176     }
177 }