001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.filter.codec.textline; 021 022import java.nio.charset.Charset; 023import java.nio.charset.CharsetEncoder; 024 025import org.apache.mina.core.buffer.IoBuffer; 026import org.apache.mina.core.session.AttributeKey; 027import org.apache.mina.core.session.IoSession; 028import org.apache.mina.filter.codec.ProtocolEncoder; 029import org.apache.mina.filter.codec.ProtocolEncoderAdapter; 030import org.apache.mina.filter.codec.ProtocolEncoderOutput; 031 032/** 033 * A {@link ProtocolEncoder} which encodes a string into a text line 034 * which ends with the delimiter. 035 * 036 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 037 */ 038public class TextLineEncoder extends ProtocolEncoderAdapter { 039 private static final AttributeKey ENCODER = new AttributeKey(TextLineEncoder.class, "encoder"); 040 041 private final Charset charset; 042 043 private final LineDelimiter delimiter; 044 045 private int maxLineLength = Integer.MAX_VALUE; 046 047 /** 048 * Creates a new instance with the current default {@link Charset} 049 * and {@link LineDelimiter#UNIX} delimiter. 050 */ 051 public TextLineEncoder() { 052 this(Charset.defaultCharset(), LineDelimiter.UNIX); 053 } 054 055 /** 056 * Creates a new instance with the current default {@link Charset} 057 * and the specified <tt>delimiter</tt>. 058 * 059 * @param delimiter The line delimiter to use 060 */ 061 public TextLineEncoder(String delimiter) { 062 this(new LineDelimiter(delimiter)); 063 } 064 065 /** 066 * Creates a new instance with the current default {@link Charset} 067 * and the specified <tt>delimiter</tt>. 068 * 069 * @param delimiter The line delimiter to use 070 */ 071 public TextLineEncoder(LineDelimiter delimiter) { 072 this(Charset.defaultCharset(), delimiter); 073 } 074 075 /** 076 * Creates a new instance with the specified <tt>charset</tt> 077 * and {@link LineDelimiter#UNIX} delimiter. 078 * 079 * @param charset The {@link Charset} to use 080 */ 081 public TextLineEncoder(Charset charset) { 082 this(charset, LineDelimiter.UNIX); 083 } 084 085 /** 086 * Creates a new instance with the specified <tt>charset</tt> 087 * and the specified <tt>delimiter</tt>. 088 * 089 * @param charset The {@link Charset} to use 090 * @param delimiter The line delimiter to use 091 */ 092 public TextLineEncoder(Charset charset, String delimiter) { 093 this(charset, new LineDelimiter(delimiter)); 094 } 095 096 /** 097 * Creates a new instance with the specified <tt>charset</tt> 098 * and the specified <tt>delimiter</tt>. 099 * 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 public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { 148 CharsetEncoder encoder = (CharsetEncoder) session.getAttribute(ENCODER); 149 150 if (encoder == null) { 151 encoder = charset.newEncoder(); 152 session.setAttribute(ENCODER, encoder); 153 } 154 155 String value = (message == null ? "" : message.toString()); 156 IoBuffer buf = IoBuffer.allocate(value.length()).setAutoExpand(true); 157 buf.putString(value, encoder); 158 159 if (buf.position() > maxLineLength) { 160 throw new IllegalArgumentException("Line length: " + buf.position()); 161 } 162 163 buf.putString(delimiter.getValue(), encoder); 164 buf.flip(); 165 out.write(buf); 166 } 167 168 /** 169 * {@inheritDoc} 170 */ 171 public void dispose() throws Exception { 172 // Do nothing 173 } 174}