001/*
002 * ====================================================================
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 * ====================================================================
020 *
021 * This software consists of voluntary contributions made by many
022 * individuals on behalf of the Apache Software Foundation.  For more
023 * information on the Apache Software Foundation, please see
024 * <http://www.apache.org/>.
025 *
026 */
027
028package org.apache.http.config;
029
030import java.nio.charset.Charset;
031import java.nio.charset.CodingErrorAction;
032
033import org.apache.http.Consts;
034import org.apache.http.annotation.ThreadingBehavior;
035import org.apache.http.annotation.Contract;
036import org.apache.http.util.Args;
037
038/**
039 * HTTP connection configuration.
040 *
041 * @since 4.3
042 */
043@Contract(threading = ThreadingBehavior.IMMUTABLE)
044public class ConnectionConfig implements Cloneable {
045
046    public static final ConnectionConfig DEFAULT = new Builder().build();
047
048    private final int bufferSize;
049    private final int fragmentSizeHint;
050    private final Charset charset;
051    private final CodingErrorAction malformedInputAction;
052    private final CodingErrorAction unmappableInputAction;
053    private final MessageConstraints messageConstraints;
054
055    ConnectionConfig(
056            final int bufferSize,
057            final int fragmentSizeHint,
058            final Charset charset,
059            final CodingErrorAction malformedInputAction,
060            final CodingErrorAction unmappableInputAction,
061            final MessageConstraints messageConstraints) {
062        super();
063        this.bufferSize = bufferSize;
064        this.fragmentSizeHint = fragmentSizeHint;
065        this.charset = charset;
066        this.malformedInputAction = malformedInputAction;
067        this.unmappableInputAction = unmappableInputAction;
068        this.messageConstraints = messageConstraints;
069    }
070
071    public int getBufferSize() {
072        return bufferSize;
073    }
074
075    public int getFragmentSizeHint() {
076        return fragmentSizeHint;
077    }
078
079    public Charset getCharset() {
080        return charset;
081    }
082
083    public CodingErrorAction getMalformedInputAction() {
084        return malformedInputAction;
085    }
086
087    public CodingErrorAction getUnmappableInputAction() {
088        return unmappableInputAction;
089    }
090
091    public MessageConstraints getMessageConstraints() {
092        return messageConstraints;
093    }
094
095    @Override
096    protected ConnectionConfig clone() throws CloneNotSupportedException {
097        return (ConnectionConfig) super.clone();
098    }
099
100    @Override
101    public String toString() {
102        final StringBuilder builder = new StringBuilder();
103        builder.append("[bufferSize=").append(this.bufferSize)
104                .append(", fragmentSizeHint=").append(this.fragmentSizeHint)
105                .append(", charset=").append(this.charset)
106                .append(", malformedInputAction=").append(this.malformedInputAction)
107                .append(", unmappableInputAction=").append(this.unmappableInputAction)
108                .append(", messageConstraints=").append(this.messageConstraints)
109                .append("]");
110        return builder.toString();
111    }
112
113    public static ConnectionConfig.Builder custom() {
114        return new Builder();
115    }
116
117    public static ConnectionConfig.Builder copy(final ConnectionConfig config) {
118        Args.notNull(config, "Connection config");
119        return new Builder()
120            .setBufferSize(config.getBufferSize())
121            .setCharset(config.getCharset())
122            .setFragmentSizeHint(config.getFragmentSizeHint())
123            .setMalformedInputAction(config.getMalformedInputAction())
124            .setUnmappableInputAction(config.getUnmappableInputAction())
125            .setMessageConstraints(config.getMessageConstraints());
126    }
127
128    public static class Builder {
129
130        private int bufferSize;
131        private int fragmentSizeHint;
132        private Charset charset;
133        private CodingErrorAction malformedInputAction;
134        private CodingErrorAction unmappableInputAction;
135        private MessageConstraints messageConstraints;
136
137        Builder() {
138            this.fragmentSizeHint = -1;
139        }
140
141        public Builder setBufferSize(final int bufferSize) {
142            this.bufferSize = bufferSize;
143            return this;
144        }
145
146        public Builder setFragmentSizeHint(final int fragmentSizeHint) {
147            this.fragmentSizeHint = fragmentSizeHint;
148            return this;
149        }
150
151        public Builder setCharset(final Charset charset) {
152            this.charset = charset;
153            return this;
154        }
155
156        public Builder setMalformedInputAction(final CodingErrorAction malformedInputAction) {
157            this.malformedInputAction = malformedInputAction;
158            if (malformedInputAction != null && this.charset == null) {
159                this.charset = Consts.ASCII;
160            }
161            return this;
162        }
163
164        public Builder setUnmappableInputAction(final CodingErrorAction unmappableInputAction) {
165            this.unmappableInputAction = unmappableInputAction;
166            if (unmappableInputAction != null && this.charset == null) {
167                this.charset = Consts.ASCII;
168            }
169            return this;
170        }
171
172        public Builder setMessageConstraints(final MessageConstraints messageConstraints) {
173            this.messageConstraints = messageConstraints;
174            return this;
175        }
176
177        public ConnectionConfig build() {
178            Charset cs = charset;
179            if (cs == null && (malformedInputAction != null || unmappableInputAction != null)) {
180                cs = Consts.ASCII;
181            }
182            final int bufSize = this.bufferSize > 0 ? this.bufferSize : 8 * 1024;
183            final int fragmentHintSize  = this.fragmentSizeHint >= 0 ? this.fragmentSizeHint : bufSize;
184            return new ConnectionConfig(
185                    bufSize,
186                    fragmentHintSize,
187                    cs,
188                    malformedInputAction,
189                    unmappableInputAction,
190                    messageConstraints);
191        }
192
193    }
194
195}